Julius Marmingerm961df858 months agoHistory
748 lines · 24.2 KB · TypeScript
RawDownload
import fs from "node:fs";import path from "node:path"; import {  ApprovalRequestId,  CommandId,  EventId,  MessageId,  ProjectId,  ProviderSessionId,  ProviderThreadId,  ProviderTurnId,  ThreadId,} from "@t3tools/contracts";import { assert, it } from "@effect/vitest";import { Effect, Option, Schema } from "effect"; import type { TestTurnResponse } from "./TestProviderAdapter.integration.ts";import {  gitRefExists,  gitShowFileAtRef,  makeOrchestrationIntegrationHarness,  type OrchestrationIntegrationHarness,} from "./OrchestrationEngineHarness.integration.ts";import { checkpointRefForThreadTurn } from "../src/checkpointing/Utils.ts"; const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value);const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value);const asEventId = (value: string): EventId => EventId.makeUnsafe(value);const asProviderSessionId = (value: string): ProviderSessionId =>  ProviderSessionId.makeUnsafe(value);const asProviderThreadId = (value: string): ProviderThreadId => ProviderThreadId.makeUnsafe(value);const asProviderTurnId = (value: string): ProviderTurnId => ProviderTurnId.makeUnsafe(value);const asApprovalRequestId = (value: string): ApprovalRequestId =>  ApprovalRequestId.makeUnsafe(value); const PROJECT_ID = asProjectId("project-1");const THREAD_ID = ThreadId.makeUnsafe("thread-1");const FIXTURE_SESSION_ID = asProviderSessionId("fixture-session");const FIXTURE_THREAD_ID = asProviderThreadId("fixture-thread");const FIXTURE_TURN_ID = asProviderTurnId("fixture-turn");const APPROVAL_REQUEST_ID = asApprovalRequestId("req-approval-1"); function nowIso() {  return new Date().toISOString();} class IntegrationWaitTimeoutError extends Schema.TaggedErrorClass<IntegrationWaitTimeoutError>()(  "IntegrationWaitTimeoutError",  {    description: Schema.String,  },) {} const sleep = (ms: number) => Effect.sleep(ms); function waitForSync<A>(  read: () => A,  predicate: (value: A) => boolean,  description: string,  timeoutMs = 3000,): Effect.Effect<A, never> {  return Effect.gen(function* () {    const deadline = Date.now() + timeoutMs;     while (true) {      const value = read();      if (predicate(value)) {        return value;      }      if (Date.now() >= deadline) {        return yield* Effect.die(new IntegrationWaitTimeoutError({ description }));      }      yield* sleep(10);    }  });} function runtimeBase(eventId: string, createdAt: string) {  return {    eventId: asEventId(eventId),    provider: "codex" as const,    sessionId: FIXTURE_SESSION_ID,    createdAt,  };} function withHarness<A, E>(use: (harness: OrchestrationIntegrationHarness) => Effect.Effect<A, E>) {  return Effect.acquireUseRelease(    makeOrchestrationIntegrationHarness,    use,    (harness) => harness.dispose,  );} const seedProjectAndThread = (harness: OrchestrationIntegrationHarness) =>  Effect.gen(function* () {    const createdAt = nowIso();     yield* harness.engine.dispatch({      type: "project.create",      commandId: CommandId.makeUnsafe("cmd-project-create"),      projectId: PROJECT_ID,      title: "Integration Project",      workspaceRoot: harness.workspaceDir,      defaultModel: "gpt-5-codex",      createdAt,    });     yield* harness.engine.dispatch({      type: "thread.create",      commandId: CommandId.makeUnsafe("cmd-thread-create"),      threadId: THREAD_ID,      projectId: PROJECT_ID,      title: "Integration Thread",      model: "gpt-5-codex",      branch: null,      worktreePath: harness.workspaceDir,      createdAt,    });  }); const startTurn = (input: {  readonly harness: OrchestrationIntegrationHarness;  readonly commandId: string;  readonly messageId: string;  readonly text: string;}) =>  input.harness.engine.dispatch({    type: "thread.turn.start",    commandId: CommandId.makeUnsafe(input.commandId),    threadId: THREAD_ID,    message: {      messageId: asMessageId(input.messageId),      role: "user",      text: input.text,      attachments: [],    },    createdAt: nowIso(),  }); it.live("runs a single turn end-to-end and persists checkpoint state in sqlite + git", () =>  withHarness((harness) =>    Effect.gen(function* () {      yield* seedProjectAndThread(harness);       const turnResponse: TestTurnResponse = {        events: [          {            type: "turn.started",            ...runtimeBase("evt-single-1", "2026-02-24T10:00:00.000Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,          },          {            type: "message.delta",            ...runtimeBase("evt-single-2", "2026-02-24T10:00:00.100Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            delta: "Single turn response.\n",          },          {            type: "turn.completed",            ...runtimeBase("evt-single-3", "2026-02-24T10:00:00.200Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            status: "completed",          },        ],      };       yield* harness.adapterHarness.queueTurnResponseForNextSession(turnResponse);      yield* startTurn({        harness,        commandId: "cmd-turn-start-single",        messageId: "msg-user-single",        text: "Say hello",      });       const thread = yield* harness.waitForThread(        THREAD_ID,        (entry) =>          entry.session?.status === "ready" &&          entry.messages.some(            (message) => message.role === "assistant" && message.streaming === false,          ) &&          entry.checkpoints.length === 1,      );      assert.equal(thread.checkpoints[0]?.status, "ready");      assert.equal(thread.checkpoints[0]?.checkpointTurnCount, 1);       const checkpointRows = yield* harness.checkpointRepository.listByThreadId({        threadId: THREAD_ID,      });      assert.equal(checkpointRows.length, 1);      assert.equal(checkpointRows[0]?.checkpointTurnCount, 1);      assert.equal(checkpointRows[0]?.status, "ready");      assert.deepEqual(checkpointRows[0]?.files, []);       yield* harness.waitForDomainEvent((event) => event.type === "thread.turn-diff-completed");       const ref0 = checkpointRefForThreadTurn(THREAD_ID, 0);      const ref1 = checkpointRefForThreadTurn(THREAD_ID, 1);      assert.equal(gitRefExists(harness.workspaceDir, ref0), true);      assert.equal(gitRefExists(harness.workspaceDir, ref1), true);      assert.equal(gitShowFileAtRef(harness.workspaceDir, ref0, "README.md"), "v1\n");      assert.equal(gitShowFileAtRef(harness.workspaceDir, ref1, "README.md"), "v1\n");    }),  ),); it.live("runs multi-turn file edits and persists checkpoint diffs", () =>  withHarness((harness) =>    Effect.gen(function* () {      yield* seedProjectAndThread(harness);       yield* harness.adapterHarness.queueTurnResponseForNextSession({        events: [          {            type: "turn.started",            ...runtimeBase("evt-multi-1", "2026-02-24T10:01:00.000Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,          },          {            type: "tool.started",            ...runtimeBase("evt-multi-2", "2026-02-24T10:01:00.100Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            toolKind: "command",            title: "Edit file",            detail: "README.md",          },          {            type: "tool.completed",            ...runtimeBase("evt-multi-3", "2026-02-24T10:01:00.200Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            toolKind: "command",            title: "Edit file",            detail: "README.md",          },          {            type: "message.delta",            ...runtimeBase("evt-multi-4", "2026-02-24T10:01:00.300Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            delta: "Updated README to v2.\n",          },          {            type: "turn.completed",            ...runtimeBase("evt-multi-5", "2026-02-24T10:01:00.400Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            status: "completed",          },        ],        mutateWorkspace: ({ cwd }) =>          Effect.sync(() => {            fs.writeFileSync(path.join(cwd, "README.md"), "v2\n", "utf8");          }),      });       yield* startTurn({        harness,        commandId: "cmd-turn-start-multi-1",        messageId: "msg-user-multi-1",        text: "Make first edit",      });       const firstTurnThread = yield* harness.waitForThread(        THREAD_ID,        (entry) => entry.checkpoints.length === 1 && entry.session?.providerSessionId !== null,      );      const sessionId = firstTurnThread.session?.providerSessionId;      assert.equal(sessionId !== null, true);      if (!sessionId) {        return;      }       yield* harness.adapterHarness.queueTurnResponse(sessionId, {        events: [          {            type: "turn.started",            ...runtimeBase("evt-multi-6", "2026-02-24T10:02:00.000Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,          },          {            type: "message.delta",            ...runtimeBase("evt-multi-7", "2026-02-24T10:02:00.100Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            delta: "Updated README to v3.\n",          },          {            type: "turn.completed",            ...runtimeBase("evt-multi-8", "2026-02-24T10:02:00.200Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            status: "completed",          },        ],        mutateWorkspace: ({ cwd }) =>          Effect.sync(() => {            fs.writeFileSync(path.join(cwd, "README.md"), "v3\n", "utf8");          }),      });       yield* startTurn({        harness,        commandId: "cmd-turn-start-multi-2",        messageId: "msg-user-multi-2",        text: "Make second edit",      });       const secondTurnThread = yield* harness.waitForThread(        THREAD_ID,        (entry) =>          entry.latestTurnId === "turn-2" &&          entry.checkpoints.length === 2 &&          entry.checkpoints.some((checkpoint) => checkpoint.checkpointTurnCount === 2),      );      const secondCheckpoint = secondTurnThread.checkpoints.find(        (checkpoint) => checkpoint.checkpointTurnCount === 2,      );      assert.equal(        secondCheckpoint?.files.some((file) => file.path === "README.md"),        true,      );       const checkpointRows = yield* harness.checkpointRepository.listByThreadId({        threadId: THREAD_ID,      });      assert.deepEqual(        checkpointRows.map((row) => row.checkpointTurnCount),        [1, 2],      );       const incrementalDiff = yield* harness.checkpointStore.diffCheckpoints({        cwd: harness.workspaceDir,        fromCheckpointRef: checkpointRefForThreadTurn(THREAD_ID, 1),        toCheckpointRef: checkpointRefForThreadTurn(THREAD_ID, 2),        fallbackFromToHead: false,      });      assert.equal(incrementalDiff.includes("README.md"), true);       const fullDiff = yield* harness.checkpointStore.diffCheckpoints({        cwd: harness.workspaceDir,        fromCheckpointRef: checkpointRefForThreadTurn(THREAD_ID, 0),        toCheckpointRef: checkpointRefForThreadTurn(THREAD_ID, 2),        fallbackFromToHead: false,      });      assert.equal(fullDiff.includes("README.md"), true);       assert.equal(        gitShowFileAtRef(          harness.workspaceDir,          checkpointRefForThreadTurn(THREAD_ID, 1),          "README.md",        ),        "v2\n",      );      assert.equal(        gitShowFileAtRef(          harness.workspaceDir,          checkpointRefForThreadTurn(THREAD_ID, 2),          "README.md",        ),        "v3\n",      );    }),  ),); it.live("tracks approval requests and resolves pending approvals on user response", () =>  withHarness((harness) =>    Effect.gen(function* () {      yield* seedProjectAndThread(harness);       yield* harness.adapterHarness.queueTurnResponseForNextSession({        events: [          {            type: "turn.started",            ...runtimeBase("evt-approval-1", "2026-02-24T10:03:00.000Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,          },          {            type: "approval.requested",            ...runtimeBase("evt-approval-2", "2026-02-24T10:03:00.100Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            requestId: APPROVAL_REQUEST_ID,            requestKind: "command",            detail: "Approve command execution",          },          {            type: "turn.completed",            ...runtimeBase("evt-approval-3", "2026-02-24T10:03:00.200Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            status: "completed",          },        ],      });       yield* startTurn({        harness,        commandId: "cmd-turn-start-approval",        messageId: "msg-user-approval",        text: "Run command needing approval",      });       const thread = yield* harness.waitForThread(THREAD_ID, (entry) =>        entry.activities.some((activity) => activity.kind === "approval.requested"),      );      assert.equal(        thread.activities.some((activity) => activity.kind === "approval.requested"),        true,      );       const pendingRow = yield* harness.waitForPendingApproval(        "req-approval-1",        (row) => row.status === "pending" && row.decision === null,      );      assert.equal(pendingRow.status, "pending");       yield* harness.engine.dispatch({        type: "thread.approval.respond",        commandId: CommandId.makeUnsafe("cmd-approval-respond"),        threadId: THREAD_ID,        requestId: APPROVAL_REQUEST_ID,        decision: "accept",        createdAt: nowIso(),      });       const resolvedRow = yield* harness.waitForPendingApproval(        "req-approval-1",        (row) => row.status === "resolved" && row.decision === "accept",      );      assert.equal(resolvedRow.status, "resolved");      assert.equal(resolvedRow.decision, "accept");       const providerSessionId = thread.session?.providerSessionId ?? "test-session-1";      const approvalResponses = yield* waitForSync(        () => harness.adapterHarness.getApprovalResponses(providerSessionId),        (responses) => responses.length === 1,        "provider approval response",      );      assert.equal(approvalResponses.length, 1);      assert.equal(approvalResponses[0]?.requestId, "req-approval-1");      assert.equal(approvalResponses[0]?.decision, "accept");    }),  ),); it.live("records failed turn runtime state and checkpoint status as error", () =>  withHarness((harness) =>    Effect.gen(function* () {      yield* seedProjectAndThread(harness);       yield* harness.adapterHarness.queueTurnResponseForNextSession({        events: [          {            type: "turn.started",            ...runtimeBase("evt-failure-1", "2026-02-24T10:04:00.000Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,          },          {            type: "message.delta",            ...runtimeBase("evt-failure-2", "2026-02-24T10:04:00.100Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            delta: "Partial output before failure.\n",          },          {            type: "runtime.error",            ...runtimeBase("evt-failure-3", "2026-02-24T10:04:00.200Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            message: "Sandbox command failed.",          },          {            type: "turn.completed",            ...runtimeBase("evt-failure-4", "2026-02-24T10:04:00.300Z"),            threadId: FIXTURE_THREAD_ID,            turnId: FIXTURE_TURN_ID,            status: "failed",            errorMessage: "Sandbox command failed.",          },        ],      });       yield* startTurn({        harness,        commandId: "cmd-turn-start-failure",        messageId: "msg-user-failure",        text: "Run risky command",

Lines 1–500 of 748.