diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea7a3c76b183..9b40b3a7cb1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,8 @@ on: push: branches: - main + # Keep v2 checked while its pull request has conflicts with main. + - t3code/codex-turn-mapping permissions: contents: read diff --git a/.macroscope/check-run-agents/effect-service-conventions.md b/.macroscope/check-run-agents/effect-service-conventions.md index cfb810e37b45..634f5adee195 100644 --- a/.macroscope/check-run-agents/effect-service-conventions.md +++ b/.macroscope/check-run-agents/effect-service-conventions.md @@ -14,6 +14,7 @@ exclude: - "**/*.test.ts" labels: - vouch:trusted + - macroscope-review requires: - Check maxBudgetPerRun: 5 diff --git a/.macroscope/check-run-agents/ui-consistency.md b/.macroscope/check-run-agents/ui-consistency.md index dd88c891ed9b..d2e450235baa 100644 --- a/.macroscope/check-run-agents/ui-consistency.md +++ b/.macroscope/check-run-agents/ui-consistency.md @@ -13,6 +13,7 @@ exclude: - "apps/web/src/**/*.test.tsx" labels: - vouch:trusted + - macroscope-review requires: - Check maxBudgetPerRun: 2 diff --git a/apps/desktop/src/settings/DesktopClientSettings.test.ts b/apps/desktop/src/settings/DesktopClientSettings.test.ts index 8d6699d014cd..d4efbfd002b3 100644 --- a/apps/desktop/src/settings/DesktopClientSettings.test.ts +++ b/apps/desktop/src/settings/DesktopClientSettings.test.ts @@ -32,6 +32,7 @@ const clientSettings: ClientSettings = { confirmThreadDelete: false, confirmThreadUnpin: false, contextWindowMeterEnabled: false, + composerCollapseOnBlur: true, composerCollapseOnScroll: true, dismissedProviderUpdateNotificationKeys: [], diffIgnoreWhitespace: true, diff --git a/apps/server/src/mcp/PreviewAutomationBroker.test.ts b/apps/server/src/mcp/PreviewAutomationBroker.test.ts index 3bc0fd71308e..42f849f5edf3 100644 --- a/apps/server/src/mcp/PreviewAutomationBroker.test.ts +++ b/apps/server/src/mcp/PreviewAutomationBroker.test.ts @@ -404,6 +404,49 @@ it.effect("classifies a remote non-editable target without collapsing it to exec ); }); +it.effect.each([ + "PreviewAutomationRecordingTransferError", + "PreviewAutomationRecordingDesktopUpdateRequiredError", + "PreviewAutomationRecordingTooLargeError", + "PreviewAutomationRecordingDeadlineExpiredError", +] as const)("preserves recording failure %s", (tag) => + Effect.scoped( + Effect.gen(function* () { + const broker = yield* makeBroker; + const remoteError = { + _tag: tag, + message: "remote recording details", + detail: { reason: "untrusted-reason", threadId: "untrusted-thread" }, + }; + const requests = requestsFrom(yield* broker.connect(makeHost())); + yield* Stream.runForEach(requests, (request) => + broker.respond({ + clientId: "client-1", + connectionId: request.connectionId, + requestId: request.requestId, + ok: false, + error: remoteError, + }), + ).pipe(Effect.forkScoped); + yield* Effect.yieldNow; + const error = yield* broker + .invoke({ + scope, + operation: "recordingStop", + input: {}, + }) + .pipe(Effect.flip); + expect(error).toMatchObject({ + _tag: tag, + threadId: scope.threadId, + }); + expect(error.cause).toBe(remoteError); + expect(error.message).toContain("remains on the desktop"); + expect(error.message).not.toContain("remote recording details"); + }), + ), +); + it.effect("distinguishes malformed remote failures", () => Effect.scoped( Effect.gen(function* () { diff --git a/apps/server/src/mcp/PreviewAutomationBroker.ts b/apps/server/src/mcp/PreviewAutomationBroker.ts index 3e9bfaac26ff..d8f17973c218 100644 --- a/apps/server/src/mcp/PreviewAutomationBroker.ts +++ b/apps/server/src/mcp/PreviewAutomationBroker.ts @@ -7,6 +7,10 @@ import { PreviewAutomationMalformedResponseError, PreviewAutomationNoAvailableHostError, PreviewAutomationRemoteUnavailableError, + PreviewAutomationRecordingTransferError, + PreviewAutomationRecordingDesktopUpdateRequiredError, + PreviewAutomationRecordingTooLargeError, + PreviewAutomationRecordingDeadlineExpiredError, PreviewAutomationRequestQueueClosedError, PreviewAutomationResultTooLargeError, PreviewAutomationTabNotFoundError, @@ -194,6 +198,26 @@ const classifyResponseError = ( cause: error, }; switch (error._tag) { + case "PreviewAutomationRecordingDesktopUpdateRequiredError": + return new PreviewAutomationRecordingDesktopUpdateRequiredError({ + threadId: context.threadId, + cause: error, + }); + case "PreviewAutomationRecordingTooLargeError": + return new PreviewAutomationRecordingTooLargeError({ + threadId: context.threadId, + cause: error, + }); + case "PreviewAutomationRecordingDeadlineExpiredError": + return new PreviewAutomationRecordingDeadlineExpiredError({ + threadId: context.threadId, + cause: error, + }); + case "PreviewAutomationRecordingTransferError": + return new PreviewAutomationRecordingTransferError({ + threadId: context.threadId, + cause: error, + }); case "PreviewAutomationNoAvailableHostError": return new PreviewAutomationNoAvailableHostError({ ...context, diff --git a/apps/server/src/mcp/toolkits/preview/handlers.test.ts b/apps/server/src/mcp/toolkits/preview/handlers.test.ts index 2c4e66746447..a2a88e14fcef 100644 --- a/apps/server/src/mcp/toolkits/preview/handlers.test.ts +++ b/apps/server/src/mcp/toolkits/preview/handlers.test.ts @@ -1,6 +1,17 @@ -import { describe, expect, it } from "vite-plus/test"; +import { describe, expect, it } from "@effect/vitest"; +import * as NodeServices from "@effect/platform-node/NodeServices"; +import { ThreadId } from "@t3tools/contracts"; +import * as Effect from "effect/Effect"; +import * as FileSystem from "effect/FileSystem"; +import * as Layer from "effect/Layer"; +import * as Path from "effect/Path"; -import { normalizePreviewOpenInput } from "./handlers.ts"; +import { + createPendingAttachmentId, + parseThreadSegmentFromAttachmentId, +} from "../../../attachmentStore.ts"; +import * as ServerConfig from "../../../config.ts"; +import { claimPreviewRecording, normalizePreviewOpenInput } from "./handlers.ts"; describe("normalizePreviewOpenInput", () => { it("leaves an unstated visibility for the client preference to decide", () => { @@ -30,3 +41,115 @@ describe("normalizePreviewOpenInput", () => { }); }); }); + +describe("claimPreviewRecording", () => { + it.effect("overlapping and repeated claims return the same retained recording", () => + Effect.gen(function* () { + const config = yield* ServerConfig.ServerConfig; + const fileSystem = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const uploadedAttachmentId = createPendingAttachmentId(".webm"); + const pendingPath = path.join(config.attachmentsDir, `${uploadedAttachmentId}.webm`); + yield* fileSystem.makeDirectory(config.attachmentsDir, { recursive: true }); + yield* fileSystem.writeFileString(pendingPath, "video!"); + const response = { + id: "desktop-recording", + tabId: "tab-1", + path: "/desktop/recording.webm", + mimeType: "video/webm", + sizeBytes: 6, + createdAt: "2026-09-07T00:00:00.000Z", + uploadedAttachmentId, + }; + const claim = claimPreviewRecording(ThreadId.make("thread-1"), response); + const [first, second] = yield* Effect.all([claim, claim], { concurrency: "unbounded" }); + expect(first).toEqual(second); + expect(yield* claim).toEqual(first); + expect(yield* fileSystem.readFileString(first.path)).toBe("video!"); + expect(yield* fileSystem.exists(pendingPath)).toBe(false); + const wrongThread = yield* claimPreviewRecording(ThreadId.make("thread-2"), response).pipe( + Effect.result, + ); + expect(wrongThread._tag).toBe("Failure"); + const wrongPath = yield* claimPreviewRecording(ThreadId.make("thread-1"), { + ...response, + uploadedAttachmentId: `../${uploadedAttachmentId}`, + }).pipe(Effect.result); + expect(wrongPath._tag).toBe("Failure"); + }).pipe( + Effect.provide( + ServerConfig.layerTest(process.cwd(), { prefix: "t3-preview-recording-" }).pipe( + Layer.provideMerge(NodeServices.layer), + ), + ), + ), + ); + + it.effect.each([6, 5])( + "claims only a complete uploaded recording (reported bytes: %s)", + (sizeBytes) => + Effect.gen(function* () { + const config = yield* ServerConfig.ServerConfig; + const fileSystem = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const uploadedAttachmentId = createPendingAttachmentId(".webm"); + const pendingPath = path.join(config.attachmentsDir, `${uploadedAttachmentId}.webm`); + yield* fileSystem.makeDirectory(config.attachmentsDir, { recursive: true }); + yield* fileSystem.writeFileString(pendingPath, "video!"); + const response = { + id: "desktop-recording", + tabId: "tab-1", + path: "/desktop/recording.webm", + mimeType: "video/webm", + sizeBytes, + createdAt: "2026-09-07T00:00:00.000Z", + uploadedAttachmentId, + }; + const result = yield* claimPreviewRecording(ThreadId.make("thread-1"), response).pipe( + Effect.result, + ); + if (sizeBytes === 6) { + expect(result._tag).toBe("Success"); + if (result._tag !== "Success") return; + expect(result.success.path).not.toBe(response.path); + expect(parseThreadSegmentFromAttachmentId(result.success.id)).toBe("thread-1"); + expect(yield* fileSystem.readFileString(result.success.path)).toBe("video!"); + expect(yield* fileSystem.exists(pendingPath)).toBe(false); + } else { + expect(result._tag).toBe("Failure"); + if (result._tag !== "Failure") return; + expect(result.failure._tag).toBe("PreviewAutomationRecordingTransferError"); + expect(yield* fileSystem.exists(pendingPath)).toBe(true); + } + }).pipe( + Effect.provide( + ServerConfig.layerTest(process.cwd(), { prefix: "t3-preview-recording-" }).pipe( + Layer.provideMerge(NodeServices.layer), + ), + ), + ), + ); + + it.effect("reports an older desktop without returning its inaccessible path", () => + Effect.gen(function* () { + const result = yield* claimPreviewRecording(ThreadId.make("thread-1"), { + id: "desktop-recording", + tabId: "tab-1", + path: "/desktop/recording.webm", + mimeType: "video/webm", + sizeBytes: 6, + createdAt: "2026-09-07T00:00:00.000Z", + }).pipe(Effect.result); + expect(result._tag).toBe("Failure"); + if (result._tag !== "Failure") return; + expect(result.failure._tag).toBe("PreviewAutomationRecordingDesktopUpdateRequiredError"); + expect(result.failure.message).toContain("Update the desktop app"); + }).pipe( + Effect.provide( + ServerConfig.layerTest(process.cwd(), { prefix: "t3-preview-recording-" }).pipe( + Layer.provideMerge(NodeServices.layer), + ), + ), + ), + ); +}); diff --git a/apps/server/src/mcp/toolkits/preview/handlers.ts b/apps/server/src/mcp/toolkits/preview/handlers.ts index c501ee08711d..ac4e124ea312 100644 --- a/apps/server/src/mcp/toolkits/preview/handlers.ts +++ b/apps/server/src/mcp/toolkits/preview/handlers.ts @@ -1,16 +1,31 @@ import * as Effect from "effect/Effect"; -import type { - PreviewAutomationOperation, - PreviewAutomationOpenInput, +import * as FileSystem from "effect/FileSystem"; +import * as Schema from "effect/Schema"; +import { + PROVIDER_SEND_TURN_MAX_FILE_BYTES, + PREVIEW_RECORDING_STOP_TIMEOUT_MS, + PreviewAutomationRecordingTransferError, + PreviewAutomationRecordingDesktopUpdateRequiredError, PreviewAutomationRecordingArtifact, - PreviewAutomationRecordingStatus, - PreviewAutomationResizeResult, - PreviewAutomationSetColorSchemeResult, - PreviewAutomationSnapshot, - PreviewAutomationStatus, - PreviewTabId, + type ThreadId, + type PreviewAutomationOperation, + type PreviewAutomationOpenInput, + type PreviewAutomationRecordingStatus, + type PreviewAutomationResizeResult, + type PreviewAutomationSetColorSchemeResult, + type PreviewAutomationSnapshot, + type PreviewAutomationStatus, + type PreviewTabId, } from "@t3tools/contracts"; +import { + parseAttachmentUuid, + parseAttachmentFileExtension, + PENDING_ATTACHMENT_THREAD_SEGMENT, + toSafeThreadAttachmentSegment, +} from "../../../attachmentStore.ts"; +import { resolveAttachmentRelativePath } from "../../../attachmentPaths.ts"; +import * as ServerConfig from "../../../config.ts"; import * as McpInvocationContext from "../../McpInvocationContext.ts"; import * as PreviewAutomationBroker from "../../PreviewAutomationBroker.ts"; import { PreviewSnapshotToolkit, PreviewStandardToolkit, PreviewToolkit } from "./tools.ts"; @@ -67,6 +82,79 @@ const invokeTargeted = ( return invoke(operation, operationInput, timeoutMs, tabId); }; +const UploadedRecordingArtifact = Schema.Struct({ + ...PreviewAutomationRecordingArtifact.fields, + uploadedAttachmentId: Schema.optional(Schema.String), +}); +const decodeUploadedRecordingArtifact = Schema.decodeUnknownEffect(UploadedRecordingArtifact); + +export const claimPreviewRecording = Effect.fn("PreviewToolkit.claimRecording")(function* ( + threadId: ThreadId, + response: unknown, +) { + const artifact = yield* decodeUploadedRecordingArtifact(response).pipe( + Effect.mapError( + (cause) => + new PreviewAutomationRecordingTransferError({ + threadId, + cause, + }), + ), + ); + if (!artifact.uploadedAttachmentId) { + return yield* new PreviewAutomationRecordingDesktopUpdateRequiredError({ threadId }); + } + const config = yield* ServerConfig.ServerConfig; + const uuid = parseAttachmentUuid(artifact.uploadedAttachmentId); + const extension = parseAttachmentFileExtension(artifact.uploadedAttachmentId); + const threadSegment = toSafeThreadAttachmentSegment(threadId); + const pendingId = `${PENDING_ATTACHMENT_THREAD_SEGMENT}-${uuid}-${extension}`; + if (!uuid || !extension || !threadSegment || artifact.uploadedAttachmentId !== pendingId) { + return yield* new PreviewAutomationRecordingTransferError({ + threadId, + }); + } + // The same completed upload can be returned to overlapping stop requests. + const finalId = `${threadSegment}-${uuid}-${extension}`; + const currentPath = resolveAttachmentRelativePath({ + attachmentsDir: config.attachmentsDir, + relativePath: `${pendingId}.${extension}`, + }); + const finalPath = resolveAttachmentRelativePath({ + attachmentsDir: config.attachmentsDir, + relativePath: `${finalId}.${extension}`, + }); + if (!currentPath || !finalPath) { + return yield* new PreviewAutomationRecordingTransferError({ threadId }); + } + const fileSystem = yield* FileSystem.FileSystem; + const validateFile = (filePath: string) => + fileSystem.stat(filePath).pipe( + Effect.filterOrFail( + (stat) => + stat.type === "File" && + Number(stat.size) === artifact.sizeBytes && + artifact.sizeBytes > 0 && + artifact.sizeBytes <= PROVIDER_SEND_TURN_MAX_FILE_BYTES, + () => new PreviewAutomationRecordingTransferError({ threadId }), + ), + ); + yield* Effect.gen(function* () { + yield* validateFile(currentPath); + yield* fileSystem.rename(currentPath, finalPath); + }).pipe( + // Another stop may already have claimed this exact upload for this thread. + Effect.catch((cause) => + cause._tag !== "PreviewAutomationRecordingTransferError" && cause.reason._tag === "NotFound" + ? validateFile(finalPath) + : Effect.fail(cause), + ), + Effect.mapError((cause) => new PreviewAutomationRecordingTransferError({ threadId, cause })), + ); + const { uploadedAttachmentId: _uploadedAttachmentId, ...recording } = artifact; + return { ...recording, id: finalId, path: finalPath }; +}); + const handlers = { preview_status: (input) => invokeTargeted("status", input ?? {}), preview_open: (input) => @@ -94,7 +182,15 @@ const handlers = { preview_recording_start: (input) => invokeTargeted("recordingStart", input ?? {}), preview_recording_stop: (input) => - invokeTargeted("recordingStop", input ?? {}), + Effect.gen(function* () { + const scope = yield* McpInvocationContext.requireMcpCapability("preview"); + const response = yield* invokeTargeted( + "recordingStop", + { ...input, transferToEnvironment: true }, + PREVIEW_RECORDING_STOP_TIMEOUT_MS, + ); + return yield* claimPreviewRecording(scope.threadId, response); + }), } satisfies Parameters[0]; const { preview_snapshot, ...standardHandlers } = handlers; diff --git a/apps/server/src/mcp/toolkits/preview/tools.ts b/apps/server/src/mcp/toolkits/preview/tools.ts index ab8d1580bb61..cc2e572bc373 100644 --- a/apps/server/src/mcp/toolkits/preview/tools.ts +++ b/apps/server/src/mcp/toolkits/preview/tools.ts @@ -19,10 +19,12 @@ import { PreviewAutomationWaitForInput, } from "@t3tools/contracts"; import * as Schema from "effect/Schema"; +import * as FileSystem from "effect/FileSystem"; import { Tool, Toolkit } from "effect/unstable/ai"; import * as McpInvocationContext from "../../McpInvocationContext.ts"; import * as PreviewAutomationBroker from "../../PreviewAutomationBroker.ts"; +import * as ServerConfig from "../../../config.ts"; const dependencies = [ McpInvocationContext.McpInvocationContext, @@ -207,11 +209,11 @@ export const PreviewRecordingStartTool = safeBrowserTool( export const PreviewRecordingStopTool = safeBrowserTool( Tool.make("preview_recording_stop", { description: - "Stop recording the collaborative browser tab selected by tabId, or this agent session's current tab when omitted, and save it as a local evidence artifact.", + "Stop recording the collaborative browser tab selected by tabId, or this agent session's current tab when omitted, and transfer the compressed recording once (up to 50 MiB) to an evidence file readable in this agent's environment. Returns its environment-local path after transfer succeeds.", parameters: PreviewAutomationTabTargetInput, success: PreviewAutomationRecordingArtifact, failure: PreviewAutomationError, - dependencies, + dependencies: [...dependencies, FileSystem.FileSystem, ServerConfig.ServerConfig], }).annotate(Tool.Title, "Stop browser recording"), ); diff --git a/apps/server/src/orchestration-v2/AgentSessionImportSources.test.ts b/apps/server/src/orchestration-v2/AgentSessionImportSources.test.ts new file mode 100644 index 000000000000..85b746f8bc7a --- /dev/null +++ b/apps/server/src/orchestration-v2/AgentSessionImportSources.test.ts @@ -0,0 +1,34 @@ +import { assert, it } from "@effect/vitest"; +import { ProviderInstanceId, ThreadId } from "@t3tools/contracts"; +import * as NodeSqliteClient from "@t3tools/shared/nodeSqliteClient"; +import * as Effect from "effect/Effect"; +import * as Layer from "effect/Layer"; +import { AgentSessionImportSources, layer } from "./AgentSessionImportSources.ts"; + +it.layer(layer.pipe(Layer.provide(NodeSqliteClient.layerMemory())))( + "AgentSessionImportSources", + (it) => { + it.effect("identifies the source and write operation when recording fails", () => + Effect.gen(function* () { + const store = yield* AgentSessionImportSources; + const threadId = ThreadId.make("thread:failed-import-record"); + const source = { + provider: "codex" as const, + providerInstanceId: ProviderInstanceId.make("codex"), + providerSessionId: "session", + filePath: "/session.jsonl", + size: 100, + mtimeMs: 1, + device: 1, + inode: 2, + birthtimeMs: 1, + }; + const failure = yield* store.record(threadId, source).pipe(Effect.flip); + assert.equal(failure.operation, "record-import-source"); + assert.equal(failure.threadId, threadId); + assert.equal(failure.filePath, source.filePath); + assert.include(failure.message, "record-import-source"); + }), + ); + }, +); diff --git a/apps/server/src/orchestration-v2/AgentSessionImportSources.ts b/apps/server/src/orchestration-v2/AgentSessionImportSources.ts new file mode 100644 index 000000000000..81658c72739c --- /dev/null +++ b/apps/server/src/orchestration-v2/AgentSessionImportSources.ts @@ -0,0 +1,74 @@ +import { + AgentSessionImportSource, + AgentSessionScanError, + ProjectId, + ThreadId, +} from "@t3tools/contracts"; +import * as Context from "effect/Context"; +import * as Effect from "effect/Effect"; +import * as Layer from "effect/Layer"; +import * as Schema from "effect/Schema"; +import * as SqlClient from "effect/unstable/sql/SqlClient"; + +/** File fingerprints are retry bookkeeping, independent of provider runtime sessions. */ +export class AgentSessionImportSources extends Context.Service< + AgentSessionImportSources, + { + readonly list: ( + projectId: ProjectId, + ) => Effect.Effect, AgentSessionScanError>; + readonly record: ( + threadId: ThreadId, + source: AgentSessionImportSource, + ) => Effect.Effect; + } +>()("t3/orchestration-v2/AgentSessionImportSources") {} + +export const layer = Layer.effect( + AgentSessionImportSources, + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + const decode = Schema.decodeUnknownEffect(Schema.fromJsonString(AgentSessionImportSource)); + const encode = Schema.encodeEffect(Schema.fromJsonString(AgentSessionImportSource)); + return AgentSessionImportSources.of({ + list: Effect.fn("AgentSessionImportSources.list")( + function* (projectId) { + const rows = yield* sql<{ readonly source_json: string }>` + SELECT source.source_json + FROM orchestration_v2_agent_session_import_sources AS source + INNER JOIN orchestration_v2_projection_threads AS thread ON thread.thread_id = source.thread_id + WHERE json_extract(thread.payload_json, '$.projectId') = ${projectId} + AND json_extract(thread.payload_json, '$.deletedAt') IS NULL + AND json_extract(thread.payload_json, '$.archivedAt') IS NULL + `; + return yield* Effect.forEach(rows, (row) => decode(row.source_json)); + }, + Effect.mapError( + (cause) => new AgentSessionScanError({ operation: "read-projects", cause }), + ), + ), + record: Effect.fn("AgentSessionImportSources.record")( + function* (threadId, source) { + const encoded = yield* encode(source); + yield* sql` + INSERT INTO orchestration_v2_agent_session_import_sources (thread_id, file_path, source_json) + VALUES (${threadId}, ${source.filePath}, ${encoded}) + ON CONFLICT(thread_id, file_path) DO UPDATE SET source_json = excluded.source_json + `; + }, + (effect, threadId, source) => + effect.pipe( + Effect.mapError( + (cause) => + new AgentSessionScanError({ + operation: "record-import-source", + threadId, + filePath: source.filePath, + cause, + }), + ), + ), + ), + }); + }), +); diff --git a/apps/server/src/persistence/Migrations.history.test.ts b/apps/server/src/persistence/Migrations.history.test.ts new file mode 100644 index 000000000000..9eeba0e56bdc --- /dev/null +++ b/apps/server/src/persistence/Migrations.history.test.ts @@ -0,0 +1,124 @@ +import { assert, it } from "@effect/vitest"; +import * as Effect from "effect/Effect"; +import * as SqlClient from "effect/unstable/sql/SqlClient"; +import * as NodeSqliteClient from "@t3tools/shared/nodeSqliteClient"; + +import { migrationEntries, migrationManifest, runMigrations } from "./Migrations.ts"; + +const seedHistorical = Effect.fn("seedHistorical")(function* (base: number, count: number) { + const sql = yield* SqlClient.SqlClient; + yield* runMigrations({ toMigrationInclusive: base }); + for (const [id, name, migration] of migrationEntries.filter( + ([id]) => id >= 48 && id < 48 + count, + )) { + yield* migration; + yield* sql`INSERT INTO effect_sql_migrations (migration_id, name) VALUES (${base + 1 + id - 48}, ${name})`; + } +}); + +for (const [base, count] of [ + [43, 9], + [44, 9], + [44, 11], + [43, 1], + [44, 5], +] as const) { + it.effect(`upgrades historical V2 ${base + 1}–${base + count} without replaying its DDL`, () => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + yield* seedHistorical(base, count); + yield* runMigrations(); + const rows = yield* sql<{ + migration_id: number; + name: string; + }>`SELECT migration_id, name FROM effect_sql_migrations ORDER BY migration_id`; + assert.deepStrictEqual( + rows.map(({ migration_id, name }) => [migration_id, name] as const), + migrationManifest, + ); + const columns = yield* sql<{ name: string }>`PRAGMA table_info(projection_projects)`; + assert.ok(columns.some(({ name }) => name === "auto_pull")); + assert.ok(columns.some(({ name }) => name === "project_icon_json")); + assert.deepStrictEqual(yield* runMigrations(), []); + }).pipe(Effect.provide(NodeSqliteClient.layerMemory())), + ); +} + +it.effect("preserves the historical manifest when a missing main migration fails", () => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + yield* seedHistorical(44, 9); + yield* sql`ALTER TABLE projection_thread_messages RENAME TO unavailable_messages`; + const before = yield* sql`SELECT * FROM effect_sql_migrations ORDER BY migration_id`; + const result = yield* Effect.exit(runMigrations()); + assert.strictEqual(result._tag, "Failure"); + assert.deepStrictEqual( + yield* sql`SELECT * FROM effect_sql_migrations ORDER BY migration_id`, + before, + ); + const columns = yield* sql<{ name: string }>`PRAGMA table_info(projection_projects)`; + assert.ok(!columns.some(({ name }) => name === "auto_pull")); + }).pipe(Effect.provide(NodeSqliteClient.layerMemory())), +); + +it.effect("rejects an unknown migration in a historical cohort without changing it", () => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + yield* seedHistorical(44, 9); + yield* sql`UPDATE effect_sql_migrations SET name = 'UnknownMigration' WHERE migration_id = 50`; + const before = yield* sql`SELECT * FROM effect_sql_migrations ORDER BY migration_id`; + assert.strictEqual((yield* Effect.exit(runMigrations()))._tag, "Failure"); + assert.deepStrictEqual( + yield* sql`SELECT * FROM effect_sql_migrations ORDER BY migration_id`, + before, + ); + }).pipe(Effect.provide(NodeSqliteClient.layerMemory())), +); + +it.effect("rolls back reconciliation when a later V2 migration fails", () => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + yield* seedHistorical(44, 11); + yield* sql`CREATE INDEX orchestration_v2_projection_turn_items_thread_run_idx ON orchestration_v2_projection_turn_items(thread_id, run_id)`; + const before = yield* sql`SELECT * FROM effect_sql_migrations ORDER BY migration_id`; + assert.strictEqual((yield* Effect.exit(runMigrations()))._tag, "Failure"); + assert.deepStrictEqual( + yield* sql`SELECT * FROM effect_sql_migrations ORDER BY migration_id`, + before, + ); + const columns = yield* sql<{ name: string }>`PRAGMA table_info(projection_projects)`; + assert.ok(!columns.some(({ name }) => name === "auto_pull")); + }).pipe(Effect.provide(NodeSqliteClient.layerMemory())), +); + +it.effect("preserves V2 import progress and original migration timestamps", () => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + yield* seedHistorical(43, 9); + yield* sql`INSERT INTO orchestration_v2_legacy_imports (thread_id, source_updated_at, shell_imported_at, imported_message_count) VALUES ('thread-1', '2026-09-01', '2026-09-02', 123)`; + yield* sql`UPDATE effect_sql_migrations SET created_at = '2026-09-01 00:00:00' WHERE migration_id = 44`; + const before = yield* sql`SELECT * FROM orchestration_v2_legacy_imports`; + yield* runMigrations(); + assert.deepStrictEqual(yield* sql`SELECT * FROM orchestration_v2_legacy_imports`, before); + assert.deepStrictEqual( + yield* sql`SELECT created_at FROM effect_sql_migrations WHERE migration_id = 48`, + [{ created_at: "2026-09-01 00:00:00" }], + ); + }).pipe(Effect.provide(NodeSqliteClient.layerMemory())), +); + +it.effect("rejects a historical migration ceiling below the required main schema", () => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + yield* seedHistorical(43, 9); + const before = yield* sql`SELECT * FROM effect_sql_migrations ORDER BY migration_id`; + assert.strictEqual( + (yield* Effect.exit(runMigrations({ toMigrationInclusive: 46 })))._tag, + "Failure", + ); + assert.deepStrictEqual( + yield* sql`SELECT * FROM effect_sql_migrations ORDER BY migration_id`, + before, + ); + }).pipe(Effect.provide(NodeSqliteClient.layerMemory())), +); diff --git a/apps/server/src/provider/Layers/ProviderRegistry.test.ts b/apps/server/src/provider/Layers/ProviderRegistry.test.ts index 7020b5c9b000..3db2ac8bd559 100644 --- a/apps/server/src/provider/Layers/ProviderRegistry.test.ts +++ b/apps/server/src/provider/Layers/ProviderRegistry.test.ts @@ -591,6 +591,41 @@ it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te ]); }); + it("stores workspace skills and commands without changing machine metadata", () => { + const provider = { + instanceId: ProviderInstanceId.make("codex"), + driver: ProviderDriverKind.make("codex"), + status: "ready", + enabled: true, + installed: true, + auth: { status: "authenticated" }, + checkedAt: "2026-03-25T00:00:00.000Z", + version: "1.0.0", + models: [], + slashCommands: [{ name: "global" }], + skills: [{ name: "global", path: "/global/SKILL.md", enabled: true }], + } satisfies ServerProvider; + const scopedSnapshot = { + ...provider, + checkedAt: "2026-03-25T00:01:00.000Z", + slashCommands: [{ name: "project" }], + skills: [{ name: "project", path: "/project/SKILL.md", enabled: true }], + } satisfies ServerProvider; + + const result = upsertProviderWorkspaceSnapshot(provider, "/project", scopedSnapshot); + + assert.deepStrictEqual(result.slashCommands, provider.slashCommands); + assert.deepStrictEqual(result.skills, provider.skills); + assert.deepStrictEqual(result.workspaceSnapshots, [ + { + cwd: "/project", + checkedAt: scopedSnapshot.checkedAt, + slashCommands: scopedSnapshot.slashCommands, + skills: scopedSnapshot.skills, + }, + ]); + }); + it("preserves previously discovered provider models when a refresh returns none", () => { const previousProvider = { instanceId: ProviderInstanceId.make("cursor"), diff --git a/apps/web/src/browser/browserRecordingUpload.ts b/apps/web/src/browser/browserRecordingUpload.ts new file mode 100644 index 000000000000..399352898388 --- /dev/null +++ b/apps/web/src/browser/browserRecordingUpload.ts @@ -0,0 +1,84 @@ +import { + PROVIDER_SEND_TURN_MAX_FILE_BYTES, + PreviewAutomationRecordingTransferError, + PreviewAutomationRecordingTooLargeError, + PreviewAutomationRecordingDeadlineExpiredError, + type DesktopPreviewRecordingArtifact, + type ScopedThreadRef, +} from "@t3tools/contracts"; +import { resolveAssetUrl } from "@t3tools/client-runtime/state/assets"; +import { + deletePendingAttachmentUpload, + runAttachmentUploadCycle, +} from "@t3tools/client-runtime/state/attachments"; + +import { appAtomRegistry } from "~/rpc/atomRegistry"; +import { attachmentEnvironment } from "~/state/attachments"; +import { readPreparedConnection } from "~/state/session"; + +/** Sends the finished encoded file once; capture frames never cross the environment connection. */ +export async function uploadBrowserRecording( + { environmentId, threadId }: ScopedThreadRef, + artifact: DesktopPreviewRecordingArtifact, + blob: Blob, + deadlineMs: number, +): Promise { + if (blob.size > PROVIDER_SEND_TURN_MAX_FILE_BYTES) { + throw new PreviewAutomationRecordingTooLargeError({ threadId }); + } + const result = await runAttachmentUploadCycle({ + registry: appAtomRegistry, + createUploadUrl: attachmentEnvironment.createUploadUrl, + remove: attachmentEnvironment.remove, + environmentId, + upload: { + type: "file", + name: artifact.path.split(/[\\/]/).at(-1) ?? artifact.id, + mimeType: artifact.mimeType, + sizeBytes: blob.size, + }, + resolveUploadUrl: (relativeUrl) => { + const connection = readPreparedConnection(environmentId); + return connection ? resolveAssetUrl(connection.httpBaseUrl, relativeUrl) : null; + }, + transport: (url) => { + const controller = new AbortController(); + // Encoding, saving and minting consume the same request budget. Leave time to reply. + const remainingMs = deadlineMs - Date.now() - 1_000; + return { + abort: () => controller.abort(), + done: + remainingMs <= 0 + ? Promise.reject(new Error("Recording transfer deadline expired.")) + : fetch(url, { + method: "POST", + headers: { "Content-Type": artifact.mimeType }, + body: blob, + signal: AbortSignal.any([controller.signal, AbortSignal.timeout(remainingMs)]), + }).then((response) => { + if (!response.ok) + throw new Error(`Recording upload rejected (${response.status}).`); + }), + }; + }, + }); + if (result.status !== "uploaded") { + if (result.attachmentId) { + deletePendingAttachmentUpload({ + registry: appAtomRegistry, + remove: attachmentEnvironment.remove, + environmentId, + attachmentId: result.attachmentId, + }); + } + const cause = result.status === "failed" ? result.error : undefined; + if (Date.now() >= deadlineMs - 1_000) { + throw new PreviewAutomationRecordingDeadlineExpiredError({ threadId, cause }); + } + throw new PreviewAutomationRecordingTransferError({ + threadId, + cause, + }); + } + return result.attachmentId; +} diff --git a/apps/web/src/components/chat/markdownImageGallery.ts b/apps/web/src/components/chat/markdownImageGallery.ts new file mode 100644 index 000000000000..b462f23c84b2 --- /dev/null +++ b/apps/web/src/components/chat/markdownImageGallery.ts @@ -0,0 +1,51 @@ +import { mediaKindFromPath } from "@t3tools/shared/filePreview"; +import { mediaUrlReference } from "@t3tools/client-runtime/media-reference"; +import type { ExpandedImageItem, ExpandedImagePreview } from "./ExpandedImagePreview"; +import { resolveExternalWebLinkHost } from "./externalLinkContextMenu"; +import { resolveProtocolRelativeMediaUrl } from "../media/mediaContent"; + +// Weak keys retain resolved media actions only while the rendered image is reachable. +export const markdownImageItems = new WeakMap(); + +/** Collect in document order only when opened, including PR sections separated by videos. */ +export function markdownImageGallery( + element: Element, + selected: ExpandedImageItem, +): ExpandedImagePreview { + const scope = element.closest("[data-image-gallery]") ?? element.closest(".chat-markdown"); + const images: ExpandedImageItem[] = []; + let index = -1; + for (const image of scope?.querySelectorAll("img") ?? []) { + const registered = markdownImageItems.get(image); + if (!registered) continue; + const link = image.closest("a"); + const href = link?.getAttribute("href") ?? ""; + if (link && mediaKindFromPath(href) !== "image") continue; + const linkedSource = + resolveExternalWebLinkHost(href) !== null ? resolveProtocolRelativeMediaUrl(href) : null; + const reference = mediaUrlReference(href); + const item = linkedSource + ? { + ...registered, + src: linkedSource, + originalUrl: href, + actionsSource: { + kind: "image" as const, + name: registered.name, + src: linkedSource, + ...(reference ? { reference } : {}), + }, + } + : registered; + if ( + image === element || + (!markdownImageItems.has(element) && index < 0 && item.src === selected.src) + ) { + index = images.length; + images.push(selected); + } else { + images.push(item); + } + } + return index < 0 ? { images: [selected], index: 0 } : { images, index }; +} diff --git a/audits/orchestrator-v2/2026-09-02/AUDIT.md b/audits/orchestrator-v2/2026-09-02/AUDIT.md new file mode 100644 index 000000000000..ecac30d310fa --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/AUDIT.md @@ -0,0 +1,99 @@ +# Orchestrator V2 audit — 2026-09-02 + +The current branch has **17 confirmed findings: 14 correctness or feature-parity problems and three unbounded data-loading/transfer paths**. The performance findings establish unnecessary read/decode or transfer work, not measured latency or memory numbers. The earlier provider/history/compatibility fixes inspected in this pass remain present. Several newly found problems already existed before the latest rebases; they are not all new rebase mistakes. + +The most urgent findings are the existing-V2 database upgrade failure, project deletion that partially deletes or orphans threads, full-thread diff failure after the second run, OpenCode work surviving cancellation/release, and background Cursor metadata generation with unrestricted tool access. The web sidebar and attachment flows also have concrete regressions. + +This is an audit, not a fix batch. Product code and existing tests were left unchanged; nothing was committed or pushed. Reports and audit-only probes are inside the repository at your request. Three GPT-5.6 Sol reviewers worked with bounded concurrency; the primary agent reviewed their claims, traced cross-cutting paths, and rejected a false positive. + +| Reference | Value | +| ----------------------------------------- | ---------------------------------------------------------------------------------------------- | +| Branch | `t3code/codex-turn-mapping` | +| Audited HEAD | `d2f1f511f4cc833bc930d6c355cd0f9b61e835a0` | +| Fetched main / merge base | `57a66608b918d673eeec7e6c94ea5906b756fcd0` | +| Branch extent | 332 branch-only commits, 0 main-only commits; 942 changed files | +| Previous reviewed object | `47f5b100440591d2f49aa30cf3bb69eacae07f52` | +| Rebased equivalent of previous review tip | `c1791ab2637` | +| Inventoried additions | 165 main commits since the old comparison base; 21 branch commits after the rebased review tip | + +Main being an ancestor does not prove parity: retained V1 implementations can be bypassed by V2 adapters and services. Likewise, a commit being an ancestor of the rebased review tip does not establish that the same main behavior was available at the original review. The classifications below follow current call paths and, where stated, the actual historical code. + +## Fix decisions + +**P1** means fix before rollout or the next substantial use of the affected path. **P2** means a confirmed, more limited behavior or scaling problem. Every row has a concrete trigger. A `YES` approves fixing that row; a `NO` accepts or defers the stated behavior. All decisions remain open; recommendations are not approvals. + +| ID | Priority | Difference and affected path | Classification | Recommendation | +| --- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | +| F01 | P1 — upgrade blocker | Old V2 databases ending at migration 052 fail at current 053 because the legacy-import table already exists. They also skip main 044's project-model repair. | New round-20 migration renumbering error. Actual current-migrator reproduction. | **YES:** reconcile supported old migration histories and apply the missed repair. Fresh-schema tests are insufficient. | +| F02 | P1 | A visible thread from an environment without hydrated provider config can crash the web/desktop sidebar. Its fallback constant is declared after an unconditional return. | Round-18 reconciliation regression. Deterministic source trace. | **YES:** restore the module-scope fallback and cover cached/disconnected environments. | +| F03 | P1 | Full-thread diff fails after an ordinary second run: all root runs share one checkpoint scope, but the zero-baseline lookup requires that scope still be owned by run one. | Older V2 integration bug, present in the previous reviewed source. Real allocator/reducer probe plus diff-path trace. | **YES:** resolve the baseline through the actual shared scope; replace the impossible two-scope test fixture. | +| F04 | P1 | Forced project deletion over WebSocket deletes imported V2 threads, then legacy validation rejects deletion of the still-populated project. | Older mixed V1/V2 lifecycle integration bug. Source-confirmed partial commit. | **YES:** carry force through and coordinate validation/deletion across both representations before destructive work. | +| F05 | P1 | HTTP and live/offline CLI project removal bypass V2 thread cleanup. A V2-only populated project can be deleted without force; imported projects reject force. HTTP create also drops the missing-directory flag. | Older transport divergence from the shared project contract. | **YES:** route these transports through the same V2-aware lifecycle and preserve contract fields. | +| F06 | P1 | OpenCode Stop discards child-list, child-abort, and traversal-timeout failures, so descendants can continue after apparent success. | Incomplete round-18 port of main #9005. | **YES:** preserve main's cancellation/acknowledgment and error semantics with bounded descendant cleanup. | +| F07 | P1 | Releasing an OpenCode session connected to an external server only disconnects local SSE; root/child work can continue after T3 shutdown or runtime release. | Missing main #9005 teardown behavior in V2. | **YES:** perform bounded root/descendant abort before closing the event stream; log teardown failures. | +| F08 | P1 | Cursor title/branch/commit/PR generation runs a tool-capable agent in the real cwd with sandboxing and approval review disabled. A metadata request can modify files or run commands. | Older SDK migration lost main's Ask boundary; the SDK migration itself is intentional. Local installed SDK implementation confirms the policy. | **YES:** restore an enforced non-writing metadata path; merely enabling the workspace-write sandbox is not equivalent. | +| F09 | P1 | Web/desktop queued-message editing accepts generic files but omits them when saving. File-only edits can also be cleared when another client starts/cancels the queued run. | Branch-only editor violates the existing attachment invariant. | **YES:** include files in upload, emptiness, replacement, and draft-recovery paths. | +| F10 | P1 | Mobile filters all non-image message attachments out before its file/PDF/video renderers, so persisted attachments appear absent. | Round-11 reconciliation regression, older than the latest 21 commits. | **YES:** retain the complete attachment list in the feed. | +| F11 | P2 | Claude workspace-image `Read` calls appear as generic tool rows on web/desktop/mobile, losing main's image preview. | Missing main #9119 feature. Client fallbacks were checked and do not derive the image path. | **YES:** derive a validated preview path from retained Read input on both clients; a new contract variant is not required. | +| F12 | P2 | A transient automatic-title error is treated as successful completion after one call and clears the marker. Main retries twice before giving up. | Missing main #8087 retry behavior. | **YES:** restore bounded initial-title retries while preserving stale-request guards and final cleanup. | +| F13 | P2 | A failure that happened before a later snooze counts as an early wake, allowing automatic settlement before the requested wake time. | New V2 auto-settlement port omitted main's timestamp ordering rule. | **YES:** require failure evidence newer than the snooze, with before/after cases. | +| F14 | P2 — performance | Every nonempty checkpoint diff loads and decodes a full V2 transcript and potentially full fork ancestors. Main uses narrow checkpoint context. | Older missed main #8988/#8992 performance invariant. Source-confirmed read cardinality. | **YES:** query only the workspace/run/scope/checkpoint fields needed for the diff. | +| F15 | P2 — performance | Startup recovery sequentially loads full histories for every active and archived thread before command readiness, including terminal threads needing no recovery. | Older V2 scaling gap compared with main's shell/runtime-state recovery. Source-confirmed read cardinality. | **YES:** select recovery candidates and load only their required runtime state. | +| F16 | P1 — performance | HTTP snapshot failure or a warm reconnect exceeding 128 events / 1 MiB falls back to a full lifetime projection over WebSocket and clears progressive-history metadata. Healthy cold opens are bounded. | Missing main #8992/#9000 fallback-window invariant. Source-confirmed server-to-client path; no measured payload size. | **YES:** apply the existing bounded snapshot/SQL/budget path to socket fallbacks and preserve a usable history cursor. | +| F17 | P2 | Mobile's active V2 assistant row bypasses its specialized Markdown renderer, losing Codex file citations/template actions. On iOS it also skips environment-aware inline image/video rendering and falls back to raw URIs. | Missing main #8584 and #9023 behavior at one actual mobile caller. Web retains the intended paths. | **YES:** restore the assistant renderer, its scoped image callback, and the template action into the V2 composer. | + +Detailed evidence, line references, triggers, proposed validation, and limits: + +- [Persistence/runtime report](persistence.md): F01, F03–F05, F13–F15. +- [Client report](clients.md): F02, F09, F10, F17. +- [Provider report](providers.md): F06–F08, F11, F16. +- [Cross-cutting report](cross-cutting.md): F12; independent review of migration, project, checkpoint, packaging, auth, and costs. + +F04 and F05 can share a project-mutation implementation, but their transport and mixed-store failure cases need separate coverage. F06 and F07 share descendant traversal but have different failure contracts: explicit Stop should surface failure; release should be bounded and log failure. F03 must be correct before F14 optimizes its reads. No recommendation requires a particular large abstraction. + +## Intentional differences and product decisions + +These are separate from the 17 findings. Previously accepted architectural choices are not reopened as bugs merely because main differs. + +| ID | Decision | Current V2 behavior | Recommendation | +| --- | ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| D01 | Port continuation after a server update now? | Main #9167 resumes active threads across restart. V2 intentionally withholds `serverUpdateThreadContinuation`; round 20 explicitly defers a V2 equivalent because recovery terminalizes active runs. | **YES before claiming parity**, or explicitly keep deferred. This is documented omission, not an accidental rebase resolution. | +| D02 | Resolve inherited markdown links against the source thread? | Inspectors use the row's `sourceThreadId`; normal message/plan markdown uses the active fork. The difference matters once source and fork worktrees diverge. | **Decision needed:** YES selects source ownership; NO keeps current-fork resolution. Main has no equivalent inherited-row model to decide this automatically. | +| D03 | Keep the Cursor SDK boundary? | SDK auth, model discovery, approval/question capabilities, and native fork/rollback support differ from V1 ACP. | **Keep the previously accepted migration.** F08's background write permission loss is a separate defect. | +| D04 | Keep the documented legacy-import scope? | Messages and thread metadata are imported; rich old tool/run/checkpoint/approval/plan history and native provider continuity are not. First V2 continuation uses a fresh session and bounded imported context. | **Keep the previously accepted scope**, with the migration docs and product messaging. F01 is an upgrade failure, not part of this tradeoff. | +| D05 | Keep protocol V2 incompatibility? | Old clients/servers are rejected by protocol negotiation; the CORS protocol-header fix remains. | **Keep the compatibility gate.** Deploy matching client/server versions. | +| D06 | Keep bounded portable handoff summaries? | Ordinary portable handoffs collapse/truncate each summarized item at 240 characters; legacy-import context has a separate 32,000-character budget. | **Keep the previously accepted limit** unless fuller handoff fidelity is now required. | +| D07 | Keep compact mobile queue controls? | Mobile can reorder, promote, and cancel queued work, but does not mirror web's composer editor/thumbnails. Working/thinking presentation also differs by surface. | **Keep as a surface choice.** F10's hidden persisted attachments is independent. | + +## Checks that remain unproven + +| ID | Question | What this audit establishes | Proposed decision | +| --- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| V01 | Does V2 need main's active-tool WebSocket coalescer? | V1 #8368 coalesces stable tool updates; V2 detail streams deliver every stored event, and several adapters emit repeated full tool state. No comparable frame/byte measurement was taken. | **YES: measure a provider replay and set a frame/byte budget.** Do not copy main's claimed percentage to V2 or coalesce persisted events blindly. | +| V02 | Is execution-triggered per-cwd skill refresh needed outside web? | Web requests cwd catalogs; Claude independently scans at execution. No equivalent V2 launch/reuse refresh was found for Codex/OpenCode, but no current-client failure was established. | **YES: add a focused stale/new-cwd scenario for CLI/mobile execution** before treating this as a confirmed missing feature. | +| V03 | Do retained UI paths work in the real clients? | Source routing and focused logic tests cover much of the port. Sidebar hydration, file edits/rendering, visibility-lease intersection changes, and hosted project defaults lack the relevant integrated assertions. | Run targeted interaction tests with any fixes. A real web/mobile/desktop pass needs the separately required browser/simulator authorization. | + +The proposed claim that "both auto-settlement settings off means all minute Git/PR work is wasted" was rejected on review. Both main and V2 still settle a **closed** PR independently of those two settings. Returning early would remove intended behavior; this is not a confirmed bug or an approved optimization. + +## Coverage and validation + +The [feature map](FEATURE-MAP.md) organizes retained, changed, missing, and deliberately deferred behavior across providers, clients, persistence, remote connections, and tooling. The [main commit/file map](main-feature-file-map.tsv) lists all 165 incoming main commits and their file comparisons. Of those, 46 touch only files identical to current main; 119 touch at least one differing file. That is a triage aid, not 165 independently verified features or proof retained code is called. + +The [previous-fix range diff](prior-fixes-range-diff.txt) compares 41 old fix/review commits with 38 rebased equivalents. Dropped/changed client patches were reviewed against current implementations; disappearance of a patch does not by itself mean its behavior was lost. The provider, persistence, and client reports contain the invariant-by-invariant results. + +| Focused validation group | Result | +| ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| Root server/compatibility/title/CLI/usage/awareness/delegation/handoff/schedule | 17 file executions, 121 tests passed | +| Sol provider and work-log suites | 8 file executions, 177 tests passed | +| Sol client and latest-main follow-up suites | 16 file executions, 599 tests passed | +| Sol persistence/history/recovery/settlement/checkpoint suites | 16 file executions, 90 tests passed | +| Disposable upgrade probe | Real current SQL migrator reproduces the old-052 → current-053 failure in an in-memory database | +| Disposable checkpoint probe | Real allocator and projection reducer confirm one shared root scope, reassigned to run two | + +The retained [audit probes](persistence-runtime-probes.test.ts) pass 3/3: they expect/capture the current migration failure, verify checkpoint scope reuse, and verify closed-PR settlement with the optional settings off. Run `vp test run audits/orchestrator-v2/2026-09-02/persistence-runtime-probes.test.ts` from the repo root. The exact output is in `persistence-runtime-probes.log`. These probes are separate from the product-test counts above. + +Suite counts include overlap between reviewers and are not a count of unique tests. Green tests do not disprove the findings: the reports identify missing scenarios, and the checkpoint happy-path fixture models a scope layout production cannot produce. + +No repo-wide checks, dev servers, browsers, simulators, live providers, external OpenCode calls, or production-state writes were used. The source audit covers the changed subsystems and feature families; it is not an exhaustive execution of every path in 942 changed files. Performance severity remains qualitative without a workload benchmark. + +Use [DECISIONS.tsv](DECISIONS.tsv) to record yes/no/defer decisions. Full references and inventories are alongside this report in [references.json](references.json), [branch-commits.txt](branch-commits.txt), [new-branch-work.txt](new-branch-work.txt), [main-since-prior.txt](main-since-prior.txt), and [changed-files.tsv](changed-files.tsv). diff --git a/audits/orchestrator-v2/2026-09-02/DECISIONS.tsv b/audits/orchestrator-v2/2026-09-02/DECISIONS.tsv new file mode 100644 index 000000000000..0af6cae2a7fa --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/DECISIONS.tsv @@ -0,0 +1,28 @@ +id priority category decision_question recommendation decision evidence +F01 P1 new rebase upgrade defect Fix upgrades from old V2 migration histories, including the missed main044 repair? YES OPEN persistence.md — finding 1 +F02 P1 new rebase client defect Fix the sidebar fallback declaration so cached/disconnected environments do not crash? YES OPEN clients.md — sidebar finding +F03 P1 older V2 correctness defect Fix the shared checkpoint-scope baseline lookup after an ordinary second run? YES OPEN persistence.md — finding 5 +F04 P1 older mixed-store lifecycle defect Fix forced WS project deletion rejecting after imported V2 threads were deleted? YES OPEN persistence.md — finding 2 +F05 P1 older transport lifecycle defect Make HTTP/live CLI/offline CLI project mutations honor V2 threads, force and creation fields? YES OPEN persistence.md — finding 3 +F06 P1 partial main port Port OpenCode descendant cancellation and error/acknowledgment semantics? YES OPEN providers.md — OpenCode Stop +F07 P1 missing main lifecycle behavior Abort external OpenCode root and child work when releasing the runtime? YES OPEN providers.md — external OpenCode release +F08 P1 older SDK behavior regression Restore an enforced non-writing boundary for Cursor background metadata generation? YES OPEN providers.md — Cursor metadata +F09 P1 branch-only attachment defect Preserve generic files in queued-message save and cross-client edit recovery? YES OPEN clients.md — queue-edit finding +F10 P1 older rebase mobile defect Restore all persisted attachment types to the mobile feed? YES OPEN clients.md — attachment-filter finding +F11 P2 missing main feature Restore Claude workspace-image Read previews on both clients? YES OPEN providers.md — Claude image preview +F12 P2 missing main fix Restore bounded retries for transient initial-title failures? YES OPEN cross-cutting.md — automatic title retries +F13 P2 new V2 port edge case Require failure evidence newer than a snooze before auto-settlement treats it as a wake? YES OPEN persistence.md — finding 4 +F14 P2 confirmed query cost Use narrow V2 checkpoint queries instead of full transcript hydration for diffs? YES OPEN persistence.md — finding 6 +F15 P2 confirmed startup cost Restrict startup recovery to relevant runtime state instead of every full history? YES OPEN persistence.md — finding 7 +F16 P1 confirmed reconnect payload cost Keep WS fallback snapshots bounded on HTTP failure and large reconnect gaps? YES OPEN providers.md — WebSocket snapshot fallbacks +F17 P2 missing main mobile renderer Restore the mobile assistant Markdown adapter, citation/template actions and iOS scoped image/video renderer? YES OPEN clients.md — assistant renderer finding +D01 decision explicitly deferred main feature Port active-thread continuation across server updates now? YES for parity; otherwise explicitly defer OPEN AUDIT.md — D01; cross-cutting.md +D02 decision new V2 ownership semantics Should inherited message/plan links resolve against their source thread instead of the active fork? Product choice: YES=source; NO=current fork OPEN clients.md — inherited fork ownership +D03 decision previously accepted architecture Keep the Cursor SDK boundary and its documented capability differences? KEEP; fix F08 independently PREVIOUSLY ACCEPTED providers.md — intentional differences +D04 decision previously accepted architecture Keep legacy import limited to messages/metadata and a fresh provider session? KEEP documented scope PREVIOUSLY ACCEPTED docs/user/thread-migration.md; persistence.md +D05 decision previously accepted compatibility Keep protocol V2 rejection of incompatible old clients/servers? KEEP PREVIOUSLY ACCEPTED cross-cutting.md — compatibility +D06 decision previously accepted context tradeoff Keep 240-character portable item summaries and separate 32000-character legacy context budget? KEEP unless fuller fidelity is required PREVIOUSLY ACCEPTED cross-cutting.md — handoff limits +D07 decision established surface difference Keep compact mobile queue controls without duplicating web editing/thumbnails? KEEP; fix F10 independently OPEN clients.md — surface differences +V01 verification unmeasured stream cost Measure V2 tool-update frame/byte counts against main's coalescing invariant? YES: measure before prescribing the change OPEN providers.md — coalescing validation gap +V02 verification unproven skills parity Check cwd skill discovery after CLI/mobile execution or reuse outside web? YES: focused scenario OPEN providers.md — execution-triggered refresh +V03 verification interaction coverage Run focused real-client checks for fixes and retained visibility/hosted-settings paths? YES when authorized; no browser permission assumed OPEN clients.md — verification gaps diff --git a/audits/orchestrator-v2/2026-09-02/FEATURE-MAP.md b/audits/orchestrator-v2/2026-09-02/FEATURE-MAP.md new file mode 100644 index 000000000000..683a8c40b4ce --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/FEATURE-MAP.md @@ -0,0 +1,89 @@ +# Feature map for the 2026-09-02 audit + +Frozen comparison: branch `d2f1f511f4` against main `57a66608b9`. Finding and decision IDs refer to [AUDIT.md](AUDIT.md). **Retained** means the relevant source path was traced and no discrepancy was found in this audit; it is not a guarantee for every provider/client combination. Exact source references and test cases are in the linked domain reports. + +The complete mechanical inventories are [942 changed files](changed-files.tsv), [332 branch commits](branch-commits.txt), [165 main commits](main-since-prior.txt), and the [main commit/file comparison](main-feature-file-map.tsv). The last file distinguishes unchanged leaf implementations from files requiring V2 behavior review. Its `review-v2-path` label describes that triage category, not a test result. + +## Providers and registration + +| Feature family | Main behavior / V2 implementation | Audit result | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| Instance registration, capabilities, models | Shared provider registry/drivers feed V2 adapters; removed custom models disappear, Claude remote manifests and bounded OpenCode version checks are retained. | Retained on inspected paths. [Provider evidence](providers.md). | +| Cwd/project skills | Claude, Codex, and OpenCode expose cwd snapshots; web requests missing snapshots, Claude also reads skills at execution. | Main execution-time refresh outside web remains unverified for Codex/OpenCode: V02. | +| Codex prompt content and usage | Native image input plus generic attachment path text; live token usage and persisted terminal-omission behavior. | Prior fixes retained; focused shared/adapter/projection tests passed. | +| Codex feedback | Persistent feedback anchors, duplicate/in-flight guards, environment/thread ownership. | Prior fixes retained on web/mobile shared command paths. [Client evidence](clients.md). | +| Claude approvals | Session-only permission suggestions, abort already signaled, policy-specific tool access, questions handled in every runtime mode. | Prior fixes retained; focused adapter tests passed. | +| Claude questions | Structured/multiple questions, multi-select normalization, structured response contract. | Prior fixes retained. | +| Claude plans, todos, compaction, subagents | Stable planning item identities/lifecycle, resume and compaction controls, model propagation across native task ordering. | Prior fixes retained. | +| Claude workspace-image reads | Main classifies image Read input for inline preview. V2 preserves input but neither client derives a preview path. | Missing main behavior: F11. | +| OpenCode prompt admission | Native request/message correlation, generation-owned status reconciliation and retries, cancellation of pending initial/steer HTTP prompts. | Prior fixes retained; targeted tests passed. | +| OpenCode cancellation | Main aborts the descendant tree and reports relevant failures. V2's new descendant traversal discards failures. | Partial port: F06. | +| OpenCode external-server teardown | Main aborts root and descendants when releasing the session. V2 release closes its subscription only. | Missing lifecycle behavior: F07. | +| Cursor SDK boundary | Native SDK replaces ACP, with different auth/model/capability support. | Intentional D03. Background text-generation write boundary is separately broken: F08. | +| Grok and generic ACP | Flavored ACP model selection, health and interruption controls; generic adapter/runtime support remains. | No additional source-confirmed regression found in the provider review. | +| Source-control and title generation | Main PR-linked title context and shared prompt changes remain in use. Initial title transient-error retries are absent. | Retained prompts; F12 and Cursor-specific F08. | + +## Persistence, thread lifecycle, and orchestration + +| Feature family | Main behavior / V2 implementation | Audit result | +| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | +| Database upgrades | Numeric migration runner plus inserted main migration 044; previously applied V2 IDs were shifted. | Fresh-schema tests pass, old-V2 upgrade fails: F01. | +| Legacy import | Metadata, pins/order, snooze and PR links copied and repaired; legacy rows kept for compatibility. | Prior metadata/search fixes retained. Loss of rich legacy history/native continuity is documented D04. | +| Project removal | Main enforces nonempty/force checks and deletes its thread representation consistently. V2 has mixed-store and transport-specific paths. | F04 over WS; F05 over HTTP and live/offline CLI. | +| Thread archive/delete visibility | V2 lifecycle, archived shell separation, migrated ownership filters in legacy search. | Prior filtering and history visibility fixes retained. Project-level cleanup is the exception above. | +| Worktree recovery | Missing worktree is recreated before provider turn start. Shared Git paths preserve local-only base support. | Recovery fix retained; scoped existing tests passed. | +| Queue ordering/delivery | Durable queued runs, delegated-completion priority, promote/steer/cancel controls. | Queue-order and delegated-completion tests passed. File editing is a separate client defect F09. | +| Settlement, pinning, snoozing | V2 server sweep evaluates main's inactivity/PR rules with live/pending-work exclusions and snapshot guards. | Most rules retained; failure-before-snooze ordering missing: F13. Closed-PR settlement remains intentionally active with optional settings off. | +| Unsettled ordering | Stable reanchoring and shared max(created/updated/unsettled) sorting. | Prior server and client fixes retained. | +| Recovery/outbox/receipts | Durable event/projection/effect transactions, replayable vs process-bound effects, checkpoint wait recovery, typed command receipts. | Focused recovery, effect worker, finalization, and runtime tests passed. Startup's query scope is overbroad: F15. | +| Checkpoint capture | Shared deterministic scope and ordinal refs; replayable capture/finalization. | Capture invariants retained. The diff query assumes an incompatible scope layout: F03. | +| Checkpoint query cost | Main queries narrow checkpoint context; V2 loads full projection. | Confirmed data-loading regression: F14. | +| History pagination | V2 SQL filters the visible cohort before LIMIT, retains paired stop requests and nested fork identities, and pages to the actual end. | Earlier fixes retained; SQL/history tests passed. | +| HTTP detail and WS fallback payloads | V2 central row/byte/control-plane budgets, overflow reporting, bounded SQL window protect healthy HTTP cold opens. Socket fallbacks bypass them. | Earlier HTTP budgeting fixes retained, but failed HTTP loads and large reconnect gaps expose F16. | +| Portable provider handoffs | V2 supports context transfer and provider changes, using bounded portable summaries and a separate legacy-import budget. | Documented D06; focused context-handoff tests passed. Full provider-switch/fork permutations were not live-tested. | +| Delegated work | App-owned child tasks, durable completion transfer, parent wake/deduplication. | Selected completion-delivery tests passed; branch-added feature rather than a direct V1-equivalence claim. | +| Scheduled tasks | App-owned interval/fixed-time scheduling and legacy interval compatibility. | Existing schedule tests passed, including legacy sub-minute floor and missed-time grace. No wall-clock/live scheduler test was run. | +| Server update continuation | Main's active-thread restart continuation is gated off by the V2 server descriptor. | Explicitly deferred D01, distinct from recovery correctness. | + +## Web, desktop, mobile, and shared client state + +| Feature family | Main behavior / V2 implementation | Audit result | +| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Sidebar environment/provider fallback | Cached shells can precede provider config. Main has a module-scope empty map; V2 declaration sits after return. | Web/desktop crash: F02. | +| Sidebar status subscriptions | Visibility leases, overscan, active-row retention, short idle grace for VCS and linked PR state. | Source port retained; intersection-driven release lacks integrated coverage (V03). | +| Composer draft/worktree setup | Promotion retains text entered during setup and moves the draft to its canonical environment/thread scope. | Main #9197 retained; direct store tests passed. | +| New-thread model choices | Sticky user selections seed drafts; only explicit provider options persist. Hosted project defaults use the representative environment. | Main #9164/#9142 retained in source. Hosted picker/mutation interaction remains untested. | +| Context meter/settings | Opt-in default false, Settings control, composer gating. Shared server preference paths remain. | Main #9190 retained; contract tests passed. | +| Attachments in ordinary sends | Shared upload claims, generic-file prompt descriptions, native image inputs, ownership and caps. | Prior fixes retained. Queue edit and mobile display have F09/F10. | +| Queued-message editing | Web accepts generic files in ordinary composer edit mode but saves only new images. | F09. Compact mobile controls are D07, not the same bug. | +| Feed attachments | Main mobile keeps images and generic files; V2 filters to images before rendering. | F10 blocks visible file/PDF/video history despite retained renderer implementations. | +| Media/file viewer entry points | File/share acquisition, eager upload, navigation guards, offline voice, external file viewing, stale-save coordination, and panel refresh paths remain wired to V2. | Detailed caller coverage is in [clients.md](clients.md). End-to-end media remains partial: F10 hides attached files, and F17 bypasses iOS assistant inline media resolution. | +| Feedback placement | Timestamp-anchored rows and direct duplicate guards on both surfaces. | Prior fixes retained. | +| Plan mode | Disabled legacy plan mode forces effective default mode before persistence/dispatch. | Prior web fix retained; no contradictory mobile override found. | +| Markdown files/images | Workspace assets, Windows paths, editor/reveal/modifier routing and owning-environment selection. | Prior web direct-row fixes retained. iOS assistant inline media is broken by F17; inherited fork context remains D02. | +| PR links and actions | Environment-scoped resolution, link/unlink, external/open actions and current-row ownership. | Prior behavior retained in inspected paths. Shared PR panel/driver changes listed in the main file map remain outside V2 event translation. | +| Inline citations | Selected assistant text, active environment/thread ownership, V2 assistant wrapper, mobile readable fallback. | Main #9146 retained; citation/draft tests passed. | +| Codex file citations, artifact templates, iOS inline media | Web still uses the directive renderer and appends chosen template prompts. Mobile bypasses its assistant helper, including its native image callback. | F17 covers the single caller gap behind main #8584/#9023 losses. Android's custom image renderer remains wired. This is separate from selected-text inline citations above. | +| Activity groups and errors | Failed tools remain visible; web working/thinking rows and compact native groups use different presentations. | Relevant prior fixes retained. No real scrolling/timing/GPU measurement was performed. | +| Mobile header and scroll fixes | Native back/title state patch, width/header dependencies, post-animation bounds updates. | Prior patches/current source retained; no simulator pass. | +| Project picker | Contained combobox and popup overflow constraints. | Prior fix absorbed into current source and retained. | +| Desktop | Wraps the web client, while shell/IPC/packaging and update infrastructure remain separate. | Web defects apply to desktop too. Native quit/update/preview behavior was source/inventory checked, not exercised on a second installed app. | + +## Remote operation, costs, packaging, and compatibility + +| Feature family | Main behavior / V2 implementation | Audit result | +| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Protocol negotiation | V2 descriptor/socket gating and CORS allowance for the protocol header. | Previous fixes retained; WS/client compatibility tests passed. Intentional version break D05. | +| Remote cookie identity | Environment identity initializes auth dependencies; cookie isolation paths retained. | Main #8085 survives the cutover in inspected source. | +| Relay credential refresh | Refresh-before-expiry implementation unchanged from main. | Main #9178 retained at the shared layer; no actual expiry/relay run. | +| HTTP route limits | 512-character parameter limit remains wired to router serve. | Main #8898 retained. | +| RPC scopes and awareness | Renamed/new V2 RPCs explicitly classified; awareness uses current event tail rather than replaying all history. | No removed scope boundary found; shared awareness tests passed. | +| Attachment cleanup ordering | Main defers deletion until command commit. V2 transaction persists cleanup outbox before worker notification. | Invariant retained; attachment-store/claim tests passed. | +| Billing/token pricing | Cached Claude pricing, incremental transcript reader, scan-cache preservation unchanged from main; V2 usage projection retains omitted terminal values. | Main #8806/#9024/#8540 and previous V2 usage fixes retained; targeted tests passed. No confirmed token-price regression. | +| Active-stream network cost | Several adapters emit repeated full tool state; main's semantic coalescer is absent from V2 detail delivery. | V01: source exposure, no measured frame/byte regression. | +| Reconnect/fallback transfer cost | Main preserves a bounded fallback window; V2 sends a lifetime projection after HTTP failure or an over-budget resume. | Confirmed F16. Individual tool-value truncation does not bound collection cardinality. | +| Startup/diff database cost | Queries read more transcript state than the operations need. | Confirmed F14/F15; no invented benchmark percentages. | +| Server bundle/service launch | Both server and service-launcher entry points remain included in build configuration. | Previous packaging fix retained; no packaging/release build run. | +| Shared non-orchestration features | PR driver/cache changes, themes, editor leaf components, native build/quit/preview updates, Windows shell utilities, release/tooling changes. | Inventoried against main. Unchanged leaf files are distinguished in the commit/file map; this audit does not claim end-to-end OS/build coverage for them. | + +The remaining gaps are explicit in [AUDIT.md](AUDIT.md): provider/burst performance, cwd refresh outside web, and real-client interaction. The review does not treat lack of a test, a renamed V1 component, or a deliberate V2 representation change as proof of a regression. diff --git a/audits/orchestrator-v2/2026-09-02/branch-commits.txt b/audits/orchestrator-v2/2026-09-02/branch-commits.txt new file mode 100644 index 000000000000..46b9b99b10bc --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/branch-commits.txt @@ -0,0 +1,332 @@ +d2f1f511f4 fix: reconcile main's round-20 features after the rebase +0550e0a34d fix(web): realign the composer and timeline with main +e6da41e5c6 fix(web): right-align the stash shoulder tab again +f0174c4577 fix: reconcile main's round-19 features after the rebase +2191297898 feat(server): evaluate automatic thread settlement in the v2 orchestrator +7697286069 fix: reconcile main's round-18 features after the rebase +99e940dc2b feat(web): port working and thinking timeline rows to orchestration v2 +acdbe292f0 fix: reconcile main's round-17 features after the rebase +4b35166d02 fix(mobile): keep scroll bounds current after animations +fa54f54607 fix(chat): remove added tool summary status counts +b27f50b65a feat(mobile): port chat summaries and transitions to orchestration v2 +60bc3cff93 feat(web): summarize T3 orchestration actions +72e0c434be fix(web): keep composer shortcut tooltip stable on Mod +6bcc0e39da fix(web): match composer actions to draft and modifier state +6ce4cb0a15 fix(web): keep queued messages in place while editing +e16d934d8a fix(web): keep queued message editing inside the queue panel +b2afc4cb45 refactor(web): use shared banner rows for queued messages +85a3c12568 fix(web): keep stash separate from the composer activity column +e82c717855 fix(web): share the outline for joined composer tabs +b1533813ce fix(web): align queue headers and prevent stash overlap +ed6aafa93f fix(web): port composer activity and grouping to orchestration v2 +c1791ab263 fix(orchestration): select visible history before limiting SQL +47ae99f517 fix(server): recover OpenCode status reconciliation +0fc565db8a fix(orchestration): retain nested fork history when paging +07889933e3 fix(server): cancel pending OpenCode prompts safely +870014496f fix(orchestration): page history through its true end +051565fc96 fix(web): retain markdown workspace ownership +be7b07634b fix(clients): anchor feedback in conversation order +de79f44221 fix(server): correlate OpenCode prompt admission +dbb6021f84 fix(server): normalize Claude question answers +70f82caaa0 fix(server): preserve Claude planning lifecycle +26dfbc2984 fix(server): preserve provider usage in persisted turns +733db7269f fix(server): allow protocol negotiation in CORS +3d5bab73d8 fix(server): restore Claude resume compaction +0921786018 perf(orchestration): bound complete thread snapshots +9a4734af8e perf(orchestration): bound history reads in SQL +ff9f875f17 fix(server): project Claude plans and todos +ecf3dd2c9a fix(server): restore Claude structured questions +98670f337e fix(server): guard OpenCode prompt admission races +68104a497e chore(repo): remove tracked audit scratch files +19a30d03be docs: state portable handoff limits +3e1ff1531d docs: explain legacy thread migration +995f4e7e5a fix(protocol): reject incompatible orchestration peers +44f2004810 fix(web): scope markdown actions to their environment +5f19d550ae fix(web): restore markdown file chip actions +642056fdd9 fix(server): keep current provider context usage +7fca26e6fb fix(web): preserve Windows markdown paths +53c6857ec9 fix(web): load workspace markdown images through assets +8bbf7f50c8 fix(server): preserve generic provider attachments +e44588afa4 fix(clients): restore Codex feedback submission +dcff638944 fix(orchestration): recreate missing worktrees before turns +eacc09d40a fix(orchestration): honor migrated thread visibility in search +2cfe234e46 fix(server): preserve Claude subagent models +930dd22e72 fix(web): honor disabled legacy plan mode +82e1b8ed60 fix(orchestration): preserve legacy thread metadata +feedc3f6bb fix(server): include service launcher in bundle build +6b3690e063 fix(server): observe pre-aborted Claude approvals +7e71ff8a80 fix(orchestration): reanchor unsettled threads +34a4d026a5 fix(server): keep Claude session approvals ephemeral +b9400c36a3 fix(web): keep failed tool items in the collapsed group summaries +e0ab034b43 fix: reconcile main's round-16 features after the rebase +91572bcaf4 chore: refresh macroscope ui-consistency check +8e0d521beb chore: retrigger ci +bbbaeeb2a3 fix(server): inject HostProcessPlatform into the Grok plan extractor +6211ffaa69 fix(lint): allowlist the queue and relationships interop boundaries +79ab9ff211 fix(mobile): replace remaining dark: utilities with adaptive semantic tokens +d17919b845 fix(web): dedupe the composer glass styles and align the chat column width +aafe194a88 fix: reconcile main's round-14 features after the rebase +3fd374226d fix(web): drag-to-reorder queued messages and retire stale pending rows +a1d309ea77 feat(web): show attachments on queued messages and edit them in the composer +1c58988751 feat(server): claim uploaded attachments at v2 dispatch +bf963f1d4f fix(web): restore the full-screen file-drop target over the chat column +084d72779d fix: restore main's automatic thread settling after the revert +a2efa89c95 fix: reconcile main's round-12 features after the rebase +690ea07bac fix(opencode): route child-session approvals through the v2 adapter +0301dc423e fix: reconcile main's round-11 features after the rebase +c380aa6c87 fix(web): collapsed tool rows preview inputs for every tool type +1c3b15a835 fix(web): show the command on collapsed tool rows, not its stdout +72056ac893 fix(web): surface v2 todo-list plans as task progress +c0cbbbc844 fix(web): collapse settled tool runs behind main's summary toggles +a8df962501 fix(web): converge ChatComposer on main's drawer-era body +d81b12f2aa fix(web): adopt main's attached-composer surface contract so the glass survives shoulder tabs +0b8e40fbc5 fix(web): repaint the composer glass and strip the thread-panel popover chrome +8fdce45017 feat(grok): capture exit_plan_mode into the v2 proposed-plan card (#8358) +2c188dd57b fix(web): keep following the stream after returning to the live edge (#6519) +dfc21af186 feat(orchestration-v2): show live context usage in the meter (#8144) +47b1560306 fix(grok): fail hung prompts on xAI rate-limit completions (#8358, partial) +a854b2fcfd feat(analytics): credit v2 threads and turns to the starting client (#7774) +4eb1099038 feat(orchestration-v2): route Codex thread feedback uploads through v2 (#7949) +f894a3531f feat(orchestration-v2): carry approval options and app names to the client (#8058) +650a24252e feat(orchestration-v2): project linked pull requests on threads (#8160) +1533041bfd fix(web): stop mis-marking recovered and text-reported tool failures in the v2 work log +ab8569a7a3 fix: reconcile main's round-10 features after the rebase +5d1e08ef48 fix(orchestration): show provider retries in the work log +8bf0b5fcb3 refactor(web): finish aligning the branch with main's style simplification +f22abd94cd fix(web): restore the titlebar sizing and timeline fade lost to main's style simplification +2e42519705 feat(server): honor withheld agent browser access in the v2 runtime +796911d54d fix: reconcile main's round-9 features after the rebase +5c722de01c feat(mobile): surface prominent activity status and metadata +d734b66fff fix(server): reject replaying a command receipt across threads in v2 +ace57ebdfc fix: reconcile main's round-8 features after the rebase +e74f01c66a perf(server): keep shell snapshots bounded and active-only +a39f6a267d fix(web): size the titlebar layout-control icons like the sidebar trigger +7c8af3708e fix(web): align titlebar clusters to one shared pixel inset +3d812634cf fix(web): keep the titlebar layout controls fixed across right-panel toggles +b16ac84793 fix: reconcile main's round-6 features after the rebase +e861e74df5 feat(contracts): track thread title regeneration +862479b515 feat(orchestration): bound thread history and resume payloads +167f5f6068 fix(web): restore main's collapse chrome and tab-status keying on the PR panel +365ffce101 feat(web): prioritize pull request row actions +9e7a5b0566 fix(web): reconcile main's round-5 features after the rebase +6f39090bcb fix(mobile): port main's composer stabilization into the v2 thread screens +15d7ed4ddc feat(web): add pull request actions to thread details +e69b9944e5 fix(web): restore the branch's slim chat header +e3fb981cac test(server): expect attachment saved-at lines in ClaudeAdapterV2 turn text +75fdf57d99 test(web): restore main's right-panel migration expectations after the panel-visibility merge +1ffb1eaf78 fix(server): port round-3 main fixes into the v2 orchestrator +fbfa125f2d chore(server): renumber v2 migrations 038-046 to 041-049 after main's 038-040 +f2d1f16c3c fix: repair rerere-damaged files and reconcile main's round-3 features with v2 +fddf025c0b fix(web): show Git action success inline in panel +09c99a51a1 fix(web): let LegendList own end-follow and disclosure anchoring (#5449) +bed1245b22 fix(web): port the refined live-follow gesture gating to the v2 timeline +4e87742e9b chore(web): prune plan-sidebar leftovers after the inline-plans rework +e778ae6f30 fix: port main fixes stranded by the v2 rewrite (round 2) +bfb9d9465a fix(server): renumber v2 migrations after main's 037_ProjectionTurnsKeysetIndex +20cec19eb5 fix: repair conflict-marker artifacts from rebase auto-resolutions +ec7370e7e5 fix(web): align git action progress button layout +2b4e393ff5 feat(orchestrator): Surface waiting background work (#4378) +6a924e9d5f test(server): align migration expectations with renumbered ids +2e3b863826 fix: port main fixes stranded by the v2 rewrite +fa557cd774 fix(server): renumber v2 migrations after main's 036_ProjectionThreadsPinned +3699b557e9 fix(web): remove open PR actions from git controls +14ca09db7b fix(server): stop tying codex text-generation temp files to the caller's scope (#5406) +7f3ebe40d9 fix(orchestrator): Prevent redundant delegated completion turns (#5311) +1b91a552e0 fix(test): keep codex replay recovery off the repo checkout +4ffad32204 chore: resolve lint warnings across v2 code +39fab14dc4 test(server): cover v2 thread title regeneration +fa775c22ad fix(web): restore compact header sizing for project script controls +d4e31cb20f fix: send mcp-protocol-version header in worktree registration test +704808d923 fix: adopt effect beta.103 APIs in rebased v2 code +4e72ea725c feat(chat): refine V2 conversation UI (#5307) +d13cb6b8f5 fix(server): restore worktree branch naming in the v2 orchestrator (#5309) +78aea07a31 fix(orchestrator): Order thread lineage by creation time (#5310) +6a8fcc6576 fix(orchestration-v2): restore generated thread titles (#5176) +6a7824f352 fix: reconcile rebase with latest main +cb592a7a92 fix(web): keep Git progress title anchored +790fe93a99 fix(web): remove elevated thread details panel styling +3cd279a07a refactor(orchestration): split thread-not-sendable into typed errors +aadfcb978b fix(orchestration): promoted queued messages keep the queued_turn intent +e2284c99f1 fix(orchestration): thread visits no longer create activity loops (#5038) +888283cd7f feat(orchestration): port thread title regeneration to the v2 runtime +5e29230798 perf(web): keep timeline minimap animations off the main thread +c123bddb2b fix(relay): stop replaying the whole event store into the awareness relay +3dc8b570af fix(chat): prevent stale timeline scroll and rerenders +0ca2c503d9 perf(orchestration): per-thread shell deltas, visit throttling, event compaction (#4971) +0d57ac71ae [codex] feat(web): show git progress in the commit button (#4963) +7b28551f4b feat(orchestration): track provider retries and thread visits +0ee02d5490 feat(server): surface legacy thread migration progress +dd9b6b0d4b fix: close failed provider adapter scopes +6832caec1f fix: preserve thread management failure semantics +981b2ddc74 fix: address latest orchestration review findings +a2b1e1ef93 fix: preserve orchestration task identity +5de1955591 fix: address orchestration review findings +fa408d129f fix(mobile): label queued message intent +9aeb65f738 fix: address orchestration review findings +8af2b58d15 fix(orchestrator): preserve migrated and nested history +327189894e fix(server): preserve project mutation client errors +e59043aebb fix(orchestrator): validate rollback and search links +614c744be9 fix(orchestrator): close cancellation edge cases +af590d13ae fix(orchestrator): decode direct Claude result blocks +9c3a6b75e9 fix(orchestrator): validate replay edge cases +69299bf47b fix(orchestrator): preserve terminal effect outcomes +7b1e9dad86 fix(orchestrator): preserve retryable effect failures +c7a62d3c36 fix(orchestrator): avoid replaying settled effects +c17955171a fix(worktrees): make handoff rollback atomic +49ad52e66d fix(orchestrator): release stranded effect claims +0a9a06ba64 fix(orchestrator): execute resolved runtime responses +785e1388d0 fix(orchestrator): harden provider edge cases +ff10b65fe6 fix(orchestrator): handle fresh review edge cases +5a2a714d78 fix(orchestrator): address late review findings +80e5ef9865 fix(mobile): gate thread controls on live runs +6179f46681 fix(checkpoints): retain thread-start baseline after failed runs +c2145dde12 fix(client): preserve live thread relationships +153a1f8548 fix(web): enforce secure provider field defaults +afeb2089d2 fix(claude): preserve explicit model options +9f71aa9ca6 fix(server): isolate deterministic attachment ids +c6adb55a0a fix(testkit): harden provider replay recording +0d5dbddd16 fix(acp): enforce task and permission invariants +6c30ce289b fix(orchestration): preserve imported conversation state +09963b2172 fix(checkpoints): preserve valid run history +345a9a4a3a fix(acp): discover final teardown descendants +120242d9fb fix(cursor): log close attempts before execution +0db5a1d2e6 fix(mobile): distinguish queued and waiting archive states +1fdab432e8 fix(mobile): allow archiving post-provider work +0900ea01d9 fix(orchestration): cancel queued work on archive +7252e40574 fix(orchestration): handle checkpoint-wait runs +3edb72687d fix(acp): make xai cancellation reliable +8d27ca499e fix(contracts): reject invalid legacy intervals +51e044f7ad fix(orchestration): preserve legacy schedule compatibility +8006f38f2e fix(mobile): preserve active thread state +32d563e07c fix(orchestration): harden scheduled task startup +6c82f71da5 fix(orchestrator): schedule effects from durable deadlines (#4656) +3ba155db4f feat: migrate v1 state into orchestrator v2 (#4400) +d59b7c2ba3 chore(orchestrator): refresh checks after main sync +ef8219c2e3 fix(web): restore checked-in project scripts +4d9180dc78 fix: ignore subagents when sorting sidebar projects +1e42d8e909 fix: hide subagent threads from v2 lists +0e018044d7 fix(claude): Settle positive task-notification results +ba3c821004 fix(orchestrator): Wake settled parents when delegated children finish +9649b22600 fix(acp): Preserve wake evidence across an app-owned wake +da04feea48 fix(grok): Prevent spurious wake run after in-turn monitors +4a3797b482 test(orchestrator): align merged V2 compatibility checks +16b8599b26 fix(server): clean up Claude replay failures +45d60f9a51 fix(server): enforce ACP auth and preserve fork provenance +bafa7a432b fix(server): keep derived threads awake +0bc459bd0f fix(mobile): wait for fork shell before navigation +7ae175a5f3 Add worktree handoff and status tools to the t3-code MCP server (#3754) +83ea5f70c1 feat(subagents): disclose projected results consistently (#3866) +2a25e1d2de fix(orchestrator): hydrate shell cache and group multi-environment projects (#3640) +b2e4223af6 test(orchestrator): align Codex approval reviewer replays (#4457) +c93936748b fix(orchestrator): Preserve claude/codex post-interrupt recovery state (#4229) +2f50f6b93f test(orchestrator): Align post-merge CTM fixtures (#4193) +b07b35f8fc fix(web): contain thread details panel effects +7e3d211988 refactor(web): use shared glass surfaces +92bfc55bc3 fix(web): remove stacked composer shadows +39505241c8 fix(web): restore v2 composer chrome +092daf3c49 fix(server): preserve released migration ordering +8e173085a7 fix(orchestration): clarify agent delegation and scheduling +d8b06653df Unify T3 MCP tool presentation across clients +c026716d34 Render T3 MCP tools with branded timeline labels +643047ad47 fix(grok): align ACP extensions with open source runtime +1695b69e12 fix(mobile): support Hermes collection sorting +a210dc8c28 test(orchestrator): align integration fixtures +8e879081c3 fix(orchestrator): Harden Grok v2 runtime lifecycle +a307962b2b fix(orchestrator): dedupe Grok continuation dispatch +555b0469e9 fix(orchestrator): harden Grok v2 lifecycle (#3578) +9a065758da fix(acp): bind MCP credentials to activated threads +14f5595b68 fix(acp): release turns after interrupt timeout +f17413cc12 fix(claude): reopen queries after MCP credential rotation +cbcfea8b7d fix(claude): enforce read-only tool availability +bf9a8775d7 fix(claude): honor never-approval runtime policies +66f3b79c8e fix(claude): allow questions during plan mode +cec49e2ca0 fix(claude): preserve approvals with full-access sandbox +6f0e825e48 fix(claude): redact launch arguments from protocol logs +17d2f5d2d4 test(desktop): expect orchestrator v2 state directory +6e01338ad3 fix(ci): restore Claude permission request identity +4060032ea1 fix(orchestrator): align Claude permission replay with SDK +ec90f1ec95 feat(orchestrator): pass model options through MCP thread targets (#3872) +822242fc77 fix(orchestrator): scope Claude MCP tool pre-approval (#3862) +935aa5deb7 [orchestrator-v2] fix(orchestrator): Codex background command completion and subagent resume (#3908) +55fd431a06 [orchestrator-v2] fix(orchestrator): Restore Claude session continuity for resume, wake, and idle release (#3860) +698f41eb60 feat(orchestrator): Add shared provider continuation and background item plumbing +25df2c7c87 feat: scheduled tasks (automations) (#3638) +5dc316e8eb Fix Claude task turn mapping +f2711e089d Allow provider switching via handoff in chat threads +695c57b422 Remove early access badges from Cursor and Grok +6c78a01831 Switch Cursor provider to the official SDK +5f2045fcc3 fix(web): align thread details panel controls and menus (#3606) +f0bd8850aa Require Cursor API key for provider checks +036f3f9daf Keep persistent cards visible in folded turns +0eb1fc59ab Clarify thread relationship icons and ordering +4313ad89dd Map nested Codex subagent threads correctly +9f06992061 Adopt userdata-v2 and subagent activity mapping +db9310c2f6 Map Grok task envelopes to subagent lineage +4d8e17808b Add iOS associated domains for Clerk +2e05af6746 Retire V1 client orchestration parity +af6028c82d Expose V2 thread workflows on mobile +327f7287bb Enrich mobile V2 execution items +1a2b7432e9 Render mobile timelines from V2 turn items +6c6e346d38 Hide subagent threads and simplify thread controls +0531d50ed5 Split open-in editor controls into panel and toolbar variants +2aad9bc514 Reserve space for inline thread details panel +ecddebcc67 Map thread panel into title bar and sidebar +fcc2a2d096 Record created threads and subagent progress +ef051d86d8 Handle preparing turns across provider orchestration +c39d610069 Integrate orchestration V2 controls and process recovery +b1c074b2ec Complete orchestration V2 frontend cutover +c9dec10181 Split the V2 frontend plan into parity and enrichment phases +b56d0e7d53 Integrate orchestration v2 with the application runtime +f254d805e7 Guarantee MCP revocation during session release +708aed97c9 Remove MCP credential expiration +e9e19735a9 Require MCP registry for V2 provider sessions +3f52b6a9ec Complete orchestration V2 application services +900c8ec277 Start orchestration V2 application services +74115dcb01 Align orchestration V2 with Effect service conventions +65345a5bb4 Share Codex sessions across orchestration threads +fb1ebd0f2f Map orchestration turns to provider instances +a115e55b34 Add Orchestration V2 application integration plan +e35661a849 Add MCP thread management and Codex turn mapping +ad109c26f5 Add ACP replay harness and session lifecycle support +4ff48c0983 Handle segmented Cursor turns and stable visible timelines +8dcf191a94 Add Cursor SDK orchestration replay support +3056bfd7c0 Add orchestration MCP toolkit +6b81144d2c refactor(orchestration-v2): adopt host process spawn policy +d855d91f0a wip +7078dac915 feat(orchestration-v2): model native subagents +a4a63953ed Map orchestration v2 WS methods to auth scopes +73fe5fd878 fix(orchestration-v2): preserve source history on merged switch +98e98085af fix(orchestration-v2): compose provider switch merge context +08430b8115 feat(orchestration-v2): add merge-back replay coverage +2e38197d2b fix(orchestration-v2): resolve cross-provider forks +e2ba0751f7 feat(orchestration-v2): support cross-provider handoff +631219bca5 feat(orchestration-v2): wire claude adapter primitives +b76bbc23de Document Cursor SDK MCP projection for V2 +2182b71bfa Add turn-interrupt replay coverage and protocol logging +617f327995 Support active Claude steering and turn replay mapping +c1e8a12537 Map Claude turns to runtime query policies +41c5f212a7 Map Claude replay fixtures to multi-turn turns +d4cd542799 Add model selection to orchestration runs +166fd1c53c Extract Claude SDK query runner from provider adapter +b460c06441 Add Claude replay fixture recorder +052c24ec16 Add V2 command capability policy +be1d5acc70 Add merge-back context handoff support +76dc095de6 Add orchestration V2 backend checklist +ca9ba20375 Add thread fork lineage and lazy context transfer +5e551ef722 Implement orchestration v2 runtime +75120285ae Map Codex turns into orchestration v2 +eb8af12dca Add orchestration v2 replay and service contracts +783f4f6e8d Add orchestration v2 docs and probe fixtures +fa13e794bb Address Codex review feedback +74942087a3 Switch Codex provider checks to app-server probe +3182df2608 Flush native logs on adapter shutdown +3bded8ba56 decoders +99e5494242 Scope Codex session runtime lifetimes +a527023141 Normalize Codex IDs and preserve streamed stdout decoding +4c8648f791 Return Cursor ACP runtime with explicit scope +ba5d340a04 Delay Codex provider availability until checked +d914dc0329 resynclock +4da42ca393 revert more +77a63c13b8 nit +e911c41199 Integrate Codex app-server support +15dff31236 chore(ov2): preserve the integration base for replay diff --git a/audits/orchestrator-v2/2026-09-02/changed-files.tsv b/audits/orchestrator-v2/2026-09-02/changed-files.tsv new file mode 100644 index 000000000000..5074bc5295d1 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/changed-files.tsv @@ -0,0 +1,942 @@ +0 429 .github/scripts/thread-transfer-report.cjs +0 292 .github/scripts/thread-transfer-report.test.cjs +10 0 .github/workflows/ci.yml +0 75 .github/workflows/thread-transfer-report.yml +1 0 README.md +2 0 apps/desktop/src/app/DesktopEnvironment.test.ts +1 1 apps/desktop/src/backend/tailscaleEndpointProvider.ts +1 0 apps/desktop/src/settings/DesktopClientSettings.test.ts +1 1 apps/marketing/src/pages/index.astro +84 0 apps/mobile/generated-uniwind-themes.css +16 0 apps/mobile/scripts/generate-uniwind-themes.mts +2 7 apps/mobile/src/components/BrandMark.tsx +10 0 apps/mobile/src/components/brandAssets.ts +166 4 apps/mobile/src/connection/environment-cache-store.test.ts +17 32 apps/mobile/src/connection/environment-cache-store.ts +9 2 apps/mobile/src/connection/runtime.ts +1 0 apps/mobile/src/connection/storage.ts +15 25 apps/mobile/src/features/archive/archivedThreadList.test.ts +3 3 apps/mobile/src/features/home/HomeScreen.tsx +28 14 apps/mobile/src/features/home/homeListItems.test.ts +3 6 apps/mobile/src/features/home/homeThreadList.test.ts +40 0 apps/mobile/src/features/home/threadArchive.test.ts +16 0 apps/mobile/src/features/home/threadArchive.ts +3 5 apps/mobile/src/features/home/useThreadListActions.ts +4 1 apps/mobile/src/features/keyboard/hardwareKeyboardCommands.ts +0 1 apps/mobile/src/features/projects/AddProjectScreen.tsx +7 11 apps/mobile/src/features/review/reviewModel.test.ts +11 10 apps/mobile/src/features/review/reviewModel.ts +13 6 apps/mobile/src/features/review/useReviewSections.ts +6 4 apps/mobile/src/features/terminal/ThreadTerminalRouteScreen.tsx +6 2 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx +11 3 apps/mobile/src/features/threads/PendingApprovalCard.tsx +20 6 apps/mobile/src/features/threads/PendingUserInputCard.tsx +203 0 apps/mobile/src/features/threads/ThreadActivityInspector.tsx +5 6 apps/mobile/src/features/threads/ThreadComposer.tsx +86 81 apps/mobile/src/features/threads/ThreadDetailScreen.tsx +358 202 apps/mobile/src/features/threads/ThreadFeed.tsx +1 1 apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx +150 0 apps/mobile/src/features/threads/ThreadQueueControl.tsx +307 0 apps/mobile/src/features/threads/ThreadRelationshipsBanner.tsx +32 29 apps/mobile/src/features/threads/ThreadRouteScreen.tsx +42 0 apps/mobile/src/features/threads/thread-activity-row-presentation.test.ts +40 0 apps/mobile/src/features/threads/thread-activity-row-presentation.ts +14 0 apps/mobile/src/features/threads/thread-feed-item-size.test.ts +21 0 apps/mobile/src/features/threads/thread-feed-item-size.ts +11 4 apps/mobile/src/features/threads/thread-list-v2-items.tsx +26 0 apps/mobile/src/features/threads/threadActivityFileNavigation.test.ts +22 0 apps/mobile/src/features/threads/threadActivityFileNavigation.ts +38 0 apps/mobile/src/features/threads/threadForkNavigation.test.ts +26 0 apps/mobile/src/features/threads/threadForkNavigation.ts +93 46 apps/mobile/src/features/threads/threadListV2.test.ts +37 8 apps/mobile/src/features/threads/threadListV2.ts +14 14 apps/mobile/src/features/threads/threadPresentation.ts +69 0 apps/mobile/src/features/threads/threadQueueControlPresentation.test.ts +52 0 apps/mobile/src/features/threads/threadQueueControlPresentation.ts +34 0 apps/mobile/src/features/threads/userMessageIntentBadge.test.ts +35 0 apps/mobile/src/features/threads/userMessageIntentBadge.ts +51 0 apps/mobile/src/lib/modelOptions.ts +1 1 apps/mobile/src/lib/projectThreadStartTurn.test.ts +13 11 apps/mobile/src/lib/projectThreadStartTurn.ts +2 2 apps/mobile/src/lib/scopedEntities.ts +664 1816 apps/mobile/src/lib/threadActivity.test.ts +663 1381 apps/mobile/src/lib/threadActivity.ts +257 0 apps/mobile/src/lib/threadActivityInspector.test.ts +308 0 apps/mobile/src/lib/threadActivityInspector.ts +1 28 apps/mobile/src/state/queries.ts +2 1 apps/mobile/src/state/threads.ts +2 2 apps/mobile/src/state/use-pending-new-tasks.ts +33 31 apps/mobile/src/state/use-selected-thread-requests.ts +5 4 apps/mobile/src/state/use-selected-thread-worktree.ts +92 64 apps/mobile/src/state/use-thread-composer-state.ts +50 5 apps/mobile/src/state/use-thread-detail.ts +13 6 apps/mobile/src/state/use-thread-outbox-drain.ts +47 16 apps/mobile/src/state/use-thread-selection.ts +56 0 apps/mobile/src/state/v2-item-support.ts +72 0 apps/mobile/src/test-fixtures.ts +3 0 apps/server/README.md +0 235 apps/server/integration/NetworkTransferMeasurement.integration.ts +0 592 apps/server/integration/OrchestrationEngineHarness.integration.ts +0 568 apps/server/integration/TestProviderAdapter.integration.ts +0 294 apps/server/integration/TransferBudgetReport.integration.ts +0 212 apps/server/integration/TransferBudgetScenario.integration.ts +0 162 apps/server/integration/fixtures/providerRuntime.ts +0 372 apps/server/integration/fixtures/transferBudget.ts +0 1441 apps/server/integration/orchestrationEngine.integration.test.ts +0 359 apps/server/integration/orphanedProviderSessionStartup.integration.test.ts +0 386 apps/server/integration/providerService.integration.test.ts +7 1 apps/server/package.json +536 43 apps/server/scripts/acp-mock-agent.ts +78 0 apps/server/scripts/acp-replay-agent.test.ts +285 0 apps/server/scripts/acp-replay-agent.ts +37 0 apps/server/scripts/acp-thread-spawn-helper.c +12 0 apps/server/scripts/acpMockCancellationState.test.ts +3 0 apps/server/scripts/acpMockCancellationState.ts +43 0 apps/server/scripts/claudeReplayRecordingConfig.test.ts +32 0 apps/server/scripts/claudeReplayRecordingConfig.ts +35 0 apps/server/scripts/codexReplayRecordingRecords.test.ts +9 0 apps/server/scripts/codexReplayRecordingRecords.ts +44 0 apps/server/scripts/cursorReplayRecordingWorkspace.test.ts +29 0 apps/server/scripts/cursorReplayRecordingWorkspace.ts +358 0 apps/server/scripts/probe-claude-fork-local-rollback-replay.ts +444 0 apps/server/scripts/record-claude-agent-sdk-replay-fixture.ts +1310 0 apps/server/scripts/record-codex-app-server-replay-fixture.ts +222 0 apps/server/scripts/record-cursor-agent-sdk-replay-fixture.ts +26 0 apps/server/scripts/replayRecorderDeferredRegistry.test.ts +43 0 apps/server/scripts/replayRecorderDeferredRegistry.ts +22 0 apps/server/src/attachmentStore.test.ts +14 0 apps/server/src/attachmentStore.ts +20 9 apps/server/src/auth/RpcAuthorization.ts +0 635 apps/server/src/bin.test.ts +169 413 apps/server/src/checkpointing/CheckpointDiffQuery.test.ts +66 100 apps/server/src/checkpointing/CheckpointDiffQuery.ts +57 0 apps/server/src/claudeModelOptions.test.ts +59 0 apps/server/src/claudeModelOptions.ts +99 2 apps/server/src/cli/project.test.ts +63 32 apps/server/src/cli/project.ts +3 1 apps/server/src/environment/ServerEnvironment.test.ts +8 4 apps/server/src/environment/ServerEnvironment.ts +12 0 apps/server/src/git/GitWorkflowService.ts +52 1 apps/server/src/http.test.ts +3 0 apps/server/src/httpCors.ts +21 1 apps/server/src/mcp/McpHttpServer.ts +3 2 apps/server/src/mcp/McpInvocationContext.ts +7 0 apps/server/src/mcp/McpProviderSession.ts +1 0 apps/server/src/mcp/McpSessionRegistry.test.ts +28 0 apps/server/src/mcp/McpSessionRegistry.testkit.ts +15 1 apps/server/src/mcp/McpSessionRegistry.ts +307 0 apps/server/src/mcp/OrchestratorMcpService.activity.test.ts +292 0 apps/server/src/mcp/OrchestratorMcpService.test.ts +1681 0 apps/server/src/mcp/OrchestratorMcpService.ts +2620 0 apps/server/src/mcp/OrchestratorMcpToolkit.integration.test.ts +1062 0 apps/server/src/mcp/WorktreeMcpService.test.ts +494 0 apps/server/src/mcp/WorktreeMcpService.ts +114 0 apps/server/src/mcp/toolkits/orchestrator/handlers.ts +28 0 apps/server/src/mcp/toolkits/orchestrator/tools.test.ts +248 0 apps/server/src/mcp/toolkits/orchestrator/tools.ts +22 0 apps/server/src/mcp/toolkits/worktree/handlers.ts +137 0 apps/server/src/mcp/toolkits/worktree/registration.test.ts +47 0 apps/server/src/mcp/toolkits/worktree/tools.ts +12 0 apps/server/src/observability/Metrics.ts +209 0 apps/server/src/orchestration-v2/AcpRegistryOrchestratorV2.live.test.ts +12118 0 apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts +195 0 apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.testkit.ts +6170 0 apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.ts +159 0 apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts +92 0 apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts +184 0 apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts +5619 0 apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts +770 0 apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.testkit.test.ts +2555 0 apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.testkit.ts +5780 0 apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts +3644 0 apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.test.ts +237 0 apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.testkit.ts +5261 0 apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.ts +196 0 apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.test.ts +102 0 apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.testkit.test.ts +1013 0 apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.testkit.ts +2538 0 apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.ts +215 0 apps/server/src/orchestration-v2/Adapters/CursorAgentSdk.test.ts +525 0 apps/server/src/orchestration-v2/Adapters/CursorAgentSdk.ts +379 0 apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts +82 0 apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.testkit.ts +375 0 apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.ts +1173 0 apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.test.ts +39 0 apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.testkit.test.ts +416 0 apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.testkit.ts +3335 0 apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.ts +184 0 apps/server/src/orchestration-v2/AttachmentClaims.test.ts +126 0 apps/server/src/orchestration-v2/AttachmentClaims.ts +41 0 apps/server/src/orchestration-v2/AttachmentPrompt.test.ts +26 0 apps/server/src/orchestration-v2/AttachmentPrompt.ts +327 0 apps/server/src/orchestration-v2/CheckpointCaptureService.test.ts +273 0 apps/server/src/orchestration-v2/CheckpointCaptureService.ts +84 0 apps/server/src/orchestration-v2/CheckpointPolicy.ts +331 0 apps/server/src/orchestration-v2/CheckpointRollbackService.test.ts +288 0 apps/server/src/orchestration-v2/CheckpointRollbackService.ts +72 0 apps/server/src/orchestration-v2/CheckpointService.test.ts +564 0 apps/server/src/orchestration-v2/CheckpointService.ts +310 0 apps/server/src/orchestration-v2/CommandPolicy.test.ts +428 0 apps/server/src/orchestration-v2/CommandPolicy.ts +167 0 apps/server/src/orchestration-v2/CommandReceiptStore.ts +164 0 apps/server/src/orchestration-v2/ContextHandoffService.test.ts +459 0 apps/server/src/orchestration-v2/ContextHandoffService.ts +279 0 apps/server/src/orchestration-v2/CursorOrchestratorV2.live.test.ts +549 0 apps/server/src/orchestration-v2/DelegatedCompletionDelivery.test.ts +612 0 apps/server/src/orchestration-v2/EffectOutbox.ts +789 0 apps/server/src/orchestration-v2/EffectWorker.test.ts +671 0 apps/server/src/orchestration-v2/EffectWorker.ts +662 0 apps/server/src/orchestration-v2/EventSink.ts +139 0 apps/server/src/orchestration-v2/EventStore.ts +2100 0 apps/server/src/orchestration-v2/FoundationPersistence.test.ts +199 0 apps/server/src/orchestration-v2/GrokOrchestratorV2.live.test.ts +407 0 apps/server/src/orchestration-v2/IdAllocator.ts +67 0 apps/server/src/orchestration-v2/KeyedSerialExecutor.test.ts +55 0 apps/server/src/orchestration-v2/KeyedSerialExecutor.ts +344 0 apps/server/src/orchestration-v2/LegacyV1ThreadImporter.test.ts +739 0 apps/server/src/orchestration-v2/LegacyV1ThreadImporter.ts +100 0 apps/server/src/orchestration-v2/Orchestrator.migration.test.ts +7349 0 apps/server/src/orchestration-v2/Orchestrator.ts +391 0 apps/server/src/orchestration-v2/ProjectionMaintenance.ts +2785 0 apps/server/src/orchestration-v2/ProjectionStore.test.ts +3303 0 apps/server/src/orchestration-v2/ProjectionStore.ts +554 0 apps/server/src/orchestration-v2/ProviderAdapter.ts +44 0 apps/server/src/orchestration-v2/ProviderAdapterDriver.ts +211 0 apps/server/src/orchestration-v2/ProviderAdapterRegistry.test.ts +319 0 apps/server/src/orchestration-v2/ProviderAdapterRegistry.ts +74 0 apps/server/src/orchestration-v2/ProviderContinuationRequests.ts +735 0 apps/server/src/orchestration-v2/ProviderContinuationService.test.ts +208 0 apps/server/src/orchestration-v2/ProviderContinuationService.ts +654 0 apps/server/src/orchestration-v2/ProviderEventIngestor.test.ts +327 0 apps/server/src/orchestration-v2/ProviderEventIngestor.ts +124 0 apps/server/src/orchestration-v2/ProviderFailure.test.ts +202 0 apps/server/src/orchestration-v2/ProviderFailure.ts +84 0 apps/server/src/orchestration-v2/ProviderRuntimeRecoveryService.regression.test.ts +948 0 apps/server/src/orchestration-v2/ProviderRuntimeRecoveryService.test.ts +532 0 apps/server/src/orchestration-v2/ProviderRuntimeRecoveryService.ts +55 0 apps/server/src/orchestration-v2/ProviderSelectionTransition.test.ts +37 0 apps/server/src/orchestration-v2/ProviderSelectionTransition.ts +2347 0 apps/server/src/orchestration-v2/ProviderSessionManager.test.ts +1685 0 apps/server/src/orchestration-v2/ProviderSessionManager.ts +176 0 apps/server/src/orchestration-v2/ProviderSessionTransitionPolicy.test.ts +96 0 apps/server/src/orchestration-v2/ProviderSessionTransitionPolicy.ts +128 0 apps/server/src/orchestration-v2/ProviderSwitchService.test.ts +189 0 apps/server/src/orchestration-v2/ProviderSwitchService.ts +287 0 apps/server/src/orchestration-v2/ProviderTurnControlService.test.ts +296 0 apps/server/src/orchestration-v2/ProviderTurnControlService.ts +129 0 apps/server/src/orchestration-v2/ProviderTurnStartService.test.ts +16 0 apps/server/src/orchestration-v2/ProviderTurnStartService.testkit.ts +561 0 apps/server/src/orchestration-v2/ProviderTurnStartService.ts +43 0 apps/server/src/orchestration-v2/ProviderTurnTokenUsage.test.ts +51 0 apps/server/src/orchestration-v2/QueuedRunOrder.test.ts +32 0 apps/server/src/orchestration-v2/QueuedRunOrder.ts +13 0 apps/server/src/orchestration-v2/RandomUuid.ts +71 0 apps/server/src/orchestration-v2/ResourceCleanupService.ts +3263 0 apps/server/src/orchestration-v2/RunExecutionService.test.ts +1364 0 apps/server/src/orchestration-v2/RunExecutionService.ts +41 0 apps/server/src/orchestration-v2/RunFinalizationService.test.ts +97 0 apps/server/src/orchestration-v2/RunFinalizationService.ts +103 0 apps/server/src/orchestration-v2/RuntimePolicy.test.ts +146 0 apps/server/src/orchestration-v2/RuntimePolicy.ts +298 0 apps/server/src/orchestration-v2/RuntimeRequestService.test.ts +141 0 apps/server/src/orchestration-v2/RuntimeRequestService.ts +644 0 apps/server/src/orchestration-v2/SelectionRestart.integration.test.ts +382 0 apps/server/src/orchestration-v2/ShellStream.test.ts +191 0 apps/server/src/orchestration-v2/ShellStream.ts +102 0 apps/server/src/orchestration-v2/SubagentProjection.test.ts +191 0 apps/server/src/orchestration-v2/SubagentProjection.ts +168 0 apps/server/src/orchestration-v2/TODO.md +148 0 apps/server/src/orchestration-v2/ThreadForkService.test.ts +116 0 apps/server/src/orchestration-v2/ThreadForkService.ts +1098 0 apps/server/src/orchestration-v2/ThreadLaunchService.test.ts +589 0 apps/server/src/orchestration-v2/ThreadLaunchService.ts +60 0 apps/server/src/orchestration-v2/ThreadLifecycleService.test.ts +142 0 apps/server/src/orchestration-v2/ThreadLifecycleService.ts +320 0 apps/server/src/orchestration-v2/ThreadManagementService.test.ts +692 0 apps/server/src/orchestration-v2/ThreadManagementService.ts +213 0 apps/server/src/orchestration-v2/ThreadSettlementService.test.ts +319 0 apps/server/src/orchestration-v2/ThreadSettlementService.ts +75 0 apps/server/src/orchestration-v2/ThreadStream.test.ts +51 0 apps/server/src/orchestration-v2/ThreadStream.ts +433 0 apps/server/src/orchestration-v2/ThreadTitleRegenerationService.test.ts +259 0 apps/server/src/orchestration-v2/ThreadTitleRegenerationService.ts +107 0 apps/server/src/orchestration-v2/TurnItemPositionStore.ts +35 0 apps/server/src/orchestration-v2/UserFacingErrors.test.ts +62 0 apps/server/src/orchestration-v2/UserFacingErrors.ts +38 0 apps/server/src/orchestration-v2/V1ImportBoundary.test.ts +113 0 apps/server/src/orchestration-v2/WireProjection.test.ts +108 0 apps/server/src/orchestration-v2/WireProjection.ts +23 0 apps/server/src/orchestration-v2/applicationLayer.ts +47 0 apps/server/src/orchestration-v2/builtInProviderAdapterDrivers.ts +258 0 apps/server/src/orchestration-v2/http.ts +1574 0 apps/server/src/orchestration-v2/runtimeLayer.test.ts +264 0 apps/server/src/orchestration-v2/runtimeLayer.ts +399 0 apps/server/src/orchestration-v2/testkit/ClaudeReplayFixtures.integration.test.ts +735 0 apps/server/src/orchestration-v2/testkit/CodexReplayFixtures.integration.test.ts +13 0 apps/server/src/orchestration-v2/testkit/DeterministicRuntime.ts +417 0 apps/server/src/orchestration-v2/testkit/OrchestratorReplayFixtures.contract.test.ts +242 0 apps/server/src/orchestration-v2/testkit/OrchestratorReplayFixtures.integration.test.ts +292 0 apps/server/src/orchestration-v2/testkit/OrchestratorReplayRecovery.integration.test.ts +600 0 apps/server/src/orchestration-v2/testkit/OrchestratorScenario.ts +17 0 apps/server/src/orchestration-v2/testkit/ProviderReplayGate.testkit.test.ts +78 0 apps/server/src/orchestration-v2/testkit/ProviderReplayGate.testkit.ts +413 0 apps/server/src/orchestration-v2/testkit/ProviderReplayHarness.ts +1251 0 apps/server/src/orchestration-v2/testkit/ProviderSwitch.integration.test.ts +74 0 apps/server/src/orchestration-v2/testkit/ReplayFixtureWorkspace.ts +98 0 apps/server/src/orchestration-v2/testkit/ReplayTranscriptNdjson.test.ts +162 0 apps/server/src/orchestration-v2/testkit/ReplayTranscriptNdjson.ts +1774 0 apps/server/src/orchestration-v2/testkit/ThreadFork.integration.test.ts +668 0 apps/server/src/orchestration-v2/testkit/ThreadMergeBack.integration.test.ts +11 0 apps/server/src/orchestration-v2/testkit/fixtures/acp_elicitation/grok_transcript.ndjson +13 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_background_task_after_root/claude_transcript.ndjson +26 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_background_task_after_root/input.ts +96 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_background_task_after_root/output.ts +19 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_idle_resume/claude_transcript.ndjson +25 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_idle_resume/input.ts +39 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_idle_resume/output.ts +12 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_local_bash_task/claude_transcript.ndjson +7 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_local_bash_task/input.ts +58 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_local_bash_task/output.ts +10 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_result_is_error/claude_transcript.ndjson +22 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_result_is_error/input.ts +71 0 apps/server/src/orchestration-v2/testkit/fixtures/claude_result_is_error/output.ts +17 0 apps/server/src/orchestration-v2/testkit/fixtures/grok_subagent_lineage/grok_transcript.ndjson +9 0 apps/server/src/orchestration-v2/testkit/fixtures/grok_subagent_lineage/input.ts +95 0 apps/server/src/orchestration-v2/testkit/fixtures/grok_subagent_lineage/output.ts +807 0 apps/server/src/orchestration-v2/testkit/fixtures/index.ts +43 0 apps/server/src/orchestration-v2/testkit/fixtures/message_steering/claude_output.ts +13 0 apps/server/src/orchestration-v2/testkit/fixtures/message_steering/claude_transcript.ndjson +43 0 apps/server/src/orchestration-v2/testkit/fixtures/message_steering/codex_output.ts +51 0 apps/server/src/orchestration-v2/testkit/fixtures/message_steering/codex_transcript.ndjson +56 0 apps/server/src/orchestration-v2/testkit/fixtures/message_steering/cursor_output.ts +21 0 apps/server/src/orchestration-v2/testkit/fixtures/message_steering/cursor_transcript.ndjson +55 0 apps/server/src/orchestration-v2/testkit/fixtures/message_steering/grok_output.ts +14 0 apps/server/src/orchestration-v2/testkit/fixtures/message_steering/grok_transcript.ndjson +31 0 apps/server/src/orchestration-v2/testkit/fixtures/message_steering/input.ts +53 0 apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/claude_output.ts +14 0 apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/claude_transcript.ndjson +40 0 apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/codex_output.ts +52 0 apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/codex_transcript.ndjson +30 0 apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/cursor_transcript.ndjson +12 0 apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/grok_transcript.ndjson +14 0 apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/input.ts +19 0 apps/server/src/orchestration-v2/testkit/fixtures/multi_turn_restart/claude_transcript.ndjson +10 0 apps/server/src/orchestration-v2/testkit/fixtures/opencode_child_approval/input.ts +36 0 apps/server/src/orchestration-v2/testkit/fixtures/opencode_child_approval/opencode_transcript.ndjson +43 0 apps/server/src/orchestration-v2/testkit/fixtures/opencode_child_approval/output.ts +7 0 apps/server/src/orchestration-v2/testkit/fixtures/opencode_subagent/input.ts +30 0 apps/server/src/orchestration-v2/testkit/fixtures/opencode_subagent/opencode_transcript.ndjson +71 0 apps/server/src/orchestration-v2/testkit/fixtures/opencode_subagent/output.ts +50 0 apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/codex_output.ts +67 0 apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/codex_transcript.ndjson +11 0 apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/grok_transcript.ndjson +17 0 apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/input.ts +26 0 apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/opencode_output.ts +23 0 apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/opencode_transcript.ndjson +38 0 apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/codex_output.ts +619 0 apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/codex_transcript.ndjson +39 0 apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/cursor_output.ts +132 0 apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/cursor_transcript.ndjson +8 0 apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/input.ts +78 0 apps/server/src/orchestration-v2/testkit/fixtures/provider_thread_resume/codex_transcript.ndjson +60 0 apps/server/src/orchestration-v2/testkit/fixtures/provider_thread_resume/cursor_transcript.ndjson +42 0 apps/server/src/orchestration-v2/testkit/fixtures/queued_cancelled_while_active/codex_output.ts +25 0 apps/server/src/orchestration-v2/testkit/fixtures/queued_cancelled_while_active/input.ts +14 0 apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/claude_transcript.ndjson +49 0 apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/codex_output.ts +52 0 apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/codex_transcript.ndjson +30 0 apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/cursor_transcript.ndjson +12 0 apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/grok_transcript.ndjson +14 0 apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/input.ts +1184 0 apps/server/src/orchestration-v2/testkit/fixtures/shared.ts +33 0 apps/server/src/orchestration-v2/testkit/fixtures/simple/claude_output.ts +10 0 apps/server/src/orchestration-v2/testkit/fixtures/simple/claude_transcript.ndjson +33 0 apps/server/src/orchestration-v2/testkit/fixtures/simple/codex_output.ts +31 0 apps/server/src/orchestration-v2/testkit/fixtures/simple/codex_transcript.ndjson +11 0 apps/server/src/orchestration-v2/testkit/fixtures/simple/cursor_transcript.ndjson +12 0 apps/server/src/orchestration-v2/testkit/fixtures/simple/grok_transcript.ndjson +7 0 apps/server/src/orchestration-v2/testkit/fixtures/simple/input.ts +19 0 apps/server/src/orchestration-v2/testkit/fixtures/simple/opencode_transcript.ndjson +135 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent/claude_output.ts +29 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent/claude_transcript.ndjson +121 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent/codex_output.ts +577 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent/codex_transcript.ndjson +96 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent/cursor_output.ts +474 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent/cursor_transcript.ndjson +7 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent/input.ts +28 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/README.md +59 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/codex_output.ts +33 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/codex_transcript.ndjson +14 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/input.ts +85 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2/codex_output.ts +25 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2/codex_transcript.ndjson +7 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2/input.ts +131 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2_nested/codex_output.ts +33 0 apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2_nested/codex_transcript.ndjson +21 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native/claude_transcript.ndjson +21 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native/codex_transcript.ndjson +49 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_continue/README.md +25 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_continue/claude_transcript.ndjson +96 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_continue/codex_transcript.ndjson +35 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_fork_local_rollback/claude_transcript.ndjson +26 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_prior_turn/claude_transcript.ndjson +933 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_prior_turn/codex_transcript.ndjson +48 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_siblings/README.md +32 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_siblings/claude_transcript.ndjson +130 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_siblings/codex_transcript.ndjson +45 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_continue/README.md +34 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_continue/claude_transcript.ndjson +112 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_continue/codex_transcript.ndjson +46 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_siblings/README.md +49 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_siblings/claude_transcript.ndjson +177 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_siblings/codex_transcript.ndjson +69 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/claude_output.ts +24 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/claude_transcript.ndjson +68 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/codex_output.ts +100 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/codex_transcript.ndjson +21 0 apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/input.ts +39 0 apps/server/src/orchestration-v2/testkit/fixtures/todo_list/codex_output.ts +105 0 apps/server/src/orchestration-v2/testkit/fixtures/todo_list/codex_transcript.ndjson +62 0 apps/server/src/orchestration-v2/testkit/fixtures/todo_list/cursor_output.ts +104 0 apps/server/src/orchestration-v2/testkit/fixtures/todo_list/cursor_transcript.ndjson +50 0 apps/server/src/orchestration-v2/testkit/fixtures/todo_list/grok_output.ts +16 0 apps/server/src/orchestration-v2/testkit/fixtures/todo_list/grok_transcript.ndjson +7 0 apps/server/src/orchestration-v2/testkit/fixtures/todo_list/input.ts +62 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/claude_output.ts +16 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/claude_transcript.ndjson +64 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/cursor_output.ts +27 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/cursor_transcript.ndjson +15 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/grok_transcript.ndjson +7 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/input.ts +50 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/claude_output.ts +15 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/claude_transcript.ndjson +36 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/codex_output.ts +65 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/codex_transcript.ndjson +13 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/grok_transcript.ndjson +10 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/input.ts +41 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/claude_output.ts +15 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/claude_transcript.ndjson +37 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/codex_output.ts +137 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/codex_transcript.ndjson +10 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/input.ts +34 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/claude_output.ts +13 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/claude_transcript.ndjson +29 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/codex_output.ts +57 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/codex_transcript.ndjson +7 0 apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/input.ts +51 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/claude_output.ts +7 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/claude_transcript.ndjson +49 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/codex_output.ts +21 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/codex_transcript.ndjson +9 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/grok_transcript.ndjson +10 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/input.ts +14 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/opencode_transcript.ndjson +95 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/claude_output.ts +11 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/claude_transcript.ndjson +146 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/codex_output.ts +35 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/codex_transcript.ndjson +75 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/cursor_output.ts +43 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/cursor_transcript.ndjson +10 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/input.ts +129 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_restart/claude_output.ts +20 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_restart/claude_transcript.ndjson +15 0 apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_restart/input.ts +58 0 apps/server/src/orchestration-v2/testkit/fixtures/web_search/claude_output.ts +16 0 apps/server/src/orchestration-v2/testkit/fixtures/web_search/claude_transcript.ndjson +41 0 apps/server/src/orchestration-v2/testkit/fixtures/web_search/codex_output.ts +22 0 apps/server/src/orchestration-v2/testkit/fixtures/web_search/codex_transcript.ndjson +7 0 apps/server/src/orchestration-v2/testkit/fixtures/web_search/input.ts +4 0 apps/server/src/orchestration-v2/testkit/index.ts +621 0 apps/server/src/orchestration-v2/threadHistoryPaging.test.ts +497 0 apps/server/src/orchestration-v2/threadHistoryPaging.ts +0 268 apps/server/src/orchestration/ActivityPayloadProjection.test.ts +0 600 apps/server/src/orchestration/ActivityPayloadProjection.ts +0 1261 apps/server/src/orchestration/Layers/CheckpointReactor.test.ts +0 946 apps/server/src/orchestration/Layers/CheckpointReactor.ts +0 1646 apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts +27 46 apps/server/src/orchestration/Layers/OrchestrationEngine.ts +0 104 apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts +0 40 apps/server/src/orchestration/Layers/OrchestrationReactor.ts +105 0 apps/server/src/orchestration/Layers/ProjectEnrichmentProjection.test.ts +0 3700 apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts +15 30 apps/server/src/orchestration/Layers/ProjectionPipeline.ts +102 0 apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.search.test.ts +0 2728 apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts +317 461 apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts +0 3385 apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts +0 1605 apps/server/src/orchestration/Layers/ProviderCommandReactor.ts +0 144 apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.activity.test.ts +0 70 apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.approval.test.ts +0 3650 apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts +0 2110 apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts +0 39 apps/server/src/orchestration/Layers/RuntimeReceiptBus.ts +0 139 apps/server/src/orchestration/Layers/ThreadDeletionReactor.test.ts +0 124 apps/server/src/orchestration/Layers/ThreadDeletionReactor.ts +0 360 apps/server/src/orchestration/Normalizer.attachments.test.ts +0 73 apps/server/src/orchestration/Normalizer.test.ts +0 299 apps/server/src/orchestration/Normalizer.ts +1 1 apps/server/src/orchestration/Schemas.ts +0 40 apps/server/src/orchestration/Services/CheckpointReactor.ts +7 7 apps/server/src/orchestration/Services/OrchestrationEngine.ts +0 32 apps/server/src/orchestration/Services/OrchestrationReactor.ts +1 1 apps/server/src/orchestration/Services/ProjectionPipeline.ts +19 8 apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts +0 42 apps/server/src/orchestration/Services/ProviderCommandReactor.ts +0 41 apps/server/src/orchestration/Services/ProviderRuntimeIngestion.ts +0 66 apps/server/src/orchestration/Services/RuntimeReceiptBus.ts +0 40 apps/server/src/orchestration/Services/ThreadDeletionReactor.ts +0 171 apps/server/src/orchestration/ThreadLiveEventCoalescer.test.ts +0 207 apps/server/src/orchestration/ThreadLiveEventCoalescer.ts +0 616 apps/server/src/orchestration/ThreadSettlementReactor.test.ts +0 191 apps/server/src/orchestration/ThreadSettlementReactor.ts +0 232 apps/server/src/orchestration/commandInvariants.test.ts +2 3 apps/server/src/orchestration/commandInvariants.ts +0 217 apps/server/src/orchestration/decider.delete.test.ts +3 3 apps/server/src/orchestration/decider.ts +0 110 apps/server/src/orchestration/http.ts +0 960 apps/server/src/orchestration/projector.test.ts +6 2 apps/server/src/orchestration/projector.ts +37 1 apps/server/src/persistence/Layers/OrchestrationCommandReceipts.ts +111 1 apps/server/src/persistence/Layers/OrchestrationEventStore.test.ts +323 3 apps/server/src/persistence/Layers/OrchestrationEventStore.ts +1 1 apps/server/src/persistence/Layers/ProjectionCheckpoints.ts +1 1 apps/server/src/persistence/Layers/ProjectionTurns.ts +18 0 apps/server/src/persistence/Migrations.ts +231 0 apps/server/src/persistence/Migrations/045_046_OrchestrationV2.test.ts +303 0 apps/server/src/persistence/Migrations/045_OrchestrationV2.ts +28 0 apps/server/src/persistence/Migrations/046_OrchestrationV2Subagents.ts +64 0 apps/server/src/persistence/Migrations/047_OrchestrationV2Foundation.test.ts +180 0 apps/server/src/persistence/Migrations/047_OrchestrationV2Foundation.ts +27 0 apps/server/src/persistence/Migrations/048_OrchestrationV2ProviderSessionBindings.ts +23 0 apps/server/src/persistence/Migrations/049_OrchestrationV2ThreadLaunchWorkflows.ts +135 0 apps/server/src/persistence/Migrations/050_ApplicationEventSource.test.ts +281 0 apps/server/src/persistence/Migrations/050_ApplicationEventSource.ts +80 0 apps/server/src/persistence/Migrations/051_OrchestrationV2EffectCancellation.test.ts +78 0 apps/server/src/persistence/Migrations/051_OrchestrationV2EffectCancellation.ts +42 0 apps/server/src/persistence/Migrations/052_ScheduledTasks.ts +27 0 apps/server/src/persistence/Migrations/053_LegacyV1ImportState.ts +2 7 apps/server/src/persistence/ProviderSessionRuntime.ts +7 6 apps/server/src/persistence/Services/OrchestrationCommandReceipts.ts +46 4 apps/server/src/persistence/Services/OrchestrationEventStore.ts +4 2 apps/server/src/persistence/Services/ProjectionCheckpoints.ts +2 5 apps/server/src/persistence/Services/ProjectionPendingApprovals.ts +2 8 apps/server/src/persistence/Services/ProjectionThreadActivities.ts +2 8 apps/server/src/persistence/Services/ProjectionThreadMessages.ts +2 7 apps/server/src/persistence/Services/ProjectionThreadProposedPlans.ts +2 8 apps/server/src/persistence/Services/ProjectionThreadSessions.ts +5 3 apps/server/src/persistence/Services/ProjectionTurns.ts +343 0 apps/server/src/project/ProjectEnrichmentService.test.ts +297 0 apps/server/src/project/ProjectEnrichmentService.ts +412 0 apps/server/src/project/ProjectService.test.ts +395 0 apps/server/src/project/ProjectService.ts +62 184 apps/server/src/project/ProjectSetupScriptRunner.test.ts +25 17 apps/server/src/project/ProjectSetupScriptRunner.ts +52 0 apps/server/src/project/http.test.ts +84 0 apps/server/src/project/http.ts +3 0 apps/server/src/provider/CodexDeveloperInstructions.ts +144 0 apps/server/src/provider/Drivers/AcpRegistryDriver.ts +36 22 apps/server/src/provider/Drivers/ClaudeDriver.ts +24 13 apps/server/src/provider/Drivers/CodexDriver.ts +35 69 apps/server/src/provider/Drivers/CursorDriver.ts +24 7 apps/server/src/provider/Drivers/GrokDriver.ts +23 9 apps/server/src/provider/Drivers/OpenCodeDriver.ts +2 165 apps/server/src/provider/Errors.ts +0 5408 apps/server/src/provider/Layers/ClaudeAdapter.test.ts +0 4820 apps/server/src/provider/Layers/ClaudeAdapter.ts +0 1684 apps/server/src/provider/Layers/CodexAdapter.test.ts +0 2038 apps/server/src/provider/Layers/CodexAdapter.ts +0 1500 apps/server/src/provider/Layers/CursorAdapter.test.ts +0 1193 apps/server/src/provider/Layers/CursorAdapter.ts +158 576 apps/server/src/provider/Layers/CursorProvider.test.ts +137 949 apps/server/src/provider/Layers/CursorProvider.ts +73 0 apps/server/src/provider/Layers/CursorSdkCatalog.ts +0 2399 apps/server/src/provider/Layers/GrokAdapter.test.ts +0 2130 apps/server/src/provider/Layers/GrokAdapter.ts +0 1 apps/server/src/provider/Layers/GrokProvider.ts +0 5358 apps/server/src/provider/Layers/OpenCodeAdapter.test.ts +0 3285 apps/server/src/provider/Layers/OpenCodeAdapter.ts +0 183 apps/server/src/provider/Layers/ProviderAdapterRegistry.test.ts +0 92 apps/server/src/provider/Layers/ProviderAdapterRegistry.ts +11 3 apps/server/src/provider/Layers/ProviderInstanceRegistryHydration.ts +21 14 apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts +36 0 apps/server/src/provider/Layers/ProviderOrchestrationAdapterInfrastructure.ts +74 8 apps/server/src/provider/Layers/ProviderRegistry.test.ts +24 0 apps/server/src/provider/Layers/ProviderRegistry.ts +0 2583 apps/server/src/provider/Layers/ProviderService.test.ts +0 1277 apps/server/src/provider/Layers/ProviderService.ts +0 271 apps/server/src/provider/Layers/ProviderSessionDirectory.test.ts +0 197 apps/server/src/provider/Layers/ProviderSessionDirectory.ts +0 640 apps/server/src/provider/Layers/ProviderSessionReaper.test.ts +0 152 apps/server/src/provider/Layers/ProviderSessionReaper.ts +40 0 apps/server/src/provider/NativeProtocolLogging.ts +7 7 apps/server/src/provider/ProviderDriver.ts +0 19 apps/server/src/provider/Services/ClaudeAdapter.ts +0 23 apps/server/src/provider/Services/CodexAdapter.ts +0 19 apps/server/src/provider/Services/CursorAdapter.ts +0 16 apps/server/src/provider/Services/GrokAdapter.ts +0 19 apps/server/src/provider/Services/OpenCodeAdapter.ts +0 138 apps/server/src/provider/Services/ProviderAdapter.ts +0 68 apps/server/src/provider/Services/ProviderAdapterRegistry.ts +0 130 apps/server/src/provider/Services/ProviderService.ts +0 70 apps/server/src/provider/Services/ProviderSessionDirectory.ts +0 15 apps/server/src/provider/Services/ProviderSessionReaper.ts +47 0 apps/server/src/provider/T3OrchestrationInstructions.test.ts +35 0 apps/server/src/provider/T3OrchestrationInstructions.ts +0 28 apps/server/src/provider/acp/AcpAdapterSupport.test.ts +0 56 apps/server/src/provider/acp/AcpAdapterSupport.ts +304 4 apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts +10 6 apps/server/src/provider/acp/AcpNativeLogging.ts +263 0 apps/server/src/provider/acp/AcpRegistrySupport.test.ts +633 0 apps/server/src/provider/acp/AcpRegistrySupport.ts +93 0 apps/server/src/provider/acp/AcpRuntimeModel.test.ts +31 0 apps/server/src/provider/acp/AcpRuntimeModel.ts +1090 0 apps/server/src/provider/acp/AcpSessionRuntime.processTree.test.ts +1549 119 apps/server/src/provider/acp/AcpSessionRuntime.ts +0 153 apps/server/src/provider/acp/CursorAcpCliProbe.test.ts +0 154 apps/server/src/provider/acp/CursorAcpExtension.test.ts +0 113 apps/server/src/provider/acp/CursorAcpExtension.ts +0 121 apps/server/src/provider/acp/CursorAcpSupport.test.ts +0 115 apps/server/src/provider/acp/CursorAcpSupport.ts +21 0 apps/server/src/provider/acp/GrokAcpCliProbe.test.ts +24 0 apps/server/src/provider/acp/GrokAcpSupport.test.ts +24 0 apps/server/src/provider/acp/GrokAcpSupport.ts +1425 76 apps/server/src/provider/acp/XAiAcpExtension.test.ts +1121 308 apps/server/src/provider/acp/XAiAcpExtension.ts +3 0 apps/server/src/provider/builtInDrivers.ts +52 0 apps/server/src/provider/cursorSdkModel.ts +11 11 apps/server/src/provider/providerMaintenanceRunner.test.ts +0 74 apps/server/src/provider/testUtils/providerAdapterRegistryMock.ts +0 727 apps/server/src/relay/AgentAwarenessRelay.test.ts +45 69 apps/server/src/relay/AgentAwarenessRelay.ts +123 0 apps/server/src/scheduledTasks/Schedule.test.ts +104 0 apps/server/src/scheduledTasks/Schedule.ts +799 0 apps/server/src/scheduledTasks/ScheduledTaskService.ts +0 9616 apps/server/src/server.test.ts +51 56 apps/server/src/server.ts +12 6 apps/server/src/serverActivation.ts +25 2 apps/server/src/serverLifecycleEvents.test.ts +6 5 apps/server/src/serverLifecycleEvents.ts +0 660 apps/server/src/serverRuntimeStartup.reconcile.test.ts +76 249 apps/server/src/serverRuntimeStartup.test.ts +286 474 apps/server/src/serverRuntimeStartup.ts +30 0 apps/server/src/textGeneration/CodexTextGeneration.test.ts +27 9 apps/server/src/textGeneration/CodexTextGeneration.ts +143 257 apps/server/src/textGeneration/CursorTextGeneration.test.ts +68 77 apps/server/src/textGeneration/CursorTextGeneration.ts +1 1 apps/server/src/textGeneration/TextGeneration.test.ts +9 0 apps/server/src/vcs/GitVcsDriver.ts +7 1 apps/server/src/vcs/GitVcsDriverCore.test.ts +15 0 apps/server/src/vcs/GitVcsDriverCore.ts +40 0 apps/server/src/ws.test.ts +1029 1082 apps/server/src/ws.ts +0 611 apps/server/test/ActivityPayloadProjection.test.ts +15 0 apps/web/src/appearanceFonts.test.ts +6 0 apps/web/src/appearanceFonts.ts +3 0 apps/web/src/components/AppSidebarLayout.tsx +13 0 apps/web/src/components/BranchToolbar.logic.test.ts +7 0 apps/web/src/components/BranchToolbar.logic.ts +42 2 apps/web/src/components/BranchToolbar.tsx +66 21 apps/web/src/components/BranchToolbarBranchSelector.tsx +98 39 apps/web/src/components/BranchToolbarEnvModeSelector.tsx +50 26 apps/web/src/components/BranchToolbarEnvironmentSelector.tsx +257 413 apps/web/src/components/ChatView.logic.test.ts +132 154 apps/web/src/components/ChatView.logic.ts +1665 1385 apps/web/src/components/ChatView.tsx +5 6 apps/web/src/components/CommandPalette.logic.test.ts +1 1 apps/web/src/components/CommandPalette.logic.ts +14 4 apps/web/src/components/CommandPalette.tsx +49 44 apps/web/src/components/DiffPanel.tsx +107 22 apps/web/src/components/GitActionsControl.logic.test.ts +106 29 apps/web/src/components/GitActionsControl.logic.ts +442 307 apps/web/src/components/GitActionsControl.tsx +4 4 apps/web/src/components/LegacySidebar.tsx +45 0 apps/web/src/components/LegacyThreadMigrationToast.tsx +34 0 apps/web/src/components/ProjectScriptsControl.test.tsx +153 39 apps/web/src/components/ProjectScriptsControl.tsx +3 0 apps/web/src/components/RightPanelTabs.tsx +512 266 apps/web/src/components/Sidebar.logic.test.ts +164 77 apps/web/src/components/Sidebar.logic.ts +105 155 apps/web/src/components/Sidebar.tsx +7 2 apps/web/src/components/ThreadStatusIndicators.tsx +6 6 apps/web/src/components/chat/ChangedFilesTree.test.tsx +12 12 apps/web/src/components/chat/ChangedFilesTree.tsx +111 27 apps/web/src/components/chat/ChatComposer.tsx +37 370 apps/web/src/components/chat/ChatHeader.tsx +7 4 apps/web/src/components/chat/ComposerPendingApprovalActions.test.tsx +6 4 apps/web/src/components/chat/ComposerPendingApprovalActions.tsx +9 5 apps/web/src/components/chat/ComposerPendingApprovalPanel.test.tsx +3 1 apps/web/src/components/chat/ComposerPendingApprovalPanel.tsx +3 2 apps/web/src/components/chat/ComposerPendingUserInputPanel.test.tsx +9 4 apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx +0 44 apps/web/src/components/chat/ComposerPrimaryActions.test.tsx +81 47 apps/web/src/components/chat/ComposerPrimaryActions.tsx +0 62 apps/web/src/components/chat/ContextWindowMeter.test.tsx +583 595 apps/web/src/components/chat/MessagesTimeline.logic.test.ts +349 174 apps/web/src/components/chat/MessagesTimeline.logic.ts +1330 355 apps/web/src/components/chat/MessagesTimeline.test.tsx +1013 416 apps/web/src/components/chat/MessagesTimeline.tsx +22 0 apps/web/src/components/chat/OpenInPicker.logic.ts +1 22 apps/web/src/components/chat/{ChatHeader.test.ts => OpenInPicker.test.ts} +55 18 apps/web/src/components/chat/OpenInPicker.tsx +43 0 apps/web/src/components/chat/OpenInPickerShortcut.ts +6 0 apps/web/src/components/chat/PanelLayoutControls.test.tsx +123 38 apps/web/src/components/chat/PanelLayoutControls.tsx +2 0 apps/web/src/components/chat/ProposedPlanCard.tsx +171 0 apps/web/src/components/chat/QueuedRunsControl.test.tsx +451 0 apps/web/src/components/chat/QueuedRunsControl.tsx +190 0 apps/web/src/components/chat/ThreadAutomationsPanel.tsx +91 0 apps/web/src/components/chat/ThreadDetailsPanel.test.tsx +280 0 apps/web/src/components/chat/ThreadDetailsPanel.tsx +415 0 apps/web/src/components/chat/ThreadDetailsPrRow.tsx +49 0 apps/web/src/components/chat/ThreadRelationshipsControl.test.tsx +373 0 apps/web/src/components/chat/ThreadRelationshipsControl.tsx +60 0 apps/web/src/components/chat/TimelineSystemDivider.tsx +312 0 apps/web/src/components/chat/V2ItemInspector.tsx +358 0 apps/web/src/components/chat/V2LifecycleRow.tsx +31 0 apps/web/src/components/chat/composerDispatch.test.ts +15 0 apps/web/src/components/chat/composerDispatch.ts +29 1 apps/web/src/components/chat/externalLinkContextMenu.test.ts +10 2 apps/web/src/components/chat/externalLinkContextMenu.ts +54 0 apps/web/src/components/chat/threadDetailsPanelStyles.ts +3 3 apps/web/src/components/chat/useAssistantCitationTarget.ts +0 1 apps/web/src/components/files/FilePreviewPanel.tsx +30 111 apps/web/src/components/preview/PreviewPanelShell.tsx +21 0 apps/web/src/components/preview/ThreadPreviewMiniPlayer.tsx +1 1 apps/web/src/components/preview/addBrowserSurface.test.ts +28 0 apps/web/src/components/preview/previewMiniPlayerLayout.test.ts +21 0 apps/web/src/components/preview/previewMiniPlayerLayout.ts +98 0 apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts +126 0 apps/web/src/components/pullRequest/pullRequestDetail.logic.ts +344 0 apps/web/src/components/pullRequest/usePullRequestActions.ts +1 6 apps/web/src/components/settings/AddProviderInstanceDialog.tsx +6 1 apps/web/src/components/settings/KeybindingsSettings.logic.test.ts +72 1 apps/web/src/components/settings/ProviderInstanceCard.test.ts +135 3 apps/web/src/components/settings/ProviderInstanceCard.tsx +28 0 apps/web/src/components/settings/ProviderSettingsForm.test.ts +741 0 apps/web/src/components/settings/ScheduledTasksSettings.tsx +56 4 apps/web/src/components/settings/SettingsPanels.tsx +3 0 apps/web/src/components/settings/SettingsSidebarNav.tsx +38 3 apps/web/src/components/settings/providerDriverMeta.ts +4 0 apps/web/src/components/settings/settingsSearch.test.ts +7 0 apps/web/src/components/settings/settingsSearch.ts +9 1 apps/web/src/components/ui/popover.tsx +119 0 apps/web/src/composerDraftStore.ts +6 2 apps/web/src/connection/runtime.ts +35 53 apps/web/src/connection/storage.ts +1 1 apps/web/src/diffFileActions.test.ts +6 20 apps/web/src/diffPanelStore.test.ts +5 5 apps/web/src/diffPanelStore.ts +25 0 apps/web/src/hooks/useElementWidth.ts +2 2 apps/web/src/hooks/useHandleNewThread.ts +91 0 apps/web/src/hooks/usePreviewPanelInlineSize.ts +5 2 apps/web/src/hooks/useThreadActionMenu.ts +33 3 apps/web/src/hooks/useThreadActions.ts +45 0 apps/web/src/hooks/useThreadVisitedMigration.ts +11 9 apps/web/src/hooks/useTurnDiffSummaries.ts +186 1 apps/web/src/index.css +39 19 apps/web/src/keybindings.test.ts +5 1 apps/web/src/keybindings.ts +50 72 apps/web/src/lib/contextWindow.test.ts +63 32 apps/web/src/lib/contextWindow.ts +54 0 apps/web/src/lib/orchestrationV2Timeline.test.ts +22 0 apps/web/src/lib/orchestrationV2Timeline.ts +9 10 apps/web/src/lib/threadSort.test.ts +24 0 apps/web/src/pendingUserInput.test.ts +11 0 apps/web/src/pendingUserInput.ts +41 0 apps/web/src/providerInstances.test.ts +18 0 apps/web/src/providerInstances.ts +23 0 apps/web/src/providerUpdateDismissal.test.ts +55 2 apps/web/src/providerUpdateDismissal.ts +19 0 apps/web/src/rightPanelLayout.test.ts +14 0 apps/web/src/rightPanelLayout.ts +82 124 apps/web/src/rightPanelStore.test.ts +206 64 apps/web/src/rightPanelStore.ts +21 0 apps/web/src/routeTree.gen.ts +2 0 apps/web/src/routes/__root.tsx +10 27 apps/web/src/routes/_chat.$environmentId.$threadId.tsx +2 2 apps/web/src/routes/_chat.draft.$draftId.tsx +6 0 apps/web/src/routes/_chat.pull-requests.tsx +7 0 apps/web/src/routes/settings.scheduled-tasks.tsx +0 172 apps/web/src/session-logic.command-output.test.ts +766 2371 apps/web/src/session-logic.test.ts +582 1530 apps/web/src/session-logic.ts +68 42 apps/web/src/state/entities.ts +0 24 apps/web/src/state/queries.ts +13 0 apps/web/src/state/server.ts +1 1 apps/web/src/state/sourceControlActions.ts +2 1 apps/web/src/state/threads.ts +62 0 apps/web/src/state/v2ItemSupport.ts +57 0 apps/web/src/state/waitForAtomValue.test.ts +56 0 apps/web/src/state/waitForAtomValue.ts +136 0 apps/web/src/test-fixtures.ts +16 22 apps/web/src/threadRoutes.test.ts +5 6 apps/web/src/threadRoutes.ts +8 1 apps/web/src/threadSync.test.ts +39 0 apps/web/src/timestampFormat.test.ts +31 0 apps/web/src/timestampFormat.ts +34 14 apps/web/src/types.ts +1 0 apps/web/src/uiStateStore.test.ts +9 0 apps/web/src/versionSkew.test.ts +14 0 apps/web/src/versionSkew.ts +5 6 apps/web/src/worktreeCleanup.test.ts +11 0 docs/README.md +19 0 docs/internals/context-handoffs.md +36 0 docs/internals/legacy-orchestration-migration.md +9 13 docs/internals/overview.md +32 0 docs/internals/performance-regressions.md +166 0 docs/orchestration-v2/README.md +679 0 docs/orchestration-v2/core-graph-and-data-model.md +231 0 docs/orchestration-v2/entity-ids-and-correlation.md +535 0 docs/orchestration-v2/feature-lifecycles.md +413 0 docs/orchestration-v2/orchestrator-mcp-server.md +284 0 docs/orchestration-v2/provider-capability-system.md +233 0 docs/orchestration-v2/provider-switching-and-context.md +233 0 docs/orchestration-v2/testing-strategy.md +286 0 docs/orchestration-v2/thread-lineage-and-context-transfer.md +17 0 docs/user/activity-log.md +11 0 docs/user/appearance.md +20 0 docs/user/composer.md +68 0 docs/user/cursor.md +19 0 docs/user/portable-handoffs.md +61 0 docs/user/thread-migration.md +4 0 docs/user/updating.md +2 0 oxlint-plugin-t3code/rules/no-mobile-uniwind-theme-escape-hatches.ts +1 0 package.json +36 0 packages/client-runtime/package.json +57 0 packages/client-runtime/src/connection/compatibility.test.ts +27 0 packages/client-runtime/src/connection/compatibility.ts +4 5 packages/client-runtime/src/connection/registry.test.ts +42 3 packages/client-runtime/src/connection/resolver.test.ts +39 9 packages/client-runtime/src/connection/resolver.ts +475 40 packages/client-runtime/src/operations/commands.test.ts +765 240 packages/client-runtime/src/operations/commands.ts +1 0 packages/client-runtime/src/operations/index.ts +1 2 packages/client-runtime/src/operations/projects.test.ts +2 4 packages/client-runtime/src/operations/projects.ts +47 0 packages/client-runtime/src/operations/threadTitle.test.ts +33 0 packages/client-runtime/src/operations/threadTitle.ts +1 0 packages/client-runtime/src/platform/index.ts +143 0 packages/client-runtime/src/platform/orchestrationCache.test.ts +36 0 packages/client-runtime/src/platform/orchestrationCache.ts +6 6 packages/client-runtime/src/platform/persistence.ts +4 3 packages/client-runtime/src/rpc/client.ts +2 2 packages/client-runtime/src/state/archivedThreads.test.ts +3 3 packages/client-runtime/src/state/archivedThreads.ts +214 0 packages/client-runtime/src/state/boundedThreadSnapshotHttp.test.ts +160 0 packages/client-runtime/src/state/boundedThreadSnapshotHttp.ts +436 299 packages/client-runtime/src/state/entities.test.ts +22 0 packages/client-runtime/src/state/environmentHttpAuth.test.ts +15 0 packages/client-runtime/src/state/environmentHttpAuth.ts +205 0 packages/client-runtime/src/state/itemSupport.test.ts +138 0 packages/client-runtime/src/state/itemSupport.ts +211 15 packages/client-runtime/src/state/models.ts +32 7 packages/client-runtime/src/state/orchestration.ts +314 0 packages/client-runtime/src/state/orchestrationV2Projection.test.ts +257 0 packages/client-runtime/src/state/orchestrationV2Projection.ts +110 0 packages/client-runtime/src/state/orchestrationV2TestFixtures.ts +2 2 packages/client-runtime/src/state/projectEntities.ts +50 8 packages/client-runtime/src/state/server.ts +469 54 packages/client-runtime/src/state/shell-sync.test.ts +10 2 packages/client-runtime/src/state/shell.test.ts +72 23 packages/client-runtime/src/state/shell.ts +379 132 packages/client-runtime/src/state/shellReducer.test.ts +129 24 packages/client-runtime/src/state/shellReducer.ts +10 6 packages/client-runtime/src/state/shellSnapshotHttp.ts +2 2 packages/client-runtime/src/state/snapshots.ts +64 0 packages/client-runtime/src/state/subagentRuntime.ts +52 0 packages/client-runtime/src/state/threadCheckpoints.ts +112 0 packages/client-runtime/src/state/threadCommands.ts +98 0 packages/client-runtime/src/state/threadDetail.test.ts +31 138 packages/client-runtime/src/state/threadDetail.ts +114 0 packages/client-runtime/src/state/threadExecution.test.ts +104 0 packages/client-runtime/src/state/threadExecution.ts +15 0 packages/client-runtime/src/state/threadFeedback.test.ts +9 0 packages/client-runtime/src/state/threadFeedback.ts +66 0 packages/client-runtime/src/state/threadHistoryController.test.ts +93 0 packages/client-runtime/src/state/threadHistoryController.ts +49 0 packages/client-runtime/src/state/threadHistoryHttp.ts +416 0 packages/client-runtime/src/state/threadHistoryMerge.test.ts +156 0 packages/client-runtime/src/state/threadHistoryMerge.ts +0 1260 packages/client-runtime/src/state/threadReducer.test.ts +0 756 packages/client-runtime/src/state/threadReducer.ts +421 0 packages/client-runtime/src/state/threadRelationships.test.ts +236 0 packages/client-runtime/src/state/threadRelationships.ts +90 0 packages/client-runtime/src/state/threadRequests.ts +79 27 packages/client-runtime/src/state/threadSettled.ts +10 10 packages/client-runtime/src/state/threadShell.ts +51 41 packages/client-runtime/src/state/threadSnapshotHttp.ts +12 0 packages/client-runtime/src/state/threadSort.test.ts +11 26 packages/client-runtime/src/state/threadState.ts +354 0 packages/client-runtime/src/state/threadWorkflows.test.ts +152 0 packages/client-runtime/src/state/threadWorkflows.ts +0 544 packages/client-runtime/src/state/threads-pagination.test.ts +696 208 packages/client-runtime/src/state/threads-sync.test.ts +398 418 packages/client-runtime/src/state/threads.ts +36 0 packages/client-runtime/src/state/turnItemPresentation.test.ts +8 0 packages/client-runtime/src/state/turnItemPresentation.ts +45 16 packages/client-runtime/src/state/vcsAction.test.ts +13 2 packages/client-runtime/src/state/vcsAction.ts +151 0 packages/client-runtime/src/t3ToolSummary.test.ts +190 0 packages/client-runtime/src/t3ToolSummary.ts +38 18 packages/client-runtime/src/work-log/presentation.test.ts +164 90 packages/client-runtime/src/work-log/presentation.ts +4 0 packages/contracts/package.json +63 0 packages/contracts/src/applicationEvent.test.ts +120 0 packages/contracts/src/applicationEvent.ts +1 1 packages/contracts/src/assets.test.ts +2 2 packages/contracts/src/assets.ts +28 0 packages/contracts/src/baseSchemas.ts +114 0 packages/contracts/src/chatAttachment.ts +65 0 packages/contracts/src/checkpointDiff.ts +13 0 packages/contracts/src/environment.ts +71 33 packages/contracts/src/environmentHttp.ts +12 0 packages/contracts/src/index.ts +20 20 packages/contracts/src/ipc.ts +5 0 packages/contracts/src/keybindings.test.ts +1 0 packages/contracts/src/keybindings.ts +3 0 packages/contracts/src/model.ts +63 0 packages/contracts/src/modelSelection.ts +5 4 packages/contracts/src/orchestration.test.ts +55 532 packages/contracts/src/orchestration.ts +24 0 packages/contracts/src/orchestrationProject.ts +772 0 packages/contracts/src/orchestrationV2.test.ts +2693 0 packages/contracts/src/orchestrationV2.ts +168 0 packages/contracts/src/orchestratorMcp.test.ts +560 0 packages/contracts/src/orchestratorMcp.ts +94 0 packages/contracts/src/project.ts +5 3 packages/contracts/src/provider.ts +60 0 packages/contracts/src/providerPolicy.ts +1 1 packages/contracts/src/providerRuntime.ts +11 1 packages/contracts/src/rpc.test.ts +182 58 packages/contracts/src/rpc.ts +52 0 packages/contracts/src/scheduledTask.test.ts +182 0 packages/contracts/src/scheduledTask.ts +17 0 packages/contracts/src/server.ts +43 0 packages/contracts/src/settings.test.ts +56 22 packages/contracts/src/settings.ts +4 2 packages/contracts/src/t3ProjectFile.test.ts +1 1 packages/contracts/src/t3ProjectFile.ts +127 0 packages/contracts/src/worktreeMcp.ts +10 0 packages/effect-acp/src/client.ts +255 0 packages/effect-acp/src/protocol.test.ts +248 10 packages/effect-acp/src/protocol.ts +8 0 packages/effect-codex-app-server/package.json +11 1 packages/effect-codex-app-server/src/client.ts +146 0 packages/effect-codex-app-server/src/replay.test.ts +532 0 packages/effect-codex-app-server/src/replay.ts +16 0 packages/shared/package.json +12 0 packages/shared/src/Array.test.ts +6 0 packages/shared/src/Array.ts +57 150 packages/shared/src/agentAwareness.test.ts +54 75 packages/shared/src/agentAwareness.ts +38 1 packages/shared/src/model.test.ts +39 0 packages/shared/src/model.ts +15 15 packages/shared/src/orchestrationTiming.ts +432 0 packages/shared/src/orchestrationV2PendingBackgroundWork.test.ts +238 0 packages/shared/src/orchestrationV2PendingBackgroundWork.ts +110 0 packages/shared/src/orchestrationV2Timeline.test.ts +73 0 packages/shared/src/orchestrationV2Timeline.ts +52 0 packages/shared/src/t3McpToolPresentation.test.ts +119 0 packages/shared/src/t3McpToolPresentation.ts +142 5 pnpm-lock.yaml +1 0 vite.config.ts diff --git a/audits/orchestrator-v2/2026-09-02/clients.md b/audits/orchestrator-v2/2026-09-02/clients.md new file mode 100644 index 000000000000..25ed1cefe69f --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/clients.md @@ -0,0 +1,147 @@ +# Client parity audit: orchestrator v2 rebases + +Audit target: `d2f1f511f4cc833bc930d6c355cd0f9b61e835a0` + +Upstream baseline: `57a66608b918d673eeec7e6c94ea5906b756fcd0` (verified ancestor) + +Prior review object: `47f5b100440591d2f49aa30cf3bb69eacae07f52`; rebased prior tip: `c1791ab2637` + +Scope: `apps/web`, `apps/mobile`, `packages/client-runtime`, and relevant desktop entrypoints. I read both supplied inventories, followed the affected UI actions through client-runtime commands and projections, and compared current code to the supplied upstream main object. This was a source review backed by focused existing tests. I did not use a browser, dev server, provider, or production state. + +## Confirmed findings + +All four findings below are source-confirmed. I did not reproduce them in a real client. + +### High: the web sidebar crashes when a listed environment has no hydrated provider config + +- **Current evidence:** `apps/web/src/components/Sidebar.tsx:3680-3682` and `:3789-3791` evaluate `EMPTY_PROVIDER_ENTRIES` as the fallback for a missing environment entry. The binding is declared inside `Sidebar` only at `:3997`, after the component's unconditional return at `:3996`, so it remains in the temporal dead zone for that render. The map is expected to be incomplete: `packages/client-runtime/src/state/shell.ts:421-433` adds only non-null server configs, while the sidebar builds provider maps from that result at `apps/web/src/components/Sidebar.tsx:1887-1899`. +- **Upstream main evidence:** at `57a66608b918d673eeec7e6c94ea5906b756fcd0`, `apps/web/src/components/Sidebar.tsx:265` declares the empty map at module scope and uses it at `:3721-3722`. `git blame` attributes the misplaced current declaration to round 18 reconciliation commit `7697286069f`. +- **Reachable trigger:** open web or desktop with a cached/disconnected, reconnecting, newly added, or otherwise not-yet-configured environment that still contributes a visible thread. Either the normal thread list or search results can take the fallback. +- **Impact:** React render throws `ReferenceError: Cannot access 'EMPTY_PROVIDER_ENTRIES' before initialization`; the whole sidebar/client surface can fail instead of showing cached threads. Any cached shell can expose it, with disconnected/reconnecting remote environments making it especially reproducible. +- **Minimal action:** restore the module-scope declaration from main. Add a rendered sidebar behavior test whose catalog/shell contains a visible remote thread while that environment's config atom is null, and assert that the row remains usable. + +### High: editing a queued web message accepts generic files, then silently omits them from the saved edit + +- **Current evidence:** edit mode uses the ordinary composer and its file picker remains enabled (`apps/web/src/components/chat/ChatComposer.tsx:842-855`, `:4390-4422`). Generic files are accepted into `composerDraft.files` at `:3151-3186`. `ChatView` reads those files at `apps/web/src/components/ChatView.tsx:5892-5904`, but the queued-edit branch at `:5938-5971` checks and serializes only `composerImages`; `composerFiles` does not participate in the empty-edit guard, upload list, or replacement attachment list. The shared command already supports mixed stored/upload attachments and persists them before dispatch (`packages/client-runtime/src/operations/commands.ts:213-225`, `:242-267`, `:843-857`). +- **Related loss path:** if the queued run starts or is cancelled from another client, `apps/web/src/components/ChatView.tsx:3323-3345` treats an edit as dirty only when text changed or images exist. A file-only edit is cleared. The move helper itself can transfer files (`apps/web/src/composerDraftStore.ts:3875-3946`); the caller simply never invokes it for a file-only edit. +- **Upstream main evidence:** v1 has no queued-message editor, but its established send invariant snapshots both images and files and runs both through attachment upload (`57a...:apps/web/src/components/ChatView.tsx:5897-5903`, `:5950-5962`). The v2 edit contract likewise explicitly accepts `UploadChatAttachment`; this is not an unsupported contract case. +- **Reachable trigger:** while an active run has a queued follow-up, choose **Edit in the composer**, attach a PDF/video/text file, then save. With no text or retained attachment, the button appears to do nothing; with text or another attachment, the edit succeeds and the newly selected file disappears. A second client starting/cancelling the run also drops a file-only unsaved edit. +- **Impact:** user-selected content is silently excluded from the queued message, including on remote/multiple-environment setups where queued editing is especially useful. The local draft is then cleared after the successful text/image edit. +- **Minimal action:** feed `composerFiles` through the existing attachment-upload path and include them in the queued edit's emptiness and replacement calculations; include files in the cross-client dirty check. If generic files are intentionally unsupported for edits, hide/disable that picker during edit mode with an explicit reason instead of accepting and dropping them. Add an interaction test that edits a queued run, selects a generic file, saves, and verifies the dispatched edit contains the persisted attachment; separately exercise a file-only edit when another client removes the run and verify it is retained in the base composer. + +### High: mobile filters out every non-image message attachment before its file/video/PDF renderer can run + +- **Current evidence:** `apps/mobile/src/features/threads/ThreadFeed.tsx:1618-1626` reduces every message's attachments to `type === "image"`. The user-message and assistant-message branches still contain file and unknown renderers at `:1678-1698` and `:1774-1794`, but those branches are unreachable after the filter. +- **Upstream main evidence:** `57a...:apps/mobile/src/features/threads/ThreadFeed.tsx:1527-1533` keeps `message.attachments ?? []`, and `:1580-1600` reaches `MessageAttachmentFile`. The image-only filter entered in round 11 reconciliation commit `0301dc423e3`; its diff changes this exact line from the complete list to the filter. +- **Reachable trigger:** send or queue a PDF, video, text file, or other generic attachment from web or desktop, then read the message in the mobile thread feed. The projection still carries user attachments (`apps/mobile/src/lib/threadActivity.ts:1055-1077`), so this is solely a presentation loss. +- **Impact:** mobile history makes attached files appear absent. Users cannot open the existing PDF/file preview or video flow, and cross-client conversations give conflicting accounts of what was sent. Data remains persisted, but the mobile UI hides it. +- **Minimal action:** restore `const attachments = message.attachments ?? []`. Add a feed interaction test with a projected file/video attachment that presses the rendered row and observes the preview/video callback; do not limit the test to component props or static markup. + +### Medium: mobile's active v2 assistant row bypasses the specialized Markdown renderer + +- **Current evidence:** `AssistantMarkdownContent` still exists at `apps/mobile/src/features/threads/ThreadFeed.tsx:969-1016`. It splits artifact-template blocks, converts file citations to ordinary Markdown links, gives template cards an `onUse` action, and passes the thread's `renderImage` callback to native Markdown. The active v2 assistant branch never calls it. Instead, `:1755-1772` sends raw `message.text` directly to the generic renderers and omits `renderImage` from `SelectableMarkdownText`. `ThreadFeedProps` also has no artifact-template callback (`:232-256`), and the real `ThreadDetailScreen` call at `apps/mobile/src/features/threads/ThreadDetailScreen.tsx:683-715` supplies none. +- **iOS media consequence:** `apps/mobile/modules/t3-markdown-text/src/SelectableMarkdownText.ios.tsx:64-80` sets the image-renderer context to `null` when the caller omits that prop. `NativeMarkdownBlock.ios.tsx:380-422` then falls back to ``. That fallback does not resolve a workspace-relative or host-machine path through the owning environment, cannot select the video renderer, and has no signed `media-file` resource. The omitted callback is the one that creates scoped image/video previews at `apps/mobile/src/features/threads/ThreadFeed.tsx:2342-2390`. Android's fallback Markdown path still receives the custom image renderer through `styles.renderers` (`:1364-1371`, `:1763-1771`). +- **V2 text remains verbatim:** the Codex adapter appends `payload.delta` without conversion (`apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.ts:3157-3167`), chooses the provider's final `payload.item.text` at `:3683-3687`, and copies that string unchanged into both the message and assistant turn item at `:2436-2468`. Client-runtime upserts the event payload unchanged (`packages/client-runtime/src/state/orchestrationV2Projection.ts:224-225`), and mobile copies `item.text` into the feed message (`apps/mobile/src/lib/threadActivity.ts:1055-1081`). The only mobile Codex directive conversion calls are inside the bypassed `AssistantMarkdownContent`, so the trigger is real rather than already normalized upstream. +- **Upstream main evidence:** `57a...:apps/mobile/src/features/threads/ThreadDetailScreen.tsx:623-636` appends the selected template prompt to the live composer and passes that callback at `:690-716`. Main's `ThreadFeed.tsx:1453-1455`, `:1633-1641`, and `:2698-2710` route assistant text through `AssistantMarkdownContent`, including `onUseArtifactTemplate` and `renderMarkdownImage`. The callback and active invocation were removed during the v2 reconciliation diff even though the adapter component was retained. +- **Reachable trigger:** read a mobile v2 Codex response containing a `codex-file-citation` or `codex-artifact-template` directive. On iOS, any assistant Markdown workspace/host image or image-syntax video reaches the same bypassed call and loses environment-aware resolution. +- **Impact:** mobile does not produce the file citation's navigable link, and artifact templates lose the **Use template** action. On iOS, assistant workspace/host images and embedded-video Markdown also fail or render through the wrong primitive. Web remains intact through `apps/web/src/components/chat/MessagesTimeline.tsx:1590-1614` and `apps/web/src/components/ChatMarkdown.tsx:2096-2109`, `:2362-2368`. +- **Minimal action:** restore `AssistantMarkdownContent` in the current assistant-row branch, restore the `ThreadFeed` callback, and adapt main's composer-append handler to the current v2 draft setter. That one caller restoration also passes `renderMarkdownImage` on iOS. Add an integrated feed/composer behavior test that selects a template and observes the draft change, a citation press that reaches scoped file navigation, and an iOS native Markdown image/video case that observes the environment-scoped media renderer rather than the direct-URI fallback. + +## Intentional or established surface divergences + +- **Mobile queue controls remain compact.** Web exposes thumbnail rows and composer-based queued-message editing (`apps/web/src/components/chat/QueuedRunsControl.tsx:44-95`, `:331-440`). Mobile exposes environment/thread-scoped reorder, promote-to-steer, and cancel controls but no editor or thumbnails (`apps/mobile/src/features/threads/ThreadQueueControl.tsx:18-72`, `:74-149`). Neither supplied main inventory nor the v1 mobile baseline establishes queued editing as a mobile requirement, so I did not report the absence itself as a regression. The hidden persisted attachments in the feed are independent and are reported above. +- **Desktop inherits the web client.** The only branch-vs-main desktop changes are `DesktopEnvironment.test.ts`, `tailscaleEndpointProvider.ts`, and `DesktopClientSettings.test.ts`; there is no separate desktop composer/timeline implementation to reconcile. The two web findings therefore apply to desktop's wrapped web surface as well. +- **Working/thinking presentation differs by surface.** Web derives explicit active-tool and working/thinking rows in `apps/web/src/components/chat/MessagesTimeline.logic.ts:760-845` and `:1067-1075`; mobile folds live activity into native grouped work rows in `apps/mobile/src/lib/threadActivity.ts:798-917`. Both retain terminal failure visibility. This looks like established compact-mobile presentation, not a semantic loss. + +## Both-main bugs + +No confirmed defect in this scope is shared by current branch and the supplied main baseline. Each finding above is either introduced by the v2/reconciliation work or is specific to a branch-only feature. + +## Uncertainty requiring a product decision + +### Inherited fork markdown currently resolves against the active fork, not the row's owning thread + +V2 feed rows preserve `sourceThreadId` (`packages/client-runtime/src/state/threadHistoryMerge.ts:54-88`; `apps/mobile/src/lib/threadActivity.ts:1055-1077`). Inspector file navigation correctly uses that source (`apps/mobile/src/features/threads/ThreadActivityInspector.tsx:84-105`), and the web inspector fix does the same (`apps/web/src/components/chat/V2ItemInspector.tsx:132-142`). Regular timeline markdown instead receives the active route thread on web (`apps/web/src/components/chat/MessagesTimeline.tsx:684-712`, `:1590-1613`) and the active screen thread on mobile (`apps/mobile/src/features/threads/ThreadFeed.tsx:2301-2340`, `:2342-2390`). Proposed-plan timeline rows also pass only the active route thread (`apps/web/src/components/chat/MessagesTimeline.tsx:1711-1726`). + +This may be intentional: a fork's continuation starts from the same workspace and users may expect inherited file links to open in the current checkout. It may instead violate the prior "owning environment/thread" rule when source and fork worktrees diverge. Main v1 has no equivalent projected inherited-row model, so there is no clean parity oracle. Before changing it, decide whether inherited message/plan markdown denotes historical source state or current-fork state, then add a behavioral fork test that opens a workspace file after the two worktrees diverge and verifies the selected thread/resource. + +## Requested latest-main follow-up + +All six requested commits are ancestors of the audited HEAD. + +| Main change | Current source result | Test coverage | +| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `f14f41b894` composer draft preservation during worktree setup | **Retained.** Promotion cleanup moves the draft to the canonical scoped thread instead of revoking it (`apps/web/src/composerDraftStore.ts:1586-1618`, `:2794-2805`). This includes text entered after setup starts. | Direct store tests cover edits made during promotion and finalization without a pre-mark (`apps/web/src/composerDraftStore.test.ts:1461-1485`). Passed in the follow-up run below. | +| `5392c9bb99` sticky model selections | **Retained.** A user model pick updates both the current draft and sticky selection (`apps/web/src/components/ChatView.tsx:7096-7102`). Both existing and fresh new-thread paths seed sticky state before project/carried overrides (`apps/web/src/hooks/useHandleNewThread.ts:263-280`, `:395-414`). Web and mobile retain only explicitly selected provider options (`apps/web/src/components/chat/composerProviderState.tsx:82-100`, `apps/mobile/src/lib/modelOptions.ts:42-61`, `packages/shared/src/model.ts:246-258`). | Web draft-store, web provider-state, mobile model-options, and shared model tests passed. No gap found in the audited call paths. | +| `a19f01fc19` opt-in context meter | **Retained.** The client setting defaults to false (`packages/contracts/src/settings.ts:270-276`), Settings exposes the opt-in (`apps/web/src/components/settings/SettingsPanels.tsx:1896-1908`), and the composer passes context usage to its primary actions only when enabled (`apps/web/src/components/chat/ChatComposer.tsx:4423-4427`). | Contract decoding and explicit opt-in tests at `packages/contracts/src/settings.test.ts:203-212` passed. No source gap found. | +| `e7deb2aaf4` inline citations | **Retained.** Chat route state resolves only citations owned by the active environment/thread (`apps/web/src/components/ChatView.tsx:1470-1481`), selected assistant text enters the composer through `citeAssistantText` (`:1531-1545`), and v2 assistant rows remain wrapped in `AssistantCitationSource` (`apps/web/src/components/chat/MessagesTimeline.tsx:1590-1614`). Mobile preserves the intended readable-text fallback (`apps/mobile/src/features/threads/ThreadFeed.tsx:1618-1622`). | The assistant-citation lifecycle suite and composer draft persistence tests passed. No v2-specific source gap found. | +| `fc53b27303` sidebar visibility leases | **Retained, with a test gap.** The lease uses the sidebar scroll viewport plus 160 px overscan and keeps active rows leased (`apps/web/src/components/Sidebar.logic.ts:20-64`). Default sidebar rows and search results gate VCS subscriptions with it (`apps/web/src/components/Sidebar.tsx:790-809`, `:1624-1637`); the legacy sidebar gates both VCS and linked-PR subscriptions (`apps/web/src/components/LegacySidebar.tsx:381-423`, `:464-477`). Client-runtime keeps short idle grace periods (`packages/client-runtime/src/state/vcs.ts:32-36`, `packages/client-runtime/src/state/pullRequests.ts:35-47`). | `Sidebar.logic.test.ts` passed, but it does not exercise `useSidebarRowSubscriptionLease` or subscription release after an intersection change. That remains a focused behavior-test gap, not a source regression. | +| `0e1570bde5` hosted explicit project defaults | **Retained, with a test gap.** Project Settings reads providers and option settings from the representative project's environment, not the absent hosted primary (`apps/web/src/components/settings/ProjectSettingsPanel.tsx:293-307`, `:424-452`). The explicit selection fans out through environment-scoped project updates to every logical-project member (`:366-400`, `:450-452`, `:860-892`). Primary-only server settings separately go inert on the hosted app (`apps/web/src/hooks/useSettings.ts:321-333`, `apps/web/src/components/settings/settingsLayout.tsx:166-217`). | Hosted-app detection tests passed, but there is no focused Project Settings behavior test proving that a hosted remote environment's providers populate the default-model picker and that selection dispatches to the correct environment members. Source routing is intact. | + +## Final bounded file/media coverage + +This pass traced each named main change into its current v2 caller; unchanged leaf utilities were not treated as parity evidence by themselves. No additional tests were run for this final pass, as requested. + +| Main change | Current v2 caller result | +| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `#8237` (`86c9a9288b`) mobile file/share receive | **Partial.** The native share presentation reaches the New Task sheet (`apps/mobile/src/Stack.tsx:368-389`), the selected environment owns capability filtering and draft merge (`apps/mobile/src/features/threads/NewTaskDraftScreen.tsx:521-644`), and manual file picks reach the same draft (`:809-835`). Submission carries the attachments through environment-scoped preparation into v2 `thread.turn.start` (`:963-977`; `apps/mobile/src/features/threads/use-project-actions.ts:66-134`; `apps/mobile/src/lib/projectThreadStartTurn.ts:37-87`). Acquisition and delivery are retained; generic received files are hidden after delivery by the already-reported `ThreadFeed.tsx:1624-1626` filter. | +| `#8978` (`9bc7a56848`) upload while composing | **Partial.** The root worker remains mounted outside composers (`apps/mobile/src/Stack.tsx:353-360`), keys transfers by environment and attachment, and updates only drafts that still own the file (`apps/mobile/src/state/composer-attachment-uploads.ts:50-125`; `apps/mobile/src/lib/composerAttachmentUploadQueue.ts:16-78`). Existing and new-task composers block connected sends until uploads are ready (`apps/mobile/src/features/threads/ThreadComposer.tsx:377-385`; `NewTaskDraftScreen.tsx:881-888`, `:1038-1048`), and v2 consumes the uploaded references. Upload/delivery is retained; post-send generic-file visibility is partial only because of the existing attachment-filter finding. | +| `#8914` (`746c932e16`) defer draft navigation | **Retained.** Successful v2 creation clears the draft, records a replacement action, and waits until the share/submission removal guard drops before dispatching it on the next frame (`apps/mobile/src/features/threads/NewTaskDraftScreen.tsx:331-347`, `:963-1020`). Failure returns without navigation or draft clearing (`:991-999`). | +| `#8614` (`352710d497`) offline iPhone voice | **Retained.** Both real composers use the local voice controller and commit transcription through their existing draft setters (`apps/mobile/src/features/threads/ThreadComposer.tsx:349-385`; `NewTaskDraftScreen.tsx:318-347`). The controller snapshots owner/text/selection and blocks send while busy (`apps/mobile/src/features/voice-input/useVoiceInputController.ts:63-126`, `:199-216`); the iOS adapter prepares and transcribes on-device (`apps/mobile/src/native/voiceTranscription.ios.ts:36-97`). Its output therefore follows the normal online or outbox-backed v2 send path without a provider dependency. | +| `#9140` (`f46a709ee4`) external Markdown/HTML/PDF | **Retained.** Web assistant rows pass the active v2 thread and workspace to `ChatMarkdown` (`apps/web/src/components/chat/MessagesTimeline.tsx:1590-1614`), which routes outside-workspace non-media files into the scoped file panel and HTML/PDF into preview (`apps/web/src/components/ChatMarkdown.tsx:2313-2358`). Mobile link handling preserves absolute paths and scopes host PDF/media resources to the active environment/thread (`apps/mobile/src/features/threads/ThreadFeed.tsx:2250-2340`; `apps/mobile/src/features/files/filePath.ts:13-48`). Host text remains read-only in the viewers. The inherited-fork ownership question remains the separate uncertainty above. | +| `#9143` (`d937e30759`) web viewer | **Retained.** The v2 right-panel surface supplies the active project environment, workspace, and thread to a stable `FilePreviewPanel` instance (`apps/web/src/components/ChatView.tsx:7287-7311`). The panel chooses video/image/HTML/PDF/Markdown/source modes, uses a sandbox for HTML, and keeps host files read-only (`apps/web/src/components/files/FilePreviewPanel.tsx:200-315`, `:947-999`, `:1159-1248`). | +| `#9023` (`beae2147a94`) host-file/video streaming | **Partial across clients.** Web/desktop v2 media resolves signed resources against the row's thread environment (`apps/web/src/components/ChatMarkdown.tsx:2016-2057`, `:2611-2693`), and Electron permits streaming plus custom-scheme media (`apps/desktop/src/electron/ElectronProtocol.ts:85-94`, `:112-134`). Mobile's scoped Markdown and file-route resource builders remain (`apps/mobile/src/features/threads/ThreadFeed.tsx:2286-2390`; `apps/mobile/src/features/files/workspaceFileAssetUrl.ts:21-40`). The file route and Android Markdown caller still reach them. The active iOS assistant caller omits `renderImage`, however, so workspace/host images and image-syntax videos fall back to a direct URI instead of these builders (`apps/mobile/src/features/threads/ThreadFeed.tsx:1755-1772`; `apps/mobile/modules/t3-markdown-text/src/NativeMarkdownBlock.ios.tsx:380-422`). Video/generic message attachments are separately blocked by the already-reported image-only filter. Both mobile losses share existing findings rather than adding another one. | +| `#8630` (`d2042d288e`) stale writes on close | **Retained.** Both editable source and rendered task-list surfaces use the coordinator (`apps/web/src/components/files/FilePreviewPanel.tsx:553-581`, `:610-624`, `:874-899`). Unmount/close disposes it, clears the debounce, and flushes the latest revision; if a save was already in flight, completion immediately persists the newer revision (`apps/web/src/components/files/fileSaveCoordinator.ts:21-34`, `:50-77`). The active v2 file panel unmounts through the right-panel branch at `apps/web/src/components/ChatView.tsx:7287-7313`. | +| `#8968` (`f2a914b858`) panel state during refresh | **Retained.** Workspace mutations refresh data without changing the file-panel key (`apps/web/src/components/ChatView.tsx:7287-7311`). The file tree batches path deltas rather than resetting its model and suppresses replayed reveals (`apps/web/src/components/files/FileBrowserPanel.tsx:274-353`). Diff refreshes keep stable identity keys and loader callbacks while content versions change (`apps/web/src/components/DiffPanel.tsx:280-326`, `:403-435`, `:919-970`; `apps/web/src/components/diffs/AnnotatableCodeView.tsx:126-167`). This preserves expansion, search, selection, collapse, and scroll state across refresh. | +| `#8584` (`c1e70b5f8`) Codex citations/artifact templates | **Partial; new finding above.** The shared parser/template prompt helpers remain (`packages/client-runtime/src/codexMarkdownDirectives.ts:187-215`, `:308-358`; `packages/client-runtime/src/codexArtifactTemplates.ts:97-127`). Web's real v2 row still renders citations/templates and appends a chosen template to the current composer (`apps/web/src/components/chat/MessagesTimeline.tsx:1590-1614`; `apps/web/src/components/ChatView.tsx:3229-3247`). Mobile retains the adapter component but the active v2 assistant row and real screen no longer call or configure it (`apps/mobile/src/features/threads/ThreadFeed.tsx:969-1016`, `:1755-1772`; `apps/mobile/src/features/threads/ThreadDetailScreen.tsx:683-715`). | + +## Feature coverage and prior-fix retention + +| Area | Web / desktop | Mobile | Result | +| ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | +| Persistent feedback placement and duplicate guards | Feedback rows are passed as anchored messages (`apps/web/src/components/ChatView.tsx:2936-2954`) and inserted before the first later timestamp (`apps/web/src/session-logic.ts:761-777`); direct in-flight guard at `ChatView.tsx:5874`, `:6024`, `:6055` | Equivalent anchored insertion at `apps/mobile/src/lib/threadActivity.ts:1113-1122`; mobile calls the shared guard at `apps/mobile/src/state/use-thread-composer-state.ts:257-258`, implemented in `packages/client-runtime/src/state/threadFeedback.ts:35-42` | Retained | +| Effective plan-mode dispatch | Disabled plan mode forces `default` (`apps/web/src/components/ChatView.logic.ts:69-76`); the same effective value is persisted and dispatched (`ChatView.tsx:6380-6454`) | Mobile uses its existing explicit interaction-mode flow; no contradictory v2 override found | Retained | +| Markdown workspace images, Windows paths, owning environment | `threadRef.environmentId` wins at `apps/web/src/components/ChatMarkdown.tsx:2016`; normalized file/image resolution and workspace assets remain at `:2099-2140`, `:2618-2690`; inspector and plan callers pass ownership at `V2ItemInspector.tsx:132-142` and `ProposedPlanCard.tsx:175-188` | Workspace links/images use the screen environment and thread; inspector activity links retain projected source ownership | Retained for direct/current rows; inherited-row semantics noted above | +| File-chip editor/reveal/modifier behavior | File chips retain panel/editor/reveal actions and modifier routing in `apps/web/src/components/ChatMarkdown.tsx:1604-1949`, `:2256-2358` | Native file navigation/preview paths remain reachable for markdown links | Retained | +| Pull-request open/link/unlink | PR resolution filters projects to the thread environment and metadata updates use that scoped thread (`apps/web/src/components/ChatMarkdown.tsx:2145-2192`); context-menu link/unlink failure reporting remains at `:2495-2555` | No matching mobile PR-link mutation entrypoint in the audited changes | Retained where applicable | +| Unsettled sorting | Shared sort key uses max of created/updated/unsettled timestamps (`packages/client-runtime/src/state/threadSort.ts:72-88`); web and mobile consume it from `Sidebar.logic.ts:668-686` and `threadListV2.ts:192-213` | Same shared rule | Retained | +| Mobile title/header/native back patch | N/A | `CompactBrandTitle.tsx:63-70` clears stale native left items; home/sidebar header option versions include width/native item dependencies (`features/home/HomeRouteScreen.tsx:140-155`, `features/threads/ThreadNavigationSidebar.tsx:1087-1144`); `patches/react-native-screens@4.26.2.patch` remains installed via the lockfile | Retained | +| Project-picker containment | `apps/web/src/components/Sidebar.tsx:3549-3616` uses the contained combobox; popup root has `min-w-0` and `overflow-hidden` at `apps/web/src/components/ui/combobox.tsx:171-184` | N/A | Retained | +| Failed tool summaries / grouped activity | Grouping preserves failure state and final-call failure presentation in `apps/web/src/components/chat/MessagesTimeline.logic.ts:907-994` | Group construction keeps failed/severe items visible in `apps/mobile/src/lib/threadActivity.ts:798-917` | Retained | +| Composer/stash attachment ownership and duplicate protection | Stash restores only in the owning environment and validates uploads before consuming the entry (`apps/web/src/components/chat/ChatComposer.tsx:2433-2502`); normal send attachment caps/dedup remain. Queued-edit generic files are the exception reported above | Existing mobile draft/composer paths remain environment scoped | Mostly retained; one confirmed queue-edit loss | +| Queue actions across environments | Web queue commands use explicit `environmentId` + `threadId` (`QueuedRunsControl.tsx:44-60`); mobile does the same (`ThreadQueueControl.tsx:18-72`) | Scoped correctly | Retained | +| Timeline/activity/working-thinking, rounds 17–20 | Recent reconciliation paths and their focused logic tests were inspected; no additional semantic regression confirmed | Recent feed/group/header changes inspected; non-image attachment filtering and the bypassed Codex directive renderer are confirmed regressions | Two confirmed mobile regressions | + +## Verification + +Focused existing tests: + +```text +vp test run packages/client-runtime/src/state/threadFeedback.test.ts \ + apps/web/src/components/ChatView.logic.test.ts \ + apps/web/src/session-logic.test.ts \ + apps/web/src/components/chat/MessagesTimeline.logic.test.ts \ + apps/mobile/src/lib/threadActivity.test.ts \ + apps/mobile/src/features/threads/threadListV2.test.ts \ + apps/web/src/components/ChatMarkdown.workspace-images.test.tsx \ + apps/web/src/components/chat/QueuedRunsControl.test.tsx + +8 test files passed; 241 tests passed. +``` + +Follow-up targeted tests: + +```text +vp test run apps/web/src/composerDraftStore.test.ts \ + apps/web/src/components/chat/composerProviderState.test.tsx \ + apps/mobile/src/lib/modelOptions.test.ts \ + packages/shared/src/model.test.ts \ + packages/contracts/src/settings.test.ts \ + apps/web/src/components/chat/AssistantCitationSource.test.ts \ + apps/web/src/components/Sidebar.logic.test.ts \ + apps/web/src/hostedPairing.test.ts + +8 test files passed; 358 tests passed. +``` + +The green suites do not cover the missing-config sidebar render, generic-file queued edit, mobile non-image attachment rendering, the mobile specialized-Markdown caller regression including iOS media, visibility-lease intersection behavior, or hosted Project Settings behavior. They were not rerun during the final bounded file/media pass. React Doctor's review criteria were applied during the source review; its network-installed CLI was not run because this audit made no React edits and the user requested avoiding broad/network-heavy tooling without clear value. No browser or real-client integration pass was run, per instruction. diff --git a/audits/orchestrator-v2/2026-09-02/cross-cutting.md b/audits/orchestrator-v2/2026-09-02/cross-cutting.md new file mode 100644 index 000000000000..dc49dcc84d6e --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/cross-cutting.md @@ -0,0 +1,44 @@ +Current-branch cross-cutting review, 2026-09-02 + +Frozen branch: `d2f1f511f4cc833bc930d6c355cd0f9b61e835a0`. Main: `57a66608b918d673eeec7e6c94ea5906b756fcd0`. Read-only product review; all files in this directory are uncommitted audit artifacts. + +**Confirmed missed port: automatic title retries (P2).** Main `fc262f1a28` (#8087) retries `generateThreadTitle` twice using exponential backoff. The v2 replacement calls `generateThreadTitle` once (`apps/server/src/orchestration-v2/ThreadTitleRegenerationService.ts:223`) and catches non-interruption failures as a successful completion (`:236`). It then clears the title marker (`:249`); the effect worker sees success and cannot retry. Initial generation is only armed when a `titleSeed` arrives with no existing messages (`Orchestrator.ts:2915`). A transient typed provider error therefore leaves the fallback title until manual regeneration. This is distinct from preserving the final-failure cleanup behavior. The common `TextGeneration.ts:150` dispatcher does not add a retry. Recommendation: port bounded retry for initial titles and retain stale-request guards/final cleanup. Source trace confirms the missing retry; the existing failure test covers cleanup after one call, not recovery from a transient typed failure. + +**Explicitly deferred main feature: continue active threads after an update.** Main `5b7d72aad1` (#9167) persists continuation markers and resumes active work after server restart. Current `ServerEnvironment.ts:230` deliberately withholds `serverUpdateThreadContinuation`; `serverRuntimeStartup.ts` and `ws.ts:1647` do not implement the main marker/continuation path. The round-20 commit (`d2f1f511f4`) explicitly records that v2 recovery terminalizes runs and a v2 equivalent is still needed. Web settings and capability-gated request plumbing are present. Recommendation: make a release decision to port this or keep it deferred; do not label it an accidental conflict resolution. + +**Root source traces reviewed with the persistence reviewer.** + +| Finding | Source trace | Confirmed scope / evidence | +| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Existing v2 database upgrade after migration renumbering | The last commit shifts old 044–052 to 045–053. Effect SQL migrator skips IDs at/below the recorded maximum; new 053 unconditionally creates a table old 052 already created. | A disposable run of the real migrator reproduces startup failure at 053. Main 044's repair is also skipped. Fresh-database success is insufficient. | +| Removing a project with imported legacy threads | `ws.ts:1238` deletes v2 threads then `ProjectService.ts:350` dispatches a legacy project deletion without force. Legacy command bootstrap still reads `projection_threads`, which the importer preserves. | Source-confirmed partial deletion: legacy validation rejects after v2 thread deletions have committed. No integrated deletion was performed. | +| Project deletion from HTTP/CLI bypasses v2 lifecycle | `project/http.ts:76` and offline `cli/project.ts:457` call project deletion directly, drop `force`, and never enumerate/delete v2 threads. Live CLI uses this HTTP endpoint. | Source-confirmed orphaning for v2-only projects and ineffective force for imported projects. HTTP also drops `createWorkspaceRootIfMissing`. | +| Checkpoint baseline after an ordinary second run | `CheckpointDiffQuery.ts:154` requires a scope owned by ordinal 1. `IdAllocator.ts:295` allocates one root scope per thread; the projector upserts its owner to each new run. | Sol's real allocator/reducer probe confirms two runs produce one scope owned by run 2. The diff lookup therefore fails even with a valid baseline. Root review broadened the initial cancelled-first-run finding to ordinary multi-run threads. | +| Diff query reads full transcript | Main #8988/#8992 uses narrow checkpoint context; v2 `CheckpointDiffQuery.ts:102` calls full `getThreadProjection`. | Source confirms an unbounded read/decode of unrelated messages/tool bodies and ancestor histories; no latency or memory benchmark was run. | + +The persistence report also confirms that a stale failure can defeat a later snooze, and that startup recovery reads full projections of every active and archived thread. Root rejected the proposed "both settlement settings disabled" early return: a closed PR still intentionally settles under both main and v2, even with those two settings off. Skipping the lookup would change that behavior. + +**Source paths checked for retained behavior.** + +| Area | Current result / evidence | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Main inclusion | Main is the exact merge base and an ancestor: 0 main-only, 332 branch-only commits; 942 changed files. This does not prove behavior parity. | +| New-main inventory | 165 main commits since the previous comparison; 46 touch only files identical to current main, 119 touch at least one differing file. See `main-feature-file-map.tsv`; file equality is not proof the runtime calls that path. | +| Previous fixes | `prior-fixes-range-diff.txt` compares all 41 previous fix/review commits with the 38 rebased equivalents. Most backend fixes are exact patches; changed/dropped client patches are assigned explicit client review. | +| Upgrade protocol / remote compatibility | Protocol-2 descriptor and socket gating remain. `httpCors.ts` still permits the orchestration protocol header. Current WS and client compatibility tests pass. Older clients/servers are intentionally incompatible. | +| Remote cookie isolation | Main #8085 identity initialization and auth dependency wiring survive in `ServerEnvironment.ts`, `server.ts`; `auth/EnvironmentAuth.ts` and HTTP handling retain main code. | +| Relay credentials | Main #9178 credential refresh files are unchanged from main; no new discrepancy identified. | +| Long HTTP thread IDs | Main #8898 `HTTP_ROUTER_CONFIG.maxParamLength = 512` and its use by `HttpRouter.serve` remain in `server.ts:126` and `:688`. | +| Local-only worktree bases | Main #8751's remote-branch existence check is ported into `ThreadLaunchService.ts:242-286`; V2 falls back to the local base when the requested origin branch is absent. | +| Service launcher packaging | `apps/server/package.json` retains main's dual bundle command including `src/service-launcher.ts`. | +| Remote desktop update | Current server descriptor/RPC/auth support remains; server continuation is separately withheld as noted above. No desktop runtime test was performed. | +| Attachment cleanup transaction ordering | Main #7941 defers cleanup until after commit. V2 encodes deletion cleanup in its outbox: `Orchestrator.ts:1971`, `EventSink.ts:397` transaction commits event/projection/effect together, then notifies workers at `:447`; cleanup runs through `EffectWorker.ts:285` and `ResourceCleanupService.ts:48`. No v2 pre-commit deletion found on this path. | +| Pending uploads | Copy-claim behavior retains retry source and releases failed claims; focused AttachmentClaims and attachment-store tests pass. | +| Main PR-title prompt fix | #9191 TextGenerationPrompts source/tests are identical to main and invoked by the retained text-generation layer; focused tests pass. | +| Billing / usage collection | Pricing and transcript/cache readers for #8806, #9024, #8540 are identical to main. In-run provider usage is reviewed separately by the provider/persistence children. | +| Auth scopes | Every renamed v2 RPC and new project/assets/scheduler RPC remains explicitly classified; no removed main scope boundary found. | +| Legacy transcript and portable handoff limits | Current user/internal docs still describe lost legacy rich history/fresh sessions and the 32,000-character migration budget versus 240-character per-item portable summaries. These are retained architectural tradeoffs from the earlier audit. | + +**Final cross-boundary checks.** Root traced a second path around the HTTP history budget and asked the provider reviewer to validate it through both current clients. F16 is confirmed: an unavailable cold HTTP loader, or a warm reconnect above the replay limits, reaches `ws.ts:860`'s full snapshot and resets progressive-history metadata. Healthy cold opens remain bounded. Root also reviewed the mobile assistant-renderer gap with the client reviewer: bypassing `AssistantMarkdownContent` loses both Codex directive actions and iOS environment-aware inline media (F17). These are concrete caller gaps despite the retained helper implementations. + +**Root validation.** `root-server-tests.log`: 6 files, 38 tests passed. `root-compatibility-tests.log`: 1 file, 3 passed. `root-title-cli-tests.log`: 3 files, 35 passed. `root-usage-tests.log`: 3 files, 29 passed. `root-awareness-tests.log`: 1 file, 4 passed. `root-core-tests.log`: 3 files, 12 passed (delegated completion, context handoff, and schedule calculation). Total: 17 file executions, 121 tests passed. The existing tests do not cover populated-project CLI removal or upgraded v2 migration IDs; the separate Sol upgrade probe supplies the migration evidence. No product code changes, repo-wide checks, browsers, live providers, or dev servers. diff --git a/audits/orchestrator-v2/2026-09-02/main-feature-file-map.tsv b/audits/orchestrator-v2/2026-09-02/main-feature-file-map.tsv new file mode 100644 index 000000000000..ee2f73d1befc --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/main-feature-file-map.tsv @@ -0,0 +1,166 @@ +main_commit main_feature_or_fix comparison files_at_commit same_as_current_main different_from_current_main files_needing_behavior_review files_identical_to_current_main +57a66608b918d673eeec7e6c94ea5906b756fcd0 fix(pull-requests): align checkout control with author (#9196) identical-final-files 1 1 0 apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx +6e3bac3722d19b2e2cb736c2e789568eaf151032 fix(web): prevent connection rows from wrapping during removal (#8706) identical-final-files 1 1 0 apps/web/src/components/settings/ConnectionsSettings.tsx +6effe0a2fab1bcd48315485b580419377451c757 feat(web): redesign provider editor and models list (#8508) review-v2-path 7 6 1 apps/web/src/components/settings/ProviderInstanceCard.tsx apps/web/src/components/settings/ProviderAccentColorPicker.tsx; apps/web/src/components/settings/ProviderModelsSection.test.ts; apps/web/src/components/settings/ProviderModelsSection.tsx; apps/web/src/components/settings/ProviderSettingsForm.tsx; apps/web/src/components/settings/ProviderSettingsPanel.environment.test.tsx; apps/web/src/components/settings/ProviderSettingsPanel.tsx +bc918e74ace5dbb4fe1ce73b59d06a9ca1be9ed3 fix(server): discover project skills for Claude (#9210) review-v2-path 1 0 1 apps/server/src/provider/Drivers/ClaudeDriver.ts +70cd258d8aac43ea57494527b00bf36de3efa6c0 fix(web): prevent two-digit list markers from being clipped (#9101) review-v2-path 3 2 1 apps/web/src/index.css apps/web/src/components/ChatMarkdown.test.tsx; apps/web/src/components/ChatMarkdown.tsx +f14f41b894448298a86865c9114e6700245356e7 fix(web): preserve composer draft during worktree setup (#9197) review-v2-path 2 1 1 apps/web/src/composerDraftStore.ts apps/web/src/composerDraftStore.test.ts +7e9d5a7efa70f92f91d960a4f50243ba44d805da fix(mobile): prevent message and composer overlap (#9195) review-v2-path 4 2 2 apps/mobile/src/features/threads/ThreadComposer.tsx; apps/mobile/src/features/threads/ThreadFeed.tsx apps/mobile/src/lib/wideMarkdownBlocks.test.ts; apps/mobile/src/lib/wideMarkdownBlocks.ts +5b7d72aad14ed37e8e5e4c02a6d49814bfe528ac feat(updates): continue active threads across server restarts (#9167) review-v2-path 26 6 20 apps/desktop/src/settings/DesktopClientSettings.test.ts; apps/server/src/environment/ServerEnvironment.test.ts; apps/server/src/environment/ServerEnvironment.ts; apps/server/src/provider/Layers/CodexAdapter.ts; apps/server/src/provider/Layers/ProviderService.test.ts; apps/server/src/provider/Layers/ProviderService.ts; apps/server/src/provider/Services/ProviderAdapter.ts; apps/server/src/server.test.ts; apps/server/src/serverRuntimeStartup.reconcile.test.ts; apps/server/src/serverRuntimeStartup.ts; apps/server/src/ws.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/settings/SettingsPanels.tsx; apps/web/src/components/settings/settingsSearch.ts; apps/web/src/versionSkew.ts; docs/user/updating.md; packages/contracts/src/environment.ts; packages/contracts/src/provider.ts; packages/contracts/src/server.ts; packages/contracts/src/settings.ts apps/server/src/cloud/selfUpdate.test.ts; apps/server/src/cloud/selfUpdate.ts; apps/server/src/desktopUpdate/DesktopAppUpdate.ts; apps/web/src/components/ServerUpdateAction.test.tsx; apps/web/src/components/ServerUpdateAction.tsx; apps/web/src/components/settings/ConnectionsSettings.tsx +14f15cfed48bc7519e8e5eeac03f483f4b11ef3a fix(server): stop titling linked PR threads from local git history (#9191) identical-final-files 2 2 0 apps/server/src/textGeneration/TextGenerationPrompts.test.ts; apps/server/src/textGeneration/TextGenerationPrompts.ts +dd6879ffea24da9fc16cb62d7d6072d2c5b2bae3 fix(pull-requests): reuse github api reads (#9176) review-v2-path 25 17 8 apps/server/src/auth/RpcAuthorization.ts; apps/server/src/orchestration/ThreadSettlementReactor.test.ts; apps/server/src/orchestration/ThreadSettlementReactor.ts; apps/server/src/server.test.ts; apps/server/src/server.ts; apps/server/src/ws.ts; apps/web/src/routes/_chat.pull-requests.tsx; packages/contracts/src/rpc.ts apps/mobile/src/state/use-thread-pr.ts; apps/server/src/pullRequest/GitHubPullRequestCli.test.ts; apps/server/src/pullRequest/GitHubPullRequestCli.ts; apps/server/src/pullRequest/GitHubPullRequestProvider.test.ts; apps/server/src/pullRequest/GitHubPullRequestProvider.ts; apps/server/src/pullRequest/PullRequestProvider.ts; apps/server/src/pullRequest/PullRequestService.test.ts; apps/server/src/pullRequest/PullRequestService.ts; apps/server/src/sourceControl/GitHubCli.test.ts; apps/server/src/sourceControl/GitHubCli.ts; apps/server/src/sourceControl/GitHubSourceControlProvider.ts; apps/server/src/vcs/VcsProcess.test.ts; apps/server/src/vcs/VcsProcess.ts; apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx; apps/web/src/state/pullRequests.ts; packages/client-runtime/src/state/pullRequests.ts; packages/contracts/src/pullRequest.ts +9e646ad84c9d5008187eabf479e85619df9de8ca fix(connect): refresh relay credentials before expiry (#9178) review-v2-path 8 7 1 packages/client-runtime/src/connection/resolver.test.ts packages/client-runtime/src/authorization/service.ts; packages/client-runtime/src/connection/model.ts; packages/client-runtime/src/connection/supervisor.test.ts; packages/client-runtime/src/connection/supervisor.ts; packages/client-runtime/src/state/pullRequestDiffHttp.test.ts; packages/client-runtime/src/state/pullRequestDiffHttp.ts; packages/client-runtime/src/state/pullRequests.ts +a19f01fc19d209d9962c4bb66372ed9e03e320a9 feat(web): make context window indicator opt-in (#9190) review-v2-path 6 0 6 apps/desktop/src/settings/DesktopClientSettings.test.ts; apps/web/src/components/chat/ChatComposer.tsx; apps/web/src/components/settings/SettingsPanels.tsx; apps/web/src/components/settings/settingsSearch.ts; packages/contracts/src/settings.test.ts; packages/contracts/src/settings.ts +6ff537f03c4df500da7283c0566fe6f8feca709b fix(web): remove projects with archived threads (#8798) review-v2-path 2 1 1 apps/web/src/components/LegacySidebar.tsx apps/web/src/components/settings/ProjectSettingsPanel.tsx +a81a52afbb4e03ba82b2743801772151ed8c7d70 fix(server): allow local-only worktree bases (#8751) review-v2-path 6 0 6 apps/server/src/git/GitWorkflowService.ts; apps/server/src/server.test.ts; apps/server/src/vcs/GitVcsDriver.ts; apps/server/src/vcs/GitVcsDriverCore.test.ts; apps/server/src/vcs/GitVcsDriverCore.ts; apps/server/src/ws.ts +a56b0cd7178dfef299aa49b26773a80a34abe205 fix(server): allow large Azure DevOps PR lists (#8572) identical-final-files 4 4 0 apps/server/src/pullRequest/AzureDevOpsPullRequestCli.test.ts; apps/server/src/pullRequest/AzureDevOpsPullRequestCli.ts; apps/server/src/sourceControl/AzureDevOpsCli.test.ts; apps/server/src/sourceControl/AzureDevOpsCli.ts +4116db9807cb37b49d3db35c7a45301f5e851b01 fix(server): bound OpenCode version probes (#8750) identical-final-files 3 3 0 apps/server/src/provider/Layers/OpenCodeProvider.test.ts; apps/server/src/provider/Layers/OpenCodeProvider.ts; apps/server/src/provider/opencodeRuntime.ts +d2042d288eaf7aaf7feda85eb7d1a6f546302c12 fix(web): avoid stale file writes on close (#8630) identical-final-files 2 2 0 apps/web/src/components/files/fileSaveCoordinator.test.ts; apps/web/src/components/files/fileSaveCoordinator.ts +7a8df3338f910cd18543cd3ea98b8b10385e8dcd fix(desktop): skip cached monitor compiler check (#9184) identical-final-files 3 3 0 docs/internals/scripts.md; scripts/build-desktop-artifact.test.ts; scripts/build-desktop-artifact.ts +827345a07a3d2348abc63e5215e57184024078d8 fix(web): model info button opens its details on click (#9177) identical-final-files 1 1 0 apps/web/src/components/settings/ProviderModelsSection.tsx +5392c9bb99c4be1f1c3fd78743df62885fd214dd fix(models): restore sticky new-thread selections (#9164) review-v2-path 17 6 11 apps/mobile/src/lib/modelOptions.ts; apps/server/src/cli/project.ts; apps/server/src/orchestration/decider.ts; apps/server/src/persistence/Migrations.ts; apps/server/src/serverRuntimeStartup.test.ts; apps/server/src/serverRuntimeStartup.ts; apps/web/src/components/CommandPalette.tsx; docs/user/composer.md; packages/contracts/src/orchestration.ts; packages/shared/src/model.test.ts; packages/shared/src/model.ts apps/mobile/src/lib/modelOptions.test.ts; apps/server/src/orchestration/decider.projectThreadEnvMode.test.ts; apps/server/src/persistence/Migrations/016_CanonicalizeModelSelections.test.ts; apps/server/src/persistence/Migrations/044_ClearAutomaticProjectModelDefaults.ts; apps/web/src/components/chat/composerProviderState.test.tsx; apps/web/src/components/chat/composerProviderState.tsx +535c83dea5025e49df12df4a14b4d1dfb7d373ce fix(web): copying a code block no longer copies triple backticks (#8448) identical-final-files 2 2 0 apps/web/src/markdown-clipboard.test.ts; apps/web/src/markdown-clipboard.ts +f9d1c65d475807f70d29deff71b16a922a61c4c0 chore: bump vendored GhosttyKit and update terminal integration (#9155) identical-final-files 31 31 0 apps/mobile/modules/t3-terminal/README.md; apps/mobile/modules/t3-terminal/THIRD_PARTY_NOTICES.md; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty/vt.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty/vt/allocator.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty/vt/color.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty/vt/key.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty/vt/key/encoder.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty/vt/key/event.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty/vt/osc.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty/vt/paste.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty/vt/result.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty/vt/sgr.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/Headers/ghostty/vt/wasm.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64-simulator/libghostty-fat.a; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty/vt.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty/vt/allocator.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty/vt/color.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty/vt/key.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty/vt/key/encoder.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty/vt/key/event.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty/vt/osc.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty/vt/paste.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty/vt/result.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty/vt/sgr.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/Headers/ghostty/vt/wasm.h; apps/mobile/modules/t3-terminal/Vendor/libghostty/GhosttyKit.xcframework/ios-arm64/libghostty-fat.a; apps/mobile/modules/t3-terminal/Vendor/libghostty/VERSION; apps/mobile/modules/t3-terminal/ios/T3TerminalView.swift; apps/mobile/modules/t3-terminal/scripts/build-libghostty-ios16.sh +0681d854994ec0ceed0562ae74549ccf8ef2ec41 fix(pull-requests): expand code tab diffs by default (#9174) identical-final-files 2 2 0 apps/web/src/components/pullRequest/pullRequestDiff.logic.test.ts; apps/web/src/components/pullRequest/pullRequestDiff.logic.ts +80a14b6588f0e856983e6d10002cde9e00e9d3e2 fix(server): discover project skills for Codex and OpenCode (#8778) review-v2-path 24 10 14 apps/server/src/orchestration/Layers/ProviderCommandReactor.ts; apps/server/src/provider/Drivers/CodexDriver.ts; apps/server/src/provider/Drivers/OpenCodeDriver.ts; apps/server/src/provider/Layers/OpenCodeAdapter.test.ts; apps/server/src/provider/Layers/ProviderRegistry.test.ts; apps/server/src/provider/Layers/ProviderRegistry.ts; apps/server/src/provider/ProviderDriver.ts; apps/server/src/provider/providerMaintenanceRunner.test.ts; apps/server/src/ws.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/ChatComposer.tsx; packages/client-runtime/src/state/server.ts; packages/contracts/src/rpc.ts; packages/contracts/src/server.ts apps/server/src/provider/Layers/CodexProvider.ts; apps/server/src/provider/Layers/OpenCodeProvider.test.ts; apps/server/src/provider/Layers/OpenCodeProvider.ts; apps/server/src/provider/OpenCodeServerOwner.test.ts; apps/server/src/provider/Services/ProviderRegistry.ts; apps/server/src/provider/opencodeRuntime.ts; apps/server/src/provider/testUtils/providerRegistryMock.ts; apps/server/src/textGeneration/OpenCodeTextGeneration.test.ts; packages/client-runtime/src/providerSkills.test.ts; packages/client-runtime/src/providerSkills.ts +082358f9ef6feaadfaafd59a7512da26beb00100 fix(desktop): check artifact build prerequisites (#8975) identical-final-files 4 4 0 CONTRIBUTING.md; docs/internals/scripts.md; scripts/build-desktop-artifact.test.ts; scripts/build-desktop-artifact.ts +43bafd4674841fb8782f5174033b684aa0d83f67 fix(web): open PR toast actions in app (#9006) review-v2-path 1 0 1 apps/web/src/components/GitActionsControl.tsx +8339508f5c244a63a845004393d7d9e701152d6e fix(chat): align failed task progress test (#9172) review-v2-path 1 0 1 apps/web/src/components/chat/MessagesTimeline.logic.test.ts +c15735dd8894f829ce396c922ce4b5a48073f05a fix(chat): replace failed tools with thinking (#9165) review-v2-path 2 0 2 apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.logic.ts +133db22fae34cfb2e62a806e99d22674b0376f35 feat(web): copy the full error report from the error page (#9166) review-v2-path 1 0 1 apps/web/src/routes/__root.tsx +b520120cf169ce63a5606447a292451e97622c9a fix(chat): improve tool group summaries and scrolling (#9106) review-v2-path 27 12 15 apps/mobile/src/features/threads/ThreadFeed.tsx; apps/mobile/src/lib/threadActivity.test.ts; apps/mobile/src/lib/threadActivity.ts; apps/web/src/components/ChatView.logic.test.ts; apps/web/src/components/ChatView.logic.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.logic.ts; apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx; apps/web/src/session-logic.test.ts; apps/web/src/session-logic.ts; packages/client-runtime/package.json; packages/client-runtime/src/work-log/presentation.test.ts; packages/client-runtime/src/work-log/presentation.ts apps/mobile/src/features/threads/thread-feed-live-follow.test.ts; apps/mobile/src/features/threads/thread-feed-live-follow.ts; apps/mobile/src/features/threads/thread-work-log.tsx; apps/mobile/src/lib/layout.test.ts; apps/mobile/src/lib/layout.ts; apps/web/src/components/T3Wordmark.tsx; apps/web/src/components/sidebar/SidebarChrome.tsx; docs/user/tool-activity.md; packages/client-runtime/src/work-log/commandLabel.test.ts; packages/client-runtime/src/work-log/commandLabel.ts; packages/client-runtime/src/work-log/scrollAnchor.test.ts; packages/client-runtime/src/work-log/scrollAnchor.ts +db4bf9497b524f35e665af9e941aa8faeb05ea9e chore: remove unused code and brittle tests (#9150) review-v2-path 41 24 17 apps/server/integration/OrchestrationEngineHarness.integration.ts; apps/server/package.json; apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts; apps/server/src/provider/Layers/ProviderAdapterRegistry.test.ts; apps/server/src/provider/Layers/ProviderAdapterRegistry.ts; apps/server/src/provider/Layers/ProviderService.test.ts; apps/server/src/provider/Services/ProviderAdapterRegistry.ts; apps/server/src/provider/testUtils/providerAdapterRegistryMock.ts; apps/web/src/components/chat/ChangedFilesTree.test.tsx; apps/web/src/components/chat/ComposerPrimaryActions.test.tsx; apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/composerDraftStore.ts; apps/web/src/keybindings.ts; apps/web/src/lib/contextWindow.ts; apps/web/src/providerInstances.ts; pnpm-lock.yaml; vite.config.ts .github/workflows/release.yml; apps/desktop/src/wsl/DesktopWslEnvironment.test.ts; apps/marketing/public/apple-touch-icon.webp; apps/marketing/public/favicon-16x16.webp; apps/marketing/public/favicon-32x32.webp; apps/marketing/public/icon.png; apps/marketing/public/screenshot.webp; apps/marketing/tweets.md; apps/mobile/package.json; apps/mobile/src/features/terminal/ThreadTerminalRouteScreen.test.ts; apps/mobile/src/features/terminal/terminalRouteBootstrap.ts; apps/server/src/textGeneration/TextGeneration.ts; apps/web/src/cloud/linkEnvironment.ts; apps/web/src/components/DiffPanelShell.tsx; apps/web/src/components/ProviderUpdateLaunchNotification.logic.ts; apps/web/src/components/chat/ComposerCommandMenu.test.tsx; apps/web/src/components/chat/providerIconUtils.ts; apps/web/src/components/desktopUpdate.logic.ts; apps/web/src/composer-logic.ts; apps/web/src/lib/utils.ts; apps/web/src/portDiscoveryState.ts; apps/web/src/providerModels.ts; apps/web/src/routes/-chatIndexTitlebar.test.ts; apps/web/src/themePalette.ts +b8262b41228e03b2e1e14b701be449034349c8ba fix(desktop): hold-to-quit no longer gets stuck (#9141) identical-final-files 4 4 0 apps/desktop/src/window/DesktopWindow.test.ts; apps/desktop/src/window/DesktopWindow.ts; apps/desktop/src/window/QuitHold.test.ts; apps/desktop/src/window/QuitHold.ts +cde12790d721ab2a90471750fd75d9f5bf13f57d fix(contracts): accept legacy pull request checkout results (#8238) identical-final-files 2 2 0 packages/contracts/src/git.test.ts; packages/contracts/src/git.ts +a1a2bb1cd9f000f53fbeae752ed5c38f152eadf2 fix(web): label keybinding condition removal actions (#8664) review-v2-path 3 2 1 apps/web/src/components/settings/KeybindingsSettings.logic.test.ts apps/web/src/components/settings/KeybindingsSettings.logic.ts; apps/web/src/components/settings/KeybindingsSettings.tsx +e9db39ce05c706122bb747fd5e7e70e1aac78935 fix(web): align composer notices and stash (#8890) review-v2-path 8 5 3 apps/web/src/components/ChatView.tsx; apps/web/src/versionSkew.test.ts; apps/web/src/versionSkew.ts apps/web/src/components/ServerUpdateAction.tsx; apps/web/src/components/chat/ComposerBanner.tsx; apps/web/src/components/chat/ComposerBannerStack.tsx; apps/web/src/components/chat/ComposerStashBadge.tsx; apps/web/src/components/chat/ComposerTasksBadge.tsx +941acb4f919bcef337d4d9e1623101bdc30d3616 fix(provider): drop removed custom models from the model picker (#9075) review-v2-path 6 4 2 apps/server/src/provider/Layers/ProviderRegistry.test.ts; apps/server/src/provider/Layers/ProviderRegistry.ts apps/server/src/provider/providerStatusCache.test.ts; apps/server/src/provider/providerStatusCache.ts; apps/web/src/modelSelection.test.ts; apps/web/src/modelSelection.ts +e7deb2aaf4d4d089618dc0c8f393fa0b8b6c77e9 feat(web): cite assistant responses with inline citations (#9146) review-v2-path 49 34 15 apps/mobile/src/features/threads/ThreadFeed.tsx; apps/mobile/src/lib/projectThreadStartTurn.test.ts; apps/mobile/src/lib/projectThreadStartTurn.ts; apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts; apps/server/src/orchestration/Layers/ProviderCommandReactor.ts; apps/server/src/provider/Layers/ProviderService.test.ts; apps/server/src/provider/Layers/ProviderService.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/ChatComposer.tsx; apps/web/src/components/chat/MessagesTimeline.tsx; apps/web/src/components/chat/useAssistantCitationTarget.ts; apps/web/src/index.css; docs/user/composer.md; packages/contracts/src/index.ts; packages/shared/package.json apps/web/src/components/ChatMarkdown.tsx; apps/web/src/components/ComposerCitationNode.tsx; apps/web/src/components/ComposerPromptEditor.test.ts; apps/web/src/components/ComposerPromptEditor.tsx; apps/web/src/components/ThreadTerminalDrawer.test.ts; apps/web/src/components/ThreadTerminalDrawer.tsx; apps/web/src/components/chat/AssistantCitationChip.tsx; apps/web/src/components/chat/AssistantCitationCommentEditor.tsx; apps/web/src/components/chat/AssistantCitationSource.test.ts; apps/web/src/components/chat/AssistantCitationSource.tsx; apps/web/src/components/chat/AssistantSelectionToolbar.tsx; apps/web/src/components/chat/ComposerStashMenu.tsx; apps/web/src/components/chat/composerSubmission.test.ts; apps/web/src/components/chat/composerSubmission.ts; apps/web/src/components/composerInlineTokenPaste.ts; apps/web/src/composer-editor-mentions.test.ts; apps/web/src/composer-editor-mentions.ts; apps/web/src/composer-logic.test.ts; apps/web/src/composer-logic.ts; apps/web/src/composerDraftStore.test.ts; apps/web/src/lib/assistantCitationNavigation.test.ts; apps/web/src/lib/assistantCitationNavigation.ts; apps/web/src/lib/assistantTextSelection.test.ts; apps/web/src/lib/assistantTextSelection.ts; apps/web/src/lib/selectionActions.test.ts; apps/web/src/lib/selectionActions.ts; apps/web/src/markdown-clipboard.test.ts; apps/web/src/promptStashStore.test.ts; apps/web/src/terminal/ghostty/surface.ts; docs/internals/assistant-citations.md; docs/internals/providers.md; packages/contracts/src/assistantCitations.ts; packages/shared/src/assistantCitations.test.ts; packages/shared/src/assistantCitations.ts +2ab7973fe06eecf8b0a0d1da8481d926fca1ee1b fix(web): hide build pill in narrow sidebars (#9159) identical-final-files 1 1 0 apps/web/src/components/sidebar/SidebarChrome.tsx +9fdafdf114a88bd7309883b4578e74cbe786d04d feat(pull-requests): copy provider checkout commands (#9086) review-v2-path 9 7 2 apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts; apps/web/src/components/pullRequest/pullRequestDetail.logic.ts apps/server/src/pullRequest/BitbucketPullRequestProvider.ts; apps/server/src/pullRequest/PullRequestProvider.ts; apps/server/src/pullRequest/PullRequestService.ts; apps/server/src/pullRequest/bitbucketPullRequestJson.test.ts; apps/server/src/pullRequest/bitbucketPullRequestJson.ts; apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx; packages/contracts/src/pullRequest.ts +47a95332a2b8fe47da9fb0af97fd6f0b542a18ee fix(web): browse folders from file breadcrumbs (#8910) review-v2-path 5 4 1 apps/web/src/components/files/FilePreviewPanel.tsx apps/web/src/components/files/FileBreadcrumbs.tsx; apps/web/src/components/files/filePath.test.ts; apps/web/src/components/files/filePath.ts; apps/web/src/components/files/projectFilesQueryState.test.tsx +fea1af81fdab64a19353224d60b4efa60f929740 fix(web): compact project settings actions (#9160) identical-final-files 1 1 0 apps/web/src/components/settings/ProjectSettingsPanel.tsx +d937e30759ceae421bf3cc1b84414de4b67df76c feat(web): render HTML and PDF files in the file viewer (#9143) review-v2-path 2 0 2 apps/web/src/components/files/FilePreviewPanel.tsx; docs/user/composer.md +f46a709ee487e1e6e04423fcb7032a26eb103129 feat(files): open markdown, HTML, and PDF files outside the workspace (#9140) review-v2-path 26 18 8 apps/mobile/src/features/threads/ThreadFeed.tsx; apps/server/src/http.test.ts; apps/web/src/components/RightPanelTabs.tsx; apps/web/src/components/files/FilePreviewPanel.tsx; apps/web/src/rightPanelStore.ts; docs/user/composer.md; packages/contracts/src/assets.ts; packages/contracts/src/project.ts apps/mobile/src/features/files/ThreadFilesRouteScreen.tsx; apps/mobile/src/features/files/filePath.test.ts; apps/mobile/src/features/files/filePath.ts; apps/mobile/src/features/files/workspaceFileAssetUrl.ts; apps/server/src/assets/AssetAccess.test.ts; apps/server/src/assets/AssetAccess.ts; apps/server/src/http.ts; apps/server/src/workspace/WorkspaceFileSystem.test.ts; apps/server/src/workspace/WorkspaceFileSystem.ts; apps/web/src/browser/openFileInPreview.ts; apps/web/src/components/ChatMarkdown.tsx; apps/web/src/components/files/filePath.test.ts; apps/web/src/components/files/filePath.ts; apps/web/src/markdown-links.test.ts; apps/web/src/markdown-links.ts; apps/web/src/terminal-links.ts; docs/internals/environment-auth.md; packages/shared/src/filePreview.ts +f2a914b8588bf3038472c14b129fbc5ddb3a2992 fix(web): preserve panel state across workspace refreshes (#8968) review-v2-path 7 6 1 apps/web/src/components/DiffPanel.tsx apps/web/src/components/diffs/AnnotatableCodeView.tsx; apps/web/src/components/files/FileBrowserPanel.tsx; apps/web/src/components/files/fileTreePathReconciliation.test.ts; apps/web/src/components/files/fileTreePathReconciliation.ts; apps/web/src/lib/diffRendering.test.ts; apps/web/src/lib/diffRendering.ts +8401f4d85887786fbb773d3fd41b8f07a77624b8 fix(web): darken neutral control surfaces (#9064) review-v2-path 5 4 1 apps/web/src/index.css apps/web/src/components/chat/ComposerBanner.tsx; apps/web/src/components/chat/ComposerSurface.tsx; apps/web/src/themePalette.test.ts; apps/web/src/themePalette.ts +0e1570bde5b64458449a45989f1b56d6fd651883 fix(web): project default model works on the hosted app (#9142) review-v2-path 8 7 1 apps/web/src/components/settings/SettingsPanels.tsx apps/web/src/components/settings/IntegrationsSettings.tsx; apps/web/src/components/settings/ProjectSettingsPanel.tsx; apps/web/src/components/settings/SourceControlSettings.tsx; apps/web/src/components/settings/SourceControlWritingSettings.tsx; apps/web/src/components/settings/settingsLayout.tsx; apps/web/src/hooks/useSettings.ts; apps/web/src/hostedPairing.ts +c37fd136edf546fd58daeac146548436c1fa38c2 test(server): measure shell, second client, and reconnect transfer (#9157) review-v2-path 6 1 5 apps/server/integration/NetworkTransferMeasurement.integration.ts; apps/server/integration/OrchestrationEngineHarness.integration.ts; apps/server/integration/TransferBudgetReport.integration.ts; apps/server/integration/TransferBudgetScenario.integration.ts; apps/server/src/server.test.ts apps/server/integration/SqlStatementCounter.integration.ts +b2f25d390a8546e42eb6186115b673a53b8c38dc feat(desktop): update the desktop app on remote Macs from the Update button (#6554) review-v2-path 41 27 14 apps/server/src/auth/RpcAuthorization.ts; apps/server/src/environment/ServerEnvironment.test.ts; apps/server/src/environment/ServerEnvironment.ts; apps/server/src/server.ts; apps/server/src/ws.ts; apps/web/src/components/ChatView.tsx; apps/web/src/versionSkew.test.ts; apps/web/src/versionSkew.ts; docs/user/updating.md; packages/client-runtime/src/connection/registry.test.ts; packages/client-runtime/src/state/server.ts; packages/contracts/src/environment.ts; packages/contracts/src/rpc.ts; packages/contracts/src/server.ts apps/desktop/src/app/DesktopApp.ts; apps/desktop/src/app/DesktopLifecycle.test.ts; apps/desktop/src/app/DesktopLifecycle.ts; apps/desktop/src/backend/DesktopBackendManager.test.ts; apps/desktop/src/backend/DesktopBackendPool.test.ts; apps/desktop/src/telemetry/DesktopTelemetryPublisher.test.ts; apps/desktop/src/telemetry/DesktopTelemetryPublisher.ts; apps/desktop/src/updates/DesktopRemoteUpdates.test.ts; apps/desktop/src/updates/DesktopRemoteUpdates.ts; apps/desktop/src/updates/DesktopUpdates.test.ts; apps/desktop/src/updates/DesktopUpdates.ts; apps/desktop/src/updates/remoteUpdateFlow.test.ts; apps/desktop/src/updates/remoteUpdateFlow.ts; apps/desktop/src/updates/updatesTestHarness.ts; apps/desktop/src/window/DesktopApplicationMenu.test.ts; apps/server/src/cloud/selfUpdate.test.ts; apps/server/src/cloud/selfUpdate.ts; apps/server/src/desktopUpdate/DesktopAppUpdate.test.ts; apps/server/src/desktopUpdate/DesktopAppUpdate.ts; apps/server/src/resourceTelemetry/DesktopTelemetryReceiver.ts; apps/web/src/components/ServerUpdateAction.test.tsx; apps/web/src/components/ServerUpdateAction.tsx; apps/web/src/components/settings/ConnectionsSettings.tsx; docs/internals/server-updates.md; packages/client-runtime/src/state/runtime.test.ts; packages/client-runtime/src/state/server.test.ts; packages/contracts/src/resourceTelemetry.ts +80c708a1fa8986bce0b2d1ba4d35e79d9e4094ba perf(web): halve the cold-start bundle by splitting Clerk and cold routes (#9058) review-v2-path 9 8 1 apps/web/src/components/AppSidebarLayout.tsx apps/web/src/components/clerk/BrowserManagedAuthShell.tsx; apps/web/src/components/clerk/ElectronManagedAuthShell.tsx; apps/web/src/components/settings/ThemeEditorHost.tsx; apps/web/src/lib/chunkReloadGuard.test.ts; apps/web/src/lib/chunkReloadGuard.ts; apps/web/src/main.tsx; apps/web/src/router.ts; apps/web/vite.config.ts +a434677eca737771dd64703545c13eb11ba92ce2 fix(grok): health check, model selection, and stop all work against the real CLI (#9154) review-v2-path 14 2 12 apps/server/scripts/acp-mock-agent.ts; apps/server/src/provider/Layers/GrokAdapter.test.ts; apps/server/src/provider/Layers/GrokAdapter.ts; apps/server/src/provider/Layers/GrokProvider.ts; apps/server/src/provider/acp/AcpRuntimeModel.ts; apps/server/src/provider/acp/AcpSessionRuntime.ts; apps/server/src/provider/acp/GrokAcpSupport.test.ts; apps/server/src/provider/acp/GrokAcpSupport.ts; apps/server/src/provider/acp/XAiAcpExtension.ts; packages/contracts/src/model.ts; packages/effect-acp/src/protocol.test.ts; packages/effect-acp/src/protocol.ts apps/server/src/provider/Layers/GrokProvider.test.ts; docs/internals/providers.md +083d4de5b0fd33efa28363546b6ed89e191c5200 fix(clients): stop repeating expanded commands (#9120) review-v2-path 11 1 10 apps/mobile/src/lib/threadActivity.test.ts; apps/mobile/src/lib/threadActivity.ts; apps/server/src/orchestration/ActivityPayloadProjection.test.ts; apps/server/src/orchestration/ActivityPayloadProjection.ts; apps/server/test/ActivityPayloadProjection.test.ts; apps/web/src/components/chat/MessagesTimeline.tsx; apps/web/src/session-logic.command-output.test.ts; apps/web/src/session-logic.ts; packages/client-runtime/src/work-log/presentation.test.ts; packages/client-runtime/src/work-log/presentation.ts apps/mobile/src/features/threads/thread-work-log.tsx +cdbf324aa043b1bc5705159127d2b55f186d1b9b fix(web): keep generated muted foreground dimmer than entered text (#9113) identical-final-files 2 2 0 apps/web/src/themePalette.test.ts; apps/web/src/themePalette.ts +d0b19b32e01d7abc8829c01353d759fed3d304ed fix(claude): preview images read from the workspace (#9119) review-v2-path 10 0 10 apps/mobile/src/lib/threadActivity.test.ts; apps/mobile/src/lib/threadActivity.ts; apps/server/src/orchestration/ActivityPayloadProjection.test.ts; apps/server/src/orchestration/ActivityPayloadProjection.ts; apps/server/src/provider/Layers/ClaudeAdapter.test.ts; apps/server/src/provider/Layers/ClaudeAdapter.ts; apps/web/src/session-logic.test.ts; apps/web/src/session-logic.ts; packages/client-runtime/src/work-log/presentation.test.ts; packages/client-runtime/src/work-log/presentation.ts +716069f40f000887cb01685099a16e19d9194307 fix(server): keep attachments until the command commits (#7941) review-v2-path 13 0 13 apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts; apps/server/src/orchestration/Layers/OrchestrationEngine.ts; apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts; apps/server/src/orchestration/Layers/ProjectionPipeline.ts; apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts; apps/server/src/orchestration/Layers/ProviderCommandReactor.ts; apps/server/src/orchestration/Services/OrchestrationEngine.ts; apps/server/src/orchestration/Services/ProjectionPipeline.ts; apps/server/src/orchestration/Services/ProviderCommandReactor.ts; apps/server/src/relay/AgentAwarenessRelay.test.ts; apps/server/src/serverRuntimeStartup.reconcile.test.ts; apps/server/src/serverRuntimeStartup.test.ts; docs/internals/overview.md +0e77fbd3d0d79eec5247e75583a04590a1785133 fix(server): prevent accidental service downgrades (#5302) identical-final-files 6 6 0 apps/server/src/cli/service.test.ts; apps/server/src/cli/service.ts; apps/server/src/cloud/bootService.test.ts; apps/server/src/cloud/bootService.ts; apps/server/src/cloud/serviceProtocol.ts; docs/user/background-service.md +8efd4e95fcb08478c9c6e8eee384bfca559f62cc fix(settings): sync auto-settle and other shared preferences across environments (#9147) review-v2-path 10 7 3 apps/web/src/components/settings/SettingsPanels.tsx; docs/internals/overview.md; packages/client-runtime/package.json apps/mobile/src/features/settings/SettingsRouteScreen.tsx; apps/web/src/components/settings/SharedSettingsMismatchAlert.tsx; apps/web/src/components/settings/SourceControlSettings.tsx; apps/web/src/hooks/useSettings.ts; docs/user/thread-sidebar.md; packages/client-runtime/src/state/sharedSettings.test.ts; packages/client-runtime/src/state/sharedSettings.ts +5014e5fcdd6e5f4a53d0fea4cbecba733821a854 fix(desktop): show newest changes in nightly previews (#9138) review-v2-path 17 15 2 docs/user/updating.md; packages/contracts/src/ipc.ts apps/desktop/src/updates/DesktopUpdates.test.ts; apps/desktop/src/updates/DesktopUpdates.ts; apps/desktop/src/updates/releaseNotes.test.ts; apps/desktop/src/updates/releaseNotes.ts; apps/desktop/src/updates/updateMachine.test.ts; apps/desktop/src/updates/updateMachine.ts; apps/web/src/components/desktopUpdate.logic.test.ts; apps/web/src/components/desktopUpdate.logic.ts; apps/web/src/components/desktopUpdate.toast.test.tsx; apps/web/src/components/desktopUpdate.toast.tsx; apps/web/src/components/sidebar/SidebarUpdatePill.test.tsx; apps/web/src/components/sidebar/SidebarUpdatePill.tsx; apps/web/src/components/sidebar/SidebarUpdateReleaseNotes.test.tsx; apps/web/src/components/sidebar/SidebarUpdateReleaseNotes.tsx; apps/web/src/state/desktopUpdate.test.ts +fc53b273039cf5e0a932582b1fbb56e7223ad4ab perf(clients): lease sidebar status by visibility (#9052) review-v2-path 6 3 3 apps/web/src/components/LegacySidebar.tsx; apps/web/src/components/Sidebar.logic.ts; apps/web/src/components/Sidebar.tsx apps/mobile/src/state/use-thread-pr.ts; packages/client-runtime/src/state/pullRequests.ts; packages/client-runtime/src/state/vcs.ts +6866fd6b5ccff82333ad4386ce68cdec03531b68 perf(client-runtime): keep turn and checkpoint refs stable while streaming (#9145) review-v2-path 2 0 2 packages/client-runtime/src/state/threadReducer.test.ts; packages/client-runtime/src/state/threadReducer.ts +7e460f429b740180cd72730418262a2df971ba54 fix(server): bound orchestration replay payloads (#8992) review-v2-path 10 0 10 apps/server/src/checkpointing/CheckpointDiffQuery.test.ts; apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts; apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts; apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts; apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts; apps/server/src/project/ProjectSetupScriptRunner.test.ts; apps/server/src/provider/Layers/ProviderSessionReaper.test.ts; apps/server/src/server.test.ts; apps/server/src/serverRuntimeStartup.test.ts; apps/server/src/ws.ts +c2283ce14628127ef1758974ddab4f5b1f89d47a perf: make streaming projection and activity appends incremental (#9152) review-v2-path 4 0 4 apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts; apps/server/src/orchestration/Layers/ProjectionPipeline.ts; packages/client-runtime/src/state/threadReducer.test.ts; packages/client-runtime/src/state/threadReducer.ts +feb3ea7ebf83de2e301adb1f20300b262773ec54 fix(web): stop highlighter freezes and worker spin by using the Oniguruma WASM engine (#8360) review-v2-path 7 4 3 apps/web/src/components/DiffPanel.tsx; apps/web/src/components/chat/MessagesTimeline.tsx; apps/web/src/components/files/FilePreviewPanel.tsx apps/web/src/components/DiffWorkerPoolProvider.tsx; apps/web/src/components/pullRequest/PullRequestCodeTab.tsx; apps/web/src/components/settings/SettingsFontPreviews.tsx; apps/web/src/lib/syntaxHighlighting.ts +ea71a19d4181ce13b0e8f374f45ba9237ee4a9ce fix(claude): skills picked from the composer now run (#9128) review-v2-path 16 12 4 apps/server/src/provider/Layers/ClaudeAdapter.test.ts; apps/server/src/provider/Layers/ClaudeAdapter.ts; docs/user/composer.md; packages/contracts/src/server.ts apps/mobile/src/features/threads/use-composer-command-menu.ts; apps/server/src/provider/Drivers/ClaudeSkillDispatch.test.ts; apps/server/src/provider/Drivers/ClaudeSkillDispatch.ts; apps/server/src/provider/Drivers/ClaudeSkills.test.ts; apps/server/src/provider/Drivers/ClaudeSkills.ts; apps/web/src/components/chat/composerSlashCommandSearch.test.ts; apps/web/src/components/chat/composerSlashCommandSearch.ts; apps/web/src/providerSkillSearch.test.ts; apps/web/src/providerSkillSearch.ts; docs/user/providers-claude.md; packages/client-runtime/src/providerSkills.test.ts; packages/client-runtime/src/providerSkills.ts +9a7b1e21e51609266adf657bcab0b43b6bcd445c perf(provider): bound persisted session lookups (#8909) review-v2-path 2 0 2 apps/server/src/provider/Layers/ProviderService.test.ts; apps/server/src/provider/Layers/ProviderService.ts +98725df00a729ba226ae8610a3488e5b9168029f fix(web): mute routine notices and update actions (#9063) review-v2-path 9 7 2 apps/web/src/components/settings/ProviderInstanceCard.tsx; apps/web/src/components/settings/SettingsPanels.tsx apps/web/src/components/ProviderUpdateEnvironmentRows.tsx; apps/web/src/components/ProviderUpdatePrimaryNotification.tsx; apps/web/src/components/ServerUpdateAction.tsx; apps/web/src/components/chat/ComposerBanner.tsx; apps/web/src/components/sidebar/DesktopUpdateStatusIcon.tsx; apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx; apps/web/src/components/sidebar/SidebarUpdatePill.tsx +08aad594f0059d28dd23914f9d37ad4e695fff75 chore: delete dead code, unused deps, and duplicate helpers (#9129) review-v2-path 103 75 28 apps/mobile/src/features/threads/threadPresentation.ts; apps/server/integration/OrchestrationEngineHarness.integration.ts; apps/server/integration/providerService.integration.test.ts; apps/server/src/bin.test.ts; apps/server/src/httpCors.ts; apps/server/src/orchestration/commandInvariants.ts; apps/server/src/persistence/Migrations.ts; apps/server/src/provider/Drivers/ClaudeDriver.ts; apps/server/src/provider/Drivers/CodexDriver.ts; apps/server/src/provider/Drivers/CursorDriver.ts; apps/server/src/provider/Drivers/GrokDriver.ts; apps/server/src/provider/Drivers/OpenCodeDriver.ts; apps/server/src/provider/Layers/ProviderRegistry.ts; apps/server/src/provider/Layers/ProviderSessionDirectory.ts; apps/server/src/provider/acp/AcpRuntimeModel.ts; apps/server/src/serverRuntimeStartup.test.ts; apps/server/src/vcs/GitVcsDriver.ts; apps/web/src/index.css; apps/web/src/state/entities.ts; package.json; packages/client-runtime/src/state/models.ts; packages/client-runtime/src/state/server.ts; packages/contracts/src/ipc.ts; packages/contracts/src/providerRuntime.ts; packages/contracts/src/settings.ts; packages/effect-codex-app-server/package.json; packages/shared/src/model.ts; pnpm-lock.yaml apps/desktop/src/preview/PickLabelPosition.ts; apps/mobile/package.json; apps/mobile/src/components/GlassSafeAreaView.tsx; apps/mobile/src/features/agent-awareness/remoteRegistration.ts; apps/mobile/src/features/cloud/managedRelayState.ts; apps/mobile/src/features/diffs/nativeReviewDiffSurface.test.ts; apps/mobile/src/features/files/ThreadFilesRouteScreen.tsx; apps/mobile/src/features/files/filePath.test.ts; apps/mobile/src/features/files/filePath.ts; apps/mobile/src/features/files/preload-workspace-file.ts; apps/mobile/src/features/review/ReviewHighlighterProvider.tsx; apps/mobile/src/features/review/diffParser.ts; apps/mobile/src/features/review/reviewCommentSelection.ts; apps/mobile/src/features/review/reviewState.ts; apps/mobile/src/features/review/shikiReviewHighlighter.ts; apps/mobile/src/features/terminal/ThreadTerminalPanel.tsx; apps/mobile/src/features/terminal/threadTerminalPanelModel.ts; apps/mobile/src/features/threads/use-composer-command-menu.test.ts; apps/mobile/src/features/threads/use-composer-command-menu.ts; apps/mobile/src/features/threads/use-legacy-plan-mode-enabled.ts; apps/mobile/src/state/auth.ts; apps/mobile/src/state/git.ts; apps/mobile/src/state/use-composer-path-search.ts; apps/server/scripts/cursor-acp-model-mismatch-probe.ts; apps/server/src/cli/config.ts; apps/server/src/cli/pair.ts; apps/server/src/cli/triage.ts; apps/server/src/cloud/bootService.ts; apps/server/src/keybindings.ts; apps/server/src/mcp/toolkits/preview/tools.ts; apps/server/src/pathExpansion.ts; apps/server/src/persistence/Layers/ProviderSessionRuntime.ts; apps/server/src/provider/Drivers/instanceIdentity.ts; apps/server/src/provider/Layers/ProviderInstanceRegistryLive.ts; apps/server/src/provider/acp/AcpCoreRuntimeEvents.ts; apps/server/src/provider/providerStatusCache.ts; apps/server/src/serverRuntimeState.ts; apps/server/src/sourceControl/AzureDevOpsSourceControlProvider.test.ts; apps/server/src/sourceControl/BitbucketSourceControlProvider.test.ts; apps/server/src/sourceControl/SourceControlRepositoryService.ts; apps/server/src/telemetry/Services/AnalyticsService.ts; apps/server/src/textGeneration/TextGenerationPresets.ts; apps/server/src/textGeneration/TextGenerationPrompts.test.ts; apps/server/src/workspace/WorkspaceEntries.ts; apps/server/src/workspace/WorkspacePaths.ts; apps/web/package.json; apps/web/public/mockServiceWorker.js; apps/web/src/components/SplashScreen.tsx; apps/web/src/components/ui/button.test.tsx; apps/web/src/components/ui/card.tsx; apps/web/src/components/ui/field.tsx; apps/web/src/components/ui/fieldset.tsx; apps/web/src/components/ui/form.tsx; apps/web/src/environments/primary/context.ts; apps/web/src/environments/primary/index.ts; apps/web/src/historyBootstrap.ts; apps/web/src/hooks/useSettings.ts; apps/web/src/lib/terminalUiStateCleanup.ts; apps/web/src/localApi.ts; apps/web/src/observability/clientTracing.ts; apps/web/src/orchestrationEventEffects.ts; apps/web/src/orchestrationRecovery.ts; apps/web/src/remoteOpen.ts; apps/web/src/rpc/atomRegistry.ts; apps/web/src/rpc/requestLatencyState.ts; packages/client-runtime/src/connection/catalog.ts; packages/client-runtime/src/state/runtime.ts; packages/effect-acp/package.json; packages/effect-acp/test/examples/cursor-acp-client.example.ts; packages/shared/src/schemaJson.ts; packages/shared/src/themePalettes.ts; packages/tailscale/package.json; packages/tailscale/src/tailscale.ts; scripts/announce-connect-ga.ts; scripts/package.json +b21d87243ea637fbb6fb50667e9a8547e1b6c4e8 chore: vouch six repeat contributors (#9131) identical-final-files 1 1 0 .github/VOUCHED.td +04efa7907e9ec207e2d6af459ce3b2ffd55f6107 feat(cli): open projects in the running desktop app (#8824) review-v2-path 26 20 6 apps/web/src/hooks/useHandleNewThread.ts; apps/web/src/routes/__root.tsx; apps/web/src/state/entities.ts; packages/contracts/src/index.ts; packages/contracts/src/ipc.ts; packages/shared/package.json apps/desktop/src/app/DesktopApp.ts; apps/desktop/src/app/DesktopAppActivation.test.ts; apps/desktop/src/app/DesktopAppActivation.ts; apps/desktop/src/app/DesktopAppActivationBroker.test.ts; apps/desktop/src/app/DesktopAppActivationBroker.ts; apps/desktop/src/ipc/DesktopIpcHandlers.ts; apps/desktop/src/ipc/channels.ts; apps/desktop/src/ipc/methods/appActivation.ts; apps/desktop/src/main.ts; apps/desktop/src/preload.ts; apps/server/src/bin.ts; apps/server/src/cli/app.test.ts; apps/server/src/cli/app.ts; apps/web/src/components/desktop/DesktopAppActivationCoordinator.tsx; apps/web/src/desktopAppActivation.test.ts; apps/web/src/desktopAppActivation.ts; docs/user/install.md; packages/contracts/src/desktopAppActivation.ts; packages/shared/src/desktopAppControl.test.ts; packages/shared/src/desktopAppControl.ts +beae2147a9487ec47ac992319f2216914b4cb62d fix(media): preview host files and stream videos across clients (#9023) review-v2-path 82 66 16 apps/mobile/src/features/threads/ThreadFeed.tsx; apps/server/src/http.test.ts; apps/web/src/components/ChatView.logic.test.ts; apps/web/src/components/ChatView.logic.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/ChatComposer.tsx; apps/web/src/components/chat/MessagesTimeline.tsx; apps/web/src/components/chat/externalLinkContextMenu.test.ts; apps/web/src/components/chat/externalLinkContextMenu.ts; apps/web/src/components/files/FilePreviewPanel.tsx; docs/user/composer.md; packages/client-runtime/package.json; packages/client-runtime/src/work-log/presentation.test.ts; packages/client-runtime/src/work-log/presentation.ts; packages/contracts/src/assets.ts; pnpm-lock.yaml apps/desktop/src/electron/ElectronProtocol.test.ts; apps/desktop/src/electron/ElectronProtocol.ts; apps/mobile/modules/t3-markdown-text/assets/file-icons/pierre_video.png; apps/mobile/modules/t3-markdown-text/package.json; apps/mobile/modules/t3-markdown-text/scripts/sync-pierre-file-icons.mjs; apps/mobile/modules/t3-markdown-text/src/markdownFileIcons.generated.ts; apps/mobile/modules/t3-markdown-text/src/markdownLinks.ts; apps/mobile/modules/t3-markdown-text/src/nativeMarkdownText.ts; apps/mobile/src/components/FilePreview.ios.tsx; apps/mobile/src/components/FilePreview.tsx; apps/mobile/src/components/FilePreviewModal.tsx; apps/mobile/src/components/MediaActionsMenu.tsx; apps/mobile/src/components/MediaImagePreview.tsx; apps/mobile/src/components/MediaSourceCaption.tsx; apps/mobile/src/components/MediaVideoPlayer.tsx; apps/mobile/src/components/MediaVideoPreviewModal.tsx; apps/mobile/src/components/VideoPreviewModal.ios.tsx; apps/mobile/src/components/VideoPreviewModal.tsx; apps/mobile/src/components/VideoThumbnailImage.tsx; apps/mobile/src/features/files/ThreadFilesRouteScreen.tsx; apps/mobile/src/features/files/WorkspaceFileImagePreview.tsx; apps/mobile/src/features/files/WorkspaceFileVideoPreview.tsx; apps/mobile/src/features/files/filePath.ts; apps/mobile/src/features/files/preload-workspace-file.ts; apps/mobile/src/features/files/workspaceFileAssetUrl.ts; apps/mobile/src/lib/markdownLinks.test.ts; apps/mobile/src/lib/markdownMedia.test.ts; apps/mobile/src/lib/markdownMedia.ts; apps/mobile/src/lib/mediaActions.ts; apps/mobile/src/lib/nativeMarkdownText.test.ts; apps/mobile/src/lib/videoPreviewSource.ts; apps/mobile/src/state/assets.ts; apps/mobile/src/state/use-atom-query-runner.ts; apps/server/src/assets/AssetAccess.test.ts; apps/server/src/assets/AssetAccess.ts; apps/server/src/assets/MediaFile.ts; apps/server/src/http.ts; apps/web/src/assets/assetUrls.ts; apps/web/src/components/ChatMarkdown.tsx; apps/web/src/components/ChatMarkdown.workspace-images.test.tsx; apps/web/src/components/chat/ExpandedImageDialog.test.tsx; apps/web/src/components/chat/ExpandedImageDialog.tsx; apps/web/src/components/chat/ExpandedImagePreview.test.ts; apps/web/src/components/chat/ExpandedImagePreview.tsx; apps/web/src/components/files/projectFilesQueryState.ts; apps/web/src/components/media/MediaActions.tsx; apps/web/src/components/media/MediaVideoPlayer.tsx; apps/web/src/components/media/OpenMediaLink.tsx; apps/web/src/components/media/mediaContent.ts; apps/web/src/components/pullRequest/PullRequestMarkdown.tsx; apps/web/src/contextMenuFallback.ts; apps/web/src/lib/videoFirstFrame.test.ts; apps/web/src/lib/videoFirstFrame.ts; apps/web/src/markdown-links.test.ts; apps/web/src/markdown-links.ts; apps/web/src/pierre-icons.ts; apps/web/src/state/use-atom-query-runner.ts; docs/internals/environment-auth.md; packages/client-runtime/src/markdownImages.ts; packages/client-runtime/src/markdownLinks.test.ts; packages/client-runtime/src/markdownLinks.ts; packages/client-runtime/src/mediaReference.test.ts; packages/client-runtime/src/mediaReference.ts; packages/shared/src/filePreview.test.ts; packages/shared/src/filePreview.ts; packages/shared/src/video.ts +60cef47ec983637ddc68faed7b1488b6f3c3a175 chore(release): prepare v0.0.38 review-v2-path 4 2 2 apps/server/package.json; packages/contracts/package.json apps/desktop/package.json; apps/web/package.json +590a579f2e9292ce314c69e459e19620004578fe fix(chat): keep latest command live between messages (#9098) review-v2-path 4 0 4 apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.logic.ts; apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx +0222aa255d11babd242dbe5ed0947e5fc5eaefee fix(web): preserve theme when toggling advanced colors (#8500) identical-final-files 1 1 0 apps/web/src/components/settings/ThemeEditorPanel.tsx +c0995d2eaf8ec787b3318ed1169ae266ed1529f8 fix(web): keep the selected environment when changing projects (#9102) review-v2-path 3 2 1 docs/user/composer.md apps/web/src/environmentGrouping.test.ts; apps/web/src/sidebarProjectGrouping.ts +d0b4acbd13b2b602710e4a7d60c42f4799a409be fix(web): keep theme placeholder text dimmer than entered text (#9104) identical-final-files 3 3 0 apps/web/src/themePalette.test.ts; apps/web/src/themePalette.ts; apps/web/src/vscodeThemeImport.test.ts +3b3465f2a9dbc541a8806e39d2889abb77b93f5d fix(web): changing projects no longer creates a draft (#9097) review-v2-path 8 5 3 apps/web/src/components/ChatView.tsx; apps/web/src/composerDraftStore.ts; apps/web/src/hooks/useHandleNewThread.ts apps/web/src/components/chat/DraftHeroHeadline.tsx; apps/web/src/composerDraftStore.test.ts; apps/web/src/lib/attachmentUploadQueue.test.ts; apps/web/src/lib/chatThreadActions.test.ts; apps/web/src/lib/chatThreadActions.ts +692eb1a5792b9930959b19805acf2bf2611318c9 fix(web): sync sidebar PR state from open panel (#9092) review-v2-path 3 1 2 apps/web/src/components/ChatView.tsx; apps/web/src/components/ThreadStatusIndicators.tsx apps/web/src/components/ThreadStatusIndicators.test.ts +163d50846bc8989b5858802bb02253254dcee0dd "Revert ""fix(chat): reuse one row for live activity"" (#9096)" review-v2-path 4 0 4 apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.logic.ts; apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx +03542836834d008a097450cf24d0d9c6f965b859 feat(models): discover Claude models from remote manifest (#9084) review-v2-path 26 18 8 apps/server/src/provider/Drivers/ClaudeDriver.ts; apps/server/src/provider/Layers/ClaudeAdapter.test.ts; apps/server/src/provider/Layers/ClaudeAdapter.ts; apps/server/src/provider/Layers/ProviderRegistry.test.ts; packages/contracts/src/model.ts; packages/contracts/src/server.ts; packages/shared/src/model.test.ts; packages/shared/src/model.ts apps/server/src/provider/ClaudeModelCatalog.test.ts; apps/server/src/provider/ClaudeModelCatalog.testFixtures.ts; apps/server/src/provider/ClaudeModelCatalog.ts; apps/server/src/provider/ClaudeModelManifest.ts; apps/server/src/provider/Layers/ClaudeProvider.ts; apps/server/src/provider/ModelManifest.test.ts; apps/server/src/provider/ModelManifest.ts; apps/server/src/provider/model-manifest.json; apps/server/src/textGeneration/ClaudeTextGeneration.test.ts; apps/server/src/textGeneration/ClaudeTextGeneration.ts; apps/web/src/components/chat/ModelPickerContent.tsx; apps/web/src/components/chat/composerProviderState.test.tsx; apps/web/src/components/chat/modelPickerModelHighlights.ts; apps/web/src/components/chat/providerIconUtils.ts; apps/web/src/modelSelection.ts; apps/web/src/providerModels.test.ts; apps/web/src/providerModels.ts; docs/internals/model-manifest.md +a924fbe08e681ef56d8cfb8b99e1e803d52aa463 fix(chat): reuse one row for live activity (#9062) review-v2-path 4 0 4 apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.logic.ts; apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx +cb007469161ff0db2bc2dc8123c4b30e186aae50 feat(web): open project settings from thread menus (#8925) review-v2-path 6 3 3 apps/web/src/components/LegacySidebar.tsx; apps/web/src/components/Sidebar.tsx; apps/web/src/hooks/useThreadActionMenu.ts apps/web/src/components/threadActionMenu.logic.test.ts; apps/web/src/components/threadActionMenu.logic.ts; apps/web/src/contextMenuFallback.ts +9d1879b142a2f5d01383357646a4679d1a2bd202 feat(desktop): add configurable quit shortcut confirmation (#9076) review-v2-path 11 5 6 apps/desktop/src/settings/DesktopClientSettings.test.ts; apps/web/src/components/settings/SettingsPanels.tsx; apps/web/src/components/settings/settingsSearch.ts; packages/contracts/src/ipc.ts; packages/contracts/src/settings.test.ts; packages/contracts/src/settings.ts apps/desktop/src/preload.ts; apps/desktop/src/window/DesktopWindow.ts; apps/desktop/src/window/QuitHold.test.ts; apps/desktop/src/window/QuitHold.ts; apps/web/src/components/QuitHoldOverlay.tsx +ef7014d851f56bb037a9da963095ffd883c7fa08 fix(preview): restore recording and macOS rendering after Electron 43 (#9001) review-v2-path 11 10 1 packages/contracts/src/ipc.ts apps/desktop/src/ipc/methods/preview.ts; apps/desktop/src/preview/Manager.test.ts; apps/desktop/src/preview/Manager.ts; apps/web/src/browser/HostedBrowserWebview.tsx; apps/web/src/browser/browserRecording.test.ts; apps/web/src/browser/browserRecording.ts; apps/web/src/browser/hostedBrowserWebviewStyle.test.ts; apps/web/src/browser/hostedBrowserWebviewStyle.ts; apps/web/src/components/preview/PreviewView.test.tsx; apps/web/src/components/preview/PreviewView.tsx +c17d02cff98f2e7b590d4c3a5775d1faa47c2e7b feat(claude): add Claude Fable 5.1 model (#9078) review-v2-path 7 3 4 apps/server/src/provider/Layers/ClaudeAdapter.test.ts; apps/server/src/provider/Layers/ProviderRegistry.test.ts; packages/contracts/src/model.ts; packages/shared/src/model.test.ts apps/server/src/provider/Layers/ClaudeProvider.ts; apps/server/src/provider/ModelManifest.test.ts; apps/server/src/provider/model-manifest.json +643b21edaa08eb1d19d633dbb0b275164bfa60be fix(server): cache project favicon resolution (#9080) identical-final-files 2 2 0 apps/server/src/project/ProjectFaviconResolver.test.ts; apps/server/src/project/ProjectFaviconResolver.ts +261380f91f764673c7fcefcb6a3f775526dbb776 fix(mobile): keep thread scroll bounds current after animations (#9013) review-v2-path 7 4 3 apps/mobile/src/features/threads/ThreadDetailScreen.tsx; apps/mobile/src/features/threads/ThreadFeed.tsx; pnpm-lock.yaml apps/mobile/src/features/threads/thread-feed-live-follow.test.ts; apps/mobile/src/features/threads/thread-feed-live-follow.ts; apps/mobile/src/features/threads/thread-work-log.tsx; patches/@legendapp__list@3.3.5.patch +2d156a83b96ebf2e4a9c6017251baad357ae6ab1 feat(shortcuts): copy active thread reference (#8994) review-v2-path 20 12 8 apps/mobile/src/features/keyboard/hardwareKeyboardCommands.ts; apps/mobile/src/state/use-thread-selection.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/CommandPalette.tsx; apps/web/src/keybindings.test.ts; packages/contracts/src/keybindings.test.ts; packages/contracts/src/keybindings.ts; packages/shared/package.json apps/mobile/modules/t3-native-controls/android/src/main/java/expo/modules/t3nativecontrols/T3KeyboardCommandsModule.kt; apps/mobile/modules/t3-native-controls/expo-module.config.json; apps/mobile/modules/t3-native-controls/ios/T3KeyboardCommandsModule.swift; apps/mobile/src/features/keyboard/HardwareKeyboardCommandProvider.tsx; apps/mobile/src/lib/copyTextWithHaptic.test.ts; apps/mobile/src/lib/copyTextWithHaptic.ts; apps/mobile/src/native/T3KeyboardCommands.android.tsx; apps/server/src/keybindings.test.ts; docs/user/keybindings.md; packages/shared/src/keybindings.ts; packages/shared/src/threadReference.test.ts; packages/shared/src/threadReference.ts +b5b6abb11e61ad2c9946b8d1346653c6c43d2261 fix(web): block type-to-focus behind open dialogs (#8139) review-v2-path 1 0 1 apps/web/src/components/ChatView.tsx +9dbdcece5f488c66f6b9ac516b610f45bbbb676a fix(web): align un-settle banner action (#9033) identical-final-files 1 1 0 apps/web/src/components/chat/ComposerBannerStack.tsx +b883fc066ea5c9bebbe1c3e9b4bc2471aab3685f perf(client-runtime): halve server config bootstrap traffic (#8367) review-v2-path 20 11 9 apps/web/src/connection/runtime.ts; packages/client-runtime/src/connection/registry.test.ts; packages/client-runtime/src/operations/commands.test.ts; packages/client-runtime/src/rpc/client.ts; packages/client-runtime/src/state/server.ts; packages/client-runtime/src/state/shell-sync.test.ts; packages/client-runtime/src/state/threads-pagination.test.ts; packages/client-runtime/src/state/threads-sync.test.ts; packages/client-runtime/src/state/vcsAction.test.ts apps/web/src/cloud/linkEnvironment.test.ts; packages/client-runtime/src/connection/layer.ts; packages/client-runtime/src/connection/supervisor.test.ts; packages/client-runtime/src/rpc/client.test.ts; packages/client-runtime/src/rpc/session.test.ts; packages/client-runtime/src/rpc/session.ts; packages/client-runtime/src/state/pullRequests.test.ts; packages/client-runtime/src/state/server.test.ts; packages/client-runtime/src/state/serverConfigProjection.ts; packages/client-runtime/src/state/sourceControl.test.ts; packages/client-runtime/src/state/vcs.test.ts +e86604d3372acccd9f6a33a2c4ae46f4e2685541 perf(server): skip full-message reads while streaming (#9032) review-v2-path 5 2 3 apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts; apps/server/src/orchestration/Layers/ProjectionPipeline.ts; apps/server/src/persistence/Services/ProjectionThreadMessages.ts apps/server/src/persistence/Layers/ProjectionThreadMessages.test.ts; apps/server/src/persistence/Layers/ProjectionThreadMessages.ts +3c73fa7ce02b7ee6b2904ec58e47c06262aebf5d perf(web): defer pull request line stats until visible (#6471) review-v2-path 5 4 1 apps/web/src/routes/_chat.pull-requests.tsx apps/web/src/components/pullRequest/PullRequestRow.tsx; apps/web/src/components/pullRequest/pullRequestList.logic.test.ts; apps/web/src/components/pullRequest/pullRequestList.logic.ts; apps/web/src/state/pullRequests.ts +62d39bf00d5ddd83a9b36a81321fe9aa4d2502bb fix(server): stop OpenCode child sessions (#9005) review-v2-path 3 1 2 apps/server/src/provider/Layers/OpenCodeAdapter.test.ts; apps/server/src/provider/Layers/OpenCodeAdapter.ts docs/user/providers-opencode.md +8b033de48247086c1b6c6968ce7cf33b358a1ec5 fix(clients): dedupe skills in composer menus (#8043) identical-final-files 5 5 0 apps/mobile/src/features/threads/use-composer-command-menu.ts; apps/web/src/providerSkillSearch.test.ts; apps/web/src/providerSkillSearch.ts; packages/client-runtime/src/providerSkills.test.ts; packages/client-runtime/src/providerSkills.ts +f32f9a2f41342bf8a1a109d6ebe9b70044c5311b fix(server): settle threads server-side (#8600) review-v2-path 55 17 38 apps/desktop/src/settings/DesktopClientSettings.test.ts; apps/mobile/src/features/home/HomeScreen.tsx; apps/mobile/src/features/home/useThreadListActions.ts; apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx; apps/mobile/src/features/threads/thread-list-v2-items.tsx; apps/mobile/src/features/threads/threadListV2.test.ts; apps/mobile/src/features/threads/threadListV2.ts; apps/server/integration/OrchestrationEngineHarness.integration.ts; apps/server/src/environment/ServerEnvironment.ts; apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts; apps/server/src/orchestration/Layers/OrchestrationEngine.ts; apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts; apps/server/src/orchestration/Layers/OrchestrationReactor.ts; apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts; apps/server/src/orchestration/Layers/ProviderCommandReactor.ts; apps/server/src/orchestration/ThreadSettlementReactor.test.ts; apps/server/src/orchestration/ThreadSettlementReactor.ts; apps/server/src/orchestration/decider.ts; apps/server/src/persistence/Layers/OrchestrationEventStore.ts; apps/server/src/persistence/Services/OrchestrationEventStore.ts; apps/server/src/server.test.ts; apps/server/src/server.ts; apps/server/src/ws.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/Sidebar.logic.ts; apps/web/src/components/Sidebar.tsx; apps/web/src/components/chat/ChatHeader.tsx; apps/web/src/components/settings/SettingsPanels.tsx; apps/web/src/components/settings/settingsSearch.test.ts; apps/web/src/components/settings/settingsSearch.ts; apps/web/src/hooks/useThreadActionMenu.ts; apps/web/src/hooks/useThreadActions.ts; docs/internals/overview.md; packages/client-runtime/src/state/threadSettled.ts; packages/contracts/src/environment.ts; packages/contracts/src/orchestration.ts; packages/contracts/src/settings.test.ts; packages/contracts/src/settings.ts apps/mobile/src/features/settings/SettingsRouteScreen.tsx; apps/mobile/src/persistence/mobile-preferences.ts; apps/server/src/git/GitManager.test.ts; apps/server/src/git/GitManager.ts; apps/server/src/orchestration/Errors.ts; apps/server/src/orchestration/ThreadSettlementPolicy.test.ts; apps/server/src/orchestration/ThreadSettlementPolicy.ts; apps/server/src/orchestration/decider.settled.test.ts; apps/server/src/serverSettings.test.ts; apps/web/src/components/ThreadStatusIndicators.test.ts; apps/web/src/components/settings/useAvailableSettingsSearchItems.ts; apps/web/src/hooks/useNowMinute.ts; apps/web/src/hooks/useSettings.test.ts; apps/web/src/hooks/useSettings.ts; docs/user/thread-sidebar.md; packages/client-runtime/src/state/threadSettled.test.ts; packages/client-runtime/src/state/threadSnoozed.test.ts +7e4ce3bbb16c3cfa1ea756de917d8f9398e5999e perf(server): cut chatty tool-update frames by 90% (#8368) review-v2-path 5 0 5 apps/server/src/orchestration/ActivityPayloadProjection.ts; apps/server/src/orchestration/ThreadLiveEventCoalescer.test.ts; apps/server/src/orchestration/ThreadLiveEventCoalescer.ts; apps/server/src/server.test.ts; apps/server/src/ws.ts +8f1ef8b9eb72ac6cd8510364608e01dc7febf9c1 perf(server): scan only appended transcript bytes for usage summaries (#9024) identical-final-files 6 6 0 apps/server/src/usage/UsageService.test.ts; apps/server/src/usage/UsageService.ts; apps/server/src/usage/usageScanCache.test.ts; apps/server/src/usage/usageScanCache.ts; apps/server/src/usage/usageTranscriptReader.test.ts; apps/server/src/usage/usageTranscriptReader.ts +0bfb6df34b26dfe0162db6c09dca00bc8c5a5ec4 perf(server): cut idle CPU use and stop provider event leaks (#8187) review-v2-path 19 11 8 apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts; apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts; apps/server/src/provider/Layers/OpenCodeAdapter.test.ts; apps/server/src/provider/Layers/OpenCodeAdapter.ts; apps/server/src/provider/acp/AcpNativeLogging.ts; apps/server/src/vcs/GitVcsDriverCore.ts; packages/effect-acp/src/protocol.test.ts; packages/effect-acp/src/protocol.ts apps/server/src/project/RepositoryIdentityResolver.test.ts; apps/server/src/project/RepositoryIdentityResolver.ts; apps/server/src/provider/Layers/EventNdjsonLogger.test.ts; apps/server/src/provider/Layers/EventNdjsonLogger.ts; apps/server/src/provider/acp/AcpNativeLogging.test.ts; apps/server/src/resourceTelemetry/NativeTelemetryClient.test.ts; apps/server/src/resourceTelemetry/NativeTelemetryClient.ts; docs/internals/resource-telemetry.md; native/resource-monitor/src/main.rs; packages/effect-codex-app-server/src/protocol.test.ts; packages/effect-codex-app-server/src/protocol.ts +a9ffb8279614df6ae2f1f4b7f09a0dc42edef797 perf(server): bound snapshot activity payload memory (#9000) review-v2-path 5 0 5 apps/server/src/orchestration/ActivityPayloadProjection.test.ts; apps/server/src/orchestration/ActivityPayloadProjection.ts; apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts; apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts; apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts +73776d4e52087331245e82ebf3c053ae0991935d test: remove static presentation snapshots (#9008) identical-final-files 2 2 0 apps/mobile/src/lib/typography.test.ts; apps/web/src/components/ui/menu.test.tsx +0947c30e6946b2ad6d6cd518fd44292e75e834e8 fix(client): use package import for markdown image helpers (#9010) review-v2-path 1 0 1 packages/client-runtime/src/work-log/presentation.ts +ce71c04f0aa9d2e5cd340e2a04cb1b0d5e24419d feat(client): render viewed images in work logs (#8936) review-v2-path 7 2 5 apps/mobile/src/features/threads/ThreadFeed.tsx; apps/web/src/components/chat/MessagesTimeline.logic.ts; apps/web/src/components/chat/MessagesTimeline.tsx; packages/client-runtime/src/work-log/presentation.test.ts; packages/client-runtime/src/work-log/presentation.ts apps/mobile/src/features/threads/thread-work-log.tsx; apps/web/src/components/ChatMarkdown.tsx +ff93aba61dc1f7839713580bc8ee08da2a395f9a feat(web): search individual settings by detail (#8831) review-v2-path 19 12 7 apps/web/src/components/CommandPalette.logic.test.ts; apps/web/src/components/CommandPalette.logic.ts; apps/web/src/components/CommandPalette.tsx; apps/web/src/components/settings/SettingsPanels.tsx; apps/web/src/components/settings/SettingsSidebarNav.tsx; apps/web/src/components/settings/settingsSearch.test.ts; apps/web/src/components/settings/settingsSearch.ts apps/web/src/components/settings/ConnectionsSettings.tsx; apps/web/src/components/settings/ProviderSettingsPanel.environment.test.tsx; apps/web/src/components/settings/ProviderSettingsPanel.logic.test.ts; apps/web/src/components/settings/ProviderSettingsPanel.logic.ts; apps/web/src/components/settings/ProviderSettingsPanel.tsx; apps/web/src/components/settings/SourceControlSettings.tsx; apps/web/src/components/settings/SourceControlWritingSettings.tsx; apps/web/src/components/settings/ThemeSettings.tsx; apps/web/src/components/settings/settingsLayout.tsx; apps/web/src/components/settings/useAvailableSettingsSearchItems.ts; apps/web/src/lib/utils.ts; docs/user/keybindings.md +d35c71d1b975660ec6a71bbceb6aa7dfd0e8c3d5 feat(web): add pull request list filters (#8809) review-v2-path 7 6 1 apps/web/src/routes/_chat.pull-requests.tsx apps/web/src/components/pullRequest/PullRequestListFilters.test.tsx; apps/web/src/components/pullRequest/PullRequestListFilters.tsx; apps/web/src/components/pullRequest/PullRequestRow.tsx; apps/web/src/components/pullRequest/PullRequestSummaryTab.tsx; apps/web/src/components/pullRequest/pullRequestList.logic.ts; docs/user/source-control.md +b17cc3d1bf0f4a5deee6dd6a470e36970b864a9b perf(server): reduce frequency of full tool call output being loaded into memory from db (#8988) review-v2-path 10 1 9 apps/server/src/orchestration/Layers/CheckpointReactor.ts; apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts; apps/server/src/orchestration/Layers/ProjectionPipeline.ts; apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts; apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts; apps/server/src/orchestration/Layers/ProviderCommandReactor.ts; apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts; apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts; apps/server/src/persistence/Services/ProjectionThreadActivities.ts apps/server/src/persistence/Layers/ProjectionThreadActivities.ts +42a8fd5103b4af57b16be721a9864ca3a5c18c5b feat(pull-requests): link GitHub references in markdown (#8812) identical-final-files 5 5 0 apps/web/src/components/ChatMarkdown.tsx; apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx; apps/web/src/components/pullRequest/PullRequestMarkdown.tsx; apps/web/src/components/pullRequest/pullRequestMarkdown.logic.ts; apps/web/src/vendor/mdast-find-and-replace.ts +c78ae50a5a5fdf8f42d0aaa0103b26ee836f0cfc fix(server): isolate remote web session cookies (#8085) review-v2-path 18 13 5 apps/server/src/bin.test.ts; apps/server/src/environment/ServerEnvironment.test.ts; apps/server/src/environment/ServerEnvironment.ts; apps/server/src/server.test.ts; apps/server/src/server.ts apps/server/src/auth/EnvironmentAuth.test.ts; apps/server/src/auth/EnvironmentAuth.ts; apps/server/src/auth/EnvironmentAuthAdmin.test.ts; apps/server/src/auth/EnvironmentAuthPolicy.test.ts; apps/server/src/auth/EnvironmentAuthPolicy.ts; apps/server/src/auth/SessionStore.test.ts; apps/server/src/auth/SessionStore.ts; apps/server/src/auth/http.ts; apps/server/src/auth/utils.test.ts; apps/server/src/auth/utils.ts; apps/server/src/cli/connect.ts; apps/server/src/cli/pair.test.ts; docs/internals/remote.md +9ecfc07a8b3acadd1612665b6e24425f625480de fix(chat): keep agent activity visible between actions (#8984) review-v2-path 4 0 4 apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.logic.ts; apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx +9bc7a56848eb7c7546605e54ff02c6abea176f96 feat(mobile): upload attachments while composing (#8978) review-v2-path 23 17 6 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx; apps/mobile/src/features/threads/ThreadComposer.tsx; apps/mobile/src/lib/projectThreadStartTurn.ts; apps/mobile/src/state/use-thread-composer-state.ts; apps/mobile/src/state/use-thread-outbox-drain.ts; docs/user/composer.md apps/mobile/src/Stack.tsx; apps/mobile/src/components/ComposerAttachmentStrip.tsx; apps/mobile/src/features/cloud/CloudAuthProvider.test.ts; apps/mobile/src/features/cloud/CloudAuthProvider.tsx; apps/mobile/src/features/cloud/cloud-drafts.ts; apps/mobile/src/features/threads/use-project-actions.ts; apps/mobile/src/lib/attachmentUpload.test.ts; apps/mobile/src/lib/attachmentUpload.ts; apps/mobile/src/lib/composer-image-schema.ts; apps/mobile/src/lib/composerAttachmentUploadQueue.test.ts; apps/mobile/src/lib/composerAttachmentUploadQueue.ts; apps/mobile/src/lib/composerImages.ts; apps/mobile/src/state/composer-attachment-uploads.ts; apps/mobile/src/state/use-composer-drafts.test.ts; apps/mobile/src/state/use-composer-drafts.ts; apps/mobile/src/state/use-thread-outbox-drain.test.ts; docs/internals/connection-runtime.md +85b656ff300f71060ad6305c7e1e29a72b442ce9 style: format CodeRabbit configuration identical-final-files 1 1 0 .coderabbit.yaml +0df043fd4eaa190eb491a3060836156eb0ae915e Add auto_review configuration to coderabbit.yaml identical-final-files 1 1 0 .coderabbit.yaml +17f00f60248374aafa2efb9b54ff08ce52e60a0a feat(web): add expand/collapse all control to the files surface (#8889) identical-final-files 3 3 0 apps/web/src/components/files/FileBrowserPanel.tsx; apps/web/src/components/files/fileTreeExpansion.test.ts; apps/web/src/components/files/fileTreeExpansion.ts +c50b0b4ef8d61ffe3de1cfa6249f906709f7da1f fix(web): make WSL settings searchable (#8881) review-v2-path 6 3 3 apps/web/src/components/settings/SettingsSidebarNav.tsx; apps/web/src/components/settings/settingsSearch.test.ts; apps/web/src/components/settings/settingsSearch.ts apps/web/src/components/settings/ConnectionsSettings.logic.test.ts; apps/web/src/components/settings/ConnectionsSettings.logic.ts; apps/web/src/components/settings/ConnectionsSettings.tsx +929f7e6479d00754dee4e4554b24b25478b8064d fix(shared): preserve Windows shell PATH priority (#8748) identical-final-files 2 2 0 packages/shared/src/shell.test.ts; packages/shared/src/shell.ts +41adccc83e819c286dcdf32cd8b5f55af8bb0b49 fix(server): allow long thread IDs in HTTP routes (#8898) review-v2-path 2 0 2 apps/server/src/server.test.ts; apps/server/src/server.ts +f8e4accf27415eb9f7f4106087d2a1b0186d66b9 feat(mobile): add native image and PDF previews (#8959) review-v2-path 26 22 4 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx; apps/mobile/src/features/threads/ThreadComposer.tsx; apps/mobile/src/features/threads/ThreadFeed.tsx; docs/user/composer.md apps/mobile/app.config.ts; apps/mobile/modules/t3-native-controls/ios/T3NativeControlsModule.swift; apps/mobile/modules/t3-native-controls/ios/T3NativeFilePresentation.swift; apps/mobile/src/components/ComposerAttachmentStrip.tsx; apps/mobile/src/components/FilePreview.ios.tsx; apps/mobile/src/components/FilePreview.tsx; apps/mobile/src/components/FilePreviewModal.tsx; apps/mobile/src/components/VideoPreviewModal.ios.tsx; apps/mobile/src/components/VideoPreviewModal.tsx; apps/mobile/src/components/VideoThumbnailImage.tsx; apps/mobile/src/features/files/ThreadFilesRouteScreen.tsx; apps/mobile/src/features/files/WorkspaceFileImagePreview.tsx; apps/mobile/src/features/review/ReviewCommentComposerSheet.tsx; apps/mobile/src/lib/composerFiles.test.ts; apps/mobile/src/lib/composerImages.ts; apps/mobile/src/lib/filePreview.test.ts; apps/mobile/src/lib/filePreview.ts; apps/mobile/src/lib/localAttachmentPreview.test.ts; apps/mobile/src/lib/localAttachmentPreview.ts; apps/mobile/src/lib/localVideoPreview.test.ts; apps/mobile/src/lib/localVideoPreview.ts; docs/internals/mobile-navigation.md +6d15c5bbc3f3c331a7466bb94c17413a35f7b659 fix(server): preserve usage cache outside walked roots (#8540) identical-final-files 2 2 0 apps/server/src/usage/usageScanCache.test.ts; apps/server/src/usage/usageScanCache.ts +f47e74004af232f0e3df8dc10093601d1c2c3ea3 fix(web): prevent chat metadata overlap (#8851) review-v2-path 3 0 3 apps/web/src/components/BranchToolbar.tsx; apps/web/src/components/BranchToolbarEnvModeSelector.tsx; apps/web/src/components/chat/ChatHeader.tsx +31c1c5996f88e3acf1566adc11c9b51ac7561554 feat(mobile): add video playback with native iOS controls (#8919) review-v2-path 37 29 8 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx; apps/mobile/src/features/threads/ThreadComposer.tsx; apps/mobile/src/features/threads/ThreadFeed.tsx; apps/server/src/http.test.ts; apps/web/src/types.ts; docs/user/composer.md; packages/shared/package.json; pnpm-lock.yaml apps/mobile/modules/t3-native-controls/ios/T3NativeControlsModule.swift; apps/mobile/modules/t3-native-controls/ios/T3NativePresentation.swift; apps/mobile/modules/t3-native-controls/ios/T3NativeVideoPresentation.swift; apps/mobile/package.json; apps/mobile/src/components/ComposerAttachmentStrip.tsx; apps/mobile/src/components/NativePresentation.ios.tsx; apps/mobile/src/components/NativePresentation.tsx; apps/mobile/src/components/VideoAttachmentMenu.tsx; apps/mobile/src/components/VideoAttachmentTile.tsx; apps/mobile/src/components/VideoPreviewModal.ios.tsx; apps/mobile/src/components/VideoPreviewModal.tsx; apps/mobile/src/components/VideoThumbnailImage.tsx; apps/mobile/src/lib/attachmentDownload.test.ts; apps/mobile/src/lib/attachmentDownload.ts; apps/mobile/src/lib/composerAttachmentFiles.ts; apps/mobile/src/lib/composerFiles.test.ts; apps/mobile/src/lib/composerImages.ts; apps/mobile/src/lib/localVideoPreview.test.ts; apps/mobile/src/lib/localVideoPreview.ts; apps/mobile/src/lib/shareFileFromSource.ios.ts; apps/mobile/src/lib/shareFileFromSource.ts; apps/mobile/src/lib/videoThumbnails.test.ts; apps/mobile/src/lib/videoThumbnails.ts; apps/mobile/src/state/use-composer-drafts.test.ts; apps/mobile/src/state/use-composer-drafts.ts; apps/server/src/http.ts; docs/internals/mobile-navigation.md; packages/shared/src/video.test.ts; packages/shared/src/video.ts +ef84bc9873a6c4565fbeb64dce3f552570e95a2d fix(chat): smooth worktree setup status (#8922) review-v2-path 16 2 14 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx; apps/mobile/src/lib/threadActivity.test.ts; apps/mobile/src/lib/threadActivity.ts; apps/web/src/components/ChatView.logic.test.ts; apps/web/src/components/ChatView.logic.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/ChatComposer.tsx; apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx; apps/web/src/routes/_chat.draft.$draftId.tsx; apps/web/src/session-logic.test.ts; apps/web/src/session-logic.ts; packages/client-runtime/src/work-log/presentation.ts apps/mobile/src/features/threads/thread-work-log.tsx; apps/web/src/components/chat/timelineScrollAnchoring.ts +4a9d2d0ced2a2b899dbee9e4a5162fd83f81edb8 chore(deps): bump Electron to 43.4.1 (#8626) review-v2-path 4 3 1 pnpm-lock.yaml apps/desktop/package.json; apps/desktop/src/preview/BrowserSession.test.ts; apps/desktop/src/preview/BrowserSession.ts +5ce92c2f192040bf77c0211fa33bf03c74c031ef fix(mobile): shimmer active tool rows (#8932) review-v2-path 3 1 2 apps/mobile/src/lib/threadActivity.test.ts; apps/mobile/src/lib/threadActivity.ts apps/mobile/src/features/threads/thread-work-log.tsx +35da5813315dc4e0c20602ed1918ceccc916b7eb fix(web): show scrollbar for wide markdown tables (#8868) identical-final-files 1 1 0 apps/web/src/components/ChatMarkdown.tsx +038bf3739b871a56b2defdb09605344801448ced Delete app.json (#8934) identical-final-files 1 1 0 app.json +4e8e64fc065a4a72535eee5fe60b689f5b48d35c chore: disable CodeRabbit review status (#8933) identical-final-files 1 1 0 .coderabbit.yaml +746c932e164d49ddb4ac98a42176194b11bf0699 fix(mobile): defer draft navigation until submission completes (#8914) review-v2-path 1 0 1 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx +bba79cc254b65969bde6b6bfc3032c3b5b9316ae fix(web): hide invalid slash skill completions (#8904) review-v2-path 3 2 1 apps/web/src/components/chat/ChatComposer.tsx apps/web/src/components/chat/composerSlashCommandSearch.test.ts; apps/web/src/components/chat/composerSlashCommandSearch.ts +2921050c698fb195e2f5590b7cfab8fdfe0ec729 fix(contracts): accept CLI event origins (#8905) review-v2-path 2 0 2 apps/server/src/persistence/Layers/OrchestrationEventStore.test.ts; packages/contracts/src/baseSchemas.ts +ad38700ac678b8c8a0310d434a44d94a7ee6a47f chore(macroscope): review diagnostic overrides (#8917) identical-final-files 2 2 0 .macroscope/approvability.md; .macroscope/check-run-agents/effect-service-conventions.md +f86c5e8c8700b76250ed1073700a5b9db47e2d57 fix(server): skip IDE detection in Claude probes (#8634) identical-final-files 2 2 0 apps/server/src/provider/Layers/ClaudeCapabilitiesProbe.test.ts; apps/server/src/provider/Layers/ClaudeProvider.ts +9b2d04317c68233782e0630464ac86d77d0686f3 fix(mobile): replace Callstack glass with Expo glass (#8862) review-v2-path 5 4 1 pnpm-lock.yaml apps/mobile/package.json; apps/mobile/src/features/threads/GitActionProgressOverlay.tsx; apps/mobile/src/features/threads/floating-working-control.tsx; docs/user/mobile-appearance.md +e9c4775e8738381140af4e5248507b15fc1cd491 fix(web): mark pull request links as external (#8856) identical-final-files 1 1 0 apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx +3958111057c10c10350dd9c20ec2a2df00f504be fix(preview): improve browser recording quality (#8839) review-v2-path 15 8 7 apps/desktop/src/settings/DesktopClientSettings.test.ts; apps/web/src/components/settings/SettingsPanels.tsx; apps/web/src/components/settings/settingsSearch.test.ts; apps/web/src/components/settings/settingsSearch.ts; packages/contracts/src/ipc.ts; packages/contracts/src/settings.test.ts; packages/contracts/src/settings.ts apps/desktop/src/ipc/methods/preview.ts; apps/desktop/src/preview/Manager.test.ts; apps/desktop/src/preview/Manager.ts; apps/web/src/browser/browserRecording.test.ts; apps/web/src/browser/browserRecording.ts; apps/web/src/components/settings/IntegrationsSettings.tsx; apps/web/src/components/settings/SettingsPanels.logic.test.ts; apps/web/src/components/settings/SettingsPanels.logic.ts +3f62e6fa65c2a2a91a367be4ee95da1b50007bde fix(web): widen sync banners and simplify the working timer (#8855) review-v2-path 4 0 4 apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/ChatComposer.tsx; apps/web/src/components/chat/MessagesTimeline.tsx; docs/user/composer.md +9842518c9a0af14fb3a3e90993692a6e34032682 fix(web): address composer banner review follow-ups (#8850) review-v2-path 10 6 4 apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/ChatComposer.tsx; apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx; docs/user/composer.md apps/web/src/components/chat/ComposerBanner.tsx; apps/web/src/components/chat/ComposerBannerStack.tsx; apps/web/src/components/chat/ComposerServerUpdateStatus.tsx; apps/web/src/components/chat/ComposerStashMenu.tsx; apps/web/src/components/chat/ComposerSurface.tsx; apps/web/src/components/chat/ComposerTasksBadge.tsx +30175a8af04c0daa359652b5e8dc8230b40b462a fix(web): restore unified activity logs and composer banners (#8734) review-v2-path 33 17 16 apps/web/src/components/BranchToolbar.tsx; apps/web/src/components/ChatView.logic.test.ts; apps/web/src/components/ChatView.logic.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/ChatComposer.tsx; apps/web/src/components/chat/ComposerPendingApprovalPanel.tsx; apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx; apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.logic.ts; apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx; apps/web/src/index.css; apps/web/src/session-logic.test.ts; apps/web/src/session-logic.ts; apps/web/src/versionSkew.test.ts; apps/web/src/versionSkew.ts apps/web/src/components/chat/ComposerActivityStatus.tsx; apps/web/src/components/chat/ComposerBanner.tsx; apps/web/src/components/chat/ComposerBannerStack.test.tsx; apps/web/src/components/chat/ComposerBannerStack.tsx; apps/web/src/components/chat/ComposerCommandMenu.test.tsx; apps/web/src/components/chat/ComposerCommandMenu.tsx; apps/web/src/components/chat/ComposerPlanFollowUpBanner.tsx; apps/web/src/components/chat/ComposerServerUpdateStatus.tsx; apps/web/src/components/chat/ComposerStashBadge.test.tsx; apps/web/src/components/chat/ComposerStashBadge.tsx; apps/web/src/components/chat/ComposerStashMenu.test.tsx; apps/web/src/components/chat/ComposerStashMenu.tsx; apps/web/src/components/chat/ComposerSurface.tsx; apps/web/src/components/chat/ComposerTasksBadge.test.tsx; apps/web/src/components/chat/ComposerTasksBadge.tsx; apps/web/src/components/chat/ThreadSyncStatusPill.test.tsx; apps/web/src/components/chat/ThreadSyncStatusPill.tsx +f9137a0c89f6190d27813bb46dbb6d1bb796f080 fix(mobile): map native menu icon colors explicitly identical-final-files 1 1 0 apps/mobile/src/components/ControlPill.tsx +e3dcc1615c9167048ecfe536f87ad1d353fa8a49 Add mobile composer attachment menu with video support (#8843) review-v2-path 19 13 6 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx; apps/mobile/src/features/threads/ThreadComposer.tsx; apps/mobile/src/features/threads/ThreadDetailScreen.tsx; apps/mobile/src/features/threads/ThreadRouteScreen.tsx; apps/mobile/src/state/use-thread-composer-state.ts; docs/user/composer.md apps/mobile/app.config.ts; apps/mobile/src/components/AppSymbol.tsx; apps/mobile/src/components/ComposerAttachmentButton.tsx; apps/mobile/src/components/ComposerToolbar.tsx; apps/mobile/src/components/ControlPill.tsx; apps/mobile/src/features/sharing/incoming-share-model.test.ts; apps/mobile/src/features/voice-input/ComposerDictationControl.tsx; apps/mobile/src/lib/composerFiles.test.ts; apps/mobile/src/lib/composerImages.ts; apps/mobile/src/lib/menu-action-colors.test.ts; apps/mobile/src/lib/menu-action-colors.ts; apps/mobile/src/state/use-composer-drafts.test.ts; docs/internals/mobile-navigation.md +7963ac7404ff2196c3e8e4198ecc02a5e742b0a1 chore(release): prepare v0.0.37 review-v2-path 4 2 2 apps/server/package.json; packages/contracts/package.json apps/desktop/package.json; apps/web/package.json +cefec32d6fc5d14f03e110ebdde534bdbcc9b62b fix(web): prevent pull request metadata overlap (#8790) review-v2-path 3 2 1 apps/web/src/routes/_chat.pull-requests.tsx apps/web/src/components/pullRequest/PullRequestRow.tsx; apps/web/src/components/pullRequest/pullRequestPresentation.tsx +352710d497cc640553e3e18e23fb5a5f3f890466 feat(mobile): add offline iPhone voice input (#8614) review-v2-path 36 29 7 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx; apps/mobile/src/features/threads/ThreadComposer.tsx; apps/mobile/src/features/threads/ThreadDetailScreen.tsx; docs/README.md; docs/user/composer.md; packages/client-runtime/package.json; pnpm-lock.yaml apps/mobile/app.config.ts; apps/mobile/modules/t3-composer-editor/ios/T3ComposerEditorModule.swift; apps/mobile/modules/t3-composer-editor/ios/T3ComposerEditorView.swift; apps/mobile/package.json; apps/mobile/src/components/GlassSurface.tsx; apps/mobile/src/features/threads/use-composer-command-menu.test.ts; apps/mobile/src/features/threads/use-composer-command-menu.ts; apps/mobile/src/features/voice-input/ComposerDictationControl.tsx; apps/mobile/src/features/voice-input/useVoiceInputController.ts; apps/mobile/src/features/voice-input/voiceInputMetering.test.ts; apps/mobile/src/features/voice-input/voiceInputMetering.ts; apps/mobile/src/features/voice-input/voiceInputPresentation.test.ts; apps/mobile/src/features/voice-input/voiceInputPresentation.ts; apps/mobile/src/native/T3ComposerEditor.ios.tsx; apps/mobile/src/native/T3ComposerEditor.native.tsx; apps/mobile/src/native/T3ComposerEditor.tsx; apps/mobile/src/native/T3ComposerEditor.types.ts; apps/mobile/src/native/voiceTranscription.ios.test.ts; apps/mobile/src/native/voiceTranscription.ios.ts; apps/mobile/src/native/voiceTranscription.ts; docs/internals/voice-input.md; packages/client-runtime/README.md; packages/client-runtime/src/voice-input/controller.test.ts; packages/client-runtime/src/voice-input/controller.ts; packages/client-runtime/src/voice-input/index.ts; packages/client-runtime/src/voice-input/transcription.ts; patches/@react-native-ai__apple@0.12.0.patch; patches/expo-audio@57.0.4.patch; pnpm-workspace.yaml +8b817cbcaad71a53e2ef73f3881067f8aa8094bc fix(web): use circle alert for failed tool calls (#8840) review-v2-path 2 0 2 apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx +17c48f7fc1af66110706b013bf41901ebcd8aedb fix(web): fold interim turn responses (#8828) review-v2-path 2 0 2 apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.logic.ts +e4f7b14fab0850bff134a3f6bfaf5b71cc8ac9fc chore: add Windows setup script to t3.json (#8814) identical-final-files 1 1 0 t3.json +c1e70b5f8c93428c1fe7af62f24ee6ff2bffff6e fix(web,mobile): render Codex citations and artifact templates (#8584) review-v2-path 19 9 10 apps/mobile/src/features/threads/ThreadDetailScreen.tsx; apps/mobile/src/features/threads/ThreadFeed.tsx; apps/web/src/components/ChatView.logic.test.ts; apps/web/src/components/ChatView.logic.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.logic.ts; apps/web/src/components/chat/MessagesTimeline.tsx; packages/client-runtime/package.json; pnpm-lock.yaml apps/web/src/components/ChatMarkdown.test.tsx; apps/web/src/components/ChatMarkdown.tsx; apps/web/src/markdown-clipboard.test.ts; packages/client-runtime/src/codexArtifactTemplates.test.ts; packages/client-runtime/src/codexArtifactTemplates.ts; packages/client-runtime/src/codexFileCitations.test.ts; packages/client-runtime/src/codexFileCitations.ts; packages/client-runtime/src/codexMarkdownDirectives.test.ts; packages/client-runtime/src/codexMarkdownDirectives.ts +e09b88b6a51bb7e4309498f01c2f36bf5ada43f4 fix(web): keep right panel synced with agent edits (#8803) review-v2-path 7 4 3 apps/web/src/components/ChatView.tsx; apps/web/src/components/DiffPanel.tsx; apps/web/src/components/files/FilePreviewPanel.tsx apps/web/src/components/files/FileBrowserPanel.tsx; apps/web/src/components/files/projectFilesQueryState.test.tsx; apps/web/src/hooks/useWorkspaceMutationRefresh.test.ts; apps/web/src/hooks/useWorkspaceMutationRefresh.ts +5885a68adb61805460047512040838bbb5e7ed65 fix(web): keep image preview above sidebar control (#8811) identical-final-files 1 1 0 apps/web/src/components/chat/ExpandedImageDialog.tsx +9072aa1fd711170af425bf6a1a2828d0d54bbfa6 fix(server): stop overpricing cached Claude tokens (#8806) identical-final-files 4 4 0 apps/server/src/usage/usagePricing.test.ts; apps/server/src/usage/usagePricing.ts; apps/server/src/usage/usageScanCache.test.ts; apps/server/src/usage/usageScanCache.ts +60f2ce0279d524bd70a573f6e0b6e9fab56e4b3e fix(git): follow repository instructions in generated source control text (#8804) identical-final-files 4 4 0 apps/server/src/git/GitManager.test.ts; apps/server/src/git/GitManager.ts; apps/server/src/textGeneration/TextGenerationPrompts.ts; docs/user/source-control.md +8f525af5afa93dff58775030d9b503d3bda36b7b fix(web): open agent images in expanded preview (#8807) review-v2-path 2 1 1 apps/web/src/components/chat/MessagesTimeline.tsx apps/web/src/components/ChatMarkdown.tsx +12fe2d6d03062c5d7fc3beff168f8c4af1235b50 fix(windows): strip quotes from repaired PATH (#8746) identical-final-files 4 4 0 apps/desktop/src/shell/DesktopShellEnvironment.test.ts; apps/desktop/src/shell/DesktopShellEnvironment.ts; packages/shared/src/shell.test.ts; packages/shared/src/shell.ts +6e324b9bbfc72e694c3c16abeb59716c37fc02d5 fix(web): reduce title bar scroll fade height (#8799) review-v2-path 5 1 4 apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx; apps/web/src/index.css; apps/web/src/routes/_chat.pull-requests.tsx apps/web/src/components/settings/settingsLayout.tsx +86c9a9288b5704e79bbe68fb0834d56036456f3e feat(mobile): pick, share, and receive files in threads (#8237) review-v2-path 47 37 10 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx; apps/mobile/src/features/threads/ThreadComposer.tsx; apps/mobile/src/features/threads/ThreadDetailScreen.tsx; apps/mobile/src/features/threads/ThreadFeed.tsx; apps/mobile/src/features/threads/ThreadRouteScreen.tsx; apps/mobile/src/lib/projectThreadStartTurn.ts; apps/mobile/src/state/use-thread-composer-state.ts; apps/mobile/src/state/use-thread-outbox-drain.ts; docs/user/composer.md; pnpm-lock.yaml apps/mobile/app.config.ts; apps/mobile/src/components/ComposerAttachmentStrip.tsx; apps/mobile/src/connection/platform.ts; apps/mobile/src/features/home/usePendingTaskListActions.ts; apps/mobile/src/features/sharing/IncomingShareProvider.tsx; apps/mobile/src/features/sharing/incoming-share-inbox.test.ts; apps/mobile/src/features/sharing/incoming-share-inbox.ts; apps/mobile/src/features/sharing/incoming-share-model.test.ts; apps/mobile/src/features/sharing/incoming-share-model.ts; apps/mobile/src/features/sharing/incoming-share-storage.test.ts; apps/mobile/src/features/sharing/incoming-share-storage.ts; apps/mobile/src/features/threads/NewTaskRouteScreen.tsx; apps/mobile/src/features/threads/new-task-flow-provider.tsx; apps/mobile/src/features/threads/use-project-actions.ts; apps/mobile/src/lib/attachmentDownload.test.ts; apps/mobile/src/lib/attachmentDownload.ts; apps/mobile/src/lib/attachmentUpload.test.ts; apps/mobile/src/lib/attachmentUpload.ts; apps/mobile/src/lib/composer-image-schema.ts; apps/mobile/src/lib/composerAttachmentFiles.test.ts; apps/mobile/src/lib/composerAttachmentFiles.ts; apps/mobile/src/lib/composerFiles.test.ts; apps/mobile/src/lib/composerImages.ts; apps/mobile/src/state/attachments.ts; apps/mobile/src/state/pending-task-editor-writes.test.ts; apps/mobile/src/state/pending-task-editor-writes.ts; apps/mobile/src/state/thread-outbox-manager.ts; apps/mobile/src/state/thread-outbox-model.ts; apps/mobile/src/state/thread-outbox-removal.test.ts; apps/mobile/src/state/thread-outbox-removal.ts; apps/mobile/src/state/thread-outbox.test.ts; apps/mobile/src/state/thread-outbox.ts; apps/mobile/src/state/use-composer-drafts.test.ts; apps/mobile/src/state/use-composer-drafts.ts; apps/mobile/src/state/use-thread-outbox-drain.test.ts; patches/expo-sharing@57.0.16.patch; pnpm-workspace.yaml +7880a6e583f8a04db2eaeef2366ce9c81c3f7bec fix(grok): allow model changes in existing threads (#8392) review-v2-path 2 1 1 apps/server/src/provider/Layers/GrokProvider.ts apps/server/src/provider/Layers/GrokProvider.test.ts +7980dfddb193864e07a5bcc013b0ccb93fb4300c fix(web,mobile): snooze menu no longer offers the same wake time twice (#8741) review-v2-path 2 1 1 packages/client-runtime/src/state/threadSettled.ts packages/client-runtime/src/state/threadSnoozed.test.ts +ac4aae101d060b5355a5de58e23c7387886d9021 feat(web): play video attachments in chat (#8688) review-v2-path 23 13 10 apps/server/src/http.test.ts; apps/web/src/components/ChatView.logic.test.ts; apps/web/src/components/ChatView.logic.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/ChatComposer.tsx; apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx; apps/web/src/composerDraftStore.ts; apps/web/src/types.ts; docs/user/composer.md apps/desktop/src/electron/ElectronProtocol.test.ts; apps/desktop/src/electron/ElectronProtocol.ts; apps/server/src/assets/AssetAccess.test.ts; apps/server/src/assets/AssetAccess.ts; apps/server/src/http.ts; apps/web/src/components/chat/ExpandedImageDialog.test.tsx; apps/web/src/components/chat/ExpandedImageDialog.tsx; apps/web/src/components/chat/ExpandedImagePreview.test.ts; apps/web/src/components/chat/ExpandedImagePreview.tsx; apps/web/src/components/chat/composerAttachmentFiles.test.ts; apps/web/src/components/chat/composerAttachmentFiles.ts; apps/web/src/components/pullRequest/PullRequestMarkdown.tsx; apps/web/src/composerDraftStore.test.ts +f15680bd3c08a154bacb9b4d163cc8608a310970 feat(mobile): update tool summaries and chat transitions (#8793) review-v2-path 14 5 9 apps/mobile/src/features/threads/ThreadComposer.tsx; apps/mobile/src/features/threads/ThreadDetailScreen.tsx; apps/mobile/src/features/threads/ThreadFeed.tsx; apps/mobile/src/lib/threadActivity.test.ts; apps/mobile/src/lib/threadActivity.ts; apps/web/src/components/chat/MessagesTimeline.tsx; packages/client-runtime/package.json; packages/client-runtime/src/work-log/presentation.ts; pnpm-lock.yaml apps/mobile/src/features/threads/floating-working-control.tsx; apps/mobile/src/features/threads/thread-work-log.tsx; packages/client-runtime/src/work-log/commandLabel.ts; patches/@legendapp__list@3.3.5.patch; patches/react-native-keyboard-controller@1.21.13.patch +2daff8c25adf701fddd062ae93b94cc57d420ec2 test(web): remove tests for unreachable helpers (#8738) review-v2-path 13 0 13 apps/web/src/appearanceFonts.test.ts; apps/web/src/appearanceFonts.ts; apps/web/src/components/Sidebar.logic.test.ts; apps/web/src/components/Sidebar.logic.ts; apps/web/src/pendingUserInput.test.ts; apps/web/src/pendingUserInput.ts; apps/web/src/providerUpdateDismissal.test.ts; apps/web/src/providerUpdateDismissal.ts; apps/web/src/threadSync.test.ts; apps/web/src/timestampFormat.test.ts; apps/web/src/timestampFormat.ts; apps/web/src/versionSkew.test.ts; apps/web/src/versionSkew.ts +8dcb96314c976899e4df6951fb9af03131c2a46f revert(web): restore previous composer banners (#8733) review-v2-path 33 17 16 apps/web/src/components/BranchToolbar.tsx; apps/web/src/components/ChatView.logic.test.ts; apps/web/src/components/ChatView.logic.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/ChatComposer.tsx; apps/web/src/components/chat/ComposerPendingApprovalPanel.tsx; apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx; apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.logic.ts; apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx; apps/web/src/index.css; apps/web/src/session-logic.test.ts; apps/web/src/session-logic.ts; apps/web/src/versionSkew.test.ts; apps/web/src/versionSkew.ts apps/web/src/components/chat/ComposerActivityStatus.tsx; apps/web/src/components/chat/ComposerBanner.tsx; apps/web/src/components/chat/ComposerBannerStack.test.tsx; apps/web/src/components/chat/ComposerBannerStack.tsx; apps/web/src/components/chat/ComposerCommandMenu.test.tsx; apps/web/src/components/chat/ComposerCommandMenu.tsx; apps/web/src/components/chat/ComposerPlanFollowUpBanner.tsx; apps/web/src/components/chat/ComposerServerUpdateStatus.tsx; apps/web/src/components/chat/ComposerStashBadge.test.tsx; apps/web/src/components/chat/ComposerStashBadge.tsx; apps/web/src/components/chat/ComposerStashMenu.test.tsx; apps/web/src/components/chat/ComposerStashMenu.tsx; apps/web/src/components/chat/ComposerSurface.tsx; apps/web/src/components/chat/ComposerTasksBadge.test.tsx; apps/web/src/components/chat/ComposerTasksBadge.tsx; apps/web/src/components/chat/ThreadSyncStatusPill.test.tsx; apps/web/src/components/chat/ThreadSyncStatusPill.tsx +1f8ed54add4133ac39effceded8fc1fff12d8e03 fix(mobile): reduce dev-client reload and Metro startup cost (#8694) review-v2-path 31 27 4 apps/mobile/src/connection/runtime.ts; apps/mobile/src/features/home/HomeScreen.tsx; packages/client-runtime/src/connection/registry.test.ts; pnpm-lock.yaml .agents/skills/test-t3-mobile/SKILL.md; AGENTS.md; apps/mobile/README.md; apps/mobile/app.config.ts; apps/mobile/package.json; apps/mobile/src/components/AppSymbol.ios.tsx; apps/mobile/src/components/AppSymbol.tabler.d.ts; apps/mobile/src/components/AppSymbol.tsx; apps/mobile/src/components/ControlPill.tsx; apps/mobile/src/features/home/HomeRouteScreen.tsx; apps/mobile/src/features/home/home-thread-navigation.test.ts; apps/mobile/src/features/home/home-thread-navigation.ts; apps/mobile/src/features/home/thread-swipe-actions.tsx; apps/mobile/src/lib/foundation-fast-refresh.ts; apps/mobile/src/lib/hot-swappable-atom-runtime.test.ts; apps/mobile/src/lib/hot-swappable-atom-runtime.ts; apps/mobile/src/lib/runtime.ts; apps/mobile/src/lib/uniwind-dev-refresh.test.ts; apps/mobile/src/state/atom-registry.ts; apps/mobile/src/state/remote-environment-projections.test.ts; apps/mobile/src/state/remote-environment-projections.ts; apps/mobile/src/state/use-remote-environment-registry.ts; docs/internals/mobile-development.md; packages/client-runtime/src/connection/registry.ts; patches/@react-native-menu__menu@2.0.0.patch; patches/uniwind@1.11.0.patch; pnpm-workspace.yaml +3d32797f6f4614205debf8a61f09e950f5f9a81c fix(web): unify activity logs and composer banners (#8693) review-v2-path 33 17 16 apps/web/src/components/BranchToolbar.tsx; apps/web/src/components/ChatView.logic.test.ts; apps/web/src/components/ChatView.logic.ts; apps/web/src/components/ChatView.tsx; apps/web/src/components/chat/ChatComposer.tsx; apps/web/src/components/chat/ComposerPendingApprovalPanel.tsx; apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx; apps/web/src/components/chat/MessagesTimeline.logic.test.ts; apps/web/src/components/chat/MessagesTimeline.logic.ts; apps/web/src/components/chat/MessagesTimeline.test.tsx; apps/web/src/components/chat/MessagesTimeline.tsx; apps/web/src/index.css; apps/web/src/session-logic.test.ts; apps/web/src/session-logic.ts; apps/web/src/versionSkew.test.ts; apps/web/src/versionSkew.ts apps/web/src/components/chat/ComposerActivityStatus.tsx; apps/web/src/components/chat/ComposerBanner.tsx; apps/web/src/components/chat/ComposerBannerStack.test.tsx; apps/web/src/components/chat/ComposerBannerStack.tsx; apps/web/src/components/chat/ComposerCommandMenu.test.tsx; apps/web/src/components/chat/ComposerCommandMenu.tsx; apps/web/src/components/chat/ComposerPlanFollowUpBanner.tsx; apps/web/src/components/chat/ComposerServerUpdateStatus.tsx; apps/web/src/components/chat/ComposerStashBadge.test.tsx; apps/web/src/components/chat/ComposerStashBadge.tsx; apps/web/src/components/chat/ComposerStashMenu.test.tsx; apps/web/src/components/chat/ComposerStashMenu.tsx; apps/web/src/components/chat/ComposerSurface.tsx; apps/web/src/components/chat/ComposerTasksBadge.test.tsx; apps/web/src/components/chat/ComposerTasksBadge.tsx; apps/web/src/components/chat/ThreadSyncStatusPill.test.tsx; apps/web/src/components/chat/ThreadSyncStatusPill.tsx +c0e09f323ac9f6bf4b9119cbad841db3379588d6 fix(web): render nested markdown images correctly (#8501) review-v2-path 8 7 1 apps/web/src/components/files/FilePreviewPanel.tsx apps/web/src/components/ChatMarkdown.tsx; apps/web/src/components/ChatMarkdown.workspace-images.test.tsx; apps/web/src/components/files/FileMarkdownPreview.tsx; apps/web/src/markdown-links.test.ts; apps/web/src/markdown-links.ts; packages/client-runtime/src/markdownImages.test.ts; packages/client-runtime/src/markdownImages.ts +72c44a847c0a76f33b0d21f47548125b7032ec35 perf(desktop): skip duplicate browser updates (#8018) identical-final-files 4 4 0 apps/desktop/src/preview/Manager.test.ts; apps/desktop/src/preview/Manager.ts; apps/web/src/previewStateStore.test.ts; apps/web/src/previewStateStore.ts +660cddd3bc9801e089afcabba11c62f41aeac5c3 fix(web): four composer spacing defects (#8090) review-v2-path 6 3 3 apps/web/src/components/ChatView.logic.test.ts; apps/web/src/components/ChatView.logic.ts; apps/web/src/components/ChatView.tsx apps/web/src/components/chat/ComposerStashBadge.tsx; apps/web/src/components/chat/ComposerTasksBadge.test.tsx; apps/web/src/components/chat/ComposerTasksBadge.tsx +ebb9b9fda03d33a81cad3ce7f4d1106adba3044b fix(client-runtime): refresh edited pull request comments (#8094) identical-final-files 2 2 0 packages/client-runtime/src/state/pullRequests.test.ts; packages/client-runtime/src/state/pullRequests.ts +fc262f1a28d8305951c751f2486da6ca72e6c1d1 fix(server): retry automatic thread title generation (#8087) review-v2-path 2 0 2 apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts; apps/server/src/orchestration/Layers/ProviderCommandReactor.ts diff --git a/audits/orchestrator-v2/2026-09-02/main-since-prior.txt b/audits/orchestrator-v2/2026-09-02/main-since-prior.txt new file mode 100644 index 000000000000..913cbdcb05cc --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/main-since-prior.txt @@ -0,0 +1,165 @@ +57a66608b9 fix(pull-requests): align checkout control with author (#9196) +6e3bac3722 fix(web): prevent connection rows from wrapping during removal (#8706) +6effe0a2fa feat(web): redesign provider editor and models list (#8508) +bc918e74ac fix(server): discover project skills for Claude (#9210) +70cd258d8a fix(web): prevent two-digit list markers from being clipped (#9101) +f14f41b894 fix(web): preserve composer draft during worktree setup (#9197) +7e9d5a7efa fix(mobile): prevent message and composer overlap (#9195) +5b7d72aad1 feat(updates): continue active threads across server restarts (#9167) +14f15cfed4 fix(server): stop titling linked PR threads from local git history (#9191) +dd6879ffea fix(pull-requests): reuse github api reads (#9176) +9e646ad84c fix(connect): refresh relay credentials before expiry (#9178) +a19f01fc19 feat(web): make context window indicator opt-in (#9190) +6ff537f03c fix(web): remove projects with archived threads (#8798) +a81a52afbb fix(server): allow local-only worktree bases (#8751) +a56b0cd717 fix(server): allow large Azure DevOps PR lists (#8572) +4116db9807 fix(server): bound OpenCode version probes (#8750) +d2042d288e fix(web): avoid stale file writes on close (#8630) +7a8df3338f fix(desktop): skip cached monitor compiler check (#9184) +827345a07a fix(web): model info button opens its details on click (#9177) +5392c9bb99 fix(models): restore sticky new-thread selections (#9164) +535c83dea5 fix(web): copying a code block no longer copies triple backticks (#8448) +f9d1c65d47 chore: bump vendored GhosttyKit and update terminal integration (#9155) +0681d85499 fix(pull-requests): expand code tab diffs by default (#9174) +80a14b6588 fix(server): discover project skills for Codex and OpenCode (#8778) +082358f9ef fix(desktop): check artifact build prerequisites (#8975) +43bafd4674 fix(web): open PR toast actions in app (#9006) +8339508f5c fix(chat): align failed task progress test (#9172) +c15735dd88 fix(chat): replace failed tools with thinking (#9165) +133db22fae feat(web): copy the full error report from the error page (#9166) +b520120cf1 fix(chat): improve tool group summaries and scrolling (#9106) +db4bf9497b chore: remove unused code and brittle tests (#9150) +b8262b4122 fix(desktop): hold-to-quit no longer gets stuck (#9141) +cde12790d7 fix(contracts): accept legacy pull request checkout results (#8238) +a1a2bb1cd9 fix(web): label keybinding condition removal actions (#8664) +e9db39ce05 fix(web): align composer notices and stash (#8890) +941acb4f91 fix(provider): drop removed custom models from the model picker (#9075) +e7deb2aaf4 feat(web): cite assistant responses with inline citations (#9146) +2ab7973fe0 fix(web): hide build pill in narrow sidebars (#9159) +9fdafdf114 feat(pull-requests): copy provider checkout commands (#9086) +47a95332a2 fix(web): browse folders from file breadcrumbs (#8910) +fea1af81fd fix(web): compact project settings actions (#9160) +d937e30759 feat(web): render HTML and PDF files in the file viewer (#9143) +f46a709ee4 feat(files): open markdown, HTML, and PDF files outside the workspace (#9140) +f2a914b858 fix(web): preserve panel state across workspace refreshes (#8968) +8401f4d858 fix(web): darken neutral control surfaces (#9064) +0e1570bde5 fix(web): project default model works on the hosted app (#9142) +c37fd136ed test(server): measure shell, second client, and reconnect transfer (#9157) +b2f25d390a feat(desktop): update the desktop app on remote Macs from the Update button (#6554) +80c708a1fa perf(web): halve the cold-start bundle by splitting Clerk and cold routes (#9058) +a434677eca fix(grok): health check, model selection, and stop all work against the real CLI (#9154) +083d4de5b0 fix(clients): stop repeating expanded commands (#9120) +cdbf324aa0 fix(web): keep generated muted foreground dimmer than entered text (#9113) +d0b19b32e0 fix(claude): preview images read from the workspace (#9119) +716069f40f fix(server): keep attachments until the command commits (#7941) +0e77fbd3d0 fix(server): prevent accidental service downgrades (#5302) +8efd4e95fc fix(settings): sync auto-settle and other shared preferences across environments (#9147) +5014e5fcdd fix(desktop): show newest changes in nightly previews (#9138) +fc53b27303 perf(clients): lease sidebar status by visibility (#9052) +6866fd6b5c perf(client-runtime): keep turn and checkpoint refs stable while streaming (#9145) +7e460f429b fix(server): bound orchestration replay payloads (#8992) +c2283ce146 perf: make streaming projection and activity appends incremental (#9152) +feb3ea7ebf fix(web): stop highlighter freezes and worker spin by using the Oniguruma WASM engine (#8360) +ea71a19d41 fix(claude): skills picked from the composer now run (#9128) +9a7b1e21e5 perf(provider): bound persisted session lookups (#8909) +98725df00a fix(web): mute routine notices and update actions (#9063) +08aad594f0 chore: delete dead code, unused deps, and duplicate helpers (#9129) +b21d87243e chore: vouch six repeat contributors (#9131) +04efa7907e feat(cli): open projects in the running desktop app (#8824) +beae2147a9 fix(media): preview host files and stream videos across clients (#9023) +60cef47ec9 chore(release): prepare v0.0.38 +590a579f2e fix(chat): keep latest command live between messages (#9098) +0222aa255d fix(web): preserve theme when toggling advanced colors (#8500) +c0995d2eaf fix(web): keep the selected environment when changing projects (#9102) +d0b4acbd13 fix(web): keep theme placeholder text dimmer than entered text (#9104) +3b3465f2a9 fix(web): changing projects no longer creates a draft (#9097) +692eb1a579 fix(web): sync sidebar PR state from open panel (#9092) +163d50846b Revert "fix(chat): reuse one row for live activity" (#9096) +0354283683 feat(models): discover Claude models from remote manifest (#9084) +a924fbe08e fix(chat): reuse one row for live activity (#9062) +cb00746916 feat(web): open project settings from thread menus (#8925) +9d1879b142 feat(desktop): add configurable quit shortcut confirmation (#9076) +ef7014d851 fix(preview): restore recording and macOS rendering after Electron 43 (#9001) +c17d02cff9 feat(claude): add Claude Fable 5.1 model (#9078) +643b21edaa fix(server): cache project favicon resolution (#9080) +261380f91f fix(mobile): keep thread scroll bounds current after animations (#9013) +2d156a83b9 feat(shortcuts): copy active thread reference (#8994) +b5b6abb11e fix(web): block type-to-focus behind open dialogs (#8139) +9dbdcece5f fix(web): align un-settle banner action (#9033) +b883fc066e perf(client-runtime): halve server config bootstrap traffic (#8367) +e86604d337 perf(server): skip full-message reads while streaming (#9032) +3c73fa7ce0 perf(web): defer pull request line stats until visible (#6471) +62d39bf00d fix(server): stop OpenCode child sessions (#9005) +8b033de482 fix(clients): dedupe skills in composer menus (#8043) +f32f9a2f41 fix(server): settle threads server-side (#8600) +7e4ce3bbb1 perf(server): cut chatty tool-update frames by 90% (#8368) +8f1ef8b9eb perf(server): scan only appended transcript bytes for usage summaries (#9024) +0bfb6df34b perf(server): cut idle CPU use and stop provider event leaks (#8187) +a9ffb82796 perf(server): bound snapshot activity payload memory (#9000) +73776d4e52 test: remove static presentation snapshots (#9008) +0947c30e69 fix(client): use package import for markdown image helpers (#9010) +ce71c04f0a feat(client): render viewed images in work logs (#8936) +ff93aba61d feat(web): search individual settings by detail (#8831) +d35c71d1b9 feat(web): add pull request list filters (#8809) +b17cc3d1bf perf(server): reduce frequency of full tool call output being loaded into memory from db (#8988) +42a8fd5103 feat(pull-requests): link GitHub references in markdown (#8812) +c78ae50a5a fix(server): isolate remote web session cookies (#8085) +9ecfc07a8b fix(chat): keep agent activity visible between actions (#8984) +9bc7a56848 feat(mobile): upload attachments while composing (#8978) +85b656ff30 style: format CodeRabbit configuration +0df043fd4e Add auto_review configuration to coderabbit.yaml +17f00f6024 feat(web): add expand/collapse all control to the files surface (#8889) +c50b0b4ef8 fix(web): make WSL settings searchable (#8881) +929f7e6479 fix(shared): preserve Windows shell PATH priority (#8748) +41adccc83e fix(server): allow long thread IDs in HTTP routes (#8898) +f8e4accf27 feat(mobile): add native image and PDF previews (#8959) +6d15c5bbc3 fix(server): preserve usage cache outside walked roots (#8540) +f47e74004a fix(web): prevent chat metadata overlap (#8851) +31c1c5996f feat(mobile): add video playback with native iOS controls (#8919) +ef84bc9873 fix(chat): smooth worktree setup status (#8922) +4a9d2d0ced chore(deps): bump Electron to 43.4.1 (#8626) +5ce92c2f19 fix(mobile): shimmer active tool rows (#8932) +35da581331 fix(web): show scrollbar for wide markdown tables (#8868) +038bf3739b Delete app.json (#8934) +4e8e64fc06 chore: disable CodeRabbit review status (#8933) +746c932e16 fix(mobile): defer draft navigation until submission completes (#8914) +bba79cc254 fix(web): hide invalid slash skill completions (#8904) +2921050c69 fix(contracts): accept CLI event origins (#8905) +ad38700ac6 chore(macroscope): review diagnostic overrides (#8917) +f86c5e8c87 fix(server): skip IDE detection in Claude probes (#8634) +9b2d04317c fix(mobile): replace Callstack glass with Expo glass (#8862) +e9c4775e87 fix(web): mark pull request links as external (#8856) +3958111057 fix(preview): improve browser recording quality (#8839) +3f62e6fa65 fix(web): widen sync banners and simplify the working timer (#8855) +9842518c9a fix(web): address composer banner review follow-ups (#8850) +30175a8af0 fix(web): restore unified activity logs and composer banners (#8734) +f9137a0c89 fix(mobile): map native menu icon colors explicitly +e3dcc1615c Add mobile composer attachment menu with video support (#8843) +7963ac7404 chore(release): prepare v0.0.37 +cefec32d6f fix(web): prevent pull request metadata overlap (#8790) +352710d497 feat(mobile): add offline iPhone voice input (#8614) +8b817cbcaa fix(web): use circle alert for failed tool calls (#8840) +17c48f7fc1 fix(web): fold interim turn responses (#8828) +e4f7b14fab chore: add Windows setup script to t3.json (#8814) +c1e70b5f8c fix(web,mobile): render Codex citations and artifact templates (#8584) +e09b88b6a5 fix(web): keep right panel synced with agent edits (#8803) +5885a68adb fix(web): keep image preview above sidebar control (#8811) +9072aa1fd7 fix(server): stop overpricing cached Claude tokens (#8806) +60f2ce0279 fix(git): follow repository instructions in generated source control text (#8804) +8f525af5af fix(web): open agent images in expanded preview (#8807) +12fe2d6d03 fix(windows): strip quotes from repaired PATH (#8746) +6e324b9bbf fix(web): reduce title bar scroll fade height (#8799) +86c9a9288b feat(mobile): pick, share, and receive files in threads (#8237) +7880a6e583 fix(grok): allow model changes in existing threads (#8392) +7980dfddb1 fix(web,mobile): snooze menu no longer offers the same wake time twice (#8741) +ac4aae101d feat(web): play video attachments in chat (#8688) +f15680bd3c feat(mobile): update tool summaries and chat transitions (#8793) +2daff8c25a test(web): remove tests for unreachable helpers (#8738) +8dcb96314c revert(web): restore previous composer banners (#8733) +1f8ed54add fix(mobile): reduce dev-client reload and Metro startup cost (#8694) +3d32797f6f fix(web): unify activity logs and composer banners (#8693) +c0e09f323a fix(web): render nested markdown images correctly (#8501) +72c44a847c perf(desktop): skip duplicate browser updates (#8018) +660cddd3bc fix(web): four composer spacing defects (#8090) +ebb9b9fda0 fix(client-runtime): refresh edited pull request comments (#8094) +fc262f1a28 fix(server): retry automatic thread title generation (#8087) diff --git a/audits/orchestrator-v2/2026-09-02/new-branch-work.txt b/audits/orchestrator-v2/2026-09-02/new-branch-work.txt new file mode 100644 index 000000000000..94a99708310f --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/new-branch-work.txt @@ -0,0 +1,21 @@ +d2f1f511f4 fix: reconcile main's round-20 features after the rebase +0550e0a34d fix(web): realign the composer and timeline with main +e6da41e5c6 fix(web): right-align the stash shoulder tab again +f0174c4577 fix: reconcile main's round-19 features after the rebase +2191297898 feat(server): evaluate automatic thread settlement in the v2 orchestrator +7697286069 fix: reconcile main's round-18 features after the rebase +99e940dc2b feat(web): port working and thinking timeline rows to orchestration v2 +acdbe292f0 fix: reconcile main's round-17 features after the rebase +4b35166d02 fix(mobile): keep scroll bounds current after animations +fa54f54607 fix(chat): remove added tool summary status counts +b27f50b65a feat(mobile): port chat summaries and transitions to orchestration v2 +60bc3cff93 feat(web): summarize T3 orchestration actions +72e0c434be fix(web): keep composer shortcut tooltip stable on Mod +6bcc0e39da fix(web): match composer actions to draft and modifier state +6ce4cb0a15 fix(web): keep queued messages in place while editing +e16d934d8a fix(web): keep queued message editing inside the queue panel +b2afc4cb45 refactor(web): use shared banner rows for queued messages +85a3c12568 fix(web): keep stash separate from the composer activity column +e82c717855 fix(web): share the outline for joined composer tabs +b1533813ce fix(web): align queue headers and prevent stash overlap +ed6aafa93f fix(web): port composer activity and grouping to orchestration v2 diff --git a/audits/orchestrator-v2/2026-09-02/persistence-runtime-probes.test.ts b/audits/orchestrator-v2/2026-09-02/persistence-runtime-probes.test.ts new file mode 100644 index 000000000000..1c843a5fd740 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/persistence-runtime-probes.test.ts @@ -0,0 +1,210 @@ +import { assert, it } from "../../../apps/server/node_modules/@effect/vitest/dist/index.js"; +import { + EventId, + type ModelSelection, + NodeId, + type OrchestrationV2AppThread, + type OrchestrationV2DomainEvent, + ProjectId, + ProviderInstanceId, + ProviderThreadId, + RunId, + ThreadId, +} from "../../../apps/server/node_modules/@t3tools/contracts/src/index.ts"; +import * as Cause from "../../../apps/server/node_modules/effect/dist/Cause.js"; +import * as DateTime from "../../../apps/server/node_modules/effect/dist/DateTime.js"; +import * as Effect from "../../../apps/server/node_modules/effect/dist/Effect.js"; +import * as SqlClient from "../../../apps/server/node_modules/effect/dist/unstable/sql/SqlClient.js"; + +import { + IdAllocatorV2, + layer as idAllocatorLayer, +} from "../../../apps/server/src/orchestration-v2/IdAllocator.ts"; +import { + applyToProjection, + emptyProjection, + threadShellFromProjection, +} from "../../../apps/server/src/orchestration-v2/ProjectionStore.ts"; +import { shouldAutoSettleThread } from "../../../apps/server/src/orchestration-v2/ThreadSettlementService.ts"; +import { + migrationEntries, + runMigrations, +} from "../../../apps/server/src/persistence/Migrations.ts"; +import * as NodeSqliteClient from "../../../apps/server/src/persistence/NodeSqliteClient.ts"; + +const providerInstanceId = ProviderInstanceId.make("codex"); +const modelSelection = { + instanceId: providerInstanceId, + model: "gpt-5.4", +} satisfies ModelSelection; + +function makeThread(threadId: ThreadId, now: DateTime.Utc): OrchestrationV2AppThread { + return { + createdBy: "user", + creationSource: "web", + id: threadId, + projectId: ProjectId.make(`project:${threadId}`), + title: `Thread ${threadId}`, + providerInstanceId, + modelSelection, + runtimeMode: "full-access", + interactionMode: "default", + branch: null, + worktreePath: null, + activeProviderThreadId: null, + lineage: { + parentThreadId: null, + relationshipToParent: null, + rootThreadId: threadId, + }, + forkedFrom: null, + createdAt: now, + updatedAt: now, + archivedAt: null, + settledOverride: null, + settledAt: null, + lastVisitedAt: null, + deletedAt: null, + }; +} + +function threadCreatedEvent( + thread: OrchestrationV2AppThread, + now: DateTime.Utc, +): Extract { + return { + id: EventId.make(`event:create:${thread.id}`), + type: "thread.created", + threadId: thread.id, + providerInstanceId, + occurredAt: now, + payload: thread, + }; +} + +it.effect("reproduces the old-052 to current-053 migration failure", () => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + yield* runMigrations({ toMigrationInclusive: 43 }); + + // Current 45-53 are the byte-equivalent old branch 44-52 bodies. Apply + // them under their old IDs/names to reproduce a database from c1791ab2637. + for (const [currentId, name, migration] of migrationEntries.filter(([id]) => id >= 45)) { + yield* migration; + yield* sql` + INSERT INTO effect_sql_migrations (migration_id, name) + VALUES (${currentId - 1}, ${name}) + `; + } + + const before = yield* sql<{ readonly migration_id: number; readonly name: string }>` + SELECT migration_id, name + FROM effect_sql_migrations + ORDER BY migration_id DESC + LIMIT 1 + `; + assert.deepStrictEqual(before, [{ migration_id: 52, name: "LegacyV1ImportState" }]); + + const exit = yield* Effect.exit(runMigrations()); + assert.strictEqual(exit._tag, "Failure"); + if (exit._tag === "Failure") { + assert.match(Cause.pretty(exit.cause), /Migration "53_LegacyV1ImportState" failed/); + assert.match(Cause.pretty(exit.cause), /already exists/); + } + + const after = yield* sql<{ readonly migration_id: number; readonly name: string }>` + SELECT migration_id, name + FROM effect_sql_migrations + ORDER BY migration_id DESC + LIMIT 1 + `; + assert.deepStrictEqual(after, before); + }).pipe(Effect.provide(NodeSqliteClient.layerMemory())), +); + +it.effect("reproduces production root-scope reuse across ordinary runs", () => + Effect.gen(function* () { + const ids = yield* IdAllocatorV2; + const threadId = ThreadId.make("thread:audit-scope"); + const now = DateTime.makeUnsafe("2026-09-02T00:00:00.000Z"); + const firstScopeId = yield* ids.allocate.checkpointScope({ threadId, name: "root" }); + const secondScopeId = yield* ids.allocate.checkpointScope({ threadId, name: "root" }); + const firstRunId = RunId.make("run:audit-scope:1"); + const secondRunId = RunId.make("run:audit-scope:2"); + const providerThreadId = ProviderThreadId.make("provider-thread:audit-scope"); + let projection = emptyProjection(threadCreatedEvent(makeThread(threadId, now), now)); + const scopeEvent = ( + eventId: EventId, + scopeId: typeof firstScopeId, + runId: RunId, + nodeId: NodeId, + ): Extract => ({ + id: eventId, + type: "checkpoint-scope.created", + threadId, + runId, + nodeId, + occurredAt: now, + payload: { + id: scopeId, + threadId, + runId, + nodeId, + parentScopeId: null, + providerThreadId, + kind: "root_run", + ordinalWithinParent: 0, + advancesAppRunCount: true, + cwd: "/repo", + createdAt: now, + }, + }); + + projection = applyToProjection( + projection, + scopeEvent( + EventId.make("event:scope:1"), + firstScopeId, + firstRunId, + NodeId.make("node:scope:1"), + ), + ); + projection = applyToProjection( + projection, + scopeEvent( + EventId.make("event:scope:2"), + secondScopeId, + secondRunId, + NodeId.make("node:scope:2"), + ), + ); + + assert.strictEqual(firstScopeId, secondScopeId); + assert.strictEqual(projection.checkpointScopes.length, 1); + assert.strictEqual(projection.checkpointScopes[0]?.runId, secondRunId); + }).pipe(Effect.provide(idAllocatorLayer)), +); + +it("confirms closed PR settlement remains active when optional settings are off", () => { + const now = Date.parse("2026-09-02T12:00:00.000Z"); + const createdAt = DateTime.makeUnsafe(now - 20 * 60_000); + const threadId = ThreadId.make("thread:audit-settlement"); + const projection = emptyProjection( + threadCreatedEvent(makeThread(threadId, createdAt), createdAt), + ); + const thread = threadShellFromProjection(projection); + + assert.strictEqual( + shouldAutoSettleThread({ + thread, + pullRequest: { + state: "closed", + updatedAt: "2026-09-02T12:00:00.000Z", + }, + nowMs: now, + autoSettleAfterDays: null, + autoSettleOnMerge: false, + }), + true, + ); +}); diff --git a/audits/orchestrator-v2/2026-09-02/persistence.md b/audits/orchestrator-v2/2026-09-02/persistence.md new file mode 100644 index 000000000000..63787ece6c9f --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/persistence.md @@ -0,0 +1,236 @@ +# Orchestration V2 persistence, runtime, and performance audit + +Date: 2026-09-02 +Frozen branch: `d2f1f511f4cc833bc930d6c355cd0f9b61e835a0` +Current main: `57a66608b918d673eeec7e6c94ea5906b756fcd0` +Prior reviewed tip: `c1791ab2637` (`47f5b100440591d2f49aa30cf3bb69eacae07f52` before rebase) + +This was a read-only review of `apps/server/src/orchestration-v2` excluding provider adapters, plus the persistence and project boundaries explicitly requested by the root review. No product source or tests were edited. The only writes are this audit report and the retained audit-only probe artifacts beside it. No live database, provider, server, browser, or production state was used. + +## Summary + +I confirmed seven findings: + +| Severity | Classification | Finding | Evidence basis | +| -------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| Blocker | Branch-upgrade rebase regression | Existing V2 databases through old migration 052 fail on current 053, while new main migration 044 is skipped. | Retained actual migration-runner/in-memory SQLite reproduction. | +| High | Preexisting V2 integration bug | WebSocket forced project deletion commits V2 thread deletions before legacy project deletion rejects the still-present imported V1 threads. | Deterministic source trace only; no integrated transport run. | +| High | Preexisting V2 integration bug | HTTP and offline CLI project mutation bypass V2 deletion and drop `force`; create also drops `createWorkspaceRootIfMissing`. | Deterministic source trace only; no integrated transport run. | +| High | V2 correctness gap | Full-thread diff fails after an ordinary second run because production reuses one root scope and updates its `runId`, while the query requires that scope to belong to run 1. | Retained real allocator/projection reproduction plus query source trace. | +| Medium | New auto-settlement regression | A failure that predates a snooze is treated as waking the snoozed thread and can settle it early. | Source and policy-test trace; no timed service run. | +| Medium | Preexisting missed-main performance gap | Checkpoint diff loads an unbounded full V2 thread projection instead of narrow checkpoint context. | SQL/source cardinality trace; not benchmarked. | +| Medium | Preexisting V2 performance gap | Startup recovery loads every persisted row for every active and archived thread before accepting commands. | SQL/source cardinality trace; not benchmarked. | + +The previously fixed token-usage, legacy metadata, migrated search, missing-worktree recovery, unsettled ordering, SQL visibility, stop-request dependency, nested-fork cursor, true-end pagination, and bounded payload invariants remain present at the frozen head. Focused tests passed, but they do not cover the broken upgrade history or populated-project deletion boundaries. + +## Confirmed findings relative to main and prior invariants + +### 1. Blocker: an existing pre-rebase V2 database cannot migrate to the current head + +**Current code.** The current manifest inserts main's `ClearAutomaticProjectModelDefaults` at ID 44 and shifts the old branch migrations to IDs 45 through 53 (`apps/server/src/persistence/Migrations.ts:58-67`, `:123-132`). The migration API documents that only IDs above the latest recorded ID run (`Migrations.ts:156-169`). The underlying Effect migrator implements exactly that rule and does not compare historical names: `currentId <= latestMigrationId` is skipped at `.repos/effect-smol/packages/effect/src/unstable/sql/Migrator.ts:228-259`, specifically `:248-252`. + +Current 053 then unconditionally creates `orchestration_v2_legacy_imports` and its index (`apps/server/src/persistence/Migrations/053_LegacyV1ImportState.ts:9-26`). Neither statement uses `IF NOT EXISTS`. + +**Historical evidence.** At `c1791ab2637`, the branch manifest assigned `OrchestrationV2` through `LegacyV1ImportState` IDs 44 through 52 (`apps/server/src/persistence/Migrations.ts` at that commit, lines 58-66 and 122-130). Old `052_LegacyV1ImportState.ts` and current `053_LegacyV1ImportState.ts` are byte-identical; both hash to `efc494840b8319531495a28a82f6624947e54be9846ee6f5a260cd7eae27fe1c`. Main's new 044 performs data repair in both `projection_projects` and `orchestration_events` (`apps/server/src/persistence/Migrations/044_ClearAutomaticProjectModelDefaults.ts:7-50`). + +**Actual disposable reproduction.** I ran the real current `runMigrations` with the repository's NodeSqlite layer against an in-memory database. The fixture first applied the current schema bodies corresponding to the old branch sequence and recorded the old IDs and names 44 through 52, ending with `[52, "LegacyV1ImportState"]` and an existing `orchestration_v2_legacy_imports` table. On the next current migration run: + +```text +latest before current run: 52_LegacyV1ImportState +current run: MigrationError: Migration "53_LegacyV1ImportState" failed +SQLite cause: table orchestration_v2_legacy_imports already exists +latest after rollback: 52_LegacyV1ImportState +``` + +This exercises the actual migration loader, tracking table, transaction, and SQLite DDL. It does not write any live database. + +**Reachable trigger.** Start this frozen build against any database that successfully ran branch tip `c1791ab2637` through migration 52. + +**Impact.** Startup fails on 053. Before that failure, the migrator silently treats current 044 through 052 as already applied because their numeric IDs are not above 52. In particular, main's automatic project-model repair at current 044 is never applied to an upgraded branch database. Making only the table creation idempotent fixes the crash but still leaves that repair skipped. + +**Compatibility fix.** The migration strategy must explicitly cover every supported historical manifest, not only the reproduced old-052 tip. Making current 053 use `IF NOT EXISTS` would unblock that one cohort, but it would neither apply skipped main 044 nor make arbitrary partially migrated old V2 cohorts safe. For example, an old database ending at 44 can run current 45's shifted copy of the same V2 DDL and collide earlier in the sequence. + +Use a manifest-aware compatibility bridge before the ordinary numeric runner, or make every shifted 45-53 step safe for its corresponding old predecessor, then append an idempotent migration that reapplies main 044's repair. A manifest-aware bridge can identify old history by recorded `(migration_id, name)` pairs, reconcile those records/schema to the new numbering, and leave released-main histories distinct. Do not infer history from the maximum ID alone. Add table-driven migration tests for each supported old branch stopping point plus released-main and fresh histories. The exact old-052 regression must remain a fixture. The existing fresh-database test at `apps/server/src/persistence/Migrations/045_046_OrchestrationV2.test.ts:174-230` starts before these IDs and cannot detect any of these upgrade failures. + +### 2. High: forced WebSocket project removal can delete V2 threads and then reject the project delete + +**Current code.** The WebSocket mutation handler obtains active and archived V2 shells, enforces `force`, and dispatches one `thread.delete` command at a time (`apps/server/src/ws.ts:1238-1258`). Those are independently committed mutations. It then calls `ProjectService.delete` without `force` (`ws.ts:1259-1262`). `ProjectDeleteInput` has no `force` member (`apps/server/src/project/ProjectService.ts:42-45`), and the service dispatches a legacy `project.delete` without it (`ProjectService.ts:348-371`). + +The legacy decider rejects a nonempty project unless its command contains `force: true`; when force is present, it deletes legacy threads and the project as one decided sequence (`apps/server/src/orchestration/decider.ts:274-306`). The legacy engine bootstraps that invariant from `getCommandReadModel` (`apps/server/src/orchestration/Layers/OrchestrationEngine.ts:344-345`). That query reads every `projection_threads` row (`apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts:430-463`, `:1858-1918`) and constructs the thread read model at `:2010-2049`. + +The V1 importer copies rows from `projection_threads`; it does not delete or supersede those rows (`apps/server/src/orchestration-v2/LegacyV1ThreadImporter.ts:459-560`). It also refuses to import the same thread again once a V2 `thread.created` event exists (`LegacyV1ThreadImporter.ts:481-489`). + +**Reachable trigger.** Use the WebSocket `project.delete` mutation with `force: true` on a project whose legacy threads have been imported into V2. This is the normal state after the V2 legacy-shell startup import. + +**Observed behavior from the source path.** Each V2 thread deletion succeeds first. The subsequent legacy `ProjectService.delete` sees the intact active `projection_threads` rows and rejects because the forwarded command has no force. The project remains, its V1 rows remain, and its V2 thread copies are deleted. A later importer pass will not restore them because their V2 creation events still exist. + +**Impact.** A user-authorized project removal fails after partially committing destructive work. The V2 UI loses the project's threads while reporting that the project could not be deleted. + +**Minimal fix.** Preserve `force` through `ProjectDeleteInput` and the legacy dispatch so this exact mixed-store path cannot reject after the V2 deletes. Prefer a single project-deletion coordinator used by all transports, with validation over both V1 and V2 and one transactional event commit; otherwise an unrelated failure in the per-thread loop can still partially delete a project. Add a focused test with one imported active thread and one imported archived thread, then force-delete through the WebSocket handler and assert the project and both representations are deleted. + +**Classification.** This predates `c1791ab2637`: the current deletion sequence traces to `b1c074b2ec3`, which is an ancestor of the prior rebased tip. It is a previously missed V2 integration bug relative to the V1 force-delete invariant, not a regression introduced by the final rebase. + +### 3. High: HTTP and offline CLI project mutations bypass the V2 lifecycle and drop contract fields + +**Current code.** `ProjectMutation` explicitly carries `createWorkspaceRootIfMissing` and deletion `force` (`packages/contracts/src/project.ts:70-95`). The WebSocket create handler forwards the former (`apps/server/src/ws.ts:1215-1223`), and `ProjectService.create` uses it when normalizing the workspace (`apps/server/src/project/ProjectService.ts:253-269`). + +The production HTTP endpoint is registered at `apps/server/src/server.ts:465-475` from the contract at `packages/contracts/src/environmentHttp.ts:560-575`. Its handler calls `ProjectService` directly. Create omits `createWorkspaceRootIfMissing`, and delete omits `force` and all V2 thread enumeration/deletion (`apps/server/src/project/http.ts:45-80`). + +The live CLI uses that HTTP endpoint (`apps/server/src/cli/project.ts:324-338`). Its offline path also maps delete directly to `ProjectService.delete` without force (`cli/project.ts:423-459`). The user-facing command accepts `--force`, describes it as deleting all threads, and includes the flag in its transport command (`cli/project.ts:522-555`). Main V1's invariant and forced sequence are the decider behavior at `apps/server/src/orchestration/decider.ts:274-306`; the prior CLI path passed the force field through to the engine. + +**Reachable triggers and actual behavior.** + +1. A V2-only project with active or archived V2 threads can be deleted by `POST /api/projects/mutate`. The legacy read model sees no V1 thread, so the project deletion succeeds while the V2 threads remain live and reference a deleted project. +2. An imported project with legacy rows rejects HTTP or CLI `--force` removal because `force` is dropped. +3. `t3 project remove`, live and offline, inherits these deletion outcomes despite promising complete forced cleanup. +4. HTTP and offline CLI project creation with `createWorkspaceRootIfMissing: true` behaves as false because the flag is dropped. + +**Impact.** The same typed mutation has materially different safety and filesystem semantics by transport. The deletion variant can orphan V2 threads or make `--force` ineffective. + +**Minimal fix.** Route WebSocket, HTTP, live CLI, and offline CLI mutations through one V2-aware project mutation coordinator. Forward both optional fields unchanged. Add transport-parity tests for V2-only populated projects, imported projects, archived threads, force false/true, and missing workspace creation. + +**Classification.** The direct HTTP/offline mappings trace to `b56d0e7d53fb`, an ancestor of `c1791ab2637`. This is a previously missed V2 transport integration bug, not a final-rebase regression. New main CLI behavior makes the existing mismatch directly user-facing in `t3 project remove`. + +### 4. Medium: auto-settlement treats a failure predating the snooze as an early wake + +**Current code.** A future snooze is bypassed whenever `thread.status === "failed"`, with no comparison to `snoozedAt` (`apps/server/src/orchestration-v2/ThreadSettlementService.ts:95-116`, especially `:107-116`). The service then performs normal inactivity/PR evaluation and can dispatch `thread.auto-settle` (`ThreadSettlementService.ts:216-270`). The current test asserts that changing only the status to failed wakes the snooze (`apps/server/src/orchestration-v2/ThreadSettlementService.test.ts:70-87`). + +**Main/prior invariant.** Main V1 only treats an error as a wake when the error session was updated after the snooze. It compares `thread.session.updatedAt` with `thread.snoozedAt` (`apps/server/src/orchestration/ThreadSettlementPolicy.ts` at main, lines 89-107, specifically 98-101). Completion has the same after-snooze rule. + +**Reachable trigger.** Let a thread fail, then snooze that already-failed thread into the future. On the next minute sweep, V2 classifies the stale failure as an early wake. If the inactivity or PR rule matches, it settles the thread before the requested wake time. + +**Impact.** A newer explicit snooze loses to older failure state, so settled/active sidebar placement contradicts the user's latest action. + +**Minimal fix.** Require the failure evidence to be newer than `snoozedAt`, as V1 does. The V2 shell already exposes `latestRunCompletedAt`; for a failed latest run, require that timestamp to be non-null and greater than `snoozedAt`. Add tests for failure before snooze (parked) and failure after snooze (candidate). + +## Confirmed V2 correctness and performance gaps + +### 5. High: full-thread diff fails after an ordinary second run + +**Current code.** For `fromTurnCount === 0`, `CheckpointDiffQuery` finds `runs.ordinal === 1`, requires a `root_run` scope whose current `runId` is that first run, and synthesizes its ordinal-0 ref (`apps/server/src/checkpointing/CheckpointDiffQuery.ts:157-180`). `getFullThreadDiff` always delegates to that path (`CheckpointDiffQuery.ts:204-248`). + +Production does not keep one distinct root scope row per run. `IdAllocator` derives a checkpoint scope solely from `threadId` and the constant scope name (`apps/server/src/orchestration-v2/IdAllocator.ts:295-300`). `makeRootRunScope` always requests the name `"root"`, but places the current run, node, provider thread, cwd, and creation time in the payload (`apps/server/src/orchestration-v2/CheckpointService.ts:184-210`, with the constant at `:27`). Each ordinary immediate run emits `checkpoint-scope.created` (`apps/server/src/orchestration-v2/Orchestrator.ts:3558-3567`). + +Both projection implementations replace the prior scope because the deterministic ID is the same. The in-memory path uses `upsertById` (`apps/server/src/orchestration-v2/ProjectionStore.ts:343-347`), and SQL uses `ON CONFLICT(scope_id) DO UPDATE`, including overwriting `run_id` (`ProjectionStore.ts:1773-1815`, specifically `:1803-1814`). Checkpoint IDs and refs remain stable by shared scope plus ordinal (`apps/server/src/orchestration-v2/CheckpointService.ts:161-181`). Thus, after run 2, the one root scope row belongs to run 2 while the valid ordinal-0 baseline from run 1 remains under that shared scope ID. + +**Test-fixture mismatch.** `CheckpointDiffQuery.test.ts:23-49` fabricates `firstScopeId` and `secondScopeId` and keeps both rows. That state cannot be produced by the real allocator for two root runs in one thread. The happy-path assertion at `:70-96` therefore hides the production failure. The missing-baseline test at `:176-196` also treats absence of a run-1-owned scope as an error, even though that is the normal projection after run 2. + +**Actual disposable allocation/projection probe.** I ran the real `IdAllocatorV2.allocate.checkpointScope` twice for the same thread and `"root"`, then applied two real `checkpoint-scope.created` events through `applyToProjection`. The two allocated IDs were equal; after the second event, `checkpointScopes.length` was 1 and the stored row's `runId` was `run:2`. The one-case audit-only Vitest probe passed and was removed afterward. + +**Reachable trigger and behavior.** Complete two ordinary immediate runs in a Git workspace, then request `getFullThreadDiff` to turn 2. The target checkpoint and shared ordinal-0 ref exist. The sole root scope now has `runId` 2, so the lookup constrained to run 1 returns undefined and the query raises `CheckpointRefUnavailableError` for the `from` ref. A cancelled/deferred first run is another trigger, but is not required. + +**Impact.** Full-thread diff is unavailable for normal multi-turn threads from the second completed run onward. + +**Minimal fix.** Stop joining the zero baseline through `firstRun.id`. Resolve the root scope by the target checkpoint's shared `scopeId`, then use that scope's ordinal-0 checkpoint/ref. Prefer the stored ready baseline ref and validate that it exists. Rewrite the happy-path test with the real allocator or one shared root scope whose current `runId` is run 2, and retain separate corrupt/missing-baseline coverage. + +**Classification.** The bad lookup traces to `b56d0e7d53fb`, while deterministic scope reuse and projection upsert predate it. `b56d0e7d53fb` is an ancestor of `c1791ab2637`, so this is a previously missed V2 correctness bug rather than a final-rebase regression. + +### 6. Medium: checkpoint diff reintroduces unbounded transcript hydration fixed on main + +**Current code.** Every nonempty diff first calls `ThreadManagementService.getThreadProjection` (`apps/server/src/checkpointing/CheckpointDiffQuery.ts:102-121`). V2's method is the unwindowed `readProjection` path (`apps/server/src/orchestration-v2/ProjectionStore.ts:2598-2599`). With no window, that path loads every turn item (`ProjectionStore.ts:2023-2030`) and selects all rows from each run, attempt, node, session, provider thread/turn, request, message, plan, checkpoint, and handoff table (`ProjectionStore.ts:2163-2399`), then decodes all of them (`ProjectionStore.ts:2401-2433`). Fork ancestry can recurse through additional full projections (`ProjectionStore.ts:2467-2589`). + +**Main invariant.** Main #8988 (`b17cc3d1bf0`) reduced full tool-output hydration, and #8992 (`7e460f429b7`) added a dedicated full-thread-diff query. The retained V1 implementation demonstrates the intended shape: a small thread/workspace query at `apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts:985-1001`, a single-row full-diff query at `:1533-1562`, and narrow service methods at `:2512-2583`. Main's `CheckpointDiffQuery` calls `getThreadCheckpointContext` or `getFullThreadDiffContext`; current V2 does neither. + +**Reachable trigger.** Request a turn diff or full-thread diff for any long thread, especially one with large tool outputs or fork ancestry. + +**Impact/cardinality.** Work is O(all persisted child rows for the thread and its fork ancestors), although the operation needs only workspace identity, run status/ordinal, scope identity, and a few checkpoint refs. A diff request can load and decode unrelated transcript bodies into memory. + +**Minimal fix.** Add V2 SQL queries equivalent to `getThreadCheckpointContext` and `getFullThreadDiffContext`, against V2 projection tables, and have the diff service use them. The full-thread endpoint needs one target checkpoint, the latest available completed turn count, a valid zero baseline, and the workspace path; it should not instantiate `OrchestrationV2ThreadProjection`. Add a cardinality test with a large unrelated tool payload and assert that the narrow query does not read/decode it. + +**Classification.** This gap was already present at `c1791ab2637`, even though main's #8988/#8992 optimizations were already in its ancestry. It is a missed main performance invariant from the prior review, not a new final-rebase regression. + +### 7. Medium: startup recovery fully hydrates every active and archived thread before readiness + +**Current code.** Recovery loads the V2 shell, iterates `shell.threads` plus `shell.archivedThreads` sequentially, and calls full `getThreadProjection` for every one (`apps/server/src/orchestration-v2/ProviderRuntimeRecoveryService.ts:470-499`). The reconciliation only needs nonterminal runs, pending runtime requests, live provider/background state, and unsettled process-bound effects (`ProviderRuntimeRecoveryService.ts:130-175` and the remainder of `reconcileProjection`). + +As above, `getThreadProjection` is unbounded (`apps/server/src/orchestration-v2/ProjectionStore.ts:2023-2030`, `:2163-2433`, `:2598-2599`) and recursively loads complete source projections for forked threads (`:2467-2589`). Startup awaits this recovery as an ordered phase (`apps/server/src/serverRuntimeStartup.ts:456-508`) and does not signal command readiness until `:615-617`. + +**Reachable trigger.** Restart an environment with many terminal threads, archived threads, long transcripts, tool payloads, checkpoints, or fork chains. No active provider work is required. + +**Impact/cardinality.** Startup database reads and decoding are O(total retained V2 projection history), not O(recoverable runtime state). The loop is sequential across threads. This can delay every local and remote client from issuing commands and creates a peak-memory cost before readiness. I did not benchmark it, so no latency number is claimed. + +**Classification.** This is a preexisting V2 design/performance gap, not a regression newly introduced by the final rebase. V1's startup read model also scans all thread shells, but it does not hydrate every transcript row, so this is not classified as a main-both bug. + +**Minimal fix.** Add an indexed recovery-candidate query that returns only thread IDs with a nonterminal run, pending request, live provider session/background item, or pending/running process-bound outbox entry. Then load a narrow recovery projection for only those IDs. Add a startup test containing many large terminal archived threads and assert that they are not passed to full projection reads. + +## Rejected candidate + +### Source-control lookup with inactivity and merge settings disabled is intentional + +An earlier draft classified recurring Git/PR lookup as unnecessary when `sidebarAutoSettleAfterDays` is null and `sidebarAutoSettleOnMerge` is false. Reviewer feedback correctly rejected that conclusion. + +Closed pull requests are an always-on settlement rule. V2 accepts `state === "closed"` regardless of `autoSettleOnMerge` and only gates the `"merged"` state on that setting (`apps/server/src/orchestration-v2/ThreadSettlementService.ts:71-91`). `shouldAutoSettleThread` evaluates that PR rule before the optional inactivity rule (`:119-140`). Main V1 has the same policy (`apps/server/src/orchestration/ThreadSettlementPolicy.ts:45-86`), and its test explicitly expects a closed request to settle with merge settlement disabled (`ThreadSettlementPolicy.test.ts:65-66`). + +The retained audit probe confirms that a closed PR newer than the user's last action settles with both optional settings off. Therefore the sweep must inspect PR state to preserve current product behavior. An early return based only on those settings would be a regression. No performance finding or fix recommendation remains for this candidate. + +## Intentional differences and separately owned gaps + +| Area | Classification and result | +| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Continue active threads after server update (#9167) | Explicitly deferred for V2 at this head. V2 recovery terminalizes interrupted work rather than persisting main's continuation marker. This is a feature-intent gap owned by the root review, not reported above as an accidental persistence regression. | +| Automatic title retry (#8087) | The root review independently confirmed that V2 lacks main's bounded retries. It is omitted from this report's findings to avoid duplicate ownership. | +| Provider adapters and client surfaces | Excluded by assignment and covered by other reviewers. Persistence-facing provider state was reviewed, but adapter protocol correctness was not. | +| Legacy import retention | Keeping `projection_threads` after import is current design and is not itself labeled a bug. The project-deletion coordinators are buggy because they assume one representation while both remain authoritative for different paths. | + +## Prior-fix retention status + +The supplied `prior-fixes-range-diff.txt` shows the previous review patch series rebased through `c1791ab2637`. I rechecked the production paths, not only patch identity. + +| Prior invariant | Status at frozen head | Current evidence | +| ----------------------------------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Persist current token usage | Preserved | Live merge retains existing usage when a terminal update omits it (`apps/server/src/orchestration-v2/ProjectionStore.ts:159-169`); SQL projection reads the prior payload before overwrite (`:1556-1574`). | +| Persisted provider usage | Preserved | Same SQL merge path above; `ProviderTurnTokenUsage.test.ts:12-42` covers the terminal omission case, and `ProjectionStore.test.ts:93-199` covers persistence. | +| Import legacy pins/order/snooze/PR metadata | Preserved | Import mapping at `LegacyV1ThreadImporter.ts:142-210`; repair selection and patch at `:390-457`. | +| Repair already imported legacy shells | Preserved | Metadata-repair events at `LegacyV1ThreadImporter.ts:390-457`; focused importer tests passed. | +| Migrated ownership/archive/deletion search | Preserved | Search joins V1 and V2 ownership and filters both lifecycle representations at `apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts:814-877`; search tests passed. | +| Missing-worktree send recovery | Preserved | Existence check and recreate-before-turn path at `apps/server/src/orchestration-v2/ProviderTurnStartService.ts:142-177`; focused tests passed. | +| Unsettled ordering/state | Preserved | Explicit settlement transitions retain/reanchor `unsettledAt` at `apps/server/src/orchestration-v2/Orchestrator.ts:1574-1598`; automatic completion path at `:2870-2893`; runtime tests passed. | +| Automatic-completion queue order | Preserved | `queuedRunsInDeliveryOrder` prioritizes delegated completion, then queue position and ordinal (`apps/server/src/orchestration-v2/QueuedRunOrder.ts:12-31`); focused tests passed. | +| SQL visible cohort before `LIMIT` | Preserved | Eligibility filters rollback, cancelled queued messages, superseded interrupts, source cutoff, and required-run handling before `selected ... LIMIT` (`apps/server/src/orchestration-v2/ProjectionStore.ts:2031-2126`). Projection/history tests passed. | +| Paired stop-request dependency | Preserved | SQL retained cohort adds the matching `run_interrupt_request` (`ProjectionStore.ts:2101-2110`); bounded projection also reserves dependencies (`threadHistoryPaging.ts:400-448`). | +| Nested fork cursor identity and empty ancestors | Preserved | Cursor source identity at `threadHistoryPaging.ts:92-140` and `:218-249`; recursive source anchoring and empty-ancestor suppression at `ProjectionStore.ts:2467-2589`. Focused nested-fork tests passed. | +| History actual-end pagination | Preserved | SQL fetch uses max page plus two rows (`apps/server/src/orchestration-v2/http.ts:132-149`); history response uses the computed page end (`:216-254`). Focused pagination tests passed. | +| Snapshot/detail/control-payload budget | Preserved | Central budgets and control-plane reservation at `apps/server/src/orchestration-v2/threadHistoryPaging.ts:10-46`, `:381-496`; bounded HTTP exposes overflow status at `apps/server/src/orchestration-v2/http.ts:195-212`. | +| Waiting checkpoint recovery | Preserved, with separate diff bug above | Recovery leaves a waiting run intact when its checkpoint effect is replayable (`ProviderRuntimeRecoveryService.ts:134-155`); checkpoint capture is at-least-once (`CheckpointCaptureService.ts:68-93`). | +| Outbox recovery and settlement | No new correctness regression found | Reconciliation requeues replayable work and retires process-bound work; focused recovery, runtime-layer, checkpoint-capture, run-finalization, and effect-worker tests passed. The full-state startup cost is finding 7. | + +## Coverage + +| Area | Files/path inspected | Result | +| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| Migration numbering and runner semantics | `Migrations.ts`, old `c179` manifest, current 044/053, Effect `Migrator.ts` | Blocker confirmed with real in-memory runner. | +| Projection persistence and rebuild | `ProjectionStore.ts`, `ProjectionMaintenance.ts`, event projection tests | Prior state/usage/history fixes retained; no additional data-loss finding. | +| Windowing/history SQL | `ProjectionStore.ts`, `threadHistoryPaging.ts`, V2 HTTP handlers | Prior SQL visibility, dependency, fork, pagination, and budget fixes retained. | +| Legacy import and repair | `LegacyV1ThreadImporter.ts`, importer tests, V1 search query | Metadata/search fixes retained; preserved V1 rows expose deletion boundary bug. | +| Runtime recovery | `ProviderRuntimeRecoveryService.ts`, `serverRuntimeStartup.ts`, recovery tests | Semantics tests pass; all-thread full hydration cost confirmed. | +| Queue and settlement | `QueuedRunOrder.ts`, `ThreadSettlementService.ts`, orchestrator settlement commands | Queue fix retained; snooze ordering regression confirmed; disabled-policy cost candidate rejected because closed-PR settlement is always active. | +| Effect queue/outbox/leases | `EffectOutbox.ts`, `EffectWorker.ts`, runtime layer and worker tests | No additional correctness finding; recovery candidate query remains too broad. | +| Checkpoint scheduling/capture/diff | `CheckpointCaptureService.ts`, `CheckpointService.ts`, `IdAllocator.ts`, `RunExecutionService.ts`, `CheckpointDiffQuery.ts` | Capture/replay invariant retained; ordinary multi-run shared-scope diff bug and full-read cost confirmed. | +| Project lifecycle boundary | WS, HTTP, CLI, `ProjectService`, V1 decider/read model | Two high-severity preexisting transport/coordinator bugs confirmed. | +| New main server features | Main-since-prior inventory, checkpoint optimizations, settlement, update continuation, project removal/model migration | Relevant discrepancies classified above; continuation/title are separately owned. | + +## Focused validation + +All commands used repository-local disposable state or mocks. No repo-wide check was run. + +| Test group | Result | +| ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| `EffectWorker.test.ts`, `ThreadSettlementService.test.ts`, migration 045/046 test | 3 files, 24 tests passed | +| `ProjectionStore.test.ts`, `threadHistoryPaging.test.ts`, legacy importer, two runtime recovery suites, provider-turn start/usage, queue order | 8 files, 45 tests passed | +| Search, runtime layer, checkpoint capture, run finalization | 4 files, 16 tests passed | +| `CheckpointDiffQuery.test.ts` | 1 file, 5 tests passed; the current missing-first-scope expectation is part of finding 5 | +| Product-test subtotal | 16 files, 90 tests passed | +| Retained audit-only migration/scope/policy probes | 1 file, 3 tests passed | + +The retained `audits/orchestrator-v2/2026-09-02/persistence-runtime-probes.test.ts` uses the actual migration runner with in-memory SQLite, the real checkpoint allocator and projection reducer, and the production V2 settlement policy. Its fixtures use typed domain events, branded identifiers, real `DateTime.Utc` values, `emptyProjection`, and `threadShellFromProjection`; there are no permissive projection/event casts. Its migration case expects and captures the current 053 failure, so the probe suite itself passes while reproducing the blocker. Its scope case confirms that two root-run allocations produce one shared scope row whose `runId` is overwritten by run 2. Its policy case records the reviewer rejection above. Audit probes are not included in the 90-product-test total. + +Exact rerun command and output are retained in `audits/orchestrator-v2/2026-09-02/persistence-runtime-probes.log`. + +## Remaining validation gaps + +- I did not mutate product tests to add the missing historical-manifest fixtures. The retained audit-only probe uses the same migration loader and SQL layer for the confirmed old-052 cohort; other supported partial old-branch stopping points still need table-driven validation. +- I did not invoke a live WebSocket/HTTP server or CLI. The project-deletion outcomes are deterministic source traces across typed handlers, committed V2 commands, and the legacy decider. An integrated disposable server test should be added with the fixes. +- I did not benchmark startup recovery or checkpoint diff. Cardinality claims above follow the explicit unwindowed SQL and loops; they do not claim measured latency or memory. +- I did not test live GitHub/PR providers. Settlement PR grouping and local Git call order were inspected statically. +- Provider adapters, browser clients, desktop/mobile behavior, build/auth compatibility, and title retries are assigned to other reviewers/root. +- The explicit server-update continuation gap needs a product decision and V2 design; it is not silently counted as passing parity. diff --git a/audits/orchestrator-v2/2026-09-02/prior-fixes-range-diff.txt b/audits/orchestrator-v2/2026-09-02/prior-fixes-range-diff.txt new file mode 100644 index 000000000000..04c2089ea8c1 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/prior-fixes-range-diff.txt @@ -0,0 +1,44 @@ + 1: 1a5dc7e5d6 = 1: 34a4d026a5 fix(server): keep Claude session approvals ephemeral + 2: d853e44391 < -: ---------- fix(web): keep project picker popup inside the sidebar + 3: 1b7221098f < -: ---------- fix(mobile): prevent header overflow and back-button artifacts + 4: f5fb255599 = 2: 7e71ff8a80 fix(orchestration): reanchor unsettled threads + 5: 5f4cd75874 = 3: 6b3690e063 fix(server): observe pre-aborted Claude approvals + 6: a0e7fa2f3e = 4: feedc3f6bb fix(server): include service launcher in bundle build + 7: 893b1c947a = 5: 82e1b8ed60 fix(orchestration): preserve legacy thread metadata + 8: d7fa7f7133 ! 6: 930dd22e72 fix(web): honor disabled legacy plan mode + 9: e127cf7480 = 7: 2cfe234e46 fix(server): preserve Claude subagent models +10: 1340b474d6 = 8: eacc09d40a fix(orchestration): honor migrated thread visibility in search +11: 0090064448 = 9: dcff638944 fix(orchestration): recreate missing worktrees before turns +12: 1b0437897c ! 10: e44588afa4 fix(clients): restore Codex feedback submission +13: 33607d9bcb = 11: 8bbf7f50c8 fix(server): preserve generic provider attachments +14: 532feb8b88 ! 12: 53c6857ec9 fix(web): load workspace markdown images through assets +15: cfa734416d < -: ---------- fix(web): preserve Windows markdown paths + -: ---------- > 13: 7fca26e6fb fix(web): preserve Windows markdown paths +16: 201dfc6c7e = 14: 642056fdd9 fix(server): keep current provider context usage +17: 3a846888a8 < -: ---------- fix(web): restore markdown file chip actions + -: ---------- > 15: 5f19d550ae fix(web): restore markdown file chip actions +18: 0bb0d2d36e ! 16: 44f2004810 fix(web): scope markdown actions to their environment +19: 37cfa6296d < -: ---------- fix(web): restore pull request markdown actions +20: ae6d09b0a8 = 17: 995f4e7e5a fix(protocol): reject incompatible orchestration peers +21: 1677769660 ! 18: 3e1ff1531d docs: explain legacy thread migration +22: 14b4b8966d = 19: 19a30d03be docs: state portable handoff limits +23: 335bad52e0 = 20: 68104a497e chore(repo): remove tracked audit scratch files +24: 6db9f290b2 = 21: 98670f337e fix(server): guard OpenCode prompt admission races +25: 686fd94e5d = 22: ecf3dd2c9a fix(server): restore Claude structured questions +26: cb8b2b5125 = 23: ff9f875f17 fix(server): project Claude plans and todos +27: d9cc96b47b = 24: 9a4734af8e perf(orchestration): bound history reads in SQL +28: e05e23f1e4 = 25: 0921786018 perf(orchestration): bound complete thread snapshots +29: b0a77b042e = 26: 3d5bab73d8 fix(server): restore Claude resume compaction +30: 825b95aed9 < -: ---------- fix(server): allow protocol negotiation in CORS + -: ---------- > 27: 733db7269f fix(server): allow protocol negotiation in CORS +31: 63d9e93e62 = 28: 26dfbc2984 fix(server): preserve provider usage in persisted turns +32: 3cd9445411 = 29: 70f82caaa0 fix(server): preserve Claude planning lifecycle +33: 48e2ea9892 = 30: dbb6021f84 fix(server): normalize Claude question answers +34: b8b10b3f9f = 31: de79f44221 fix(server): correlate OpenCode prompt admission +35: 06483fbdfa = 32: be7b07634b fix(clients): anchor feedback in conversation order +36: 52de095cf3 = 33: 051565fc96 fix(web): retain markdown workspace ownership +37: 25b367a4c8 = 34: 870014496f fix(orchestration): page history through its true end +38: d6a5a888bc = 35: 07889933e3 fix(server): cancel pending OpenCode prompts safely +39: 677dd4f4e5 = 36: 0fc565db8a fix(orchestration): retain nested fork history when paging +40: 0079d8b918 = 37: 47ae99f517 fix(server): recover OpenCode status reconciliation +41: 47f5b10044 = 38: c1791ab263 fix(orchestration): select visible history before limiting SQL diff --git a/audits/orchestrator-v2/2026-09-02/providers.md b/audits/orchestrator-v2/2026-09-02/providers.md new file mode 100644 index 000000000000..fd98c5562cc0 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/providers.md @@ -0,0 +1,188 @@ +# Orchestrator V2 provider behavior audit + +Date: 2026-09-02 +Audited HEAD: `d2f1f511f4cc833bc930d6c355cd0f9b61e835a0` +Comparison main: `57a66608b918d673eeec7e6c94ea5906b756fcd0` +Prior reviewed object: `47f5b100440591d2f49aa30cf3bb69eacae07f52` +Rebased prior-equivalent tip: `c1791ab2637` + +## Verdict + +The supplied main is an ancestor of the frozen HEAD, and the branch is 332 commits ahead. The previously reported provider fixes survive the rebase. I found five confirmed behavior regressions against current main V1: + +1. Cursor background text generation runs a full agent with its sandbox and approval boundary disabled. +2. Claude workspace image reads do not become image previews in either current V2 client projection. +3. OpenCode Stop reports descendant cleanup as successful even when child discovery or abort fails or times out. +4. Releasing an OpenCode V2 session connected to an external server never asks that server to abort root or child work. +5. V2 reconnect and HTTP-failure fallbacks bypass the bounded thread-snapshot path and can send the full lifetime projection over WebSocket. + +The Cursor SDK migration itself is intentional, but I found no evidence that removing the metadata-generation write guard was an accepted part of it. The Claude result is a missing user-visible main feature. The OpenCode findings partially port main's `#9005` fix but leave reachable stop/teardown behavior weaker than V1. The snapshot issue is not the ordinary healthy cold-open path—the bounded HTTP request protects that case—but it is an active fallback used by both current clients. + +## Confirmed regressions + +### P1 — Cursor metadata generation runs with unrestricted write/tool access + +**Current V2 evidence:** `apps/server/src/textGeneration/CursorTextGeneration.ts:75-157`. + +- Every Cursor commit message, change-request description, branch name, and thread title calls `Agent.prompt` with `mode: "agent"`, `local.autoReview: false`, and `local.sandboxOptions.enabled: false` (`90-104`; callers at `159-251`). The focused test explicitly pins those options but mocks the SDK, so it does not exercise their permission behavior (`CursorTextGeneration.test.ts:38-85`). +- The installed dependency is `@cursor/sdk@1.0.22`. Its public types expose only `"agent" | "plan"` modes and a boolean sandbox switch (`node_modules/.pnpm/@cursor+sdk@1.0.22/node_modules/@cursor/sdk/dist/esm/options.d.ts:3-4, 63-65, 108-145, 218-240`). Inspection of the installed runtime bundle shows that `enabled: false` immediately selects `defaultSandboxPolicy: { type: "insecure_none" }`, before considering the loaded per-user sandbox policy; because that policy is insecure and `autoReview` is false, it supplies neither `approvalMode` nor a `pendingDecisionProvider` (`dist/esm/357.js:1`). The same bundle maps `mode: "agent"` to the native `AGENT` mode and implements `Agent.prompt` as create/send/wait/dispose, so this is the normal tool-capable local agent path rather than a text-only inference call. + +**Main evidence:** supplied main's `apps/server/src/textGeneration/CursorTextGeneration.ts:85-105` starts Cursor ACP and deliberately calls `runtime.setMode("ask")` before prompting. The accompanying Cursor ACP capability names Ask as “Request permission before making any changes,” contrasted with Code's full tool access (`apps/server/scripts/acp-mock-agent.ts` at supplied main: `271-287`). The SDK migration commit `6c78a01831d` documents the intentional boundary/auth/model-discovery change, but neither its message nor its implementation records an intentional relaxation for background metadata generation. + +**Reachable trigger:** Select Cursor as the text-generation/source-control writer. Initial and regenerated titles invoke the service against the real worktree (`ThreadTitleRegenerationService.ts:184-245`), commit generation passes the real source-control cwd (`GitManager.ts:1618-1657`), and automatic worktree naming does likewise (`ThreadLaunchService.ts:178-213`). The title prompt explicitly tells the model to use available tools for linked-only context (`TextGenerationPrompts.ts:219-243`). Any resulting shell, edit, or delete tool call executes without main's ask boundary; the user message and diff content supplied to these prompts can also request or induce such a call. + +**User impact:** A background title/branch generation or a commit/PR-copy request can modify or delete workspace files, run commands, or perform other agent actions even though the operation is presented as metadata generation. Explicitly disabling the SDK sandbox also overrides a user's configured Cursor sandbox for these calls. + +**Minimal recommendation:** Restore an enforced non-writing boundary for Cursor text generation before using `Agent.prompt`. The installed SDK does not expose an Ask mode, and `sandboxOptions.enabled: true` maps to workspace read-write, so neither that flag nor an unverified switch to Plan should be treated as equivalent. Use a documented SDK text-only/read-only policy if one is added; otherwise retain a guarded metadata path or do not offer Cursor for these background generators. Add a behavioral integration test with a fake/local SDK runtime that attempts shell and file-write tools and proves they are denied; do not merely assert option shape. + +### P1 — OpenCode Stop swallows descendant cleanup failures + +**Current V2 evidence:** `apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.ts:2986-3069`. + +- V2 first waits for `session.abort` on the root (`3013-3029`). It then describes descendant cleanup as best-effort (`3030-3033`). +- A failed `session.children` call is converted to `Option.none` (`3038-3043`), each child `session.abort` failure is ignored (`3049-3055`), and the whole traversal's 15-second timeout or failure is ignored (`3058-3059`). The outer `ProviderAdapterInterruptError` mapping therefore never sees any descendant cleanup failure. +- V2 also waits up to ten seconds for the root HTTP abort even when native session events have already acknowledged or completed cancellation (`3013-3029`). + +**Main evidence:** commit `62d39bf00d` (`fix(server): stop OpenCode child sessions (#9005)`). At main, `apps/server/src/provider/Layers/OpenCodeAdapter.ts:707-774` walks all descendants and returns the first non-not-found list/abort failure. Its interrupt state machine at `2987-3122` races the HTTP request with native acknowledgment/completion and propagates a descendant failure or timeout unless the turn has independently completed. + +**Reachable trigger:** An OpenCode turn has spawned a task child or grandchild and the user presses Stop while `session.children` or a child `session.abort` errors or hangs. A slow root abort request with a prompt native acknowledgment also reaches the avoidable delay. + +**User impact:** T3 can acknowledge Stop while one or more OpenCode child sessions continue executing commands or modifying files. Failures leave no caller-visible indication. The root abort can also keep the Stop command pending for up to ten seconds after native cancellation is already known. + +**Minimal recommendation:** Port main's cancellation state machine into V2: keep prompt-admission cancellation, race root abort against native acknowledgment/terminal completion, traverse descendants with the cycle guard and bounded concurrency, ignore only explicit not-found responses, and propagate the first other failure or timeout while the cancellation is still live. Add adapter tests for nested children, list failure, child-abort failure, timeout, and acknowledgment winning a pending HTTP request. + +### P1 — External OpenCode work survives V2 session release + +**Current V2 evidence:** + +- An OpenCode session may connect to an external configured server at `apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.ts:882-902`. +- Its only explicit scope finalizer aborts the local SSE subscription controller at `apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.ts:2488-2496`. The only root/descendant `session.abort` calls in this adapter are inside `interruptTurn` at `3013-3059`; session release has no corresponding path. +- The V2 runtime interface has no close/teardown callback (`apps/server/src/orchestration-v2/ProviderAdapter.ts:470-535`). The manager releases sessions by closing the adapter scope (`apps/server/src/orchestration-v2/ProviderSessionManager.ts:611-706`) for idle timeout, runtime error, manual shutdown, and server shutdown (`ProviderSessionManager.ts:47-52, 761-839, 1361-1389, 1555-1565`). +- Normal server shutdown calls `providerSessions.shutdown` before terminalizing durable work (`apps/server/src/serverRuntimeStartup.ts:386-402`). For an external OpenCode server, closing T3's scope only disconnects its event stream; there is no owned local child process whose teardown could stop the remote sessions. + +**Main evidence:** the same main commit, `62d39bf00d`. Main implements `abortOpenCodeSessionForTeardown` at `apps/server/src/provider/Layers/OpenCodeAdapter.ts:776-787` and calls it from normal context stop at `828-860`. It explicitly aborts the parent, snapshots the child tree, and aborts descendants before closing local handles. + +**Reachable trigger:** Use an OpenCode provider configured with `serverUrl`, start work, then shut down T3, manually close/detach the single-thread session, hit the idle-release path, or lose the V2 event stream without first completing a successful explicit interrupt. + +**User impact:** T3 marks/releases the session and loses its event stream while the external OpenCode server can continue root or child work unseen. On shutdown this can leave commands and file writes running after the local UI/server has stopped. + +**Minimal recommendation:** Add a provider-runtime teardown effect (or an OpenCode-specific scope finalizer) that best-effort aborts the root and the complete descendant tree before the SSE subscription is closed. Preserve strict failure reporting for explicit Stop, but time-box and log teardown failures. Cover external connections and all four manager release reasons in focused tests. + +### P1 — V2 WebSocket snapshot fallbacks bypass the bounded history path + +**Current V2 evidence:** + +- The server advertises `threadSnapshotPagination`, but the V2 subscription input has no window/limit field (`apps/server/src/ws.ts:770-792`; `packages/contracts/src/orchestrationV2.ts:2430-2443`). Both a subscription without `afterSequence` and a resume rejected by the 128-event or 1 MiB replay limits call `snapshotThenLive` (`apps/server/src/ws.ts:829-922`; limits at `apps/server/src/orchestration-v2/ThreadStream.ts:1-50`). That function calls the unwindowed `getThreadSnapshot`, projects it, and emits it as one socket item (`ws.ts:860-884`). +- The call remains unwindowed through `ThreadManagementService` (`apps/server/src/orchestration-v2/ThreadManagementService.ts:413-423`). `ProjectionStore` consequently reads every turn item and all rows in each projection collection without a `LIMIT` when `window` is absent, and recursively does the same for inherited source-thread history (`apps/server/src/orchestration-v2/ProjectionStore.ts:2023-2030, 2146-2399, 2467-2589, 2601-2626`). The bounded SQL read is a separate API at `2628-2677`. +- Wire projection caps individual detail/dynamic values at 32 KiB/16 KiB, but maps every `turnItems` and `visibleTurnItems` entry; it does not cap collection cardinality (`apps/server/src/orchestration-v2/WireProjection.ts:7-99`). The bounded HTTP implementation instead budgets at most 75 timeline items and about 1 MiB, including the duplicate local-item cost across those two arrays (`apps/server/src/orchestration-v2/threadHistoryPaging.ts:9-16, 61-79, 420-496`). +- The current web and mobile runtimes both install the shared bounded HTTP loader. A healthy cold open therefore gets the intended bounded snapshot first. The loader has a six-second budget and deliberately returns `unavailable` on transient failure so the socket is used (`packages/client-runtime/src/state/boundedThreadSnapshotHttp.ts:23-65, 109-156`). When no projection was installed, the client subscribes without `afterSequence`; a warm cached projection skips HTTP and subscribes with its sequence (`packages/client-runtime/src/state/threads.ts:580-647`; the latter behavior is pinned at `threads-sync.test.ts:289-308, 472-507`). A received socket snapshot is installed as a full replacement and clears progressive-history metadata (`threads.ts:288-307`), so this is neither a dead nor control-plane-only fallback. + +**Main evidence:** Main `#8992` (`7e460f429b`) bounds replay and falls back to a snapshot; `#9000` (`a9ffb827961`) adds bounded snapshot activity reads/projection. Crucially, current main's subscription contract accepts `turnLimit` and defines it as the fallback-snapshot window (`packages/contracts/src/orchestration.ts` at supplied main: `630-653`). The client always sends its ten-user-turn initial limit to pagination-capable servers specifically so a missing cursor or failed resume does not redownload the full thread (`packages/client-runtime/src/state/threads.ts` at supplied main: `43-50, 560-637`), and the server passes that limit into `getThreadDetailSnapshot` on the fallback path (`apps/server/src/ws.ts` at supplied main: `1525-1654`). Main `#9032` (`e86604d337`) avoids repeated full-message reads while streaming; it does not close or establish this snapshot bound and is not used as proof for the finding. + +**Reachable trigger:** Either (1) open a thread with an empty client cache while the bounded HTTP request times out or fails transiently, or (2) reconnect/foreground a warm cached thread after more than 128 thread events or more than 1 MiB of encoded replay events accumulated. The first subscribes without a cursor; the second makes `decideThreadResume` choose snapshot. Both reach the same unwindowed snapshot call. + +**User impact:** On a long-lived thread, the server queries and decodes every historical row across the projection tables (and inherited parent history), serializes the full projection, and sends it as one WebSocket snapshot. Work and payload size therefore grow with lifetime thread cardinality despite the advertised paginated path; remote clients are especially exposed when the bounded HTTP request is the part that failed. The client then loses its load-earlier cursor because it treats the socket result as complete. This audit proves the unbounded cardinality and reachable paths from source; it did not measure a percentage, frame size, or memory peak. + +**Minimal recommendation:** Extend the V2 subscription with a pagination-capable fallback request, then build its socket snapshot through `getThreadSnapshotWindow` plus the existing bounded projection/budget logic and carry progressive-history metadata in the stream item. Preserve an explicit full fallback for legacy clients if needed. Add focused cases for a warm bounded cache whose gap exceeds 128 events and a cold loader-unavailable path; assert a bounded timeline, retained live control state, a usable history cursor, and the payload-budget signal rather than a timing percentage. + +### P2 — Claude workspace image reads lose image-preview projection + +**Current V2 evidence:** + +- Claude's V2 tool classifier only permits `command_execution`, `file_change`, `dynamic_tool`, and `web_search`; `Read` is always `dynamic_tool` (`apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts:1392-1447`). +- The actual tool-start caller has the parsed `toolInput` but calls `classifyClaudeNativeTool(input.toolName)` without it (`ClaudeAdapterV2.ts:3601-3630`). Artifact construction can consequently emit only those four item types (`ClaudeAdapterV2.ts:3001-3039`). +- V2 does retain the native Read input in the generic `dynamic_tool.input` field (`ClaudeAdapterV2.ts:3001-3039`; contract at `packages/contracts/src/orchestrationV2.ts:1069-1075`), so contract shape alone does not prove the preview is lost. The actual client projections do: web puts the input only in `toolData` and supplies neither `detail` nor `viewedImagePath` (`apps/web/src/session-logic.ts:591-597`), and mobile does the same (`apps/mobile/src/lib/threadActivity.ts:467-472`). +- The shared preview detector reads only an explicit `viewedImagePath` or a single-line `detail` on a Read entry; it never inspects `dynamic_tool.input` (`packages/client-runtime/src/work-log/presentation.ts:354-385`). Consequently the web renderer receives `null` at `MessagesTimeline.tsx:3275-3282` and cannot enter its image branch at `3378-3389`; mobile likewise receives `null` at `apps/mobile/src/features/threads/thread-work-log.tsx:651-665` and skips its image branch at `759-770`. The expanded inspector renders structured input/output JSON only (`apps/web/src/components/chat/V2ItemInspector.tsx:227-244`). + +**Main evidence:** commit `d0b19b32e0` (`fix(claude): preview images read from the workspace (#9119)`). Main's `apps/server/src/provider/Layers/ClaudeAdapter.ts:717-727` recognizes only `Read`/`Read file` calls whose `file_path` or `path` passes `isWorkspaceImagePreviewPath`; `730-777` classifies them as `image_view`; `1188-1192` retains the path as display detail. Main's regression test at `apps/server/src/provider/Layers/ClaudeAdapter.test.ts:1438-1574` verifies the streamed Read input transitions from a generic start to `image_view` updates/completion carrying the image path. + +**Reachable trigger:** Claude invokes its `Read` or `Read file` tool for a supported workspace image such as PNG, JPEG, GIF, or WebP. + +**User impact:** V2 renders a generic Read tool row (and structured JSON when expanded) instead of main's inline workspace image preview on both web/desktop and mobile. + +**Minimal recommendation:** A new turn-item variant is not required. On both client projections, recognize `dynamic_tool` names `Read` / `Read file`, extract `file_path` or `path` from `input`, validate it with the shared workspace-image predicate, and populate `viewedImagePath`; alternatively project the same explicit path server-side if maintainers want a provider-neutral contract field. Preserve the generic-start-to-image transition when streamed partial JSON reveals the path only later. Add the main streamed-input regression case plus web and mobile projection/render coverage. + +## Prior-fix status + +| Prior concern | Status at frozen HEAD | Evidence | +| -------------------------------------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Generic attachments for all providers | Preserved | Shared path text is built by `AttachmentPrompt.ts:11-25`; Claude, Codex, Cursor, ACP/Grok, and OpenCode all call it on their actual prompt paths. Native image blocks remain additive where the provider supports them. The focused attachment/adapter tests passed. | +| Claude session-scoped permission suggestions | Preserved | `ClaudeAdapterV2.ts:1894-1945` rewrites every suggested permission destination to `session` and synthesizes a whole-tool session rule if none was supplied. | +| Claude pre-aborted approval/user-input signals | Preserved | `ClaudeAdapterV2.ts:1948-1973` installs the listener and immediately observes `signal.aborted`; cancellation listeners are removed by the callback finalizer. | +| Claude structured and multi-select questions in all permission modes | Preserved | `AskUserQuestion` is handled before the permission-callback policy gate at `ClaudeAdapterV2.ts:4714-4807`; `canUseTool` is installed unconditionally at `5029-5031`. The full-access structured-question test passed. | +| Claude plan/todo identity and lifecycle | Preserved | Stable per-native-item IDs and latest-per-kind supersession live at `ClaudeAdapterV2.ts:2417-2420, 3468-3598`; the generic completion regression test passed. | +| Claude compaction controls/resume | Preserved | `autoCompactWindow` and `resumeSessionAt` are compiled at `ClaudeAdapterV2.ts:730-753`; the resume dialog is projected through structured user input at `4882-4955`; resumed queries pass the native head at `4972-5031`. | +| Claude/Codex token usage | Preserved | Claude emits root-assistant usage at `ClaudeAdapterV2.ts:4359-4387`; Codex retains its usage conversion and provider-turn updates. `ProviderTurnTokenUsage.test.ts` passed. | +| Claude subagent model propagation | Preserved | Pending assistant-snapshot models are retained until task registration and used by the subagent lifecycle; the ordering regression test (`keeps a subagent snapshot model that arrives before task_started`) passed. | +| OpenCode native message correlation | Preserved | Each initial/steer prompt receives a generated `admissionMessageId` (`OpenCodeAdapterV2.ts:2787-2845, 2929-2955`), and only the matching native user message advances admission (`2256-2266`). | +| OpenCode pending initial/steer prompt cancellation | Preserved | Initial and steer requests combine the SDK signal with a turn-owned abort controller; interrupt invalidates the generation and aborts it (`OpenCodeAdapterV2.ts:2787-2850, 2929-2965, 3000-3011`). | +| OpenCode generation-owned status retry | Preserved | Admission reconciliation checks turn identity and generation before every status request and adoption (`OpenCodeAdapterV2.ts:2017-2091`). Transient-retry, stale-generation, delayed-reply, and abort-winning-status tests passed. | + +## Current-main feature coverage + +| Main provider change since the prior reviewed base | V2 status | +| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Claude project/per-cwd skills (`bc918e74ac`, later `#9210`) | Driver-side `snapshotForCwd` is present, and Claude's actual query path also resolves cwd skills. Covered, with the refresh caveat below. | +| Codex/OpenCode per-cwd skills (`80a14b6588`) | Driver `snapshotForCwd` implementations are present for both. Web requests cwd snapshots. Covered for the web entry path; execution-trigger refresh parity remains unverified. | +| Remote Claude model manifest (`0354283683`) | Shared driver/catalog path is used by V2. Covered. | +| OpenCode bounded version probes (`4116db9807`) | Shared OpenCode runtime/driver path is used by V2. Covered. | +| Removed custom models disappear (`941acb4f91`) | Shared provider registry and client selection normalization apply to V2. Covered. | +| Grok health/model selection/Stop (`a434677eca`, `7880a6e583`) | V2 ACP flavor carries live model switching and Grok-specific interrupt/runtime-restart controls. Covered in the shared runtime path. | +| Claude workspace image preview (`d0b19b32e0`) | **Missing; confirmed regression above.** | +| OpenCode child-session stop (`62d39bf00d`) | **Partial; explicit interrupt traversal exists, but failure semantics and release teardown are missing.** | +| Bounded V1 persisted-session lookup (`9a7b1e21e5`) | Not directly applicable: V2 uses `ProviderSessionManagerV2`'s keyed live-session map and projection APIs rather than V1's ProviderService scan. | +| Provider-event leak/idle CPU fixes (`0bfb6df34b`) | The OpenCode assistant merge change is present; other changes target V1 ingestion/logging or shared runtimes. No V2-specific regression found in this provider audit. | +| Active tool-update frame coalescing (`7e4ce3bbb1`, `#8368`) | No equivalent V2 thread-detail coalescer was found. This is a performance validation gap, detailed below; the audit did not reproduce or quantify the main PR's 90% reduction against V2. | +| Bounded replay/snapshot work (`#8992`, `#9000`, `#9032`) | **Partial.** V2 bounds replay and has a bounded HTTP snapshot, but its no-cursor and over-budget WebSocket fallbacks use the full-cardinality projection; confirmed regression above. `#9032` concerns streaming-message reads and was not treated as snapshot proof. | +| Cursor text-generation Ask guard (present at supplied main) | **Missing after the intentional Cursor SDK migration; confirmed regression above.** | + +Provider execution paths inspected: Claude Agent SDK; Codex app-server; Cursor Agent SDK; OpenCode SDK/SSE; Grok through the flavored ACP adapter; ACP Registry through the generic ACP adapter; provider driver creation, model/skill snapshot plumbing, session lifecycle, and the relevant orchestration V2 contracts. + +## Intentional differences + +- **Restart continuation is deliberately withheld in V2.** Main's `5b7d72aad1` / `#9167` keeps active V1 threads resumable across server restarts. The frozen HEAD's commit message explicitly says the server-side continuation markers were not ported because they live in the V1 session directory and V2 recovery terminalizes running runs. That matches `ProviderRuntimeRecoveryService.ts:130-190, 450-526`. I do not classify this as a regression without a V2 durability design. +- **Cursor uses the Cursor Agent SDK rather than main V1's ACP boundary.** Its orchestration capabilities intentionally advertise no live approvals/structured questions and no native fork/rollback (`CursorAdapterV2.ts:101-158`). I found no evidence that the chosen SDK boundary exposes equivalent interactive callbacks that V2 is silently dropping. This intentional D01/API-boundary change does not make unrestricted background text generation intentional; that separate loss is the confirmed finding above. +- **V2 session residency differs from V1.** The V1 persisted-session lookup optimization does not map one-for-one to V2's keyed in-memory manager. This is an architectural difference, not missing parity. + +## Suspected or unverified cases + +- **Execution-triggered per-cwd skill refresh:** main V1 refreshes the workspace provider snapshot both after starting a provider session and when reusing one (`ProviderCommandReactor.ts` at supplied main: `660-681, 712-740`). V2 has the registry RPC (`apps/server/src/ws.ts:1574-1587`) and web proactively requests a missing cwd snapshot (`apps/web/src/components/chat/ChatComposer.tsx:1143-1194`), but I found no equivalent refresh in V2 launch/run execution. Claude independently scans skills while forming its query, so execution is safe there; Codex/OpenCode slash-command discovery appears UI-facing. I did not find a reachable current-client failure, so this remains a parity/test gap rather than a confirmed regression. +- **Active-detail WebSocket coalescing/performance:** main commit `7e4ce3bbb1` adds a semantic, stable-tool-call coalescer with a 50 ms/512-event bound before V1 live thread-detail delivery (`ThreadLiveEventCoalescer.ts` at that commit: `13-14, 20-89, 91-205`; V1 `ws.ts:1499-1513`). The V2 thread subscription maps every stored event directly to a wire event at `apps/server/src/ws.ts:807-827` and uses that same uncoalesced stream for live delivery at `883, 918`. The grouped/coalesced V2 streams at `ws.ts:1001-1026, 1181-1190` are shell/archive paths, not active thread detail. Static provider paths can generate repeated full-state events: Cursor sends a node plus turn-item update on every shell-output delta (`CursorAdapterV2.ts:1094-1102, 1838-1847`), ACP/Grok reprojects tool state for every native tool-call update (`AcpAdapterV2.ts:2604-2613, 3693-3701`), and OpenCode reprojects every tool `message.part.updated` (`OpenCodeAdapterV2.ts:2270-2295`). Codex assistant text has its own adapter coalescer, but each `item/plan/delta` emits full node, plan, and turn-item events (`CodexAdapterV2.ts:3171-3205`). This establishes exposure to chatty frames, not a measured regression: V2 event shapes, persistence, client reduction, and provider fixture rates differ from V1, and main's coalescer targeted `tool.updated`, not plan deltas. Add an integrated V2 stream test using a burst of stable tool updates plus an interleaved boundary, and record frame/byte counts on checked-in provider replays before assigning severity or claiming the main PR's 90% figure. Any fix should coalesce only wire delivery, retain persisted events, key by turn plus stable item identity, and preserve sequence/completion-marker semantics. + +## Known-main bugs + +None identified in the provider behaviors used as comparison evidence. The five findings above are branch omissions or weaker semantics, not defects inherited unchanged from main. + +## Verification and gaps + +- Read `AGENTS.md` and `.repos/effect-smol/LLMS.md` before assessing Effect scopes, finalizers, races, and error handling. +- Verified the exact frozen HEAD, supplied main ancestry, and 332-commit count before and after inspection. +- Ran: + + ```text + vp test run \ + apps/server/src/orchestration-v2/AttachmentPrompt.test.ts \ + apps/server/src/orchestration-v2/ProviderTurnTokenUsage.test.ts \ + apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts \ + apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.test.ts + ``` + + Result: 4 files passed, 96 tests passed. + +- Ran the bounded follow-up suite for the Cursor SDK wrapper and the web/mobile work-log projections: + + ```text + vp test run \ + apps/server/src/textGeneration/CursorTextGeneration.test.ts \ + packages/client-runtime/src/work-log/presentation.test.ts \ + apps/web/src/session-logic.test.ts \ + apps/mobile/src/lib/threadActivity.test.ts + ``` + + Result: 4 files passed, 81 tests passed. These tests confirm the current option and projection shapes; they do not attempt a live provider call or prove tool denial/image rendering, which is why the missing behavioral cases remain gaps below. + +- Per instructions, no live provider, server, browser, external OpenCode server, or production state was used. SDK behavior was validated from checked-in types, testkits, full callers, current-main adapter tests, and the exact installed `@cursor/sdk@1.0.22` type declarations/runtime bundle. +- The focused suite has no Cursor text-generation tool-denial test, no V2 Claude workspace-image projection test, no OpenCode child-list/child-abort failure test, no external-server session-release test, and no V2 large-gap or HTTP-unavailable test asserting a bounded socket snapshot with progressive-history metadata. Those are the direct verification gaps behind the five recommendations. +- The final WebSocket snapshot check was source-only; no additional test was run because the existing fixtures stop at client subscription inputs or the pure replay decision and do not exercise the server fallback through client history installation. +- No focused V2 test currently demonstrates semantic coalescing or establishes a frame/byte budget for active tool-update or plan-delta bursts. No performance percentage was inferred from main's benchmark claim. +- No product or test source was edited. This report is the only file written by this audit. diff --git a/audits/orchestrator-v2/2026-09-02/references.json b/audits/orchestrator-v2/2026-09-02/references.json new file mode 100644 index 000000000000..c86f21e471d7 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-02/references.json @@ -0,0 +1,11 @@ +{ + "branch": "t3code/codex-turn-mapping", + "head": "d2f1f511f4cc833bc930d6c355cd0f9b61e835a0", + "main": "57a66608b918d673eeec7e6c94ea5906b756fcd0", + "merge_base": "57a66608b918d673eeec7e6c94ea5906b756fcd0", + "prior_review": "47f5b100440591d2f49aa30cf3bb69eacae07f52", + "rebased_prior_review_tip": "c1791ab2637", + "date": "2026-09-02", + "initial_status": "clean", + "mode": "read-only audit; no fixes, commits, browsers, servers or live provider tests" +} diff --git a/audits/orchestrator-v2/2026-09-04/AUDIT.md b/audits/orchestrator-v2/2026-09-04/AUDIT.md new file mode 100644 index 000000000000..149fc0c1d0fb --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/AUDIT.md @@ -0,0 +1,151 @@ +# Orchestrator V2 re-audit, September 4, 2026 + +The branch still needs corrective work before rollout. **13 of the previous 17 findings remain open; four are fixed. This audit adds five findings: four missed provider ports and one scheduler scaling defect.** Fifteen main-only commits are assessed separately: eight at the initial capture and seven that arrived during review. Their absence is not evidence of another bad rebase, and V1-specific changes need an equivalent-behavior check before being ported. + +The most consequential open paths are historical V2 upgrades, mixed V1/V2 project deletion, full checkpoint diffs after a second run, and provider operations that hang or continue after the UI considers them finished. The recent recovery, query, coalescing, and client rendering fixes are real improvements and are credited below. + +This was an audit, not an implementation pass. Three GPT-5.6 Sol reviewers worked in bounded parallel groups; the parent reviewed their evidence and resolved classification disagreements. No product source or existing test was edited by this audit. Artifacts and audit-only probes are kept here, uncommitted, as requested. Existing local work was preserved. + +## Reviewed state + +| Reference | Value | +| ------------------------------ | ------------------------------------------------------------------------------------------- | +| Branch | `t3code/codex-turn-mapping` | +| Committed target | `8af5734365f7c45bc08b57066dbae42f9f7d4235` | +| Initial fetched `origin/main` | `d7cf8aaa8d4fbcbdd523b4f4bc86fda5c47b4a70` | +| Main at the final audit cutoff | `f6db4206258b0ef30e8dd8949627acfd209bf338` | +| Merge base | `c8f77e0d441264efb0acfac312e852c81ae3da83` | +| Prior audit target | `d2f1f511f4cc833bc930d6c355cd0f9b61e835a0` | +| Prior audit main | `57a66608b918d673eeec7e6c94ea5906b756fcd0` | +| Initial comparison | 333 branch-only commits; eight main-only commits; 991 changed files between the final trees | +| Closing comparison | 333 branch-only commits; 15 main-only commits; 999 changed files between the final trees | +| Incoming-main inventory | 240 initial commits plus seven late arrivals since the preceding audit's main reference | +| Pull request | [#2829](https://github.com/pingdotgg/t3code/pull/2829) | + +Committed findings use the frozen Git revisions, not whatever another process subsequently writes into this worktree. Local changes are reviewed separately in the domain reports. The initial capture contained 56 dirty paths; the final overlay contains 59. Later changes and their hashes are recorded in `worktree-final-manifest.json` and `worktree-drift.diff`; `closing-references.json` confirms they had not changed again. Frozen copies end in `.snapshot` so they cannot accidentally become product test suites. The local `main` branch is stale and was not used as the baseline. + +The initial file and main-commit inventories are in [changed-files.tsv](changed-files.tsv), [main-feature-file-map.tsv](main-feature-file-map.tsv), and [main-since-prior.txt](main-since-prior.txt). [changed-files-final.tsv](changed-files-final.tsv) and [main-late-arrivals.txt](main-late-arrivals.txt) record the closing comparison and seven additional commits. The [feature map](FEATURE-MAP.md) records behavior, surfaces, exceptions, and validation limits. Inventory coverage is not a claim that every changed line or every live integration was executed. Main commits after the explicit cutoff are outside this audit. + +## What changed since the previous audit + +| Previous item | Current result | Evidence | +| ----------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| F02: sidebar initialization crash | **Fixed in committed HEAD.** | `Sidebar.tsx:209-212` declares `EMPTY_PROVIDER_ENTRIES` at module scope before every use. | +| F14: full transcript hydration for checkpoint diffs | **Fixed in committed HEAD.** | `CheckpointDiffQuery.ts:102-121` uses the three narrow `getCheckpointContext` queries. F03's baseline ownership bug is separate. | +| F15: recovery loads every active and archived history | **Fixed in committed HEAD.** | Recovery selects `getRecoveryThreadIds("runtime")` and loads only candidates. Corruption verification still scans canonical rows; that is recorded separately as V04. | +| F17: mobile assistant renderer bypass | **Fixed in committed HEAD.** | The active assistant row now uses the specialized citation/template renderer with its scoped media callback and composer template action. | +| V01: missing tool-event coalescer | **Implementation gap addressed.** | V2 coalesces live tool updates and bounds buffered/unacknowledged events. A provider-workload byte/frame benchmark is still absent. | +| V02: cwd catalog refresh outside web | **Broad concern closed.** | Mobile refreshes cwd-specific catalogs; no narrower execution-only stale-catalog failure was established. | +| F01: historical V2 migration failure | **Still open, reproduced against more histories.** | Actual migrations fail for old 052, prior-audit 053, and pre-reconciliation 055 manifests. Fresh/main-to-V2 and committed 058 to local 059 work. | +| F05: project transport divergence | **Still open and broadened.** | HTTP/offline CLI now also omit recently added project update fields. | + +Range-diff review found 265 equal patches, 64 changed pairs, three unmatched old patches, and four unmatched new patches. The old Codex availability patch was absorbed by the managed-driver initializer, not lost. Integration/lint bookkeeping accounts for two unmatched pairs. The two remaining new commits carry resource work and main reconciliation. See [the concise range-diff inventory](prior-audit-range-diff-summary.txt); an unmatched patch alone was not treated as a regression. + +## Open findings + +P1 means fix before rollout for the stated trigger. P2 means a concrete correctness or scaling issue that should be scheduled; it does not imply every user hits it. These 18 rows exclude the main-only changes, intentional product decisions, and unmeasured validation questions. + +| ID | Priority | Trigger and observable consequence | Classification | Recommended action | +| --- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| F01 | P1 | Starting this build on reproduced historical V2 databases fails migration with duplicate-column/table errors. New main migrations below the old numeric maximum are also skipped. | Rebase/branch-history compatibility regression. | Reconcile recorded migration identities and repair skipped main work; test supported historical manifests. Making one DDL statement idempotent is insufficient. | +| F03 | P1 | After two ordinary runs, full diff from baseline zero rejects because the shared root checkpoint scope now belongs to run 2, while the query requires run-1 ownership. | V2 checkpoint model/query mismatch. | Resolve the baseline using the actual shared scope; build the regression fixture through the real allocator/projector. | +| F04 | P1 | Force-deleting a project with imported V1 threads over WebSocket commits V2 thread deletions, then rejects the force-less legacy project deletion. Deleted V2 history is not reimported. | Destructive split lifecycle regression. | Validate and coordinate mixed-store deletion before irreversible work; preserve force and cover partial failure. | +| F05 | P1 | HTTP and live/offline CLI can orphan V2 threads on project deletion, reject requested forced deletion, or silently drop missing-root creation and new project update fields. | Cross-transport port omission. | Route transports through the same lifecycle semantics and preserve every typed input field. | +| F06 | P1 | OpenCode Stop ignores descendant enumeration/abort failures and traversal timeout, so child work can continue after success is reported. | Missing explicit-Stop failure behavior from main. | Bound traversal but propagate relevant failures for explicit Stop; tolerate only known benign not-found cases. | +| F07 | P1 | Releasing a session attached to an external OpenCode server aborts local SSE but does not stop its root/child provider work. | Missing teardown behavior from main. | Perform bounded root/descendant shutdown and log cleanup failures. | +| F08 | P1 | Cursor background title/metadata generation runs unrestricted SDK agent mode in the real project directory, with its sandbox disabled. | Lost metadata permission boundary during the accepted SDK migration. | Restore a read-only/non-tool boundary for metadata work; a timeout alone cannot prevent writes. | +| F09 | P1 | Saving a queued edit with newly selected generic files drops those files; a file-only edit can also be cleared when another device advances the queued run. | Bug in V2's added queue editor. | Include files in saveability, uploads, dirty-state detection, and recovery. | +| F10 | P1 | Mobile reloads a message containing a file/PDF/video but shows no attachment because the V2 feed filters all non-images before rendering. | Client port regression from main. | Preserve the full attachment list and use the existing type-specific renderers. | +| F11 | P2 | Claude reads a workspace image, but both client adapters flatten it into a generic tool row without the preview path. | Missing main image-preview feature. | Derive and validate image paths from retained Read input on web and mobile. | +| F12 | P2 | A transient initial title-generation error ends the job after one call and clears its marker. Main retries before giving up. | Missing main retry behavior. | Restore bounded initial retries while preserving stale-request guards and final cleanup. | +| F13 | P2 | A thread fails, then is snoozed into the future; its older failed status immediately defeats that newer snooze and permits early settlement. | Missing timestamp ordering in the settlement port. | Require failure evidence newer than `snoozedAt`; test both orderings. | +| F16 | P1, performance | HTTP snapshot failure or a reconnect beyond 128 events/1 MiB sends a full lifetime projection over WebSocket and loses progressive-history metadata. Healthy HTTP opens are bounded. | Missing bounded fallback invariant from main. | Use the existing window/budget query for socket fallback and preserve a usable history cursor. | +| F18 | P1 | OpenCode's native SSE iterable ends cleanly without local abort. The adapter ignores the end and keeps its public queue alive, so subsequent provider events never arrive and turns can stick. | New missed main port from [#9653](https://github.com/pingdotgg/t3code/pull/9653). Domain ID `PROV-OPENCODE-01`. | Treat unexpected EOF as a broken session and terminalize/reconnect through the intended lifecycle. | +| F19 | P1 | An OpenCode approval/question reply never resolves. The durable request is already resolved, while its unbounded SDK call holds an effect worker and blocks that thread's subsequent non-title effects. | New missed main port from [#9653](https://github.com/pingdotgg/t3code/pull/9653). Domain ID `PROV-OPENCODE-02`. | Pass the SDK abort signal, bound the call, and make delivery failure/retry behavior explicit. | +| F20 | P1 | Claude returns `subtype: success`, `is_error: false`, and a dead-turn `terminal_reason` such as `api_error` or `blocking_limit`. V2 records successful completion without the failure explanation. | New missed SDK-result port from [#9135](https://github.com/pingdotgg/t3code/pull/9135). Domain ID `PROV-CLAUDE-01`. | Classify structured terminal reasons before success and preserve the user-facing failure. | +| F21 | P2 | OpenCode emits `step-finish` token counts, but V2 ignores them and emits terminal provider-turn usage as unavailable. | New missed telemetry port from [#9132](https://github.com/pingdotgg/t3code/pull/9132). Domain ID `PROV-OPENCODE-03`. | Accumulate tokens with correct turn ownership and complete/partial/unavailable status. This finding does not establish increased billing or a broken separate usage dashboard. | +| F22 | P2, performance | Every five-second scheduler tick reads, decodes, and sorts all tasks, including disabled and far-future tasks, despite an existing due-task index. | Scaling defect in a branch-only feature. Domain ID `PERSIST-N01`. | Query due candidates directly; retain separate crash recovery and corrupt-row isolation. | + +The detailed reports contain file/line evidence, actual callers, main counterparts, and proof limits: + +- [Persistence and lifecycle](persistence.md): F01, F03-F05, F13-F15, F22; historical migration and allocator/policy probes. +- [Providers](providers.md): F06-F08, F11, F18-F21; all seven built-in drivers and capability differences. +- [Clients](clients.md): F02, F09-F10, F17, inherited rendering and queue decisions, recent main UI/performance work. +- [Cross-cutting review](cross-cutting.md): F12, F16, protocol/remote boundaries, packaging, usage, coalescing, rebase inventory, CI. + +F04/F05 can share a project lifecycle implementation, but mixed-store deletion and each transport need distinct coverage. F06/F07 share traversal mechanics but have different contracts: explicit Stop surfaces failure; release is bounded and logs failure. F14 is fixed without fixing F03. Live coalescing is fixed without fixing F16 or unused-stream lifetime. + +## Main-only catch-up + +The first eight changes below were absent at the initial capture. Seven more arrived during review and are assessed in the addendum. None is counted among the 18 findings. The first column is a stable decision ID, not a severity rank. + +| ID | Main change | Current branch difference | Recommendation | +| --- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | +| M01 | [#9740](https://github.com/pingdotgg/t3code/pull/9740), stop unused thread streams | Live/detail atoms retain subscriptions for five minutes after the last consumer. Main closes them immediately and retains only a separate warm resume snapshot. Applies to all clients and remote connections. | Port, high performance priority. Client report `CLIENT-01`. | +| M02 | [#9744](https://github.com/pingdotgg/t3code/pull/9744), update notice refinement | Base notice exists; narrow-layout threshold, tooltip truncation, and icon refinement are absent. | Port as visual polish; no total feature loss claimed. | +| M03 | [#9627](https://github.com/pingdotgg/t3code/pull/9627), PR author profile links | Avatar/name render without the new non-bot profile link. | Port, ordinary feature catch-up. | +| M04 | [#9748](https://github.com/pingdotgg/t3code/pull/9748), terminal history byte cap | History is limited by line count only; a giant line and saved-history load remain unbounded. Main adds an 8 MiB cap and bounded Unicode-safe tail reads. | Port, high performance priority. | +| M05 | [#9747](https://github.com/pingdotgg/t3code/pull/9747), terminal metadata indexing | Every mounted row consumer rescans/sorts environment terminal metadata. Local palette visibility work only gates PR/VCS reads. | Port the shared index and stable identities. Client report `CLIENT-02`. | +| M06 | [#9749](https://github.com/pingdotgg/t3code/pull/9749), mobile parsed-review cache bound | Per-section keep-alive entries retain parsed diffs indefinitely and prewarming includes all loaded sections. Main bounds retention and nearby prewarming. | Port, high mobile memory priority. Client report `CLIENT-03`. | +| M07 | [#9743](https://github.com/pingdotgg/t3code/pull/9743), new-thread Project settings shortcut | Sidebar and command palette access remain; the new-thread header callback is unwired. | Port the missing entry point. | +| M08 | [#9739](https://github.com/pingdotgg/t3code/pull/9739), fold a single trailing activity | One successful late tool row stays detached below a settled answer. Main folds only that safe single-row case. | Port, presentation priority. Client report `CLIENT-04`. | + +Late arrivals, reviewed separately against the unchanged branch: + +| ID | Main change | Current branch difference | Recommendation | +| --- | --------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| M09 | [#9752](https://github.com/pingdotgg/t3code/pull/9752), defer mobile file highlighter startup | Opening a file route can start the highlighter before any source view needs it, including on image/video/preview routes. The manager deduplicates later starts; source highlighting already has a lazy consumer. | Port; remove redundant route-wide startup while preserving source highlighting. | +| M10 | [#9758](https://github.com/pingdotgg/t3code/pull/9758), avoid history reads for metadata/control commands | V2 metadata mutations, initial title generation, runtime-request replies and provider controls still load full projections. Local `getThread` work only narrows visits and auto-settlement. Branch-name generation already consumes launch input directly. | Adapt narrow queries to V2; preserve session-detach and target-identity guards. Keep the context needed by turn start or explicit title regeneration. An app-thread-only lookup cannot replace every read safely. | +| M11 | [#9760](https://github.com/pingdotgg/t3code/pull/9760), defer history image URL requests | Chat scope requests asset URLs for all loaded user attachments before row virtualization. Main requests historical image URLs from mounted user rows. | Port the row-scoped lookup while preserving pending local-preview handoff. | +| M12 | [#9762](https://github.com/pingdotgg/t3code/pull/9762), current model classification | Bundled Codex manifest lacks `gpt-6-astra` in its current list. Runtime remote-manifest refresh can compensate online; offline/fallback classification remains stale. | Port the small bundled-data change. This is not missing provider execution support. | +| M13 | [#9753](https://github.com/pingdotgg/t3code/pull/9753), proactive diff activation | A completed run's empty/non-ready checkpoint can open the diff panel, including over an active PR panel. V2 checks summary existence only. | Adapt main's active-surface/readiness/nonempty guard to V2 run summaries. | +| M14 | [#9759](https://github.com/pingdotgg/t3code/pull/9759), sidebar background prominence | Unread/wake state prevents dimming a still-working thread. Main reserves that prominence for ready or action-required states. | Port the presentation rule using V2 statuses. | +| M15 | [#9763](https://github.com/pingdotgg/t3code/pull/9763), automatic-pull reset | The on/off switch works, but its standard reset-to-default button is absent. | Port the small reset affordance; the underlying feature is retained. | + +## Intentional differences and decisions + +Previously accepted architectural choices are not reopened merely because their implementations differ from V1. + +| ID | Question | Current behavior and recommendation | +| --- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| D01 | Port continuation after a server update now? | V2 explicitly withholds `serverUpdateThreadContinuation`; recovery terminalizes running work. Main resumes it. Port before claiming full update-continuation parity, or keep the deferral explicit. | +| D02 | Should inherited message/plan links use their source worktree? | Normal web/mobile Markdown uses the active fork; the inspector uses source ownership. Decide source-history versus current-fork semantics before changing this. Main has no equivalent inherited-row oracle. | +| D03 | Keep the Cursor SDK boundary? | Keep the accepted SDK migration and explicit unsupported capabilities. F08's metadata permission loss is an independent bug. | +| D04 | Keep the limited legacy import? | Keep the documented metadata/message import, fresh provider continuation, and bounded imported context. Rich old tools/runs/checkpoints/approvals/plans and native-session continuity remain intentionally excluded. F01 is not part of this tradeoff. | +| D05 | Keep protocol V2 incompatibility? | Keep the version gate and deploy matching clients/servers. CORS permits the protocol header. | +| D06 | Keep bounded portable summaries? | Keep the accepted 240-character per-item portable summary limit and separate 32,000-character legacy context budget unless fuller fidelity is now required. | +| D07 | Keep compact mobile queue controls? | Mobile supports reorder/steer/cancel; active server queues still lack web's composer editor and thumbnails. New-task outbox editing is a different path. Keep as a surface choice unless parity is now wanted. F10 is independent. | +| D08 | What happens to schedules bound to archived/deleted threads? | Binding/upsert does not reject archived targets; later sends reject them, and recurring tasks stay enabled. Choose reject/disable behavior or deliberate waiting for unarchive. This is a branch-only lifecycle decision, not a missing main feature. | + +## Cost and validation limits + +| ID | What remains unproven | Next useful proof | +| --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| V01 | Actual frame/byte savings from V2 coalescing and the workload impact of fallback snapshots. Source and focused tests establish bounds on live events, not end-to-end payload cost. | Replay representative provider activity and large-thread reconnects; measure frames, bytes, and retained state. Keep persisted events intact. | +| V03 | Real interaction behavior across web, desktop, mobile, and remote/relay connections. | An authorized integrated pass for attachments, queue edits, inherited links, and fallback resume. No browser/simulator permission was given for this audit. | +| V04 | Latency of the deliberate startup corruption scan. It pages in groups of 500 and decodes each canonical row once, but still scans all 16 projection tables before command readiness. | Benchmark representative retained databases before choosing a different strategy. Preserve corrupt-row detection/recovery; do not label this the old F15 history-hydration bug. | + +Cost findings are based on concrete ownership, SQL, retention, or transport paths. No measured CPU, latency, heap, or billing multiplier is asserted. F06/F07 permit provider work to continue after intended shutdown, but this audit did not measure resulting spend. F21 is missing telemetry, not proof of excess spend. The old V1 transfer benchmark/report workflow remains deliberately removed; focused V2 wire tests are not an equivalent workload benchmark. + +## Validation and CI + +| Focused batch | Passing checks | Evidence | +| ------------------------ | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Parent cross-cutting | 19 file executions, 193 tests | Five `root-*-tests*.log` batches covering authorization, startup, WS helpers, coalescing/budgets, awareness, usage, attachments, title handling, native-command routing and launch guards. | +| Providers | Nine files, 215 tests | [providers-tests.log](providers-tests.log), seven V2 adapters plus auth/registry. These mocked suites do not exercise real provider processes. | +| Persistence | Ten product files, 52 tests | [persistence-tests.log](persistence-tests.log), recovery, checkpointing, import, scheduling, project handlers, and local settlement. | +| Clients | Three committed files/21 tests; five local-overlay selections/60 tests | [clients-focused-tests.log](clients-focused-tests.log), queue behavior, status leases, desktop topology, and patched Swift notification harness. No simulator ran. | +| Persistence audit probes | Six cases using real migration, allocator/projector, and policy implementations | [persistence-audit-probes.test.ts](persistence-audit-probes.test.ts). Passing means the asserted failures/state mismatches reproduced; it does not mean those bugs are fixed. | +| Provider audit probe | One case through the actual Claude V2 adapter | [provider-adapter-regression-probes.test.ts](provider-adapter-regression-probes.test.ts) and its [log](provider-adapter-regression-probes.log). A structured `api_error` result incorrectly emits completed/no failure. | + +The parent re-ran both audit probe files together after reviewing their code: all seven assertions passed in [reviewed-probes.log](reviewed-probes.log). This confirms the reproductions, not repaired behavior. Repeat runs are not counted as additional coverage. + +One initial test invocation accidentally discovered a frozen `.test.ts` copy under this audit directory. Its relative import failed while the actual three product suites passed. Copies were renamed to `.snapshot`, the manifest was updated, and the rerun passed. This was an audit setup failure, not a product regression. + +Current-head [CI Check](https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744766) fails formatting in seven files: `WorktreeMcpService.ts`, `EffectOutbox.ts`, `cursorSdkModel.ts`, two V2 architecture docs, `boundedThreadSnapshotHttp.ts`, and `threadSnapshotHttp.ts`. Generic tests and server shards 1/2 passed; server shard 3 was cancelled. Rust and release smoke passed. Web/mobile/macOS previews were skipped. Recent review comments since the previous audit cutoff were empty. These statuses apply to committed HEAD, not the uncommitted overlay. + +No repo-wide checks, dev servers, browser sessions, provider processes, production database writes, commits, pushes, PR creation, or external review comments were performed. Green focused tests do not contradict findings whose production trigger their fixtures omit. The full historical-manifest matrix and live client/provider validation remain incomplete. + +## Decision sheet + +[DECISIONS.tsv](DECISIONS.tsv) gives each finding, catch-up item, and product question a separate row. `user_decision` is blank: enter `yes`, `no`, or `defer`. Fixed findings are retained as closed rows so a later rebase audit can test them again. The recommendations do not authorize or implement new fixes. diff --git a/audits/orchestrator-v2/2026-09-04/DECISIONS.tsv b/audits/orchestrator-v2/2026-09-04/DECISIONS.tsv new file mode 100644 index 000000000000..492a6e3835d2 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/DECISIONS.tsv @@ -0,0 +1,51 @@ +id category status priority difference proposed_action recommendation user_decision validation evidence +F01 correctness open P1 Historical V2 upgrades fail Repair migration identity reconciliation and skipped main work yes Three historical full manifests plus partial checkpoints; never touch live userdata persistence.md +F02 correctness fixed closed Sidebar empty-provider initialization No new fix; revalidate after future rebases no action Module-scope declaration precedes all uses clients.md +F03 correctness open P1 Full diff fails after ordinary run 2 Resolve baseline through actual shared checkpoint scope yes Build two runs through real allocator/projector and request full diff persistence.md +F04 correctness open P1 WebSocket forced project deletion partially commits Coordinate V1/V2 deletion and preserve force yes Imported plus V2-only, active plus archived, force false/true and downstream rejection persistence.md +F05 correctness open-broadened P1 HTTP and CLI project lifecycle drops fields and cleanup Use consistent typed lifecycle semantics across transports yes HTTP/live/offline CLI; populated deletion and every create/update field persistence.md +F06 correctness open P1 OpenCode Stop hides descendant failures Propagate explicit Stop failures with bounded traversal yes Nested descendant enumeration and abort failures; benign not-found; timeout providers.md +F07 correctness open P1 External OpenCode work survives release Bound root/descendant shutdown and log cleanup failures yes External server root and child activity stops during session release providers.md +F08 correctness open P1 Cursor metadata helper can write project files Restore constrained metadata generation yes Metadata generation cannot invoke write/command tools at project cwd providers.md +F09 correctness open P1 Queued edit loses newly added generic files Carry files through save and external-start recovery yes File-only and mixed edits; another device starts/cancels queued run clients.md +F10 correctness open P1 Mobile persisted non-image attachments disappear Remove image-only filtering before attachment renderer yes Reload file/PDF/video messages and open scoped attachments clients.md +F11 correctness open P2 Claude Read image previews absent Derive validated preview path on both clients yes Image Read versus non-image Read; web and mobile scoped assets providers.md +F12 correctness open P2 Initial automatic title has no transient retry Restore bounded retry with stale marker protection yes Transient typed failure then success; exhausted retries; stale request cross-cutting.md +F13 correctness open P2 Old failure defeats a newer snooze Require failed-run evidence newer than snoozedAt yes Failure before snooze versus after; closed-PR rule preserved persistence.md +F14 performance fixed closed Checkpoint query hydrated full history No new fix; retain narrow checkpoint context no action Three metadata queries; no transcript/fork hydration persistence.md +F15 performance fixed closed Runtime recovery loaded all terminal histories No new fix; retain recovery candidate selection no action Terminal histories excluded; actual incomplete work still selected persistence.md +F16 performance open P1 WebSocket fallback sends lifetime history Window and budget socket snapshots and keep history cursor yes HTTP failure and large/invalid reconnect; frame/row bounds; later history paging cross-cutting.md +F17 correctness fixed closed Mobile assistant renderer bypass No new fix; retain scoped specialized renderer no action Citations, template action, iOS scoped image/video callback are wired clients.md +F18 missed-main-port new P1 Clean OpenCode SSE EOF leaves session apparently ready Handle unexpected clean EOF through failure/reconnect lifecycle yes Deterministic stream completion; no timing-based absence assertion providers.md: PROV-OPENCODE-01 +F19 missed-main-port new P1 OpenCode approval/question reply can hang effect lane Abort and time-bound SDK replies; define delivery failure handling yes Never-resolving reply; cancellation; next same-thread effect; both reply types providers.md: PROV-OPENCODE-02 +F20 missed-main-port new P1 Claude dead-turn reason reported completed Classify structured terminal_reason and preserve failure detail yes Actual adapter reproducer plus all SDK dead-turn reasons and interrupts providers.md: PROV-CLAUDE-01 +F21 missed-main-port new P2 OpenCode per-turn token telemetry unavailable Accumulate step-finish usage with correct turn ownership yes Multiple steps, partial usage, cache/reasoning tokens, out-of-turn events providers.md: PROV-OPENCODE-03 +F22 performance new P2 Scheduler scans all rows every five seconds Query only due candidates and retain corrupt-row isolation yes Many future/disabled tasks; only due rows decoded; crash recovery separate persistence.md: PERSIST-N01 +M01 main-only-catch-up absent high performance Release unused thread streams Port [#9740](https://github.com/pingdotgg/t3code/pull/9740) yes Last consumer closes stream; remount retains cursor/warm snapshot; all clients clients.md: CLIENT-01 +M02 main-only-catch-up absent polish Server update notice refinement Port [#9744](https://github.com/pingdotgg/t3code/pull/9744) yes Narrow layout and tooltip; no baseline notice removal clients.md +M03 main-only-catch-up absent feature Pull request author profile links Port [#9627](https://github.com/pingdotgg/t3code/pull/9627) yes Non-bot author link preserves existing avatar/name clients.md +M04 main-only-catch-up absent high performance Bound terminal history by bytes Port [#9748](https://github.com/pingdotgg/t3code/pull/9748) yes Giant partial line, UTF-8 tail, saved history read and attach payload cross-cutting.md +M05 main-only-catch-up absent performance Index terminal metadata once per snapshot Port [#9747](https://github.com/pingdotgg/t3code/pull/9747) yes Many row consumers reuse one index and unaffected array identities clients.md: CLIENT-02 +M06 main-only-catch-up absent high performance Bound mobile parsed review cache and prewarm Port [#9749](https://github.com/pingdotgg/t3code/pull/9749) yes Count/source-size limits, large entries, adjacent prewarm, registry isolation clients.md: CLIENT-03 +M07 main-only-catch-up absent entry point New-thread Project settings shortcut Port [#9743](https://github.com/pingdotgg/t3code/pull/9743) yes Header path works; sidebar and palette remain available clients.md +M08 main-only-catch-up absent presentation Fold one safe trailing activity Port [#9739](https://github.com/pingdotgg/t3code/pull/9739) yes Single ordinary success folded; failures, resource rows and groups stay visible clients.md: CLIENT-04 +M09 main-only-catch-up absent performance Defer mobile file highlighter startup Port [#9752](https://github.com/pingdotgg/t3code/pull/9752) yes First image/video/preview route does not load highlighter; source route still lazily highlights clients.md: late-main addendum +M10 main-only-catch-up missing; local groundwork performance Avoid full history for metadata and provider control Adapt narrow-read invariant from [#9758](https://github.com/pingdotgg/t3code/pull/9758) to V2 yes Metadata edits, interrupt and runtime replies do not read unrelated history; actual turn/title context retained persistence.md: M10 +M11 main-only-catch-up absent performance Defer signed URLs for offscreen history images Port [#9760](https://github.com/pingdotgg/t3code/pull/9760) yes Only mounted image rows query URLs; pending local-preview handoff preserved clients.md: late-main addendum +M12 main-only-catch-up bundled fallback behind catalog Current Codex model classification Port bundled manifest from [#9762](https://github.com/pingdotgg/t3code/pull/9762) yes Offline bundle marks gpt-6-astra current; online remote refresh already can compensate cross-cutting.md +M13 main-only-catch-up absent correctness Prevent empty proactive diffs replacing a pull request Adapt [#9753](https://github.com/pingdotgg/t3code/pull/9753) to V2 run summaries yes Active PR remains selected; only ready nonempty checkpoints open; loading can defer cross-cutting.md +M14 main-only-catch-up absent presentation Dim background working threads consistently Adapt [#9759](https://github.com/pingdotgg/t3code/pull/9759) using V2 statuses yes Unread/wake does not promote background work; active/selected/action-required states remain clear cross-cutting.md +M15 main-only-catch-up absent affordance Reset automatic pull to default Port [#9763](https://github.com/pingdotgg/t3code/pull/9763) reset action yes Reset calls existing false setter; on/off switch remains functional cross-cutting.md +D01 product-decision explicitly deferred decision Server-update continuation Port V2 continuation or keep capability explicitly unavailable yes for parity, otherwise defer Restart active work through intended recovery semantics cross-cutting.md +D02 product-decision unresolved decision Inherited Markdown source ownership Choose source worktree versus current fork for inherited references decision needed Diverged source/fork worktrees; normal messages, plans and inspector; both clients clients.md +D03 product-decision accepted decision Cursor SDK architecture Keep SDK migration and explicit unsupported capabilities keep F08 permission boundary is an independent required fix providers.md +D04 product-decision accepted decision Legacy import scope Keep metadata/message import with fresh provider continuation keep Docs and product messaging remain accurate; F01 still needs repair persistence.md +D05 product-decision accepted decision Protocol V2 compatibility gate Keep rejecting mismatched peers keep Matching hosted/local/mobile/desktop server protocol; CORS header cross-cutting.md +D06 product-decision accepted decision Portable context summary limits Keep per-item and legacy-import context budgets keep Explicitly accept fidelity tradeoff unless requirements change AUDIT.md +D07 product-decision accepted decision Compact mobile active-thread queue Keep reorder/steer/cancel without web editor and thumbnails keep New-task outbox editor is separate; F10 attachment rendering remains a bug clients.md +D08 product-decision unresolved decision Schedules targeting archived or deleted threads Choose disable/reject or deliberate waiting for unarchive decision needed Archive/unarchive/delete existing target; new binding; recurring failure state cross-cutting.md +V01 validation implementation fixed; measurement open validation V2 wire workload budget Measure coalescing and fallback on representative provider replay yes Frames, bytes, retained state; persisted events untouched cross-cutting.md +V02 validation closed as broad concern closed Cwd catalog refresh outside web No broad fix without a narrower reproduction no action Mobile refresh retained; no execution-only stale failure established providers.md +V03 validation not run validation Real client and remote interactions Run integrated pass when explicitly authorized yes with authorization Web/desktop/mobile attachments, queue edits, inherited links, remote fallback AUDIT.md +V04 validation unmeasured tradeoff validation Startup canonical projection verification Benchmark before changing full corruption verification measure first Large retained DB, startup latency and memory; preserve corruption recovery persistence.md +C01 ci failed merge gate Current-head formatting failure Fix seven formatting errors and obtain non-cancelled required checks yes CI Check plus server shard 3; do not confuse dirty overlay with committed CI ci-check-failure.log diff --git a/audits/orchestrator-v2/2026-09-04/FEATURE-MAP.md b/audits/orchestrator-v2/2026-09-04/FEATURE-MAP.md new file mode 100644 index 000000000000..a301a8ddfe12 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/FEATURE-MAP.md @@ -0,0 +1,110 @@ +# Main and Orchestrator V2 feature map + +Comparison: committed V2 `8af5734365f7c45bc08b57066dbae42f9f7d4235` against initially fetched main `d7cf8aaa8d4fbcbdd523b4f4bc86fda5c47b4a70`, with uncommitted work reviewed separately. Seven late main commits through the final cutoff `f6db4206258b0ef30e8dd8949627acfd209bf338` are assessed as M09-M15. See [AUDIT.md](AUDIT.md) for findings, decisions, and evidence limits. + +“Retained” means the inspected implementation and its active caller have an equivalent path, not that every surface was exercised. “Shared” means the implementation matches the initial main; changed callers still need review. “Intentional” records an architectural choice rather than treating file deletion as feature deletion. Findings F01-F22 exclude closed IDs F02/F14/F15/F17. Main-only items M01-M15 are assessed separately for equivalent behavior or catch-up work. + +## Core, data, and transports + +| Feature | Main behavior / invariant | V2 committed behavior | Assessment | +| ----------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Commands, events, read models | Durable commands/events and client projections | Replaced with V2 run/node/provider-thread graph, typed receipts, outbox and canonical projections | Intentional architecture; broad source and focused lifecycle review, not a V1 file-for-file port. | +| Fresh/current-main database upgrade | Latest main schema starts cleanly | Main 047 enters V2 048-058 | Retained. Local 059 upgrade is also probed. | +| Historical V2 database upgrade | A previously used branch database should remain readable | Old 052/053/055 manifests collide with renumbered migrations and skip lower-numbered main work | F01, three reproduced cohorts; partial historical stopping points remain untested. | +| Legacy thread discovery/import | Existing conversations remain discoverable | Metadata/shell import plus on-demand messages; importer leaves V1 source rows intact | Retained within D04's accepted import scope. | +| Rich legacy history and provider continuity | V1 retains native history, runs, tools and checkpoints | Rich old state is not reconstructed as V2 graph; first continuation is fresh with bounded imported context | D04, explicit limitation; not equivalent to F01's startup failure. | +| Startup effect recovery | Recover pending durable work and reconcile live provider state | Replay-safe/process-bound separation, typed receipts, candidate selection | Retained in tested paths; F15 fixed. | +| Corrupt projection recovery | Detect unusable persisted state before serving commands | All 16 canonical tables paged and decoded before readiness | V04, deliberate safety/performance tradeoff; peak page size bounded, total work unbenchmarked. | +| Metadata and provider-control reads | Latest main uses shell queries for checks/replies/interrupts that do not need conversation detail | Several V2 mutation/control services still load full projections; local narrow reads cover visit and auto-settlement only | M10, adapt to V2 with required run/request/session metadata preserved. Branch-name generation already uses launch input directly; initial titles still load full history to locate one message. | +| Project create/update | Typed project fields and missing-root option survive transport | WebSocket preserves current fields; HTTP/offline CLI drop several fields | F05. Main's new auto-pull/icon/default-environment fields make the omission broader. | +| Project deletion | Force semantics and associated-thread cleanup stay consistent | WebSocket deletes V2 children before force-less legacy delete; HTTP/CLI bypass V2 cleanup | F04/F05; imported, V2-only, active and archived children need explicit tests. | +| Thread archive/unarchive/delete | Reverse states and explicit thread identity | Commands go through V2 WebSocket orchestration; HTTP provides reads | No separate duplicate mutation path found. Project-owned cleanup is the exception above. | +| HTTP thread reads | Bounded shell/detail/history access | Dedicated V2 query services and windowed snapshots | Retained for healthy HTTP; F16 is the socket fallback. | +| Reconnect and snapshot fallback | Large history must not become one unbounded recovery frame | Full projection used after HTTP failure or invalid/large reconnect range | F16. Per-item truncation and live event budgets do not bound row count. | +| Live tool update coalescing | Merge repeated active tool updates without dropping terminal state | Stable-ID coalescing, ordered boundary flushes, bounded live/unacknowledged buffers | V01 implementation concern addressed; focused tests pass. | +| Unused stream lifetime | New main releases live subscription at last consumer | Five-minute live/detail retention remains | M01. Shared by web, desktop and mobile. | +| Protocol negotiation and HTTP CORS | Compatible peers negotiate version; protocol header permitted | Explicit protocol V2 gate and CORS allowlist retained | D05, matching deployment required. | +| RPC authorization | Every exposed method maps to a scope | New V2/project/assets/scheduler methods have explicit mappings | Inspected and focused tests pass; no authorization bypass found. | +| Pairing, credential refresh and remote identity | Pairing secrets excluded from read models; refresh does not disconnect | Shared implementations match main; V2 routing retains environment identity | Retained in source, not exercised against a live relay. | +| Long delegated-task IDs | Encoded IDs must reach environment/relay routes | Both routers permit 512-character parameters; relay worker wires config | Retained. | +| Relay push limits and decoding | Bound stalled pushes and avoid redundant parsing | Relevant shared relay files match main | Retained; local awareness overlay reviewed separately. | +| Server-update continuation | Main continues active work across server restart | Capability explicitly withheld; recovery terminalizes active work | D01, acknowledged deferral. | + +## Provider and registration parity + +The production built-in registry includes Codex, Claude, Cursor, Grok, OpenCode, Antigravity, and ACP Registry. An older helper's shorter list is not the production registration path. The managed-driver initialization, settings hydration, catalog discovery, and auth paths were reviewed separately from per-turn adapters. See [providers.md](providers.md) for precise capability limits and line evidence. + +| Provider | Retained or explicit V2 behavior | Actual gaps / decisions | +| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| Codex | Pending/unavailable state until health check; auth/discovery; native resume/fork/from-turn/rollback; tool approvals; structured and async questions; native compaction; per-turn usage | No new committed parity defect found in reviewed scope. Local `turn/diff/updated` opt-out is not committed and has focused coverage. | +| Claude | Registry/auth; resume/fork/from-turn/rollback; approvals/questions; slash-command attachment ordering; native compaction; usage | F11 Read-image presentation; F20 dead-turn result classification. SDK 0.3.260 is present, but its terminal-reason handling was not fully ported. | +| Cursor | Accepted SDK implementation; auth/model/skills discovery; resume; mode mapping; interrupt-restart | D03: fork/rollback/approval/question capabilities are explicitly unsupported. F08: background metadata uses unrestricted agent mode in real cwd. | +| OpenCode | Local/external server configuration; access policy; workspace skills through SDK; resume/fork/from-turn/rollback; native compaction; root stop timeout | F06 descendant Stop failures; F07 external teardown; F18 clean SSE EOF; F19 reply hangs; F21 token accumulation. | +| Grok | Registered ACP specialization; auth/catalog; session loading; permission and question extensions; interrupt/teardown | Unsupported native fork/rollback/usage are explicit protocol limitations. No new concrete regression established. | +| Antigravity | Registered official ACP agent; managed health/profile auth; negotiated capability/catalog updates; subagent translation; constrained metadata helper | No new concrete server parity defect established. Capability limits follow the runtime; no real sign-in/provider session was launched. | +| ACP Registry | Instance-specific command/auth discovery; negotiated loading/fork/model/MCP capabilities; permissions/questions; interrupt/teardown | Native rollback and text generation are explicitly unsupported; live request IDs cannot be resumed after process loss. | + +| Cross-provider feature | Current V2 path | Assessment | +| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| Provider availability | Codex driver uses `makePendingCodexProvider`, with unchecked `installed: false` | Dropped-patch lead rejected; behavior was absorbed. | +| Cwd-specific catalogs | Web and mobile request selected-workspace catalogs; Claude also scans for execution | Prior broad V02 concern closed. No narrower CLI-only failure proved. | +| Bundled current-model classification | Initial main manifest is retained; remote refresh can update it independently | M12: latest main adds `gpt-6-astra`; offline fallback still labels it legacy. | +| Native compaction | Launch guards recognize native commands; run execution calls adapter `compactThread`; unsupported providers reject explicitly | Retained; focused launch/execution and adapter tests pass. | +| Logout / session teardown | Auth service passes V2 session stop to controller; native logout command is guarded during launch | Shared path retained. OpenCode external cleanup still has F07. | +| Automatic title generation | Shared prompts/dispatch and stale-request cleanup | F12 lacks main's bounded initial retry. Cursor boundary F08 is independent. | +| Usage dashboard/pricing/limits | Shared readers, pricing, proxy-account deduplication, limits and reset-credit APIs are retained | Inspected shared source and focused usage tests pass. F21 concerns per-turn OpenCode telemetry, not demonstrated dashboard loss. | +| Provider text/event logging | V2 protocol-event log infrastructure replaces older orchestration logging | Bounded logging work retained; dirty event logger work reviewed separately. No production-volume benchmark run. | + +## Checkpoints, workspaces, and background work + +| Feature | V2 behavior | Assessment | +| ---------------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| Full diff from thread start | Query requires a run-1-owned root scope, but real allocator reassigns shared scope on every run | F03. Existing happy-path fixture creates impossible separate root scopes. | +| Checkpoint read cardinality | Three narrow context queries; shared summary store avoids full patches | F14 fixed; no history hydration needed for diff metadata. | +| Rollback | Typed checkpoint restore with state checks | Focused rollback tests pass; not a live Git/provider restoration exercise. | +| Fork/from-turn and lineage | Provider capability drives native fork; otherwise bounded context handoff | Intentional V2 model. Provider capabilities and inherited ownership are explicit. | +| Portable context transfer | Per-item truncation and separate legacy import budget | D06, accepted fidelity limit. | +| Worktree cleanup and Git patch rendering | Shared Git implementation and recent main cleanup/prefix handling remain | No new concrete omission found in inspected shared paths. | +| Automatic project pull | Opt-in project policy reaches VCS broadcaster and startup auto-pull | Retained; not a missing provider launch hook. HTTP can fail to update the setting through F05. | +| Automatic pull reset UI | On/off switch remains functional; standard reset button is missing | M15, late-main affordance only. | +| PR state after a turn | Execution refreshes cached PR lookup; checkpoint finalization refreshes branch PR state | Main's newly-opened/changed PR discovery path remains wired. | +| Auto-settlement | Closed PRs settle independently; merged and age options are respected; local work narrows candidates | F13's stale-failure/snooze ordering persists. Do not skip closed-PR handling when both optional settings are off. | +| Snooze completion wake | Completion requires evidence newer than snooze | Retained; failure ordering is the exception F13. | +| Durable schedules | Branch-only schedule persistence, due-run computation, missed-run and crash recovery | Focused scheduling tests pass. F22 full polling scan; D08 archived-target policy. | +| Active awareness | V2 run/request/metadata state feeds relay activity | Committed behavior retained; local coalescing/config-cache/retry changes separately inspected and tested. | + +## Client surfaces and entry points + +Desktop uses the web UI, so a web fix normally needs the same renderer there plus any native IPC boundary. Mobile has its own React Native call sites and cannot be inferred from web parity. + +| Feature | Web / desktop | Mobile | Assessment | +| ---------------------------------------- | ------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| Sidebar shell hydration | Stable empty provider entries and grouped shell identities | Native shell/list path | F02 fixed; recent thread-list identity work retained. | +| Working-row prominence | Unread/wake state keeps background-working rows prominent | Separate native list | M14, late-main visual policy. | +| Queued work | Reorder, steer, cancel, thumbnails and queued composer editor | Reorder, steer and cancel; pending new-task outbox has a separate editor | F09 drops generic files in web queue edits; D07 compact mobile queue is explicit. | +| Message attachments | Generic files and images render | Image-only filter prevents file/PDF/video renderer reachability | F10. Server projection and asset transport retain the attachment. | +| Offscreen attachment URLs | All loaded user attachments resolve at chat scope, ahead of virtualization | Separate native attachment path | M11, late main moves history image lookup into mounted rows. | +| Assistant citations, media and templates | Specialized Markdown path remains | Active V2 rows now use specialized renderer, scoped media and template callback | F17 fixed. Integrated interactions were not run. | +| Claude Read image preview | Generic dynamic-tool conversion omits derived preview path | Same missing projection into presentation | F11, both clients need a decision/implementation. | +| Inherited Markdown references | Normal messages/plans use active fork; inspector uses source | Active screen thread/workspace owns callbacks | D02, source-history versus active-fork semantics. | +| Streaming rows/Markdown | V2 provenance-aware row reuse and stable Markdown rendering retained | Feed row reuse retained | Source equivalents inspected; no frame-rate benchmark. | +| Terminal rendering | Existing incremental output and hidden-panel machinery retained | Native terminal flow | M04 history byte bound missing; M05 repeated row metadata scans; no visual terminal pass. | +| Diff review | Web diff/tree/settings features remain | Parsed section cache and all-section prewarming are unbounded | M06, mobile memory priority. | +| File highlighter startup | Separate web file renderer | First file-preview route can initialize highlighting even for an image/video; later starts are deduplicated | M09, late main defers initialization to the already-lazy source consumer. | +| Settled work folding | Prior trailing-group safety retained; single late success remains detached | Separate native grouping | M08, presentation-only; compaction/failed/interrupted groups have separate safeguards. | +| Proactive diff panels | Any completed-run checkpoint summary can open diff, without checking active PR or nonempty ready state | Separate native flow | M13, late-main guard missing in V2's run-summary caller. | +| Project settings entry points | Sidebar and contextual command palette work; new-thread header shortcut absent | Separate project/settings flow | M07, missing one entry point, not the whole feature. | +| PR author identity | Name/avatar render; new profile link absent | Separate native presentation | M03. | +| Update notices | Existing status component with older narrow-layout rules | Separate mobile flow | M02 polish; D01 is the distinct continuation capability gap. | +| Browser profiles/import/SSH/preview IPC | Shared native handlers, preload and contracts present | Not applicable to desktop IPC | No production Electron behavior divergence found beyond a type annotation. No packaged app launched. | +| Connection modes | Explicit environment identity across hosted web, local web, desktop and relay | Shared client-runtime connection core | No new remote-only defect found in inspected identity/auth paths; real remote validation remains V03. | + +## Local work and coverage limits + +Local changes were not attributed to committed HEAD. The dirty overlay includes narrower settlement and visit reads plus migration 059 indexes, cheaper local Git status, visibility-leased palette PR/VCS data, stable desktop topology identity, Codex notification opt-out, logger bounds, awareness coalescing and retries, and the Expo notification synchronization patch. Focused local tests passed; no new concrete regression was found in the inspected changes. F01/F03-F13/F16 and the new findings remain as documented. + +Other work continued during the audit. Later awareness source/tests, projection-settlement tests, and three internal docs are captured separately in `worktree-drift`. The awareness changes were re-read; they retain bounded retries and stop retrying on disabled/unlinked configuration. Hashes and paths identify what was reviewed and tested without overwriting anyone else's work. + +All seven production providers, the V1-to-V2 registration boundary, WebSocket/HTTP/live-CLI/offline-CLI project lifecycle, web/desktop/mobile client callers, and local/remote protocol boundaries were included in source review. The initial eight unmerged main commits and seven late arrivals were inspected individually. The initial 240-commit incoming inventory and 991-file tree comparison guided the review; the closing incoming inventory has 247 commits, with final file counts recorded in `closing-references.json`. Equality or a matching patch was not treated as sufficient proof of feature parity after a caller moved. The client report additionally traces six recent ports through actual V2 callers: file-backed image readiness, hidden terminal visibility, static chat status, failed preview-capture cleanup, Antigravity unknown-auth behavior, and sidebar multi-select unpin. All six are retained. + +No live provider, browser, simulator, packaged desktop app, full release build, or repository-wide test suite ran. Windows/Linux native execution, full historical migration stopping points, actual provider stream recovery, end-to-end relay expiry, and workload-level CPU/heap/frame measurements remain outside this audit's proof. Marketing-only/shared unchanged files received inventory review rather than a separate UI audit. diff --git a/audits/orchestrator-v2/2026-09-04/branch-commits.txt b/audits/orchestrator-v2/2026-09-04/branch-commits.txt new file mode 100644 index 000000000000..7bdbbea2e6da --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/branch-commits.txt @@ -0,0 +1,333 @@ +8af5734365f7c45bc08b57066dbae42f9f7d4235 fix: reconcile main updates with orchestration v2 +d98f1d5e38fb7dac334193d1cd7e103997b486e8 fix(server): reduce v2 recovery and runtime resource usage +96aff3564b3c2a9a543fed654388d2741fb6de9f fix: reconcile main's round-20 features after the rebase +4f924bfd310d5d673f038ed9ce3be3fe50fba959 fix(web): realign the composer and timeline with main +4199e9db5169f6a88a04457a1bd6224deaf2853e fix(web): right-align the stash shoulder tab again +dc4cd901af59e732c06ff60bfea9d8c730f2146e fix: reconcile main's round-19 features after the rebase +702ef5e5851264ea231c9cb4ecfd0b5f9c016042 feat(server): evaluate automatic thread settlement in the v2 orchestrator +ddf58d90d47e2b6aaefc61bc15e6c3028b61c3e0 fix: reconcile main's round-18 features after the rebase +38f3e4d0e02cd58f79fa7ebe37250ee93c973f60 feat(web): port working and thinking timeline rows to orchestration v2 +27ef79dc301dc4400e3fafe834d514fa3b8de942 fix: reconcile main's round-17 features after the rebase +42dee149f7861f9d84650c04e047f5fd48b3466b fix(mobile): keep scroll bounds current after animations +8b2f951e68a7f5effa16201263e4b47cbf517ad0 fix(chat): remove added tool summary status counts +6bc5b0f798228f387e9e42cabe51ae3d99a1cfa1 feat(mobile): port chat summaries and transitions to orchestration v2 +cafacd53b80eb399df5ad0cac37d9f6777d46e80 feat(web): summarize T3 orchestration actions +5145881d4c23094f7ca14deea1ee0cc8c2603219 fix(web): keep composer shortcut tooltip stable on Mod +f8ed1f080ddec3c13eed613927178b0614cbf696 fix(web): match composer actions to draft and modifier state +5d5f370ad678f933e66b215eaef856656a464b9f fix(web): keep queued messages in place while editing +1a56fa6768fdd7ef063e291bcfc8900f07926995 fix(web): keep queued message editing inside the queue panel +b952c574d5350c880f1f2f805d39839baeae3845 refactor(web): use shared banner rows for queued messages +1a600882893faf73f596d57ddba72a5b239482b2 fix(web): keep stash separate from the composer activity column +f21af84a704c3435c461a199468f7ce56232741f fix(web): share the outline for joined composer tabs +61e3568dac81141fa3d5e7c90a78eb4cb485207c fix(web): align queue headers and prevent stash overlap +7efa4e84b1a52583fcc3249293e92e94d0fadab4 fix(web): port composer activity and grouping to orchestration v2 +93620dfab0f877d204b97c5b5c3d9ea5352f080e fix(orchestration): select visible history before limiting SQL +f45dde3c8615033422102a0202ba17dc04e3a858 fix(server): recover OpenCode status reconciliation +42bafcb317e48299ccfb82a8b07882447cbc740c fix(orchestration): retain nested fork history when paging +1fc6d2c90585d74f1e5e3b53363e5c2a2c9b37e9 fix(server): cancel pending OpenCode prompts safely +14322467cf335509915dfdcb5167a6d97341703b fix(orchestration): page history through its true end +8d2c45c539916b048cf794ad0752c7876946bbae fix(web): retain markdown workspace ownership +d4debe5ae8d9465528dfbb75e77be01f8e306837 fix(clients): anchor feedback in conversation order +a8370c67278c8031d78a214c312e1191495e39b4 fix(server): correlate OpenCode prompt admission +3d2d5711be63952a5ada478638d10ce6d7802ecf fix(server): normalize Claude question answers +a4891183060e0c4c125e842d0ed6004ec33431da fix(server): preserve Claude planning lifecycle +4c25c80607d0a76ff68fcf9a5bedd050fdbec71b fix(server): preserve provider usage in persisted turns +03d8aef938d607bf4d03d7910eadc2054398c831 fix(server): allow protocol negotiation in CORS +48dab8cd209d056b95f31105281d2b550be87b7f fix(server): restore Claude resume compaction +ac7e04ae29e7351c1a36f92a446ea3e9aba7d3ea perf(orchestration): bound complete thread snapshots +d16e890b16d5dc5acedfbe4a334d40fe0c8c0426 perf(orchestration): bound history reads in SQL +9991452ad2f5318a95ffa9d41992fe421b97dd0b fix(server): project Claude plans and todos +537861cf9a92f7fe4efe01786ef8409422aa29e5 fix(server): restore Claude structured questions +0439f0f162af8ae9753349686437fe269d667158 fix(server): guard OpenCode prompt admission races +2e88e58640ca167a411196318fa773b47fc86519 chore(repo): remove tracked audit scratch files +d9e87450162db54237c995151a2a371169060ce5 docs: state portable handoff limits +adc3d1acaa308bd0e18adfefbed2e74237d1a60f docs: explain legacy thread migration +8853fd4386d5079c54ad5f6f9a96ee682377d327 fix(protocol): reject incompatible orchestration peers +875b9d88568a12af71283bb4c95221b3c50e98bb fix(web): scope markdown actions to their environment +a4cee6104d5f088c886a202f5dec8fb70df99489 fix(web): restore markdown file chip actions +980df245b1955831d3869b1ec83be2aa2c055861 fix(server): keep current provider context usage +fa61cae19d4d6c946207a2abb904dedde00a7c1c fix(web): preserve Windows markdown paths +dfaf815157fbc94e858ea771c3f64d20db2c34e3 fix(web): load workspace markdown images through assets +1322c48d5d22686a413a898f1af9276514c469cf fix(server): preserve generic provider attachments +54c0c030ef4876979122944db0689a67f7e6175a fix(clients): restore Codex feedback submission +1acca70823ec6bca52b56d87a8af5a748416e811 fix(orchestration): recreate missing worktrees before turns +202da64207f35cdccfdba6bd63d94d19ce3c004d fix(orchestration): honor migrated thread visibility in search +d72da77e7737b2b6b0c6067492a8bc00551669e5 fix(server): preserve Claude subagent models +8f0ada76d8f6875e074990170d229f7cc157d62c fix(web): honor disabled legacy plan mode +4fdafec1d5699d67326b25f66f7dc8a59cf5819a fix(orchestration): preserve legacy thread metadata +635f552718bbb34c39a8bc7b89d6f01eed22203b fix(server): include service launcher in bundle build +7933dd671dcf72bf1aadc2b207f32178b3a480bf fix(server): observe pre-aborted Claude approvals +b28c4a4c1257f7a7957ce028270c2283fa4426db fix(orchestration): reanchor unsettled threads +608793e39e16db8ef01fc906210143c1ca741ecb fix(server): keep Claude session approvals ephemeral +b14ca6bf3aea8d77518e2ee8982864c03c8799f7 fix(web): keep failed tool items in the collapsed group summaries +12bf10144bec533bb5aab073a223c4d342bc103b fix: reconcile main's round-16 features after the rebase +2fe6d79c49bda1f9e8e9ff8b289f6f5df5f19292 chore: refresh macroscope ui-consistency check +2a94e7b2d286576174cdbe7a60a861bb54960608 chore: retrigger ci +edbe21f803a7a61ab1c0e16048a12febb1cfc6b2 fix(server): inject HostProcessPlatform into the Grok plan extractor +e89268b409baf86103e38f3c2ab5299facfead86 fix(lint): allowlist the queue and relationships interop boundaries +e7d813ad06c639bda0f8f430176f433ebef4607c fix(mobile): replace remaining dark: utilities with adaptive semantic tokens +731e44ac8627a73f05fcd50c8b71dd9c48d9a95c fix(web): dedupe the composer glass styles and align the chat column width +03c974d7dd927c94ac132fd6fd58dd75d190367e fix: reconcile main's round-14 features after the rebase +399df7a43976776b350c7bbb4e0a4d62d6552cb8 fix(web): drag-to-reorder queued messages and retire stale pending rows +dbe86d12fd1767fb84b4e33c33b4453329d9713c feat(web): show attachments on queued messages and edit them in the composer +e3d09455f4f177cd2a51c263d18e95f2fa41d55f feat(server): claim uploaded attachments at v2 dispatch +2dbca2799fc0515913916e2cb026a02ce1947684 fix(web): restore the full-screen file-drop target over the chat column +bbde25092291d843bb5777f482a869aeb197dc3b fix: restore main's automatic thread settling after the revert +7b35f0756fbec4fe4016e3a2a71594a69642030d fix: reconcile main's round-12 features after the rebase +344d661accea0e076b388d40711e04313b640050 fix(opencode): route child-session approvals through the v2 adapter +a2c1f7fde395ceb7246a53def1466ad0f93deedb fix: reconcile main's round-11 features after the rebase +698db66a384504caf9c140b9fba337cac2a541c8 fix(web): collapsed tool rows preview inputs for every tool type +d209d13ff9701c8938d147f98b313a3a044e7f56 fix(web): show the command on collapsed tool rows, not its stdout +6bc36d5fdef70f482dd0a292e0433459558e585c fix(web): surface v2 todo-list plans as task progress +15ac91d2ee36371be6e2cc259ca4012a26460924 fix(web): collapse settled tool runs behind main's summary toggles +7e9527c2a7e7c09ef8e09b97bb4a9608d11c3ab4 fix(web): converge ChatComposer on main's drawer-era body +2c7ab194c49cb00d0b90228a1dea70df5448f98d fix(web): adopt main's attached-composer surface contract so the glass survives shoulder tabs +c6ac7fae2f6e34030ae1d6cbd7a70d5eab9d33d5 fix(web): repaint the composer glass and strip the thread-panel popover chrome +718ff37efae80d2a84e341b72983e3836e9e9a69 feat(grok): capture exit_plan_mode into the v2 proposed-plan card (#8358) +d7f68523648f1ab52d4a9bda171b1461d87c548e fix(web): keep following the stream after returning to the live edge (#6519) +8c559a0fe9dc4d417d0270c22e7c9198433db1d8 feat(orchestration-v2): show live context usage in the meter (#8144) +197d245344fa63c46cd8525875a06ce582321bfc fix(grok): fail hung prompts on xAI rate-limit completions (#8358, partial) +d4735799dd360d56ec9585a6a8e9ab5803898917 feat(analytics): credit v2 threads and turns to the starting client (#7774) +96a5bf0bde62d3804c12d571a6a573a7085556b8 feat(orchestration-v2): route Codex thread feedback uploads through v2 (#7949) +4650a6971b4cab6808fbec7a919b3b0dd49188b4 feat(orchestration-v2): carry approval options and app names to the client (#8058) +f2b786b92ec0df5c53d144849f8fb241e1ca4733 feat(orchestration-v2): project linked pull requests on threads (#8160) +2c3c47d1dd35812edea0a842d9e7fb894a4acc63 fix(web): stop mis-marking recovered and text-reported tool failures in the v2 work log +06a2b41a06c648433c0bacd8c5e8be2d18ab3fbb fix: reconcile main's round-10 features after the rebase +6d31e48c7d22d57026c2d4913c233d5165bfd633 fix(orchestration): show provider retries in the work log +3bbb50c08e8e12dd03b1a8fda2d4f6d9bde30b63 refactor(web): finish aligning the branch with main's style simplification +bd70826128670a103dc832264b874e42e55823eb fix(web): restore the titlebar sizing and timeline fade lost to main's style simplification +0e4c8cf65be39cd4c03829a5480047fdde620072 feat(server): honor withheld agent browser access in the v2 runtime +40b35dbb9f2b9f6aec8049c3c9abcd493993bd89 fix: reconcile main's round-9 features after the rebase +1c3f3ff94a8d148b9d3e9de190d509794935305c feat(mobile): surface prominent activity status and metadata +358fa7b42d1cc1f25b840292b7aecd2c1a132255 fix(server): reject replaying a command receipt across threads in v2 +95ea8072fa8d8ba1037b5e147ecd31976d3ffa52 fix: reconcile main's round-8 features after the rebase +eeb374557dc3c06894fcaa676b295dfaf5ce5080 perf(server): keep shell snapshots bounded and active-only +66051a7d8549a1200d8f3eef4d77d4eb1918d7c5 fix(web): size the titlebar layout-control icons like the sidebar trigger +8e026d246427ef6a25c5efe4f4501c747afcf29f fix(web): align titlebar clusters to one shared pixel inset +ecbf6849d78edee17458ef834dc33d9366873457 fix(web): keep the titlebar layout controls fixed across right-panel toggles +0c2def0526e53deacdc5a981efe7ac9eda6b0290 fix: reconcile main's round-6 features after the rebase +35e8172373ef618965fa3c601d56c29fc4dc5586 feat(contracts): track thread title regeneration +54912ca1722280d2ab1c5a4e98cb1d4841ed43ab feat(orchestration): bound thread history and resume payloads +4569224ce1d2fdd96e36436d374bee88e3bd5422 fix(web): restore main's collapse chrome and tab-status keying on the PR panel +8c976ef74d2ab13998c2e8672669aafe6b313928 feat(web): prioritize pull request row actions +647dcb34c3a4784c8161e78c7e95b56dbcec137b fix(web): reconcile main's round-5 features after the rebase +cf8159205d6e018f3d7125b2a58bb1e185d25ae9 fix(mobile): port main's composer stabilization into the v2 thread screens +b23bae2e07ce3c31e5e919528279e1c7ce5c6024 feat(web): add pull request actions to thread details +c6429f0ec600ded05245e1c312d6e47910b3b31b fix(web): restore the branch's slim chat header +c95f718a92a2584980a0a6ed51b59a34690e54cd test(server): expect attachment saved-at lines in ClaudeAdapterV2 turn text +17abb7b57ae29a8a206fd0db3c2802e8c78dd1d4 test(web): restore main's right-panel migration expectations after the panel-visibility merge +b10a1a4a613ab4529aa916d705fdde6422e4b625 fix(server): port round-3 main fixes into the v2 orchestrator +976fa4da28739720063f879cfb6176829924b326 chore(server): renumber v2 migrations 038-046 to 041-049 after main's 038-040 +7b7a3c68f5eca0d6bcb6f4f21b88bb7c78b87c25 fix: repair rerere-damaged files and reconcile main's round-3 features with v2 +f568e4df2cec22e56415ea6c32c268fd7eec6599 fix(web): show Git action success inline in panel +cd782e9cdce402854a1e1d65c74a4e96dab8115c fix(web): let LegendList own end-follow and disclosure anchoring (#5449) +1b95828aec9fa44f490b293038fdb10d5d4a3ffe fix(web): port the refined live-follow gesture gating to the v2 timeline +be208f5073b0b48894bbf54d20e08c4a96fef654 chore(web): prune plan-sidebar leftovers after the inline-plans rework +103f1e6cd2281cf475d25db3cc81cf114e2fa9b0 fix: port main fixes stranded by the v2 rewrite (round 2) +7222e6bdf716ef72fa1baa8a87a9c982bce12ffe fix(server): renumber v2 migrations after main's 037_ProjectionTurnsKeysetIndex +acbb25bc1758a19f205404fc3967485ec6f85af0 fix: repair conflict-marker artifacts from rebase auto-resolutions +3f8506737ca05b4ea1c9841477c9cd243b5c41e0 fix(web): align git action progress button layout +a657cb37357f6df029275fd104b6aaaff27faf95 feat(orchestrator): Surface waiting background work (#4378) +690257b3cd2626f8faa318bf915de8f4a9bc81df test(server): align migration expectations with renumbered ids +8ba222e52010b4bb6be4e32937c92d3d5a961b9b fix: port main fixes stranded by the v2 rewrite +e609aabd27d6e7d3b59bf18d4a0688003281af70 fix(server): renumber v2 migrations after main's 036_ProjectionThreadsPinned +ec1fd6195a5c8fb7d2c8962c83a147d6ec38974f fix(web): remove open PR actions from git controls +00efd07bd4277f4e589e20a6666f37864b964bd4 fix(server): stop tying codex text-generation temp files to the caller's scope (#5406) +cf0835134461535d82d94beb583bb409a9829ff4 fix(orchestrator): Prevent redundant delegated completion turns (#5311) +648d1f42b862b222b9cbacacc075e69ea6d6a283 fix(test): keep codex replay recovery off the repo checkout +1691887191e0a382f93fea30d65fb55df462e6bd chore: resolve lint warnings across v2 code +69d932b37a291825aad7136b3f89f95551fac18a test(server): cover v2 thread title regeneration +413885f1d3ca859a7da348ec08b89260adc2c53a fix(web): restore compact header sizing for project script controls +ea285714f2e848643c5734c52a1cab4ea3b0ae49 fix: send mcp-protocol-version header in worktree registration test +0d5f04f604193d5248c52da181b540a1e60c78fe fix: adopt effect beta.103 APIs in rebased v2 code +51d7089afc6f1860cc5cbc0742c466528a52e05e feat(chat): refine V2 conversation UI (#5307) +7c9c6dcb7f12659ea09b7199f9ae9aaf4df4b644 fix(server): restore worktree branch naming in the v2 orchestrator (#5309) +4fad4c56afcd0ddd3f2fb30ab08bbb7f78e77206 fix(orchestrator): Order thread lineage by creation time (#5310) +daa272bac55305833675cbb83c57afdfdd6fe192 fix(orchestration-v2): restore generated thread titles (#5176) +f44c22a14a8380c385079a2f1effb742159a64dd fix: reconcile rebase with latest main +b8a1f761729fe117afc0e7e69cc722ae434373a8 fix(web): keep Git progress title anchored +3df8422d5694c56a7fbe81d77199e77e69e17857 fix(web): remove elevated thread details panel styling +1c378332b103b258af1a655ae025f8517b591193 refactor(orchestration): split thread-not-sendable into typed errors +a78cc2c52384e0f9153ee83468544234ddf3da81 fix(orchestration): promoted queued messages keep the queued_turn intent +8c7e1c13fa2c289ededc69a393c161251f675b06 fix(orchestration): thread visits no longer create activity loops (#5038) +5d0644e2af933d494c969cc22592aec59d14220c feat(orchestration): port thread title regeneration to the v2 runtime +1fc6545515ef29d6c9698f4ece7547f8baaa9fa8 perf(web): keep timeline minimap animations off the main thread +673e0f49e7eef76545b9bc3a7ccc8ad46566ff15 fix(relay): stop replaying the whole event store into the awareness relay +16620e9fe4b656303cdd646dd6d5daaca741afb5 fix(chat): prevent stale timeline scroll and rerenders +b5d353cc8a3f0f1253629ec3a5fd9ad01e6d0d13 perf(orchestration): per-thread shell deltas, visit throttling, event compaction (#4971) +bedec74e8575b7e50641a03b0985bf74ffd44259 [codex] feat(web): show git progress in the commit button (#4963) +27806ef4d8513393503556108f973ee2bb3de94f feat(orchestration): track provider retries and thread visits +a12849d59167dde40a7028813ef839c39161a095 feat(server): surface legacy thread migration progress +5c24e3506aee88519926bc490b04d9c122b5ef68 fix: close failed provider adapter scopes +d4990c75c3a674ef39ad54877eae6549decdf872 fix: preserve thread management failure semantics +dbc5127f330b114e4668a0b1b82c553b95bdb608 fix: address latest orchestration review findings +1e65d374c192348690365a7cd1c669a0d3c44e95 fix: preserve orchestration task identity +88a1900091bb28b2596386bb88962d9b6c226598 fix: address orchestration review findings +3e72c6a17b22dff3843ad5123cf3ee626d37491b fix(mobile): label queued message intent +01c127f54ede66e2b9e6393a0ffe3a612f048861 fix: address orchestration review findings +10c462fbd20b1c0147a76c6505b8301f871168a7 fix(orchestrator): preserve migrated and nested history +014e9a2621e861a688fe81f279d7b16c42c3865d fix(server): preserve project mutation client errors +6fcbf009d4268d240c8264aeac37108cdf5905ec fix(orchestrator): validate rollback and search links +2e813f8c4bd22ce905cfceee7a02d7ec5095468b fix(orchestrator): close cancellation edge cases +697fff8d50d5518e0c9febb7575e4dbf3e0150bf fix(orchestrator): decode direct Claude result blocks +9a404d4672f5c3b7272642804d0969e21dd88fec fix(orchestrator): validate replay edge cases +ddb3c272115d65e4ac7879667684f4d00752f20c fix(orchestrator): preserve terminal effect outcomes +83cf7d6dfa67d36172423d9263061c4e04c37e56 fix(orchestrator): preserve retryable effect failures +f081c2c84c465fb04ba2f0106ff02928b82a0920 fix(orchestrator): avoid replaying settled effects +c2a48e3c8e9979afb34953cf31ebdb82fa6d5674 fix(worktrees): make handoff rollback atomic +dd2b88149757c41c79c14c889ee30e07628d7cb2 fix(orchestrator): release stranded effect claims +d6eb526629a8dbcd0ac096e8d596d0711278e85a fix(orchestrator): execute resolved runtime responses +b65d8ca4cf639b8197c13f3a507287694896d1c7 fix(orchestrator): harden provider edge cases +739c3ff962d3f70eada4f1fddaabc738462fe816 fix(orchestrator): handle fresh review edge cases +088c56b41f31d61bd5d8be115b4fc2b90ee3ee1b fix(orchestrator): address late review findings +91e3a339592acdd321301eb2abaa02787466eded fix(mobile): gate thread controls on live runs +67f85a5c781131e8e1db51d11087e16cea279768 fix(checkpoints): retain thread-start baseline after failed runs +b605ddde083344d75718d9f8511a6dba7e2ffc99 fix(client): preserve live thread relationships +0954b3bb5977fac6a3d6bb2b30a0d85ae05405ea fix(web): enforce secure provider field defaults +2ca3166d40908502b575f7e3e36a4aaae3e47348 fix(claude): preserve explicit model options +4cf4ed7202f7220608ec77dd1dbb630afa63e014 fix(server): isolate deterministic attachment ids +bd653b476bfcf0d0db332d9e06cc2d805b96b331 fix(testkit): harden provider replay recording +6ab76be22432d266dc0b2574659be43dfc5cb1b1 fix(acp): enforce task and permission invariants +c2b51fc09027b688a01094515c15e2f62bce3a34 fix(orchestration): preserve imported conversation state +d0fca84e65107f02c81ecf97a6f91e97ebe579ab fix(checkpoints): preserve valid run history +ff5e6f1b32dc7904b75c32e5b3fda6d1cddd7646 fix(acp): discover final teardown descendants +4fd8f62bc947245442785fa75fa720f7d2cc082d fix(cursor): log close attempts before execution +14d68b3c2adf008872fb8a4cd7ee1c71d393274a fix(mobile): distinguish queued and waiting archive states +3087d27841d78909de6134b6919f6eedc1fb5a06 fix(mobile): allow archiving post-provider work +9761382b9dfa80e6e4ed66a391f6906c79fc88b6 fix(orchestration): cancel queued work on archive +49654af76e5c04f7bf62b51f0a65b9f7253a2967 fix(orchestration): handle checkpoint-wait runs +cedc11513d4a262786fffdb1415c5c947c78cb35 fix(acp): make xai cancellation reliable +385f1537b784a1abd337eb30ec427a8fb41ec878 fix(contracts): reject invalid legacy intervals +657ee69e5ff0fac40c23f59ebdd26a59f2ef099d fix(orchestration): preserve legacy schedule compatibility +384873780e83648f68a0c24a4b426d869ce8b51e fix(mobile): preserve active thread state +73fb62aeed30b7977bb552ed2bcefa1dac77e330 fix(orchestration): harden scheduled task startup +81619adf57bf4a8e964b33b22cc7eb4950c18524 fix(orchestrator): schedule effects from durable deadlines (#4656) +e684489f7d8aae43e7c8e7aa339e68b56ec4f984 feat: migrate v1 state into orchestrator v2 (#4400) +4569c531d594c3018bbcbbe4fadbfc74ee2500f5 chore(orchestrator): refresh checks after main sync +933d9c0421749fe4d1205f2c5477e01f6c3a7f18 fix(web): restore checked-in project scripts +bc1a9c7d76baba0d25ce08cc91a89b7c7124ed5b fix: ignore subagents when sorting sidebar projects +dda77e7bb49fccd5cf211565ea88c6396af04c48 fix: hide subagent threads from v2 lists +f0b7a4ed427259519850bd4933ca01ab1178e8a7 fix(claude): Settle positive task-notification results +f4553701dbb3d453687129ff1c50ae0aea042376 fix(orchestrator): Wake settled parents when delegated children finish +af0f7759971f9163adefbcd5f21029b6a6d1cb36 fix(acp): Preserve wake evidence across an app-owned wake +e05564e15a5bd00e03b3414226eb5bffa26ceb20 fix(grok): Prevent spurious wake run after in-turn monitors +0bcafedc7ca250d3bcb5bf407a0d182a2617d4b4 test(orchestrator): align merged V2 compatibility checks +8fb4634569577ac40cad07b4103f903dd8646b22 fix(server): clean up Claude replay failures +961a655902ecda13d01a23bb0ef1f79a920ef6fe fix(server): enforce ACP auth and preserve fork provenance +55cb69380550972f8e44a92936be163e0e1ac7bf fix(server): keep derived threads awake +64a9daf87cd8260f66d0d5d3e5ccb44e786ece1b fix(mobile): wait for fork shell before navigation +d52c1e6e6d5638215f55c11fe357872037388b8b Add worktree handoff and status tools to the t3-code MCP server (#3754) +780302519d3e38170a9b8f926bac13272b5a8368 feat(subagents): disclose projected results consistently (#3866) +dff34c177aa4312146726f7d3e8300db39e15da9 fix(orchestrator): hydrate shell cache and group multi-environment projects (#3640) +c75cec919c37c526a572c153cabcf8cba75c6ce3 test(orchestrator): align Codex approval reviewer replays (#4457) +3e6d9c12dd69e3210fd3976d1d0504ef7dd5681e fix(orchestrator): Preserve claude/codex post-interrupt recovery state (#4229) +df52327334430eec54aaaefb93ae4b41a9861147 test(orchestrator): Align post-merge CTM fixtures (#4193) +b51d858ac04ab281df13bcd7ec1d3acd14d02aae fix(web): contain thread details panel effects +3fa4661dd66fa3e59e65ba9c20431987986e9ec1 refactor(web): use shared glass surfaces +80a9b6628b86d0b6dc6cc4ed6a1bd9683159f489 fix(web): remove stacked composer shadows +f18cbfb6841f29ac13e1c540bf486b89c3a3c4f0 fix(web): restore v2 composer chrome +cd095953df759b49c9b19d045853058ca82421ed fix(server): preserve released migration ordering +bcf43a8f0185e7ac94fbbffcb14c6dda13d079ad fix(orchestration): clarify agent delegation and scheduling +917fad6c322bc2c8a75c023e193067b96ab0813b Unify T3 MCP tool presentation across clients +1093a70b448df21a18b408e0fff2eb79963a98ea Render T3 MCP tools with branded timeline labels +2fd782d05bc061773d39515dc8daebb0986f3dd8 fix(grok): align ACP extensions with open source runtime +fa905ec63629cbee1fd6b4619b0bb209a2d05aa0 fix(mobile): support Hermes collection sorting +b116daa728b3473a7b493169f616c37db327ed2f test(orchestrator): align integration fixtures +007b51b0ce57caded57da85108cd3da10db7dd2e fix(orchestrator): Harden Grok v2 runtime lifecycle +f006bffe139212841f36e6aca84491dd1c8ff47a fix(orchestrator): dedupe Grok continuation dispatch +333ecf1ff797ba2eb6940a9f43752a6cc7c34958 fix(orchestrator): harden Grok v2 lifecycle (#3578) +be7bb48c0aad9f2137d2b00dfad09aecdc4ed572 fix(acp): bind MCP credentials to activated threads +1124866e9f672272fd9759fe16231dd6866887b2 fix(acp): release turns after interrupt timeout +1e4a96b561036e50945d022cd3cdaf05d271bb1b fix(claude): reopen queries after MCP credential rotation +f218e04f09a13da565a981b35efb5bd33090236b fix(claude): enforce read-only tool availability +3c091989c6fde3d53abfb2050b4d98a8e0986c2b fix(claude): honor never-approval runtime policies +bad24edaf5c00b594333ff675307f910a3e44a9c fix(claude): allow questions during plan mode +bfb55f793b386dec833a0d62a1dded65c477b47d fix(claude): preserve approvals with full-access sandbox +5ce823a928ce9aad26754ad361989583ceabe2b0 fix(claude): redact launch arguments from protocol logs +b9668c948391803ce80440869d83f59686ee280c test(desktop): expect orchestrator v2 state directory +5d7d125331d609c13083cef3564dccad69e4ea44 fix(ci): restore Claude permission request identity +8a79bdd091cde84416bd22949ccebec2fe97f425 fix(orchestrator): align Claude permission replay with SDK +a9f67f41d33abc6d5d9c4580fd36d2b7be8d732c feat(orchestrator): pass model options through MCP thread targets (#3872) +e15cb8b34f64ec9676a59626020af98aa4ec2d68 fix(orchestrator): scope Claude MCP tool pre-approval (#3862) +f11c744887c8d8839316c7a5f080912ec756be21 [orchestrator-v2] fix(orchestrator): Codex background command completion and subagent resume (#3908) +47ec735048db5b7d45728108bc93e62e002a769d [orchestrator-v2] fix(orchestrator): Restore Claude session continuity for resume, wake, and idle release (#3860) +c1bae1c69fcac25f0cb36a6c9f0ff5b9bee5bf18 feat(orchestrator): Add shared provider continuation and background item plumbing +2871cf85de7f2d3eda78c31b121f447bbd6fa47f feat: scheduled tasks (automations) (#3638) +cb43524758270f7dbb9f5380d4fca94bcf9abaf8 Fix Claude task turn mapping +89eb3f0bb822d6615168a7ea19bcfa585936b98b Allow provider switching via handoff in chat threads +61dec910677504c3b47501913d130c6a56eff35b Remove early access badges from Cursor and Grok +8e2e8edd364de25e83caf6ca2ae42755071245e6 Switch Cursor provider to the official SDK +0d4886de7c94e2d5c457fc2329ba4d7b49ca7653 fix(web): align thread details panel controls and menus (#3606) +f8579194c5a67774e41da249b6d67f4f778e00f4 Require Cursor API key for provider checks +aa9c46184f2e93fed7a4e6d32ea1c638b5e0f5df Keep persistent cards visible in folded turns +47f269d43643fe1c2d31e14230fcedb93255ca67 Clarify thread relationship icons and ordering +30d6cf06ec933d2edaa7c434083dcd073c28592e Map nested Codex subagent threads correctly +4a7e85f0fca573de31740f728dee6a7c6e019401 Adopt userdata-v2 and subagent activity mapping +569c448f0094ca43951224d98b2dfce7fb44760d Map Grok task envelopes to subagent lineage +1ee6b0622eb06e918928c71466aad9f7c678be7c Add iOS associated domains for Clerk +e70b8940053b4ca8db6f2956dd3ad5a8f4da8ea4 Retire V1 client orchestration parity +06c57e49daacf968501a1960c11d7061edd0fb02 Expose V2 thread workflows on mobile +d5a4342a3daa5a83f373c62733b2e921e24eccc5 Enrich mobile V2 execution items +4b5fa27f95ccbd83cd7d47d193fdc09eb492819c Render mobile timelines from V2 turn items +c8dce47576c9cb90e5112cb8fcabb6ba57bcfa77 Hide subagent threads and simplify thread controls +b9ae98f979413ce98b96f87ad11ee6bcc5df157d Split open-in editor controls into panel and toolbar variants +7d5eedaf9f67801c5ed3b9eb648aade5c82c8f98 Reserve space for inline thread details panel +b9717bb8517d8bf954b18dc83fa79326733387d8 Map thread panel into title bar and sidebar +890f95e6a7fbaa906eb50157314e0932cbe732fa Record created threads and subagent progress +9b1752222929c1665c4b46ba72ae3458e7272827 Handle preparing turns across provider orchestration +61182514a62cad88a235fe68684d575f245103bd Integrate orchestration V2 controls and process recovery +65e85e1e2d4f4d36a3682e4ede0b63f830f8c29d Complete orchestration V2 frontend cutover +78b451958a7eba484ca9af0078f8af8980d13ad6 Split the V2 frontend plan into parity and enrichment phases +c0bb02d6da0aa4648f838202e4fac152166fc3f8 Integrate orchestration v2 with the application runtime +418deadc7263301c86eba31ab7a878df40f2c749 Guarantee MCP revocation during session release +7ba8f57840af1f86b25871dfb1a3880c8c18cf6f Remove MCP credential expiration +591c8b76b6e459af28c15b1213931d2239bbb7e4 Require MCP registry for V2 provider sessions +4d85c0c89bd57b61f0419a702f68c69997d3f96e Complete orchestration V2 application services +5bac980a78eed9e356c205d63a32a7ad67ac608f Start orchestration V2 application services +9caaa2e23f802ebfa7ff84c241201fbf15f79bc0 Align orchestration V2 with Effect service conventions +f1d7d1c122621d22401c92d07e590d6ab78f95f2 Share Codex sessions across orchestration threads +dab646dc400a921db52e665eba87a4169205c846 Map orchestration turns to provider instances +915e6b385a29c24350fcf00fbe752fc849dba5fb Add Orchestration V2 application integration plan +7cfebe0be47dcf77d7d2446c8757f434d8d8f99b Add MCP thread management and Codex turn mapping +b43bc2b62c41dcce16cad95fe61c47cb6e4d774d Add ACP replay harness and session lifecycle support +37045a02fe9b96e283b50dde70bb4e66d2280a2d Handle segmented Cursor turns and stable visible timelines +26e930ea40800bcb19430f15bd3d0b86a8593997 Add Cursor SDK orchestration replay support +8cc9df27fa72c9940e78f44863396293243237f3 Add orchestration MCP toolkit +a244d5c89514f23019e0975b21d6ca91dab4f91b refactor(orchestration-v2): adopt host process spawn policy +5dec17fc19c7984020f3af870b8b43de96460be9 wip +d175a63a1bcfc114e6b63f094fa75991ad67700e feat(orchestration-v2): model native subagents +4391068367180f05515fe210618a93da9555df53 Map orchestration v2 WS methods to auth scopes +3c06f0c2c9c389f45b2872c7099aff42bc5b0dac fix(orchestration-v2): preserve source history on merged switch +28cc526e1f8b82e88e0318367504924796ba432e fix(orchestration-v2): compose provider switch merge context +86f785623b169c309ce3feca151cd832fcadc4fd feat(orchestration-v2): add merge-back replay coverage +69cba683fa066b6a496a9ae6946fc5d7eb7ed62e fix(orchestration-v2): resolve cross-provider forks +1ed757ba0c5e05ebe7df83bb61dc1be15dbcb8a0 feat(orchestration-v2): support cross-provider handoff +bf94a66361a6f4454461d057cfd76d2c12a9344d feat(orchestration-v2): wire claude adapter primitives +ec935be6a56201c2a4006b5af16223f1b267d04d Document Cursor SDK MCP projection for V2 +ebf98e4217765858626681c4d516f20de6c27ece Add turn-interrupt replay coverage and protocol logging +1be35b30fa1fa7d6b82d01b204ea5be6aac4ae85 Support active Claude steering and turn replay mapping +d9f4e700c077c2ceede384b684979628270bb5d3 Map Claude turns to runtime query policies +c71caf0f964ccb80cc60cce7e5438ef2095af669 Map Claude replay fixtures to multi-turn turns +f806017a3c6fd4d986233e1ca7334197089e4d57 Add model selection to orchestration runs +05d619192a41b686ab3ef228e91b15fea640a1a1 Extract Claude SDK query runner from provider adapter +5c6af6923c2dd66017476d9c7ae261ca1ebe9150 Add Claude replay fixture recorder +3a75dbb5a18b15fbc8f129a36d8844e65d0d83a4 Add V2 command capability policy +88b265dab638b61c7d81652783f048445abc03bb Add merge-back context handoff support +5169fe6083b191cac4c76451d914d1266b834db0 Add orchestration V2 backend checklist +959c0e22e73063bdc0394ad6243b7b1f937c61ce Add thread fork lineage and lazy context transfer +41937c522ee8c013d80d4538c06431589daea6eb Implement orchestration v2 runtime +67d40b8e8ee93bb94e5d2407b5bd2fee265ff122 Map Codex turns into orchestration v2 +28999d551518a8b3368b18bb46a91988569b75ae Add orchestration v2 replay and service contracts +99de1c8833ea1d8f16976ed19bbc239c74f626c7 Add orchestration v2 docs and probe fixtures +d2a22ec16520e6d690924471c38f53d7c7e139a2 Address Codex review feedback +ce08dee1407d352821edc904274b890901aea815 Switch Codex provider checks to app-server probe +a1d85aa33315cf862303ad6e729e1e72f3d26aae Flush native logs on adapter shutdown +faf4d6c04e25bb531e45a809ec657262c07a2a8b decoders +c41b812f43f9172c6ca3aceaae17a213f6e5ee04 Scope Codex session runtime lifetimes +f355bd32b1075f5e0c1f734b99899cba0bf55691 Normalize Codex IDs and preserve streamed stdout decoding +773f789c82880988ea775aeff5abc3b7afe3a224 Return Cursor ACP runtime with explicit scope +fdf63358fa26262c3a3c1e06be2c674b99237a09 resynclock +3fe3534dbefd1d13e2dedfda8a706aa21306219b revert more +8852b94978538d264cad8ce8781e557d9c25d745 nit +cc2e380a1ed3ebdc664650fc87933c89f2050ac6 Integrate Codex app-server support +b8b7f894fcd31c400bbb51e197daf04c56728005 chore(ov2): preserve the integration base for replay diff --git a/audits/orchestrator-v2/2026-09-04/changed-files-final.tsv b/audits/orchestrator-v2/2026-09-04/changed-files-final.tsv new file mode 100644 index 000000000000..1648453af83d --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/changed-files-final.tsv @@ -0,0 +1,999 @@ +D .github/scripts/thread-transfer-report.cjs +D .github/scripts/thread-transfer-report.test.cjs +M .github/workflows/ci.yml +D .github/workflows/thread-transfer-report.yml +M README.md +M apps/desktop/src/app/DesktopEnvironment.test.ts +M apps/desktop/src/backend/tailscaleEndpointProvider.ts +M apps/desktop/src/settings/DesktopClientSettings.test.ts +A apps/marketing/public/app-desktop.webp +M apps/marketing/src/pages/index.astro +M apps/mobile/generated-uniwind-themes.css +M apps/mobile/scripts/generate-uniwind-themes.mts +M apps/mobile/src/components/BrandMark.tsx +A apps/mobile/src/components/brandAssets.ts +M apps/mobile/src/connection/environment-cache-store.test.ts +M apps/mobile/src/connection/environment-cache-store.ts +M apps/mobile/src/connection/runtime.ts +M apps/mobile/src/connection/storage.ts +M apps/mobile/src/features/archive/archivedThreadList.test.ts +M apps/mobile/src/features/files/ThreadFilesRouteScreen.tsx +M apps/mobile/src/features/home/HomeScreen.tsx +M apps/mobile/src/features/home/homeListItems.test.ts +M apps/mobile/src/features/home/homeThreadList.test.ts +A apps/mobile/src/features/home/threadArchive.test.ts +A apps/mobile/src/features/home/threadArchive.ts +M apps/mobile/src/features/home/useThreadListActions.ts +M apps/mobile/src/features/keyboard/hardwareKeyboardCommands.ts +M apps/mobile/src/features/projects/AddProjectScreen.tsx +A apps/mobile/src/features/review/ReviewHighlighterProvider.tsx +A apps/mobile/src/features/review/reviewHighlighterState.test.ts +A apps/mobile/src/features/review/reviewHighlighterState.ts +M apps/mobile/src/features/review/reviewModel.test.ts +M apps/mobile/src/features/review/reviewModel.ts +M apps/mobile/src/features/review/reviewState.test.ts +M apps/mobile/src/features/review/reviewState.ts +M apps/mobile/src/features/review/shikiReviewHighlighter.test.ts +D apps/mobile/src/features/review/useReviewDiffPrewarming.test.ts +M apps/mobile/src/features/review/useReviewDiffPrewarming.ts +M apps/mobile/src/features/review/useReviewSections.ts +M apps/mobile/src/features/terminal/ThreadTerminalRouteScreen.tsx +M apps/mobile/src/features/threads/NewTaskDraftScreen.tsx +M apps/mobile/src/features/threads/PendingApprovalCard.tsx +M apps/mobile/src/features/threads/PendingUserInputCard.tsx +A apps/mobile/src/features/threads/ThreadActivityInspector.tsx +M apps/mobile/src/features/threads/ThreadComposer.tsx +M apps/mobile/src/features/threads/ThreadDetailScreen.tsx +M apps/mobile/src/features/threads/ThreadFeed.tsx +M apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx +A apps/mobile/src/features/threads/ThreadQueueControl.tsx +A apps/mobile/src/features/threads/ThreadRelationshipsBanner.tsx +M apps/mobile/src/features/threads/ThreadRouteScreen.tsx +A apps/mobile/src/features/threads/thread-activity-row-presentation.test.ts +A apps/mobile/src/features/threads/thread-activity-row-presentation.ts +A apps/mobile/src/features/threads/thread-feed-item-size.test.ts +A apps/mobile/src/features/threads/thread-feed-item-size.ts +M apps/mobile/src/features/threads/thread-list-v2-items.tsx +A apps/mobile/src/features/threads/threadActivityFileNavigation.test.ts +A apps/mobile/src/features/threads/threadActivityFileNavigation.ts +A apps/mobile/src/features/threads/threadForkNavigation.test.ts +A apps/mobile/src/features/threads/threadForkNavigation.ts +M apps/mobile/src/features/threads/threadListV2.test.ts +M apps/mobile/src/features/threads/threadListV2.ts +M apps/mobile/src/features/threads/threadPresentation.ts +A apps/mobile/src/features/threads/threadQueueControlPresentation.test.ts +A apps/mobile/src/features/threads/threadQueueControlPresentation.ts +A apps/mobile/src/features/threads/userMessageIntentBadge.test.ts +A apps/mobile/src/features/threads/userMessageIntentBadge.ts +M apps/mobile/src/lib/modelOptions.ts +M apps/mobile/src/lib/projectThreadStartTurn.test.ts +M apps/mobile/src/lib/projectThreadStartTurn.ts +M apps/mobile/src/lib/scopedEntities.ts +M apps/mobile/src/lib/threadActivity.test.ts +M apps/mobile/src/lib/threadActivity.ts +A apps/mobile/src/lib/threadActivityInspector.test.ts +A apps/mobile/src/lib/threadActivityInspector.ts +M apps/mobile/src/state/queries.ts +M apps/mobile/src/state/threads.ts +M apps/mobile/src/state/use-pending-new-tasks.ts +M apps/mobile/src/state/use-selected-thread-requests.ts +M apps/mobile/src/state/use-selected-thread-worktree.ts +M apps/mobile/src/state/use-thread-composer-state.ts +M apps/mobile/src/state/use-thread-detail.ts +M apps/mobile/src/state/use-thread-outbox-drain.test.ts +M apps/mobile/src/state/use-thread-outbox-drain.ts +M apps/mobile/src/state/use-thread-selection.ts +A apps/mobile/src/state/v2-item-support.ts +A apps/mobile/src/test-fixtures.ts +A apps/server/README.md +D apps/server/integration/NetworkTransferMeasurement.integration.ts +D apps/server/integration/OrchestrationEngineHarness.integration.ts +D apps/server/integration/TestProviderAdapter.integration.ts +D apps/server/integration/TransferBudgetReport.integration.ts +D apps/server/integration/TransferBudgetScenario.integration.ts +D apps/server/integration/fixtures/providerRuntime.ts +D apps/server/integration/fixtures/transferBudget.ts +D apps/server/integration/orchestrationEngine.integration.test.ts +D apps/server/integration/orphanedProviderSessionStartup.integration.test.ts +D apps/server/integration/providerService.integration.test.ts +M apps/server/package.json +M apps/server/scripts/acp-mock-agent.ts +A apps/server/scripts/acp-replay-agent.test.ts +A apps/server/scripts/acp-replay-agent.ts +A apps/server/scripts/acp-thread-spawn-helper.c +A apps/server/scripts/acpMockCancellationState.test.ts +A apps/server/scripts/acpMockCancellationState.ts +A apps/server/scripts/claudeReplayRecordingConfig.test.ts +A apps/server/scripts/claudeReplayRecordingConfig.ts +A apps/server/scripts/codexReplayRecordingRecords.test.ts +A apps/server/scripts/codexReplayRecordingRecords.ts +A apps/server/scripts/cursorReplayRecordingWorkspace.test.ts +A apps/server/scripts/cursorReplayRecordingWorkspace.ts +A apps/server/scripts/probe-claude-fork-local-rollback-replay.ts +A apps/server/scripts/record-claude-agent-sdk-replay-fixture.ts +A apps/server/scripts/record-codex-app-server-replay-fixture.ts +A apps/server/scripts/record-cursor-agent-sdk-replay-fixture.ts +A apps/server/scripts/replayRecorderDeferredRegistry.test.ts +A apps/server/scripts/replayRecorderDeferredRegistry.ts +M apps/server/src/attachmentStore.test.ts +M apps/server/src/attachmentStore.ts +M apps/server/src/auth/RpcAuthorization.ts +D apps/server/src/bin.test.ts +M apps/server/src/checkpointing/CheckpointDiffQuery.test.ts +M apps/server/src/checkpointing/CheckpointDiffQuery.ts +A apps/server/src/claudeModelOptions.test.ts +A apps/server/src/claudeModelOptions.ts +M apps/server/src/cli/project.test.ts +M apps/server/src/cli/project.ts +M apps/server/src/environment/ServerEnvironment.test.ts +M apps/server/src/environment/ServerEnvironment.ts +M apps/server/src/git/GitWorkflowService.ts +M apps/server/src/http.test.ts +M apps/server/src/httpCors.ts +M apps/server/src/mcp/McpHttpServer.ts +M apps/server/src/mcp/McpInvocationContext.ts +M apps/server/src/mcp/McpProviderSession.ts +M apps/server/src/mcp/McpSessionRegistry.test.ts +A apps/server/src/mcp/McpSessionRegistry.testkit.ts +M apps/server/src/mcp/McpSessionRegistry.ts +A apps/server/src/mcp/OrchestratorMcpService.activity.test.ts +A apps/server/src/mcp/OrchestratorMcpService.test.ts +A apps/server/src/mcp/OrchestratorMcpService.ts +A apps/server/src/mcp/OrchestratorMcpToolkit.integration.test.ts +A apps/server/src/mcp/WorktreeMcpService.test.ts +A apps/server/src/mcp/WorktreeMcpService.ts +A apps/server/src/mcp/toolkits/orchestrator/handlers.ts +A apps/server/src/mcp/toolkits/orchestrator/tools.test.ts +A apps/server/src/mcp/toolkits/orchestrator/tools.ts +A apps/server/src/mcp/toolkits/worktree/handlers.ts +A apps/server/src/mcp/toolkits/worktree/registration.test.ts +A apps/server/src/mcp/toolkits/worktree/tools.ts +M apps/server/src/observability/Metrics.ts +A apps/server/src/orchestration-v2/AcpRegistryOrchestratorV2.live.test.ts +A apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.testkit.test.ts +A apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.testkit.test.ts +A apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/CursorAgentSdk.test.ts +A apps/server/src/orchestration-v2/Adapters/CursorAgentSdk.ts +A apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.testkit.test.ts +A apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.ts +A apps/server/src/orchestration-v2/AttachmentClaims.test.ts +A apps/server/src/orchestration-v2/AttachmentClaims.ts +A apps/server/src/orchestration-v2/AttachmentPrompt.test.ts +A apps/server/src/orchestration-v2/AttachmentPrompt.ts +A apps/server/src/orchestration-v2/CheckpointCaptureService.test.ts +A apps/server/src/orchestration-v2/CheckpointCaptureService.ts +A apps/server/src/orchestration-v2/CheckpointPolicy.ts +A apps/server/src/orchestration-v2/CheckpointRollbackService.test.ts +A apps/server/src/orchestration-v2/CheckpointRollbackService.ts +A apps/server/src/orchestration-v2/CheckpointService.test.ts +A apps/server/src/orchestration-v2/CheckpointService.ts +A apps/server/src/orchestration-v2/CommandPolicy.test.ts +A apps/server/src/orchestration-v2/CommandPolicy.ts +A apps/server/src/orchestration-v2/CommandReceiptStore.ts +A apps/server/src/orchestration-v2/ContextHandoffService.test.ts +A apps/server/src/orchestration-v2/ContextHandoffService.ts +A apps/server/src/orchestration-v2/CursorOrchestratorV2.live.test.ts +A apps/server/src/orchestration-v2/DelegatedCompletionDelivery.test.ts +A apps/server/src/orchestration-v2/EffectOutbox.ts +A apps/server/src/orchestration-v2/EffectWorker.test.ts +A apps/server/src/orchestration-v2/EffectWorker.ts +A apps/server/src/orchestration-v2/EventSink.ts +A apps/server/src/orchestration-v2/EventStore.ts +A apps/server/src/orchestration-v2/FoundationPersistence.test.ts +A apps/server/src/orchestration-v2/GrokOrchestratorV2.live.test.ts +A apps/server/src/orchestration-v2/IdAllocator.ts +A apps/server/src/orchestration-v2/KeyedSerialExecutor.test.ts +A apps/server/src/orchestration-v2/KeyedSerialExecutor.ts +A apps/server/src/orchestration-v2/LegacyV1ThreadImporter.test.ts +A apps/server/src/orchestration-v2/LegacyV1ThreadImporter.ts +A apps/server/src/orchestration-v2/Orchestrator.migration.test.ts +A apps/server/src/orchestration-v2/Orchestrator.ts +A apps/server/src/orchestration-v2/ProjectionMaintenance.ts +A apps/server/src/orchestration-v2/ProjectionRecovery.test.ts +A apps/server/src/orchestration-v2/ProjectionStore.test.ts +A apps/server/src/orchestration-v2/ProjectionStore.ts +A apps/server/src/orchestration-v2/ProviderAdapter.ts +A apps/server/src/orchestration-v2/ProviderAdapterDriver.ts +A apps/server/src/orchestration-v2/ProviderAdapterRegistry.test.ts +A apps/server/src/orchestration-v2/ProviderAdapterRegistry.ts +A apps/server/src/orchestration-v2/ProviderContinuationRequests.ts +A apps/server/src/orchestration-v2/ProviderContinuationService.test.ts +A apps/server/src/orchestration-v2/ProviderContinuationService.ts +A apps/server/src/orchestration-v2/ProviderEventIngestor.test.ts +A apps/server/src/orchestration-v2/ProviderEventIngestor.ts +A apps/server/src/orchestration-v2/ProviderFailure.test.ts +A apps/server/src/orchestration-v2/ProviderFailure.ts +A apps/server/src/orchestration-v2/ProviderRuntimeRecoveryService.regression.test.ts +A apps/server/src/orchestration-v2/ProviderRuntimeRecoveryService.test.ts +A apps/server/src/orchestration-v2/ProviderRuntimeRecoveryService.ts +A apps/server/src/orchestration-v2/ProviderSelectionTransition.test.ts +A apps/server/src/orchestration-v2/ProviderSelectionTransition.ts +A apps/server/src/orchestration-v2/ProviderSessionManager.test.ts +A apps/server/src/orchestration-v2/ProviderSessionManager.ts +A apps/server/src/orchestration-v2/ProviderSessionTransitionPolicy.test.ts +A apps/server/src/orchestration-v2/ProviderSessionTransitionPolicy.ts +A apps/server/src/orchestration-v2/ProviderSwitchService.test.ts +A apps/server/src/orchestration-v2/ProviderSwitchService.ts +A apps/server/src/orchestration-v2/ProviderTurnControlService.test.ts +A apps/server/src/orchestration-v2/ProviderTurnControlService.ts +A apps/server/src/orchestration-v2/ProviderTurnStartService.test.ts +A apps/server/src/orchestration-v2/ProviderTurnStartService.testkit.ts +A apps/server/src/orchestration-v2/ProviderTurnStartService.ts +A apps/server/src/orchestration-v2/ProviderTurnTokenUsage.test.ts +A apps/server/src/orchestration-v2/QueuedRunOrder.test.ts +A apps/server/src/orchestration-v2/QueuedRunOrder.ts +A apps/server/src/orchestration-v2/RandomUuid.ts +A apps/server/src/orchestration-v2/ResourceCleanupService.ts +A apps/server/src/orchestration-v2/RunExecutionService.test.ts +A apps/server/src/orchestration-v2/RunExecutionService.ts +A apps/server/src/orchestration-v2/RunFinalizationService.test.ts +A apps/server/src/orchestration-v2/RunFinalizationService.ts +A apps/server/src/orchestration-v2/RuntimePolicy.test.ts +A apps/server/src/orchestration-v2/RuntimePolicy.ts +A apps/server/src/orchestration-v2/RuntimeRequestService.test.ts +A apps/server/src/orchestration-v2/RuntimeRequestService.ts +A apps/server/src/orchestration-v2/SelectionRestart.integration.test.ts +A apps/server/src/orchestration-v2/ShellStream.test.ts +A apps/server/src/orchestration-v2/ShellStream.ts +A apps/server/src/orchestration-v2/SubagentProjection.test.ts +A apps/server/src/orchestration-v2/SubagentProjection.ts +A apps/server/src/orchestration-v2/TODO.md +A apps/server/src/orchestration-v2/ThreadForkService.test.ts +A apps/server/src/orchestration-v2/ThreadForkService.ts +A apps/server/src/orchestration-v2/ThreadLaunchService.test.ts +A apps/server/src/orchestration-v2/ThreadLaunchService.ts +A apps/server/src/orchestration-v2/ThreadLifecycleService.test.ts +A apps/server/src/orchestration-v2/ThreadLifecycleService.ts +R060 apps/server/src/orchestration/ThreadLiveEventCoalescer.test.ts apps/server/src/orchestration-v2/ThreadLiveEventCoalescer.test.ts +R062 apps/server/src/orchestration/ThreadLiveEventCoalescer.ts apps/server/src/orchestration-v2/ThreadLiveEventCoalescer.ts +A apps/server/src/orchestration-v2/ThreadManagementService.test.ts +A apps/server/src/orchestration-v2/ThreadManagementService.ts +A apps/server/src/orchestration-v2/ThreadSettlementService.test.ts +R059 apps/server/src/orchestration/ThreadSettlementReactor.ts apps/server/src/orchestration-v2/ThreadSettlementService.ts +A apps/server/src/orchestration-v2/ThreadStream.test.ts +A apps/server/src/orchestration-v2/ThreadStream.ts +A apps/server/src/orchestration-v2/ThreadTitleRegenerationService.test.ts +A apps/server/src/orchestration-v2/ThreadTitleRegenerationService.ts +A apps/server/src/orchestration-v2/TurnItemPositionStore.ts +A apps/server/src/orchestration-v2/UserFacingErrors.test.ts +A apps/server/src/orchestration-v2/UserFacingErrors.ts +A apps/server/src/orchestration-v2/V1ImportBoundary.test.ts +A apps/server/src/orchestration-v2/WireProjection.test.ts +A apps/server/src/orchestration-v2/WireProjection.ts +A apps/server/src/orchestration-v2/applicationLayer.ts +A apps/server/src/orchestration-v2/builtInProviderAdapterDrivers.ts +A apps/server/src/orchestration-v2/http.ts +A apps/server/src/orchestration-v2/runtimeLayer.test.ts +A apps/server/src/orchestration-v2/runtimeLayer.ts +A apps/server/src/orchestration-v2/testkit/ClaudeReplayFixtures.integration.test.ts +A apps/server/src/orchestration-v2/testkit/CodexReplayFixtures.integration.test.ts +A apps/server/src/orchestration-v2/testkit/DeterministicRuntime.ts +A apps/server/src/orchestration-v2/testkit/OrchestratorReplayFixtures.contract.test.ts +A apps/server/src/orchestration-v2/testkit/OrchestratorReplayFixtures.integration.test.ts +A apps/server/src/orchestration-v2/testkit/OrchestratorReplayRecovery.integration.test.ts +A apps/server/src/orchestration-v2/testkit/OrchestratorScenario.ts +A apps/server/src/orchestration-v2/testkit/ProviderReplayGate.testkit.test.ts +A apps/server/src/orchestration-v2/testkit/ProviderReplayGate.testkit.ts +A apps/server/src/orchestration-v2/testkit/ProviderReplayHarness.ts +A apps/server/src/orchestration-v2/testkit/ProviderSwitch.integration.test.ts +A apps/server/src/orchestration-v2/testkit/ReplayFixtureWorkspace.ts +A apps/server/src/orchestration-v2/testkit/ReplayTranscriptNdjson.test.ts +A apps/server/src/orchestration-v2/testkit/ReplayTranscriptNdjson.ts +A apps/server/src/orchestration-v2/testkit/ThreadFork.integration.test.ts +A apps/server/src/orchestration-v2/testkit/ThreadMergeBack.integration.test.ts +A apps/server/src/orchestration-v2/testkit/fixtures/acp_elicitation/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/claude_background_task_after_root/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/claude_background_task_after_root/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_background_task_after_root/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_idle_resume/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/claude_idle_resume/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_idle_resume/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_local_bash_task/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/claude_local_bash_task/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_local_bash_task/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_result_is_error/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/claude_result_is_error/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_result_is_error/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/grok_subagent_lineage/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/grok_subagent_lineage/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/grok_subagent_lineage/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/index.ts +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/grok_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn_restart/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_child_approval/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_child_approval/opencode_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_child_approval/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_subagent/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_subagent/opencode_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_subagent/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/opencode_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/opencode_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/provider_thread_resume/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/provider_thread_resume/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/queued_cancelled_while_active/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/queued_cancelled_while_active/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/shared.ts +A apps/server/src/orchestration-v2/testkit/fixtures/simple/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/simple/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/simple/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/simple/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/simple/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/simple/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/simple/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/simple/opencode_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/README.md +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2_nested/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2_nested/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_continue/README.md +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_continue/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_continue/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_fork_local_rollback/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_prior_turn/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_prior_turn/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_siblings/README.md +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_siblings/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_siblings/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_continue/README.md +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_continue/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_continue/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_siblings/README.md +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_siblings/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_siblings/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/grok_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/opencode_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_restart/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_restart/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_restart/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/web_search/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/web_search/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/web_search/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/web_search/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/web_search/input.ts +A apps/server/src/orchestration-v2/testkit/index.ts +A apps/server/src/orchestration-v2/threadHistoryPaging.test.ts +A apps/server/src/orchestration-v2/threadHistoryPaging.ts +D apps/server/src/orchestration/ActivityPayloadProjection.test.ts +D apps/server/src/orchestration/ActivityPayloadProjection.ts +D apps/server/src/orchestration/Layers/CheckpointReactor.test.ts +D apps/server/src/orchestration/Layers/CheckpointReactor.ts +D apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts +M apps/server/src/orchestration/Layers/OrchestrationEngine.ts +D apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts +D apps/server/src/orchestration/Layers/OrchestrationReactor.ts +A apps/server/src/orchestration/Layers/ProjectEnrichmentProjection.test.ts +D apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts +M apps/server/src/orchestration/Layers/ProjectionPipeline.ts +A apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.search.test.ts +D apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts +M apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts +D apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts +D apps/server/src/orchestration/Layers/ProviderCommandReactor.ts +D apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.activity.test.ts +D apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.approval.test.ts +D apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts +D apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts +D apps/server/src/orchestration/Layers/RuntimeReceiptBus.ts +D apps/server/src/orchestration/Layers/ThreadDeletionReactor.test.ts +D apps/server/src/orchestration/Layers/ThreadDeletionReactor.ts +M apps/server/src/orchestration/LiveStreamBudget.test.ts +M apps/server/src/orchestration/LiveStreamBudget.ts +D apps/server/src/orchestration/Normalizer.attachments.test.ts +D apps/server/src/orchestration/Normalizer.test.ts +D apps/server/src/orchestration/Normalizer.ts +M apps/server/src/orchestration/Schemas.ts +D apps/server/src/orchestration/Services/CheckpointReactor.ts +M apps/server/src/orchestration/Services/OrchestrationEngine.ts +D apps/server/src/orchestration/Services/OrchestrationReactor.ts +M apps/server/src/orchestration/Services/ProjectionPipeline.ts +M apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts +D apps/server/src/orchestration/Services/ProviderCommandReactor.ts +D apps/server/src/orchestration/Services/ProviderRuntimeIngestion.ts +D apps/server/src/orchestration/Services/RuntimeReceiptBus.ts +D apps/server/src/orchestration/Services/ThreadDeletionReactor.ts +D apps/server/src/orchestration/ThreadSettlementReactor.test.ts +D apps/server/src/orchestration/commandInvariants.test.ts +M apps/server/src/orchestration/commandInvariants.ts +D apps/server/src/orchestration/decider.delete.test.ts +M apps/server/src/orchestration/decider.ts +D apps/server/src/orchestration/http.ts +D apps/server/src/orchestration/projector.test.ts +M apps/server/src/orchestration/projector.ts +M apps/server/src/persistence/Layers/OrchestrationCommandReceipts.ts +A apps/server/src/persistence/Layers/OrchestrationEventStore.sequence.test.ts +M apps/server/src/persistence/Layers/OrchestrationEventStore.test.ts +M apps/server/src/persistence/Layers/OrchestrationEventStore.ts +M apps/server/src/persistence/Layers/ProjectionCheckpoints.ts +M apps/server/src/persistence/Layers/ProjectionTurns.ts +M apps/server/src/persistence/Migrations.ts +A apps/server/src/persistence/Migrations/048_049_OrchestrationV2.test.ts +A apps/server/src/persistence/Migrations/048_OrchestrationV2.ts +A apps/server/src/persistence/Migrations/049_OrchestrationV2Subagents.ts +A apps/server/src/persistence/Migrations/050_OrchestrationV2Foundation.test.ts +A apps/server/src/persistence/Migrations/050_OrchestrationV2Foundation.ts +A apps/server/src/persistence/Migrations/051_OrchestrationV2ProviderSessionBindings.ts +A apps/server/src/persistence/Migrations/052_OrchestrationV2ThreadLaunchWorkflows.ts +A apps/server/src/persistence/Migrations/053_ApplicationEventSource.test.ts +A apps/server/src/persistence/Migrations/053_ApplicationEventSource.ts +A apps/server/src/persistence/Migrations/054_OrchestrationV2EffectCancellation.test.ts +A apps/server/src/persistence/Migrations/054_OrchestrationV2EffectCancellation.ts +A apps/server/src/persistence/Migrations/055_ScheduledTasks.ts +A apps/server/src/persistence/Migrations/056_LegacyV1ImportState.ts +A apps/server/src/persistence/Migrations/057_ApplicationEventSequenceIndexes.ts +A apps/server/src/persistence/Migrations/058_OrchestrationV2RecoveryIndexes.ts +M apps/server/src/persistence/ProviderSessionRuntime.ts +M apps/server/src/persistence/Services/OrchestrationCommandReceipts.ts +M apps/server/src/persistence/Services/OrchestrationEventStore.ts +M apps/server/src/persistence/Services/ProjectionCheckpoints.ts +M apps/server/src/persistence/Services/ProjectionPendingApprovals.ts +M apps/server/src/persistence/Services/ProjectionThreadActivities.ts +M apps/server/src/persistence/Services/ProjectionThreadMessages.ts +M apps/server/src/persistence/Services/ProjectionThreadProposedPlans.ts +M apps/server/src/persistence/Services/ProjectionThreadSessions.ts +M apps/server/src/persistence/Services/ProjectionTurns.ts +A apps/server/src/project/ProjectEnrichmentService.test.ts +A apps/server/src/project/ProjectEnrichmentService.ts +A apps/server/src/project/ProjectService.test.ts +A apps/server/src/project/ProjectService.ts +M apps/server/src/project/ProjectSetupScriptRunner.test.ts +M apps/server/src/project/ProjectSetupScriptRunner.ts +A apps/server/src/project/http.test.ts +A apps/server/src/project/http.ts +A apps/server/src/provider/ClaudeTurnTokenUsage.ts +M apps/server/src/provider/CodexDeveloperInstructions.ts +A apps/server/src/provider/CodexToolPresentation.ts +A apps/server/src/provider/CodexTurnTokenUsage.ts +A apps/server/src/provider/Drivers/AcpRegistryDriver.ts +M apps/server/src/provider/Drivers/AntigravityDriver.test.ts +M apps/server/src/provider/Drivers/AntigravityDriver.ts +M apps/server/src/provider/Drivers/ClaudeDriver.ts +M apps/server/src/provider/Drivers/CodexDriver.ts +M apps/server/src/provider/Drivers/CursorDriver.ts +A apps/server/src/provider/Drivers/CursorSkills.test.ts +M apps/server/src/provider/Drivers/GrokDriver.ts +M apps/server/src/provider/Drivers/OpenCodeDriver.ts +M apps/server/src/provider/Errors.ts +D apps/server/src/provider/Layers/AntigravityAdapter.test.ts +D apps/server/src/provider/Layers/AntigravityAdapter.ts +D apps/server/src/provider/Layers/ClaudeAdapter.test.ts +D apps/server/src/provider/Layers/ClaudeAdapter.ts +D apps/server/src/provider/Layers/CodexAdapter.test.ts +D apps/server/src/provider/Layers/CodexAdapter.ts +D apps/server/src/provider/Layers/CursorAdapter.test.ts +D apps/server/src/provider/Layers/CursorAdapter.ts +M apps/server/src/provider/Layers/CursorProvider.test.ts +M apps/server/src/provider/Layers/CursorProvider.ts +A apps/server/src/provider/Layers/CursorSdkCatalog.ts +M apps/server/src/provider/Layers/EventNdjsonLogger.test.ts +M apps/server/src/provider/Layers/EventNdjsonLogger.ts +D apps/server/src/provider/Layers/GrokAdapter.test.ts +D apps/server/src/provider/Layers/GrokAdapter.ts +M apps/server/src/provider/Layers/GrokProvider.ts +D apps/server/src/provider/Layers/OpenCodeAdapter.test.ts +D apps/server/src/provider/Layers/OpenCodeAdapter.ts +D apps/server/src/provider/Layers/ProviderAdapterRegistry.test.ts +D apps/server/src/provider/Layers/ProviderAdapterRegistry.ts +M apps/server/src/provider/Layers/ProviderAuthService.test.ts +M apps/server/src/provider/Layers/ProviderAuthService.ts +M apps/server/src/provider/Layers/ProviderInstanceRegistryHydration.ts +M apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts +A apps/server/src/provider/Layers/ProviderOrchestrationAdapterInfrastructure.ts +M apps/server/src/provider/Layers/ProviderRegistry.test.ts +M apps/server/src/provider/Layers/ProviderRegistry.ts +D apps/server/src/provider/Layers/ProviderService.test.ts +D apps/server/src/provider/Layers/ProviderService.ts +D apps/server/src/provider/Layers/ProviderSessionDirectory.test.ts +D apps/server/src/provider/Layers/ProviderSessionDirectory.ts +D apps/server/src/provider/Layers/ProviderSessionReaper.test.ts +D apps/server/src/provider/Layers/ProviderSessionReaper.ts +M apps/server/src/provider/Layers/ProviderUsageLimitsIngestion.ts +A apps/server/src/provider/NativeProtocolLogging.ts +M apps/server/src/provider/ProviderDriver.ts +D apps/server/src/provider/Services/ClaudeAdapter.ts +D apps/server/src/provider/Services/CodexAdapter.ts +D apps/server/src/provider/Services/CursorAdapter.ts +D apps/server/src/provider/Services/GrokAdapter.ts +D apps/server/src/provider/Services/OpenCodeAdapter.ts +D apps/server/src/provider/Services/ProviderAdapter.ts +D apps/server/src/provider/Services/ProviderAdapterRegistry.ts +D apps/server/src/provider/Services/ProviderService.ts +D apps/server/src/provider/Services/ProviderSessionDirectory.ts +D apps/server/src/provider/Services/ProviderSessionReaper.ts +A apps/server/src/provider/T3OrchestrationInstructions.test.ts +A apps/server/src/provider/T3OrchestrationInstructions.ts +A apps/server/src/provider/TurnTokenUsage.test.ts +D apps/server/src/provider/acp/AcpAdapterSupport.test.ts +D apps/server/src/provider/acp/AcpAdapterSupport.ts +M apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts +M apps/server/src/provider/acp/AcpNativeLogging.ts +A apps/server/src/provider/acp/AcpRegistrySupport.test.ts +A apps/server/src/provider/acp/AcpRegistrySupport.ts +M apps/server/src/provider/acp/AcpRuntimeModel.test.ts +M apps/server/src/provider/acp/AcpRuntimeModel.ts +A apps/server/src/provider/acp/AcpSessionRuntime.processTree.test.ts +M apps/server/src/provider/acp/AcpSessionRuntime.ts +M apps/server/src/provider/acp/AntigravityAcpSupport.ts +A apps/server/src/provider/acp/AntigravityClientFiles.ts +M apps/server/src/provider/acp/AntigravityProtocol.ts +D apps/server/src/provider/acp/CursorAcpCliProbe.test.ts +D apps/server/src/provider/acp/CursorAcpExtension.test.ts +D apps/server/src/provider/acp/CursorAcpExtension.ts +D apps/server/src/provider/acp/CursorAcpSupport.test.ts +D apps/server/src/provider/acp/CursorAcpSupport.ts +M apps/server/src/provider/acp/GrokAcpCliProbe.test.ts +M apps/server/src/provider/acp/GrokAcpSupport.test.ts +M apps/server/src/provider/acp/GrokAcpSupport.ts +M apps/server/src/provider/acp/XAiAcpExtension.test.ts +M apps/server/src/provider/acp/XAiAcpExtension.ts +M apps/server/src/provider/builtInDrivers.ts +A apps/server/src/provider/cursorSdkModel.ts +M apps/server/src/provider/model-manifest.json +M apps/server/src/provider/providerInstallation.test.ts +M apps/server/src/provider/providerMaintenanceRunner.test.ts +D apps/server/src/provider/testUtils/providerAdapterRegistryMock.ts +D apps/server/src/relay/AgentAwarenessRelay.test.ts +M apps/server/src/relay/AgentAwarenessRelay.ts +A apps/server/src/scheduledTasks/Schedule.test.ts +A apps/server/src/scheduledTasks/Schedule.ts +A apps/server/src/scheduledTasks/ScheduledTaskService.ts +D apps/server/src/server.test.ts +M apps/server/src/server.ts +M apps/server/src/serverActivation.ts +M apps/server/src/serverLifecycleEvents.test.ts +M apps/server/src/serverLifecycleEvents.ts +D apps/server/src/serverRuntimeStartup.reconcile.test.ts +M apps/server/src/serverRuntimeStartup.test.ts +M apps/server/src/serverRuntimeStartup.ts +M apps/server/src/terminal/Manager.test.ts +M apps/server/src/terminal/Manager.ts +M apps/server/src/textGeneration/CodexTextGeneration.test.ts +M apps/server/src/textGeneration/CodexTextGeneration.ts +M apps/server/src/textGeneration/CursorTextGeneration.test.ts +M apps/server/src/textGeneration/CursorTextGeneration.ts +M apps/server/src/textGeneration/TextGeneration.test.ts +M apps/server/src/vcs/GitVcsDriver.ts +M apps/server/src/vcs/GitVcsDriverCore.test.ts +M apps/server/src/vcs/GitVcsDriverCore.ts +A apps/server/src/ws.test.ts +M apps/server/src/ws.ts +D apps/server/test/ActivityPayloadProjection.test.ts +M apps/web/src/appearanceFonts.test.ts +M apps/web/src/appearanceFonts.ts +M apps/web/src/components/AppSidebarLayout.tsx +M apps/web/src/components/BranchToolbar.logic.test.ts +M apps/web/src/components/BranchToolbar.logic.ts +M apps/web/src/components/BranchToolbar.tsx +M apps/web/src/components/BranchToolbarBranchSelector.tsx +M apps/web/src/components/BranchToolbarEnvModeSelector.tsx +M apps/web/src/components/BranchToolbarEnvironmentSelector.tsx +M apps/web/src/components/ChatView.logic.test.ts +M apps/web/src/components/ChatView.logic.ts +M apps/web/src/components/ChatView.tsx +M apps/web/src/components/CommandPalette.logic.test.ts +M apps/web/src/components/CommandPalette.logic.ts +M apps/web/src/components/CommandPalette.tsx +M apps/web/src/components/DiffPanel.tsx +M apps/web/src/components/GitActionsControl.logic.test.ts +M apps/web/src/components/GitActionsControl.logic.ts +M apps/web/src/components/GitActionsControl.tsx +M apps/web/src/components/LegacySidebar.tsx +A apps/web/src/components/LegacyThreadMigrationToast.tsx +M apps/web/src/components/ProjectScriptsControl.tsx +M apps/web/src/components/RightPanelTabs.tsx +M apps/web/src/components/Sidebar.logic.test.ts +M apps/web/src/components/Sidebar.logic.ts +M apps/web/src/components/Sidebar.tsx +M apps/web/src/components/ThreadStatusIndicators.tsx +M apps/web/src/components/chat/ChangedFilesTree.test.tsx +M apps/web/src/components/chat/ChangedFilesTree.tsx +M apps/web/src/components/chat/ChatComposer.tsx +M apps/web/src/components/chat/ChatHeader.tsx +M apps/web/src/components/chat/ComposerBanner.tsx +M apps/web/src/components/chat/ComposerBannerStack.tsx +M apps/web/src/components/chat/ComposerPendingApprovalActions.test.tsx +M apps/web/src/components/chat/ComposerPendingApprovalActions.tsx +M apps/web/src/components/chat/ComposerPendingApprovalPanel.test.tsx +M apps/web/src/components/chat/ComposerPendingApprovalPanel.tsx +M apps/web/src/components/chat/ComposerPendingUserInputPanel.test.tsx +M apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx +M apps/web/src/components/chat/ComposerPrimaryActions.test.tsx +M apps/web/src/components/chat/ComposerPrimaryActions.tsx +M apps/web/src/components/chat/ComposerServerUpdateStatus.tsx +D apps/web/src/components/chat/ContextWindowMeter.test.tsx +M apps/web/src/components/chat/MessagesTimeline.logic.test.ts +M apps/web/src/components/chat/MessagesTimeline.logic.ts +M apps/web/src/components/chat/MessagesTimeline.test.tsx +M apps/web/src/components/chat/MessagesTimeline.tsx +A apps/web/src/components/chat/OpenInPicker.logic.ts +R073 apps/web/src/components/chat/ChatHeader.test.ts apps/web/src/components/chat/OpenInPicker.test.ts +M apps/web/src/components/chat/OpenInPicker.tsx +A apps/web/src/components/chat/OpenInPickerShortcut.ts +M apps/web/src/components/chat/PanelLayoutControls.tsx +M apps/web/src/components/chat/ProposedPlanCard.tsx +A apps/web/src/components/chat/QueuedRunsControl.test.tsx +A apps/web/src/components/chat/QueuedRunsControl.tsx +A apps/web/src/components/chat/ThreadAutomationsPanel.tsx +A apps/web/src/components/chat/ThreadDetailsPanel.test.tsx +A apps/web/src/components/chat/ThreadDetailsPanel.tsx +A apps/web/src/components/chat/ThreadDetailsPrRow.tsx +A apps/web/src/components/chat/ThreadRelationshipsControl.test.tsx +A apps/web/src/components/chat/ThreadRelationshipsControl.tsx +A apps/web/src/components/chat/TimelineSystemDivider.tsx +A apps/web/src/components/chat/V2ItemInspector.tsx +A apps/web/src/components/chat/V2LifecycleRow.tsx +A apps/web/src/components/chat/composerDispatch.test.ts +A apps/web/src/components/chat/composerDispatch.ts +M apps/web/src/components/chat/externalLinkContextMenu.test.ts +M apps/web/src/components/chat/externalLinkContextMenu.ts +A apps/web/src/components/chat/threadDetailsPanelStyles.ts +M apps/web/src/components/chat/useAssistantCitationTarget.ts +M apps/web/src/components/files/FilePreviewPanel.tsx +M apps/web/src/components/preview/PreviewPanelShell.tsx +M apps/web/src/components/preview/ThreadPreviewMiniPlayer.tsx +M apps/web/src/components/preview/addBrowserSurface.test.ts +M apps/web/src/components/preview/previewMiniPlayerLayout.test.ts +M apps/web/src/components/preview/previewMiniPlayerLayout.ts +M apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx +M apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts +M apps/web/src/components/pullRequest/pullRequestDetail.logic.ts +M apps/web/src/components/pullRequest/pullRequestPresentation.tsx +A apps/web/src/components/pullRequest/usePullRequestActions.ts +M apps/web/src/components/settings/AddProviderInstanceDialog.tsx +M apps/web/src/components/settings/KeybindingsSettings.logic.test.ts +M apps/web/src/components/settings/ProjectSettingsPanel.tsx +M apps/web/src/components/settings/ProviderInstanceCard.test.ts +M apps/web/src/components/settings/ProviderInstanceCard.tsx +M apps/web/src/components/settings/ProviderSettingsForm.test.ts +A apps/web/src/components/settings/ScheduledTasksSettings.tsx +M apps/web/src/components/settings/SettingsPanels.tsx +M apps/web/src/components/settings/SettingsSidebarNav.tsx +M apps/web/src/components/settings/providerDriverMeta.ts +M apps/web/src/components/settings/settingsSearch.test.ts +M apps/web/src/components/settings/settingsSearch.ts +M apps/web/src/components/ui/popover.tsx +M apps/web/src/composerDraftStore.ts +M apps/web/src/connection/runtime.ts +M apps/web/src/connection/storage.ts +M apps/web/src/diffFileActions.test.ts +M apps/web/src/diffPanelStore.test.ts +M apps/web/src/diffPanelStore.ts +A apps/web/src/hooks/useElementWidth.ts +M apps/web/src/hooks/useHandleNewThread.ts +A apps/web/src/hooks/usePreviewPanelInlineSize.ts +M apps/web/src/hooks/useThreadActionMenu.ts +M apps/web/src/hooks/useThreadActions.ts +A apps/web/src/hooks/useThreadVisitedMigration.ts +M apps/web/src/hooks/useTurnDiffSummaries.ts +M apps/web/src/index.css +M apps/web/src/keybindings.test.ts +M apps/web/src/keybindings.ts +M apps/web/src/lib/contextWindow.test.ts +M apps/web/src/lib/contextWindow.ts +A apps/web/src/lib/orchestrationV2Timeline.test.ts +A apps/web/src/lib/orchestrationV2Timeline.ts +M apps/web/src/lib/threadSort.test.ts +M apps/web/src/pendingUserInput.test.ts +M apps/web/src/pendingUserInput.ts +M apps/web/src/providerInstances.test.ts +M apps/web/src/providerInstances.ts +A apps/web/src/providerUpdateDismissal.test.ts +M apps/web/src/providerUpdateDismissal.ts +A apps/web/src/rightPanelLayout.test.ts +M apps/web/src/rightPanelLayout.ts +M apps/web/src/rightPanelStore.test.ts +M apps/web/src/rightPanelStore.ts +M apps/web/src/routeTree.gen.ts +M apps/web/src/routes/__root.tsx +M apps/web/src/routes/_chat.$environmentId.$threadId.tsx +M apps/web/src/routes/_chat.draft.$draftId.tsx +M apps/web/src/routes/_chat.pull-requests.tsx +A apps/web/src/routes/settings.scheduled-tasks.tsx +D apps/web/src/session-logic.command-output.test.ts +M apps/web/src/session-logic.test.ts +M apps/web/src/session-logic.ts +M apps/web/src/state/entities.ts +M apps/web/src/state/queries.ts +M apps/web/src/state/server.ts +M apps/web/src/state/sourceControlActions.ts +D apps/web/src/state/terminalSessions.test.ts +M apps/web/src/state/terminalSessions.ts +M apps/web/src/state/threads.ts +A apps/web/src/state/v2ItemSupport.ts +A apps/web/src/state/waitForAtomValue.test.ts +A apps/web/src/state/waitForAtomValue.ts +A apps/web/src/test-fixtures.ts +M apps/web/src/threadRoutes.test.ts +M apps/web/src/threadRoutes.ts +M apps/web/src/threadSync.test.ts +M apps/web/src/timestampFormat.test.ts +M apps/web/src/timestampFormat.ts +M apps/web/src/types.ts +M apps/web/src/uiStateStore.test.ts +M apps/web/src/versionSkew.test.ts +M apps/web/src/versionSkew.ts +M apps/web/src/worktreeCleanup.test.ts +M docs/README.md +M docs/internals/connection-runtime.md +A docs/internals/context-handoffs.md +A docs/internals/legacy-orchestration-migration.md +M docs/internals/overview.md +A docs/internals/performance-regressions.md +M docs/internals/providers.md +M docs/internals/terminal-runtime.md +A docs/orchestration-v2/README.md +A docs/orchestration-v2/core-graph-and-data-model.md +A docs/orchestration-v2/entity-ids-and-correlation.md +A docs/orchestration-v2/feature-lifecycles.md +A docs/orchestration-v2/orchestrator-mcp-server.md +A docs/orchestration-v2/provider-capability-system.md +A docs/orchestration-v2/provider-switching-and-context.md +A docs/orchestration-v2/testing-strategy.md +A docs/orchestration-v2/thread-lineage-and-context-transfer.md +A docs/user/activity-log.md +A docs/user/appearance.md +M docs/user/composer.md +A docs/user/cursor.md +A docs/user/portable-handoffs.md +M docs/user/source-control.md +D docs/user/terminal.md +A docs/user/thread-migration.md +M docs/user/updating.md +M infra/relay/src/http/Api.test.ts +M infra/relay/src/http/Api.ts +M infra/relay/src/worker.ts +M package.json +M packages/client-runtime/package.json +A packages/client-runtime/src/connection/compatibility.test.ts +A packages/client-runtime/src/connection/compatibility.ts +M packages/client-runtime/src/connection/registry.test.ts +M packages/client-runtime/src/connection/resolver.test.ts +M packages/client-runtime/src/connection/resolver.ts +M packages/client-runtime/src/operations/commands.test.ts +M packages/client-runtime/src/operations/commands.ts +M packages/client-runtime/src/operations/index.ts +M packages/client-runtime/src/operations/projects.test.ts +M packages/client-runtime/src/operations/projects.ts +A packages/client-runtime/src/operations/threadTitle.test.ts +A packages/client-runtime/src/operations/threadTitle.ts +M packages/client-runtime/src/platform/index.ts +A packages/client-runtime/src/platform/orchestrationCache.test.ts +A packages/client-runtime/src/platform/orchestrationCache.ts +M packages/client-runtime/src/platform/persistence.ts +M packages/client-runtime/src/rpc/client.ts +M packages/client-runtime/src/state/archivedThreads.test.ts +M packages/client-runtime/src/state/archivedThreads.ts +A packages/client-runtime/src/state/boundedThreadSnapshotHttp.test.ts +A packages/client-runtime/src/state/boundedThreadSnapshotHttp.ts +M packages/client-runtime/src/state/entities.test.ts +A packages/client-runtime/src/state/environmentHttpAuth.test.ts +M packages/client-runtime/src/state/environmentHttpAuth.ts +A packages/client-runtime/src/state/itemSupport.test.ts +A packages/client-runtime/src/state/itemSupport.ts +M packages/client-runtime/src/state/models.ts +M packages/client-runtime/src/state/orchestration.ts +A packages/client-runtime/src/state/orchestrationV2Projection.test.ts +A packages/client-runtime/src/state/orchestrationV2Projection.ts +A packages/client-runtime/src/state/orchestrationV2TestFixtures.ts +M packages/client-runtime/src/state/projectEntities.ts +M packages/client-runtime/src/state/server.ts +M packages/client-runtime/src/state/shell-sync.test.ts +M packages/client-runtime/src/state/shell.test.ts +M packages/client-runtime/src/state/shell.ts +M packages/client-runtime/src/state/shellReducer.test.ts +M packages/client-runtime/src/state/shellReducer.ts +M packages/client-runtime/src/state/shellSnapshotHttp.ts +M packages/client-runtime/src/state/snapshots.ts +M packages/client-runtime/src/state/subagentRuntime.ts +A packages/client-runtime/src/state/threadCheckpoints.ts +M packages/client-runtime/src/state/threadCommands.ts +A packages/client-runtime/src/state/threadDetail.test.ts +M packages/client-runtime/src/state/threadDetail.ts +A packages/client-runtime/src/state/threadExecution.test.ts +A packages/client-runtime/src/state/threadExecution.ts +M packages/client-runtime/src/state/threadFeedback.test.ts +M packages/client-runtime/src/state/threadFeedback.ts +A packages/client-runtime/src/state/threadHistoryController.test.ts +A packages/client-runtime/src/state/threadHistoryController.ts +A packages/client-runtime/src/state/threadHistoryHttp.ts +A packages/client-runtime/src/state/threadHistoryMerge.test.ts +A packages/client-runtime/src/state/threadHistoryMerge.ts +D packages/client-runtime/src/state/threadReducer.test.ts +D packages/client-runtime/src/state/threadReducer.ts +A packages/client-runtime/src/state/threadRelationships.test.ts +A packages/client-runtime/src/state/threadRelationships.ts +A packages/client-runtime/src/state/threadRequests.test.ts +A packages/client-runtime/src/state/threadRequests.ts +M packages/client-runtime/src/state/threadRetention.ts +M packages/client-runtime/src/state/threadSettled.ts +A packages/client-runtime/src/state/threadShell.test.ts +M packages/client-runtime/src/state/threadShell.ts +M packages/client-runtime/src/state/threadSnapshotHttp.ts +M packages/client-runtime/src/state/threadSort.test.ts +M packages/client-runtime/src/state/threadSort.ts +M packages/client-runtime/src/state/threadState.ts +A packages/client-runtime/src/state/threadWorkflows.test.ts +A packages/client-runtime/src/state/threadWorkflows.ts +M packages/client-runtime/src/state/threads-atoms.test.ts +D packages/client-runtime/src/state/threads-pagination.test.ts +M packages/client-runtime/src/state/threads-sync.test.ts +M packages/client-runtime/src/state/threads.ts +A packages/client-runtime/src/state/turnItemPresentation.test.ts +A packages/client-runtime/src/state/turnItemPresentation.ts +M packages/client-runtime/src/state/vcsAction.test.ts +M packages/client-runtime/src/state/vcsAction.ts +A packages/client-runtime/src/t3ToolSummary.test.ts +A packages/client-runtime/src/t3ToolSummary.ts +M packages/client-runtime/src/work-log/presentation.test.ts +M packages/client-runtime/src/work-log/presentation.ts +M packages/contracts/package.json +A packages/contracts/src/applicationEvent.test.ts +A packages/contracts/src/applicationEvent.ts +M packages/contracts/src/assets.test.ts +M packages/contracts/src/assets.ts +M packages/contracts/src/baseSchemas.ts +A packages/contracts/src/chatAttachment.ts +A packages/contracts/src/checkpointDiff.ts +M packages/contracts/src/environment.ts +M packages/contracts/src/environmentHttp.ts +M packages/contracts/src/index.ts +M packages/contracts/src/ipc.ts +M packages/contracts/src/keybindings.test.ts +M packages/contracts/src/keybindings.ts +M packages/contracts/src/model.ts +A packages/contracts/src/modelSelection.ts +M packages/contracts/src/orchestration.test.ts +M packages/contracts/src/orchestration.ts +A packages/contracts/src/orchestrationProject.ts +A packages/contracts/src/orchestrationV2.test.ts +A packages/contracts/src/orchestrationV2.ts +A packages/contracts/src/orchestratorMcp.test.ts +A packages/contracts/src/orchestratorMcp.ts +M packages/contracts/src/project.ts +M packages/contracts/src/provider.ts +A packages/contracts/src/providerPolicy.ts +M packages/contracts/src/providerRuntime.ts +M packages/contracts/src/rpc.test.ts +M packages/contracts/src/rpc.ts +A packages/contracts/src/scheduledTask.test.ts +A packages/contracts/src/scheduledTask.ts +M packages/contracts/src/server.ts +M packages/contracts/src/settings.test.ts +M packages/contracts/src/settings.ts +M packages/contracts/src/t3ProjectFile.test.ts +M packages/contracts/src/t3ProjectFile.ts +A packages/contracts/src/worktreeMcp.ts +M packages/effect-acp/src/client.ts +M packages/effect-acp/src/protocol.test.ts +M packages/effect-acp/src/protocol.ts +M packages/effect-codex-app-server/package.json +M packages/effect-codex-app-server/src/client.ts +A packages/effect-codex-app-server/src/replay.test.ts +A packages/effect-codex-app-server/src/replay.ts +M packages/shared/package.json +A packages/shared/src/Array.test.ts +A packages/shared/src/Array.ts +M packages/shared/src/agentAwareness.test.ts +M packages/shared/src/agentAwareness.ts +M packages/shared/src/model.test.ts +M packages/shared/src/model.ts +M packages/shared/src/orchestrationTiming.ts +A packages/shared/src/orchestrationV2PendingBackgroundWork.test.ts +A packages/shared/src/orchestrationV2PendingBackgroundWork.ts +A packages/shared/src/orchestrationV2Timeline.test.ts +A packages/shared/src/orchestrationV2Timeline.ts +A packages/shared/src/t3McpToolPresentation.test.ts +A packages/shared/src/t3McpToolPresentation.ts +M pnpm-lock.yaml +M vite.config.ts diff --git a/audits/orchestrator-v2/2026-09-04/changed-files.tsv b/audits/orchestrator-v2/2026-09-04/changed-files.tsv new file mode 100644 index 000000000000..b74e5f541bf9 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/changed-files.tsv @@ -0,0 +1,991 @@ +D .github/scripts/thread-transfer-report.cjs +D .github/scripts/thread-transfer-report.test.cjs +M .github/workflows/ci.yml +D .github/workflows/thread-transfer-report.yml +M README.md +M apps/desktop/src/app/DesktopEnvironment.test.ts +M apps/desktop/src/backend/tailscaleEndpointProvider.ts +M apps/desktop/src/settings/DesktopClientSettings.test.ts +A apps/marketing/public/app-desktop.webp +M apps/marketing/src/pages/index.astro +M apps/mobile/generated-uniwind-themes.css +M apps/mobile/scripts/generate-uniwind-themes.mts +M apps/mobile/src/components/BrandMark.tsx +A apps/mobile/src/components/brandAssets.ts +M apps/mobile/src/connection/environment-cache-store.test.ts +M apps/mobile/src/connection/environment-cache-store.ts +M apps/mobile/src/connection/runtime.ts +M apps/mobile/src/connection/storage.ts +M apps/mobile/src/features/archive/archivedThreadList.test.ts +M apps/mobile/src/features/home/HomeScreen.tsx +M apps/mobile/src/features/home/homeListItems.test.ts +M apps/mobile/src/features/home/homeThreadList.test.ts +A apps/mobile/src/features/home/threadArchive.test.ts +A apps/mobile/src/features/home/threadArchive.ts +M apps/mobile/src/features/home/useThreadListActions.ts +M apps/mobile/src/features/keyboard/hardwareKeyboardCommands.ts +M apps/mobile/src/features/projects/AddProjectScreen.tsx +M apps/mobile/src/features/review/reviewModel.test.ts +M apps/mobile/src/features/review/reviewModel.ts +M apps/mobile/src/features/review/reviewState.test.ts +M apps/mobile/src/features/review/reviewState.ts +D apps/mobile/src/features/review/useReviewDiffPrewarming.test.ts +M apps/mobile/src/features/review/useReviewDiffPrewarming.ts +M apps/mobile/src/features/review/useReviewSections.ts +M apps/mobile/src/features/terminal/ThreadTerminalRouteScreen.tsx +M apps/mobile/src/features/threads/NewTaskDraftScreen.tsx +M apps/mobile/src/features/threads/PendingApprovalCard.tsx +M apps/mobile/src/features/threads/PendingUserInputCard.tsx +A apps/mobile/src/features/threads/ThreadActivityInspector.tsx +M apps/mobile/src/features/threads/ThreadComposer.tsx +M apps/mobile/src/features/threads/ThreadDetailScreen.tsx +M apps/mobile/src/features/threads/ThreadFeed.tsx +M apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx +A apps/mobile/src/features/threads/ThreadQueueControl.tsx +A apps/mobile/src/features/threads/ThreadRelationshipsBanner.tsx +M apps/mobile/src/features/threads/ThreadRouteScreen.tsx +A apps/mobile/src/features/threads/thread-activity-row-presentation.test.ts +A apps/mobile/src/features/threads/thread-activity-row-presentation.ts +A apps/mobile/src/features/threads/thread-feed-item-size.test.ts +A apps/mobile/src/features/threads/thread-feed-item-size.ts +M apps/mobile/src/features/threads/thread-list-v2-items.tsx +A apps/mobile/src/features/threads/threadActivityFileNavigation.test.ts +A apps/mobile/src/features/threads/threadActivityFileNavigation.ts +A apps/mobile/src/features/threads/threadForkNavigation.test.ts +A apps/mobile/src/features/threads/threadForkNavigation.ts +M apps/mobile/src/features/threads/threadListV2.test.ts +M apps/mobile/src/features/threads/threadListV2.ts +M apps/mobile/src/features/threads/threadPresentation.ts +A apps/mobile/src/features/threads/threadQueueControlPresentation.test.ts +A apps/mobile/src/features/threads/threadQueueControlPresentation.ts +A apps/mobile/src/features/threads/userMessageIntentBadge.test.ts +A apps/mobile/src/features/threads/userMessageIntentBadge.ts +M apps/mobile/src/lib/modelOptions.ts +M apps/mobile/src/lib/projectThreadStartTurn.test.ts +M apps/mobile/src/lib/projectThreadStartTurn.ts +M apps/mobile/src/lib/scopedEntities.ts +M apps/mobile/src/lib/threadActivity.test.ts +M apps/mobile/src/lib/threadActivity.ts +A apps/mobile/src/lib/threadActivityInspector.test.ts +A apps/mobile/src/lib/threadActivityInspector.ts +M apps/mobile/src/state/queries.ts +M apps/mobile/src/state/threads.ts +M apps/mobile/src/state/use-pending-new-tasks.ts +M apps/mobile/src/state/use-selected-thread-requests.ts +M apps/mobile/src/state/use-selected-thread-worktree.ts +M apps/mobile/src/state/use-thread-composer-state.ts +M apps/mobile/src/state/use-thread-detail.ts +M apps/mobile/src/state/use-thread-outbox-drain.test.ts +M apps/mobile/src/state/use-thread-outbox-drain.ts +M apps/mobile/src/state/use-thread-selection.ts +A apps/mobile/src/state/v2-item-support.ts +A apps/mobile/src/test-fixtures.ts +A apps/server/README.md +D apps/server/integration/NetworkTransferMeasurement.integration.ts +D apps/server/integration/OrchestrationEngineHarness.integration.ts +D apps/server/integration/TestProviderAdapter.integration.ts +D apps/server/integration/TransferBudgetReport.integration.ts +D apps/server/integration/TransferBudgetScenario.integration.ts +D apps/server/integration/fixtures/providerRuntime.ts +D apps/server/integration/fixtures/transferBudget.ts +D apps/server/integration/orchestrationEngine.integration.test.ts +D apps/server/integration/orphanedProviderSessionStartup.integration.test.ts +D apps/server/integration/providerService.integration.test.ts +M apps/server/package.json +M apps/server/scripts/acp-mock-agent.ts +A apps/server/scripts/acp-replay-agent.test.ts +A apps/server/scripts/acp-replay-agent.ts +A apps/server/scripts/acp-thread-spawn-helper.c +A apps/server/scripts/acpMockCancellationState.test.ts +A apps/server/scripts/acpMockCancellationState.ts +A apps/server/scripts/claudeReplayRecordingConfig.test.ts +A apps/server/scripts/claudeReplayRecordingConfig.ts +A apps/server/scripts/codexReplayRecordingRecords.test.ts +A apps/server/scripts/codexReplayRecordingRecords.ts +A apps/server/scripts/cursorReplayRecordingWorkspace.test.ts +A apps/server/scripts/cursorReplayRecordingWorkspace.ts +A apps/server/scripts/probe-claude-fork-local-rollback-replay.ts +A apps/server/scripts/record-claude-agent-sdk-replay-fixture.ts +A apps/server/scripts/record-codex-app-server-replay-fixture.ts +A apps/server/scripts/record-cursor-agent-sdk-replay-fixture.ts +A apps/server/scripts/replayRecorderDeferredRegistry.test.ts +A apps/server/scripts/replayRecorderDeferredRegistry.ts +M apps/server/src/attachmentStore.test.ts +M apps/server/src/attachmentStore.ts +M apps/server/src/auth/RpcAuthorization.ts +D apps/server/src/bin.test.ts +M apps/server/src/checkpointing/CheckpointDiffQuery.test.ts +M apps/server/src/checkpointing/CheckpointDiffQuery.ts +A apps/server/src/claudeModelOptions.test.ts +A apps/server/src/claudeModelOptions.ts +M apps/server/src/cli/project.test.ts +M apps/server/src/cli/project.ts +M apps/server/src/environment/ServerEnvironment.test.ts +M apps/server/src/environment/ServerEnvironment.ts +M apps/server/src/git/GitWorkflowService.ts +M apps/server/src/http.test.ts +M apps/server/src/httpCors.ts +M apps/server/src/mcp/McpHttpServer.ts +M apps/server/src/mcp/McpInvocationContext.ts +M apps/server/src/mcp/McpProviderSession.ts +M apps/server/src/mcp/McpSessionRegistry.test.ts +A apps/server/src/mcp/McpSessionRegistry.testkit.ts +M apps/server/src/mcp/McpSessionRegistry.ts +A apps/server/src/mcp/OrchestratorMcpService.activity.test.ts +A apps/server/src/mcp/OrchestratorMcpService.test.ts +A apps/server/src/mcp/OrchestratorMcpService.ts +A apps/server/src/mcp/OrchestratorMcpToolkit.integration.test.ts +A apps/server/src/mcp/WorktreeMcpService.test.ts +A apps/server/src/mcp/WorktreeMcpService.ts +A apps/server/src/mcp/toolkits/orchestrator/handlers.ts +A apps/server/src/mcp/toolkits/orchestrator/tools.test.ts +A apps/server/src/mcp/toolkits/orchestrator/tools.ts +A apps/server/src/mcp/toolkits/worktree/handlers.ts +A apps/server/src/mcp/toolkits/worktree/registration.test.ts +A apps/server/src/mcp/toolkits/worktree/tools.ts +M apps/server/src/observability/Metrics.ts +A apps/server/src/orchestration-v2/AcpRegistryOrchestratorV2.live.test.ts +A apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.testkit.test.ts +A apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.testkit.test.ts +A apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/CursorAgentSdk.test.ts +A apps/server/src/orchestration-v2/Adapters/CursorAgentSdk.ts +A apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.ts +A apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.test.ts +A apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.testkit.test.ts +A apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.testkit.ts +A apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.ts +A apps/server/src/orchestration-v2/AttachmentClaims.test.ts +A apps/server/src/orchestration-v2/AttachmentClaims.ts +A apps/server/src/orchestration-v2/AttachmentPrompt.test.ts +A apps/server/src/orchestration-v2/AttachmentPrompt.ts +A apps/server/src/orchestration-v2/CheckpointCaptureService.test.ts +A apps/server/src/orchestration-v2/CheckpointCaptureService.ts +A apps/server/src/orchestration-v2/CheckpointPolicy.ts +A apps/server/src/orchestration-v2/CheckpointRollbackService.test.ts +A apps/server/src/orchestration-v2/CheckpointRollbackService.ts +A apps/server/src/orchestration-v2/CheckpointService.test.ts +A apps/server/src/orchestration-v2/CheckpointService.ts +A apps/server/src/orchestration-v2/CommandPolicy.test.ts +A apps/server/src/orchestration-v2/CommandPolicy.ts +A apps/server/src/orchestration-v2/CommandReceiptStore.ts +A apps/server/src/orchestration-v2/ContextHandoffService.test.ts +A apps/server/src/orchestration-v2/ContextHandoffService.ts +A apps/server/src/orchestration-v2/CursorOrchestratorV2.live.test.ts +A apps/server/src/orchestration-v2/DelegatedCompletionDelivery.test.ts +A apps/server/src/orchestration-v2/EffectOutbox.ts +A apps/server/src/orchestration-v2/EffectWorker.test.ts +A apps/server/src/orchestration-v2/EffectWorker.ts +A apps/server/src/orchestration-v2/EventSink.ts +A apps/server/src/orchestration-v2/EventStore.ts +A apps/server/src/orchestration-v2/FoundationPersistence.test.ts +A apps/server/src/orchestration-v2/GrokOrchestratorV2.live.test.ts +A apps/server/src/orchestration-v2/IdAllocator.ts +A apps/server/src/orchestration-v2/KeyedSerialExecutor.test.ts +A apps/server/src/orchestration-v2/KeyedSerialExecutor.ts +A apps/server/src/orchestration-v2/LegacyV1ThreadImporter.test.ts +A apps/server/src/orchestration-v2/LegacyV1ThreadImporter.ts +A apps/server/src/orchestration-v2/Orchestrator.migration.test.ts +A apps/server/src/orchestration-v2/Orchestrator.ts +A apps/server/src/orchestration-v2/ProjectionMaintenance.ts +A apps/server/src/orchestration-v2/ProjectionRecovery.test.ts +A apps/server/src/orchestration-v2/ProjectionStore.test.ts +A apps/server/src/orchestration-v2/ProjectionStore.ts +A apps/server/src/orchestration-v2/ProviderAdapter.ts +A apps/server/src/orchestration-v2/ProviderAdapterDriver.ts +A apps/server/src/orchestration-v2/ProviderAdapterRegistry.test.ts +A apps/server/src/orchestration-v2/ProviderAdapterRegistry.ts +A apps/server/src/orchestration-v2/ProviderContinuationRequests.ts +A apps/server/src/orchestration-v2/ProviderContinuationService.test.ts +A apps/server/src/orchestration-v2/ProviderContinuationService.ts +A apps/server/src/orchestration-v2/ProviderEventIngestor.test.ts +A apps/server/src/orchestration-v2/ProviderEventIngestor.ts +A apps/server/src/orchestration-v2/ProviderFailure.test.ts +A apps/server/src/orchestration-v2/ProviderFailure.ts +A apps/server/src/orchestration-v2/ProviderRuntimeRecoveryService.regression.test.ts +A apps/server/src/orchestration-v2/ProviderRuntimeRecoveryService.test.ts +A apps/server/src/orchestration-v2/ProviderRuntimeRecoveryService.ts +A apps/server/src/orchestration-v2/ProviderSelectionTransition.test.ts +A apps/server/src/orchestration-v2/ProviderSelectionTransition.ts +A apps/server/src/orchestration-v2/ProviderSessionManager.test.ts +A apps/server/src/orchestration-v2/ProviderSessionManager.ts +A apps/server/src/orchestration-v2/ProviderSessionTransitionPolicy.test.ts +A apps/server/src/orchestration-v2/ProviderSessionTransitionPolicy.ts +A apps/server/src/orchestration-v2/ProviderSwitchService.test.ts +A apps/server/src/orchestration-v2/ProviderSwitchService.ts +A apps/server/src/orchestration-v2/ProviderTurnControlService.test.ts +A apps/server/src/orchestration-v2/ProviderTurnControlService.ts +A apps/server/src/orchestration-v2/ProviderTurnStartService.test.ts +A apps/server/src/orchestration-v2/ProviderTurnStartService.testkit.ts +A apps/server/src/orchestration-v2/ProviderTurnStartService.ts +A apps/server/src/orchestration-v2/ProviderTurnTokenUsage.test.ts +A apps/server/src/orchestration-v2/QueuedRunOrder.test.ts +A apps/server/src/orchestration-v2/QueuedRunOrder.ts +A apps/server/src/orchestration-v2/RandomUuid.ts +A apps/server/src/orchestration-v2/ResourceCleanupService.ts +A apps/server/src/orchestration-v2/RunExecutionService.test.ts +A apps/server/src/orchestration-v2/RunExecutionService.ts +A apps/server/src/orchestration-v2/RunFinalizationService.test.ts +A apps/server/src/orchestration-v2/RunFinalizationService.ts +A apps/server/src/orchestration-v2/RuntimePolicy.test.ts +A apps/server/src/orchestration-v2/RuntimePolicy.ts +A apps/server/src/orchestration-v2/RuntimeRequestService.test.ts +A apps/server/src/orchestration-v2/RuntimeRequestService.ts +A apps/server/src/orchestration-v2/SelectionRestart.integration.test.ts +A apps/server/src/orchestration-v2/ShellStream.test.ts +A apps/server/src/orchestration-v2/ShellStream.ts +A apps/server/src/orchestration-v2/SubagentProjection.test.ts +A apps/server/src/orchestration-v2/SubagentProjection.ts +A apps/server/src/orchestration-v2/TODO.md +A apps/server/src/orchestration-v2/ThreadForkService.test.ts +A apps/server/src/orchestration-v2/ThreadForkService.ts +A apps/server/src/orchestration-v2/ThreadLaunchService.test.ts +A apps/server/src/orchestration-v2/ThreadLaunchService.ts +A apps/server/src/orchestration-v2/ThreadLifecycleService.test.ts +A apps/server/src/orchestration-v2/ThreadLifecycleService.ts +R060 apps/server/src/orchestration/ThreadLiveEventCoalescer.test.ts apps/server/src/orchestration-v2/ThreadLiveEventCoalescer.test.ts +R062 apps/server/src/orchestration/ThreadLiveEventCoalescer.ts apps/server/src/orchestration-v2/ThreadLiveEventCoalescer.ts +A apps/server/src/orchestration-v2/ThreadManagementService.test.ts +A apps/server/src/orchestration-v2/ThreadManagementService.ts +A apps/server/src/orchestration-v2/ThreadSettlementService.test.ts +R059 apps/server/src/orchestration/ThreadSettlementReactor.ts apps/server/src/orchestration-v2/ThreadSettlementService.ts +A apps/server/src/orchestration-v2/ThreadStream.test.ts +A apps/server/src/orchestration-v2/ThreadStream.ts +A apps/server/src/orchestration-v2/ThreadTitleRegenerationService.test.ts +A apps/server/src/orchestration-v2/ThreadTitleRegenerationService.ts +A apps/server/src/orchestration-v2/TurnItemPositionStore.ts +A apps/server/src/orchestration-v2/UserFacingErrors.test.ts +A apps/server/src/orchestration-v2/UserFacingErrors.ts +A apps/server/src/orchestration-v2/V1ImportBoundary.test.ts +A apps/server/src/orchestration-v2/WireProjection.test.ts +A apps/server/src/orchestration-v2/WireProjection.ts +A apps/server/src/orchestration-v2/applicationLayer.ts +A apps/server/src/orchestration-v2/builtInProviderAdapterDrivers.ts +A apps/server/src/orchestration-v2/http.ts +A apps/server/src/orchestration-v2/runtimeLayer.test.ts +A apps/server/src/orchestration-v2/runtimeLayer.ts +A apps/server/src/orchestration-v2/testkit/ClaudeReplayFixtures.integration.test.ts +A apps/server/src/orchestration-v2/testkit/CodexReplayFixtures.integration.test.ts +A apps/server/src/orchestration-v2/testkit/DeterministicRuntime.ts +A apps/server/src/orchestration-v2/testkit/OrchestratorReplayFixtures.contract.test.ts +A apps/server/src/orchestration-v2/testkit/OrchestratorReplayFixtures.integration.test.ts +A apps/server/src/orchestration-v2/testkit/OrchestratorReplayRecovery.integration.test.ts +A apps/server/src/orchestration-v2/testkit/OrchestratorScenario.ts +A apps/server/src/orchestration-v2/testkit/ProviderReplayGate.testkit.test.ts +A apps/server/src/orchestration-v2/testkit/ProviderReplayGate.testkit.ts +A apps/server/src/orchestration-v2/testkit/ProviderReplayHarness.ts +A apps/server/src/orchestration-v2/testkit/ProviderSwitch.integration.test.ts +A apps/server/src/orchestration-v2/testkit/ReplayFixtureWorkspace.ts +A apps/server/src/orchestration-v2/testkit/ReplayTranscriptNdjson.test.ts +A apps/server/src/orchestration-v2/testkit/ReplayTranscriptNdjson.ts +A apps/server/src/orchestration-v2/testkit/ThreadFork.integration.test.ts +A apps/server/src/orchestration-v2/testkit/ThreadMergeBack.integration.test.ts +A apps/server/src/orchestration-v2/testkit/fixtures/acp_elicitation/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/claude_background_task_after_root/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/claude_background_task_after_root/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_background_task_after_root/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_idle_resume/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/claude_idle_resume/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_idle_resume/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_local_bash_task/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/claude_local_bash_task/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_local_bash_task/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_result_is_error/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/claude_result_is_error/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/claude_result_is_error/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/grok_subagent_lineage/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/grok_subagent_lineage/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/grok_subagent_lineage/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/index.ts +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/grok_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/message_steering/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/multi_turn_restart/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_child_approval/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_child_approval/opencode_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_child_approval/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_subagent/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_subagent/opencode_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/opencode_subagent/output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/opencode_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/opencode_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/provider_thread_resume/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/provider_thread_resume/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/queued_cancelled_while_active/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/queued_cancelled_while_active/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/shared.ts +A apps/server/src/orchestration-v2/testkit/fixtures/simple/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/simple/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/simple/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/simple/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/simple/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/simple/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/simple/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/simple/opencode_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/README.md +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2_nested/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2_nested/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_continue/README.md +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_continue/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_continue/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_fork_local_rollback/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_prior_turn/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_prior_turn/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_siblings/README.md +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_siblings/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_siblings/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_continue/README.md +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_continue/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_continue/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_siblings/README.md +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_siblings/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_siblings/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/grok_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/todo_list/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/grok_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/opencode_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/cursor_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/cursor_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_restart/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_restart/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_restart/input.ts +A apps/server/src/orchestration-v2/testkit/fixtures/web_search/claude_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/web_search/claude_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/web_search/codex_output.ts +A apps/server/src/orchestration-v2/testkit/fixtures/web_search/codex_transcript.ndjson +A apps/server/src/orchestration-v2/testkit/fixtures/web_search/input.ts +A apps/server/src/orchestration-v2/testkit/index.ts +A apps/server/src/orchestration-v2/threadHistoryPaging.test.ts +A apps/server/src/orchestration-v2/threadHistoryPaging.ts +D apps/server/src/orchestration/ActivityPayloadProjection.test.ts +D apps/server/src/orchestration/ActivityPayloadProjection.ts +D apps/server/src/orchestration/Layers/CheckpointReactor.test.ts +D apps/server/src/orchestration/Layers/CheckpointReactor.ts +D apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts +M apps/server/src/orchestration/Layers/OrchestrationEngine.ts +D apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts +D apps/server/src/orchestration/Layers/OrchestrationReactor.ts +A apps/server/src/orchestration/Layers/ProjectEnrichmentProjection.test.ts +D apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts +M apps/server/src/orchestration/Layers/ProjectionPipeline.ts +A apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.search.test.ts +D apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts +M apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts +D apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts +D apps/server/src/orchestration/Layers/ProviderCommandReactor.ts +D apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.activity.test.ts +D apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.approval.test.ts +D apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts +D apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts +D apps/server/src/orchestration/Layers/RuntimeReceiptBus.ts +D apps/server/src/orchestration/Layers/ThreadDeletionReactor.test.ts +D apps/server/src/orchestration/Layers/ThreadDeletionReactor.ts +M apps/server/src/orchestration/LiveStreamBudget.test.ts +M apps/server/src/orchestration/LiveStreamBudget.ts +D apps/server/src/orchestration/Normalizer.attachments.test.ts +D apps/server/src/orchestration/Normalizer.test.ts +D apps/server/src/orchestration/Normalizer.ts +M apps/server/src/orchestration/Schemas.ts +D apps/server/src/orchestration/Services/CheckpointReactor.ts +M apps/server/src/orchestration/Services/OrchestrationEngine.ts +D apps/server/src/orchestration/Services/OrchestrationReactor.ts +M apps/server/src/orchestration/Services/ProjectionPipeline.ts +M apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts +D apps/server/src/orchestration/Services/ProviderCommandReactor.ts +D apps/server/src/orchestration/Services/ProviderRuntimeIngestion.ts +D apps/server/src/orchestration/Services/RuntimeReceiptBus.ts +D apps/server/src/orchestration/Services/ThreadDeletionReactor.ts +D apps/server/src/orchestration/ThreadSettlementReactor.test.ts +D apps/server/src/orchestration/commandInvariants.test.ts +M apps/server/src/orchestration/commandInvariants.ts +D apps/server/src/orchestration/decider.delete.test.ts +M apps/server/src/orchestration/decider.ts +D apps/server/src/orchestration/http.ts +D apps/server/src/orchestration/projector.test.ts +M apps/server/src/orchestration/projector.ts +M apps/server/src/persistence/Layers/OrchestrationCommandReceipts.ts +A apps/server/src/persistence/Layers/OrchestrationEventStore.sequence.test.ts +M apps/server/src/persistence/Layers/OrchestrationEventStore.test.ts +M apps/server/src/persistence/Layers/OrchestrationEventStore.ts +M apps/server/src/persistence/Layers/ProjectionCheckpoints.ts +M apps/server/src/persistence/Layers/ProjectionTurns.ts +M apps/server/src/persistence/Migrations.ts +A apps/server/src/persistence/Migrations/048_049_OrchestrationV2.test.ts +A apps/server/src/persistence/Migrations/048_OrchestrationV2.ts +A apps/server/src/persistence/Migrations/049_OrchestrationV2Subagents.ts +A apps/server/src/persistence/Migrations/050_OrchestrationV2Foundation.test.ts +A apps/server/src/persistence/Migrations/050_OrchestrationV2Foundation.ts +A apps/server/src/persistence/Migrations/051_OrchestrationV2ProviderSessionBindings.ts +A apps/server/src/persistence/Migrations/052_OrchestrationV2ThreadLaunchWorkflows.ts +A apps/server/src/persistence/Migrations/053_ApplicationEventSource.test.ts +A apps/server/src/persistence/Migrations/053_ApplicationEventSource.ts +A apps/server/src/persistence/Migrations/054_OrchestrationV2EffectCancellation.test.ts +A apps/server/src/persistence/Migrations/054_OrchestrationV2EffectCancellation.ts +A apps/server/src/persistence/Migrations/055_ScheduledTasks.ts +A apps/server/src/persistence/Migrations/056_LegacyV1ImportState.ts +A apps/server/src/persistence/Migrations/057_ApplicationEventSequenceIndexes.ts +A apps/server/src/persistence/Migrations/058_OrchestrationV2RecoveryIndexes.ts +M apps/server/src/persistence/ProviderSessionRuntime.ts +M apps/server/src/persistence/Services/OrchestrationCommandReceipts.ts +M apps/server/src/persistence/Services/OrchestrationEventStore.ts +M apps/server/src/persistence/Services/ProjectionCheckpoints.ts +M apps/server/src/persistence/Services/ProjectionPendingApprovals.ts +M apps/server/src/persistence/Services/ProjectionThreadActivities.ts +M apps/server/src/persistence/Services/ProjectionThreadMessages.ts +M apps/server/src/persistence/Services/ProjectionThreadProposedPlans.ts +M apps/server/src/persistence/Services/ProjectionThreadSessions.ts +M apps/server/src/persistence/Services/ProjectionTurns.ts +A apps/server/src/project/ProjectEnrichmentService.test.ts +A apps/server/src/project/ProjectEnrichmentService.ts +A apps/server/src/project/ProjectService.test.ts +A apps/server/src/project/ProjectService.ts +M apps/server/src/project/ProjectSetupScriptRunner.test.ts +M apps/server/src/project/ProjectSetupScriptRunner.ts +A apps/server/src/project/http.test.ts +A apps/server/src/project/http.ts +A apps/server/src/provider/ClaudeTurnTokenUsage.ts +M apps/server/src/provider/CodexDeveloperInstructions.ts +A apps/server/src/provider/CodexToolPresentation.ts +A apps/server/src/provider/CodexTurnTokenUsage.ts +A apps/server/src/provider/Drivers/AcpRegistryDriver.ts +M apps/server/src/provider/Drivers/AntigravityDriver.test.ts +M apps/server/src/provider/Drivers/AntigravityDriver.ts +M apps/server/src/provider/Drivers/ClaudeDriver.ts +M apps/server/src/provider/Drivers/CodexDriver.ts +M apps/server/src/provider/Drivers/CursorDriver.ts +A apps/server/src/provider/Drivers/CursorSkills.test.ts +M apps/server/src/provider/Drivers/GrokDriver.ts +M apps/server/src/provider/Drivers/OpenCodeDriver.ts +M apps/server/src/provider/Errors.ts +D apps/server/src/provider/Layers/AntigravityAdapter.test.ts +D apps/server/src/provider/Layers/AntigravityAdapter.ts +D apps/server/src/provider/Layers/ClaudeAdapter.test.ts +D apps/server/src/provider/Layers/ClaudeAdapter.ts +D apps/server/src/provider/Layers/CodexAdapter.test.ts +D apps/server/src/provider/Layers/CodexAdapter.ts +D apps/server/src/provider/Layers/CursorAdapter.test.ts +D apps/server/src/provider/Layers/CursorAdapter.ts +M apps/server/src/provider/Layers/CursorProvider.test.ts +M apps/server/src/provider/Layers/CursorProvider.ts +A apps/server/src/provider/Layers/CursorSdkCatalog.ts +M apps/server/src/provider/Layers/EventNdjsonLogger.test.ts +M apps/server/src/provider/Layers/EventNdjsonLogger.ts +D apps/server/src/provider/Layers/GrokAdapter.test.ts +D apps/server/src/provider/Layers/GrokAdapter.ts +M apps/server/src/provider/Layers/GrokProvider.ts +D apps/server/src/provider/Layers/OpenCodeAdapter.test.ts +D apps/server/src/provider/Layers/OpenCodeAdapter.ts +D apps/server/src/provider/Layers/ProviderAdapterRegistry.test.ts +D apps/server/src/provider/Layers/ProviderAdapterRegistry.ts +M apps/server/src/provider/Layers/ProviderAuthService.test.ts +M apps/server/src/provider/Layers/ProviderAuthService.ts +M apps/server/src/provider/Layers/ProviderInstanceRegistryHydration.ts +M apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts +A apps/server/src/provider/Layers/ProviderOrchestrationAdapterInfrastructure.ts +M apps/server/src/provider/Layers/ProviderRegistry.test.ts +M apps/server/src/provider/Layers/ProviderRegistry.ts +D apps/server/src/provider/Layers/ProviderService.test.ts +D apps/server/src/provider/Layers/ProviderService.ts +D apps/server/src/provider/Layers/ProviderSessionDirectory.test.ts +D apps/server/src/provider/Layers/ProviderSessionDirectory.ts +D apps/server/src/provider/Layers/ProviderSessionReaper.test.ts +D apps/server/src/provider/Layers/ProviderSessionReaper.ts +M apps/server/src/provider/Layers/ProviderUsageLimitsIngestion.ts +A apps/server/src/provider/NativeProtocolLogging.ts +M apps/server/src/provider/ProviderDriver.ts +D apps/server/src/provider/Services/ClaudeAdapter.ts +D apps/server/src/provider/Services/CodexAdapter.ts +D apps/server/src/provider/Services/CursorAdapter.ts +D apps/server/src/provider/Services/GrokAdapter.ts +D apps/server/src/provider/Services/OpenCodeAdapter.ts +D apps/server/src/provider/Services/ProviderAdapter.ts +D apps/server/src/provider/Services/ProviderAdapterRegistry.ts +D apps/server/src/provider/Services/ProviderService.ts +D apps/server/src/provider/Services/ProviderSessionDirectory.ts +D apps/server/src/provider/Services/ProviderSessionReaper.ts +A apps/server/src/provider/T3OrchestrationInstructions.test.ts +A apps/server/src/provider/T3OrchestrationInstructions.ts +A apps/server/src/provider/TurnTokenUsage.test.ts +D apps/server/src/provider/acp/AcpAdapterSupport.test.ts +D apps/server/src/provider/acp/AcpAdapterSupport.ts +M apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts +M apps/server/src/provider/acp/AcpNativeLogging.ts +A apps/server/src/provider/acp/AcpRegistrySupport.test.ts +A apps/server/src/provider/acp/AcpRegistrySupport.ts +M apps/server/src/provider/acp/AcpRuntimeModel.test.ts +M apps/server/src/provider/acp/AcpRuntimeModel.ts +A apps/server/src/provider/acp/AcpSessionRuntime.processTree.test.ts +M apps/server/src/provider/acp/AcpSessionRuntime.ts +M apps/server/src/provider/acp/AntigravityAcpSupport.ts +A apps/server/src/provider/acp/AntigravityClientFiles.ts +M apps/server/src/provider/acp/AntigravityProtocol.ts +D apps/server/src/provider/acp/CursorAcpCliProbe.test.ts +D apps/server/src/provider/acp/CursorAcpExtension.test.ts +D apps/server/src/provider/acp/CursorAcpExtension.ts +D apps/server/src/provider/acp/CursorAcpSupport.test.ts +D apps/server/src/provider/acp/CursorAcpSupport.ts +M apps/server/src/provider/acp/GrokAcpCliProbe.test.ts +M apps/server/src/provider/acp/GrokAcpSupport.test.ts +M apps/server/src/provider/acp/GrokAcpSupport.ts +M apps/server/src/provider/acp/XAiAcpExtension.test.ts +M apps/server/src/provider/acp/XAiAcpExtension.ts +M apps/server/src/provider/builtInDrivers.ts +A apps/server/src/provider/cursorSdkModel.ts +M apps/server/src/provider/providerInstallation.test.ts +M apps/server/src/provider/providerMaintenanceRunner.test.ts +D apps/server/src/provider/testUtils/providerAdapterRegistryMock.ts +D apps/server/src/relay/AgentAwarenessRelay.test.ts +M apps/server/src/relay/AgentAwarenessRelay.ts +A apps/server/src/scheduledTasks/Schedule.test.ts +A apps/server/src/scheduledTasks/Schedule.ts +A apps/server/src/scheduledTasks/ScheduledTaskService.ts +D apps/server/src/server.test.ts +M apps/server/src/server.ts +M apps/server/src/serverActivation.ts +M apps/server/src/serverLifecycleEvents.test.ts +M apps/server/src/serverLifecycleEvents.ts +D apps/server/src/serverRuntimeStartup.reconcile.test.ts +M apps/server/src/serverRuntimeStartup.test.ts +M apps/server/src/serverRuntimeStartup.ts +M apps/server/src/terminal/Manager.test.ts +M apps/server/src/terminal/Manager.ts +M apps/server/src/textGeneration/CodexTextGeneration.test.ts +M apps/server/src/textGeneration/CodexTextGeneration.ts +M apps/server/src/textGeneration/CursorTextGeneration.test.ts +M apps/server/src/textGeneration/CursorTextGeneration.ts +M apps/server/src/textGeneration/TextGeneration.test.ts +M apps/server/src/vcs/GitVcsDriver.ts +M apps/server/src/vcs/GitVcsDriverCore.test.ts +M apps/server/src/vcs/GitVcsDriverCore.ts +A apps/server/src/ws.test.ts +M apps/server/src/ws.ts +D apps/server/test/ActivityPayloadProjection.test.ts +M apps/web/src/appearanceFonts.test.ts +M apps/web/src/appearanceFonts.ts +M apps/web/src/components/AppSidebarLayout.tsx +M apps/web/src/components/BranchToolbar.logic.test.ts +M apps/web/src/components/BranchToolbar.logic.ts +M apps/web/src/components/BranchToolbar.tsx +M apps/web/src/components/BranchToolbarBranchSelector.tsx +M apps/web/src/components/BranchToolbarEnvModeSelector.tsx +M apps/web/src/components/BranchToolbarEnvironmentSelector.tsx +M apps/web/src/components/ChatView.logic.test.ts +M apps/web/src/components/ChatView.logic.ts +M apps/web/src/components/ChatView.tsx +M apps/web/src/components/CommandPalette.logic.test.ts +M apps/web/src/components/CommandPalette.logic.ts +M apps/web/src/components/CommandPalette.tsx +M apps/web/src/components/DiffPanel.tsx +M apps/web/src/components/GitActionsControl.logic.test.ts +M apps/web/src/components/GitActionsControl.logic.ts +M apps/web/src/components/GitActionsControl.tsx +M apps/web/src/components/LegacySidebar.tsx +A apps/web/src/components/LegacyThreadMigrationToast.tsx +M apps/web/src/components/ProjectScriptsControl.tsx +M apps/web/src/components/RightPanelTabs.tsx +M apps/web/src/components/Sidebar.logic.test.ts +M apps/web/src/components/Sidebar.logic.ts +M apps/web/src/components/Sidebar.tsx +M apps/web/src/components/ThreadStatusIndicators.tsx +M apps/web/src/components/chat/ChangedFilesTree.test.tsx +M apps/web/src/components/chat/ChangedFilesTree.tsx +M apps/web/src/components/chat/ChatComposer.tsx +M apps/web/src/components/chat/ChatHeader.tsx +M apps/web/src/components/chat/ComposerBanner.tsx +M apps/web/src/components/chat/ComposerBannerStack.tsx +M apps/web/src/components/chat/ComposerPendingApprovalActions.test.tsx +M apps/web/src/components/chat/ComposerPendingApprovalActions.tsx +M apps/web/src/components/chat/ComposerPendingApprovalPanel.test.tsx +M apps/web/src/components/chat/ComposerPendingApprovalPanel.tsx +M apps/web/src/components/chat/ComposerPendingUserInputPanel.test.tsx +M apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx +M apps/web/src/components/chat/ComposerPrimaryActions.test.tsx +M apps/web/src/components/chat/ComposerPrimaryActions.tsx +M apps/web/src/components/chat/ComposerServerUpdateStatus.tsx +D apps/web/src/components/chat/ContextWindowMeter.test.tsx +M apps/web/src/components/chat/MessagesTimeline.logic.test.ts +M apps/web/src/components/chat/MessagesTimeline.logic.ts +M apps/web/src/components/chat/MessagesTimeline.test.tsx +M apps/web/src/components/chat/MessagesTimeline.tsx +A apps/web/src/components/chat/OpenInPicker.logic.ts +R073 apps/web/src/components/chat/ChatHeader.test.ts apps/web/src/components/chat/OpenInPicker.test.ts +M apps/web/src/components/chat/OpenInPicker.tsx +A apps/web/src/components/chat/OpenInPickerShortcut.ts +M apps/web/src/components/chat/PanelLayoutControls.tsx +M apps/web/src/components/chat/ProposedPlanCard.tsx +A apps/web/src/components/chat/QueuedRunsControl.test.tsx +A apps/web/src/components/chat/QueuedRunsControl.tsx +A apps/web/src/components/chat/ThreadAutomationsPanel.tsx +A apps/web/src/components/chat/ThreadDetailsPanel.test.tsx +A apps/web/src/components/chat/ThreadDetailsPanel.tsx +A apps/web/src/components/chat/ThreadDetailsPrRow.tsx +A apps/web/src/components/chat/ThreadRelationshipsControl.test.tsx +A apps/web/src/components/chat/ThreadRelationshipsControl.tsx +A apps/web/src/components/chat/TimelineSystemDivider.tsx +A apps/web/src/components/chat/V2ItemInspector.tsx +A apps/web/src/components/chat/V2LifecycleRow.tsx +A apps/web/src/components/chat/composerDispatch.test.ts +A apps/web/src/components/chat/composerDispatch.ts +M apps/web/src/components/chat/externalLinkContextMenu.test.ts +M apps/web/src/components/chat/externalLinkContextMenu.ts +A apps/web/src/components/chat/threadDetailsPanelStyles.ts +M apps/web/src/components/chat/useAssistantCitationTarget.ts +M apps/web/src/components/files/FilePreviewPanel.tsx +M apps/web/src/components/preview/PreviewPanelShell.tsx +M apps/web/src/components/preview/ThreadPreviewMiniPlayer.tsx +M apps/web/src/components/preview/addBrowserSurface.test.ts +M apps/web/src/components/preview/previewMiniPlayerLayout.test.ts +M apps/web/src/components/preview/previewMiniPlayerLayout.ts +M apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx +M apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts +M apps/web/src/components/pullRequest/pullRequestDetail.logic.ts +M apps/web/src/components/pullRequest/pullRequestPresentation.tsx +A apps/web/src/components/pullRequest/usePullRequestActions.ts +M apps/web/src/components/settings/AddProviderInstanceDialog.tsx +M apps/web/src/components/settings/KeybindingsSettings.logic.test.ts +M apps/web/src/components/settings/ProviderInstanceCard.test.ts +M apps/web/src/components/settings/ProviderInstanceCard.tsx +M apps/web/src/components/settings/ProviderSettingsForm.test.ts +A apps/web/src/components/settings/ScheduledTasksSettings.tsx +M apps/web/src/components/settings/SettingsPanels.tsx +M apps/web/src/components/settings/SettingsSidebarNav.tsx +M apps/web/src/components/settings/providerDriverMeta.ts +M apps/web/src/components/settings/settingsSearch.test.ts +M apps/web/src/components/settings/settingsSearch.ts +M apps/web/src/components/ui/popover.tsx +M apps/web/src/composerDraftStore.ts +M apps/web/src/connection/runtime.ts +M apps/web/src/connection/storage.ts +M apps/web/src/diffFileActions.test.ts +M apps/web/src/diffPanelStore.test.ts +M apps/web/src/diffPanelStore.ts +A apps/web/src/hooks/useElementWidth.ts +M apps/web/src/hooks/useHandleNewThread.ts +A apps/web/src/hooks/usePreviewPanelInlineSize.ts +M apps/web/src/hooks/useThreadActionMenu.ts +M apps/web/src/hooks/useThreadActions.ts +A apps/web/src/hooks/useThreadVisitedMigration.ts +M apps/web/src/hooks/useTurnDiffSummaries.ts +M apps/web/src/index.css +M apps/web/src/keybindings.test.ts +M apps/web/src/keybindings.ts +M apps/web/src/lib/contextWindow.test.ts +M apps/web/src/lib/contextWindow.ts +A apps/web/src/lib/orchestrationV2Timeline.test.ts +A apps/web/src/lib/orchestrationV2Timeline.ts +M apps/web/src/lib/threadSort.test.ts +M apps/web/src/pendingUserInput.test.ts +M apps/web/src/pendingUserInput.ts +M apps/web/src/providerInstances.test.ts +M apps/web/src/providerInstances.ts +A apps/web/src/providerUpdateDismissal.test.ts +M apps/web/src/providerUpdateDismissal.ts +A apps/web/src/rightPanelLayout.test.ts +M apps/web/src/rightPanelLayout.ts +M apps/web/src/rightPanelStore.test.ts +M apps/web/src/rightPanelStore.ts +M apps/web/src/routeTree.gen.ts +M apps/web/src/routes/__root.tsx +M apps/web/src/routes/_chat.$environmentId.$threadId.tsx +M apps/web/src/routes/_chat.draft.$draftId.tsx +M apps/web/src/routes/_chat.pull-requests.tsx +A apps/web/src/routes/settings.scheduled-tasks.tsx +D apps/web/src/session-logic.command-output.test.ts +M apps/web/src/session-logic.test.ts +M apps/web/src/session-logic.ts +M apps/web/src/state/entities.ts +M apps/web/src/state/queries.ts +M apps/web/src/state/server.ts +M apps/web/src/state/sourceControlActions.ts +D apps/web/src/state/terminalSessions.test.ts +M apps/web/src/state/terminalSessions.ts +M apps/web/src/state/threads.ts +A apps/web/src/state/v2ItemSupport.ts +A apps/web/src/state/waitForAtomValue.test.ts +A apps/web/src/state/waitForAtomValue.ts +A apps/web/src/test-fixtures.ts +M apps/web/src/threadRoutes.test.ts +M apps/web/src/threadRoutes.ts +M apps/web/src/threadSync.test.ts +M apps/web/src/timestampFormat.test.ts +M apps/web/src/timestampFormat.ts +M apps/web/src/types.ts +M apps/web/src/uiStateStore.test.ts +M apps/web/src/versionSkew.test.ts +M apps/web/src/versionSkew.ts +M apps/web/src/worktreeCleanup.test.ts +M docs/README.md +M docs/internals/connection-runtime.md +A docs/internals/context-handoffs.md +A docs/internals/legacy-orchestration-migration.md +M docs/internals/overview.md +A docs/internals/performance-regressions.md +M docs/internals/providers.md +M docs/internals/terminal-runtime.md +A docs/orchestration-v2/README.md +A docs/orchestration-v2/core-graph-and-data-model.md +A docs/orchestration-v2/entity-ids-and-correlation.md +A docs/orchestration-v2/feature-lifecycles.md +A docs/orchestration-v2/orchestrator-mcp-server.md +A docs/orchestration-v2/provider-capability-system.md +A docs/orchestration-v2/provider-switching-and-context.md +A docs/orchestration-v2/testing-strategy.md +A docs/orchestration-v2/thread-lineage-and-context-transfer.md +A docs/user/activity-log.md +A docs/user/appearance.md +M docs/user/composer.md +A docs/user/cursor.md +A docs/user/portable-handoffs.md +D docs/user/terminal.md +A docs/user/thread-migration.md +M docs/user/updating.md +M infra/relay/src/http/Api.test.ts +M infra/relay/src/http/Api.ts +M infra/relay/src/worker.ts +M package.json +M packages/client-runtime/package.json +A packages/client-runtime/src/connection/compatibility.test.ts +A packages/client-runtime/src/connection/compatibility.ts +M packages/client-runtime/src/connection/registry.test.ts +M packages/client-runtime/src/connection/resolver.test.ts +M packages/client-runtime/src/connection/resolver.ts +M packages/client-runtime/src/operations/commands.test.ts +M packages/client-runtime/src/operations/commands.ts +M packages/client-runtime/src/operations/index.ts +M packages/client-runtime/src/operations/projects.test.ts +M packages/client-runtime/src/operations/projects.ts +A packages/client-runtime/src/operations/threadTitle.test.ts +A packages/client-runtime/src/operations/threadTitle.ts +M packages/client-runtime/src/platform/index.ts +A packages/client-runtime/src/platform/orchestrationCache.test.ts +A packages/client-runtime/src/platform/orchestrationCache.ts +M packages/client-runtime/src/platform/persistence.ts +M packages/client-runtime/src/rpc/client.ts +M packages/client-runtime/src/state/archivedThreads.test.ts +M packages/client-runtime/src/state/archivedThreads.ts +A packages/client-runtime/src/state/boundedThreadSnapshotHttp.test.ts +A packages/client-runtime/src/state/boundedThreadSnapshotHttp.ts +M packages/client-runtime/src/state/entities.test.ts +A packages/client-runtime/src/state/environmentHttpAuth.test.ts +M packages/client-runtime/src/state/environmentHttpAuth.ts +A packages/client-runtime/src/state/itemSupport.test.ts +A packages/client-runtime/src/state/itemSupport.ts +M packages/client-runtime/src/state/models.ts +M packages/client-runtime/src/state/orchestration.ts +A packages/client-runtime/src/state/orchestrationV2Projection.test.ts +A packages/client-runtime/src/state/orchestrationV2Projection.ts +A packages/client-runtime/src/state/orchestrationV2TestFixtures.ts +M packages/client-runtime/src/state/projectEntities.ts +M packages/client-runtime/src/state/server.ts +M packages/client-runtime/src/state/shell-sync.test.ts +M packages/client-runtime/src/state/shell.test.ts +M packages/client-runtime/src/state/shell.ts +M packages/client-runtime/src/state/shellReducer.test.ts +M packages/client-runtime/src/state/shellReducer.ts +M packages/client-runtime/src/state/shellSnapshotHttp.ts +M packages/client-runtime/src/state/snapshots.ts +M packages/client-runtime/src/state/subagentRuntime.ts +A packages/client-runtime/src/state/threadCheckpoints.ts +M packages/client-runtime/src/state/threadCommands.ts +A packages/client-runtime/src/state/threadDetail.test.ts +M packages/client-runtime/src/state/threadDetail.ts +A packages/client-runtime/src/state/threadExecution.test.ts +A packages/client-runtime/src/state/threadExecution.ts +M packages/client-runtime/src/state/threadFeedback.test.ts +M packages/client-runtime/src/state/threadFeedback.ts +A packages/client-runtime/src/state/threadHistoryController.test.ts +A packages/client-runtime/src/state/threadHistoryController.ts +A packages/client-runtime/src/state/threadHistoryHttp.ts +A packages/client-runtime/src/state/threadHistoryMerge.test.ts +A packages/client-runtime/src/state/threadHistoryMerge.ts +D packages/client-runtime/src/state/threadReducer.test.ts +D packages/client-runtime/src/state/threadReducer.ts +A packages/client-runtime/src/state/threadRelationships.test.ts +A packages/client-runtime/src/state/threadRelationships.ts +A packages/client-runtime/src/state/threadRequests.test.ts +A packages/client-runtime/src/state/threadRequests.ts +M packages/client-runtime/src/state/threadRetention.ts +M packages/client-runtime/src/state/threadSettled.ts +A packages/client-runtime/src/state/threadShell.test.ts +M packages/client-runtime/src/state/threadShell.ts +M packages/client-runtime/src/state/threadSnapshotHttp.ts +M packages/client-runtime/src/state/threadSort.test.ts +M packages/client-runtime/src/state/threadSort.ts +M packages/client-runtime/src/state/threadState.ts +A packages/client-runtime/src/state/threadWorkflows.test.ts +A packages/client-runtime/src/state/threadWorkflows.ts +M packages/client-runtime/src/state/threads-atoms.test.ts +D packages/client-runtime/src/state/threads-pagination.test.ts +M packages/client-runtime/src/state/threads-sync.test.ts +M packages/client-runtime/src/state/threads.ts +A packages/client-runtime/src/state/turnItemPresentation.test.ts +A packages/client-runtime/src/state/turnItemPresentation.ts +M packages/client-runtime/src/state/vcsAction.test.ts +M packages/client-runtime/src/state/vcsAction.ts +A packages/client-runtime/src/t3ToolSummary.test.ts +A packages/client-runtime/src/t3ToolSummary.ts +M packages/client-runtime/src/work-log/presentation.test.ts +M packages/client-runtime/src/work-log/presentation.ts +M packages/contracts/package.json +A packages/contracts/src/applicationEvent.test.ts +A packages/contracts/src/applicationEvent.ts +M packages/contracts/src/assets.test.ts +M packages/contracts/src/assets.ts +M packages/contracts/src/baseSchemas.ts +A packages/contracts/src/chatAttachment.ts +A packages/contracts/src/checkpointDiff.ts +M packages/contracts/src/environment.ts +M packages/contracts/src/environmentHttp.ts +M packages/contracts/src/index.ts +M packages/contracts/src/ipc.ts +M packages/contracts/src/keybindings.test.ts +M packages/contracts/src/keybindings.ts +M packages/contracts/src/model.ts +A packages/contracts/src/modelSelection.ts +M packages/contracts/src/orchestration.test.ts +M packages/contracts/src/orchestration.ts +A packages/contracts/src/orchestrationProject.ts +A packages/contracts/src/orchestrationV2.test.ts +A packages/contracts/src/orchestrationV2.ts +A packages/contracts/src/orchestratorMcp.test.ts +A packages/contracts/src/orchestratorMcp.ts +M packages/contracts/src/project.ts +M packages/contracts/src/provider.ts +A packages/contracts/src/providerPolicy.ts +M packages/contracts/src/providerRuntime.ts +M packages/contracts/src/rpc.test.ts +M packages/contracts/src/rpc.ts +A packages/contracts/src/scheduledTask.test.ts +A packages/contracts/src/scheduledTask.ts +M packages/contracts/src/server.ts +M packages/contracts/src/settings.test.ts +M packages/contracts/src/settings.ts +M packages/contracts/src/t3ProjectFile.test.ts +M packages/contracts/src/t3ProjectFile.ts +A packages/contracts/src/worktreeMcp.ts +M packages/effect-acp/src/client.ts +M packages/effect-acp/src/protocol.test.ts +M packages/effect-acp/src/protocol.ts +M packages/effect-codex-app-server/package.json +M packages/effect-codex-app-server/src/client.ts +A packages/effect-codex-app-server/src/replay.test.ts +A packages/effect-codex-app-server/src/replay.ts +M packages/shared/package.json +A packages/shared/src/Array.test.ts +A packages/shared/src/Array.ts +M packages/shared/src/agentAwareness.test.ts +M packages/shared/src/agentAwareness.ts +M packages/shared/src/model.test.ts +M packages/shared/src/model.ts +M packages/shared/src/orchestrationTiming.ts +A packages/shared/src/orchestrationV2PendingBackgroundWork.test.ts +A packages/shared/src/orchestrationV2PendingBackgroundWork.ts +A packages/shared/src/orchestrationV2Timeline.test.ts +A packages/shared/src/orchestrationV2Timeline.ts +A packages/shared/src/t3McpToolPresentation.test.ts +A packages/shared/src/t3McpToolPresentation.ts +M pnpm-lock.yaml +M vite.config.ts diff --git a/audits/orchestrator-v2/2026-09-04/clients.md b/audits/orchestrator-v2/2026-09-04/clients.md new file mode 100644 index 000000000000..40c703ead74f --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/clients.md @@ -0,0 +1,157 @@ +# Client parity and regression audit, 2026-09-04 + +## Result + +The committed client surface still has two previously reported correctness defects: F09 silently drops newly attached generic files from queued-message edits, and F10 hides every non-image attachment in the mobile V2 feed. F02 and F17 are fixed in committed HEAD. D02 remains an unresolved ownership decision, and D07 remains the deliberate compact mobile queue surface even after the large composer port. + +I found four additional differences from the frozen main tree. Three are current-main-only performance fixes that have not yet been incorporated, not rebase regressions: immediate thread-stream release from [#9740](https://github.com/pingdotgg/t3code/pull/9740), indexed terminal metadata from [#9747](https://github.com/pingdotgg/t3code/pull/9747), and the bounded mobile parsed-review cache from [#9749](https://github.com/pingdotgg/t3code/pull/9749). The fourth is the current-main-only trailing-activity fold fix from [#9739](https://github.com/pingdotgg/t3code/pull/9739). Main lag is kept separate from lost earlier ports throughout this report. + +Review anchors: + +- committed branch: `8af5734365f7c45bc08b57066dbae42f9f7d4235` +- frozen main: `d7cf8aaa8d4fbcbdd523b4f4bc86fda5c47b4a70` +- merge base: `c8f77e0d441264efb0acfac312e852c81ae3da83` +- previous audit branch/main: `d2f1f511f4cc833bc930d6c355cd0f9b61e835a0` / `57a66608b918d673eeec7e6c94ea5906b756fcd0` + +Committed evidence was read with `git show :`. Local-only evidence came from the `.snapshot` files named by `worktree-manifest.json`. All scoped overlay, manifest, and live-worktree hashes matched before the local tests ran. + +## Open committed findings + +### F09, P1: queued-message edits still discard newly attached generic files + +`apps/web/src/components/ChatView.tsx:6596-6610` reads both `images` and `files` from the real composer. Once queued edit mode is active, however, the save path copies only `composerImages` into `newEditImages` at `:6644-6649`. Its attachment-only guard checks original attachments and new images, but not `composerFiles`, at `:6650-6655`. It uploads only `newEditImages` at `:6659-6667`, sends original attachments plus those image uploads at `:6668-6677`, then clears the whole edit draft at `:6684-6688`. + +The actual caller does not disable generic attachment input during editing. `ChatView` points `ChatComposer` at the queued-edit draft and passes ordinary attachment capability props at `:8400-8410`; the queue editor is selected at `:8421-8430`. The editor even renders the original attachment set at `:8508-8510`. Therefore: + +- A file-only new edit with no text, original attachment, or image cannot be saved because the guard returns. +- If text or an image makes the edit sendable, the command succeeds without the generic file and the subsequent draft clear destroys the local selection. +- If another client starts or cancels the queued run first, the recovery effect calls the file-capable `moveComposerPromptAndImages` helper, but its dirtiness check ignores files at `:3540-3547`. A file-only unsaved edit therefore takes the clearing branch at `:3555-3560`. The helper itself demonstrably supports `source.files` and writes them to the destination in `apps/web/src/composerDraftStore.ts:3911-4000`; the caller never reaches it for that state. + +Existing committed queue tests verify thumbnails, optimistic-row removal, and keeping the source row visible while editing. They do not submit a generic file or exercise file-only external-start recovery. Main has no equivalent queued editor, so this is a bug in the V2 branch feature rather than a lost main port. + +### F10, P1: mobile V2 feed still filters out non-image attachments + +`apps/mobile/src/features/threads/ThreadFeed.tsx:1508-1516` derives the attachment list for every message with `attachment.type === "image"`. Both user and assistant branches then contain correct file and unknown renderers at `:1569-1590` and `:1657-1678`, but those branches are unreachable because the shared list has already discarded files, PDFs, videos, and unknown attachment kinds. + +Frozen main uses `message.attachments ?? []` without the filter at `apps/mobile/src/features/threads/ThreadFeed.tsx:1407-1414`. Mobile attachment upload and persisted V2 projections can therefore contain a valid non-image attachment that survives transport but has no visible message chip or preview entry after reopening the thread. This remains a committed branch regression, independent of D07's compact queue controls. + +## New provisional findings + +### CLIENT-01, P1 performance: shared thread streams remain live for five minutes after their last consumer + +This is a current-main-only parity gap, not a rebase regression. In committed HEAD, `packages/client-runtime/src/state/threadRetention.ts:1-3` explicitly retains stream-backed state for five minutes. Every derived detail atom uses that TTL at `packages/client-runtime/src/state/threadDetail.ts:20-73`, and the raw `environment-thread-state` atom also uses it at `packages/client-runtime/src/state/threads.ts:687-696`. + +Trigger: open a thread detail or mount any detail/status consumer, then navigate away. The atom remains mounted during its idle TTL, so the `subscribeThread` stream and its in-memory projection continue receiving events for up to five minutes. Repeated navigation can accumulate one live stream per recently visited thread on web, desktop, or mobile. Remote and relay connections pay the same unnecessary event traffic and server projection work. No multiplier or measured byte count is claimed. + +Frozen main's [#9740](https://github.com/pingdotgg/t3code/pull/9740) splits these lifetimes. Derived and live atoms use `Atom.setIdleTTL(0)` in `threadDetail.ts:75-82` and `threads.ts:827-844`, so the last consumer closes the stream immediately. A distinct resume atom retains only a warm snapshot/cursor for five minutes at `threads.ts:816-825`. Main's behavioral tests close the first stream at last unmount and reopen from the retained sequence without another HTTP load. The branch's existing `threads-atoms.test.ts:12-22` instead codifies the old five-minute live retention. + +This mechanism is separate from live-event coalescing and snapshot size. The committed server now calls `coalesceThreadLiveStream` at `apps/server/src/ws.ts:813-834`, which reduces update frequency while a stream exists. It does not end unused streams. F16 is also separate: it concerns an unbounded single fallback snapshot outside the coalesced event path. + +### CLIENT-02, P2 performance: each terminal-status consumer rescans and resorts all environment metadata + +This is also a current-main-only parity gap. `apps/web/src/state/terminalSessions.ts:51-82` filters, maps, allocates, and numerically sorts the entire environment terminal array inside every `useKnownTerminalSessions` consumer whenever the metadata snapshot changes. `useThreadRunningTerminalIds` immediately performs another selection at `:85-90`. + +The operation is not confined to one chat view. It is called from sidebar rows (`apps/web/src/components/Sidebar.tsx:826` and `:1763`), legacy sidebar rows (`apps/web/src/components/LegacySidebar.tsx:386`), every command-palette thread row through `ThreadRowTrailingStatus` (`apps/web/src/components/ThreadStatusIndicators.tsx:671-675` and `CommandPalette.tsx:1189`), and several `ChatView` consumers. A terminal metadata update therefore does repeated O(terminal count) scans, conversions, sorts, and fresh-array publication across the number of mounted rows. The local command-palette patch bounds VCS and linked-PR reads only; trailing terminal consumers remain on this committed implementation. + +Frozen main's [#9747](https://github.com/pingdotgg/t3code/pull/9747) builds one WeakMap-backed ordered index per immutable metadata snapshot, groups summaries by thread once, and reuses unaffected group/session identities in `apps/web/src/state/terminalSessions.ts:20-121`. Its test at `terminalSessions.test.ts:152-170` verifies that 40 thread selectors cause exactly one traversal of the 40-entry source array. The branch has no equivalent selector or test. + +### CLIENT-03, P1 performance: mobile parsed review diffs are retained and prewarmed without a bound + +This is a current-main-only parity gap. Committed `apps/mobile/src/features/review/reviewState.ts:90-95` creates a keep-alive family entry for every `threadKey:sectionId`. `getCachedReviewParsedDiff` stores both the normalized source string and full parsed structure in that permanent entry at `:259-281`. `useReviewDiffPrewarming` collects every loaded non-selected section at `apps/mobile/src/features/review/useReviewDiffPrewarming.ts:58-65` and schedules all of them at `:70-93`. + +Trigger: browse review sections across multiple threads, especially large diffs. Each distinct section can retain its source and parsed representation for the app-registry lifetime, and idle prewarming eagerly creates entries for all loaded sections. The native review adapter is keyed by these parsed objects, so permanent parsed ownership also prevents those associated native-data entries from becoming collectible. On memory-constrained mobile devices, the retained working set grows with review history rather than an explicit budget. No heap-size estimate is claimed. + +Frozen main's [#9749](https://github.com/pingdotgg/t3code/pull/9749) replaces the family with one registry-local LRU-style cache capped at eight diffs and 4 MiB of source characters (`reviewState.ts:90-104`, `:291-327`). It skips oversized inputs and prewarms only nearby sections that fit the same budget (`useReviewDiffPrewarming.ts:38-99`). + +### CLIENT-04, P2 presentation: one ordinary late activity remains outside an otherwise settled fold + +This is the fourth current-main-only gap. Committed `apps/web/src/components/chat/MessagesTimeline.logic.ts:639-643` deliberately leaves work arriving after the terminal assistant message visible. The fold loop at `:719-731` skips every non-compaction entry after that message, including the common case where exactly one successful ordinary tool activity lands late. + +The consequence is a detached tool row below a settled assistant response even though the rest of that turn is behind its `Worked for ...` fold. Failures, interrupted work, persistent resources, and multi-row trailing groups should remain explicit; the concrete mismatch is the single non-failed activity case. Frozen main's [#9739](https://github.com/pingdotgg/t3code/pull/9739) admits exactly that one case into the fold while retaining the safeguards for failures and larger groups. This is user-visible clutter, not lost data. + +## Prior-ID status + +| ID | Frozen committed status | Evidence and classification | +| --- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| F02 | **Resolved** | `EMPTY_PROVIDER_ENTRIES` is now module-scoped at `apps/web/src/components/Sidebar.tsx:209-212`, before uses at `:3854-3857` and `:3974-3977`. There is no render-time TDZ. This is a committed fix, not only a dirty-overlay change. | +| F09 | **Open, P1** | The queued save/recovery callers still ignore `composerFiles`; detailed above. Committed defect. | +| F10 | **Open, P1** | Mobile still filters the shared message attachment list to images before dispatching to file renderers. Committed regression from main. | +| F17 | **Resolved** | `AssistantMarkdownContent` now splits artifact templates, transforms Codex citations, and passes the scoped image renderer at `apps/mobile/src/features/threads/ThreadFeed.tsx:824-870`. Active assistant rows call it with `onUseArtifactTemplate` and `renderMarkdownImage` at `:1647-1655`. `ThreadDetailScreen` appends selected templates into the composer at `apps/mobile/src/features/threads/ThreadDetailScreen.tsx:655-669` and passes the callback into the feed at `:722-755`. This is committed. No focused component test currently proves all three behaviors together. | +| D02 | **Still open decision** | Normal web inherited assistant messages use the timeline's active `ctx.threadRef`/`markdownCwd` at `MessagesTimeline.tsx:1713-1736`; inherited proposed plans use the same active values at `:1899-1914`. Inspector reasoning is different and explicitly builds a ref from `projectedItem.sourceThreadId` at `V2ItemInspector.tsx:132-142`. Mobile builds all Markdown link/image handlers from the active screen `environmentId`, `threadId`, and `workspaceRoot` at `ThreadFeed.tsx:2139-2180` and `:2256-2303`. Thus ordinary inherited message/plan links still resolve against the active fork, not the source worktree. Main has no inherited-row oracle. Decide source-history ownership versus current-fork ownership before changing it. | +| D07 | **Retained intentional difference** | The active-thread mobile queue still exposes reorder, steer, and cancel only in `ThreadQueueControl.tsx:18-149`. Shared workflow state carries queued attachments (`packages/client-runtime/src/state/threadWorkflows.ts:21-25`, `:100-113`), but the mobile row destructures only `run` and `text` and renders no edit action or thumbnail. The large composer port added full editing for pending new-task outbox entries in `NewTaskDraftScreen`, not for server-projected queued runs. This is a surface choice, not a new regression. | + +Root's cross-domain status is recorded without re-auditing ownership here: F13 remains an error-without-timestamp settlement case, F14 improved, F15 is fixed, and F16 remains open. F15's separate startup verification scan is an accepted performance tradeoff. The client-side F16 consequence is precise: committed `packages/client-runtime/src/state/threads.ts:643-647` sends no `turnLimit`, and a fallback snapshot replaces state without a usable progressive-history cursor. The healthy bounded HTTP path and committed live-event coalescer are not affected by that statement. + +## Old bot lead disposition + +- **Stopped/cancelled tools shown as green Completed: rejected.** `apps/web/src/session-logic.ts:481-498` maps cancelled and interrupted V2 items to `stopped`. `workEntryIndicatesToolSuccess` excludes `stopped` and `idle` at `:270-285`; the neutral-status path handles the remainder. A settled neutral row may be omitted by folding, but the current source does not relabel it as a successful green completion. +- **Server-thread environment selector appears actionable but can no-op: source-confirmed in both trees, not elevated as a V2 parity finding.** Committed `ChatView.tsx:3358-3374` allows the callback only when `draftId` exists, while `:8539-8545` passes it whenever multiple environments exist. An empty server-backed thread with no live runtime can therefore render an unlocked selector whose callback returns. Frozen main has the same shape at `ChatView.tsx:3145-3165` and `:8047-8053`. It is a shared pre-existing edge case, most reachable through externally created/imported/failed empty threads because ordinary new-thread navigation uses a draft route. + +## Frozen-main feature matrix + +| Main change | Equivalent V2 behavior at frozen HEAD | Classification | +| ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | +| [#9740](https://github.com/pingdotgg/t3code/pull/9740), stop unused thread streams | **Missing.** Live and derived atoms retain five-minute TTLs. | CLIENT-01, main-only catch-up required. | +| [#9744](https://github.com/pingdotgg/t3code/pull/9744), update notice refinement | Base update notice exists; the narrower banner threshold, tooltip truncation, and download icon are not present. | Main-only visual polish, no correctness finding. No UI rendering performed. | +| [#9627](https://github.com/pingdotgg/t3code/pull/9627), link PR author profiles | Author avatar/name render, but no non-bot GitHub profile URL is exposed. | Main-only feature omission, low-risk and not V2-specific. | +| [#9748](https://github.com/pingdotgg/t3code/pull/9748), bound terminal history by bytes | Server-owned and outside this domain. Its client attach payload consequences are covered by root. | Excluded here. | +| [#9747](https://github.com/pingdotgg/t3code/pull/9747), index terminal metadata | **Missing.** Every row consumer still filters/maps/sorts. | CLIENT-02, main-only catch-up required. | +| [#9749](https://github.com/pingdotgg/t3code/pull/9749), bound mobile parsed review cache | **Missing.** Keep-alive per-section cache and all-section prewarm remain. | CLIENT-03, main-only catch-up required. | +| [#9743](https://github.com/pingdotgg/t3code/pull/9743), project settings from new-thread header | The command palette already offers contextual Project settings at `CommandPalette.tsx:1748-1769`, and sidebar project settings remain. `ChatHeader` has the callback surface, but frozen `ChatView` does not wire it for a draft; main does. | Main-only entry-point shortcut, not a loss of all access. | +| [#9739](https://github.com/pingdotgg/t3code/pull/9739), fold one late activity | **Missing.** All ordinary post-message activity stays outside the fold. | CLIENT-04, main-only catch-up required. | + +Fresh checks against earlier post-audit main work also found equivalent branch-specific implementations rather than treating file differences as omissions. Streaming assistant row reuse from [#9725](https://github.com/pingdotgg/t3code/pull/9725) is represented by `deriveMessagesTimelineRowsWithState` and V2 provenance-aware streaming replacement in `MessagesTimeline.logic.ts:1331-1429` and `session-logic.ts:844-880`. Thread-list identity reuse from [#9716](https://github.com/pingdotgg/t3code/pull/9716) is present through the WeakMap-backed scoped-shell cache and stable grouped arrays in `packages/client-runtime/src/state/threadShell.ts:34-170`. Recent desktop browser-profile/import, SSH-resolution, and screenshot-failure IPC contracts and handlers are also present in frozen HEAD. These are not findings. + +## Bounded six-port caller sweep + +This follow-up was source-only against frozen committed HEAD. It traces the active V2 callers but does not claim runtime or rendered-UI verification. All six named main changes retain equivalent behavior; differing files reflect later V2 work rather than dropped ports. + +- [#9713](https://github.com/pingdotgg/t3code/pull/9713), file-backed mobile image drafts: **retained**. `attachmentUpload.ts:192-226` reads file-backed images when the legacy inline path needs bytes, and `:312-322` waits for that conversion before returning `ready`. The immediate new-thread caller waits on `prepareTurnAttachments` at `use-project-actions.ts:83-107` and sends only `prepared.attachments` at `:131-151`. The offline and queued caller does the same at `use-thread-outbox-drain.ts:118-155`, `:697-706`, and `:874-884`. `projectThreadStartTurn.ts:15-53` no longer has a fallback that treats an absent inline `dataUrl` as ready. +- [#9718](https://github.com/pingdotgg/t3code/pull/9718), hidden terminal rendering: **retained active caller**. The V2 right-panel terminal passes `rightPanelOpen` into `PersistentThreadTerminalPanel` at `ChatView.tsx:7910-7927`, and that panel passes `visible` into `ThreadTerminalDrawer` at `:1165-1283`. The otherwise shared drawer calls the terminal surface's visibility gate and suppresses hidden focus and fit work at `ThreadTerminalDrawer.tsx:438-489` and `:913-943`; both split and single viewports receive the flag at `:1492-1543`. The changed `ChatView` layout did not strand the unchanged terminal gate. +- [#9709](https://github.com/pingdotgg/t3code/pull/9709), continuous chat status animation removal: **retained**. The running update icon is static at `ComposerServerUpdateStatus.tsx:9-20`. V2 setup, compaction, working, and thinking rows render static text or icons at `MessagesTimeline.tsx:2541-2584`, and `LiveActivityRow` has no shimmer overlay at `:2588-2608`. The removed `live-activity-focus` and ultrathink animation utilities have no active caller or definition in frozen HEAD. The remaining timer text update is not a CSS animation. +- [#9127](https://github.com/pingdotgg/t3code/pull/9127), desktop preview-capture failure unlock: **retained end to end**. Desktop reports `screenshotFailed` when crop capture fails at `apps/desktop/src/preview/Manager.ts:2473-2487`, and the IPC schema carries it at `packages/contracts/src/ipc.ts:936-947`. The renderer bounds its own crop conversion to five seconds at `apps/web/src/lib/previewAnnotation.ts:113-147`, keeps the annotation without the crop, and always clears the active pick in `PreviewView.tsx:580-630`. A failed capture cannot leave the composer locked on this path. +- [#9647](https://github.com/pingdotgg/t3code/pull/9647), Antigravity restart sign-in behavior: **retained active callers**. `ChatComposer.tsx:1644-1651` still uses `getAntigravitySendBlockReason` for the actual send gate. The helper permits `auth.status === "unknown"` after validating installation and a selected model at `ChatView.logic.ts:415-428`; it blocks only explicit unauthenticated state. The active banner also suppresses the installed Antigravity warning while auth is unknown at `ProviderStatusBanner.tsx:9-31`, and `ChatView.tsx:3279-3292` uses that result. +- [#9651](https://github.com/pingdotgg/t3code/pull/9651), sidebar multi-select unpin: **retained**. The active multi-select context-menu caller filters selected rows to pin-capable, currently pinned threads and adds `Unpin (k)` at `Sidebar.tsx:2978-3019`. Selecting it calls `attemptUnpin` for exactly that filtered set and clears selection at `:3101-3107`. `Sidebar.logic.ts:209-218` omits the action when the pinned count is zero. + +No finding was added for this six-item sweep. + +## Late-main addendum + +Main advanced after the frozen comparison to `bc03c3640d6d3bb44e5fb477bfd78d7484cd0e00`. The branch HEAD and overlay did not move. These two items are late-main catch-up gaps, not claims that an earlier port was lost. + +- **M09, defer the mobile file highlighter from [#9752](https://github.com/pingdotgg/t3code/pull/9752): missing.** Frozen HEAD wraps every valid `ThreadFileScreen` in `ReviewHighlighterProvider` at `ThreadFilesRouteScreen.tsx:825-943`. The provider immediately calls `useReviewHighlighterState` at `ReviewHighlighterProvider.tsx:11-19`, whose mount effect prepares the engine and initial language set at `reviewHighlighterState.ts:164-176`. This happens for image, video, browser-preview, Markdown-preview, and source routes even though only `SourceFileSurface` consumes `sourceHighlightAtom`. That real consumer already starts `highlightSourceFile` lazily through `sourceHighlightingState.ts:29-50`. The late main commit removes the redundant route-wide provider and manager, so the branch still pays highlighter startup on file routes that do not need syntax highlighting. +- **M11, defer history image URLs from [#9760](https://github.com/pingdotgg/t3code/pull/9760): missing.** Frozen `ChatView` walks every loaded user message attachment at `ChatView.tsx:2910-2919`, turns the full set into asset resources, and calls `useAssetUrls` at `:2959-2977`. The resulting URLs are projected into the whole timeline at `:3072-3130`, before virtualization determines which message rows are mounted. The active V2 `UserTimelineRow` at `MessagesTimeline.tsx:1381-1445` merely consumes those prefilled URLs. The late main commit keeps only pending local-preview handoffs at chat scope and moves image resource selection plus `useAssetUrls` into each mounted user row. The branch therefore still requests signed URLs for offscreen history, including IDs collected from non-image user attachments. This is a post-freeze performance gap, not an old-regression finding. + +## Surface and entry-point matrix + +| Contract or behavior | Web | Desktop shell | Mobile | Remote / multi-environment consequence | +| --------------------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| V2 queued work | Reorder, steer, cancel, thumbnails, composer editing; F09 loses newly selected generic files | Same web UI | Reorder, steer, cancel only by D07; pending new-task outbox has a separate editor | Commands carry explicit environment/thread IDs. F09 is especially easy to hit while another device advances the queue. | +| Persisted message attachments | Images and generic files render | Same web UI | F10 hides non-images before otherwise valid file/PDF/video renderers | Assets remain environment/thread scoped; the defect is client filtering after projection. | +| Assistant Markdown/templates/citations/images | Specialized renderer retained; D02 uses active fork for ordinary inherited rows | Same web renderer | F17 fixed; scoped iOS media and template callback restored; D02 still uses active screen ownership | Direct rows resolve against the selected environment. Source-versus-fork semantics remain undecided only for inherited history. | +| Thread stream lifetime | Five-minute live idle retention | Same web client runtime | Same shared runtime | CLIENT-01 keeps unused remote streams and event delivery alive; coalescing reduces event rate but not lifetime. | +| Terminal row status | Repeated metadata scan/sort in sidebar, palette, and chat | Same web UI plus desktop terminals | Separate native terminal flow | CLIENT-02 scales with mounted web rows and terminal count. The dirty palette patch does not gate trailing terminal reads. | +| New-thread Project settings | Sidebar and command palette work; header shortcut absent | Same web UI | Separate project selection/settings flow | No total feature loss; [#9743](https://github.com/pingdotgg/t3code/pull/9743) adds one web/desktop entry point. | +| Settled activity folding | Single late success remains detached | Same web UI | Separate native grouping implementation | CLIENT-04 is presentation-only and does not change wire state. | +| Review diff cache | Not applicable | Not applicable | Unbounded parsed keep-alive cache | CLIENT-03 is device-local memory growth; remote source size can accelerate it. | +| Desktop IPC parity | Browser profiles/import, SSH host resolution, and preview failure contracts are present | Handlers/preload present | Not applicable | No frozen-main desktop-shell omission found in the inspected recent contracts. | + +## Dirty overlay, local-only review + +No new concrete defect was found in the scoped dirty overlay. These are not committed fixes and do not change the committed status of any finding above. + +- **Command palette / thread indicators.** The snapshot passes the existing thread change-request snapshot into each leading status row. `ThreadRowLeadingStatus` observes its containing result with the shared sidebar lease, gates linked-PR and VCS queries on near-viewport visibility, retains the last live value by environment/worktree key, and falls back only to a same-branch, non-linked snapshot. The local 128-row test verifies zero offscreen reads, eight reads for the first visible set, eight more after moving visibility, and retained cached badges. It does not cover the trailing terminal query, which is why CLIENT-02 remains. +- **Desktop local topology.** `desktopLocal.ts.snapshot` keeps the last array identity when a bridge returns fresh objects with equal `id`, label, distro, HTTP URL, WS URL, and bootstrap token. It publishes a new identity when any field changes and keeps the bridge-less empty array stable. Tests cover every compared field. +- **Expo notifications patch.** The patch protects delegates and pending responses with `NSLock`, snapshots delegate lists before callbacks, appends a response before releasing the lock, and removes only the exact handled response identities afterward. That ordering covers both interleavings between delegate registration and delivery and preserves responses created during a replay callback. Workspace patch mapping and lockfile hash wiring match the patch. The native test compiles the installed patched Swift source with ThreadSanitizer; no simulator was launched. + +## Tests and limitations + +Detailed output is in `clients-focused-tests.log`. + +- The six-port sweep and M09/M11 addendum are source-only. No tests were rerun for this follow-up. +- **Committed-source evidence:** 3 files, 21 tests passed. Before execution, all three live files had SHA-256 hashes identical to frozen committed HEAD. These cover queue ordering/capability presentation and web queue-row behavior. They do not cover F09 submission or D02 routing. +- **Local-only overlay evidence:** 5 files, 60 tests passed. The four requested filter strings selected one additional committed `.test.tsx` file because Vite+ file filtering is substring-based; it is not counted as separate intended coverage. The scoped live files matched the suffixed frozen snapshots and manifest hashes before execution. The only warning was `react-test-renderer` deprecation. +- The root batch's earlier copied-test import failure was audit-artifact discovery noise. All frozen overlay test copies now end in `.snapshot`; no copied audit test ran in this client batch. +- No browser, desktop app, provider, server, simulator, or real UI renderer was launched. No visual behavior is claimed for update-notice layout, attachment chips, folds, or Markdown interaction. +- No live T3 userdata was opened or mutated. No product code or existing test was edited. No repo-wide command, commit, push, GitHub action, or review comment was performed. +- Source inspection proves the stated control/data paths. It does not provide measured frame sizes, heap growth, CPU percentages, or end-to-end remote latency. diff --git a/audits/orchestrator-v2/2026-09-04/closing-references.json b/audits/orchestrator-v2/2026-09-04/closing-references.json new file mode 100644 index 000000000000..c3f8ecbbf4a3 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/closing-references.json @@ -0,0 +1,15 @@ +{ + "capturedAt": "2026-09-04T19:30:28.136740+00:00", + "head": "8af5734365f7c45bc08b57066dbae42f9f7d4235", + "initialMain": "d7cf8aaa8d4fbcbdd523b4f4bc86fda5c47b4a70", + "reviewedMainAtClose": "f6db4206258b0ef30e8dd8949627acfd209bf338", + "mainOnlyCommits": 15, + "branchOnlyCommits": 333, + "initialTreeChangedFiles": 991, + "closingTreeChangedFiles": 999, + "incomingMainCommitsSincePreviousAudit": 247, + "dirtyFiles": 59, + "dirtyFilesChangedSinceFinalManifest": [], + "noLongerDirty": [], + "cutoffNote": "Main revisions after reviewedMainAtClose are outside this audit." +} diff --git a/audits/orchestrator-v2/2026-09-04/cross-cutting.md b/audits/orchestrator-v2/2026-09-04/cross-cutting.md new file mode 100644 index 000000000000..985b7f521a8d --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/cross-cutting.md @@ -0,0 +1,64 @@ +# Cross-cutting review, 2026-09-04 + +Committed target: `8af5734365f7c45bc08b57066dbae42f9f7d4235`. Main: `d7cf8aaa8d4fbcbdd523b4f4bc86fda5c47b4a70`. The worktree is changing independently; frozen local copies have a `.snapshot` suffix and are listed in `worktree-manifest.json`. These are review artifacts, not product changes. + +## Prior findings + +**F12 remains open, P2.** Initial automatic titles still make one request. [ThreadTitleRegenerationService.ts](/Users/julius/.t3/worktrees/codething-mvp/t3code-7f11a674/apps/server/src/orchestration-v2/ThreadTitleRegenerationService.ts:223) calls `generateThreadTitle`, then catches non-interruption failures as completion at line 236 and clears the request marker. The shared text-generation layer adds no retry. Main's `ProviderCommandReactor.ts:963` retries initial generation twice with exponential backoff, from [#8087](https://github.com/pingdotgg/t3code/pull/8087). A transient typed provider error therefore leaves the fallback title until manual regeneration. The existing failure test deliberately dies, asserts one call, and verifies cleanup; it does not test transient typed failure followed by success. Restore bounded retries for initial titles while retaining stale-request guards and cleanup. Source is unchanged between the preceding audited revision and this committed target. + +**F16 remains open, P1 for large histories.** [ws.ts](/Users/julius/.t3/worktrees/codething-mvp/t3code-7f11a674/apps/server/src/ws.ts:867) still obtains `getThreadSnapshot`, projects the entire result, and emits it as one socket snapshot. Invalid cursors and reconnect ranges above 128 events or 1 MiB use this function. A cold HTTP snapshot failure uses it too. `ThreadManagementService` delegates this to the full projection-store snapshot, despite having a separate windowed snapshot method. Per-item wire truncation does not cap the number of rows. [threads.ts](/Users/julius/.t3/worktrees/codething-mvp/t3code-7f11a674/packages/client-runtime/src/state/threads.ts:301) accepts the full snapshot and resets progressive history metadata. Main's `ws.ts:1676` forwards the client's `turnLimit` when obtaining the fallback snapshot. The existing healthy HTTP path is bounded; this finding concerns fallback. Route fallback through the bounded query/budget path and carry a valid history cursor. No latency or memory multiplier is claimed. + +**V01's missing-coalescer concern is addressed in committed code.** `ws.ts:827` now wires `coalesceThreadLiveStream`. The new implementation combines repeated running tool updates by thread, run, and stable item ID in a 50 ms window. Lifecycle/message boundaries flush survivors in sequence order. Its tests exercise independent calls, terminal boundaries, cancellation, and retained-buffer limits. The separate `LiveStreamBudget` also limits queued and unacknowledged live events. This does not fix F16 because the snapshot frame is produced outside that bounded event path. Actual provider-workload byte/frame comparisons remain unmeasured. + +**D01 is still an explicit deferral.** [ServerEnvironment.ts](/Users/julius/.t3/worktrees/codething-mvp/t3code-7f11a674/apps/server/src/environment/ServerEnvironment.ts:230) withholds `serverUpdateThreadContinuation` and explains that V2 recovery terminalizes running work instead. Main's continuation feature from [#9167](https://github.com/pingdotgg/t3code/pull/9167) is not provided. This is a documented product decision, not evidence of a careless conflict resolution. + +## Main lag and retained boundaries + +There are eight main-only commits. The [main-only inventory](main-only-commits.txt) is separate from old porting failures. In particular, [#9748](https://github.com/pingdotgg/t3code/pull/9748) adds an 8 MiB terminal-history cap, bounded Unicode-safe tail reads, and protection against giant partial lines. This branch still limits terminal history by 5,000 lines only and reads the entire saved history before capping it at `terminal/Manager.ts:1494`. A long line remains unbounded in memory, storage, and attach snapshots. That change is independent of V2 and should be incorporated when catching up with main. Main's preceding incremental terminal-history change is already present. + +| Boundary | Current evidence | +| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| PR and base | [#2829](https://github.com/pingdotgg/t3code/pull/2829) targets main and has the reviewed head. Main is eight commits ahead of the merge base; there are 333 branch-only commits and 991 changed files in the final-tree comparison. | +| Incoming main inventory | 240 commits since the previous main reference. 64 touch only files now identical to main; 176 touch at least one differing file. File equality is a triage aid, not proof of a caller being retained. | +| Rebase patch inventory | The range comparison has 265 equal patches, 64 changed pairs, three unmatched old patches and four unmatched new patches. Two unmatched pairs are integration/lint bookkeeping. The unmatched old Codex availability patch is absorbed: `CodexProvider.ts:489-525` still initializes an unchecked provider with `installed: false`. The prior audit tip maps exactly to `96aff3564b3`; the two subsequent commits contain the new resource work and main reconciliation. | +| Protocol and CORS | Protocol V2 negotiation remains explicit, and `httpCors.ts` permits the protocol header. Renamed/new RPCs retain explicit auth-scope entries. Focused tests pass. | +| Remote identity, credentials and pairing | Shared auth implementations apart from the RPC mapping, and cloud credential refresh code, match main. This includes the pairing read-model and refresh-without-disconnect changes. No live relay or expiry flow was exercised. | +| Long delegated IDs | Both environment HTTP routing and relay HTTP routing allow 512-character parameters. The relay worker supplies that router configuration. | +| Relay push and decoding changes | Main's stalled-push bounds and decoding changes are in identical relay files outside the V2 awareness adapter. | +| Background metadata prompts and pricing | Shared text-generation prompts/dispatcher, usage readers and cloud code match main. Provider-specific permissions and token translation are reviewed separately. | +| Checkpoint summaries | Shared `CheckpointStore` matches main, including avoiding full patches when only summaries are needed. F03 concerns the V2 baseline query, not that shared implementation. | +| Automatic project pulls and PR refresh | The opt-in project setting reaches `VcsStatusBroadcaster`'s policy and startup `autoPullProjects`. V2 run execution invokes the cached `refreshAfterTurn` observer, and checkpoint finalization refreshes branch PR status. These replacements remain wired to the shared implementations. | +| Desktop and service launch | Server bundle still includes both the main binary and service launcher. The only differing production Electron file has a type annotation in the Tailscale fallback, with no behavioral change. Web findings still affect desktop. No packaging or native runtime was launched. | +| Performance CI | The V1-specific transfer-report workflow was deliberately removed by commit `103f1e6cd22`. Its commit message calls for a V2 replacement. A focused V2 wire regression script now exists, but the old built-app benchmark/report is not restored. Keep this distinction when claiming performance verification. | + +## Additional lifecycle question + +The old bot observation about archived scheduled-task targets still has a valid source path, but it is not a main-to-V2 regression because main has no equivalent scheduled-task service. `OrchestratorMcpService.ts:953` accepts the current thread as a schedule target without checking whether it is archived, and the generic scheduled-task upsert does not validate its target. Later, `ThreadManagementService.ts:483` rejects sends to archived threads. Recurring tasks retain their enabled state and compute the next occurrence after each failure. Archiving or deleting an existing bound target raises the same lifecycle question. Decide whether to disable such schedules, reject new bindings, or keep schedules enabled for later unarchive. No scheduling action or live provider was invoked for this audit. + +## Late main arrivals + +While the reviewed branch and local source stayed unchanged, `origin/main` advanced to `bc03c3640d6d3bb44e5fb477bfd78d7484cd0e00`. The four new commits are recorded in `main-late-arrivals.txt`; M09-M12 in the consolidated report cover them. The original frozen-main comparison and its eight missing commits remain reproducible. + +**M12, bundled model classification.** [#9762](https://github.com/pingdotgg/t3code/pull/9762) adds `gpt-6-astra` to the Codex `currentModels` list and advances the bundled manifest timestamp. The branch's manifest still matches the earlier main version. `ModelManifest.ts:210-221` classifies built-in models missing from that list as legacy. This affects the bundled/offline fallback: the existing runtime manifest refresh can obtain the updated main file and compensate online. It is not evidence that the provider cannot execute the model or that model discovery is absent. Incorporate the small data update during main catch-up. + +The parent independently checked OpenCode's installed SDK SSE generator: `dist/v2/gen/core/serverSentEvents.gen.js:117` exits the stream loop on normal completion. A clean response-body EOF does not automatically resubscribe, which supports F18's trigger. The adapter finding remains source-backed, without a timing-based absence test. + +Three final UI commits arrived before the cutoff was set at `f6db4206258b0ef30e8dd8949627acfd209bf338`. The parent reviewed these directly: + +- **M13, proactive diff activation, [#9753](https://github.com/pingdotgg/t3code/pull/9753).** V2 `ChatView.tsx:4261-4275` opens a diff whenever a completed run has any checkpoint summary and the workspace is a Git repository. It does not check whether the active surface is a pull request or whether the checkpoint is ready and nonempty. `threadCheckpoints.ts:29-51` preserves empty-file and non-ready summaries, so the active caller can replace a PR panel with an empty or unavailable diff. Main's new decision helper rejects those cases and preserves deferred loading. Adapt it to V2's `runId` summaries. +- **M14, sidebar background prominence, [#9759](https://github.com/pingdotgg/t3code/pull/9759).** V2 `Sidebar.tsx:866-893` lets unread/woken state override dimming even while a thread is still working. Main dims unselected/unfocused working or monitoring rows regardless of unread completion, while retaining unread/wake prominence for ready and action-required states. Port the presentation rule using V2 statuses. This is visual policy catch-up, not lost conversation data. +- **M15, automatic-pull reset affordance, [#9763](https://github.com/pingdotgg/t3code/pull/9763).** `ProjectSettingsPanel.tsx:989-999` still renders the working on/off switch without the new reset button. Main adds a reset action that calls the existing setter with `false`. The feature and its reverse operation already work; only the standard reset affordance is absent. + +The initial eight main-only commits plus these seven arrivals total 15 main-only commits at the final cutoff. No later main revision is included in this audit. + +## Focused checks and limitations + +- `root-contract-tests.log`: 6 file executions, 41 tests passed, covering WS compatibility, startup, RPC authorization, title handling, live coalescing, and wire projection. +- `root-budget-awareness-tests-rerun.log`: 3 file executions, 28 tests passed, covering live-stream budgets and shared/local awareness behavior. +- `root-resume-tests.log`: 3 file executions, 25 tests passed, covering resume decisions, active/archive shell streams, and HTTP contracts. The resume tests verify the fallback decision, not a bounded end-to-end fallback snapshot. +- `root-usage-attachments-tests.log`: 5 file executions, 38 tests passed, covering usage readers/pricing/proxy limits, attachment claims, and metadata prompts. +- `root-native-command-tests.log`: 2 file executions, 61 tests passed, covering V2 run execution and launch behavior, including native compaction routing and logout guards. +- The first awareness run also selected a frozen audit copy because Vitest's file filter matched its suffix. Its import failure was an audit-artifact discovery problem; the three actual suites passed. Frozen files were renamed with `.snapshot`, and the rerun passed. No product source was changed to resolve this. +- These are focused tests on the current worktree, including its local awareness work. They do not establish correctness for every client, provider, upgrade history, or fallback transport. + +Current-head [CI Check](https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744766) fails formatting in seven files. The generic test job and server shards 1 and 2 passed; server shard 3 was cancelled. Release smoke and Rust passed; web/mobile/macOS preview builds were skipped. The [captured metadata](pr-metadata.json) and [failed log](ci-check-failure.log) retain exact evidence. CI does not cover the uncommitted overlay. No repo-wide check, browser, simulator, dev server, live-provider validation, production database write, commit, push, or review comment was performed. diff --git a/audits/orchestrator-v2/2026-09-04/dirty-stat.txt b/audits/orchestrator-v2/2026-09-04/dirty-stat.txt new file mode 100644 index 000000000000..80b82d7c6810 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/dirty-stat.txt @@ -0,0 +1,50 @@ + apps/server/src/git/GitManager.ts | 2 +- + .../Adapters/CodexAdapterV2.test.ts | 5 +- + .../orchestration-v2/Adapters/CodexAdapterV2.ts | 1 + + apps/server/src/orchestration-v2/Orchestrator.ts | 86 +++++---- + .../server/src/orchestration-v2/ProjectionStore.ts | 192 +++++++++++++++++++++ + .../ProviderTurnControlService.test.ts | 2 + + .../ThreadSettlementService.test.ts | 8 +- + .../orchestration-v2/ThreadSettlementService.ts | 12 +- + .../src/orchestration-v2/runtimeLayer.test.ts | 32 ++++ + .../message_steering/codex_transcript.ndjson | 2 +- + .../fixtures/multi_turn/codex_transcript.ndjson | 2 +- + .../plan_questions/codex_transcript.ndjson | 2 +- + .../fixtures/proposed_plan/codex_transcript.ndjson | 2 +- + .../provider_thread_resume/codex_transcript.ndjson | 4 +- + .../fixtures/queued_turn/codex_transcript.ndjson | 2 +- + .../fixtures/simple/codex_transcript.ndjson | 2 +- + .../fixtures/subagent/codex_transcript.ndjson | 2 +- + .../subagent_continue/codex_transcript.ndjson | 2 +- + .../fixtures/subagent_v2/codex_transcript.ndjson | 2 +- + .../subagent_v2_nested/codex_transcript.ndjson | 2 +- + .../thread_fork_native/codex_transcript.ndjson | 2 +- + .../codex_transcript.ndjson | 2 +- + .../codex_transcript.ndjson | 2 +- + .../codex_transcript.ndjson | 2 +- + .../codex_transcript.ndjson | 2 +- + .../codex_transcript.ndjson | 2 +- + .../thread_rollback/codex_transcript.ndjson | 2 +- + .../fixtures/todo_list/codex_transcript.ndjson | 2 +- + .../codex_transcript.ndjson | 2 +- + .../codex_transcript.ndjson | 2 +- + .../codex_transcript.ndjson | 2 +- + .../turn_interrupt/codex_transcript.ndjson | 2 +- + .../codex_transcript.ndjson | 2 +- + .../fixtures/web_search/codex_transcript.ndjson | 2 +- + apps/server/src/persistence/Migrations.ts | 2 + + .../src/provider/Layers/EventNdjsonLogger.test.ts | 16 ++ + .../src/provider/Layers/EventNdjsonLogger.ts | 1 + + apps/server/src/relay/AgentAwarenessRelay.ts | 120 +++++++++++-- + apps/server/src/server.ts | 2 +- + apps/server/src/vcs/GitVcsDriver.ts | 10 +- + apps/server/src/vcs/GitVcsDriverCore.test.ts | 90 +++++++++- + apps/server/src/vcs/GitVcsDriverCore.ts | 30 +++- + apps/web/src/components/CommandPalette.tsx | 10 +- + .../src/components/ThreadStatusIndicators.test.ts | 19 ++ + apps/web/src/components/ThreadStatusIndicators.tsx | 76 ++++++-- + apps/web/src/connection/desktopLocal.test.ts | 63 ++++++- + apps/web/src/connection/desktopLocal.ts | 21 ++- + pnpm-lock.yaml | 5 +- + pnpm-workspace.yaml | 1 + + 49 files changed, 732 insertions(+), 126 deletions(-) diff --git a/audits/orchestrator-v2/2026-09-04/drift-interim.json b/audits/orchestrator-v2/2026-09-04/drift-interim.json new file mode 100644 index 000000000000..a34270154505 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/drift-interim.json @@ -0,0 +1,8 @@ +[ + "apps/server/src/orchestration-v2/ProjectionSettlement.test.ts", + "apps/server/src/relay/AgentAwarenessRelay.test.ts", + "apps/server/src/relay/AgentAwarenessRelay.ts", + "docs/internals/mobile-development.md", + "docs/internals/performance-regressions.md", + "docs/internals/providers.md" +] diff --git a/audits/orchestrator-v2/2026-09-04/initial-status.txt b/audits/orchestrator-v2/2026-09-04/initial-status.txt new file mode 100644 index 000000000000..7c6bd753f9b1 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/initial-status.txt @@ -0,0 +1,57 @@ + M apps/server/src/git/GitManager.ts + M apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.test.ts + M apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.ts + M apps/server/src/orchestration-v2/Orchestrator.ts + M apps/server/src/orchestration-v2/ProjectionStore.ts + M apps/server/src/orchestration-v2/ProviderTurnControlService.test.ts + M apps/server/src/orchestration-v2/ThreadSettlementService.test.ts + M apps/server/src/orchestration-v2/ThreadSettlementService.ts + M apps/server/src/orchestration-v2/runtimeLayer.test.ts + M apps/server/src/orchestration-v2/testkit/fixtures/message_steering/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/multi_turn/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/plan_questions/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/proposed_plan/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/provider_thread_resume/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/queued_turn/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/simple/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/subagent/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/subagent_continue/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/subagent_v2_nested/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_continue/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_prior_turn/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/thread_fork_native_siblings/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_continue/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/thread_merge_back_siblings/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/thread_rollback/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/todo_list/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/tool_call_read_only_on_request/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/tool_call_restricted_granular/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/tool_call_workspace_never/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt_mid_tool/codex_transcript.ndjson + M apps/server/src/orchestration-v2/testkit/fixtures/web_search/codex_transcript.ndjson + M apps/server/src/persistence/Migrations.ts + M apps/server/src/provider/Layers/EventNdjsonLogger.test.ts + M apps/server/src/provider/Layers/EventNdjsonLogger.ts + M apps/server/src/relay/AgentAwarenessRelay.ts + M apps/server/src/server.ts + M apps/server/src/vcs/GitVcsDriver.ts + M apps/server/src/vcs/GitVcsDriverCore.test.ts + M apps/server/src/vcs/GitVcsDriverCore.ts + M apps/web/src/components/CommandPalette.tsx + M apps/web/src/components/ThreadStatusIndicators.test.ts + M apps/web/src/components/ThreadStatusIndicators.tsx + M apps/web/src/connection/desktopLocal.test.ts + M apps/web/src/connection/desktopLocal.ts + M pnpm-lock.yaml + M pnpm-workspace.yaml +?? apps/mobile/scripts/fixtures/ +?? apps/mobile/scripts/notification-center-manager.test.ts +?? apps/server/src/orchestration-v2/ProjectionSettlement.test.ts +?? apps/server/src/persistence/Migrations/059_OrchestrationV2ShellIndexes.ts +?? apps/server/src/relay/AgentAwarenessRelay.test.ts +?? apps/web/src/components/ThreadStatusIndicators.subscriptions.test.tsx +?? audits/ +?? patches/expo-notifications@57.0.15.patch diff --git a/audits/orchestrator-v2/2026-09-04/main-feature-file-map.tsv b/audits/orchestrator-v2/2026-09-04/main-feature-file-map.tsv new file mode 100644 index 000000000000..bb04ddf7f194 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/main-feature-file-map.tsv @@ -0,0 +1,241 @@ +commit subject files differing_files differing_paths +d7cf8aaa8d4fbcbdd523b4f4bc86fda5c47b4a70 perf(client): stop thread streams when unused (#9740) 6 6 docs/internals/connection-runtime.md;packages/client-runtime/src/state/threadDetail.ts;packages/client-runtime/src/state/threadRetention.ts;packages/client-runtime/src/state/threads-atoms.test.ts;packages/client-runtime/src/state/threads-sync.test.ts;packages/client-runtime/src/state/threads.ts +0de956ed2f92b8a6ead56e1566801db232d365dc fix(web): refine server update notice (#9744) 4 4 apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/ComposerBanner.tsx;apps/web/src/components/chat/ComposerBannerStack.tsx;apps/web/src/components/chat/ComposerServerUpdateStatus.tsx +a76b898b3aa4fd4081104b06a3b2c942bd4fecb7 feat(web): link pull request authors to profiles (#9627) 2 2 apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx;apps/web/src/components/pullRequest/pullRequestPresentation.tsx +cf9729d5ee9660c08556e823080d3bb19648ed28 perf(server): bound terminal history by bytes (#9748) 4 4 apps/server/src/terminal/Manager.test.ts;apps/server/src/terminal/Manager.ts;docs/internals/terminal-runtime.md;docs/user/terminal.md +fec606f9ae524277ef1f6886e614f32d9e15e36e perf(web): avoid repeated terminal metadata scans (#9747) 2 2 apps/web/src/state/terminalSessions.test.ts;apps/web/src/state/terminalSessions.ts +d6e29dc9dee943b34d6b0d11441fa944c7bff7c9 perf(mobile): bound the parsed review cache (#9749) 4 4 apps/mobile/src/features/review/reviewState.test.ts;apps/mobile/src/features/review/reviewState.ts;apps/mobile/src/features/review/useReviewDiffPrewarming.test.ts;apps/mobile/src/features/review/useReviewDiffPrewarming.ts +cbe93e8dfba68ff6fbe8c69e43a633fdc79db62d fix(web): show project settings for new threads (#9743) 2 2 apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/ChatHeader.tsx +cfc9bf34156ddcc4a98b7f5c67193adb5aedce06 fix(web): fold single trailing activity (#9739) 3 3 apps/web/src/components/chat/MessagesTimeline.logic.test.ts;apps/web/src/components/chat/MessagesTimeline.logic.ts;apps/web/src/components/chat/MessagesTimeline.test.tsx +c8f77e0d441264efb0acfac312e852c81ae3da83 perf(server): stop caching unused OpenCode tool parts (#9738) 2 2 apps/server/src/provider/Layers/OpenCodeAdapter.test.ts;apps/server/src/provider/Layers/OpenCodeAdapter.ts +088cc3f95599b7b933289d719fa1e9b0608cb4cd fix(relay): bound stalled push requests (#9734) 3 0 +19c1710a88a2c87c159d76269dacdf0b17ddd9f4 perf(web): reuse timeline rows while text streams (#9725) 6 6 apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/MessagesTimeline.logic.test.ts;apps/web/src/components/chat/MessagesTimeline.logic.ts;apps/web/src/components/chat/MessagesTimeline.tsx;apps/web/src/session-logic.test.ts;apps/web/src/session-logic.ts +c7bf3115f2223ede5cb2316613dc7369155dbeb1 feat(web): unpin threads from the sidebar multi-select menu (#9651) 3 3 apps/web/src/components/Sidebar.logic.test.ts;apps/web/src/components/Sidebar.logic.ts;apps/web/src/components/Sidebar.tsx +7d5dc66c151a9ca7bfef45cffc9d3516842c5566 fix(web): mute composer helper text (#9654) 1 0 +50bfca43d76ced00f5d67cfbab8bc44c50eb0e53 perf(server): replay only the selected thread (#9726) 12 12 apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts;apps/server/src/orchestration/Layers/OrchestrationEngine.ts;apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts;apps/server/src/orchestration/Services/OrchestrationEngine.ts;apps/server/src/persistence/Layers/OrchestrationEventStore.test.ts;apps/server/src/persistence/Layers/OrchestrationEventStore.ts;apps/server/src/persistence/Services/OrchestrationEventStore.ts;apps/server/src/relay/AgentAwarenessRelay.test.ts;apps/server/src/server.test.ts;apps/server/src/serverRuntimeStartup.reconcile.test.ts;apps/server/src/serverRuntimeStartup.test.ts;apps/server/src/ws.ts +c4353bc6b972fa527579b530f01cc8744b2407d2 fix(mobile): read file-backed image drafts before enabling them (#9713) 18 3 apps/mobile/src/lib/projectThreadStartTurn.test.ts;apps/mobile/src/lib/projectThreadStartTurn.ts;apps/mobile/src/state/use-thread-outbox-drain.ts +5eab021a5185e492b6b021f83564143d5263e8a6 perf(web): stop rendering hidden terminals (#9718) 4 1 apps/web/src/components/ChatView.tsx +9eb4d71681dc7d002082db2f8b4bacf7614412f4 fix(mobile): remove provider setup (#9721) 19 3 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx;apps/mobile/src/state/use-thread-composer-state.ts;apps/mobile/src/state/use-thread-outbox-drain.ts +120fab18d84f1eb993ecc7fa858a8dd212747079 fix(web): keep the slash menu above the composer when vertical space is short (#9625) 2 1 apps/web/src/components/chat/ChatComposer.tsx +8357eef14cbd5ed063e4a64404c33d1bfbc78446 fix(web): match provider settings layout for disconnected devices (#9619) 4 1 apps/web/src/components/settings/ProviderInstanceCard.tsx +8ccb933a8aae461b616b199ab287164c3311a755 test(server): allow either valid file-search match (#9720) 1 0 +108f295cc3672716c3cb8291ce487846df5ce098 fix(server): bound slow-client event buffers (#9715) 6 6 apps/server/src/orchestration/LiveStreamBudget.test.ts;apps/server/src/orchestration/LiveStreamBudget.ts;apps/server/src/orchestration/ThreadLiveEventCoalescer.test.ts;apps/server/src/orchestration/ThreadLiveEventCoalescer.ts;apps/server/src/server.test.ts;apps/server/src/ws.ts +d536b0580d044967dc644498d8c5a6e96464f767 fix(server): settle inactive threads with open PRs (#9610) 4 1 apps/server/src/orchestration/ThreadSettlementReactor.test.ts +c66f15f39e61fda0a9a100578833ec12e7526859 perf(client): reduce thread-list update work (#9716) 2 2 packages/client-runtime/src/state/entities.test.ts;packages/client-runtime/src/state/threadShell.ts +95103905f5f045523994213bf76bfb14acc31b27 feat(web): preview pull request links (#9631) 5 0 +da7e46d08e85bcb07ecd78721a40f7b612fac2f2 perf(web): stop replaying terminal buffers on rollover (#9707) 8 0 +7839140e5e93d3f401d7eb45b86cf1a234eb3609 fix(mobile): preserve saved work after storage read failures (#9710) 5 0 +c7c1dfe4df99edf65a49d8a31b39ef1361f37f44 perf(web): stop continuous chat status animations (#9709) 6 5 apps/web/src/components/chat/ComposerServerUpdateStatus.tsx;apps/web/src/components/chat/MessagesTimeline.test.tsx;apps/web/src/components/chat/MessagesTimeline.tsx;apps/web/src/index.css;docs/user/composer.md +c75299ee2085a121bceb6df76796e971fe92b5b6 perf(relay): avoid repeated activity decoding (#9708) 4 0 +dffb4cd3b16dc6f41aced99922950ee3083082c6 perf(server): use one query for buffered provider events (#9706) 10 10 apps/server/src/checkpointing/CheckpointDiffQuery.test.ts;apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts;apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts;apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts;apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts;apps/server/src/project/ProjectSetupScriptRunner.test.ts;apps/server/src/provider/Layers/ProviderSessionReaper.test.ts;apps/server/src/serverRuntimeStartup.test.ts +3bbbc1d9fd8b3d649c60ba0137c7dae93a6aab3f perf(server): stop rebuilding terminal history per chunk (#9703) 3 3 apps/server/src/terminal/Manager.test.ts;apps/server/src/terminal/Manager.ts;docs/internals/terminal-runtime.md +010d6bb1b5281cb1e6eacf1ee0f2500973242836 perf(marketing): serve website fonts locally (#9701) 12 0 +b3e1d88590489da2bb63b95c18a57e6f400b8b7f perf(web): defer diff workers until a code view opens (#9692) 11 5 apps/web/src/components/ChatView.tsx;apps/web/src/components/DiffPanel.tsx;apps/web/src/components/chat/MessagesTimeline.test.tsx;apps/web/src/components/chat/MessagesTimeline.tsx;apps/web/src/components/files/FilePreviewPanel.tsx +c163d502dd32b993c03d8c20a5fae55b159bd8dc perf(server): avoid full patches for checkpoint summaries (#9694) 14 5 apps/server/package.json;apps/server/src/orchestration/Layers/CheckpointReactor.test.ts;apps/server/src/orchestration/Layers/CheckpointReactor.ts;apps/server/src/vcs/GitVcsDriver.ts;pnpm-lock.yaml +4ee2a9d046a0986451c703c9221bb32ba53540bb perf(marketing): stop continuous homepage motion (#9697) 1 1 apps/marketing/src/pages/index.astro +1587f248dd81ed45e214d476451ebf16dbfadb1a feat(server): measure provider turn token usage (#9132) 14 10 apps/server/src/provider/Layers/ClaudeAdapter.test.ts;apps/server/src/provider/Layers/ClaudeAdapter.ts;apps/server/src/provider/Layers/CodexAdapter.test.ts;apps/server/src/provider/Layers/CodexAdapter.ts;apps/server/src/provider/Layers/OpenCodeAdapter.test.ts;apps/server/src/provider/Layers/OpenCodeAdapter.ts;apps/server/src/provider/Layers/ProviderService.test.ts;apps/server/src/provider/Layers/ProviderService.ts;docs/README.md;packages/contracts/src/providerRuntime.ts +dab5f6e6e02e78675655e69503aa89654e5b8050 perf(web): defer composer draft serialization (#9695) 3 1 apps/web/src/composerDraftStore.ts +777f5bb2e11fe30e7fdcb5741b0b1d9bb20924d6 perf(mobile): reuse diff rows during comment edits (#9693) 2 0 +246064993535e5d90107d3d7784ceef3cc883435 perf(clients): avoid waiting to read cached relay tokens (#9691) 2 0 +ec8b2119c377f5c1dbe6235b221ef98eca31a96e perf(server): omit repeated OpenCode progress logs (#9689) 3 3 apps/server/src/provider/Layers/EventNdjsonLogger.test.ts;apps/server/src/provider/Layers/EventNdjsonLogger.ts;docs/internals/providers.md +44dc8ae259f5c3349f7ab8045e39bd62408b52a9 perf(mobile): reuse chat feed rows during streaming (#9688) 3 3 apps/mobile/src/lib/threadActivity.test.ts;apps/mobile/src/lib/threadActivity.ts;apps/mobile/src/state/use-thread-composer-state.ts +f2e3764c257a7e27c8171d7dd1e38d4383074206 perf(server): stop retaining unused OpenCode tool history (#9684) 1 1 apps/server/src/provider/Layers/OpenCodeAdapter.ts +2263e13fda8c9a4f1b6f4dee32e3c9020195e2aa perf(server): batch projector cursor writes (#9671) 4 2 apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts;apps/server/src/orchestration/Layers/ProjectionPipeline.ts +27e6cc27fe0f3cff53a44905e40615b7db99c80c perf(server): cache and stream static web assets (#9669) 3 1 apps/server/src/server.test.ts +8e3aa324b57dd645980b203d5f8a5b9f9dc53a84 perf(marketing): serve images at their display size (#9682) 8 3 apps/marketing/public/app-desktop.webp;apps/marketing/src/pages/index.astro;pnpm-lock.yaml +7cf5b284e6e37895f535433c77f728b3e4292c9b perf(mobile): skip unused legacy list work (#9679) 3 2 apps/mobile/src/features/home/HomeScreen.tsx;apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx +887ece307131bdc853cc10f3b82067dee77c4ecf perf(web): keep Markdown mounted during streaming (#9677) 5 2 apps/web/src/components/chat/MessagesTimeline.tsx;pnpm-lock.yaml +3b6be3ef4daa848e10c095d8a088064ac836be7f perf(mobile): bound diff syntax highlighting work (#9673) 2 0 +082cab224624eb3a6cd494df3719c59014fb0c99 fix(web): show machine icons in the environment picker (#9668) 1 1 apps/web/src/components/CommandPalette.tsx +cccd7e3c885065e925f559c5708378cdb3b51eb3 perf(web): speed up terminal snapshots (#9663) 3 0 +8ac5462920c45cdee63af15b2598909736f2ec84 perf(server): stop loading message bodies for thread summaries (#9662) 7 4 apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts;apps/server/src/orchestration/Layers/ProjectionPipeline.ts;apps/server/src/persistence/Services/ProjectionPendingApprovals.ts;apps/server/src/persistence/Services/ProjectionThreadMessages.ts +560afffdea82000d757c98ea79678aee75f8648c fix(server): update Claude Agent SDK to 0.3.260 (#9135) 5 4 apps/server/package.json;apps/server/src/provider/Layers/ClaudeAdapter.test.ts;apps/server/src/provider/Layers/ClaudeAdapter.ts;pnpm-lock.yaml +caa8a0db98f9d32e98a1645caa7f7dd37b14f187 fix(desktop): quit immediately on a second shortcut press (#9657) 5 1 apps/web/src/components/settings/SettingsPanels.tsx +01f3e50eca5102ccd881de6f942a98fe6a518ad4 fix(server): unblock OpenCode approvals and stop (#9653) 17 12 apps/mobile/src/lib/threadActivity.test.ts;apps/mobile/src/lib/threadActivity.ts;apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts;apps/server/src/orchestration/Layers/ProjectionPipeline.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts;apps/server/src/provider/Layers/OpenCodeAdapter.test.ts;apps/server/src/provider/Layers/OpenCodeAdapter.ts;apps/web/src/session-logic.test.ts;apps/web/src/session-logic.ts;packages/client-runtime/src/work-log/presentation.test.ts;packages/client-runtime/src/work-log/presentation.ts +f0347322441f3b8e473a8d13ea7006cbcb4fb761 feat(web): show which sidebar threads hold an unsent draft (#9658) 4 2 apps/web/src/components/Sidebar.tsx;apps/web/src/composerDraftStore.ts +d5b94100863057fb4629f9ad4a35753d16917924 feat(mobile): paste the phone clipboard into the terminal (#9199) 8 1 apps/mobile/src/features/terminal/ThreadTerminalRouteScreen.tsx +d487dfbf46be344e818725be70ee04be2436bfb4 fix(web): resume Antigravity threads without repeated sign-in (#9647) 5 2 apps/web/src/components/ChatView.logic.test.ts;apps/web/src/components/ChatView.logic.ts +eb77683e5544e071db74831bae052bbd8a7d5f88 fix(server): prevent duplicate desktop clients after restart 8 1 apps/server/src/server.test.ts +14bf3f6d1644a37029be58429e8f0138e1ceb743 fix(web): toggle a single stashed prompt with Cmd+S (#9644) 3 2 apps/web/src/components/chat/ChatComposer.tsx;docs/user/composer.md +09d13de4381925fa2a6dea74eff8185fa301e905 feat(mobile): make chat text selectable on Android (#8779) 10 1 pnpm-lock.yaml +5f878d2a85807618a4c8571cdef5daa3124672d6 fix(web,mobile): fold context compaction under settled turn folds (#9623) 2 2 apps/mobile/src/lib/threadActivity.ts;apps/web/src/components/chat/MessagesTimeline.logic.ts +ec3ec6f0b4e005c47aff07d4d9e31506241bce3a fix(web): mute sidebar branch name to match worktree icon (#9622) 1 1 apps/web/src/components/Sidebar.tsx +2152d44de2db30a6bae965b0afd30be080e5c872 fix(server): load OpenCode workspace skills via SDK to avoid 64KB CLI pipe truncation (#9585) 1 1 apps/server/src/provider/Drivers/OpenCodeDriver.ts +706231535ceac8618712913dfdc4a058c2ffb0d8 fix(web): match composer pull request state icons (#9375) 4 3 apps/web/src/components/BranchToolbarBranchSelector.tsx;apps/web/src/components/LegacySidebar.tsx;apps/web/src/components/ThreadStatusIndicators.tsx +93c3ab4ffe408a3e06228a33efc8a0745da91178 fix(web): snooze menu no longer overlaps thread details (#9601) 1 1 apps/web/src/components/Sidebar.tsx +4cc800c7593db13726171918572afe3502c43ba6 fix(web): keep command palette above composer menus (#9613) 1 1 apps/web/src/components/chat/ChatComposer.tsx +99e3b721c5255ded20b00ba1798f848bfc0f1f65 fix(connect): diagnose incomplete headless server setup (#9602) 11 1 apps/server/src/server.ts +c3b8825bf476cbce5e061c0f99570cf1f6723b89 fix: preserve tool icons on failed calls (#9606) 5 3 apps/web/src/components/chat/MessagesTimeline.test.tsx;apps/web/src/components/chat/MessagesTimeline.tsx;apps/web/src/index.css +61a91b6ef1bd45424169c6650362b358d49bbe34 fix(web): group image views like other tool calls (#9597) 17 14 apps/server/src/provider/CodexDeveloperInstructions.ts;apps/server/src/provider/Layers/AntigravityAdapter.test.ts;apps/server/src/provider/Layers/AntigravityAdapter.ts;apps/server/src/provider/Layers/ClaudeAdapter.test.ts;apps/server/src/provider/Layers/ClaudeAdapter.ts;apps/server/src/provider/Layers/CursorAdapter.test.ts;apps/server/src/provider/Layers/CursorAdapter.ts;apps/server/src/provider/Layers/GrokAdapter.test.ts;apps/server/src/provider/Layers/GrokAdapter.ts;apps/server/src/provider/Layers/OpenCodeAdapter.test.ts;apps/server/src/provider/Layers/OpenCodeAdapter.ts;apps/web/src/components/chat/MessagesTimeline.logic.test.ts;apps/web/src/components/chat/MessagesTimeline.logic.ts;docs/internals/providers.md +00f8b7c28056188e3c5630160806a0afe51c9010 fix: show idle subagent batches without completion marks (#9616) 11 6 apps/mobile/src/lib/threadActivity.test.ts;apps/mobile/src/lib/threadActivity.ts;apps/server/src/provider/Layers/AntigravityAdapter.test.ts;apps/server/src/provider/Layers/AntigravityAdapter.ts;apps/web/src/components/chat/MessagesTimeline.tsx;packages/client-runtime/src/state/subagentRuntime.ts +f1e90e388b86fe4b007a55c0e685a1fa878115e6 refactor(web): move usage provider controls to settings (#9599) 10 2 apps/web/src/components/settings/settingsSearch.test.ts;apps/web/src/components/settings/settingsSearch.ts +caab2fdbac041ac2e851ad4fa3ac4a40a1d4a8f6 fix(web): render draft PRs in gray (#9537) 30 4 apps/web/src/components/Sidebar.tsx;apps/web/src/components/ThreadStatusIndicators.tsx;apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx;apps/web/src/components/pullRequest/pullRequestPresentation.tsx +5cc369b7eb882dbea8d5ad21ba688c73a0058748 fix(pull-requests): refresh data after thread turns (#9496) 15 9 apps/server/integration/OrchestrationEngineHarness.integration.ts;apps/server/src/auth/RpcAuthorization.ts;apps/server/src/orchestration/Layers/CheckpointReactor.test.ts;apps/server/src/orchestration/Layers/CheckpointReactor.ts;apps/server/src/ws.ts;apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx;apps/web/src/routes/_chat.pull-requests.tsx;packages/client-runtime/src/rpc/client.ts;packages/contracts/src/rpc.ts +f559fe0ba6fb5950bd14a2404f10b9c94b33f696 fix(web): show context meter in compact composer (#9430) 1 1 apps/web/src/components/chat/ChatComposer.tsx +39abb9d1d6ae6501c573b9dc0cb9c28e2f75659c fix(connect): refresh authorization without disconnecting (#9582) 2 0 +57832803eed4c87c462de92892777a0934019721 fix(desktop): restore panel titlebar interactions (#9591) 2 2 apps/web/src/components/ChatView.tsx;apps/web/src/components/RightPanelTabs.tsx +07891e9569c88457516b44c08c820471762969e8 fix(web): bound disconnected send toasts (#9592) 1 1 apps/web/src/components/ChatView.tsx +b34ff8f56469afa8f3f85d89894e1b4cf49b5213 fix(usage): deduplicate CLI proxy subscription accounts (#9584) 5 0 +09b81a34954c990f70257ae05efbb602c90aac97 fix(mobile): render workspace images in markdown file previews (#8769) 4 1 apps/mobile/src/features/threads/ThreadFeed.tsx +2675e3c70327719a99af4ae6e53e7b74fb8a9be0 fix(antigravity): keep subagent batches active after launch (#9579) 7 4 apps/server/src/provider/Layers/AntigravityAdapter.test.ts;apps/server/src/provider/Layers/AntigravityAdapter.ts;apps/server/src/provider/acp/AntigravityProtocol.ts;packages/client-runtime/src/state/subagentRuntime.ts +bf40fa786c521b552eb554bbd4f2c75c4123cd03 fix(web): align the sidebar wordmark by baseline (#9578) 1 0 +0cb02abf5b3af2985d9dd23a637a63388e98fd49 fix: better shell syntax handling for labels (#9371) 6 4 apps/mobile/src/lib/threadActivity.test.ts;apps/mobile/src/lib/threadActivity.ts;apps/web/src/session-logic.test.ts;apps/web/src/session-logic.ts +42bdea1c9c1d4b7c5c2e77cd23cf53fae68a6fd4 fix(web): stabilize right panel transitions (#9554) 2 2 apps/web/src/components/ChatView.tsx;apps/web/src/components/preview/PreviewPanelShell.tsx +95390ed78458f139cb795bab4baa53ec39222ff7 chore: vouch august contributors (#9557) 1 0 +2b10398cca3fa74a7c2187c8d9c23ba789333f5b fix(web): render settings sidebar immediately (#9563) 2 2 apps/web/src/components/AppSidebarLayout.tsx;apps/web/src/components/settings/SettingsSidebarNav.tsx +d7884ce90b9845e6e8aa737dfe02062b91b11c91 fix(web): make settings sidebar sub-section buttons full width (#9562) 1 1 apps/web/src/components/settings/SettingsSidebarNav.tsx +65f1839ae82af4e67f389f23e4ccc50f51a4a83f fix(web): keep codex restart responses continuous (#9560) 2 2 apps/web/src/components/chat/MessagesTimeline.logic.test.ts;apps/web/src/components/chat/MessagesTimeline.logic.ts +fee2e0ff8168b82ab19f496fcc874c1f3871f522 test(web): fix flaky startup and Tailwind tests (#9558) 2 0 +9e1bc36a0843699db54ee28abbdac70584ae8f33 fix(web): keep the last message visible when the resting composer expands (#9553) 5 3 apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/ChatComposer.tsx;docs/user/composer.md +710f6dc417ebf303eede3df3605a6938482d83ab fix(web): simplify expanded tool details (#9549) 1 1 apps/web/src/components/chat/MessagesTimeline.tsx +f96a220b5b154ea44c94bf43929c6362cd511699 ci: add on-demand Windows test workflow (#9538) 3 0 +4e547318b60031eb546d8cf2b84ad9fa0785a87a fix(server): find newly opened pull requests after agent turns (#9125) 11 6 apps/server/integration/OrchestrationEngineHarness.integration.ts;apps/server/src/git/GitWorkflowService.ts;apps/server/src/orchestration/Layers/CheckpointReactor.test.ts;apps/server/src/orchestration/Layers/CheckpointReactor.ts;apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts;docs/internals/overview.md +1641b4aba58ab495cad7a9800b173af3416e16dd feat(usage): redeem Codex reset credits from the Limits tab (#9534) 18 9 apps/server/src/auth/RpcAuthorization.ts;apps/server/src/provider/Drivers/CodexDriver.ts;apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts;apps/server/src/provider/Layers/ProviderRegistry.test.ts;apps/server/src/provider/ProviderDriver.ts;apps/server/src/server.ts;apps/server/src/ws.ts;packages/client-runtime/src/state/server.ts;packages/contracts/src/rpc.ts +232de5e8aac61e6f3de4bc61d10746167db9e905 feat(marketing): fresh screenshot and floating marks on the homepage (#9547) 6 2 apps/marketing/public/app-desktop.webp;apps/marketing/src/pages/index.astro +617edab6539ee6573055dc9fc45fdeacdb12f673 fix(server): reveal normalized paths in File Explorer (#9551) 2 0 +3e2c1a66f74f0a45768332c360cd3682f61129e1 fix(web): thread error banner no longer shifts the chat (#9473) 2 1 apps/web/src/components/ChatView.tsx +f239b77df93077e40c27cc5c5909e94266571859 fix(web): close composer menus when their controls hide (#9541) 6 1 apps/web/src/components/chat/ChatComposer.tsx +3c3e05ccfe34ab7af273f4a4faa72909cafd7a21 fix(web): measure collapsed model labels at their visible width (#9540) 2 0 +54aef6fbe16f637092505b30bd25230c4b0744d8 fix(web): restore composer controls as space becomes available (#9539) 2 0 +5989de44a24888dab02854477ea1d0f50ac3a4a6 fix(mobile): keep store screenshots free of system banners and show dictation (#9548) 2 0 +c5ba51d629b3813182cf3e161cc3f23b1e541dc3 feat(providers): add context compaction command (#9293) 53 42 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx;apps/mobile/src/features/threads/ThreadComposer.tsx;apps/mobile/src/features/threads/ThreadDetailScreen.tsx;apps/mobile/src/features/threads/ThreadFeed.tsx;apps/mobile/src/features/threads/ThreadRouteScreen.tsx;apps/mobile/src/lib/threadActivity.test.ts;apps/mobile/src/lib/threadActivity.ts;apps/mobile/src/state/use-thread-composer-state.ts;apps/mobile/src/state/use-thread-outbox-drain.ts;apps/server/integration/orphanedProviderSessionStartup.integration.test.ts;apps/server/src/orchestration/Layers/CheckpointReactor.test.ts;apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts;apps/server/src/orchestration/Layers/ProjectionPipeline.ts;apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts;apps/server/src/orchestration/Layers/ProviderCommandReactor.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts;apps/server/src/provider/Layers/ClaudeAdapter.test.ts;apps/server/src/provider/Layers/ClaudeAdapter.ts;apps/server/src/provider/Layers/CodexAdapter.test.ts;apps/server/src/provider/Layers/CodexAdapter.ts;apps/server/src/provider/Layers/CursorProvider.ts;apps/server/src/provider/Layers/GrokProvider.ts;apps/server/src/provider/Layers/OpenCodeAdapter.test.ts;apps/server/src/provider/Layers/OpenCodeAdapter.ts;apps/server/src/provider/Layers/ProviderRegistry.test.ts;apps/server/src/provider/Layers/ProviderService.test.ts;apps/server/src/provider/Layers/ProviderService.ts;apps/server/src/provider/Layers/ProviderSessionReaper.test.ts;apps/server/src/provider/Services/ProviderAdapter.ts;apps/server/src/provider/Services/ProviderService.ts;apps/server/src/serverRuntimeStartup.reconcile.test.ts;apps/web/src/components/ChatView.logic.test.ts;apps/web/src/components/ChatView.logic.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/ChatComposer.tsx;apps/web/src/components/chat/MessagesTimeline.logic.test.ts;apps/web/src/components/chat/MessagesTimeline.logic.ts;apps/web/src/components/chat/MessagesTimeline.test.tsx;apps/web/src/components/chat/MessagesTimeline.tsx;docs/user/composer.md;packages/contracts/src/providerRuntime.ts +6f405370c8e552da9dcfdd6922e85789fd918340 fix(dev): keep shared dev reloads and hot updates working (#9543) 11 0 +dddc0bdcb2230147e207efb17df2e49dbe1bdd8c fix(server): include SQLite conditions in persistence errors 2 0 +07c4ab5077fa9c32bf34ab07dd2caa3907878dd9 fix(web): keep automatic project icons consistent (#9535) 5 2 apps/web/src/components/LegacySidebar.tsx;apps/web/src/components/Sidebar.tsx +0ba06a122bc73f705bfc18875366b4eeb1160992 fix(web): settle the resting composer layout with a pixel of slack (#9482) 3 1 apps/web/src/components/chat/ChatComposer.tsx +f54ab901fa77f76eeb1e1cdfa103b9ed6f5ee4ca Fix worktree removal timing out on large install trees (#3902) 2 2 apps/server/src/vcs/GitVcsDriverCore.test.ts;apps/server/src/vcs/GitVcsDriverCore.ts +6319a9714881a1d25549f797c468fabebae92813 fix(desktop): preview CDP sessions no longer hard-crash the app (#9068) 2 0 +75ab5ab3fb6ad35117da754644c404a31b2fed84 fix(codex): accept rate limit errors on thread resume (#8897) 3 0 +b90898077e60290a1eb7bea4224f325fd3bb1595 fix(server): back off relay client restarts after rapid exits (#8788) 2 0 +2b96220f00de09b61327c8e881b7f509f8cc5a79 fix(server): settle branch threads immediately on pull request merge (#9528) 3 2 apps/server/src/orchestration/ThreadSettlementReactor.test.ts;apps/server/src/orchestration/ThreadSettlementReactor.ts +343db2c328af56fe0fa7672f3af055550832689b feat(web): reorganize settings pages (#9354) 15 5 apps/web/src/components/settings/ProviderInstanceCard.tsx;apps/web/src/components/settings/SettingsPanels.tsx;apps/web/src/components/settings/SettingsSidebarNav.tsx;apps/web/src/components/settings/settingsSearch.test.ts;apps/web/src/components/settings/settingsSearch.ts +19d8ab2ae9fc562ee7b216a0d72903fbfafa9572 feat(usage): show Codex and Claude subscription limits on a Limits tab (#9507) 56 21 apps/server/src/environment/ServerEnvironment.ts;apps/server/src/provider/Drivers/ClaudeDriver.ts;apps/server/src/provider/Layers/ClaudeAdapter.test.ts;apps/server/src/provider/Layers/ClaudeAdapter.ts;apps/server/src/provider/Layers/CodexAdapter.ts;apps/server/src/provider/Layers/ProviderAdapterRegistry.test.ts;apps/server/src/provider/Layers/ProviderRegistry.test.ts;apps/server/src/provider/Layers/ProviderUsageLimitsIngestion.ts;apps/server/src/server.test.ts;apps/server/src/server.ts;apps/server/src/ws.ts;apps/web/src/state/server.ts;apps/web/src/timestampFormat.ts;packages/client-runtime/src/state/server.ts;packages/contracts/src/environment.ts;packages/contracts/src/index.ts;packages/contracts/src/providerRuntime.ts;packages/contracts/src/rpc.ts;packages/contracts/src/server.ts;packages/contracts/src/settings.ts;packages/shared/package.json +0a0b6be96833adae68b36540c00d347eda278736 fix(web): keep right panel controls clickable (#9517) 2 2 apps/web/src/components/ChatView.tsx;apps/web/src/components/RightPanelTabs.tsx +d76b24dd15a219666941ab1b4967d8f738adcda0 feat(codex): support async questions (#9512) 26 22 apps/mobile/src/lib/threadActivity.test.ts;apps/mobile/src/lib/threadActivity.ts;apps/server/src/checkpointing/CheckpointDiffQuery.test.ts;apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts;apps/server/src/orchestration/Layers/OrchestrationEngine.ts;apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts;apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts;apps/server/src/orchestration/decider.ts;apps/server/src/orchestration/projector.ts;apps/server/src/project/ProjectSetupScriptRunner.test.ts;apps/server/src/provider/Layers/CodexAdapter.test.ts;apps/server/src/provider/Layers/CodexAdapter.ts;apps/server/src/provider/Layers/ProviderSessionReaper.test.ts;apps/server/src/server.test.ts;apps/server/src/serverRuntimeStartup.reconcile.test.ts;apps/server/src/serverRuntimeStartup.test.ts;apps/web/src/session-logic.test.ts;apps/web/src/session-logic.ts;docs/internals/providers.md;packages/contracts/src/providerRuntime.ts +e3723e06b5b154a3e0ede55c02e2cabc5301d3bf chore: drop comment events from Cursor hygiene forwarder (#9527) 1 0 +9d28c21a26aeef198cb064fe466e49cbeabfe09c fix(auth): keep pairing credentials out of access read models (#9523) 11 1 apps/server/src/server.test.ts +44701efd6790c39dc82cb08104f7295e1780210f chore: forward issue/PR/discussion events to Cursor hygiene (#9518) 1 0 +9c9ae3dc0e94a957d9c4a61bb211caf914828054 fix(server): keep events during thread subscription startup (#9521) 2 2 apps/server/src/server.test.ts;apps/server/src/ws.ts +c0ebc882b88dbcffd5a712e403b3c3c517ba4ea6 fix(web): return focus to the composer after closing a media preview (#9513) 1 0 +522ebe65a542ace6f22d9ad95f95ef9ade7e87f1 fix(web): keep the composer open while selecting timeline text (#9499) 3 1 apps/web/src/components/chat/ChatComposer.tsx +6382268323f86e01b2d40206bcf33beccb3fb64a fix(web): let paste expand a resting composer (#9498) 1 1 apps/web/src/components/ChatView.tsx +f8a14b28ff80a92d8f4df9a9aa53bfacb8195199 feat(antigravity): show subagent calls and results (#9515) 7 5 apps/mobile/src/lib/threadActivity.test.ts;apps/mobile/src/lib/threadActivity.ts;apps/server/src/provider/Layers/AntigravityAdapter.test.ts;apps/server/src/provider/Layers/AntigravityAdapter.ts;apps/server/src/provider/acp/AntigravityProtocol.ts +3653cb22ffb30bf133fecc30c955941fe267cf1c fix(desktop): address the browser import review left over from the stack (#9516) 9 0 +8ea52c8f2f4361e875d72ab30d72d37cfae4d87f fix(antigravity): update managed runtime to 1.1.1 (#9509) 2 0 +eb334ca57448742139fb8ec38fb397c1e51c45c5 fix(antigravity): handle native sign-in URLs on stderr (#9514) 6 4 apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts;apps/server/src/provider/acp/AcpSessionRuntime.ts;apps/server/src/provider/acp/AntigravityAcpSupport.ts;docs/internals/providers.md +baf67b6e3accd48d510fd0d39a4e6b978a1eea80 fix(antigravity): keep model choices up to date (#9511) 10 7 apps/server/src/provider/Drivers/AntigravityDriver.ts;apps/server/src/provider/Layers/AntigravityAdapter.test.ts;apps/server/src/provider/Layers/AntigravityAdapter.ts;apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts;apps/server/src/provider/acp/AcpRuntimeModel.ts;apps/server/src/provider/acp/AcpSessionRuntime.ts;docs/internals/providers.md +f25e4428961982e3935300cfd3c78f7d0fac4ee9 fix(antigravity): allow slow runtime startup during setup (#9510) 7 2 apps/server/src/provider/Drivers/AntigravityDriver.test.ts;apps/server/src/provider/Drivers/AntigravityDriver.ts +498ab9c399d5e8c3097a286be14d03238e071ac1 feat(desktop): resolve Chromium cookie keys on Linux (#7261) 27 1 .github/workflows/ci.yml +ff5843410d44796676b06627788d94354849c4d7 feat(desktop): import from Chrome, Edge, Brave, Vivaldi, Opera, Arc and Firefox (#7260) 13 0 +39449e53e31a56103192aa7905e89fc92c977a4a feat(desktop): import browser cookies into a profile (#7255) 27 5 apps/web/src/components/settings/settingsSearch.test.ts;apps/web/src/components/settings/settingsSearch.ts;packages/contracts/src/index.ts;packages/contracts/src/ipc.ts;pnpm-lock.yaml +e01c153c18a94a2aa33df7115c6cfee1eb09880f fix(antigravity): forward Google sign-in URLs from browser helper (#9425) 9 3 apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts;apps/server/src/provider/acp/AcpSessionRuntime.ts;apps/server/src/provider/acp/AntigravityAcpSupport.ts +ef4cc6085e24d6309252412c6dab5482ac11a09f fix(mobile): resolve Antigravity provider icon and normalize driver matching (#9495) 2 0 +0aae1e2ad7ab174004f39746eb4c72b905de932d fix(antigravity): discover legacy workspace skills (#9410) 3 0 +80b53730d1e821563e5c348fdf4f5fc7616a49f7 fix(mobile): let back swipe pop from horizontal scroll edges (#9493) 3 1 pnpm-lock.yaml +409bc4fa6f3bb9869052bdba4244b30606457f20 fix(mobile): keep the machine glyph next to the environment label (#9486) 1 1 apps/mobile/src/features/threads/thread-list-v2-items.tsx +12e8997e58dbca8f1bd8c63b67d662eb69cf0e0d fix(web): keep agent browser preview visible (#9484) 19 7 apps/web/src/components/ChatView.logic.test.ts;apps/web/src/components/ChatView.logic.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/preview/ThreadPreviewMiniPlayer.tsx;apps/web/src/components/preview/previewMiniPlayerLayout.ts;apps/web/src/rightPanelLayout.ts;packages/contracts/src/settings.ts +c726c30a148c2add6a3ec7f31f54ae48dc5d2f0c fix(web): keep opencode icon hollow in collapsed composer (#9492) 2 1 apps/web/src/components/chat/ChatComposer.tsx +678f23a69943e3eef7171f452b44f2931d2ef21f fix(desktop): restore second-press quit fallback (#9485) 2 0 +77138cf33194a303adfbbd69cc93efa69f84245d fix(web): dont collapse composer when interacting with bottom row (#9490) 7 5 apps/web/src/components/BranchToolbar.tsx;apps/web/src/components/BranchToolbarBranchSelector.tsx;apps/web/src/components/BranchToolbarEnvModeSelector.tsx;apps/web/src/components/BranchToolbarEnvironmentSelector.tsx;apps/web/src/components/chat/ChatComposer.tsx +0869ad648b67a286d7a47af878f1d256d0ff689f fix(web): let the PR reviewer and label search boxes take keystrokes (#9479) 1 0 +4b8b5d9e0177002c84a6f55837670aa0ef816915 fix(desktop): refresh generated annotation styles (#9488) 1 0 +373be93e68bf3d32207471b27e976ac84bff806a fix(web): move workflow approval beside checks (#9465) 1 1 apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx +03728361aa7beb9c13da320097450e6fe65aac3e feat(web): let users turn off composer collapse on blur and scroll (#9469) 10 7 apps/desktop/src/settings/DesktopClientSettings.test.ts;apps/web/src/components/chat/ChatComposer.tsx;apps/web/src/components/settings/SettingsPanels.tsx;apps/web/src/components/settings/settingsSearch.ts;docs/user/composer.md;packages/contracts/src/settings.test.ts;packages/contracts/src/settings.ts +493fbb58870c912b9cb2ba6c2f1dae938877a59a fix(web): reuse pull request list data while loading (#9467) 3 2 apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx;apps/web/src/routes/_chat.pull-requests.tsx +d2b6f3b9296f682c6158b894ab33d98d0c4bfb2b fix(server): full-access OpenCode threads no longer ask for approvals (#9282) 3 3 apps/server/src/provider/Layers/OpenCodeAdapter.test.ts;apps/server/src/provider/Layers/OpenCodeAdapter.ts;docs/internals/providers.md +36c4e9cf5c0123e33d65f2af9497ee090404b532 fix(server): keep a/ and b/ prefixes in rendered git patches (#9438) 4 3 apps/server/src/vcs/GitVcsDriver.ts;apps/server/src/vcs/GitVcsDriverCore.test.ts;apps/server/src/vcs/GitVcsDriverCore.ts +de025aa69ffb0ce1a45d30aed25c60454660b62d fix(mobile): show loading and syncing in the working pill (#9466) 4 3 apps/mobile/src/features/threads/ThreadComposer.tsx;apps/mobile/src/features/threads/ThreadDetailScreen.tsx;apps/mobile/src/features/threads/ThreadRouteScreen.tsx +db8d60f486c5fc1a80d01b591a359f0c87f0868c fix(web): render transparent previews on white (#9463) 1 0 +46e8b1a23ab14fa2c128c6b315955d8eb976d85f fix(web): make right panel tabs easier to scroll (#9461) 1 1 apps/web/src/components/RightPanelTabs.tsx +d5825e1d2fb1703ced2bbe2661f6a4937dd530bf fix(web): stop clipping the traits chevron on long Codex effort labels (#9433) 1 0 +126afb56fca56c663f4f40acd46f123ab27eee2b fix(web): banner buttons no longer expand the resting composer (#9452) 3 1 apps/web/src/components/chat/ChatComposer.tsx +8bd544cdfd22aa38ab82bc1adc0b851755a299ef fix(web): keep agent images collapsed (#9460) 1 1 apps/web/src/components/chat/MessagesTimeline.tsx +c78f05a45e1c2b274d8b0ab2b4d2d88b4767c968 fix(server): reuse pr state when settling threads (#9459) 2 2 apps/server/src/orchestration/ThreadSettlementReactor.test.ts;apps/server/src/orchestration/ThreadSettlementReactor.ts +4e89d74436a167c01f25a6a5283638843398ea3a fix(web): make project icons the default (#9457) 6 0 +645d58547d282eb2aaf6c48e5907625fc112386a fix(web): prioritize authored pull requests (#9453) 4 1 apps/web/src/routes/_chat.pull-requests.tsx +21b9dda5afb00a33e228a68d2ccc885bba7285dc fix(web): unify skeleton loading animations on one pulse (#9448) 4 1 apps/web/src/index.css +d4ba2a1f11498eae9683f6dc95a08b1c17c29765 fix(composer): mute fast icon when collapsed (#9451) 1 0 +2120fbc185737b71f09de020b95224f9e636d1e5 fix(web): avoid duplicate Antigravity install status (#9419) 2 0 +cfddb4201df8941bbfde008919da70fe5ec7552b fix(mobile): skip unsupported shared settings targets (#9381) 6 1 docs/internals/overview.md +57626eb6eaa436b22260068d23f4e3df5f389cd1 fix(web): prevent loading ssh environments from overriding navigation (#9168) 2 1 apps/web/src/hooks/useHandleNewThread.ts +098bf5329727fcd7d973bf842e6b4d50d6e7b924 fix(web): preserve explicit preview navigation URLs (#8902) 2 0 +77e35c561259733d880ab62a43aad0894d301d9b fix(web): send cited messages with Cmd+Enter (#9307) 5 1 apps/web/src/components/chat/ChatComposer.tsx +fff33f9e851912363c5b1f3ac65598be35eb5f0d perf(ci): reuse dependency checks in release builds (#9399) 2 0 +1e051873094c0c75cd35fef89c90461c22cce76b fix(antigravity): refresh the model manifest so older Gemini models fold as legacy (#9397) 5 1 apps/server/src/provider/Drivers/AntigravityDriver.ts +19c97ea56d30b3a2de31a060f8f47d6b7404b78f fix(web): unlock the composer when preview capture fails (#9127) 8 1 packages/contracts/src/ipc.ts +2b745efe57cddc1753d3007d081c64bd20e3ab79 fix(usage): price new models without waiting a day for the rate table (#9202) 11 4 apps/server/src/auth/RpcAuthorization.ts;apps/server/src/ws.ts;packages/client-runtime/src/state/server.ts;packages/contracts/src/rpc.ts +2aa907b1969237efdaced29612fb46ba51be7041 fix(mobile): show an error instead of an endless preview spinner (#9123) 6 0 +06336460c9988f29c71e839c4c9c840c4552e077 feat(providers): add Google Antigravity via the official ACP agent (#9348) 169 83 README.md;apps/mobile/src/features/threads/NewTaskDraftScreen.tsx;apps/mobile/src/features/threads/PendingApprovalCard.tsx;apps/mobile/src/features/threads/PendingUserInputCard.tsx;apps/mobile/src/features/threads/ThreadComposer.tsx;apps/mobile/src/features/threads/ThreadDetailScreen.tsx;apps/mobile/src/lib/modelOptions.ts;apps/mobile/src/lib/threadActivity.test.ts;apps/mobile/src/lib/threadActivity.ts;apps/mobile/src/state/use-selected-thread-requests.ts;apps/mobile/src/state/use-thread-composer-state.ts;apps/mobile/src/state/use-thread-outbox-drain.test.ts;apps/mobile/src/state/use-thread-outbox-drain.ts;apps/server/integration/OrchestrationEngineHarness.integration.ts;apps/server/integration/orphanedProviderSessionStartup.integration.test.ts;apps/server/package.json;apps/server/scripts/acp-mock-agent.ts;apps/server/src/auth/RpcAuthorization.ts;apps/server/src/orchestration/Layers/CheckpointReactor.test.ts;apps/server/src/orchestration/Layers/CheckpointReactor.ts;apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts;apps/server/src/orchestration/Layers/ProviderCommandReactor.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts;apps/server/src/provider/Drivers/AntigravityDriver.test.ts;apps/server/src/provider/Drivers/AntigravityDriver.ts;apps/server/src/provider/Layers/AntigravityAdapter.test.ts;apps/server/src/provider/Layers/AntigravityAdapter.ts;apps/server/src/provider/Layers/ProviderAuthService.test.ts;apps/server/src/provider/Layers/ProviderAuthService.ts;apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts;apps/server/src/provider/Layers/ProviderRegistry.test.ts;apps/server/src/provider/Layers/ProviderRegistry.ts;apps/server/src/provider/Layers/ProviderService.test.ts;apps/server/src/provider/Layers/ProviderService.ts;apps/server/src/provider/Layers/ProviderSessionReaper.test.ts;apps/server/src/provider/ProviderDriver.ts;apps/server/src/provider/Services/ProviderAdapter.ts;apps/server/src/provider/Services/ProviderService.ts;apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts;apps/server/src/provider/acp/AcpRuntimeModel.test.ts;apps/server/src/provider/acp/AcpRuntimeModel.ts;apps/server/src/provider/acp/AcpSessionRuntime.ts;apps/server/src/provider/acp/AntigravityAcpSupport.ts;apps/server/src/provider/acp/AntigravityProtocol.ts;apps/server/src/provider/builtInDrivers.ts;apps/server/src/provider/providerInstallation.test.ts;apps/server/src/server.test.ts;apps/server/src/server.ts;apps/server/src/serverRuntimeStartup.reconcile.test.ts;apps/server/src/ws.ts;apps/web/src/components/ChatView.logic.test.ts;apps/web/src/components/ChatView.logic.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/ChatComposer.tsx;apps/web/src/components/chat/ComposerPendingApprovalActions.test.tsx;apps/web/src/components/chat/ComposerPendingApprovalActions.tsx;apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx;apps/web/src/components/settings/ProviderInstanceCard.tsx;apps/web/src/components/settings/ProviderSettingsForm.test.ts;apps/web/src/components/settings/SettingsPanels.tsx;apps/web/src/components/settings/providerDriverMeta.ts;apps/web/src/components/settings/settingsSearch.test.ts;apps/web/src/components/settings/settingsSearch.ts;apps/web/src/composerDraftStore.ts;apps/web/src/pendingUserInput.test.ts;apps/web/src/pendingUserInput.ts;apps/web/src/session-logic.test.ts;apps/web/src/session-logic.ts;docs/internals/overview.md;docs/internals/providers.md;packages/client-runtime/src/rpc/client.ts;packages/client-runtime/src/state/server.ts;packages/contracts/src/index.ts;packages/contracts/src/model.ts;packages/contracts/src/orchestration.ts;packages/contracts/src/providerRuntime.ts;packages/contracts/src/rpc.ts;packages/contracts/src/server.ts;packages/contracts/src/settings.ts;packages/effect-acp/src/client.ts;packages/effect-acp/src/protocol.test.ts;packages/effect-acp/src/protocol.ts;pnpm-lock.yaml +652515a349741d234111b85f27597be3265d1ffc fix(web): render assistant images inline in chat (#9126) 4 3 apps/web/src/components/chat/MessagesTimeline.logic.test.ts;apps/web/src/components/chat/MessagesTimeline.logic.ts;apps/web/src/components/chat/MessagesTimeline.tsx +044ea8e347d980a215057c325de8335d38f0f9aa fix(web): stop the resting composer layout loop (#9393) 7 3 apps/web/src/components/BranchToolbar.logic.ts;apps/web/src/components/BranchToolbar.tsx;apps/web/src/components/chat/ChatComposer.tsx +18573d60aab1344bf124a044b01445086e910c4c fix(claude): expand slash commands when a message has attachments (#9122) 2 2 apps/server/src/provider/Layers/ClaudeAdapter.test.ts;apps/server/src/provider/Layers/ClaudeAdapter.ts +5d1b02cdeebff4b0b4f15a1e8425b06ae3cfe8d1 feat(marketing): put named-developer quotes on the landing page (#9385) 10 0 +4b26132d2c740ff344ef3fae7ae62e9765759e29 "fix(web): keep trailing tool groups out of ""Worked for"" accordion (#9384)" 4 4 apps/web/src/components/chat/MessagesTimeline.logic.test.ts;apps/web/src/components/chat/MessagesTimeline.logic.ts;apps/web/src/components/chat/MessagesTimeline.test.tsx;apps/web/src/components/chat/MessagesTimeline.tsx +5b8445b7a777ab1070aa97b062b1618971073a96 fix(web): collapse the resting composer (#7855) 33 12 apps/web/src/components/BranchToolbar.logic.test.ts;apps/web/src/components/BranchToolbar.logic.ts;apps/web/src/components/BranchToolbar.tsx;apps/web/src/components/BranchToolbarBranchSelector.tsx;apps/web/src/components/BranchToolbarEnvModeSelector.tsx;apps/web/src/components/BranchToolbarEnvironmentSelector.tsx;apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/ChatComposer.tsx;apps/web/src/components/chat/ComposerPrimaryActions.tsx;apps/web/src/components/chat/MessagesTimeline.test.tsx;apps/web/src/components/chat/MessagesTimeline.tsx;docs/user/composer.md +24799de4f85a9071afc2420362784ea46041d544 fix(mobile): size expanded tool groups correctly (#9359) 1 0 +1f7a3c11ca864898b136a35011ad10777ea07544 fix(mobile): pressed and disabled styles no longer apply unconditionally (#9355) 2 1 pnpm-lock.yaml +cf0bb4c3571badbc5aaa8189cd5cbe3563ec73c1 fix(web): match project icon chooser button sizes (#9368) 1 0 +c89e3e12a41e13e09e0103d08a41d0688a99fb49 fix(web): settled sidebar rows use the project fallback icon (#9366) 1 1 apps/web/src/components/Sidebar.tsx +829c3db94830fc70b5754513b8a370f7301ca213 fix(environments): draw the machine icon everywhere an environment is named (#9365) 10 5 apps/mobile/src/features/projects/AddProjectScreen.tsx;apps/mobile/src/features/threads/NewTaskDraftScreen.tsx;apps/web/src/components/BranchToolbarEnvironmentSelector.tsx;apps/web/src/components/CommandPalette.tsx;apps/web/src/components/ThreadStatusIndicators.tsx +5eb4f452ee0fcde7b5bbc93d62de9118b70a33b2 test(web): remove static markup-only component tests (#9364) 6 0 +d4bd8923ad8cab346a854967015b06d9e5cd77f7 feat(web): mod+w closes the active right panel tab before the window (#9363) 7 4 apps/web/src/components/ChatView.tsx;apps/web/src/keybindings.test.ts;apps/web/src/routes/_chat.pull-requests.tsx;packages/contracts/src/keybindings.ts +b5f4e8137b3cbd657fbe2b698f9db4e321acbc3d feat(web): suggest ssh hosts in a dropdown under the host field (#9171) 9 1 packages/contracts/src/ipc.ts +9f9359bd8132c425493720080149dcc0d3da9436 fix(web): stop usage summary requests reporting slow RPCs (#9358) 2 0 +854541a04e07b7960698b381bcfd2fda73eb276c fix(pull-requests): shared state + not settling? (#9332) 9 5 apps/server/src/orchestration/ThreadSettlementReactor.test.ts;apps/server/src/orchestration/ThreadSettlementReactor.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/ThreadStatusIndicators.tsx;apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx +48ba76bc26337f23d1f0991bbac51f996a3333dc fix(web): collapse oldest pull request comments (#9323) 1 0 +6cf0c6ea55d281f65c80502ec1871b0adf472025 feat: display native app and browser icons in work logs (#9093) 32 21 apps/mobile/src/features/threads/ThreadFeed.tsx;apps/mobile/src/lib/threadActivity.test.ts;apps/mobile/src/lib/threadActivity.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts;apps/server/src/provider/Layers/CodexAdapter.test.ts;apps/server/src/provider/Layers/CodexAdapter.ts;apps/server/src/server.test.ts;apps/server/src/server.ts;apps/server/src/ws.ts;apps/web/src/components/chat/MessagesTimeline.logic.test.ts;apps/web/src/components/chat/MessagesTimeline.logic.ts;apps/web/src/components/chat/MessagesTimeline.tsx;apps/web/src/session-logic.test.ts;apps/web/src/session-logic.ts;packages/client-runtime/package.json;packages/client-runtime/src/work-log/presentation.test.ts;packages/client-runtime/src/work-log/presentation.ts;packages/contracts/src/assets.ts;packages/contracts/src/providerRuntime.ts;packages/shared/package.json +0bc59bbae391ee45ab3a7cfb2dc703c8b27e5772 fix(web): let the pull request list use wide screens (#9351) 2 1 apps/web/src/routes/_chat.pull-requests.tsx +1575ada305b9686b9771df2dca304f391e85a76e fix(mobile): stop indented code overflowing Android chat bubbles (#9347) 2 0 +f6c04c552c203350705f9ab1e47773ea736af245 feat(web): add customizable project icons (#9137) 34 16 apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts;apps/server/src/orchestration/Layers/ProjectionPipeline.ts;apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts;apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts;apps/server/src/orchestration/decider.ts;apps/server/src/orchestration/projector.ts;apps/server/src/persistence/Migrations.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/CommandPalette.tsx;apps/web/src/components/LegacySidebar.tsx;apps/web/src/components/Sidebar.tsx;apps/web/src/components/chat/ChatHeader.tsx;apps/web/src/components/settings/SettingsPanels.tsx;apps/web/src/routes/_chat.pull-requests.tsx;packages/contracts/src/orchestration.test.ts;packages/contracts/src/orchestration.ts +6a5a18cb1bc9ea878afa1146950439b5d4744110 fix(web): add press feedback to buttons (#9349) 1 0 +18062da9425909a0a92bce0b692c9de6fbba56ee feat(web): choose whether links open in the default browser or in T3 Code (#9339) 24 8 apps/desktop/src/settings/DesktopClientSettings.test.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/GitActionsControl.tsx;apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx;apps/web/src/components/settings/SettingsPanels.tsx;apps/web/src/components/settings/settingsSearch.test.ts;apps/web/src/components/settings/settingsSearch.ts;packages/contracts/src/settings.ts +d42254dfb462e4ab23a42d4bef53b1ce00a72396 fix(web): resolve Vite sourcemap and supports warnings (#9343) 3 1 apps/web/src/components/chat/ComposerBanner.tsx +2a3cfe456375fd34b906f849b04706109dc74170 fix(web): collapse PR header actions to icons when narrow (#9334) 1 1 apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx +5f84efa1ec2fb3cd6f6c54545cc34bb77ac1ddb8 feat(web): add PageUp/PageDown chat navigation (#9315) 5 2 apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/ChatComposer.tsx +1aa44a071f66bdfd9430356ab824b5a6985fb459 feat(web): add a file tree to the diff panel and pull request code tab (#9330) 8 1 apps/web/src/components/DiffPanel.tsx +f5fbb1bcb0db378c61addd5b49ef2d95bd888168 chore: upgrade vite-plus to 0.3.0 (#9327) 31 8 apps/mobile/src/features/terminal/ThreadTerminalRouteScreen.tsx;apps/mobile/src/features/threads/threadListV2.ts;apps/server/src/mcp/McpHttpServer.ts;apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts;apps/server/src/provider/Layers/ClaudeAdapter.ts;apps/server/src/provider/Layers/CodexAdapter.test.ts;apps/server/src/provider/Layers/ProviderService.test.ts;pnpm-lock.yaml +3b2de9da1c8763602e283e8d14b41b5d57a9d0c7 chore: dedupe lightningcss and tailwind node bindings (#9331) 3 2 apps/mobile/generated-uniwind-themes.css;pnpm-lock.yaml +9409dd20a9fbce491d49d09c79b289d8fb8bfe3e fix(web): make the diff layout toggle a persisted setting (#9326) 9 7 apps/desktop/src/settings/DesktopClientSettings.test.ts;apps/web/src/components/DiffPanel.tsx;apps/web/src/components/settings/SettingsPanels.tsx;apps/web/src/components/settings/settingsSearch.ts;apps/web/src/diffPanelStore.test.ts;apps/web/src/diffPanelStore.ts;packages/contracts/src/settings.ts +12f1fc427efad4b683835a72bda6f74bebb5d641 fix(web): line up the titlebar wordmark label and version pill (#9255) 2 0 +66419a1d1b80110c9702edae641bddcc2888fc98 fix(dev): share dev servers on the loopback Vite actually binds (#9324) 2 0 +85f2479ffe5c9d8ffa91f1bfae5234df4061292f refactor(mobile): style plain views with Uniwind classes instead of the theme bridge (#9322) 5 2 apps/mobile/src/features/threads/thread-list-v2-items.tsx;vite.config.ts +b9b1b8fdddf9d006fdb820af770063e1f968345b chore(ci): narrow the Effect conventions check-run agent (#9321) 1 0 +194f838e7636f97739c440c7855aed195dbd7f52 chore: audit lint directives and move plugin allowlists into config (#9300) 21 3 apps/server/src/relay/AgentAwarenessRelay.test.ts;apps/server/src/server.test.ts;vite.config.ts +ec44bc56f598be16ffbc22ed0e4e095447043844 fix(chat): keep live tool labels in present tense (#9316) 8 7 apps/mobile/src/lib/threadActivity.test.ts;apps/mobile/src/lib/threadActivity.ts;apps/web/src/components/chat/MessagesTimeline.logic.test.ts;apps/web/src/components/chat/MessagesTimeline.logic.ts;apps/web/src/components/chat/MessagesTimeline.test.tsx;packages/client-runtime/src/work-log/presentation.test.ts;packages/client-runtime/src/work-log/presentation.ts +922bd692251bc803c12a3fab159efe83c957bb70 refactor(media): unify file and media previews across clients (#9253) 52 11 apps/mobile/src/features/threads/ThreadFeed.tsx;apps/web/src/components/ChatView.logic.test.ts;apps/web/src/components/ChatView.logic.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/ChatComposer.tsx;apps/web/src/components/chat/MessagesTimeline.test.tsx;apps/web/src/components/chat/MessagesTimeline.tsx;docs/user/composer.md;packages/client-runtime/package.json;packages/client-runtime/src/work-log/presentation.test.ts;packages/client-runtime/src/work-log/presentation.ts +31eeb443305a4e11c8b20a7c8ff2b3f5e841eb0f fix(sidebar): collapse settled and snoozed shelves by default (#9314) 4 1 apps/web/src/components/Sidebar.tsx +9ebbeda5a03fd8fce7be147b65ea396e50721c68 feat(web): apply and remove labels from the pull request tab (#9313) 19 3 apps/server/src/auth/RpcAuthorization.ts;apps/server/src/ws.ts;packages/contracts/src/rpc.ts +0fbb94248581aaefda36e4f8a40ec2c6455c779a feat(environments): draw each environment as the machine it runs on (#9299) 32 17 apps/mobile/src/features/home/HomeScreen.tsx;apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx;apps/mobile/src/features/threads/thread-list-v2-items.tsx;apps/server/src/environment/ServerEnvironment.ts;apps/web/src/components/BranchToolbar.logic.ts;apps/web/src/components/BranchToolbar.tsx;apps/web/src/components/ChatView.tsx;apps/web/src/components/LegacySidebar.tsx;apps/web/src/components/Sidebar.tsx;apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx;apps/web/src/components/settings/settingsSearch.ts;apps/web/src/routes/_chat.pull-requests.tsx;packages/contracts/src/baseSchemas.ts;packages/contracts/src/environment.ts;packages/contracts/src/server.ts;packages/contracts/src/settings.test.ts;packages/contracts/src/settings.ts +d897641d738c67dd7c12cbb3a273b43fe17a5eb1 fix(pull-requests): keep cached PR chrome on reopen (#9294) 5 3 apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx;apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts;apps/web/src/components/pullRequest/pullRequestDetail.logic.ts +355fbd96d5e90b52961ac5f1e035112fc3bad4a9 fix(web): stop remounting markdown on every activity delta (#9306) 1 1 apps/web/src/components/chat/MessagesTimeline.tsx +ef6cc0b362019f32152470ed96c1aa1b813fb7f6 chore(ci): only run check-run agents on vouched contributors (#9298) 2 0 +e94603adfac7d8734f9af01e33f67e776daf482d chore(ci): narrow the UI consistency check-run agent (#9297) 1 0 +77512998485718eb1b6c336e20f196eb40a6a32f feat(web): preview document attachments in the file viewer (#9292) 16 11 apps/server/src/http.test.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/RightPanelTabs.tsx;apps/web/src/components/chat/MessagesTimeline.test.tsx;apps/web/src/components/chat/MessagesTimeline.tsx;apps/web/src/components/files/FilePreviewPanel.tsx;apps/web/src/rightPanelStore.test.ts;apps/web/src/rightPanelStore.ts;apps/web/src/types.ts;docs/user/composer.md;packages/contracts/src/assets.ts +dbc7bfa3f36cc61a3f1a2015e47d71ae9dee5421 fix(opencode): show Reasoning selector for OpenCode models (#9287) 3 0 +2971ec3209d7ef1b00d7ded70fe6342816b1539f fix(server): preserve automatic settlement timestamps (#9254) 22 15 apps/mobile/src/features/threads/thread-list-v2-items.tsx;apps/mobile/src/features/threads/threadListV2.test.ts;apps/mobile/src/features/threads/threadListV2.ts;apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts;apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts;apps/server/src/orchestration/ThreadSettlementReactor.test.ts;apps/server/src/orchestration/ThreadSettlementReactor.ts;apps/server/src/orchestration/decider.ts;apps/server/src/persistence/Migrations.ts;apps/web/src/components/Sidebar.logic.ts;apps/web/src/components/Sidebar.tsx;docs/internals/overview.md;packages/client-runtime/src/state/threadSort.test.ts;packages/client-runtime/src/state/threadSort.ts;packages/contracts/src/orchestration.ts +15fea6c5f40331c8325f33bd08b2dcbf924e935a fix(providers): discover workspace skills everywhere (#9180) 15 10 apps/mobile/src/features/threads/NewTaskDraftScreen.tsx;apps/mobile/src/features/threads/ThreadComposer.tsx;apps/mobile/src/features/threads/ThreadDetailScreen.tsx;apps/server/src/provider/Drivers/CursorDriver.ts;apps/server/src/provider/Drivers/GrokDriver.ts;apps/server/src/provider/Layers/CursorAdapter.test.ts;apps/server/src/provider/Layers/CursorAdapter.ts;apps/server/src/provider/Layers/CursorProvider.test.ts;apps/server/src/provider/Layers/GrokProvider.ts;apps/web/src/components/chat/ChatComposer.tsx +443b4ebfe83fcfe64c34b09ecb5a5fffdebb85c7 fix(pull-requests): missing features & better behaviour (#9188) 34 5 apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx;apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts;apps/web/src/components/pullRequest/pullRequestDetail.logic.ts;apps/web/src/components/pullRequest/pullRequestPresentation.tsx;apps/web/src/routes/_chat.pull-requests.tsx +4ba39a6f408bdee468df2e3ffdf7d5dc08e7b59d fix(desktop): detect installed Spectre libs for Windows builds 1 0 +994bd7373cf3a335c204a617604e690ed4c00cba fix(cursor): honor auto and full access modes (#9283) 5 4 apps/server/src/provider/Layers/CursorAdapter.test.ts;apps/server/src/provider/Layers/CursorAdapter.ts;apps/server/src/provider/acp/CursorAcpSupport.test.ts;apps/server/src/provider/acp/CursorAcpSupport.ts +c742edd46c5b6792ec8647f934a4703f9103aa82 fix(web): show scroll-to-end as soon as the last message slips under the composer (#9280) 4 4 apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/MessagesTimeline.logic.ts;apps/web/src/components/chat/MessagesTimeline.test.tsx;apps/web/src/components/chat/MessagesTimeline.tsx +63f334baf3432c4404ddfc9e71d33bf16575f0ed "Revert ""feat(providers): add context compaction across harnesses"" (#9284)" 35 27 apps/server/integration/orphanedProviderSessionStartup.integration.test.ts;apps/server/src/orchestration/Layers/CheckpointReactor.test.ts;apps/server/src/orchestration/Layers/ProjectionPipeline.ts;apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts;apps/server/src/orchestration/Layers/ProviderCommandReactor.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts;apps/server/src/provider/Layers/ClaudeAdapter.test.ts;apps/server/src/provider/Layers/ClaudeAdapter.ts;apps/server/src/provider/Layers/CodexAdapter.test.ts;apps/server/src/provider/Layers/CodexAdapter.ts;apps/server/src/provider/Layers/CursorProvider.ts;apps/server/src/provider/Layers/GrokProvider.ts;apps/server/src/provider/Layers/OpenCodeAdapter.test.ts;apps/server/src/provider/Layers/OpenCodeAdapter.ts;apps/server/src/provider/Layers/ProviderRegistry.test.ts;apps/server/src/provider/Layers/ProviderService.test.ts;apps/server/src/provider/Layers/ProviderService.ts;apps/server/src/provider/Layers/ProviderSessionReaper.test.ts;apps/server/src/provider/Services/ProviderAdapter.ts;apps/server/src/provider/Services/ProviderService.ts;apps/server/src/serverRuntimeStartup.reconcile.test.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/ChatComposer.tsx;apps/web/src/components/chat/MessagesTimeline.test.tsx;docs/user/composer.md;packages/contracts/src/providerRuntime.ts +064392ffc7fc58fcc3018fd2ba2df33fbb21f1de fix(web): offer browser profiles from the empty-panel launcher (#9279) 1 1 apps/web/src/components/RightPanelTabs.tsx +b59b7d0af9536a2d61ddfcf8d33420b890b2faca fix(web): unify control sizing across settings pages (#9281) 20 4 apps/web/src/components/BranchToolbarBranchSelector.tsx;apps/web/src/components/settings/AddProviderInstanceDialog.tsx;apps/web/src/components/settings/ProviderInstanceCard.tsx;apps/web/src/components/settings/SettingsPanels.tsx +fb93902ee24d4ba380508df33d25478d3baf7a72 feat(web): add proactive panels (#9276) 9 8 apps/desktop/src/settings/DesktopClientSettings.test.ts;apps/web/src/components/ChatView.logic.test.ts;apps/web/src/components/ChatView.logic.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/settings/SettingsPanels.tsx;apps/web/src/components/settings/settingsSearch.ts;packages/contracts/src/settings.test.ts;packages/contracts/src/settings.ts +535557b3f785629e6f48cad40c5a4b78b3b3c5d6 feat(providers): add context compaction across harnesses (#8808) 35 27 apps/server/integration/orphanedProviderSessionStartup.integration.test.ts;apps/server/src/orchestration/Layers/CheckpointReactor.test.ts;apps/server/src/orchestration/Layers/ProjectionPipeline.ts;apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts;apps/server/src/orchestration/Layers/ProviderCommandReactor.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts;apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts;apps/server/src/provider/Layers/ClaudeAdapter.test.ts;apps/server/src/provider/Layers/ClaudeAdapter.ts;apps/server/src/provider/Layers/CodexAdapter.test.ts;apps/server/src/provider/Layers/CodexAdapter.ts;apps/server/src/provider/Layers/CursorProvider.ts;apps/server/src/provider/Layers/GrokProvider.ts;apps/server/src/provider/Layers/OpenCodeAdapter.test.ts;apps/server/src/provider/Layers/OpenCodeAdapter.ts;apps/server/src/provider/Layers/ProviderRegistry.test.ts;apps/server/src/provider/Layers/ProviderService.test.ts;apps/server/src/provider/Layers/ProviderService.ts;apps/server/src/provider/Layers/ProviderSessionReaper.test.ts;apps/server/src/provider/Services/ProviderAdapter.ts;apps/server/src/provider/Services/ProviderService.ts;apps/server/src/serverRuntimeStartup.reconcile.test.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/chat/ChatComposer.tsx;apps/web/src/components/chat/MessagesTimeline.test.tsx;docs/user/composer.md;packages/contracts/src/providerRuntime.ts +1eb36b45ef7aa5c028380afb7266bcabf258a55e fix(web): show pull request state icons in tabs (#9112) 7 6 apps/web/src/components/ChatView.tsx;apps/web/src/components/RightPanelTabs.tsx;apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx;apps/web/src/rightPanelStore.test.ts;apps/web/src/rightPanelStore.ts;apps/web/src/routes/_chat.pull-requests.tsx +ba3cb0773859334fe9f75016295bb3893c9e6044 feat(projects): automatically pull clean default branches (#9277) 20 11 apps/server/integration/orphanedProviderSessionStartup.integration.test.ts;apps/server/src/orchestration/Layers/ProjectionPipeline.ts;apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts;apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts;apps/server/src/orchestration/decider.ts;apps/server/src/orchestration/projector.ts;apps/server/src/persistence/Migrations.ts;apps/server/src/server.ts;apps/server/src/serverRuntimeStartup.test.ts;apps/server/src/serverRuntimeStartup.ts;packages/contracts/src/orchestration.ts +91c8d4771ccb503a9dde65190b87db642df0a6ea feat(web): add opt-in panel animations (#8830) 20 13 apps/desktop/src/settings/DesktopClientSettings.test.ts;apps/web/src/components/AppSidebarLayout.tsx;apps/web/src/components/ChatView.tsx;apps/web/src/components/RightPanelTabs.tsx;apps/web/src/components/chat/ChatComposer.tsx;apps/web/src/components/chat/ChatHeader.tsx;apps/web/src/components/preview/PreviewPanelShell.tsx;apps/web/src/components/settings/SettingsPanels.tsx;apps/web/src/components/settings/settingsSearch.test.ts;apps/web/src/components/settings/settingsSearch.ts;apps/web/src/routes/_chat.pull-requests.tsx;packages/contracts/src/settings.test.ts;packages/contracts/src/settings.ts +ca63d42d670837b918081d1fc1ebada553814b4c refactor(shared): move the node:sqlite Effect SQL client into shared (#7272) 22 1 packages/shared/package.json +134d51096ea0d00a53a499e8f0c87e31fafb0006 feat(desktop): browser profiles for the preview browser (#7254) 40 9 apps/desktop/src/settings/DesktopClientSettings.test.ts;apps/web/src/components/ChatView.tsx;apps/web/src/components/RightPanelTabs.tsx;apps/web/src/components/preview/addBrowserSurface.test.ts;apps/web/src/components/settings/settingsSearch.ts;apps/web/src/routes/_chat.pull-requests.tsx;packages/contracts/src/index.ts;packages/contracts/src/ipc.ts;packages/contracts/src/settings.ts +28ddaf75917140e5e4355d4386bc5d14d9dad7b6 fix(web): confirm closing agent-controlled browsers (#9272) 3 3 apps/web/src/components/ChatView.logic.test.ts;apps/web/src/components/ChatView.logic.ts;apps/web/src/components/ChatView.tsx +5a9b56291f82b9269346053594d8b5dfca736976 fix(web): warn when shared settings have no target environment (#9207) 1 0 +46b5c66406b9942589d7e9132beeafda2434f113 fix(chat): show single tool calls without summaries (#9267) 5 5 apps/mobile/src/lib/threadActivity.test.ts;apps/mobile/src/lib/threadActivity.ts;apps/web/src/components/chat/MessagesTimeline.logic.test.ts;apps/web/src/components/chat/MessagesTimeline.logic.ts;apps/web/src/components/chat/MessagesTimeline.tsx +62c68dc41f9d9d7ecaf5193a6a8d997ebf671a61 fix(mobile): show filled filter icon on Android when filters are active (#9217) 1 0 +f90e2f2bd26e22b77ccf781cccdf95afd3c3ac1c fix(server): subscribe before provider settings watcher (#9271) 2 2 apps/server/src/provider/Layers/ProviderInstanceRegistryHydration.ts;apps/server/src/provider/Layers/ProviderRegistry.test.ts +b57726ca842624b713572529109ac49b17c93fb3 feat(web): add copy path button to diff headers (#2403) 6 1 apps/web/src/components/DiffPanel.tsx +8d5b712de3cbd84118327808c403756e8894014a fix(desktop): exclude opposite macOS pty prebuilds (#9240) 1 0 +9159b808d35a88e74fc91e11070f3270cdb321f9 feat(mobile): long-press file references for path and open actions (#9258) 17 2 apps/mobile/src/features/threads/ThreadFeed.tsx;docs/user/composer.md +2a7a449cca3c7760b689a54b3aa02476a206dbc9 fix(web): hide deleted providers with prototype keys (#8337) 2 2 apps/web/src/providerInstances.test.ts;apps/web/src/providerInstances.ts +aab4049646ffa8b9bcff92562992e6c3a8554bf0 fix(ci): keep Expo Sharing patch applied (#9248) 5 1 pnpm-lock.yaml +b5a09e13fa464a8681e0bf9df404dd3c0afe8ac8 fix(release): pin patched expo-sharing version (#9250) 2 1 pnpm-lock.yaml diff --git a/audits/orchestrator-v2/2026-09-04/main-late-arrivals.txt b/audits/orchestrator-v2/2026-09-04/main-late-arrivals.txt new file mode 100644 index 000000000000..630693d8a665 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/main-late-arrivals.txt @@ -0,0 +1,7 @@ +f6db4206258b0ef30e8dd8949627acfd209bf338 fix(web): reset automatic pull to default (#9763) +45bd3b631bf1e84520c90ebdfdd1b135871ced14 fix(sidebar): mute background working threads (#9759) +d115a96763b76d00f06b06272688cf68eebe8206 fix(web): stop empty diffs replacing pull requests (#9753) +bc03c3640d6d3bb44e5fb477bfd78d7484cd0e00 fix(models): make GPT-6-Astra current (#9762) +15eda897d37aad232fca5089f5eb6ef7b726c31c perf(web): defer image URL requests for thread history (#9760) +6365919f2e5bcfb4fa4020b95e19af26ae40979f perf(server): skip history reads for metadata commands (#9758) +77b655c47b82c9b2aad09e447117b7618a16e21d perf(mobile): defer file preview highlighter startup (#9752) diff --git a/audits/orchestrator-v2/2026-09-04/main-only-commits.txt b/audits/orchestrator-v2/2026-09-04/main-only-commits.txt new file mode 100644 index 000000000000..a83780bd886f --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/main-only-commits.txt @@ -0,0 +1,8 @@ +d7cf8aaa8d4fbcbdd523b4f4bc86fda5c47b4a70 perf(client): stop thread streams when unused (#9740) +0de956ed2f92b8a6ead56e1566801db232d365dc fix(web): refine server update notice (#9744) +a76b898b3aa4fd4081104b06a3b2c942bd4fecb7 feat(web): link pull request authors to profiles (#9627) +cf9729d5ee9660c08556e823080d3bb19648ed28 perf(server): bound terminal history by bytes (#9748) +fec606f9ae524277ef1f6886e614f32d9e15e36e perf(web): avoid repeated terminal metadata scans (#9747) +d6e29dc9dee943b34d6b0d11441fa944c7bff7c9 perf(mobile): bound the parsed review cache (#9749) +cbe93e8dfba68ff6fbe8c69e43a633fdc79db62d fix(web): show project settings for new threads (#9743) +cfc9bf34156ddcc4a98b7f5c67193adb5aedce06 fix(web): fold single trailing activity (#9739) diff --git a/audits/orchestrator-v2/2026-09-04/main-since-prior.txt b/audits/orchestrator-v2/2026-09-04/main-since-prior.txt new file mode 100644 index 000000000000..a318a9ddb184 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/main-since-prior.txt @@ -0,0 +1,240 @@ +d7cf8aaa8d4fbcbdd523b4f4bc86fda5c47b4a70 perf(client): stop thread streams when unused (#9740) +0de956ed2f92b8a6ead56e1566801db232d365dc fix(web): refine server update notice (#9744) +a76b898b3aa4fd4081104b06a3b2c942bd4fecb7 feat(web): link pull request authors to profiles (#9627) +cf9729d5ee9660c08556e823080d3bb19648ed28 perf(server): bound terminal history by bytes (#9748) +fec606f9ae524277ef1f6886e614f32d9e15e36e perf(web): avoid repeated terminal metadata scans (#9747) +d6e29dc9dee943b34d6b0d11441fa944c7bff7c9 perf(mobile): bound the parsed review cache (#9749) +cbe93e8dfba68ff6fbe8c69e43a633fdc79db62d fix(web): show project settings for new threads (#9743) +cfc9bf34156ddcc4a98b7f5c67193adb5aedce06 fix(web): fold single trailing activity (#9739) +c8f77e0d441264efb0acfac312e852c81ae3da83 perf(server): stop caching unused OpenCode tool parts (#9738) +088cc3f95599b7b933289d719fa1e9b0608cb4cd fix(relay): bound stalled push requests (#9734) +19c1710a88a2c87c159d76269dacdf0b17ddd9f4 perf(web): reuse timeline rows while text streams (#9725) +c7bf3115f2223ede5cb2316613dc7369155dbeb1 feat(web): unpin threads from the sidebar multi-select menu (#9651) +7d5dc66c151a9ca7bfef45cffc9d3516842c5566 fix(web): mute composer helper text (#9654) +50bfca43d76ced00f5d67cfbab8bc44c50eb0e53 perf(server): replay only the selected thread (#9726) +c4353bc6b972fa527579b530f01cc8744b2407d2 fix(mobile): read file-backed image drafts before enabling them (#9713) +5eab021a5185e492b6b021f83564143d5263e8a6 perf(web): stop rendering hidden terminals (#9718) +9eb4d71681dc7d002082db2f8b4bacf7614412f4 fix(mobile): remove provider setup (#9721) +120fab18d84f1eb993ecc7fa858a8dd212747079 fix(web): keep the slash menu above the composer when vertical space is short (#9625) +8357eef14cbd5ed063e4a64404c33d1bfbc78446 fix(web): match provider settings layout for disconnected devices (#9619) +8ccb933a8aae461b616b199ab287164c3311a755 test(server): allow either valid file-search match (#9720) +108f295cc3672716c3cb8291ce487846df5ce098 fix(server): bound slow-client event buffers (#9715) +d536b0580d044967dc644498d8c5a6e96464f767 fix(server): settle inactive threads with open PRs (#9610) +c66f15f39e61fda0a9a100578833ec12e7526859 perf(client): reduce thread-list update work (#9716) +95103905f5f045523994213bf76bfb14acc31b27 feat(web): preview pull request links (#9631) +da7e46d08e85bcb07ecd78721a40f7b612fac2f2 perf(web): stop replaying terminal buffers on rollover (#9707) +7839140e5e93d3f401d7eb45b86cf1a234eb3609 fix(mobile): preserve saved work after storage read failures (#9710) +c7c1dfe4df99edf65a49d8a31b39ef1361f37f44 perf(web): stop continuous chat status animations (#9709) +c75299ee2085a121bceb6df76796e971fe92b5b6 perf(relay): avoid repeated activity decoding (#9708) +dffb4cd3b16dc6f41aced99922950ee3083082c6 perf(server): use one query for buffered provider events (#9706) +3bbbc1d9fd8b3d649c60ba0137c7dae93a6aab3f perf(server): stop rebuilding terminal history per chunk (#9703) +010d6bb1b5281cb1e6eacf1ee0f2500973242836 perf(marketing): serve website fonts locally (#9701) +b3e1d88590489da2bb63b95c18a57e6f400b8b7f perf(web): defer diff workers until a code view opens (#9692) +c163d502dd32b993c03d8c20a5fae55b159bd8dc perf(server): avoid full patches for checkpoint summaries (#9694) +4ee2a9d046a0986451c703c9221bb32ba53540bb perf(marketing): stop continuous homepage motion (#9697) +1587f248dd81ed45e214d476451ebf16dbfadb1a feat(server): measure provider turn token usage (#9132) +dab5f6e6e02e78675655e69503aa89654e5b8050 perf(web): defer composer draft serialization (#9695) +777f5bb2e11fe30e7fdcb5741b0b1d9bb20924d6 perf(mobile): reuse diff rows during comment edits (#9693) +246064993535e5d90107d3d7784ceef3cc883435 perf(clients): avoid waiting to read cached relay tokens (#9691) +ec8b2119c377f5c1dbe6235b221ef98eca31a96e perf(server): omit repeated OpenCode progress logs (#9689) +44dc8ae259f5c3349f7ab8045e39bd62408b52a9 perf(mobile): reuse chat feed rows during streaming (#9688) +f2e3764c257a7e27c8171d7dd1e38d4383074206 perf(server): stop retaining unused OpenCode tool history (#9684) +2263e13fda8c9a4f1b6f4dee32e3c9020195e2aa perf(server): batch projector cursor writes (#9671) +27e6cc27fe0f3cff53a44905e40615b7db99c80c perf(server): cache and stream static web assets (#9669) +8e3aa324b57dd645980b203d5f8a5b9f9dc53a84 perf(marketing): serve images at their display size (#9682) +7cf5b284e6e37895f535433c77f728b3e4292c9b perf(mobile): skip unused legacy list work (#9679) +887ece307131bdc853cc10f3b82067dee77c4ecf perf(web): keep Markdown mounted during streaming (#9677) +3b6be3ef4daa848e10c095d8a088064ac836be7f perf(mobile): bound diff syntax highlighting work (#9673) +082cab224624eb3a6cd494df3719c59014fb0c99 fix(web): show machine icons in the environment picker (#9668) +cccd7e3c885065e925f559c5708378cdb3b51eb3 perf(web): speed up terminal snapshots (#9663) +8ac5462920c45cdee63af15b2598909736f2ec84 perf(server): stop loading message bodies for thread summaries (#9662) +560afffdea82000d757c98ea79678aee75f8648c fix(server): update Claude Agent SDK to 0.3.260 (#9135) +caa8a0db98f9d32e98a1645caa7f7dd37b14f187 fix(desktop): quit immediately on a second shortcut press (#9657) +01f3e50eca5102ccd881de6f942a98fe6a518ad4 fix(server): unblock OpenCode approvals and stop (#9653) +f0347322441f3b8e473a8d13ea7006cbcb4fb761 feat(web): show which sidebar threads hold an unsent draft (#9658) +d5b94100863057fb4629f9ad4a35753d16917924 feat(mobile): paste the phone clipboard into the terminal (#9199) +d487dfbf46be344e818725be70ee04be2436bfb4 fix(web): resume Antigravity threads without repeated sign-in (#9647) +eb77683e5544e071db74831bae052bbd8a7d5f88 fix(server): prevent duplicate desktop clients after restart +14bf3f6d1644a37029be58429e8f0138e1ceb743 fix(web): toggle a single stashed prompt with Cmd+S (#9644) +09d13de4381925fa2a6dea74eff8185fa301e905 feat(mobile): make chat text selectable on Android (#8779) +5f878d2a85807618a4c8571cdef5daa3124672d6 fix(web,mobile): fold context compaction under settled turn folds (#9623) +ec3ec6f0b4e005c47aff07d4d9e31506241bce3a fix(web): mute sidebar branch name to match worktree icon (#9622) +2152d44de2db30a6bae965b0afd30be080e5c872 fix(server): load OpenCode workspace skills via SDK to avoid 64KB CLI pipe truncation (#9585) +706231535ceac8618712913dfdc4a058c2ffb0d8 fix(web): match composer pull request state icons (#9375) +93c3ab4ffe408a3e06228a33efc8a0745da91178 fix(web): snooze menu no longer overlaps thread details (#9601) +4cc800c7593db13726171918572afe3502c43ba6 fix(web): keep command palette above composer menus (#9613) +99e3b721c5255ded20b00ba1798f848bfc0f1f65 fix(connect): diagnose incomplete headless server setup (#9602) +c3b8825bf476cbce5e061c0f99570cf1f6723b89 fix: preserve tool icons on failed calls (#9606) +61a91b6ef1bd45424169c6650362b358d49bbe34 fix(web): group image views like other tool calls (#9597) +00f8b7c28056188e3c5630160806a0afe51c9010 fix: show idle subagent batches without completion marks (#9616) +f1e90e388b86fe4b007a55c0e685a1fa878115e6 refactor(web): move usage provider controls to settings (#9599) +caab2fdbac041ac2e851ad4fa3ac4a40a1d4a8f6 fix(web): render draft PRs in gray (#9537) +5cc369b7eb882dbea8d5ad21ba688c73a0058748 fix(pull-requests): refresh data after thread turns (#9496) +f559fe0ba6fb5950bd14a2404f10b9c94b33f696 fix(web): show context meter in compact composer (#9430) +39abb9d1d6ae6501c573b9dc0cb9c28e2f75659c fix(connect): refresh authorization without disconnecting (#9582) +57832803eed4c87c462de92892777a0934019721 fix(desktop): restore panel titlebar interactions (#9591) +07891e9569c88457516b44c08c820471762969e8 fix(web): bound disconnected send toasts (#9592) +b34ff8f56469afa8f3f85d89894e1b4cf49b5213 fix(usage): deduplicate CLI proxy subscription accounts (#9584) +09b81a34954c990f70257ae05efbb602c90aac97 fix(mobile): render workspace images in markdown file previews (#8769) +2675e3c70327719a99af4ae6e53e7b74fb8a9be0 fix(antigravity): keep subagent batches active after launch (#9579) +bf40fa786c521b552eb554bbd4f2c75c4123cd03 fix(web): align the sidebar wordmark by baseline (#9578) +0cb02abf5b3af2985d9dd23a637a63388e98fd49 fix: better shell syntax handling for labels (#9371) +42bdea1c9c1d4b7c5c2e77cd23cf53fae68a6fd4 fix(web): stabilize right panel transitions (#9554) +95390ed78458f139cb795bab4baa53ec39222ff7 chore: vouch august contributors (#9557) +2b10398cca3fa74a7c2187c8d9c23ba789333f5b fix(web): render settings sidebar immediately (#9563) +d7884ce90b9845e6e8aa737dfe02062b91b11c91 fix(web): make settings sidebar sub-section buttons full width (#9562) +65f1839ae82af4e67f389f23e4ccc50f51a4a83f fix(web): keep codex restart responses continuous (#9560) +fee2e0ff8168b82ab19f496fcc874c1f3871f522 test(web): fix flaky startup and Tailwind tests (#9558) +9e1bc36a0843699db54ee28abbdac70584ae8f33 fix(web): keep the last message visible when the resting composer expands (#9553) +710f6dc417ebf303eede3df3605a6938482d83ab fix(web): simplify expanded tool details (#9549) +f96a220b5b154ea44c94bf43929c6362cd511699 ci: add on-demand Windows test workflow (#9538) +4e547318b60031eb546d8cf2b84ad9fa0785a87a fix(server): find newly opened pull requests after agent turns (#9125) +1641b4aba58ab495cad7a9800b173af3416e16dd feat(usage): redeem Codex reset credits from the Limits tab (#9534) +232de5e8aac61e6f3de4bc61d10746167db9e905 feat(marketing): fresh screenshot and floating marks on the homepage (#9547) +617edab6539ee6573055dc9fc45fdeacdb12f673 fix(server): reveal normalized paths in File Explorer (#9551) +3e2c1a66f74f0a45768332c360cd3682f61129e1 fix(web): thread error banner no longer shifts the chat (#9473) +f239b77df93077e40c27cc5c5909e94266571859 fix(web): close composer menus when their controls hide (#9541) +3c3e05ccfe34ab7af273f4a4faa72909cafd7a21 fix(web): measure collapsed model labels at their visible width (#9540) +54aef6fbe16f637092505b30bd25230c4b0744d8 fix(web): restore composer controls as space becomes available (#9539) +5989de44a24888dab02854477ea1d0f50ac3a4a6 fix(mobile): keep store screenshots free of system banners and show dictation (#9548) +c5ba51d629b3813182cf3e161cc3f23b1e541dc3 feat(providers): add context compaction command (#9293) +6f405370c8e552da9dcfdd6922e85789fd918340 fix(dev): keep shared dev reloads and hot updates working (#9543) +dddc0bdcb2230147e207efb17df2e49dbe1bdd8c fix(server): include SQLite conditions in persistence errors +07c4ab5077fa9c32bf34ab07dd2caa3907878dd9 fix(web): keep automatic project icons consistent (#9535) +0ba06a122bc73f705bfc18875366b4eeb1160992 fix(web): settle the resting composer layout with a pixel of slack (#9482) +f54ab901fa77f76eeb1e1cdfa103b9ed6f5ee4ca Fix worktree removal timing out on large install trees (#3902) +6319a9714881a1d25549f797c468fabebae92813 fix(desktop): preview CDP sessions no longer hard-crash the app (#9068) +75ab5ab3fb6ad35117da754644c404a31b2fed84 fix(codex): accept rate limit errors on thread resume (#8897) +b90898077e60290a1eb7bea4224f325fd3bb1595 fix(server): back off relay client restarts after rapid exits (#8788) +2b96220f00de09b61327c8e881b7f509f8cc5a79 fix(server): settle branch threads immediately on pull request merge (#9528) +343db2c328af56fe0fa7672f3af055550832689b feat(web): reorganize settings pages (#9354) +19d8ab2ae9fc562ee7b216a0d72903fbfafa9572 feat(usage): show Codex and Claude subscription limits on a Limits tab (#9507) +0a0b6be96833adae68b36540c00d347eda278736 fix(web): keep right panel controls clickable (#9517) +d76b24dd15a219666941ab1b4967d8f738adcda0 feat(codex): support async questions (#9512) +e3723e06b5b154a3e0ede55c02e2cabc5301d3bf chore: drop comment events from Cursor hygiene forwarder (#9527) +9d28c21a26aeef198cb064fe466e49cbeabfe09c fix(auth): keep pairing credentials out of access read models (#9523) +44701efd6790c39dc82cb08104f7295e1780210f chore: forward issue/PR/discussion events to Cursor hygiene (#9518) +9c9ae3dc0e94a957d9c4a61bb211caf914828054 fix(server): keep events during thread subscription startup (#9521) +c0ebc882b88dbcffd5a712e403b3c3c517ba4ea6 fix(web): return focus to the composer after closing a media preview (#9513) +522ebe65a542ace6f22d9ad95f95ef9ade7e87f1 fix(web): keep the composer open while selecting timeline text (#9499) +6382268323f86e01b2d40206bcf33beccb3fb64a fix(web): let paste expand a resting composer (#9498) +f8a14b28ff80a92d8f4df9a9aa53bfacb8195199 feat(antigravity): show subagent calls and results (#9515) +3653cb22ffb30bf133fecc30c955941fe267cf1c fix(desktop): address the browser import review left over from the stack (#9516) +8ea52c8f2f4361e875d72ab30d72d37cfae4d87f fix(antigravity): update managed runtime to 1.1.1 (#9509) +eb334ca57448742139fb8ec38fb397c1e51c45c5 fix(antigravity): handle native sign-in URLs on stderr (#9514) +baf67b6e3accd48d510fd0d39a4e6b978a1eea80 fix(antigravity): keep model choices up to date (#9511) +f25e4428961982e3935300cfd3c78f7d0fac4ee9 fix(antigravity): allow slow runtime startup during setup (#9510) +498ab9c399d5e8c3097a286be14d03238e071ac1 feat(desktop): resolve Chromium cookie keys on Linux (#7261) +ff5843410d44796676b06627788d94354849c4d7 feat(desktop): import from Chrome, Edge, Brave, Vivaldi, Opera, Arc and Firefox (#7260) +39449e53e31a56103192aa7905e89fc92c977a4a feat(desktop): import browser cookies into a profile (#7255) +e01c153c18a94a2aa33df7115c6cfee1eb09880f fix(antigravity): forward Google sign-in URLs from browser helper (#9425) +ef4cc6085e24d6309252412c6dab5482ac11a09f fix(mobile): resolve Antigravity provider icon and normalize driver matching (#9495) +0aae1e2ad7ab174004f39746eb4c72b905de932d fix(antigravity): discover legacy workspace skills (#9410) +80b53730d1e821563e5c348fdf4f5fc7616a49f7 fix(mobile): let back swipe pop from horizontal scroll edges (#9493) +409bc4fa6f3bb9869052bdba4244b30606457f20 fix(mobile): keep the machine glyph next to the environment label (#9486) +12e8997e58dbca8f1bd8c63b67d662eb69cf0e0d fix(web): keep agent browser preview visible (#9484) +c726c30a148c2add6a3ec7f31f54ae48dc5d2f0c fix(web): keep opencode icon hollow in collapsed composer (#9492) +678f23a69943e3eef7171f452b44f2931d2ef21f fix(desktop): restore second-press quit fallback (#9485) +77138cf33194a303adfbbd69cc93efa69f84245d fix(web): dont collapse composer when interacting with bottom row (#9490) +0869ad648b67a286d7a47af878f1d256d0ff689f fix(web): let the PR reviewer and label search boxes take keystrokes (#9479) +4b8b5d9e0177002c84a6f55837670aa0ef816915 fix(desktop): refresh generated annotation styles (#9488) +373be93e68bf3d32207471b27e976ac84bff806a fix(web): move workflow approval beside checks (#9465) +03728361aa7beb9c13da320097450e6fe65aac3e feat(web): let users turn off composer collapse on blur and scroll (#9469) +493fbb58870c912b9cb2ba6c2f1dae938877a59a fix(web): reuse pull request list data while loading (#9467) +d2b6f3b9296f682c6158b894ab33d98d0c4bfb2b fix(server): full-access OpenCode threads no longer ask for approvals (#9282) +36c4e9cf5c0123e33d65f2af9497ee090404b532 fix(server): keep a/ and b/ prefixes in rendered git patches (#9438) +de025aa69ffb0ce1a45d30aed25c60454660b62d fix(mobile): show loading and syncing in the working pill (#9466) +db8d60f486c5fc1a80d01b591a359f0c87f0868c fix(web): render transparent previews on white (#9463) +46e8b1a23ab14fa2c128c6b315955d8eb976d85f fix(web): make right panel tabs easier to scroll (#9461) +d5825e1d2fb1703ced2bbe2661f6a4937dd530bf fix(web): stop clipping the traits chevron on long Codex effort labels (#9433) +126afb56fca56c663f4f40acd46f123ab27eee2b fix(web): banner buttons no longer expand the resting composer (#9452) +8bd544cdfd22aa38ab82bc1adc0b851755a299ef fix(web): keep agent images collapsed (#9460) +c78f05a45e1c2b274d8b0ab2b4d2d88b4767c968 fix(server): reuse pr state when settling threads (#9459) +4e89d74436a167c01f25a6a5283638843398ea3a fix(web): make project icons the default (#9457) +645d58547d282eb2aaf6c48e5907625fc112386a fix(web): prioritize authored pull requests (#9453) +21b9dda5afb00a33e228a68d2ccc885bba7285dc fix(web): unify skeleton loading animations on one pulse (#9448) +d4ba2a1f11498eae9683f6dc95a08b1c17c29765 fix(composer): mute fast icon when collapsed (#9451) +2120fbc185737b71f09de020b95224f9e636d1e5 fix(web): avoid duplicate Antigravity install status (#9419) +cfddb4201df8941bbfde008919da70fe5ec7552b fix(mobile): skip unsupported shared settings targets (#9381) +57626eb6eaa436b22260068d23f4e3df5f389cd1 fix(web): prevent loading ssh environments from overriding navigation (#9168) +098bf5329727fcd7d973bf842e6b4d50d6e7b924 fix(web): preserve explicit preview navigation URLs (#8902) +77e35c561259733d880ab62a43aad0894d301d9b fix(web): send cited messages with Cmd+Enter (#9307) +fff33f9e851912363c5b1f3ac65598be35eb5f0d perf(ci): reuse dependency checks in release builds (#9399) +1e051873094c0c75cd35fef89c90461c22cce76b fix(antigravity): refresh the model manifest so older Gemini models fold as legacy (#9397) +19c97ea56d30b3a2de31a060f8f47d6b7404b78f fix(web): unlock the composer when preview capture fails (#9127) +2b745efe57cddc1753d3007d081c64bd20e3ab79 fix(usage): price new models without waiting a day for the rate table (#9202) +2aa907b1969237efdaced29612fb46ba51be7041 fix(mobile): show an error instead of an endless preview spinner (#9123) +06336460c9988f29c71e839c4c9c840c4552e077 feat(providers): add Google Antigravity via the official ACP agent (#9348) +652515a349741d234111b85f27597be3265d1ffc fix(web): render assistant images inline in chat (#9126) +044ea8e347d980a215057c325de8335d38f0f9aa fix(web): stop the resting composer layout loop (#9393) +18573d60aab1344bf124a044b01445086e910c4c fix(claude): expand slash commands when a message has attachments (#9122) +5d1b02cdeebff4b0b4f15a1e8425b06ae3cfe8d1 feat(marketing): put named-developer quotes on the landing page (#9385) +4b26132d2c740ff344ef3fae7ae62e9765759e29 fix(web): keep trailing tool groups out of "Worked for" accordion (#9384) +5b8445b7a777ab1070aa97b062b1618971073a96 fix(web): collapse the resting composer (#7855) +24799de4f85a9071afc2420362784ea46041d544 fix(mobile): size expanded tool groups correctly (#9359) +1f7a3c11ca864898b136a35011ad10777ea07544 fix(mobile): pressed and disabled styles no longer apply unconditionally (#9355) +cf0bb4c3571badbc5aaa8189cd5cbe3563ec73c1 fix(web): match project icon chooser button sizes (#9368) +c89e3e12a41e13e09e0103d08a41d0688a99fb49 fix(web): settled sidebar rows use the project fallback icon (#9366) +829c3db94830fc70b5754513b8a370f7301ca213 fix(environments): draw the machine icon everywhere an environment is named (#9365) +5eb4f452ee0fcde7b5bbc93d62de9118b70a33b2 test(web): remove static markup-only component tests (#9364) +d4bd8923ad8cab346a854967015b06d9e5cd77f7 feat(web): mod+w closes the active right panel tab before the window (#9363) +b5f4e8137b3cbd657fbe2b698f9db4e321acbc3d feat(web): suggest ssh hosts in a dropdown under the host field (#9171) +9f9359bd8132c425493720080149dcc0d3da9436 fix(web): stop usage summary requests reporting slow RPCs (#9358) +854541a04e07b7960698b381bcfd2fda73eb276c fix(pull-requests): shared state + not settling? (#9332) +48ba76bc26337f23d1f0991bbac51f996a3333dc fix(web): collapse oldest pull request comments (#9323) +6cf0c6ea55d281f65c80502ec1871b0adf472025 feat: display native app and browser icons in work logs (#9093) +0bc59bbae391ee45ab3a7cfb2dc703c8b27e5772 fix(web): let the pull request list use wide screens (#9351) +1575ada305b9686b9771df2dca304f391e85a76e fix(mobile): stop indented code overflowing Android chat bubbles (#9347) +f6c04c552c203350705f9ab1e47773ea736af245 feat(web): add customizable project icons (#9137) +6a5a18cb1bc9ea878afa1146950439b5d4744110 fix(web): add press feedback to buttons (#9349) +18062da9425909a0a92bce0b692c9de6fbba56ee feat(web): choose whether links open in the default browser or in T3 Code (#9339) +d42254dfb462e4ab23a42d4bef53b1ce00a72396 fix(web): resolve Vite sourcemap and supports warnings (#9343) +2a3cfe456375fd34b906f849b04706109dc74170 fix(web): collapse PR header actions to icons when narrow (#9334) +5f84efa1ec2fb3cd6f6c54545cc34bb77ac1ddb8 feat(web): add PageUp/PageDown chat navigation (#9315) +1aa44a071f66bdfd9430356ab824b5a6985fb459 feat(web): add a file tree to the diff panel and pull request code tab (#9330) +f5fbb1bcb0db378c61addd5b49ef2d95bd888168 chore: upgrade vite-plus to 0.3.0 (#9327) +3b2de9da1c8763602e283e8d14b41b5d57a9d0c7 chore: dedupe lightningcss and tailwind node bindings (#9331) +9409dd20a9fbce491d49d09c79b289d8fb8bfe3e fix(web): make the diff layout toggle a persisted setting (#9326) +12f1fc427efad4b683835a72bda6f74bebb5d641 fix(web): line up the titlebar wordmark label and version pill (#9255) +66419a1d1b80110c9702edae641bddcc2888fc98 fix(dev): share dev servers on the loopback Vite actually binds (#9324) +85f2479ffe5c9d8ffa91f1bfae5234df4061292f refactor(mobile): style plain views with Uniwind classes instead of the theme bridge (#9322) +b9b1b8fdddf9d006fdb820af770063e1f968345b chore(ci): narrow the Effect conventions check-run agent (#9321) +194f838e7636f97739c440c7855aed195dbd7f52 chore: audit lint directives and move plugin allowlists into config (#9300) +ec44bc56f598be16ffbc22ed0e4e095447043844 fix(chat): keep live tool labels in present tense (#9316) +922bd692251bc803c12a3fab159efe83c957bb70 refactor(media): unify file and media previews across clients (#9253) +31eeb443305a4e11c8b20a7c8ff2b3f5e841eb0f fix(sidebar): collapse settled and snoozed shelves by default (#9314) +9ebbeda5a03fd8fce7be147b65ea396e50721c68 feat(web): apply and remove labels from the pull request tab (#9313) +0fbb94248581aaefda36e4f8a40ec2c6455c779a feat(environments): draw each environment as the machine it runs on (#9299) +d897641d738c67dd7c12cbb3a273b43fe17a5eb1 fix(pull-requests): keep cached PR chrome on reopen (#9294) +355fbd96d5e90b52961ac5f1e035112fc3bad4a9 fix(web): stop remounting markdown on every activity delta (#9306) +ef6cc0b362019f32152470ed96c1aa1b813fb7f6 chore(ci): only run check-run agents on vouched contributors (#9298) +e94603adfac7d8734f9af01e33f67e776daf482d chore(ci): narrow the UI consistency check-run agent (#9297) +77512998485718eb1b6c336e20f196eb40a6a32f feat(web): preview document attachments in the file viewer (#9292) +dbc7bfa3f36cc61a3f1a2015e47d71ae9dee5421 fix(opencode): show Reasoning selector for OpenCode models (#9287) +2971ec3209d7ef1b00d7ded70fe6342816b1539f fix(server): preserve automatic settlement timestamps (#9254) +15fea6c5f40331c8325f33bd08b2dcbf924e935a fix(providers): discover workspace skills everywhere (#9180) +443b4ebfe83fcfe64c34b09ecb5a5fffdebb85c7 fix(pull-requests): missing features & better behaviour (#9188) +4ba39a6f408bdee468df2e3ffdf7d5dc08e7b59d fix(desktop): detect installed Spectre libs for Windows builds +994bd7373cf3a335c204a617604e690ed4c00cba fix(cursor): honor auto and full access modes (#9283) +c742edd46c5b6792ec8647f934a4703f9103aa82 fix(web): show scroll-to-end as soon as the last message slips under the composer (#9280) +63f334baf3432c4404ddfc9e71d33bf16575f0ed Revert "feat(providers): add context compaction across harnesses" (#9284) +064392ffc7fc58fcc3018fd2ba2df33fbb21f1de fix(web): offer browser profiles from the empty-panel launcher (#9279) +b59b7d0af9536a2d61ddfcf8d33420b890b2faca fix(web): unify control sizing across settings pages (#9281) +fb93902ee24d4ba380508df33d25478d3baf7a72 feat(web): add proactive panels (#9276) +535557b3f785629e6f48cad40c5a4b78b3b3c5d6 feat(providers): add context compaction across harnesses (#8808) +1eb36b45ef7aa5c028380afb7266bcabf258a55e fix(web): show pull request state icons in tabs (#9112) +ba3cb0773859334fe9f75016295bb3893c9e6044 feat(projects): automatically pull clean default branches (#9277) +91c8d4771ccb503a9dde65190b87db642df0a6ea feat(web): add opt-in panel animations (#8830) +ca63d42d670837b918081d1fc1ebada553814b4c refactor(shared): move the node:sqlite Effect SQL client into shared (#7272) +134d51096ea0d00a53a499e8f0c87e31fafb0006 feat(desktop): browser profiles for the preview browser (#7254) +28ddaf75917140e5e4355d4386bc5d14d9dad7b6 fix(web): confirm closing agent-controlled browsers (#9272) +5a9b56291f82b9269346053594d8b5dfca736976 fix(web): warn when shared settings have no target environment (#9207) +46b5c66406b9942589d7e9132beeafda2434f113 fix(chat): show single tool calls without summaries (#9267) +62c68dc41f9d9d7ecaf5193a6a8d997ebf671a61 fix(mobile): show filled filter icon on Android when filters are active (#9217) +f90e2f2bd26e22b77ccf781cccdf95afd3c3ac1c fix(server): subscribe before provider settings watcher (#9271) +b57726ca842624b713572529109ac49b17c93fb3 feat(web): add copy path button to diff headers (#2403) +8d5b712de3cbd84118327808c403756e8894014a fix(desktop): exclude opposite macOS pty prebuilds (#9240) +9159b808d35a88e74fc91e11070f3270cdb321f9 feat(mobile): long-press file references for path and open actions (#9258) +2a7a449cca3c7760b689a54b3aa02476a206dbc9 fix(web): hide deleted providers with prototype keys (#8337) +aab4049646ffa8b9bcff92562992e6c3a8554bf0 fix(ci): keep Expo Sharing patch applied (#9248) +b5a09e13fa464a8681e0bf9df404dd3c0afe8ac8 fix(release): pin patched expo-sharing version (#9250) diff --git a/audits/orchestrator-v2/2026-09-04/persistence-audit-probes.test.ts b/audits/orchestrator-v2/2026-09-04/persistence-audit-probes.test.ts new file mode 100644 index 000000000000..807b892eb707 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/persistence-audit-probes.test.ts @@ -0,0 +1,323 @@ +import { assert, it } from "../../../apps/server/node_modules/@effect/vitest/dist/index.js"; +import { + EventId, + MessageId, + type ModelSelection, + NodeId, + type OrchestrationV2AppThread, + type OrchestrationV2DomainEvent, + ProjectId, + ProviderInstanceId, + ProviderThreadId, + RunId, + ThreadId, +} from "../../../apps/server/node_modules/@t3tools/contracts/src/index.ts"; +import * as Cause from "../../../apps/server/node_modules/effect/dist/Cause.js"; +import * as DateTime from "../../../apps/server/node_modules/effect/dist/DateTime.js"; +import * as Effect from "../../../apps/server/node_modules/effect/dist/Effect.js"; +import * as SqlClient from "../../../apps/server/node_modules/effect/dist/unstable/sql/SqlClient.js"; + +import { + IdAllocatorV2, + layer as idAllocatorLayer, +} from "../../../apps/server/src/orchestration-v2/IdAllocator.ts"; +import { + applyToProjection, + emptyProjection, + threadShellFromProjection, +} from "../../../apps/server/src/orchestration-v2/ProjectionStore.ts"; +import { isAutoSettlementCandidate } from "../../../apps/server/src/orchestration-v2/ThreadSettlementService.ts"; +import { + migrationEntries, + runMigrations, +} from "../../../apps/server/src/persistence/Migrations.ts"; +import * as NodeSqliteClient from "../../../packages/shared/src/nodeSqliteClient.ts"; + +const providerInstanceId = ProviderInstanceId.make("codex"); +const modelSelection = { + instanceId: providerInstanceId, + model: "gpt-5.4", +} satisfies ModelSelection; + +function makeThread( + threadId: ThreadId, + now: DateTime.Utc, + overrides: Partial = {}, +): OrchestrationV2AppThread { + return { + createdBy: "user", + creationSource: "web", + id: threadId, + projectId: ProjectId.make(`project:${threadId}`), + title: `Thread ${threadId}`, + providerInstanceId, + modelSelection, + runtimeMode: "full-access", + interactionMode: "default", + branch: null, + worktreePath: null, + activeProviderThreadId: null, + lineage: { + parentThreadId: null, + relationshipToParent: null, + rootThreadId: threadId, + }, + forkedFrom: null, + createdAt: now, + updatedAt: now, + archivedAt: null, + settledOverride: null, + settledAt: null, + lastVisitedAt: null, + deletedAt: null, + ...overrides, + }; +} + +function threadCreatedEvent( + thread: OrchestrationV2AppThread, + now: DateTime.Utc, +): Extract { + return { + id: EventId.make(`event:create:${thread.id}`), + type: "thread.created", + threadId: thread.id, + providerInstanceId, + occurredAt: now, + payload: thread, + }; +} + +const applyHistoricalCohort = ( + mappings: ReadonlyArray, +) => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + for (const [currentId, historicalId] of mappings) { + const entry = migrationEntries.find(([id]) => id === currentId); + assert.ok(entry, `missing current migration ${currentId}`); + const [, name, migration] = entry; + yield* migration; + yield* sql` + INSERT INTO effect_sql_migrations (migration_id, name) + VALUES (${historicalId}, ${name}) + `; + } + }); + +it.effect("upgrades committed-058 state through the live-059 overlay", () => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + yield* runMigrations({ toMigrationInclusive: 58 }); + const executed = yield* runMigrations(); + assert.deepStrictEqual(executed, [[59, "OrchestrationV2ShellIndexes"]]); + const indexes = yield* sql<{ readonly name: string }>` + SELECT name FROM sqlite_master + WHERE type = 'index' AND name LIKE 'orchestration_v2_%_idx' + `; + const names = new Set(indexes.map(({ name }) => name)); + assert.strictEqual(names.has("orchestration_v2_projection_turn_items_shell_pending_idx"), true); + assert.strictEqual(names.has("orchestration_v2_projection_messages_latest_user_idx"), true); + }).pipe(Effect.provide(NodeSqliteClient.layerMemory())), +); + +it.effect("reproduces the old-052 cohort collision against the current migrator", () => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + yield* runMigrations({ toMigrationInclusive: 43 }); + yield* applyHistoricalCohort( + Array.from({ length: 9 }, (_, offset) => [48 + offset, 44 + offset] as const), + ); + + const before = yield* sql<{ readonly migration_id: number; readonly name: string }>` + SELECT migration_id, name + FROM effect_sql_migrations + ORDER BY migration_id DESC + LIMIT 1 + `; + assert.deepStrictEqual(before, [{ migration_id: 52, name: "LegacyV1ImportState" }]); + + const exit = yield* Effect.exit(runMigrations()); + assert.strictEqual(exit._tag, "Failure"); + if (exit._tag === "Failure") { + const failure = Cause.pretty(exit.cause); + assert.match(failure, /Migration "53_ApplicationEventSource" failed/); + assert.match(failure, /duplicate column name|already exists/i); + } + + const after = yield* sql<{ readonly migration_id: number; readonly name: string }>` + SELECT migration_id, name + FROM effect_sql_migrations + ORDER BY migration_id DESC + LIMIT 1 + `; + assert.deepStrictEqual(after, before); + }).pipe(Effect.provide(NodeSqliteClient.layerMemory())), +); + +it.effect("reproduces the old-055 cohort collision and skipped main columns", () => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + yield* runMigrations({ toMigrationInclusive: 44 }); + yield* applyHistoricalCohort([ + ...Array.from({ length: 9 }, (_, offset) => [48 + offset, 45 + offset] as const), + [57, 54], + [58, 55], + ]); + + const projectColumns = yield* sql<{ readonly name: string }>` + SELECT name FROM pragma_table_info('projection_projects') + `; + const columnNames = new Set(projectColumns.map(({ name }) => name)); + assert.strictEqual(columnNames.has("auto_pull"), false); + assert.strictEqual(columnNames.has("project_icon"), false); + + const exit = yield* Effect.exit(runMigrations()); + assert.strictEqual(exit._tag, "Failure"); + if (exit._tag === "Failure") { + const failure = Cause.pretty(exit.cause); + assert.match(failure, /Migration "56_LegacyV1ImportState" failed/); + assert.match(failure, /already exists/i); + } + }).pipe(Effect.provide(NodeSqliteClient.layerMemory())), +); + +it.effect("reproduces the prior-audit old-053 cohort collision", () => + Effect.gen(function* () { + const sql = yield* SqlClient.SqlClient; + yield* runMigrations({ toMigrationInclusive: 44 }); + yield* applyHistoricalCohort( + Array.from({ length: 9 }, (_, offset) => [48 + offset, 45 + offset] as const), + ); + + const before = yield* sql<{ readonly migration_id: number; readonly name: string }>` + SELECT migration_id, name + FROM effect_sql_migrations + ORDER BY migration_id DESC + LIMIT 1 + `; + assert.deepStrictEqual(before, [{ migration_id: 53, name: "LegacyV1ImportState" }]); + + const exit = yield* Effect.exit(runMigrations()); + assert.strictEqual(exit._tag, "Failure"); + if (exit._tag === "Failure") { + const failure = Cause.pretty(exit.cause); + assert.match(failure, /Migration "56_LegacyV1ImportState" failed/); + assert.match(failure, /already exists/i); + } + + const after = yield* sql<{ readonly migration_id: number; readonly name: string }>` + SELECT migration_id, name + FROM effect_sql_migrations + ORDER BY migration_id DESC + LIMIT 1 + `; + assert.deepStrictEqual(after, before); + }).pipe(Effect.provide(NodeSqliteClient.layerMemory())), +); + +it.effect("reproduces root checkpoint-scope reuse across ordinary runs", () => + Effect.gen(function* () { + const ids = yield* IdAllocatorV2; + const threadId = ThreadId.make("thread:audit-scope"); + const now = DateTime.makeUnsafe("2026-09-04T00:00:00.000Z"); + const firstScopeId = yield* ids.allocate.checkpointScope({ threadId, name: "root" }); + const secondScopeId = yield* ids.allocate.checkpointScope({ threadId, name: "root" }); + const firstRunId = RunId.make("run:audit-scope:1"); + const secondRunId = RunId.make("run:audit-scope:2"); + const providerThreadId = ProviderThreadId.make("provider-thread:audit-scope"); + let projection = emptyProjection(threadCreatedEvent(makeThread(threadId, now), now)); + const scopeEvent = ( + eventId: EventId, + scopeId: typeof firstScopeId, + runId: RunId, + nodeId: NodeId, + ): Extract => ({ + id: eventId, + type: "checkpoint-scope.created", + threadId, + runId, + nodeId, + occurredAt: now, + payload: { + id: scopeId, + threadId, + runId, + nodeId, + parentScopeId: null, + providerThreadId, + kind: "root_run", + ordinalWithinParent: 0, + advancesAppRunCount: true, + cwd: "/repo", + createdAt: now, + }, + }); + + projection = applyToProjection( + projection, + scopeEvent( + EventId.make("event:scope:1"), + firstScopeId, + firstRunId, + NodeId.make("node:scope:1"), + ), + ); + projection = applyToProjection( + projection, + scopeEvent( + EventId.make("event:scope:2"), + secondScopeId, + secondRunId, + NodeId.make("node:scope:2"), + ), + ); + + assert.strictEqual(firstScopeId, secondScopeId); + assert.strictEqual(projection.checkpointScopes.length, 1); + assert.strictEqual(projection.checkpointScopes[0]?.runId, secondRunId); + }).pipe(Effect.provide(idAllocatorLayer)), +); + +it("reproduces a stale failed run waking a later snooze", () => { + const threadId = ThreadId.make("thread:audit-snooze"); + const createdAt = DateTime.makeUnsafe("2026-08-01T00:00:00.000Z"); + const failedAt = DateTime.makeUnsafe("2026-08-20T00:00:00.000Z"); + const snoozedAt = DateTime.makeUnsafe("2026-09-01T00:00:00.000Z"); + const snoozedUntil = DateTime.makeUnsafe("2026-09-10T00:00:00.000Z"); + let projection = emptyProjection( + threadCreatedEvent(makeThread(threadId, createdAt, { snoozedAt, snoozedUntil }), createdAt), + ); + projection = applyToProjection(projection, { + id: EventId.make("event:audit-snooze:failed-run"), + type: "run.created", + threadId, + providerInstanceId, + occurredAt: failedAt, + payload: { + id: RunId.make("run:audit-snooze:1"), + threadId, + ordinal: 1, + providerInstanceId, + modelSelection, + providerThreadId: null, + userMessageId: MessageId.make("message:audit-snooze:1"), + rootNodeId: null, + activeAttemptId: null, + status: "failed", + requestedAt: failedAt, + startedAt: failedAt, + completedAt: failedAt, + checkpointId: null, + contextHandoffId: null, + }, + }); + + assert.strictEqual( + isAutoSettlementCandidate( + threadShellFromProjection(projection), + Date.parse("2026-09-04T00:00:00.000Z"), + ), + true, + ); +}); diff --git a/audits/orchestrator-v2/2026-09-04/persistence.md b/audits/orchestrator-v2/2026-09-04/persistence.md new file mode 100644 index 000000000000..76cde26e6e0f --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/persistence.md @@ -0,0 +1,312 @@ +# Orchestrator V2 persistence and lifecycle audit + +Date: 2026-09-04 +Frozen branch HEAD: `8af5734365f7c45bc08b57066dbae42f9f7d4235` +Initial fetched main: `d7cf8aaa8d4fbcbdd523b4f4bc86fda5c47b4a70` +Final fetched main: `bc03c3640d6d3bb44e5fb477bfd78d7484cd0e00` +Merge base: `c8f77e0d441264efb0acfac312e852c81ae3da83` +Prior audit HEAD: `d2f1f511f4cc833bc930d6c355cd0f9b61e835a0` + +This audit is limited to schema upgrades, legacy import, projections, startup and recovery, outbox behavior, checkpoint diff and rollback, project and thread lifecycle boundaries, auto-settlement and snooze behavior, durable scheduling, and query cardinality. I reviewed committed source with `git show :` and local-only changes from the `.snapshot` paths recorded in `worktree-manifest.json`. I did not modify product source or product tests. + +## Outcome + +Five prior correctness findings remain open, and both prior performance findings are fixed. I found one additional concrete performance issue in the durable scheduler. The final main fingerprint added one late performance-parity gap, M10. Startup corruption verification has a separate, unmeasured safety/performance tradeoff recorded below; it is not a continuation of F15. + +| ID | Priority | Frozen committed status | Frozen overlay status | Result | +| ----------- | -------- | ------------------------ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| F01 | P1 | Open | Open | Old V2 migration histories at 052, 053, and 055 still collide with renumbered current migrations and skip newer main migrations. | +| F03 | P1 | Open | Open | A second ordinary run still reuses and reassigns the only root checkpoint scope, while full diff requires a run-1-owned root scope. | +| F04 | P1 | Open | Open | WebSocket forced project deletion still commits V2 thread deletions before a force-less legacy project deletion can reject. | +| F05 | P1 | Open, broadened | Open | HTTP and live/offline CLI still bypass the V2-aware project lifecycle. HTTP also drops the newly added update fields. | +| F13 | P2 | Open | Open | Failed status still wakes a later snooze without proving the failure occurred after the snooze. | +| F14 | P2 | Fixed | Fixed | Checkpoint diff now uses a narrow three-query checkpoint context instead of hydrating the transcript. | +| F15 | P2 | Fixed | Fixed | Startup recovery now selects unfinished candidates and no longer sequentially loads every active and archived thread history. | +| PERSIST-N01 | P2 | New | Open | The five-second scheduler poll full-scans and decodes every scheduled task instead of using the due-task index. | +| M10 | P2 | Missing late-main parity | Partial groundwork only | V2 metadata and provider-control paths still hydrate unrelated history after main [#9758](https://github.com/pingdotgg/t3code/pull/9758) stopped doing so. | + +F01, F03, F04, F05, and F13 are rollout risks. F14 is a real fix in the last committed reconciliation. F15 is fixed by the candidate-selection work in `d98f1d5e38`. + +## F01: historical V2 migration cohorts still cannot upgrade + +### Evidence + +The frozen manifest puts main migrations at 44 through 47 and the V2 sequence at 48 through 58 (`apps/server/src/persistence/Migrations.ts` at frozen HEAD, lines 58-72 and 128-142). The runner executes only IDs above the latest recorded ID (`Migrations.ts:166-184`). It does not use the recorded migration names to reconcile a renamed history. + +I verified the manifest-selected migration bodies by Git blob identity, not by filename inference: + +| Historical cohort | Historical manifest | Current identical bodies | +| ------------------------- | --------------------- | ------------------------ | +| `c1791ab2637` | V2 migrations 044-052 | Current 048-056 | +| Prior audit `d2f1f511...` | V2 migrations 045-053 | Current 048-056 | +| `d98f1d5e38` | V2 migrations 045-055 | Current 048-058 | + +The old `c1791ab2637` tree contains an unused `044_ClearAutomaticProjectModelDefaults.ts`, but its manifest imports and records `044_OrchestrationV2`. The cohort comparison and probe use the manifest-selected file. + +The audit probe uses the actual current migration functions to create those byte-identical historical schemas under their recorded old IDs, then invokes the actual current migrator against in-memory SQLite. Results: + +- Old 052 starts current 053 `ApplicationEventSource`, whose old 049 body already ran. Its unconditional `ALTER TABLE ... ADD COLUMN application_event_version` at `053_ApplicationEventSource.ts:33-47` fails with a duplicate-column error. +- Old 053 starts current 054 and reaches current 056 `LegacyV1ImportState`, whose old 053 body already created the table. `056_LegacyV1ImportState.ts:9-26` fails because the table already exists. +- Old 055 starts current 056 and fails at the same preexisting legacy-import table. + +All three failures roll the attempted migration batch back to the prior recorded maximum. The probe also confirms that old 055 lacks `auto_pull` and `project_icon_json` because numeric IDs 45 through 47 are treated as already applied. + +The skipped work depends on cohort: + +- Old 052 skips current 044 through 052, including `ClearAutomaticProjectModelDefaults`, `ProjectionProjectsAutoPull`, `RepairAutomaticSettlementTimestamps`, and `ProjectionProjectIcon`. +- Old 053 and 055 already applied current 044 under that name, but skip current 045 through 047 and the renumbered V2 steps below their maximum. + +Main itself ends at migration 047. A database produced by current main therefore advances into branch migration 048 correctly. Fresh installs also work. This is a branch-history compatibility regression, not main lag. + +### Trigger and consequence + +Start the frozen build against a database previously opened by any of the reproduced V2 cohorts. Server startup fails before readiness. Making only one DDL statement idempotent would move the collision but would not execute the skipped main data repairs and schema additions. + +### Required coverage + +Use a manifest-aware bridge keyed by recorded `(migration_id, name)` history, then append idempotent repair migrations for any main work skipped by old numeric maxima. Add table-driven upgrade fixtures for each supported historical manifest and useful partial stopping points. Fresh-schema tests cannot prove upgrade compatibility. + +### Overlay + +The frozen overlay adds migration 059 with three indexes. The audit probe confirms committed 058 upgrades through live 059 and the indexes exist. Historical cohorts still fail at 053 or 056 before 059 can run, so the finding applies equally to frozen committed 058 and the local 059 overlay. + +## F03: full diff still fails after an ordinary second run + +### Evidence + +For a zero baseline, `CheckpointDiffQuery` finds run ordinal 1 and requires a `root_run` scope whose current `runId` equals that first run (`apps/server/src/checkpointing/CheckpointDiffQuery.ts` at frozen HEAD, lines 157-170). If it cannot find that scope, it returns `CheckpointRefUnavailableError` at lines 173-179. + +Production creates a different state: + +- `IdAllocator.allocate.checkpointScope` derives the ID only from `threadId` and scope name (`orchestration-v2/IdAllocator.ts:295-300`). +- Every ordinary root run requests the same name, `root`, while storing the current `runId` in the scope payload (`CheckpointService.ts:184-210`). +- Projection upsert replaces the prior row for that deterministic scope ID, including its ownership fields. + +The real allocator/reducer audit probe allocates and applies two ordinary root scopes. Both allocations return the same ID; after run 2, there is one scope row and its `runId` is run 2. Root independently confirmed the same production ownership shape. + +The product test fabricates two different root scope IDs and retains one scope for each run (`checkpointing/CheckpointDiffQuery.test.ts:18-44`). Its happy path therefore cannot be produced by the allocator it is meant to cover. + +### Trigger and consequence + +Complete two ordinary runs in one Git-backed thread, then request a full diff through turn 2. The shared scope's ordinal-zero baseline ref is still derivable, and the target checkpoint exists, but the query rejects because the shared scope is no longer owned by run 1. Full-thread diff fails from the second completed run onward. + +The zero baseline should be resolved from the actual shared root scope, normally the target checkpoint's scope, rather than by joining scope ownership to run ordinal 1. Replace the two-scope fixture with state made by the real allocator/projector. + +### Overlay + +No frozen overlay file changes `CheckpointDiffQuery`, `IdAllocator`, or `CheckpointService`. The ProjectionStore overlay does not change checkpoint-scope ownership. F03 remains open locally. + +## F04: WebSocket force deletion can partially commit + +### Evidence + +The WebSocket project handler reads active and archived V2 shells, checks `force`, and independently dispatches one `thread.delete` per thread (`apps/server/src/ws.ts` at frozen HEAD, lines 1299-1319). Only after those commits does it call `ProjectService.delete`, omitting `force` (`ws.ts:1320-1323`). + +`ProjectDeleteInput` has no force field, and `ProjectService.delete` dispatches a legacy `project.delete` without one (`project/ProjectService.ts:48-51,363-386`). The legacy decider rejects any nonempty project unless `force === true`; with force, it decides thread and project deletion as one sequence (`orchestration/decider.ts:280-313`). + +The legacy importer reads `projection_threads` and writes V2 events, but it intentionally leaves the V1 rows in place (`orchestration-v2/LegacyV1ThreadImporter.ts:459-490`). Once a V2 `thread.created` event exists, the importer does not create that thread again. + +### Trigger and consequence + +Force-delete through WebSocket a project containing imported V1 threads. V2 thread deletions commit first. The legacy project delete sees the still-present V1 threads and rejects because force was dropped. The project and V1 rows remain, the V2 copies are deleted, and later import does not restore them. This is a destructive partial commit, not merely a mismatched error message. + +Main's V1 WebSocket path normalizes the original command and sends it intact to one decider transaction (`ws.ts` at main, lines 1263-1296); the decider carries force through the thread/project sequence. The V2 split coordinator regresses that invariant. + +### Overlay + +The frozen overlay does not contain `ws.ts`, `ProjectService.ts`, the legacy decider, or the importer. F04 is unchanged. + +## F05: project lifecycle still diverges across transports + +### Evidence + +The shared `ProjectMutation` contract carries: + +- `createWorkspaceRootIfMissing` on create; +- `autoPull`, `projectIcon`, `faviconPath`, and `defaultThreadEnvMode` on update; +- `force` on delete. + +See `packages/contracts/src/project.ts` at frozen HEAD, lines 116-145. The WebSocket create and update branches forward these fields (`apps/server/src/ws.ts:1264-1298`) and perform V2 thread validation/deletion for project removal. + +The HTTP mutation handler calls `ProjectService` directly and drops all of the fields above except the older title/root/model/scripts set (`apps/server/src/project/http.ts:45-80`). The live CLI delegates to this HTTP endpoint (`cli/project.ts:324-338`). The offline CLI duplicates the same reduced mapping and direct legacy deletion (`cli/project.ts:423-459`). + +The last committed reconciliation added `autoPull`, project icon, favicon, and default environment mode to the shared update contract and WebSocket mapping, but did not add them to HTTP or offline CLI. This broadens F05; it is not a separate finding. + +### Triggers and consequences + +- Delete a V2-only populated project through HTTP. The V1 read model can see no thread, so the legacy project row is deleted while V2 threads remain and reference a deleted project. +- Force-delete an imported populated project through HTTP, live CLI, or offline CLI. Force is dropped, so the legacy decider rejects. +- Send a typed HTTP create with `createWorkspaceRootIfMissing: true`. The service receives the default false behavior. +- Send a typed HTTP update for `autoPull`, project icon, favicon, or default thread environment mode. The request succeeds without applying that field. + +The current HTTP tests cover only error translation (`project/http.test.ts:15-51`). The CLI integration covers add, title rename, and empty-project removal (`cli/project.test.ts:116-133`). Neither suite exercises the dropped fields or populated mixed-store deletion. + +One lifecycle coordinator should own validation and mutation across V1/V2, with WebSocket, HTTP, live CLI, and offline CLI preserving the same typed input. Tests need imported and V2-only projects, active and archived threads, force false/true, missing-root creation, and every update field. + +### Thread lifecycle note + +V2 thread mutation commands remain on the WebSocket command path. The V2 HTTP surface reviewed here serves shell, detail, and history reads through `ThreadManagementService`; it does not define a competing HTTP thread-mutation implementation. I found no separate thread archive/unarchive/delete divergence within that intended split. Project deletion is the cross-store exception because it owns thread cleanup. + +### Overlay + +No project transport or lifecycle source is present in the frozen overlay. F05 remains open locally. + +## F13: stale failure still wakes a newer snooze + +### Evidence + +For a future snooze, V2 defines `wokeOnError` as `thread.status === "failed"` with no time comparison (`orchestration-v2/ThreadSettlementService.ts` at frozen HEAD, lines 108-117). Completion correctly requires `latestRunCompletedAt > snoozedAt` in the next two lines. + +Main's V1 policy requires the error session's `updatedAt` to be newer than `snoozedAt` (`orchestration/ThreadSettlementPolicy.ts` at main, lines 98-109). The V2 shell already exposes the latest run completion time needed for an equivalent ordering check. + +The audit probe creates a projected failed run completed on August 20, then a snooze beginning September 1 and ending September 10. At September 4, the production V2 policy returns `true`, treating the old failure as an early wake. The frozen overlay's unit test also explicitly expects any failed status to wake a future snooze without a failure timestamp (`ThreadSettlementService.test.ts.snapshot:127-139`). + +### Trigger and consequence + +Fail a thread, then snooze it into the future. At the next settlement evaluation, the stale failure defeats the newer snooze. If the thread also matches closed-PR or inactivity settlement policy, it can move to settled before the requested wake time. + +Require failed-run completion evidence newer than `snoozedAt`. Cover both failure-before-snooze and failure-after-snooze through the projected candidate path. + +### Rejected lead + +Closed pull requests should continue to settle when the optional day and on-merge settings are off. `pullRequestSettles` accepts `closed` independently and gates only `merged` on `autoSettleOnMerge` (`ThreadSettlementService.ts:80-92`). The frozen overlay preserves this behavior and its test at `ThreadSettlementService.test.ts.snapshot:230-238`. An unconditional early return when both optional settings are off would remove valid closed-PR behavior and is not recommended. + +## F14: checkpoint diff hydration is fixed + +Commit `8af5734365` changes checkpoint diff to call `getCheckpointContext` (`checkpointing/CheckpointDiffQuery.ts:102-121`). `ProjectionStore.getCheckpointContext` performs three narrow queries for run ID/ordinal/status, scope ID/run/kind/cwd, and checkpoint scope/run/app ordinal/status/ref (`orchestration-v2/ProjectionStore.ts:2957-3002`). It does not read transcript messages, turn items, provider histories, or fork ancestry. + +The focused checkpoint diff suite passes 5 tests. This fixes the prior read-cardinality issue. It does not fix F03 because the narrow query faithfully returns the production shared-scope ownership that the zero-baseline logic mishandles. + +The frozen ProjectionStore overlay retains the narrow query unchanged. + +## F15: startup recovery targeting is fixed + +Commit `d98f1d5e38` removes the prior recovery call over every active and archived shell. `ProviderRuntimeRecoveryService` now asks for `getRecoveryThreadIds("runtime")` and full-loads only those candidates (`ProviderRuntimeRecoveryService.ts:482-511`). The candidate SQL selects nonterminal runs, pending runtime requests, nonterminal sessions, provider-owned background work, relevant nonterminal turn items, and pending/running outbox entries (`ProjectionStore.ts:2696-2787`). The focused recovery tests confirm terminal histories are not loaded for runtime reconciliation. + +That fixes F15 as previously defined and recommended. It also removes repeated shared-session and fork-history hydration. The frozen overlay does not regress this path. + +## Separate startup corruption-verification tradeoff + +Startup still blocks command readiness on `projectionMaintenance.verify` (`serverRuntimeStartup.ts:518-553`). Verification calls `getUnreadableThreadIds` (`ProjectionMaintenance.ts:75-119`), which pages through all 16 canonical projection tables, selects each `payload_json`, and schema-decodes every row (`ProjectionStore.ts:2789-2952`). Messages, turn items, provider turns, checkpoints, active threads, archived threads, and terminal history are all included. Paging at 500 bounds peak row memory and each canonical row is decoded once, but total startup work remains O(all retained V2 projection rows). + +This is not the old F15 recovery behavior. It is an intentional safety check that detects corrupt canonical rows and propagates unreadability through fork ancestry before accepting commands. I did not benchmark its latency or memory impact, so it is not reported as a defect. Benchmark representative large databases before deciding whether the readiness cost is acceptable. Any optimization must preserve equivalent corruption detection, for example through validated incremental metadata or another complete verification strategy; simply removing or narrowing the scan would weaken recovery safety. + +The frozen overlay improves periodic settlement separately by adding `getSettlementCandidates` and narrow `getThread` reads. Migration 059 supplies the relevant indexes. It does not change startup verification. + +## PERSIST-N01: the scheduler ignores its due-task index every five seconds + +Priority: P2 performance. + +### Evidence + +`ScheduledTaskService.selectAllRows` selects every column of every scheduled task and orders the complete table by update time (`scheduledTasks/ScheduledTaskService.ts` at frozen HEAD, lines 175-199). `listTasksLenient` decodes every row's schedule, workspace strategy, and model selection (`:207-224`). `runDueTasks` calls that full-list path and only then filters enabled, due, and non-running tasks in memory (`:583-609`). The loop repeats every five seconds (`:665-669`). + +Migration 055 already creates `idx_scheduled_tasks_due(enabled, next_run_at)` with a partial predicate for enabled tasks having a next run (`persistence/Migrations/055_ScheduledTasks.ts:32-36`). The polling query has no `WHERE` clause, so it cannot use that index to bound candidates by `next_run_at`. + +### Trigger and consequence + +Accumulate many disabled tasks or enabled tasks scheduled far in the future. Even when nothing is due, the server reads, allocates, JSON-decodes, and sorts every row every five seconds. Cost is O(all scheduled tasks) per poll instead of O(due tasks), creating steady database and CPU load. + +This scheduler is branch-only at the compared main commit, so the issue is not main lag. It is a scaling defect in the added durable scheduling core. Query due rows directly with `enabled = 1`, non-null `next_run_at`, `next_run_at <= now`, and non-running status. Crash recovery can keep its separate one-time running-row query. Add a behavior/cardinality test that seeds many future/disabled rows and proves the poll decodes only due rows. + +## M10 late arrival: metadata and provider-control paths still hydrate history + +Priority: P2 performance and failure isolation. Status: missing at frozen committed HEAD. The frozen overlay adds useful groundwork but does not address the affected paths. + +Late main commit `6365919f2e5bcfb4fa4020b95e19af26ae40979f`, [#9758](https://github.com/pingdotgg/t3code/pull/9758), splits `ProviderCommandReactor` reads into thread shell and thread detail. Main now uses shell reads for session state, compaction guards, post-generation title checks, interrupt and recovery, approval and user-input forwarding, session stop, and runtime-mode propagation (`ProviderCommandReactor.ts` at that commit, lines 528-538, 572-608, 984-995, 1375-1385, 1442-1640, and 1700-1715). It keeps detail reads for the two operations that consume transcript data: title regeneration and turn start (`:1008-1058` and `:1178-1201`). Three changed behavior tests put invalid JSON in an old message and prove approval response, user-input response, and session stop no longer decode that unrelated body (`ProviderCommandReactor.test.ts` at that commit, lines 517-530, 3556-3595, 3597-3640, and 3846-3886). + +V2 distributes the same responsibilities across services, so copying the V1 reactor would be the wrong fix. The actual paths are: + +| Behavior | V2 committed path | Assessment | +| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Worktree and branch naming | `ThreadLaunchService.ts:194-213` generates from the supplied initial message without reading history. | Generation is already superseded by the V2 design. The workspace and rename results still dispatch `thread.metadata.update` through the full projection path at `:287-319`. | +| Initial title generation | `ThreadTitleRegenerationService.ts:184-228` loads the whole projection to locate one initial message, then dispatches completion at `:169-182` and `:247-253`. | Missing. Initial generation needs one message and thread metadata, not the full transcript. | +| Explicit title regeneration | The same service formats the transcript at `:190-228`. | Full history is intentional here, matching main's retained detail read. Only the stale guard and completion write should be narrow. | +| Metadata and mode mutations | `Orchestrator.ts:1389-1425` routes `thread.metadata.update`, `thread.title.regeneration.complete`, and runtime/interaction mode changes through `getThreadProjection`. Their reducers use thread payload fields at `:1694-1721`; workspace and runtime-mode changes also inspect provider sessions to plan detaches at `:1884-1900`. `ThreadLifecycleService.ts:80-87` then reads the full projection again for its result. | Missing transcript isolation, but not every case is app-thread-only. Title completion and interaction mode need only the thread. Workspace changes and runtime mode need a narrow thread-plus-session context. None needs messages. | +| Approval and user-input responses | `RuntimeRequestService.ts:76-125` loads the full projection to locate one runtime request before calling the live session. | Missing, but a narrow runtime-request lookup is required. The app-thread-only `getThread` read cannot replace this safely. | +| Interrupt and restart | `ProviderTurnControlService.ts:80-162` loads the full projection to validate one provider thread and turn; restart polls the full projection again at `:211-231`. | Missing. This needs a narrow provider execution context, not a V1 shell port or an app-thread-only read. | +| Session stop and detach | `Orchestrator.ts:2003-2053` loads the full projection to validate one provider session. `ProviderSessionManager.ts:1566-1605` loads it again when a multi-thread-capable runtime must interrupt attached active turns. | Missing transcript isolation. Preserve the exact session and active-turn checks in a narrow context. | +| Provider turn start | `ProviderTurnStartService.ts:91-125` reads runs, nodes, attempts, messages, checkpoint scopes, handoffs, and provider state. | No gap. Main also keeps detail for turn start. | + +The committed generic mutation handler creates a concrete failure boundary. `getThreadProjection` selects every message payload for an unwindowed read (`ProjectionStore.ts:2398-2402`) and schema-decodes all of them (`:2515-2531`). A long thread therefore pays O(retained history) to rename a branch, update a title, complete title regeneration, or change runtime mode. One malformed old message also rejects the metadata command before it can emit its event. This is the same isolation problem that the new main tests cover, expressed through V2's projection tables. + +The dirty overlay is not a local-only fix for M10. `ProjectionStore.ts.snapshot:173-175` and `:3003-3019` add `getThread`, which selects and decodes only the app-thread payload. `Orchestrator.ts.snapshot:1389-1430` uses it for `thread.visit`, and `:6944-6975` uses it for the auto-settlement guard. However, `thread.metadata.update`, `thread.title.regeneration.complete`, and mode mutations remain in `dispatchThreadMutation`, whose first operation is still `getThreadProjection` (`Orchestrator.ts.snapshot:1432-1468` and `:6988-6995`). Runtime requests and provider-turn control are unchanged in the frozen overlay. + +The smallest V2-shaped fix is command-specific. Route title-only metadata, title completion, and interaction-mode mutations through the overlay's `getThread`. Give workspace metadata and runtime-mode mutations a narrow context containing the app thread plus the provider-session fields their detach logic uses. Initial title generation can use a narrow message lookup plus app-thread metadata. Runtime-request response, session detach, and provider-turn control need narrow queries keyed by their existing IDs. Keep full or purpose-built context reads for explicit title regeneration and turn start. Regression coverage should corrupt an unrelated historical message and prove metadata update, title completion, runtime-request response, interrupt, and session stop remain usable without weakening stale-request, detach, or target-identity checks. + +## Feature parity matrix + +| Area | Main or intended behavior | Frozen committed branch | Frozen overlay | Assessment | +| -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------ | +| Fresh/main migration | Main 047 advances into V2 048 | Works | 058 to 059 probe passes | Parity for fresh/current-main histories | +| Historical V2 upgrade | Supported old branch state should start | 052/053/055 cohorts fail | Still fail below 059 | F01 open | +| Legacy shell import | Import metadata cheaply and hydrate transcript on demand | Preserved and idempotent | Unchanged | Pass | +| Projection recovery targeting | Load only unfinished/recoverable threads | Candidate SQL after `d98f1d5e38` | Unchanged | Pass | +| Projection startup validation | Detect corrupt projection rows before readiness | Paged decode of every canonical row | Unchanged | Unmeasured safety/performance tradeoff; benchmark and decide | +| Outbox recovery | Requeue durable work, retire process-bound work, drain before readiness | Preserved; focused recovery tests pass | Unchanged | Pass within tested cases | +| Checkpoint diff read model | Narrow metadata lookup | Three narrow queries | Preserved | F14 fixed | +| Full diff after run 2 | Resolve the real baseline for shared scope | Requires run-1-owned scope | Unchanged | F03 open | +| Checkpoint rollback | Validate state and restore through typed service | Focused rollback tests pass | Unchanged | Pass within tested cases | +| WS project create/update | Preserve typed fields | Preserves current fields | Unchanged | Pass | +| WS forced project delete | Validate and delete without partial commit | Split V2 deletes then force-less V1 delete | Unchanged | F04 open | +| HTTP project mutation | Same semantics as WS | Drops fields and V2 cleanup | Unchanged | F05 open | +| Live CLI project mutation | Same as typed server lifecycle | Inherits HTTP divergence | Unchanged | F05 open | +| Offline CLI project mutation | Same lifecycle without server | Direct reduced `ProjectService` mapping | Unchanged | F05 open | +| V2 HTTP thread reads | Bounded shell/detail/history reads | Uses V2 projection services | Overlay narrows visit/settlement metadata | Pass in scope | +| Metadata/provider command reads after [#9758](https://github.com/pingdotgg/t3code/pull/9758) | Shell or narrow context unless transcript is consumed | Generic metadata mutations and provider control hydrate full history | `getThread` exists but is used only for visit and the auto-settlement guard | M10 missing; overlay is partial groundwork | +| Snooze ordering | Only later failure/completion wakes early | Completion ordered, failure unordered | Still unordered | F13 open | +| Closed-PR settlement | Closed PR settles independently of optional flags | Preserved | Preserved | Pass; false positive rejected | +| Settlement query cost | Avoid full shell/history reads per sweep | Full shell snapshot at committed HEAD | Narrow candidate and metadata reads | Local-only improvement | +| Durable schedule calculation | Fixed-time/interval semantics and missed-run handling | Focused tests pass | Unchanged | Pass | +| Durable schedule polling | Query only due work | Full table decode every 5 seconds | Unchanged | PERSIST-N01 | +| Git/VCS status used by settlement | Local status should not pay unnecessary divergence walks | Full local status at committed HEAD | `--no-ahead-behind`; remote status retains divergence/PR lookup | Local-only improvement; no correctness regression found | + +## Frozen overlay review + +I inspected the requested files separately from committed evidence: + +- `Orchestrator.ts.snapshot` moves visits and auto-settlement guards to the new narrow thread metadata read. It preserves forward-only `lastVisitedAt`, deletion checks, and the settlement snapshot guard. +- `ProjectionStore.ts.snapshot` adds narrow thread and settlement candidate queries. Its SQL excludes archived, deleted, overridden, pinned, active-run, and pending-request rows before loading candidate background data. The paired SQL/memory parity test passes. F13 remains because failed ordering is policy logic after the query. +- `ThreadSettlementService.ts.snapshot` consumes the candidate query instead of the full shell snapshot. Closed-PR behavior remains correct. +- `Migrations.ts.snapshot` and `059_OrchestrationV2ShellIndexes.ts.snapshot` add indexes used by the settlement candidate path. The committed-058 to local-059 upgrade probe passes. +- `GitManager.ts.snapshot`, `GitVcsDriver.ts.snapshot`, and `GitVcsDriverCore.ts.snapshot` let local-only status skip ahead/behind revision walks. Remote status still computes upstream divergence and PR association. The review/action path still requests full status. I found no lifecycle or settlement correctness regression from this change. +- `server.ts.snapshot` supplies `ProjectionStoreV2.layer` to the application layer required by the new settlement dependency. +- The new `getThread` primitive is suitable for M10's title-only, title-completion, and other app-thread-only handlers, but the overlay has not routed them through it. It cannot replace workspace/runtime-mode, provider-session, provider-turn, or runtime-request lookups because those need child records. + +The overlay's `ProjectionSettlement.test.ts.snapshot` is substantive behavior coverage. It compares SQL and memory candidates, tests background work parity, corrupt historical payload isolation, and query-plan index use. The live version passed. It does not test failure-before-snooze, and the existing settlement unit test currently encodes the opposite behavior. + +## Focused validation + +No repository-wide check was run. Unique product coverage was 10 files and 52 tests, all passing: + +- checkpoint diff, checkpoint rollback, legacy import; +- projection recovery and provider runtime recovery; +- schedule calculation; +- project HTTP error mapping and CLI empty-project lifecycle; +- live dirty-overlay settlement policy and SQL/memory projection settlement. + +The audit-only probe has exactly 6 passing cases: + +| Probe name | Result | +| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| `upgrades committed-058 state through the live-059 overlay` | Passed | +| `reproduces the old-052 cohort collision against the current migrator` | Passed; asserted the expected current-053 migration failure and rollback | +| `reproduces the old-055 cohort collision and skipped main columns` | Passed; asserted the expected current-056 migration failure and absent main columns | +| `reproduces the prior-audit old-053 cohort collision` | Passed; asserted the expected current-056 migration failure and rollback | +| `reproduces root checkpoint-scope reuse across ordinary runs` | Passed; one shared scope remained owned by run 2 | +| `reproduces a stale failed run waking a later snooze` | Passed; production policy returned `true` for the reproduced stale-failure state | + +Exact totals for consolidation: 10 unique product test files with 52 tests passed, plus 1 audit-only probe file with 6 tests passed. Combined, 11 unique test files and 58 tests passed. Repeated authoring/rerun invocations are not counted as additional coverage. + +The exact commands and results are in `persistence-tests.log`. The probe is `persistence-audit-probes.test.ts`. It uses in-memory SQLite and actual implementations. No live T3 userdata was opened. + +The earlier copied-test import failure reported by root was caused by unsuffixed audit snapshots entering Vitest discovery. All frozen overlay copies now end in `.snapshot`; none was discovered in these runs. It is not a product regression. + +## Limitations + +- I did not launch a server, provider, browser, simulator, or live/offline CLI process. The project lifecycle findings are deterministic handler/service/decider traces; integrated disposable transport tests remain necessary with a fix. +- I did not benchmark startup verification or scheduler polling. Startup verification is recorded only as a safety/performance tradeoff; PERSIST-N01 is based on explicit polling SQL and loop cardinality, not measured latency or memory. +- M10 is a source-only review of late main commit `6365919f2e5bcfb4fa4020b95e19af26ae40979f` and its direct V2 equivalents. I ran no additional tests for this addendum. +- Migration probes cover three known complete historical manifests. Other partial stopping points still need a table-driven compatibility matrix. +- I did not modify existing tests. Current green tests do not contradict F03, F04, F05, or F13 because their fixtures omit the production trigger or encode the faulty behavior. +- Provider adapter protocol behavior, auth/relay, title retry, PR metadata, WebSocket fallback F16, and the separately reviewed archived-thread scheduler/MCP lead are outside this report. diff --git a/audits/orchestrator-v2/2026-09-04/pr-metadata-final.json b/audits/orchestrator-v2/2026-09-04/pr-metadata-final.json new file mode 100644 index 000000000000..70b150fdf04d --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/pr-metadata-final.json @@ -0,0 +1,257 @@ +{ + "baseRefName": "main", + "headRefOid": "8af5734365f7c45bc08b57066dbae42f9f7d4235", + "number": 2829, + "state": "OPEN", + "statusCheckRollup": [ + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:25:05Z", + "conclusion": "FAILURE", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744766", + "name": "Check", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:27Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624915/job/101129746493", + "name": "Build macOS Apple Silicon preview", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "Desktop macOS Preview" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:27Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624962/job/101129746252", + "name": "EAS Preview", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "Mobile EAS Preview" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:27Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624883/job/101129745113", + "name": "Deploy web preview", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "Web Preview" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:24:30Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624996/job/101129747755", + "name": "Native fingerprint diff", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "Mobile Fingerprint Check" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:33Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905622732/job/101129737618", + "name": "Prepare PR size config", + "startedAt": "2026-09-04T18:23:28Z", + "status": "COMPLETED", + "workflowName": "PR Size" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:29Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905622705/job/101129737077", + "name": "Collect PR targets", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "PR Vouch" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:27Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624915/job/101129745554", + "name": "Remove preview download", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "Desktop macOS Preview" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:33Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905622732/job/101129775867", + "name": "Sync PR size label definitions", + "startedAt": "2026-09-04T18:23:34Z", + "status": "COMPLETED", + "workflowName": "PR Size" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:25:06Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744778", + "name": "Test", + "startedAt": "2026-09-04T18:23:37Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:43Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905622705/job/101129757508", + "name": "Label PR 2829", + "startedAt": "2026-09-04T18:23:32Z", + "status": "COMPLETED", + "workflowName": "PR Vouch" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:27Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624915/job/101129746083", + "name": "Publish anonymous download", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "Desktop macOS Preview" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:26:43Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744870", + "name": "Test Server 1", + "startedAt": "2026-09-04T18:23:35Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:54Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905622732/job/101129772818", + "name": "Label PR size", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "PR Size" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:26:01Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744788", + "name": "Test Server 2", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:33:55Z", + "conclusion": "CANCELLED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744689", + "name": "Test Server 3", + "startedAt": "2026-09-04T18:23:34Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:24:03Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744861", + "name": "Rust", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:45Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744696", + "name": "Mobile Native Changes", + "startedAt": "2026-09-04T18:23:35Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:24:57Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744508", + "name": "Release Smoke", + "startedAt": "2026-09-04T18:23:34Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:25:00Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129836308", + "name": "Mobile Native Static Analysis", + "startedAt": "2026-09-04T18:24:05Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:26:19Z", + "conclusion": "NEUTRAL", + "detailsUrl": "https://github.com/pingdotgg/t3code/pull/2829/checks?check_run_id=101129651357", + "name": "Macroscope - Approvability Check", + "startedAt": "2026-09-04T18:23:08Z", + "status": "COMPLETED", + "workflowName": "" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:46Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/pull/2829/checks?check_run_id=101129648791", + "name": "Macroscope - Correctness Check", + "startedAt": "2026-09-04T18:23:07Z", + "status": "COMPLETED", + "workflowName": "" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:39Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/pull/2829/checks?check_run_id=101129783475", + "name": "Macroscope - Effect Service Conventions", + "startedAt": "2026-09-04T18:23:35Z", + "status": "COMPLETED", + "workflowName": "" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:40Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/pull/2829/checks?check_run_id=101129786339", + "name": "Macroscope - UI Consistency", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "" + }, + { + "__typename": "StatusContext", + "context": "CodeRabbit", + "startedAt": "2026-09-04T18:23:29Z", + "state": "SUCCESS", + "targetUrl": "" + } + ], + "updatedAt": "2026-09-04T18:52:35Z", + "url": "https://github.com/pingdotgg/t3code/pull/2829" +} diff --git a/audits/orchestrator-v2/2026-09-04/pr-metadata.json b/audits/orchestrator-v2/2026-09-04/pr-metadata.json new file mode 100644 index 000000000000..b0dec15a6427 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/pr-metadata.json @@ -0,0 +1,261 @@ +{ + "baseRefName": "main", + "body": "## Summary\n- wire orchestration V2 provider adapter registry/factory flow for Codex and Claude provider instances\n- add Claude replay/query primitives, native fork/rollback fixtures, subagent fixture coverage, and provider replay harness updates\n- update debugger model/provider picker and improve user-facing orchestration errors\n\n## Validation\n- bun fmt\n- bun lint\n- bun typecheck\n- bun run test -- src/orchestration-v2/testkit/OrchestratorReplayFixtures.integration.test.ts -t claudeAgent\n- bun run test -- src/orchestration-v2/testkit/ClaudeReplayFixtures.integration.test.ts\n- bun run test -- src/orchestration-v2/testkit/ThreadFork.integration.test.ts -t Claude\n\n## Notes\n- Draft PR for review of current branch state. Codex all-provider replay still needs schema alignment with latest app-server behavior before it can be treated as a full-suite signal.\n\n## Closes\n\nVerified against the branch with code/commit evidence.\n\n### High confidence\nCloses #4952\nCloses #4873\nCloses #4775\nCloses #4795\nCloses #4710\nCloses #4668\nCloses #4619\nCloses #4584\nCloses #4561\nCloses #4713\nCloses #4198\nCloses #4452\nCloses #3797\nCloses #4232\nCloses #3666\nCloses #3580\nCloses #2785\nCloses #2789\nCloses #3138\nCloses #1404\nCloses #231\nCloses #216\n\n### Medium confidence (under review)\nCloses #4568\nCloses #4766\nCloses #4495\nCloses #4456\nCloses #4399\nCloses #3744\nCloses #2921\nCloses #3624\nCloses #3149\nCloses #2336\nCloses #538\nCloses #2173\nCloses #2065\n\n\n\n\n> [!NOTE]\n> ### Introduce orchestration V2 runtime, provider adapters, MCP toolkits, and scheduled tasks\n> - Adds a complete orchestration V2 runtime: event store, projection store, effect outbox/worker, run execution, checkpoint capture/rollback, context handoff, thread launch/lifecycle/fork services, runtime policy, provider session management, and runtime recovery\n> - Adds V2 provider adapter framework with built-in adapters for Claude, Codex, Cursor, Grok, OpenCode, Antigravity, and ACP Registry, all sharing a common ACP or SDK integration layer\n> - Adds orchestrator and worktree MCP toolkits with typed tool definitions, handlers, and HTTP registration\n> - Adds a scheduled-task service with interval and fixed-time schedules, persistence, live subscriptions, and CRUD operations\n> - Adds database migrations 048–058 for V2 event/projection schema, subagents, provider-session bindings, thread-launch workflows, application event sourcing, effect cancellation, scheduled tasks, legacy import state, and recovery indexes\n> - Adds a legacy V1 thread importer for one-way migration of existing thread shells and transcripts into V2\n> - Migrates web and mobile clients, shared packages, and client-runtime state to consume V2 projections, shells, and runtime models instead of the legacy session/turn model\n> - Risk: replaces the legacy orchestration engine's thread handling with V2; the old `OrchestrationEngine` now handles project commands only and no longer performs thread auto-settlement, user-input activity lookup, or thread replay. Cursor settings no longer define `binaryPath` or `apiEndpoint`. Provider instances expose `orchestrationAdapter` instead of `adapter`.\n>\n> \n>\n> Macroscope summarized 8af5734.\n> \n>\n\n\n\n---\n\n> [!NOTE]\n> **Medium Risk**\n> Mobile thread persistence and list/archive/stop behavior change with V2 runtime semantics; removing the thread-transfer report workflow reduces PR visibility into transfer budget regressions.\n> \n> **Overview**\n> This slice of the orchestration V2 rollout **retires the thread-transfer PR comment pipeline** (trusted publisher script, tests, and `workflow_run` workflow) while CI can still emit transfer artifacts; it also **installs `build-essential` in CI** so ACP process-tree fixtures compile instead of soft-skipping.\n> \n> **Mobile** moves onto shared V2 client-runtime pieces: SQLite cache uses `ORCHESTRATION_CACHE_SCHEMA_VERSION` and stored V2 shell/thread snapshots, runtime wiring swaps in bounded thread snapshot loading and history control, and thread detail/review/archive flows read **projections** (`runtime`, `RuntimeRequestId`, checkpoint summaries from `runId`) instead of V1 session/turn shapes. UX additions include **activity inspector**, **queue control**, **relationships banner**, progressive **history controls**, server **visit** watermarking, stricter **archive** rules via `threadCanArchive`, and approval/user-input cards that honor **live vs dead** provider `responseCapability`.\n> \n> Smaller touches: shared **brand mark** module, new **uniwind adaptive color** tokens, desktop env test for user-data dir names, README link to appearance docs, and marketing copy for Cursor harness.\n> \n> Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 9eeed8c17109be3752d2f8e1643583d1f579ea2d. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).\n\n\n", + "headRefName": "t3code/codex-turn-mapping", + "headRefOid": "8af5734365f7c45bc08b57066dbae42f9f7d4235", + "isDraft": false, + "number": 2829, + "state": "OPEN", + "statusCheckRollup": [ + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:25:05Z", + "conclusion": "FAILURE", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744766", + "name": "Check", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:27Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624915/job/101129746493", + "name": "Build macOS Apple Silicon preview", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "Desktop macOS Preview" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:27Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624962/job/101129746252", + "name": "EAS Preview", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "Mobile EAS Preview" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:27Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624883/job/101129745113", + "name": "Deploy web preview", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "Web Preview" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:24:30Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624996/job/101129747755", + "name": "Native fingerprint diff", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "Mobile Fingerprint Check" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:33Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905622732/job/101129737618", + "name": "Prepare PR size config", + "startedAt": "2026-09-04T18:23:28Z", + "status": "COMPLETED", + "workflowName": "PR Size" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:29Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905622705/job/101129737077", + "name": "Collect PR targets", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "PR Vouch" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:27Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624915/job/101129745554", + "name": "Remove preview download", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "Desktop macOS Preview" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:33Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905622732/job/101129775867", + "name": "Sync PR size label definitions", + "startedAt": "2026-09-04T18:23:34Z", + "status": "COMPLETED", + "workflowName": "PR Size" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:25:06Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744778", + "name": "Test", + "startedAt": "2026-09-04T18:23:37Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:43Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905622705/job/101129757508", + "name": "Label PR 2829", + "startedAt": "2026-09-04T18:23:32Z", + "status": "COMPLETED", + "workflowName": "PR Vouch" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:27Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624915/job/101129746083", + "name": "Publish anonymous download", + "startedAt": "2026-09-04T18:23:27Z", + "status": "COMPLETED", + "workflowName": "Desktop macOS Preview" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:26:43Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744870", + "name": "Test Server 1", + "startedAt": "2026-09-04T18:23:35Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:54Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905622732/job/101129772818", + "name": "Label PR size", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "PR Size" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:26:01Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744788", + "name": "Test Server 2", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:33:55Z", + "conclusion": "CANCELLED", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744689", + "name": "Test Server 3", + "startedAt": "2026-09-04T18:23:34Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:24:03Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744861", + "name": "Rust", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:45Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744696", + "name": "Mobile Native Changes", + "startedAt": "2026-09-04T18:23:35Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:24:57Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129744508", + "name": "Release Smoke", + "startedAt": "2026-09-04T18:23:34Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:25:00Z", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/pingdotgg/t3code/actions/runs/33905624991/job/101129836308", + "name": "Mobile Native Static Analysis", + "startedAt": "2026-09-04T18:24:05Z", + "status": "COMPLETED", + "workflowName": "CI" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:26:19Z", + "conclusion": "NEUTRAL", + "detailsUrl": "https://github.com/pingdotgg/t3code/pull/2829/checks?check_run_id=101129651357", + "name": "Macroscope - Approvability Check", + "startedAt": "2026-09-04T18:23:08Z", + "status": "COMPLETED", + "workflowName": "" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:46Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/pull/2829/checks?check_run_id=101129648791", + "name": "Macroscope - Correctness Check", + "startedAt": "2026-09-04T18:23:07Z", + "status": "COMPLETED", + "workflowName": "" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:39Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/pull/2829/checks?check_run_id=101129783475", + "name": "Macroscope - Effect Service Conventions", + "startedAt": "2026-09-04T18:23:35Z", + "status": "COMPLETED", + "workflowName": "" + }, + { + "__typename": "CheckRun", + "completedAt": "2026-09-04T18:23:40Z", + "conclusion": "SKIPPED", + "detailsUrl": "https://github.com/pingdotgg/t3code/pull/2829/checks?check_run_id=101129786339", + "name": "Macroscope - UI Consistency", + "startedAt": "2026-09-04T18:23:36Z", + "status": "COMPLETED", + "workflowName": "" + }, + { + "__typename": "StatusContext", + "context": "CodeRabbit", + "startedAt": "2026-09-04T18:23:29Z", + "state": "SUCCESS", + "targetUrl": "" + } + ], + "title": "feat(orchestrator): introduce new orchestrator", + "updatedAt": "2026-09-04T18:52:35Z", + "url": "https://github.com/pingdotgg/t3code/pull/2829" +} diff --git a/audits/orchestrator-v2/2026-09-04/prior-audit-range-diff-summary.txt b/audits/orchestrator-v2/2026-09-04/prior-audit-range-diff-summary.txt new file mode 100644 index 000000000000..c5b520db04d5 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/prior-audit-range-diff-summary.txt @@ -0,0 +1,336 @@ + 1: 15dff312363 < -: ----------- chore(ov2): preserve the integration base for replay + -: ----------- > 1: b8b7f894fcd chore(ov2): preserve the integration base for replay + 2: e911c41199e ! 2: cc2e380a1ed Integrate Codex app-server support + 3: 77a63c13b82 ! 3: 8852b949785 nit + 4: 4da42ca393a ! 4: 3fe3534dbef revert more + 5: d914dc03290 = 5: fdf63358fa2 resynclock + 6: ba5d340a047 < -: ----------- Delay Codex provider availability until checked + 7: 4c8648f791f = 6: 773f789c828 Return Cursor ACP runtime with explicit scope + 8: a5270231419 = 7: f355bd32b10 Normalize Codex IDs and preserve streamed stdout decoding + 9: 99e5494242a ! 8: c41b812f43f Scope Codex session runtime lifetimes + 10: 3bded8ba565 = 9: faf4d6c04e2 decoders + 11: 3182df2608d = 10: a1d85aa3331 Flush native logs on adapter shutdown + 12: 74942087a35 ! 11: ce08dee1407 Switch Codex provider checks to app-server probe + 13: fa13e794bbe ! 12: d2a22ec1652 Address Codex review feedback + 14: 783f4f6e8d2 = 13: 99de1c8833e Add orchestration v2 docs and probe fixtures + 15: eb8af12dca3 = 14: 28999d55151 Add orchestration v2 replay and service contracts + 16: 75120285ae7 = 15: 67d40b8e8ee Map Codex turns into orchestration v2 + 17: 5e551ef7227 ! 16: 41937c522ee Implement orchestration v2 runtime + 18: ca9ba20375c = 17: 959c0e22e73 Add thread fork lineage and lazy context transfer + 19: 76dc095de6a = 18: 5169fe6083b Add orchestration V2 backend checklist + 20: be1d5acc702 = 19: 88b265dab63 Add merge-back context handoff support + 21: 052c24ec16d = 20: 3a75dbb5a18 Add V2 command capability policy + 22: b460c064415 = 21: 5c6af6923c2 Add Claude replay fixture recorder + 23: 166fd1c53cf = 22: 05d619192a4 Extract Claude SDK query runner from provider adapter + 24: d4cd5427996 = 23: f806017a3c6 Add model selection to orchestration runs + 25: 41c5f212a75 = 24: c71caf0f964 Map Claude replay fixtures to multi-turn turns + 26: c1e8a125374 = 25: d9f4e700c07 Map Claude turns to runtime query policies + 27: 617f3279952 = 26: 1be35b30fa1 Support active Claude steering and turn replay mapping + 28: 2182b71bfab = 27: ebf98e42177 Add turn-interrupt replay coverage and protocol logging + 29: b76bbc23de9 = 28: ec935be6a56 Document Cursor SDK MCP projection for V2 + 30: 631219bca58 = 29: bf94a66361a feat(orchestration-v2): wire claude adapter primitives + 31: e2ba0751f78 = 30: 1ed757ba0c5 feat(orchestration-v2): support cross-provider handoff + 32: 2e38197d2b2 = 31: 69cba683fa0 fix(orchestration-v2): resolve cross-provider forks + 33: 08430b8115f = 32: 86f785623b1 feat(orchestration-v2): add merge-back replay coverage + 34: 98e98085afd = 33: 28cc526e1f8 fix(orchestration-v2): compose provider switch merge context + 35: 73fe5fd8780 = 34: 3c06f0c2c9c fix(orchestration-v2): preserve source history on merged switch + 36: a4a63953eda ! 35: 43910683671 Map orchestration v2 WS methods to auth scopes + 37: 7078dac915d = 36: d175a63a1bc feat(orchestration-v2): model native subagents + 38: d855d91f0a3 ! 37: 5dec17fc19c wip + 39: 6b81144d2cd = 38: a244d5c8951 refactor(orchestration-v2): adopt host process spawn policy + 40: 3056bfd7c01 = 39: 8cc9df27fa7 Add orchestration MCP toolkit + 41: 8dcf191a942 ! 40: 26e930ea408 Add Cursor SDK orchestration replay support + 42: 4ff48c09838 = 41: 37045a02fe9 Handle segmented Cursor turns and stable visible timelines + 43: ad109c26f5a ! 42: b43bc2b62c4 Add ACP replay harness and session lifecycle support + 44: e35661a8497 = 43: 7cfebe0be47 Add MCP thread management and Codex turn mapping + 45: a115e55b347 = 44: 915e6b385a2 Add Orchestration V2 application integration plan + 46: fb1ebd0f2f7 ! 45: dab646dc400 Map orchestration turns to provider instances + 47: 65345a5bb44 = 46: f1d7d1c1226 Share Codex sessions across orchestration threads + 48: 74115dcb013 = 47: 9caaa2e23f8 Align orchestration V2 with Effect service conventions + 49: 900c8ec2778 = 48: 5bac980a78e Start orchestration V2 application services + 50: 3f52b6a9ec1 = 49: 4d85c0c89bd Complete orchestration V2 application services + 51: e9e19735a94 = 50: 591c8b76b6e Require MCP registry for V2 provider sessions + 52: 708aed97c9f = 51: 7ba8f57840a Remove MCP credential expiration + 53: f254d805e70 = 52: 418deadc726 Guarantee MCP revocation during session release + 54: b56d0e7d53f ! 53: c0bb02d6da0 Integrate orchestration v2 with the application runtime + 55: c9dec101819 = 54: 78b451958a7 Split the V2 frontend plan into parity and enrichment phases + 56: b1c074b2ec3 ! 55: 65e85e1e2d4 Complete orchestration V2 frontend cutover + 57: c39d6100691 ! 56: 61182514a62 Integrate orchestration V2 controls and process recovery + 58: ef051d86d84 ! 57: 9b175222292 Handle preparing turns across provider orchestration + 59: fcc2a2d0963 = 58: 890f95e6a7f Record created threads and subagent progress + 60: ecddebcc67d ! 59: b9717bb8517 Map thread panel into title bar and sidebar + 61: 2aad9bc514f ! 60: 7d5eedaf9f6 Reserve space for inline thread details panel + 62: 0531d50ed58 = 61: b9ae98f9794 Split open-in editor controls into panel and toolbar variants + 63: 6c6e346d381 ! 62: c8dce47576c Hide subagent threads and simplify thread controls + 64: 1a2b7432e98 ! 63: 4b5fa27f95c Render mobile timelines from V2 turn items + 65: 327f7287bb8 ! 64: d5a4342a3da Enrich mobile V2 execution items + 66: af6028c82dc ! 65: 06c57e49daa Expose V2 thread workflows on mobile + 67: 2e05af67463 ! 66: e70b8940053 Retire V1 client orchestration parity + 68: 4d8e17808be = 67: 1ee6b0622eb Add iOS associated domains for Clerk + 69: db9310c2f62 = 68: 569c448f009 Map Grok task envelopes to subagent lineage + 70: 9f069920613 = 69: 4a7e85f0fca Adopt userdata-v2 and subagent activity mapping + 71: 4313ad89dd3 = 70: 30d6cf06ec9 Map nested Codex subagent threads correctly + 72: 0eb1fc59abf = 71: 47f269d4364 Clarify thread relationship icons and ordering + 73: 036f3f9daf4 = 72: aa9c46184f2 Keep persistent cards visible in folded turns + 74: f0bd8850aa2 ! 73: f8579194c5a Require Cursor API key for provider checks + 75: 5f2045fcc32 = 74: 0d4886de7c9 fix(web): align thread details panel controls and menus (#3606) + 76: 6c78a01831d ! 75: 8e2e8edd364 Switch Cursor provider to the official SDK + 77: 695c57b4227 = 76: 61dec910677 Remove early access badges from Cursor and Grok + 78: f2711e089d1 = 77: 89eb3f0bb82 Allow provider switching via handoff in chat threads + 79: 5dc316e8ebe = 78: cb435247582 Fix Claude task turn mapping + 80: 25df2c7c873 ! 79: 2871cf85de7 feat: scheduled tasks (automations) (#3638) + 81: 698f41eb600 = 80: c1bae1c69fc feat(orchestrator): Add shared provider continuation and background item plumbing + 82: 55fd431a069 ! 81: 47ec735048d [orchestrator-v2] fix(orchestrator): Restore Claude session continuity for resume, wake, and idle release (#3860) + 83: 935aa5deb7a = 82: f11c744887c [orchestrator-v2] fix(orchestrator): Codex background command completion and subagent resume (#3908) + 84: 822242fc77b = 83: e15cb8b34f6 fix(orchestrator): scope Claude MCP tool pre-approval (#3862) + 85: ec90f1ec95e = 84: a9f67f41d33 feat(orchestrator): pass model options through MCP thread targets (#3872) + 86: 4060032ea1d = 85: 8a79bdd091c fix(orchestrator): align Claude permission replay with SDK + 87: 6e01338ad37 = 86: 5d7d125331d fix(ci): restore Claude permission request identity + 88: 17d2f5d2d42 = 87: b9668c94839 test(desktop): expect orchestrator v2 state directory + 89: 6f0e825e483 = 88: 5ce823a928c fix(claude): redact launch arguments from protocol logs + 90: cec49e2ca05 = 89: bfb55f793b3 fix(claude): preserve approvals with full-access sandbox + 91: 66f3b79c8e1 = 90: bad24edaf5c fix(claude): allow questions during plan mode + 92: bf9a8775d7c = 91: 3c091989c6f fix(claude): honor never-approval runtime policies + 93: cbcfea8b7d0 = 92: f218e04f09a fix(claude): enforce read-only tool availability + 94: f17413cc120 = 93: 1e4a96b5610 fix(claude): reopen queries after MCP credential rotation + 95: 14f5595b686 = 94: 1124866e9f6 fix(acp): release turns after interrupt timeout + 96: 9a065758da1 = 95: be7bb48c0aa fix(acp): bind MCP credentials to activated threads + 97: 555b0469e9d ! 96: 333ecf1ff79 fix(orchestrator): harden Grok v2 lifecycle (#3578) + 98: a307962b2ba = 97: f006bffe139 fix(orchestrator): dedupe Grok continuation dispatch + 99: 8e879081c3f = 98: 007b51b0ce5 fix(orchestrator): Harden Grok v2 runtime lifecycle +100: a210dc8c288 = 99: b116daa728b test(orchestrator): align integration fixtures +101: 1695b69e128 = 100: fa905ec6362 fix(mobile): support Hermes collection sorting +102: 643047ad47f = 101: 2fd782d05bc fix(grok): align ACP extensions with open source runtime +103: c026716d343 ! 102: 1093a70b448 Render T3 MCP tools with branded timeline labels +104: d8b06653dff ! 103: 917fad6c322 Unify T3 MCP tool presentation across clients +105: 8e173085a7c ! 104: bcf43a8f018 fix(orchestration): clarify agent delegation and scheduling +106: 092daf3c497 = 105: cd095953df7 fix(server): preserve released migration ordering +107: 39505241c82 = 106: f18cbfb6841 fix(web): restore v2 composer chrome +108: 92bfc55bc39 = 107: 80a9b6628b8 fix(web): remove stacked composer shadows +109: 7e3d2119880 = 108: 3fa4661dd66 refactor(web): use shared glass surfaces +110: b07b35f8fcc = 109: b51d858ac04 fix(web): contain thread details panel effects +111: 2f50f6b93f0 = 110: df523273344 test(orchestrator): Align post-merge CTM fixtures (#4193) +112: c93936748b4 = 111: 3e6d9c12dd6 fix(orchestrator): Preserve claude/codex post-interrupt recovery state (#4229) +113: b2e4223af67 = 112: c75cec919c3 test(orchestrator): align Codex approval reviewer replays (#4457) +114: 2a25e1d2deb = 113: dff34c177aa fix(orchestrator): hydrate shell cache and group multi-environment projects (#3640) +115: 83ea5f70c16 = 114: 780302519d3 feat(subagents): disclose projected results consistently (#3866) +116: 7ae175a5f35 = 115: d52c1e6e6d5 Add worktree handoff and status tools to the t3-code MCP server (#3754) +117: 0bc459bd0fa = 116: 64a9daf87cd fix(mobile): wait for fork shell before navigation +118: bafa7a432ba = 117: 55cb6938055 fix(server): keep derived threads awake +119: 45d60f9a51b = 118: 961a655902e fix(server): enforce ACP auth and preserve fork provenance +120: 16b8599b267 = 119: 8fb46345695 fix(server): clean up Claude replay failures +121: 4a3797b4825 = 120: 0bcafedc7ca test(orchestrator): align merged V2 compatibility checks +122: da04feea481 = 121: e05564e15a5 fix(grok): Prevent spurious wake run after in-turn monitors +123: 9649b226006 = 122: af0f7759971 fix(acp): Preserve wake evidence across an app-owned wake +124: ba3c8210040 = 123: f4553701dbb fix(orchestrator): Wake settled parents when delegated children finish +125: 0e018044d74 = 124: f0b7a4ed427 fix(claude): Settle positive task-notification results +126: 1e42d8e9098 ! 125: dda77e7bb49 fix: hide subagent threads from v2 lists +127: 4d9180dc781 = 126: bc1a9c7d76b fix: ignore subagents when sorting sidebar projects +128: ef8219c2e3d = 127: 933d9c04217 fix(web): restore checked-in project scripts +129: d59b7c2ba35 = 128: 4569c531d59 chore(orchestrator): refresh checks after main sync +130: 3ba155db4fa = 129: e684489f7d8 feat: migrate v1 state into orchestrator v2 (#4400) +131: 6c82f71da51 = 130: 81619adf57b fix(orchestrator): schedule effects from durable deadlines (#4656) +132: 32d563e07ce = 131: 73fb62aeed3 fix(orchestration): harden scheduled task startup +133: 8006f38f2e6 ! 132: 384873780e8 fix(mobile): preserve active thread state +134: 51e044f7ad1 = 133: 657ee69e5ff fix(orchestration): preserve legacy schedule compatibility +135: 8d27ca499e3 = 134: 385f1537b78 fix(contracts): reject invalid legacy intervals +136: 3edb72687d6 = 135: cedc11513d4 fix(acp): make xai cancellation reliable +137: 7252e405740 = 136: 49654af76e5 fix(orchestration): handle checkpoint-wait runs +138: 0900ea01d94 = 137: 9761382b9df fix(orchestration): cancel queued work on archive +139: 1fdab432e8f = 138: 3087d27841d fix(mobile): allow archiving post-provider work +140: 0db5a1d2e6d = 139: 14d68b3c2ad fix(mobile): distinguish queued and waiting archive states +141: 120242d9fb5 = 140: 4fd8f62bc94 fix(cursor): log close attempts before execution +142: 345a9a4a3a6 = 141: ff5e6f1b32d fix(acp): discover final teardown descendants +143: 09963b2172d = 142: d0fca84e651 fix(checkpoints): preserve valid run history +144: 6c30ce289bd = 143: c2b51fc0902 fix(orchestration): preserve imported conversation state +145: 0d5dbddd166 = 144: 6ab76be2243 fix(acp): enforce task and permission invariants +146: c6adb55a0a7 = 145: bd653b476bf fix(testkit): harden provider replay recording +147: 9f71aa9ca6b = 146: 4cf4ed7202f fix(server): isolate deterministic attachment ids +148: afeb2089d20 = 147: 2ca3166d409 fix(claude): preserve explicit model options +149: 153a1f8548e = 148: 0954b3bb597 fix(web): enforce secure provider field defaults +150: c2145dde126 = 149: b605ddde083 fix(client): preserve live thread relationships +151: 6179f46681c = 150: 67f85a5c781 fix(checkpoints): retain thread-start baseline after failed runs +152: 80e5ef9865d = 151: 91e3a339592 fix(mobile): gate thread controls on live runs +153: 5a2a714d781 ! 152: 088c56b41f3 fix(orchestrator): address late review findings +154: ff10b65fe6e = 153: 739c3ff962d fix(orchestrator): handle fresh review edge cases +155: 785e1388d01 = 154: b65d8ca4cf6 fix(orchestrator): harden provider edge cases +156: 0a9a06ba642 = 155: d6eb526629a fix(orchestrator): execute resolved runtime responses +157: 49ad52e66d3 = 156: dd2b8814975 fix(orchestrator): release stranded effect claims +158: c17955171a4 = 157: c2a48e3c8e9 fix(worktrees): make handoff rollback atomic +159: c7a62d3c36d = 158: f081c2c84c4 fix(orchestrator): avoid replaying settled effects +160: 7b1e9dad867 = 159: 83cf7d6dfa6 fix(orchestrator): preserve retryable effect failures +161: 69299bf47b7 = 160: ddb3c272115 fix(orchestrator): preserve terminal effect outcomes +162: 9c3a6b75e98 = 161: 9a404d4672f fix(orchestrator): validate replay edge cases +163: af590d13aea = 162: 697fff8d50d fix(orchestrator): decode direct Claude result blocks +164: 614c744be91 = 163: 2e813f8c4bd fix(orchestrator): close cancellation edge cases +165: e59043aebb2 = 164: 6fcbf009d42 fix(orchestrator): validate rollback and search links +166: 327189894e0 = 165: 014e9a2621e fix(server): preserve project mutation client errors +167: 8af2b58d152 = 166: 10c462fbd20 fix(orchestrator): preserve migrated and nested history +168: 9aeb65f738d = 167: 01c127f54ed fix: address orchestration review findings +169: fa408d129f1 = 168: 3e72c6a17b2 fix(mobile): label queued message intent +170: 5de19555913 = 169: 88a1900091b fix: address orchestration review findings +171: a2b1e1ef93f = 170: 1e65d374c19 fix: preserve orchestration task identity +172: 981b2ddc749 = 171: dbc5127f330 fix: address latest orchestration review findings +173: 6832caec1f1 = 172: d4990c75c3a fix: preserve thread management failure semantics +174: dd9b6b0d4bd = 173: 5c24e3506ae fix: close failed provider adapter scopes +175: 0ee02d54900 = 174: a12849d5916 feat(server): surface legacy thread migration progress +176: 7b28551f4bb ! 175: 27806ef4d85 feat(orchestration): track provider retries and thread visits +177: 0d57ac71aed = 176: bedec74e857 [codex] feat(web): show git progress in the commit button (#4963) +178: 0ca2c503d95 = 177: b5d353cc8a3 perf(orchestration): per-thread shell deltas, visit throttling, event compaction (#4971) +179: 3dc8b570afc = 178: 16620e9fe4b fix(chat): prevent stale timeline scroll and rerenders +180: c123bddb2bf = 179: 673e0f49e7e fix(relay): stop replaying the whole event store into the awareness relay +181: 5e292307986 = 180: 1fc6545515e perf(web): keep timeline minimap animations off the main thread +182: 888283cd7ff = 181: 5d0644e2af9 feat(orchestration): port thread title regeneration to the v2 runtime +183: e2284c99f17 = 182: 8c7e1c13fa2 fix(orchestration): thread visits no longer create activity loops (#5038) +184: aadfcb978b7 = 183: a78cc2c5238 fix(orchestration): promoted queued messages keep the queued_turn intent +185: 3cd279a07a3 = 184: 1c378332b10 refactor(orchestration): split thread-not-sendable into typed errors +186: 790fe93a99d = 185: 3df8422d569 fix(web): remove elevated thread details panel styling +187: cb592a7a920 = 186: b8a1f761729 fix(web): keep Git progress title anchored +188: 6a7824f3525 ! 187: f44c22a14a8 fix: reconcile rebase with latest main +189: 6a8fcc6576e ! 188: daa272bac55 fix(orchestration-v2): restore generated thread titles (#5176) +190: 78aea07a319 = 189: 4fad4c56afc fix(orchestrator): Order thread lineage by creation time (#5310) +191: d13cb6b8f50 = 190: 7c9c6dcb7f1 fix(server): restore worktree branch naming in the v2 orchestrator (#5309) +192: 4e72ea725c1 ! 191: 51d7089afc6 feat(chat): refine V2 conversation UI (#5307) +193: 704808d9235 = 192: 0d5f04f6041 fix: adopt effect beta.103 APIs in rebased v2 code +194: d4e31cb20fd = 193: ea285714f2e fix: send mcp-protocol-version header in worktree registration test +195: fa775c22ad2 = 194: 413885f1d3c fix(web): restore compact header sizing for project script controls +196: 39fab14dc40 = 195: 69d932b37a2 test(server): cover v2 thread title regeneration +197: 4ffad32204a ! 196: 1691887191e chore: resolve lint warnings across v2 code +198: 1b91a552e00 = 197: 648d1f42b86 fix(test): keep codex replay recovery off the repo checkout +199: 7f3ebe40d91 = 198: cf083513446 fix(orchestrator): Prevent redundant delegated completion turns (#5311) +200: 14ca09db7b5 = 199: 00efd07bd42 fix(server): stop tying codex text-generation temp files to the caller's scope (#5406) +201: 3699b557e91 = 200: ec1fd6195a5 fix(web): remove open PR actions from git controls +202: fa557cd7741 = 201: e609aabd27d fix(server): renumber v2 migrations after main's 036_ProjectionThreadsPinned +203: 2e3b8638261 ! 202: 8ba222e5201 fix: port main fixes stranded by the v2 rewrite +204: 6a924e9d5f4 = 203: 690257b3cd2 test(server): align migration expectations with renumbered ids +205: 2b4e393ff5b = 204: a657cb37357 feat(orchestrator): Surface waiting background work (#4378) +206: ec7370e7e52 = 205: 3f8506737ca fix(web): align git action progress button layout +207: 20cec19eb52 = 206: acbb25bc175 fix: repair conflict-marker artifacts from rebase auto-resolutions +208: bfb9d9465a3 = 207: 7222e6bdf71 fix(server): renumber v2 migrations after main's 037_ProjectionTurnsKeysetIndex +209: e778ae6f30a ! 208: 103f1e6cd22 fix: port main fixes stranded by the v2 rewrite (round 2) +210: 4e87742e9ba = 209: be208f5073b chore(web): prune plan-sidebar leftovers after the inline-plans rework +211: bed1245b22d = 210: 1b95828aec9 fix(web): port the refined live-follow gesture gating to the v2 timeline +212: 09c99a51a1d = 211: cd782e9cdce fix(web): let LegendList own end-follow and disclosure anchoring (#5449) +213: fddf025c0bf = 212: f568e4df2ce fix(web): show Git action success inline in panel +214: f2d1f16c3c7 ! 213: 7b7a3c68f5e fix: repair rerere-damaged files and reconcile main's round-3 features with v2 +215: fbfa125f2df = 214: 976fa4da287 chore(server): renumber v2 migrations 038-046 to 041-049 after main's 038-040 +216: 1ffb1eaf785 = 215: b10a1a4a613 fix(server): port round-3 main fixes into the v2 orchestrator +217: 75fdf57d998 = 216: 17abb7b57ae test(web): restore main's right-panel migration expectations after the panel-visibility merge +218: e3fb981cacd = 217: c95f718a92a test(server): expect attachment saved-at lines in ClaudeAdapterV2 turn text +219: e69b9944e54 = 218: c6429f0ec60 fix(web): restore the branch's slim chat header +220: 15d7ed4ddc5 ! 219: b23bae2e07c feat(web): add pull request actions to thread details +221: 6f39090bcbc = 220: cf8159205d6 fix(mobile): port main's composer stabilization into the v2 thread screens +222: 9e7a5b0566e = 221: 647dcb34c3a fix(web): reconcile main's round-5 features after the rebase +223: 365ffce1014 ! 222: 8c976ef74d2 feat(web): prioritize pull request row actions +224: 167f5f6068b = 223: 4569224ce1d fix(web): restore main's collapse chrome and tab-status keying on the PR panel +225: 862479b5159 = 224: 54912ca1722 feat(orchestration): bound thread history and resume payloads +226: e861e74df5e = 225: 35e8172373e feat(contracts): track thread title regeneration +227: b16ac847938 = 226: 0c2def0526e fix: reconcile main's round-6 features after the rebase +228: 3d812634cfd = 227: ecbf6849d78 fix(web): keep the titlebar layout controls fixed across right-panel toggles +229: 7c8af3708e0 = 228: 8e026d24642 fix(web): align titlebar clusters to one shared pixel inset +230: a39f6a267d8 = 229: 66051a7d854 fix(web): size the titlebar layout-control icons like the sidebar trigger +231: e74f01c66a9 = 230: eeb374557dc perf(server): keep shell snapshots bounded and active-only +232: ace57ebdfc6 ! 231: 95ea8072fa8 fix: reconcile main's round-8 features after the rebase +233: d734b66fff0 = 232: 358fa7b42d1 fix(server): reject replaying a command receipt across threads in v2 +234: 5c722de01c3 ! 233: 1c3f3ff94a8 feat(mobile): surface prominent activity status and metadata +235: 796911d54dd ! 234: 40b35dbb9f2 fix: reconcile main's round-9 features after the rebase +236: 2e425197055 ! 235: 0e4c8cf65be feat(server): honor withheld agent browser access in the v2 runtime +237: f22abd94cd9 = 236: bd708261286 fix(web): restore the titlebar sizing and timeline fade lost to main's style simplification +238: 8bf0b5fcb34 = 237: 3bbb50c08e8 refactor(web): finish aligning the branch with main's style simplification +239: 5d1e08ef48f = 238: 6d31e48c7d2 fix(orchestration): show provider retries in the work log +240: ab8569a7a35 ! 239: 06a2b41a06c fix: reconcile main's round-10 features after the rebase +241: 1533041bfd6 ! 240: 2c3c47d1dd3 fix(web): stop mis-marking recovered and text-reported tool failures in the v2 work log +242: 650a24252e6 = 241: f2b786b92ec feat(orchestration-v2): project linked pull requests on threads (#8160) +243: f894a3531f6 = 242: 4650a6971b4 feat(orchestration-v2): carry approval options and app names to the client (#8058) +244: 4eb10990383 = 243: 96a5bf0bde6 feat(orchestration-v2): route Codex thread feedback uploads through v2 (#7949) +245: a854b2fcfd6 = 244: d4735799dd3 feat(analytics): credit v2 threads and turns to the starting client (#7774) +246: 47b1560306c = 245: 197d245344f fix(grok): fail hung prompts on xAI rate-limit completions (#8358, partial) +247: dfc21af186a = 246: 8c559a0fe9d feat(orchestration-v2): show live context usage in the meter (#8144) +248: 2c188dd57be = 247: d7f68523648 fix(web): keep following the stream after returning to the live edge (#6519) +249: 8fdce450171 = 248: 718ff37efae feat(grok): capture exit_plan_mode into the v2 proposed-plan card (#8358) +250: 0b8e40fbc57 = 249: c6ac7fae2f6 fix(web): repaint the composer glass and strip the thread-panel popover chrome +251: d81b12f2aae = 250: 2c7ab194c49 fix(web): adopt main's attached-composer surface contract so the glass survives shoulder tabs +252: a8df9625013 = 251: 7e9527c2a7e fix(web): converge ChatComposer on main's drawer-era body +253: c0cbbbc8441 = 252: 15ac91d2ee3 fix(web): collapse settled tool runs behind main's summary toggles +254: 72056ac8934 = 253: 6bc36d5fdef fix(web): surface v2 todo-list plans as task progress +255: 1c3b15a8352 = 254: d209d13ff97 fix(web): show the command on collapsed tool rows, not its stdout +256: c380aa6c877 = 255: 698db66a384 fix(web): collapsed tool rows preview inputs for every tool type +257: 0301dc423e3 ! 256: a2c1f7fde39 fix: reconcile main's round-11 features after the rebase +258: 690ea07bacf = 257: 344d661acce fix(opencode): route child-session approvals through the v2 adapter +259: a2efa89c95e = 258: 7b35f0756fb fix: reconcile main's round-12 features after the rebase +260: 084d72779dd = 259: bbde2509229 fix: restore main's automatic thread settling after the revert +261: bf963f1d4f5 = 260: 2dbca2799fc fix(web): restore the full-screen file-drop target over the chat column +262: 1c589887516 = 261: e3d09455f4f feat(server): claim uploaded attachments at v2 dispatch +263: a1d309ea774 = 262: dbe86d12fd1 feat(web): show attachments on queued messages and edit them in the composer +264: 3fd374226d0 = 263: 399df7a4397 fix(web): drag-to-reorder queued messages and retire stale pending rows +265: aafe194a883 = 264: 03c974d7dd9 fix: reconcile main's round-14 features after the rebase +266: d17919b8451 = 265: 731e44ac862 fix(web): dedupe the composer glass styles and align the chat column width +267: 79ab9ff2114 ! 266: e7d813ad06c fix(mobile): replace remaining dark: utilities with adaptive semantic tokens +268: 6211ffaa69a < -: ----------- fix(lint): allowlist the queue and relationships interop boundaries + -: ----------- > 267: e89268b409b fix(lint): allowlist the queue and relationships interop boundaries +269: bbbaeeb2a3e = 268: edbe21f803a fix(server): inject HostProcessPlatform into the Grok plan extractor +270: 8e0d521bebd = 269: 2a94e7b2d28 chore: retrigger ci +271: 91572bcaf43 = 270: 2fe6d79c49b chore: refresh macroscope ui-consistency check +272: e0ab034b430 ! 271: 12bf10144be fix: reconcile main's round-16 features after the rebase +273: b9400c36a37 = 272: b14ca6bf3ae fix(web): keep failed tool items in the collapsed group summaries +274: 34a4d026a5f = 273: 608793e39e1 fix(server): keep Claude session approvals ephemeral +275: 7e71ff8a806 ! 274: b28c4a4c125 fix(orchestration): reanchor unsettled threads +276: 6b3690e0632 = 275: 7933dd671dc fix(server): observe pre-aborted Claude approvals +277: feedc3f6bbe = 276: 635f552718b fix(server): include service launcher in bundle build +278: 82e1b8ed604 = 277: 4fdafec1d56 fix(orchestration): preserve legacy thread metadata +279: 930dd22e720 = 278: 8f0ada76d8f fix(web): honor disabled legacy plan mode +280: 2cfe234e46c = 279: d72da77e773 fix(server): preserve Claude subagent models +281: eacc09d40ab = 280: 202da64207f fix(orchestration): honor migrated thread visibility in search +282: dcff638944a = 281: 1acca70823e fix(orchestration): recreate missing worktrees before turns +283: e44588afa4c ! 282: 54c0c030ef4 fix(clients): restore Codex feedback submission +284: 8bbf7f50c83 = 283: 1322c48d5d2 fix(server): preserve generic provider attachments +285: 53c6857ec93 = 284: dfaf815157f fix(web): load workspace markdown images through assets +286: 7fca26e6fbf = 285: fa61cae19d4 fix(web): preserve Windows markdown paths +287: 642056fdd9e = 286: 980df245b19 fix(server): keep current provider context usage +288: 5f19d550ae3 = 287: a4cee6104d5 fix(web): restore markdown file chip actions +289: 44f2004810b = 288: 875b9d88568 fix(web): scope markdown actions to their environment +290: 995f4e7e5ad ! 289: 8853fd4386d fix(protocol): reject incompatible orchestration peers +291: 3e1ff1531dd = 290: adc3d1acaa3 docs: explain legacy thread migration +292: 19a30d03be9 = 291: d9e87450162 docs: state portable handoff limits +293: 68104a497e1 = 292: 2e88e58640c chore(repo): remove tracked audit scratch files +294: 98670f337e4 = 293: 0439f0f162a fix(server): guard OpenCode prompt admission races +295: ecf3dd2c9a0 = 294: 537861cf9a9 fix(server): restore Claude structured questions +296: ff9f875f17a = 295: 9991452ad2f fix(server): project Claude plans and todos +297: 9a4734af8e5 = 296: d16e890b16d perf(orchestration): bound history reads in SQL +298: 0921786018a = 297: ac7e04ae29e perf(orchestration): bound complete thread snapshots +299: 3d5bab73d85 = 298: 48dab8cd209 fix(server): restore Claude resume compaction +300: 733db7269f6 = 299: 03d8aef938d fix(server): allow protocol negotiation in CORS +301: 26dfbc29847 = 300: 4c25c80607d fix(server): preserve provider usage in persisted turns +302: 70f82caaa0c = 301: a4891183060 fix(server): preserve Claude planning lifecycle +303: dbb6021f840 = 302: 3d2d5711be6 fix(server): normalize Claude question answers +304: de79f442213 = 303: a8370c67278 fix(server): correlate OpenCode prompt admission +305: be7b07634bb = 304: d4debe5ae8d fix(clients): anchor feedback in conversation order +306: 051565fc96f = 305: 8d2c45c5399 fix(web): retain markdown workspace ownership +307: 870014496f4 = 306: 14322467cf3 fix(orchestration): page history through its true end +308: 07889933e39 = 307: 1fc6d2c9058 fix(server): cancel pending OpenCode prompts safely +309: 0fc565db8ac = 308: 42bafcb317e fix(orchestration): retain nested fork history when paging +310: 47ae99f5176 = 309: f45dde3c861 fix(server): recover OpenCode status reconciliation +311: c1791ab2637 = 310: 93620dfab0f fix(orchestration): select visible history before limiting SQL +312: ed6aafa93f5 ! 311: 7efa4e84b1a fix(web): port composer activity and grouping to orchestration v2 +313: b1533813ce1 = 312: 61e3568dac8 fix(web): align queue headers and prevent stash overlap +314: e82c7178550 = 313: f21af84a704 fix(web): share the outline for joined composer tabs +315: 85a3c125681 = 314: 1a600882893 fix(web): keep stash separate from the composer activity column +316: b2afc4cb458 = 315: b952c574d53 refactor(web): use shared banner rows for queued messages +317: e16d934d8a0 = 316: 1a56fa6768f fix(web): keep queued message editing inside the queue panel +318: 6ce4cb0a15d = 317: 5d5f370ad67 fix(web): keep queued messages in place while editing +319: 6bcc0e39da0 = 318: f8ed1f080dd fix(web): match composer actions to draft and modifier state +320: 72e0c434bea = 319: 5145881d4c2 fix(web): keep composer shortcut tooltip stable on Mod +321: 60bc3cff930 ! 320: cafacd53b80 feat(web): summarize T3 orchestration actions +322: b27f50b65aa ! 321: 6bc5b0f7982 feat(mobile): port chat summaries and transitions to orchestration v2 +323: fa54f546075 = 322: 8b2f951e68a fix(chat): remove added tool summary status counts +324: 4b35166d028 = 323: 42dee149f78 fix(mobile): keep scroll bounds current after animations +325: acdbe292f03 ! 324: 27ef79dc301 fix: reconcile main's round-17 features after the rebase +326: 99e940dc2b3 = 325: 38f3e4d0e02 feat(web): port working and thinking timeline rows to orchestration v2 +327: 7697286069f ! 326: ddf58d90d47 fix: reconcile main's round-18 features after the rebase +328: 2191297898e ! 327: 702ef5e5851 feat(server): evaluate automatic thread settlement in the v2 orchestrator +329: f0174c45778 ! 328: dc4cd901af5 fix: reconcile main's round-19 features after the rebase +330: e6da41e5c6f = 329: 4199e9db516 fix(web): right-align the stash shoulder tab again +331: 0550e0a34db ! 330: 4f924bfd310 fix(web): realign the composer and timeline with main +332: d2f1f511f4c = 331: 96aff3564b3 fix: reconcile main's round-20 features after the rebase + -: ----------- > 332: d98f1d5e38f fix(server): reduce v2 recovery and runtime resource usage + -: ----------- > 333: 8af5734365f fix: reconcile main updates with orchestration v2 diff --git a/audits/orchestrator-v2/2026-09-04/prior-audit-range-diff.txt b/audits/orchestrator-v2/2026-09-04/prior-audit-range-diff.txt new file mode 100644 index 000000000000..120c338db429 --- /dev/null +++ b/audits/orchestrator-v2/2026-09-04/prior-audit-range-diff.txt @@ -0,0 +1,106728 @@ + 1: 15dff312363 < -: ----------- chore(ov2): preserve the integration base for replay + -: ----------- > 1: b8b7f894fcd chore(ov2): preserve the integration base for replay + 2: e911c41199e ! 2: cc2e380a1ed Integrate Codex app-server support + @@ apps/server/integration/orchestrationEngine.integration.test.ts: it.live("forwar + + ## apps/server/package.json ## + @@ + - "@types/node": "catalog:", + + "@types/yauzl": "^3.4.0", + "effect-acp": "workspace:*", + "effect-codex-app-server": "workspace:*", + - "vite-plus": "catalog:" + @@ apps/server/package.json + "node": "^22.16 || ^23.11 || >=24.10" + + ## apps/server/scripts/acp-mock-agent.ts ## + +@@ + + import * as NodeFS from "node:fs"; + + + + import * as Effect from "effect/Effect"; + +-import * as Deferred from "effect/Deferred"; + + + + import * as NodeServices from "@effect/platform-node/NodeServices"; + + import * as NodeRuntime from "@effect/platform-node/NodeRuntime"; + @@ apps/server/scripts/acp-mock-agent.ts: import * as AcpError from "effect-acp/errors"; + import type * as AcpSchema from "effect-acp/schema"; + + const requestLogPath = process.env.T3_ACP_REQUEST_LOG_PATH; + -const exitLogPath = process.env.T3_ACP_EXIT_LOG_PATH; + +-const antigravityProfile = process.env.T3_ACP_ANTIGRAVITY === "1"; + const emitToolCalls = process.env.T3_ACP_EMIT_TOOL_CALLS === "1"; + const emitInterleavedAssistantToolCalls = + process.env.T3_ACP_EMIT_INTERLEAVED_ASSISTANT_TOOL_CALLS === "1"; + +@@ apps/server/scripts/acp-mock-agent.ts: const emitContentThenHang = process.env.T3_ACP_EMIT_CONTENT_THEN_HANG === "1"; + + const emitPlanThenHang = process.env.T3_ACP_EMIT_PLAN_THEN_HANG === "1"; + + const emitActiveToolThenHang = process.env.T3_ACP_EMIT_ACTIVE_TOOL_THEN_HANG === "1"; + + const emitForeignSessionUpdates = process.env.T3_ACP_EMIT_FOREIGN_SESSION_UPDATES === "1"; + +-const waitForResumeRelease = process.env.T3_ACP_WAIT_FOR_RESUME_RELEASE === "1"; + +-const completeFirstPromptOnCancel = process.env.T3_ACP_COMPLETE_FIRST_PROMPT_ON_CANCEL === "1"; + +-const floodStderr = process.env.T3_ACP_FLOOD_STDERR === "1"; + + const hangPromptForever = process.env.T3_ACP_HANG_PROMPT_FOREVER === "1"; + + const hangFirstPromptForever = process.env.T3_ACP_HANG_FIRST_PROMPT_FOREVER === "1"; + + const emitLateUpdateAfterCancel = process.env.T3_ACP_EMIT_LATE_UPDATE_AFTER_CANCEL === "1"; + +@@ apps/server/scripts/acp-mock-agent.ts: const permissionRequestCount = Math.max( + + ); + + const sessionId = "mock-session-1"; + + + +-let currentModeId = antigravityProfile ? "default" : "ask"; + +-let currentModelId = antigravityProfile ? "gemini-test-low" : "default"; + ++let currentModeId = "ask"; + ++let currentModelId = "default"; + + let parameterizedModelPicker = false; + + let currentReasoning = "medium"; + + let currentContext = "272k"; + @@ apps/server/scripts/acp-mock-agent.ts: let promptCount = 0; + let overlappingFirstPromptId: string | undefined; + const cancelledSessions = new Set(); + @@ apps/server/scripts/acp-mock-agent.ts: let promptCount = 0; + -}); + - + function configOptions(): ReadonlyArray { + +- if (antigravityProfile) { + +- return [ + +- { + +- id: "model", + +- name: "Model", + +- category: "model", + +- type: "select", + +- currentValue: currentModelId, + +- options: antigravityModels.map((model) => ({ value: model.modelId, name: model.name })), + +- }, + +- { + +- id: "mode", + +- name: "Mode", + +- category: "mode", + +- type: "select", + +- currentValue: currentModeId, + +- options: availableModes.map((mode) => ({ value: mode.id, name: mode.name })), + +- }, + +- ]; + +- } + if (parameterizedModelPicker) { + const baseOptions: Array = [ + + { + +@@ apps/server/scripts/acp-mock-agent.ts: function availableModels(): ReadonlyArray<{ + + })); + + } + + + +-const antigravityModels = [ + +- { modelId: "gemini-test-low", name: "Gemini Test Low" }, + +- { modelId: "gemini-test-high", name: "Gemini Test High" }, + +-] satisfies ReadonlyArray; + +- + +-const availableModes: ReadonlyArray = antigravityProfile + +- ? [ + +- { id: "default", name: "Default" }, + +- { id: "auto_edit", name: "Auto edit" }, + +- { id: "yolo", name: "YOLO" }, + +- ] + +- : [ + +- { + +- id: "ask", + +- name: "Ask", + +- description: "Request permission before making any changes", + +- }, + +- { + +- id: "architect", + +- name: "Architect", + +- description: "Design and plan software systems without implementation", + +- }, + +- { + +- id: "code", + +- name: "Code", + +- description: "Write and modify code with full tool access", + +- }, + +- ]; + ++const availableModes: ReadonlyArray = [ + ++ { + ++ id: "ask", + ++ name: "Ask", + ++ description: "Request permission before making any changes", + ++ }, + ++ { + ++ id: "architect", + ++ name: "Architect", + ++ description: "Design and plan software systems without implementation", + ++ }, + ++ { + ++ id: "code", + ++ name: "Code", + ++ description: "Write and modify code with full tool access", + ++ }, + ++]; + + + + function modeState(): AcpSchema.SessionModeState { + + return { + +@@ apps/server/scripts/acp-mock-agent.ts: const grokAcpModels: ReadonlyArray = [ + + ]; + + + + function modelState(): AcpSchema.SessionModelState { + +- if (antigravityProfile) { + +- return { currentModelId, availableModels: antigravityModels }; + +- } + + const modelId = grokAcpModels.some((model) => model.modelId === currentModelId) + + ? currentModelId + + : "grok-4.6"; + +@@ apps/server/scripts/acp-mock-agent.ts: function modelState(): AcpSchema.SessionModelState { + + + + const program = Effect.gen(function* () { + + const agent = yield* EffectAcpAgent.AcpAgent; + +- const resumeRelease = yield* Deferred.make(); + +- const nativeCancelRequested = yield* Deferred.make(); + +- const nativeCancelRelease = yield* Deferred.make(); + +- const publishAntigravityCommands = (targetSessionId: string) => + +- agent.client.sessionUpdate({ + +- sessionId: targetSessionId, + +- update: { + +- sessionUpdate: "available_commands_update", + +- availableCommands: [ + +- { name: "plan", description: "Plan a task", input: { hint: "task" } }, + +- { name: "logout", description: "Sign out" }, + +- ], + +- }, + +- }); + + + + yield* agent.handleInitialize((request) => + +- Effect.gen(function* () { + +- if (floodStderr) { + +- yield* Effect.promise( + +- () => + +- new Promise((resolve) => { + +- process.stderr.write("stderr".repeat(350_000), () => resolve()); + +- }), + +- ); + +- } + ++ Effect.sync(() => { + + parameterizedModelPicker = + + request.clientCapabilities?._meta?.parameterizedModelPicker === true; + +- if (antigravityProfile) { + +- return { + +- protocolVersion: 1, + +- agentInfo: { name: "antigravity-acp", version: "mock" }, + +- agentCapabilities: { + +- loadSession: true, + +- sessionCapabilities: { resume: {} }, + +- auth: { logout: {} }, + +- promptCapabilities: { image: true, embeddedContext: true }, + +- }, + +- authMethods: [{ id: "oauth-personal", name: "Sign in with Google" }], + +- }; + +- } + + return { + + protocolVersion: 1, + +- agentCapabilities: { loadSession: true, sessionCapabilities: { resume: {} } }, + ++ agentCapabilities: { loadSession: true }, + + // Grok advertises model state before any session exists; the provider + + // health check reads it from here without authenticating. + + _meta: { modelState: modelState() }, + +@@ apps/server/scripts/acp-mock-agent.ts: const program = Effect.gen(function* () { + + }), + + ); + + + +- // Mirrors the real agent: the API key method reads GEMINI_API_KEY from the + +- // process environment and rejects when it is missing. + +- yield* agent.handleAuthenticate((request) => + +- !antigravityProfile || request.methodId === "oauth-personal" + +- ? Effect.succeed({}) + +- : request.methodId === "gemini-api-key" && process.env.GEMINI_API_KEY + +- ? Effect.succeed({}) + +- : Effect.fail( + +- AcpError.AcpRequestError.invalidParams( + +- `Mock Antigravity rejected auth method ${request.methodId}.`, + +- ), + +- ), + +- ); + +- if (antigravityProfile) { + +- yield* agent.handleLogout(() => Effect.succeed({})); + +- } + ++ yield* agent.handleAuthenticate(() => Effect.succeed({})); + + + + yield* agent.handleCreateSession(() => + +- Effect.gen(function* () { + +- if (antigravityProfile) { + +- yield* publishAntigravityCommands(sessionId); + +- } + +- return { + +- sessionId, + +- modes: modeState(), + +- models: modelState(), + +- configOptions: configOptions(), + +- }; + +- }), + +- ); + +- + +- yield* agent.handleResumeSession((request) => + +- Effect.gen(function* () { + +- yield* agent.client.sessionUpdate({ + +- sessionId: request.sessionId, + +- update: { + +- sessionUpdate: "user_message_chunk", + +- content: { type: "text", text: "native-resume-started" }, + +- }, + +- }); + +- if (waitForResumeRelease) { + +- yield* Deferred.await(resumeRelease); + +- } + +- if (antigravityProfile) { + +- yield* publishAntigravityCommands(request.sessionId); + +- } + +- return { + +- modes: modeState(), + +- models: modelState(), + +- configOptions: configOptions(), + +- _meta: { nativeResume: true }, + +- }; + ++ Effect.succeed({ + ++ sessionId, + ++ modes: modeState(), + ++ models: modelState(), + ++ configOptions: configOptions(), + + }), + + ); + + + +@@ apps/server/scripts/acp-mock-agent.ts: const program = Effect.gen(function* () { + + + + yield* agent.handleSetSessionModel((request) => + + Effect.gen(function* () { + +- if (!modelState().availableModels.some((model) => model.modelId === request.modelId)) { + ++ if (!grokAcpModels.some((model) => model.modelId === request.modelId)) { + + return yield* AcpError.AcpRequestError.invalidParams( + + `Unknown mock model id: ${request.modelId}`, + + { + @@ apps/server/scripts/acp-mock-agent.ts: const program = Effect.gen(function* () { + ); + + @@ apps/server/scripts/acp-mock-agent.ts: const program = Effect.gen(function* () { + - Effect.gen(function* () { + - const cancelledSessionId = String(sessionId ?? "mock-session-1"); + - cancelledSessions.add(cancelledSessionId); + +- if (completeFirstPromptOnCancel) { + +- yield* Deferred.succeed(nativeCancelRequested, undefined); + +- yield* agent.client.sessionUpdate({ + +- sessionId: cancelledSessionId, + +- update: { + +- sessionUpdate: "agent_thought_chunk", + +- content: { type: "text", text: "native-cancel-received" }, + +- }, + +- }); + +- } + - if (emitLateUpdateAfterCancel) { + - yield* Effect.sleep("50 millis"); + - yield* Effect.sync(() => { + @@ apps/server/scripts/acp-mock-agent.ts: const program = Effect.gen(function* () { + }), + ); + + - + - ## apps/server/src/git/GitManager.test.ts ## + -@@ apps/server/src/git/GitManager.test.ts: const GitManagerTestLayer = GitVcsDriver.layer.pipe( + - ); + - + - it.layer(GitManagerTestLayer)("GitManager", (it) => { + -- it.effect("status includes PR metadata when branch already has an open PR", () => + -+ const LONG_EFFECT_TEST_TIMEOUT_MS = 30_000; + -+ const effect = ( + -+ name: string, + -+ test: Parameters[1], + -+ timeout = LONG_EFFECT_TEST_TIMEOUT_MS, + -+ ) => it.effect(name, test, timeout); + -+ + -+ effect("status includes PR metadata when branch already has an open PR", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - baseRef: "main", + - headRef: "feature/status-open-pr", + - state: "open", + -- updatedAt: null, + - }); + - }), + - ); + - + -- it.effect("status trims PR metadata returned by gh before publishing it", () => + -+ effect("status trims PR metadata returned by gh before publishing it", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - baseRef: "main", + - headRef: "feature/status-trimmed-pr", + - state: "open", + -- updatedAt: null, + - }); + - }), + - ); + - + -- it.effect("status ignores invalid gh pr list entries and keeps valid ones", () => + -+ effect("status ignores invalid gh pr list entries and keeps valid ones", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - baseRef: "main", + - headRef: "feature/status-valid-pr-entry", + - state: "open", + -- updatedAt: null, + - }); + - }), + - ); + - + -- it.effect("status preserves lowercase merged and closed PR states from gh json", () => + -+ effect("status preserves lowercase merged and closed PR states from gh json", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - baseRef: "main", + - headRef: "feature/status-lowercase-state", + - state: "merged", + -- updatedAt: "2026-01-02T00:00:00.000Z", + - }); + - }), + - ); + - + -- it.effect("status returns an explicit non-repo result for non-git directories", () => + -+ effect("status returns an explicit non-repo result for non-git directories", () => + - Effect.gen(function* () { + - const cwd = yield* makeTempDir("t3code-git-manager-non-repo-"); + - const { manager } = yield* makeManager(); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("status returns an explicit non-repo result for deleted directories", () => + -+ effect("status returns an explicit non-repo result for deleted directories", () => + - Effect.gen(function* () { + - const rootDir = yield* makeTempDir("t3code-git-manager-missing-dir-"); + - const cwd = NodePath.join(rootDir, "deleted-repo"); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("status briefly caches repeated lookups for the same cwd", () => + -+ effect("status briefly caches repeated lookups for the same cwd", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - expect(ghCalls.filter((call) => call.startsWith("pr list ")).length).toBeGreaterThan(0); + - }), + - ); + -- + - it.effect("status still looks up PRs for a branch pushed without --set-upstream", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }); + - + - it.effect( + -+ effect( + - "status ignores unrelated fork PRs when the current branch tracks the same repository", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect( + -+ effect( + - "status detects cross-repo PRs from the upstream remote URL owner", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - baseRef: "main", + - headRef: "statemachine", + - state: "open", + -- updatedAt: "2026-03-10T07:00:00.000Z", + - }); + - expect(ghCalls).toContain( + - "pr list --head jasonLaster:statemachine --state all --limit 20 --json number,title,url,baseRefName,headRefName,state,mergedAt,updatedAt,isCrossRepository,headRepository,headRepositoryOwner", + - ); + - }), + -- 20_000, + -+ LONG_EFFECT_TEST_TIMEOUT_MS, + - ); + - + -- it.effect( + -- "status preserves a fork PR whose head is named after the default branch", + -- () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- const originDir = yield* createBareRemote(); + -- const forkDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "origin", originDir]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "main"]); + -- yield* runGit(repoDir, ["remote", "set-head", "origin", "main"]); + -- yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); + -- yield* runGit(repoDir, ["push", "fork-seed", "main"]); + -- yield* runGit(repoDir, ["checkout", "-b", "t3code/pr-777/main"]); + -- yield* runGit(repoDir, ["branch", "--set-upstream-to", "fork-seed/main"]); + -- yield* configureVisibleRemoteUrlWithLocalRewrite( + -- repoDir, + -- "fork-seed", + -- "git@github.com:contributor/codething-mvp.git", + -- forkDir, + -- ); + -- + -- const { manager, ghCalls } = yield* makeManager({ + -- ghScenario: { + -- prListByHeadSelector: { + -- // @effect-diagnostics-next-line preferSchemaOverJson:off + -- "contributor:main": JSON.stringify([ + -- { + -- number: 777, + -- title: "Fork PR from main", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/777", + -- baseRefName: "main", + -- headRefName: "main", + -- state: "OPEN", + -- updatedAt: "2026-03-10T07:00:00Z", + -- isCrossRepository: true, + -- headRepository: { + -- nameWithOwner: "contributor/codething-mvp", + -- }, + -- headRepositoryOwner: { + -- login: "contributor", + -- }, + -- }, + -- ]), + -- }, + +@@ apps/server/scripts/acp-mock-agent.ts: const program = Effect.gen(function* () { + + const requestedSessionId = String(request.sessionId ?? sessionId); + + promptCount += 1; + + + +- if (completeFirstPromptOnCancel && promptCount === 1) { + +- yield* agent.client.sessionUpdate({ + +- sessionId: requestedSessionId, + +- update: { + +- sessionUpdate: "tool_call", + +- toolCallId: "native-cancel-tool", + +- title: "Long command", + +- kind: "execute", + +- status: "in_progress", + - }, + - }); + -- + -- const status = yield* manager.status({ cwd: repoDir }); + -- expect(status.refName).toBe("t3code/pr-777/main"); + -- expect(status.pr).toEqual({ + -- number: 777, + -- title: "Fork PR from main", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/777", + -- baseRef: "main", + -- headRef: "main", + -- state: "open", + -- updatedAt: "2026-03-10T07:00:00.000Z", + +- yield* Deferred.await(nativeCancelRequested); + +- yield* Deferred.await(nativeCancelRelease); + +- yield* agent.client.sessionUpdate({ + +- sessionId: requestedSessionId, + +- update: { + +- sessionUpdate: "tool_call_update", + +- toolCallId: "native-cancel-tool", + +- status: "failed", + +- content: [{ type: "content", content: { type: "text", text: "Cancelled." } }], + +- }, + - }); + -- expect(ghCalls).toContain( + -- "pr list --head contributor:main --state all --limit 20 --json number,title,url,baseRefName,headRefName,state,mergedAt,updatedAt,isCrossRepository,headRepository,headRepositoryOwner", + -- ); + -- }), + -- 20_000, + -- ); + +- yield* agent.client.sessionUpdate({ + +- sessionId: requestedSessionId, + +- update: { + +- sessionUpdate: "agent_message_chunk", + +- content: { type: "text", text: "Request cancelled." }, + +- }, + +- }); + +- return { stopReason: "cancelled", _meta: { nativeCancel: true } }; + +- } + - + -- it.effect( + -+ effect( + - "status ignores synthetic local branch aliases when the upstream remote name contains slashes", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - baseRef: "main", + - headRef: "effect-atom", + - state: "open", + -- updatedAt: "2026-03-01T10:00:00.000Z", + - }); + - expect(ghCalls.some((call) => call.includes("pr list --head upstream/effect-atom "))).toBe( + - false, + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - ), + - ).toBe(false); + - }), + -- 20_000, + -+ LONG_EFFECT_TEST_TIMEOUT_MS, + - ); + - + -- it.effect("status returns merged PR state when latest PR was merged", () => + -+ effect("status returns merged PR state when latest PR was merged", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - baseRef: "main", + - headRef: "feature/status-merged-pr", + - state: "merged", + -- updatedAt: "2026-01-30T10:00:00.000Z", + - }); + - }), + + if (Number.isFinite(promptDelayMs) && promptDelayMs > 0) { + + yield* Effect.sleep(`${promptDelayMs} millis`); + + } + +@@ apps/server/scripts/acp-mock-agent.ts: const program = Effect.gen(function* () { + ); + + -- it.effect("status hides merged PRs on the default branch", () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- + -- const { manager } = yield* makeManager({ + -- ghScenario: { + -- prListSequence: [ + -- // @effect-diagnostics-next-line preferSchemaOverJson:off + -- JSON.stringify([ + -- { + -- number: 23, + -- title: "Merged PR", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/23", + -- baseRefName: "feature/status-default-branch-target", + -- headRefName: "main", + -- state: "MERGED", + -- mergedAt: "2026-01-30T10:00:00Z", + -- updatedAt: "2026-01-30T10:00:00Z", + -- }, + -- ]), + -- ], + -- }, + + yield* agent.handleUnknownExtRequest((method, params) => { + +- if (method === "_test/environment") { + +- return Effect.succeed({ + +- inherited: process.env.T3_ACP_RUNTIME_AMBIENT === "sentinel", + +- explicit: process.env.T3_ACP_RUNTIME_EXPLICIT === "kept", + - }); + -- + -- const status = yield* manager.status({ cwd: repoDir }); + -- expect(status.refName).toBe("main"); + -- expect(status.pr).toBeNull(); + -- }), + -- ); + -- + -- it.effect("status does not inherit a merged PR from a feature branch's default upstream", () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- const remoteDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "main"]); + -- yield* runGit(repoDir, ["remote", "set-head", "origin", "main"]); + -- yield* runGit(repoDir, ["checkout", "-b", "feature/from-main", "origin/main"]); + -- + -- const { manager, ghCalls } = yield* makeManager({ + -- ghScenario: { + -- prListSequence: [ + -- // @effect-diagnostics-next-line preferSchemaOverJson:off + -- JSON.stringify([ + -- { + -- number: 54, + -- title: "Reverse merge from main", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/54", + -- baseRefName: "je-filter-list", + -- headRefName: "main", + -- state: "MERGED", + -- mergedAt: "2023-09-28T03:21:10Z", + -- updatedAt: "2023-09-28T03:21:10Z", + -- }, + -- ]), + -- ], + -- }, + +- } + +- if (method === "_test/release-resume") { + +- return Deferred.succeed(resumeRelease, undefined).pipe(Effect.as({})); + +- } + +- if (method === "_test/finish-cancel") { + +- return Deferred.succeed(nativeCancelRelease, undefined).pipe(Effect.as({})); + +- } + +- if (method === "_test/startup-metadata") { + +- return Effect.gen(function* () { + +- for (const [metadataSessionId, commandName, modeId] of [ + +- [sessionId, "plan", "code"], + +- ["child-session", "foreign-command", "ask"], + +- ] as const) { + +- yield* agent.client.sessionUpdate({ + +- sessionId: metadataSessionId, + +- update: { + +- sessionUpdate: "available_commands_update", + +- availableCommands: [{ name: commandName, description: "Native command" }], + +- }, + +- }); + +- yield* agent.client.sessionUpdate({ + +- sessionId: metadataSessionId, + +- update: { sessionUpdate: "current_mode_update", currentModeId: modeId }, + +- }); + +- yield* agent.client.sessionUpdate({ + +- sessionId: metadataSessionId, + +- update: { + +- sessionUpdate: "config_option_update", + +- configOptions: configOptions().map((option) => + +- option.type === "select" && option.category === "model" + +- ? { + +- ...option, + +- currentValue: metadataSessionId === sessionId ? "gpt-5.4" : "default", + +- } + +- : option, + +- ), + +- }, + +- }); + +- yield* agent.client.sessionUpdate({ + +- sessionId: metadataSessionId, + +- update: { + +- sessionUpdate: "agent_message_chunk", + +- content: { type: "text", text: "Startup transcript must not replay." }, + +- }, + +- }); + +- } + +- return {}; + - }); + -- + -- const status = yield* manager.status({ cwd: repoDir }); + -- expect(status.refName).toBe("feature/from-main"); + -- expect(status.pr).toBeNull(); + -- expect(ghCalls.some((call) => call.includes("pr list"))).toBe(false); + -- }), + -- ); + -- + -- it.effect("status prefers open PR when merged PR has newer updatedAt", () => + -+ effect("status prefers open PR when merged PR has newer updatedAt", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - baseRef: "main", + - headRef: "feature/status-open-over-merged", + - state: "open", + -- updatedAt: "2026-01-30T10:00:00.000Z", + - }); + - }), + - ); + - + -- it.effect("status is resilient to gh lookup failures and returns pr null", () => + -+ effect("status is resilient to gh lookup failures and returns pr null", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("commits only selected files when filePaths is provided", () => + -+ effect("commits only selected files when filePaths is provided", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("creates feature branch, commits, and pushes with featureBranch option", () => + -+ effect("creates feature branch, commits, and pushes with featureBranch option", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("featureBranch uses custom commit message and derives branch name", () => + -+ effect("featureBranch uses custom commit message and derives branch name", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("skips commit when there are no uncommitted changes", () => + -+ effect("skips commit when there are no uncommitted changes", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("featureBranch returns error when worktree is clean", () => + -+ effect("featureBranch returns error when worktree is clean", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("commits and pushes with upstream auto-setup when needed", () => + -+ effect("commits and pushes with upstream auto-setup when needed", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect( + -+ effect( + - "pushes and creates PR from a no-upstream branch when local commits are ahead of base", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("skips push when branch is already up to date", () => + -+ effect("skips push when branch is already up to date", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("pushes existing clean commits without rerunning commit logic", () => + -+ effect("pushes existing clean commits without rerunning commit logic", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + +- } + + if (method === "cursor/list_available_models") { + + return Effect.succeed({ + + models: availableModels(), + +@@ apps/server/scripts/acp-mock-agent.ts: const program = Effect.gen(function* () { + + return Effect.succeed({}); + + }); + + -- it.effect("pushes existing commits without committing dirty worktree changes", () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- yield* runGit(repoDir, ["checkout", "-b", "feature/push-dirty"]); + -- const remoteDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); + -- NodeFS.writeFileSync(NodePath.join(repoDir, "push-dirty.txt"), "push dirty\n"); + -- yield* runGit(repoDir, ["add", "push-dirty.txt"]); + -- yield* runGit(repoDir, ["commit", "-m", "Push dirty branch"]); + -- NodeFS.mkdirSync(NodePath.join(repoDir, ".vercel")); + -- NodeFS.writeFileSync(NodePath.join(repoDir, ".vercel", "project.json"), "{}\n"); + -- + -- const { manager } = yield* makeManager(); + -- const result = yield* runStackedAction(manager, { + -- cwd: repoDir, + -- action: "push", + -- }); + +- yield* agent.handleUnknownExtNotification((method) => + +- method === "_test/exit" ? Effect.sync(() => process.exit(19)) : Effect.void, + +- ); + - + -- expect(result.commit.status).toBe("skipped_not_requested"); + -- expect(result.push.status).toBe("pushed"); + -- expect(result.pr.status).toBe("skipped_not_requested"); + -- expect( + -- yield* runGit(repoDir, ["status", "--porcelain"]).pipe( + -- Effect.map((output) => output.stdout.trim()), + -- ), + -- ).toContain("?? .vercel/"); + -- expect( + -- yield* runGit(remoteDir, ["log", "-1", "--pretty=%s", "feature/push-dirty"]).pipe( + -- Effect.map((output) => output.stdout.trim()), + -- ), + -- ).toBe("Push dirty branch"); + -- }), + -- ); + -- + -- it.effect("create_pr pushes a clean branch before creating the PR when needed", () => + -+ effect("create_pr pushes a clean branch before creating the PR when needed", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("create_pr falls back to main when source control provider detection fails", () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- yield* runGit(repoDir, ["checkout", "-b", "feature/provider-fallback"]); + -- NodeFS.writeFileSync(NodePath.join(repoDir, "provider-fallback.txt"), "fallback\n"); + -- yield* runGit(repoDir, ["add", "provider-fallback.txt"]); + -- yield* runGit(repoDir, ["commit", "-m", "Provider fallback"]); + -- const remoteDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); + -- + -- const { manager, ghCalls } = yield* makeManager({ + -- ghScenario: { + -- prListSequence: [ + -- "[]", + -- // @effect-diagnostics-next-line preferSchemaOverJson:off + -- JSON.stringify([ + -- { + -- number: 404, + -- title: "Provider fallback", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/404", + -- baseRefName: "main", + -- headRefName: "feature/provider-fallback", + -- }, + -- ]), + -- ], + -- }, + -- }); + -- + -- const result = yield* runStackedAction(manager, { + -- cwd: repoDir, + -- action: "create_pr", + -- }); + -- + -- expect(result.pr.status).toBe("created"); + -- expect(result.pr.number).toBe(404); + -- expect( + -- ghCalls.some((call) => + -- call.includes("pr create --base main --head feature/provider-fallback"), + -- ), + -- ).toBe(true); + -- }), + -- ); + -- + -- it.effect("create_pr targets the remote default branch when it is not main", () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- const remoteDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); + -- // A repository whose default branch is master, with no main anywhere. + -- yield* runGit(repoDir, ["push", "origin", "HEAD:master"]); + -- yield* runGit(repoDir, ["fetch", "origin"]); + -- yield* runGit(repoDir, ["remote", "set-head", "origin", "master"]); + -- + -- yield* runGit(repoDir, ["checkout", "-b", "feature/master-default"]); + -- NodeFS.writeFileSync(NodePath.join(repoDir, "master-default.txt"), "master default\n"); + -- yield* runGit(repoDir, ["add", "master-default.txt"]); + -- yield* runGit(repoDir, ["commit", "-m", "Master default"]); + -- + -- const { manager, ghCalls } = yield* makeManager({ + -- ghScenario: { + -- // Mirrors a provider that cannot report a default branch, as the Azure + -- // DevOps CLI does when it cannot detect the repository. + -- defaultBranch: "", + -- prListSequence: [ + -- "[]", + -- // @effect-diagnostics-next-line preferSchemaOverJson:off + -- JSON.stringify([ + -- { + -- number: 505, + -- title: "Master default", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/505", + -- baseRefName: "master", + -- headRefName: "feature/master-default", + -- }, + -- ]), + -- ], + -- }, + -- }); + -- + -- const result = yield* runStackedAction(manager, { + -- cwd: repoDir, + -- action: "create_pr", + -- }); + -- + -- expect(result.pr.status).toBe("created"); + -- expect( + -- ghCalls.some((call) => + -- call.includes("pr create --base master --head feature/master-default"), + -- ), + -- ).toBe(true); + -- }), + -- ); + -- + -- it.effect("returns existing PR metadata for commit/push/pr action", () => + -+ effect("returns existing PR metadata for commit/push/pr action", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect( + -+ effect( + - "returns existing cross-repo PR metadata using the fork owner selector", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - ).toBe(true); + - expect(ghCalls.some((call) => call.startsWith("pr create "))).toBe(false); + - }), + -- 12_000, + -+ LONG_EFFECT_TEST_TIMEOUT_MS, + - ); + - + -- it.effect( + -+ effect( + - "returns the correct existing PR when a slash remote checks out to a synthetic local alias", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - false, + - ); + - }), + -- 20_000, + -+ LONG_EFFECT_TEST_TIMEOUT_MS, + - ); + - + -- it.effect( + -+ effect( + - "prefers owner-qualified selectors before bare branch names for cross-repo PRs", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - expect(ownerSelectorCallIndex).toBeGreaterThanOrEqual(0); + - expect(ghCalls.some((call) => call.startsWith("pr create "))).toBe(false); + - }), + -- 12_000, + -+ LONG_EFFECT_TEST_TIMEOUT_MS, + - ); + - + -- it.effect( + -+ effect( + - "stops probing head selectors after finding an existing PR", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - "pr list --head octocat:statemachine --state open --limit 1", + - ); + - }), + -- 12_000, + -- ); + -- + -- it.effect( + -- "does not reuse a cross-repo PR when GitHub omits head identity metadata", + -- () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- yield* runGit(repoDir, ["checkout", "-b", "statemachine"]); + -- const forkDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); + -- yield* runGit(repoDir, ["push", "-u", "fork-seed", "statemachine"]); + -- yield* runGit(repoDir, [ + -- "config", + -- "remote.fork-seed.url", + -- "git@github.com:octocat/codething-mvp.git", + -- ]); + -- + -- const { manager, ghCalls } = yield* makeManager({ + -- ghScenario: { + -- prListSequenceByHeadSelector: { + -- "octocat:statemachine": [ + -- `[{"number":41,"title":"Ambiguous fork PR","url":"https://github.com/pingdotgg/codething-mvp/pull/41","baseRefName":"main","headRefName":"statemachine","state":"OPEN"}]`, + -- `[{"number":142,"title":"Add stacked git actions","url":"https://github.com/pingdotgg/codething-mvp/pull/142","baseRefName":"main","headRefName":"statemachine","state":"OPEN","isCrossRepository":true,"headRepository":{"nameWithOwner":"octocat/codething-mvp"},"headRepositoryOwner":{"login":"octocat"}}]`, + -- ], + -- "fork-seed:statemachine": ["[]"], + -- statemachine: ["[]"], + -- }, + -- }, + -- }); + -- + -- const result = yield* runStackedAction(manager, { + -- cwd: repoDir, + -- action: "commit_push_pr", + -- }); + -- + -- expect(result.pr.status).toBe("created"); + -- expect(result.pr.number).toBe(142); + -- expect(ghCalls.some((call) => call.startsWith("pr create "))).toBe(true); + -- }), + -- 20_000, + -+ LONG_EFFECT_TEST_TIMEOUT_MS, + - ); + - + -- it.effect("rejects same-repo PR metadata when matching a cross-repo head context", () => + -- Effect.sync(() => { + -- const headContext = { + -- headBranch: "statemachine", + -- headRepositoryNameWithOwner: "pingdotgg/codething-mvp", + -- headRepositoryOwnerLogin: "pingdotgg", + -- isCrossRepository: true, + -- }; + -- + -- expect( + -- GitManager.matchesBranchHeadContext( + -- { + -- number: 41, + -- title: "Same-repo PR", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/41", + -- baseRefName: "main", + -- headRefName: "statemachine", + -- state: "open", + -- updatedAt: Option.none(), + -- isCrossRepository: false, + -- headRepositoryNameWithOwner: "pingdotgg/codething-mvp", + -- headRepositoryOwnerLogin: "pingdotgg", + -- }, + -- headContext, + -- ), + -- ).toBe(false); + -- + -- expect( + -- GitManager.matchesBranchHeadContext( + -- { + -- number: 142, + -- title: "Fork PR", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/142", + -- baseRefName: "main", + -- headRefName: "statemachine", + -- state: "open", + -- updatedAt: Option.none(), + -- isCrossRepository: true, + -- headRepositoryNameWithOwner: "pingdotgg/codething-mvp", + -- headRepositoryOwnerLogin: "pingdotgg", + -- }, + -- headContext, + -- ), + -- ).toBe(true); + -- }), + -- ); + -- + -- it.effect("accepts fork PR metadata when origin is the fork checkout remote", () => + -- Effect.sync(() => { + -- const headContext = { + -- headBranch: "t3code/git-audit-stability", + -- headRepositoryNameWithOwner: "justsomelegs/t3code", + -- headRepositoryOwnerLogin: "justsomelegs", + -- isCrossRepository: false, + -- }; + -- + -- expect( + -- GitManager.matchesBranchHeadContext( + -- { + -- number: 2284, + -- title: "Improve branch mismatch warnings", + -- url: "https://github.com/pingdotgg/t3code/pull/2284", + -- baseRefName: "main", + -- headRefName: "t3code/git-audit-stability", + -- state: "open", + -- updatedAt: Option.none(), + -- isCrossRepository: true, + -- headRepositoryNameWithOwner: "justsomelegs/t3code", + -- headRepositoryOwnerLogin: "justsomelegs", + -- }, + -- headContext, + -- ), + -- ).toBe(true); + -- }), + -- ); + -- + -- it.effect("creates PR when one does not already exist", () => + -+ effect("creates PR when one does not already exist", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("generates PR content against the remote base when the local base is stale", () => + -+ effect("creates a new PR instead of reusing an unrelated fork PR with the same head branch", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -+ yield* runGit(repoDir, ["checkout", "-b", "feature/no-fork-match"]); + - const remoteDir = yield* createBareRemote(); + - yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "main"]); + -- yield* runGit(remoteDir, ["symbolic-ref", "HEAD", "refs/heads/main"]); + -- + -- const peerDir = yield* makeTempDir("t3code-git-peer-"); + -- yield* runGit(peerDir, ["clone", remoteDir, "."]); + -- yield* runGit(peerDir, ["config", "user.email", "peer@example.com"]); + -- yield* runGit(peerDir, ["config", "user.name", "Peer User"]); + -- NodeFS.writeFileSync(NodePath.join(peerDir, "remote.txt"), "remote\n"); + -- yield* runGit(peerDir, ["add", "remote.txt"]); + -- yield* runGit(peerDir, ["commit", "-m", "Remote base commit"]); + -- yield* runGit(peerDir, ["push", "origin", "main"]); + -- + -- yield* runGit(repoDir, ["fetch", "origin"]); + -- yield* runGit(repoDir, [ + -- "checkout", + -- "--no-track", + -- "-b", + -- "feature/remote-base", + -- "origin/main", + -- ]); + -- NodeFS.writeFileSync(NodePath.join(repoDir, "feature.txt"), "feature\n"); + -- yield* runGit(repoDir, ["add", "feature.txt"]); + -+ fs.writeFileSync(path.join(repoDir, "changes.txt"), "change\n"); + -+ yield* runGit(repoDir, ["add", "changes.txt"]); + - yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "feature/remote-base"]); + -- yield* runGit(repoDir, ["config", "branch.feature/remote-base.gh-merge-base", "main"]); + -+ yield* runGit(repoDir, ["push", "-u", "origin", "feature/no-fork-match"]); + - + -- let generatedCommitSummary = ""; + -- const { manager } = yield* makeManager({ + -+ const { manager, ghCalls } = yield* makeManager({ + - ghScenario: { + -- prListSequence: ["[]", "[]"], + -- }, + -- textGeneration: { + -- generatePrContent: (input) => { + -- generatedCommitSummary = input.commitSummary; + -- return Effect.succeed({ title: "Feature PR", body: "Feature body" }); + -- }, + -+ prListSequence: [ + -+ JSON.stringify([ + -+ { + -+ number: 1661, + -+ title: "Fork PR with same branch name", + -+ url: "https://github.com/pingdotgg/t3code/pull/1661", + -+ baseRefName: "main", + -+ headRefName: "feature/no-fork-match", + -+ state: "OPEN", + -+ isCrossRepository: true, + -+ headRepository: { + -+ nameWithOwner: "lnieuwenhuis/t3code", + -+ }, + -+ headRepositoryOwner: { + -+ login: "lnieuwenhuis", + -+ }, + -+ }, + -+ ]), + -+ JSON.stringify([ + -+ { + -+ number: 188, + -+ title: "Add stacked git actions", + -+ url: "https://github.com/pingdotgg/codething-mvp/pull/188", + -+ baseRefName: "main", + -+ headRefName: "feature/no-fork-match", + -+ state: "OPEN", + -+ isCrossRepository: false, + -+ }, + -+ ]), + -+ ], + - }, + - }); + -- + - const result = yield* runStackedAction(manager, { + - cwd: repoDir, + -- action: "create_pr", + -+ action: "commit_push_pr", + - }); + - + - expect(result.pr.status).toBe("created"); + -- expect(generatedCommitSummary).toContain("Feature commit"); + -- expect(generatedCommitSummary).not.toContain("Remote base commit"); + -+ expect(result.pr.number).toBe(188); + -+ expect(result.toast).toEqual({ + -+ title: "Created PR #188", + -+ description: "Add stacked git actions", + -+ cta: { + -+ kind: "open_pr", + -+ label: "View PR", + -+ url: "https://github.com/pingdotgg/codething-mvp/pull/188", + -+ }, + -+ }); + -+ expect( + -+ ghCalls.some((call) => call.includes("pr create --base main --head feature/no-fork-match")), + -+ ).toBe(true); + - }), + - ); + - + -- it.effect( + -- "creates a new PR instead of reusing an unrelated fork PR with the same head branch", + -- () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- yield* runGit(repoDir, ["checkout", "-b", "feature/no-fork-match"]); + -- const remoteDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); + -- NodeFS.writeFileSync(NodePath.join(repoDir, "changes.txt"), "change\n"); + -- yield* runGit(repoDir, ["add", "changes.txt"]); + -- yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "feature/no-fork-match"]); + -- + -- const { manager, ghCalls } = yield* makeManager({ + -- ghScenario: { + -- prListSequence: [ + -- // @effect-diagnostics-next-line preferSchemaOverJson:off + -- JSON.stringify([ + -- { + -- number: 1661, + -- title: "Fork PR with same branch name", + -- url: "https://github.com/pingdotgg/t3code/pull/1661", + -- baseRefName: "main", + -- headRefName: "feature/no-fork-match", + -- state: "OPEN", + -- isCrossRepository: true, + -- headRepository: { + -- nameWithOwner: "lnieuwenhuis/t3code", + -- }, + -- headRepositoryOwner: { + -- login: "lnieuwenhuis", + -- }, + -- }, + -- ]), + -- // @effect-diagnostics-next-line preferSchemaOverJson:off + -- JSON.stringify([ + -- { + -- number: 188, + -- title: "Add stacked git actions", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/188", + -- baseRefName: "main", + -- headRefName: "feature/no-fork-match", + -- state: "OPEN", + -- isCrossRepository: false, + -- }, + -- ]), + -- ], + -- }, + -- }); + -- const result = yield* runStackedAction(manager, { + -- cwd: repoDir, + -- action: "commit_push_pr", + -- }); + -- + -- expect(result.pr.status).toBe("created"); + -- expect(result.pr.number).toBe(188); + -- expect(result.toast).toEqual({ + -- title: "Created PR #188", + -- description: "Add stacked git actions", + -- cta: { + -- kind: "open_pr", + -- label: "View PR", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/188", + -- }, + -- }); + -- expect( + -- ghCalls.some((call) => + -- call.includes("pr create --base main --head feature/no-fork-match"), + -- ), + -- ).toBe(true); + -- }), + -- ); + -- + -- it.effect("creates cross-repo PRs with the fork owner selector and default base branch", () => + -+ effect("creates cross-repo PRs with the fork owner selector and default base branch", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("rejects push/pr actions from detached HEAD", () => + -+ effect("rejects push/pr actions from detached HEAD", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("surfaces missing gh binary errors", () => + -+ effect("surfaces missing gh binary errors", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("surfaces gh auth errors with guidance", () => + -+ effect("surfaces gh auth errors with guidance", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("resolves pull requests from #number references", () => + -+ effect("resolves pull requests from #number references", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("prepares pull request threads in local mode by checking out the PR branch", () => + -+ effect("prepares pull request threads in local mode by checking out the PR branch", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect( + -- "restores same-repository upstream tracking after local PR checkout without a remote ref", + -- () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- const remoteDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "main"]); + -- yield* runGit(repoDir, ["checkout", "-b", "feature/pr-local-upstream"]); + -- NodeFS.writeFileSync(NodePath.join(repoDir, "upstream.txt"), "upstream\n"); + -- yield* runGit(repoDir, ["add", "upstream.txt"]); + -- yield* runGit(repoDir, ["commit", "-m", "Local upstream PR branch"]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-local-upstream"]); + -- yield* runGit(repoDir, ["checkout", "main"]); + -- yield* runGit(repoDir, ["branch", "-D", "feature/pr-local-upstream"]); + -- yield* runGit(repoDir, [ + -- "update-ref", + -- "-d", + -- "refs/remotes/origin/feature/pr-local-upstream", + -- ]); + -- + -- const { manager } = yield* makeManager({ + -- ghScenario: { + -- pullRequest: { + -- number: 65, + -- title: "Local upstream PR", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/65", + -- baseRefName: "main", + -- headRefName: "feature/pr-local-upstream", + -- state: "open", + -- isCrossRepository: false, + -- headRepositoryNameWithOwner: "pingdotgg/codething-mvp", + -- headRepositoryOwnerLogin: "pingdotgg", + -- }, + -- repositoryCloneUrls: { + -- "pingdotgg/codething-mvp": { + -- url: remoteDir, + -- sshUrl: remoteDir, + -- }, + -- }, + -- }, + -- }); + -- + -- const result = yield* preparePullRequestThread(manager, { + -- cwd: repoDir, + -- reference: "65", + -- mode: "local", + -- }); + -- + -- expect(result.worktreePath).toBeNull(); + -- expect(result.branch).toBe("feature/pr-local-upstream"); + -- expect( + -- (yield* runGit(repoDir, ["rev-parse", "--abbrev-ref", "@{upstream}"])).stdout.trim(), + -- ).toBe("origin/feature/pr-local-upstream"); + -- }), + -- ); + -- + -- it.effect( + -- "restores same-repository upstream tracking when provider omits head repository metadata", + -- () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- const remoteDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "main"]); + -- yield* runGit(repoDir, ["checkout", "-b", "feature/pr-local-no-head-repo"]); + -- NodeFS.writeFileSync(NodePath.join(repoDir, "no-head-repo.txt"), "upstream\n"); + -- yield* runGit(repoDir, ["add", "no-head-repo.txt"]); + -- yield* runGit(repoDir, ["commit", "-m", "Local PR branch without repo metadata"]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-local-no-head-repo"]); + -- yield* runGit(repoDir, ["checkout", "main"]); + -- yield* runGit(repoDir, ["branch", "-D", "feature/pr-local-no-head-repo"]); + -- yield* runGit(repoDir, [ + -- "update-ref", + -- "-d", + -- "refs/remotes/origin/feature/pr-local-no-head-repo", + -- ]); + -- + -- const { manager } = yield* makeManager({ + -- ghScenario: { + -- pullRequest: { + -- number: 66, + -- title: "Local upstream PR without repo metadata", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/66", + -- baseRefName: "main", + -- headRefName: "feature/pr-local-no-head-repo", + -- state: "open", + -- }, + -- }, + -- }); + -- + -- const result = yield* preparePullRequestThread(manager, { + -- cwd: repoDir, + -- reference: "66", + -- mode: "local", + -- }); + -- + -- expect(result.worktreePath).toBeNull(); + -- expect(result.branch).toBe("feature/pr-local-no-head-repo"); + -- expect( + -- (yield* runGit(repoDir, ["rev-parse", "--abbrev-ref", "@{upstream}"])).stdout.trim(), + -- ).toBe("origin/feature/pr-local-no-head-repo"); + -- }), + -- ); + -- + -- it.effect("prepares pull request threads in worktree mode on the PR head branch", () => + -+ effect("prepares pull request threads in worktree mode on the PR head branch", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("preserves fork upstream tracking when preparing a local PR thread", () => + -+ effect("preserves fork upstream tracking when preparing a local PR thread", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("derives fork repository identity from PR URL when GitHub omits nameWithOwner", () => + -+ effect("derives fork repository identity from PR URL when GitHub omits nameWithOwner", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("reuses an existing dedicated worktree for the PR head branch", () => + -+ effect("reuses an existing dedicated worktree for the PR head branch", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect( + -+ effect( + - "does not block fork PR worktree prep when the fork head branch collides with root main", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect( + -- "does not overwrite an existing local main branch when preparing a fork PR worktree", + -- () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- const originDir = yield* createBareRemote(); + -- const forkDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "origin", originDir]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "main"]); + -- yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); + -- yield* runGit(repoDir, ["checkout", "-b", "fork-main-source"]); + -- NodeFS.writeFileSync(NodePath.join(repoDir, "fork-main-second.txt"), "fork main second\n"); + -- yield* runGit(repoDir, ["add", "fork-main-second.txt"]); + -- yield* runGit(repoDir, ["commit", "-m", "Fork main second branch"]); + -- yield* runGit(repoDir, ["push", "-u", "fork-seed", "fork-main-source:main"]); + -- yield* runGit(repoDir, ["checkout", "main"]); + -- const localMainBefore = (yield* runGit(repoDir, ["rev-parse", "main"])).stdout.trim(); + -- yield* runGit(repoDir, ["checkout", "-b", "feature/root-branch"]); + -+ effect("does not overwrite an existing local main branch when preparing a fork PR worktree", () => + -+ Effect.gen(function* () { + -+ const repoDir = yield* makeTempDir("t3code-git-manager-"); + -+ yield* initRepo(repoDir); + -+ const originDir = yield* createBareRemote(); + -+ const forkDir = yield* createBareRemote(); + -+ yield* runGit(repoDir, ["remote", "add", "origin", originDir]); + -+ yield* runGit(repoDir, ["push", "-u", "origin", "main"]); + -+ yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); + -+ yield* runGit(repoDir, ["checkout", "-b", "fork-main-source"]); + -+ fs.writeFileSync(path.join(repoDir, "fork-main-second.txt"), "fork main second\n"); + -+ yield* runGit(repoDir, ["add", "fork-main-second.txt"]); + -+ yield* runGit(repoDir, ["commit", "-m", "Fork main second branch"]); + -+ yield* runGit(repoDir, ["push", "-u", "fork-seed", "fork-main-source:main"]); + -+ yield* runGit(repoDir, ["checkout", "main"]); + -+ const localMainBefore = (yield* runGit(repoDir, ["rev-parse", "main"])).stdout.trim(); + -+ yield* runGit(repoDir, ["checkout", "-b", "feature/root-branch"]); + - + -- const { manager } = yield* makeManager({ + -- ghScenario: { + -- pullRequest: { + -- number: 92, + -- title: "Fork main overwrite PR", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/92", + -- baseRefName: "main", + -- headRefName: "main", + -- state: "open", + -- isCrossRepository: true, + -- headRepositoryNameWithOwner: "octocat/codething-mvp", + -- headRepositoryOwnerLogin: "octocat", + -- }, + -- repositoryCloneUrls: { + -- "octocat/codething-mvp": { + -- url: forkDir, + -- sshUrl: forkDir, + -- }, + -+ const { manager } = yield* makeManager({ + -+ ghScenario: { + -+ pullRequest: { + -+ number: 92, + -+ title: "Fork main overwrite PR", + -+ url: "https://github.com/pingdotgg/codething-mvp/pull/92", + -+ baseRefName: "main", + -+ headRefName: "main", + -+ state: "open", + -+ isCrossRepository: true, + -+ headRepositoryNameWithOwner: "octocat/codething-mvp", + -+ headRepositoryOwnerLogin: "octocat", + -+ }, + -+ repositoryCloneUrls: { + -+ "octocat/codething-mvp": { + -+ url: forkDir, + -+ sshUrl: forkDir, + - }, + - }, + -- }); + -+ }, + -+ }); + - + -- const result = yield* preparePullRequestThread(manager, { + -- cwd: repoDir, + -- reference: "92", + -- mode: "worktree", + -- }); + -+ const result = yield* preparePullRequestThread(manager, { + -+ cwd: repoDir, + -+ reference: "92", + -+ mode: "worktree", + -+ }); + - + -- expect(result.branch).toBe("t3code/pr-92/main"); + -- expect((yield* runGit(repoDir, ["rev-parse", "main"])).stdout.trim()).toBe(localMainBefore); + -- expect( + -- (yield* runGit(result.worktreePath as string, [ + -- "rev-parse", + -- "--abbrev-ref", + -- "@{upstream}", + -- ])).stdout.trim(), + -- ).toBe("fork-seed/main"); + -- }), + -+ expect(result.branch).toBe("t3code/pr-92/main"); + -+ expect((yield* runGit(repoDir, ["rev-parse", "main"])).stdout.trim()).toBe(localMainBefore); + -+ expect( + -+ (yield* runGit(result.worktreePath as string, [ + -+ "rev-parse", + -+ "--abbrev-ref", + -+ "@{upstream}", + -+ ])).stdout.trim(), + -+ ).toBe("fork-seed/main"); + -+ }), + - ); + - + -- it.effect("reuses an existing PR worktree and restores fork upstream tracking", () => + -+ effect("reuses an existing PR worktree and restores fork upstream tracking", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("emits ordered progress events for commit hooks", () => + -+ effect("emits ordered progress events for commit hooks", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- it.effect("emits action_failed when a commit hook rejects", () => + -+ effect("emits action_failed when a commit hook rejects", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + + return yield* Effect.never; + + }).pipe( + + Effect.provide( + + ## apps/server/src/git/Layers/CodexTextGeneration.ts (new) ## + @@ + @@ apps/server/src/git/Services/TextGeneration.ts (new) + +) {} + + ## apps/server/src/orchestration/Layers/CheckpointReactor.test.ts ## + -@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: async function waitForThread( + - checkpoints: ReadonlyArray<{ checkpointTurnCount: number }>; + - activities: ReadonlyArray<{ kind: string }>; + - }) => boolean, + -- timeoutMs = 15_000, + -+ timeoutMs = 30_000, + - ) { + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: import { + + } from "@t3tools/contracts"; + + import * as NodeServices from "@effect/platform-node/NodeServices"; + + import * as Clock from "effect/Clock"; + +-import * as Deferred from "effect/Deferred"; + + import * as Effect from "effect/Effect"; + + import * as Exit from "effect/Exit"; + + import * as Layer from "effect/Layer"; + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: import * as PubSub from "effect/PubSub"; + + import * as Queue from "effect/Queue"; + + import * as Scope from "effect/Scope"; + + import * as Stream from "effect/Stream"; + +-import { it as effectIt } from "@effect/vitest"; + + import { afterEach, describe, expect, it, vi } from "vite-plus/test"; + + + + import * as CheckpointStore from "../../checkpointing/CheckpointStore.ts"; + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: import { + + type ProviderServiceShape, + + } from "../../provider/Services/ProviderService.ts"; + + import { checkpointRefForThreadTurn } from "../../checkpointing/Utils.ts"; + +-import { ProviderValidationError } from "../../provider/Errors.ts"; + + import { ServerConfig } from "../../config.ts"; + + import * as WorkspaceEntries from "../../workspace/WorkspaceEntries.ts"; + + import * as WorkspacePaths from "../../workspace/WorkspacePaths.ts"; + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: function createProviderServiceHarness( + + const rollbackConversation = vi.fn( + + (_input: { readonly threadId: ThreadId; readonly numTurns: number }) => Effect.void, + + ); + +- const assertConversationRollbackSupported = vi.fn< + +- ProviderServiceShape["assertConversationRollbackSupported"] + +- >(() => Effect.void); + + + + const unsupported = () => + + Effect.die(new Error("Unsupported provider call in test")) as Effect.Effect; + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: function createProviderServiceHarness( + + const service: ProviderServiceShape = { + + startSession: () => unsupported(), + + sendTurn: () => unsupported(), + +- compactThread: () => unsupported(), + + interruptTurn: () => unsupported(), + + respondToRequest: () => unsupported(), + + respondToUserInput: () => unsupported(), + + stopSession: () => unsupported(), + + listSessions, + + getCapabilities: () => Effect.succeed({ sessionModelSwitch: "in-session" }), + +- assertConversationRollbackSupported, + + getInstanceInfo: (instanceId) => + + Effect.succeed({ + + instanceId, + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: function createProviderServiceHarness( + + + + return { + + service, + +- assertConversationRollbackSupported, + + rollbackConversation, + + emit, + + }; + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: async function waitForThread( + + checkpoints: ReadonlyArray<{ checkpointTurnCount: number }>; + + activities: ReadonlyArray<{ kind: string }>; + + }) => boolean, + +- timeoutMs = 15_000, + ++ timeoutMs = 30_000, + + ) { + const deadline = (await Effect.runPromise(Clock.currentTimeMillis)) + timeoutMs; + const poll = async (): Promise<{ + @@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: async function waitForThread( + @@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: async function w + let runtime: ManagedRuntime.ManagedRuntime< + | OrchestrationEngineService + | CheckpointReactor + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("CheckpointReactor", () => { + + readonly providerSessionCwd?: string; + + readonly providerName?: ProviderDriverKind; + + readonly gitStatusRefreshCalls?: Array; + +- readonly pullRequestRefreshCalls?: Array; + + }) { + + const cwd = createGitRepository(); + + tempDirs.push(cwd); + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("CheckpointReactor", () => { + + Effect.as({ + + isRepo: true, + + hasPrimaryRemote: false, + +- isDefaultRef: + +- options?.localStatusRefName === undefined || options.localStatusRefName === "main", + ++ isDefaultRef: true, + + refName: + + options?.localStatusRefName !== undefined ? options.localStatusRefName : "main", + + hasWorkingTreeChanges: false, + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("CheckpointReactor", () => { + + }), + + ), + + refreshStatus: () => Effect.die("refreshStatus should not be called in this test"), + +- refreshPullRequestStatus: (cwd: string) => + +- Effect.sync(() => { + +- options?.pullRequestRefreshCalls?.push(cwd); + +- }).pipe(Effect.as(null)), + + streamStatus: () => Stream.empty, + + }); + + + @@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("CheckpointReactor", () => { + }; + } + + -- it("captures pre-turn baseline on turn.started and post-turn checkpoint on turn.completed", async () => { + +- effectIt.effect("captures baseline and large turn summaries before completion receipts", () => + +- Effect.gen(function* () { + +- const harness = yield* Effect.promise(() => + +- createHarness({ seedFilesystemCheckpoints: false }), + +- ); + +- const createdAt = "2026-01-01T00:00:00.000Z"; + + test("captures pre-turn baseline on turn.started and post-turn checkpoint on turn.completed", async () => { + - const harness = await createHarness({ seedFilesystemCheckpoints: false }); + ++ const harness = await createHarness({ seedFilesystemCheckpoints: false }); + ++ const createdAt = "2026-01-01T00:00:00.000Z"; + + + + yield* harness.engine.dispatch({ + + type: "thread.session.set", + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("CheckpointReactor", () => { + + expect(gitStatusRefreshCalls).toEqual([harness.cwd]); + + }); + + + +- it("re-asks for the pull request at turn end when the thread branch is checked out", async () => { + +- const pullRequestRefreshCalls: string[] = []; + +- const harness = await createHarness({ + +- seedFilesystemCheckpoints: false, + +- threadBranch: "t3code/feature", + +- localStatusRefName: "t3code/feature", + +- pullRequestRefreshCalls, + +- }); + +- + +- harness.provider.emit({ + +- type: "turn.completed", + +- eventId: EventId.make("evt-turn-completed-refresh-pr"), + +- provider: ProviderDriverKind.make("codex"), + +- createdAt: "2026-01-01T00:00:00.000Z", + +- threadId: ThreadId.make("thread-1"), + +- turnId: asTurnId("turn-refresh-pr"), + +- payload: { state: "completed" }, + +- }); + +- + +- await harness.drain(); + +- + +- expect(pullRequestRefreshCalls).toEqual([harness.cwd]); + +- }); + +- + +- it("re-asks for the pull request after adopting a drifted checkout", async () => { + +- const pullRequestRefreshCalls: string[] = []; + +- const harness = await createHarness({ + +- seedFilesystemCheckpoints: false, + +- threadBranch: "t3code/original-branch", + +- localStatusRefName: "t3code/renamed-by-agent", + +- pullRequestRefreshCalls, + +- }); + +- + +- harness.provider.emit({ + +- type: "turn.completed", + +- eventId: EventId.make("evt-turn-completed-drift-pr"), + +- provider: ProviderDriverKind.make("codex"), + +- createdAt: "2026-01-01T00:00:00.000Z", + +- threadId: ThreadId.make("thread-1"), + +- turnId: asTurnId("turn-drift-pr"), + +- payload: { state: "completed" }, + +- }); + +- + +- await harness.drain(); + +- + +- expect(pullRequestRefreshCalls).toEqual([harness.cwd]); + +- }); + +- + +- it("does not re-ask for the pull request at turn end on the default branch", async () => { + +- const pullRequestRefreshCalls: string[] = []; + +- const harness = await createHarness({ + +- seedFilesystemCheckpoints: false, + +- threadBranch: "main", + +- localStatusRefName: "main", + +- pullRequestRefreshCalls, + +- }); + +- + +- harness.provider.emit({ + +- type: "turn.completed", + +- eventId: EventId.make("evt-turn-completed-no-pr-refresh"), + +- provider: ProviderDriverKind.make("codex"), + +- createdAt: "2026-01-01T00:00:00.000Z", + +- threadId: ThreadId.make("thread-1"), + +- turnId: asTurnId("turn-no-pr-refresh"), + +- payload: { state: "completed" }, + +- }); + +- + +- await harness.drain(); + +- + +- expect(pullRequestRefreshCalls).toEqual([]); + +- }); + +- + + it("adopts a drifted checkout as the thread branch on a dedicated worktree", async () => { + + const harness = await createHarness({ + + seedFilesystemCheckpoints: false, + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("CheckpointReactor", () => { + + }); + + + + it("does not adopt a drifted checkout when the worktree is shared by another thread", async () => { + +- const pullRequestRefreshCalls: string[] = []; + + const harness = await createHarness({ + + seedFilesystemCheckpoints: false, + + threadBranch: "t3code/original-branch", + + localStatusRefName: "t3code/renamed-by-agent", + + secondThreadSharingWorktree: true, + +- pullRequestRefreshCalls, + + }); + + + + harness.provider.emit({ + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("CheckpointReactor", () => { + + const snapshot = await harness.readModel(); + + const thread = snapshot.threads.find((entry) => entry.id === ThreadId.make("thread-1")); + + expect(thread?.branch).toBe("t3code/original-branch"); + +- expect(pullRequestRefreshCalls).toEqual([]); + + }); + + + + it("does not adopt a temporary placeholder checkout as the thread branch", async () => { + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("CheckpointReactor", () => { + + }); + + + + it("ignores auxiliary thread turn completion while primary turn is active", async () => { + +- const pullRequestRefreshCalls: string[] = []; + +- const harness = await createHarness({ + +- seedFilesystemCheckpoints: false, + +- threadBranch: "t3code/feature", + +- localStatusRefName: "t3code/feature", + +- pullRequestRefreshCalls, + +- }); + ++ const harness = await createHarness({ seedFilesystemCheckpoints: false }); + const createdAt = "2026-01-01T00:00:00.000Z"; + + + await Effect.runPromise( + @@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("CheckpointReactor", () => { + + const midReadModel = await harness.readModel(); + + const midThread = midReadModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); + + expect(midThread?.checkpoints).toHaveLength(0); + +- expect(pullRequestRefreshCalls).toEqual([]); + +- expect(harness.pullRequestRefreshes).toEqual([]); + + + + harness.provider.emit({ + + type: "turn.completed", + +@@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("CheckpointReactor", () => { + + (entry) => entry.latestTurn?.turnId === "turn-main" && entry.checkpoints.length === 1, + + ); + expect(thread.checkpoints[0]?.checkpointTurnCount).toBe(1); + +- await harness.drain(); + +- expect(pullRequestRefreshCalls).toEqual([harness.cwd]); + +- expect(harness.pullRequestRefreshes).toEqual([1]); + }); + + - it("captures pre-turn and completion checkpoints for claude runtime events", async () => { + @@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("Checkp + ).toBe(true); + }); + + +- effectIt.effect("rejects unsupported rewind before changing files, checkpoints, or history", () => + +- Effect.gen(function* () { + +- const harness = yield* Effect.promise(() => + +- createHarness({ providerName: ProviderDriverKind.make("antigravity") }), + +- ); + +- const threadId = ThreadId.make("thread-1"); + +- const createdAt = "2026-01-01T00:00:00.000Z"; + +- const checked = yield* Deferred.make(); + +- harness.provider.assertConversationRollbackSupported.mockImplementation(() => + +- Deferred.succeed(checked, undefined).pipe( + +- Effect.andThen( + +- Effect.fail( + +- new ProviderValidationError({ + +- operation: "ProviderService.assertConversationRollbackSupported", + +- issue: "Provider 'antigravity' does not support conversation rewind.", + +- }), + +- ), + +- ), + +- ), + +- ); + +- + +- for (const turnCount of [1, 2]) { + +- yield* harness.engine.dispatch({ + +- type: "thread.turn.start", + +- commandId: CommandId.make(`cmd-unsupported-rewind-message-${turnCount}`), + +- threadId, + +- message: { + +- messageId: MessageId.make(`message-unsupported-rewind-${turnCount}`), + +- role: "user", + +- text: `Keep message ${turnCount}`, + +- attachments: [], + +- }, + +- interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + +- runtimeMode: "approval-required", + +- createdAt, + +- }); + +- yield* harness.engine.dispatch({ + +- type: "thread.turn.diff.complete", + +- commandId: CommandId.make(`cmd-unsupported-rewind-diff-${turnCount}`), + +- threadId, + +- turnId: asTurnId(`turn-unsupported-rewind-${turnCount}`), + +- completedAt: createdAt, + +- checkpointRef: checkpointRefForThreadTurn(threadId, turnCount), + +- status: "ready", + +- files: [], + +- checkpointTurnCount: turnCount, + +- createdAt, + +- }); + +- } + +- const before = (yield* Effect.promise(() => harness.readModel())).threads.find( + +- (thread) => thread.id === threadId, + +- ); + +- + +- yield* harness.engine.dispatch({ + +- type: "thread.checkpoint.revert", + +- commandId: CommandId.make("cmd-unsupported-rewind"), + +- threadId, + +- turnCount: 1, + +- createdAt, + +- }); + +- yield* Deferred.await(checked); + +- yield* Effect.promise(() => harness.drain()); + +- + +- const after = (yield* Effect.promise(() => harness.readModel())).threads.find( + +- (thread) => thread.id === threadId, + +- ); + +- expect(after?.checkpoints).toEqual(before?.checkpoints); + +- expect(after?.messages).toEqual(before?.messages); + +- expect(after?.latestTurn).toEqual(before?.latestTurn); + +- expect(after?.activities).toContainEqual( + +- expect.objectContaining({ + +- kind: "checkpoint.revert.failed", + +- payload: expect.objectContaining({ + +- detail: expect.stringContaining("does not support conversation rewind"), + +- }), + +- }), + +- ); + +- expect(harness.provider.rollbackConversation).not.toHaveBeenCalled(); + +- expect(NodeFS.readFileSync(NodePath.join(harness.cwd, "README.md"), "utf8")).toBe("v3\n"); + +- expect(gitRefExists(harness.cwd, checkpointRefForThreadTurn(threadId, 2))).toBe(true); + +- }), + +- ); + +- + - it("executes provider revert and emits thread.reverted for checkpoint revert requests", async () => { + + test("executes provider revert and emits thread.reverted for checkpoint revert requests", async () => { + const harness = await createHarness(); + @@ apps/server/src/orchestration/Layers/CheckpointReactor.test.ts: describe("Checkp + + + ## apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts ## + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: import { + + ProviderSession, + + ProviderDriverKind, + + ProviderInstanceId, + +- ProviderSetupError, + + } from "@t3tools/contracts"; + + import { createModelSelection } from "@t3tools/shared/model"; + + import { + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: import { + ThreadId, + TurnId, + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: import { + -import * as PubSub from "effect/PubSub"; + -import * as Scope from "effect/Scope"; + -import * as Stream from "effect/Stream"; + +-import * as SqlClient from "effect/unstable/sql/SqlClient"; + -import { it as effectIt } from "@effect/vitest"; + -import { afterEach, describe, expect, it, vi } from "vite-plus/test"; + +import { Deferred, Effect, Exit, Layer, ManagedRuntime, PubSub, Scope, Stream } from "effect"; + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: import { + + import { deriveServerPaths, ServerConfig } from "../../config.ts"; + import { TextGenerationError } from "@t3tools/contracts"; + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: import { + + ProviderService, + + type ProviderServiceShape, + + } from "../../provider/Services/ProviderService.ts"; + +-import { ProviderAuthService } from "../../provider/Services/ProviderAuthService.ts"; + + import { makeProviderRegistryLayer } from "../../provider/testUtils/providerRegistryMock.ts"; + + import { TextGeneration } from "../../textGeneration/TextGeneration.ts"; + + import * as RepositoryIdentityResolver from "../../project/RepositoryIdentityResolver.ts"; + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: async function waitFor( + + + + describe("ProviderCommandReactor", () => { + + let runtime: ManagedRuntime.ManagedRuntime< + +- | OrchestrationEngineService + +- | ProviderCommandReactor + +- | ProjectionSnapshotQuery + +- | SqlClient.SqlClient, + ++ OrchestrationEngineService | ProviderCommandReactor | ProjectionSnapshotQuery, + + unknown + + > | null = null; + + let scope: Scope.Closeable | null = null; + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + readonly requiresNewThreadForModelChange?: boolean; + readonly titleRegenerationCompletionDispatchFailures?: number; + readonly titleRegenerationBeforeStart?: "one" | "two"; + - readonly serverActivation?: Effect.Effect; + +- readonly beforeReadySessionDispatch?: () => Effect.Effect; + +- readonly compactThreadEffect?: () => Effect.Effect; + - readonly interruptTurnEffect?: () => Effect.Effect; + - readonly stopSessionEffect?: () => Effect.Effect; + readonly startSessionEffect?: ( + session: ProviderSession, + ) => Effect.Effect; + +- readonly tryHandlePromptCommandEffect?: ProviderAuthService["Service"]["tryHandlePromptCommand"]; + + }) { + + const now = "2026-01-01T00:00:00.000Z"; + + const baseDir = + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + + const { stateDir } = deriveServerPathsSync(baseDir, undefined); + + createdStateDirs.add(stateDir); + + const runtimeEventPubSub = Effect.runSync(PubSub.unbounded()); + +- const tryHandlePromptCommand = vi.fn( + +- input?.tryHandlePromptCommandEffect ?? (() => Effect.succeed(false)), + +- ); + + let nextSessionIndex = 1; + + const runtimeSessions: Array = []; + + const modelSelection = input?.threadModelSelection ?? { + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + turnId: asTurnId("turn-1"), + }), + ); + +- const compactThread = vi.fn((_: ThreadId) => input?.compactThreadEffect?.() ?? Effect.void); + - const interruptTurn = vi.fn((_: unknown) => input?.interruptTurnEffect?.() ?? Effect.void); + + const interruptTurn = vi.fn((_: unknown) => Effect.void); + const respondToRequest = vi.fn(() => Effect.void); + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("P + const refreshStatus = vi.fn((_: string) => + Effect.succeed({ + isRepo: true, + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + + const service: ProviderServiceShape = { + + startSession: startSession as ProviderServiceShape["startSession"], + + sendTurn: sendTurn as ProviderServiceShape["sendTurn"], + +- compactThread, + + interruptTurn: interruptTurn as ProviderServiceShape["interruptTurn"], + + respondToRequest: respondToRequest as ProviderServiceShape["respondToRequest"], + + respondToUserInput: respondToUserInput as ProviderServiceShape["respondToUserInput"], + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + + Effect.succeed({ + + sessionModelSwitch: input?.sessionModelSwitch ?? "in-session", + + }), + +- assertConversationRollbackSupported: () => unsupported(), + + getInstanceInfo: (instanceId) => { + + const raw = String(instanceId); + + const driverKind = ProviderDriverKind.make( + +- raw.startsWith("claude") + +- ? "claudeAgent" + +- : raw.startsWith("codex") + +- ? "codex" + +- : raw.startsWith("antigravity") + +- ? "antigravity" + +- : raw, + ++ raw.startsWith("claude") ? "claudeAgent" : raw.startsWith("codex") ? "codex" : raw, + + ); + + return Effect.succeed({ + + instanceId, + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + }); + }, + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("P + return Stream.fromPubSub(runtimeEventPubSub); + }, + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + + return Effect.die(new Error("Injected title regeneration completion failure")); + + } + + } + +- return ( + +- command.type === "thread.session.set" && command.session.status === "ready" + +- ? (input?.beforeReadySessionDispatch?.() ?? Effect.void) + +- : Effect.void + +- ).pipe(Effect.andThen(engine.dispatch(command))); + ++ return engine.dispatch(command); + + }, + + get streamDomainEvents() { + + return engine.streamDomainEvents; + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + + Layer.provideMerge(reactorOrchestrationLayer), + + Layer.provideMerge(projectionSnapshotLayer), + + Layer.provideMerge(Layer.succeed(ProviderService, service)), + +- Layer.provide(Layer.mock(ProviderAuthService, { tryHandlePromptCommand })), + + Layer.provideMerge(makeProviderRegistryLayer(providerSnapshots as never)), + Layer.provideMerge( + Layer.mock(GitWorkflowService.GitWorkflowService)({ + renameBranch, + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("P + ), + Layer.provideMerge( + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + + refreshLocalStatus: () => + + Effect.die("refreshLocalStatus should not be called in this test"), + + refreshStatus, + +- refreshPullRequestStatus: () => + +- Effect.die("refreshPullRequestStatus should not be called in this test"), + + streamStatus: () => Stream.die("streamStatus should not be called in this test"), + + }), + + ), + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + + }), + + ), + + Layer.provideMerge(ServerSettingsService.layerTest()), + +- Layer.provideMerge(SqlitePersistenceMemory), + + Layer.provideMerge(ServerConfig.layerTest(process.cwd(), baseDir)), + + Layer.provideMerge(NodeServices.layer), + + ); + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + + return { + + engine, + + readModel: () => Effect.runPromise(snapshotQuery.getSnapshot()), + +- readPendingTurnStarts: () => + +- runtime!.runPromise( + +- Effect.gen(function* () { + +- const sql = yield* SqlClient.SqlClient; + +- return yield* sql<{ readonly threadId: string }>` + +- SELECT thread_id AS "threadId" + +- FROM projection_turns + +- WHERE turn_id IS NULL AND state = 'pending' + +- `; + +- }), + +- ), + +- tryHandlePromptCommand, + + startSession, + + sendTurn, + +- compactThread, + + interruptTurn, + + respondToRequest, + respondToUserInput, + stopSession, + renameBranch, + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("P + generateBranchName, + generateThreadTitle, + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + - expect(thread?.session?.runtimeMode).toBe("approval-required"); + - }); + + }; + + } + + -- effectIt.effect("retains a turn dispatched immediately after start until activation", () => + +- effectIt.effect.each(["new", "ready", "stopped"] as const)( + +- "handles sign-out for a %s thread before worktree repair, text helpers, or startup", + +- (sessionStatus) => + +- Effect.gen(function* () { + +- const instanceId = ProviderInstanceId.make("antigravity-personal"); + +- const handled = yield* Deferred.make(); + +- const harness = yield* Effect.promise(() => + +- createHarness({ + +- ...(sessionStatus === "new" + +- ? {} + +- : { + +- threadModelSelection: { instanceId, model: "gemini-3.1-pro" }, + +- }), + +- tryHandlePromptCommandEffect: () => + +- Deferred.succeed(handled, undefined).pipe(Effect.as(true)), + +- }), + +- ); + +- const threadId = ThreadId.make("thread-1"); + +- const createdAt = "2026-01-01T00:00:00.000Z"; + +- if (sessionStatus !== "new") { + +- yield* harness.engine.dispatch({ + +- type: "thread.session.set", + +- commandId: CommandId.make("cmd-sign-out-bound-session"), + +- threadId, + +- session: { + +- threadId, + +- providerInstanceId: instanceId, + +- providerName: "antigravity", + +- status: sessionStatus, + +- runtimeMode: "approval-required", + +- activeTurnId: null, + +- lastError: null, + +- updatedAt: createdAt, + +- }, + +- createdAt, + +- }); + +- } + +- yield* harness.engine.dispatch({ + +- type: "thread.meta.update", + +- commandId: CommandId.make("cmd-sign-out-worktree"), + +- threadId, + +- title: "New thread", + +- branch: "t3code/1234abcd", + +- worktreePath: NodePath.join(harness.stateDir, "missing-worktree"), + +- }); + +- + +- yield* harness.engine.dispatch({ + +- type: "thread.turn.start", + +- commandId: CommandId.make("cmd-provider-sign-out"), + +- threadId, + +- message: { + +- messageId: MessageId.make("message-provider-sign-out"), + +- role: "user", + +- text: "/logout", + +- attachments: [], + +- }, + +- modelSelection: { + +- instanceId: + +- sessionStatus === "new" ? instanceId : ProviderInstanceId.make("antigravity-other"), + +- model: "gemini-3.1-pro", + +- }, + +- interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + +- runtimeMode: "approval-required", + +- createdAt, + +- }); + +- yield* Deferred.await(handled); + +- yield* Effect.promise(() => harness.drain()); + +- + +- const thread = (yield* Effect.promise(() => harness.readModel())).threads.find( + +- (entry) => entry.id === threadId, + +- ); + +- expect(thread?.session).toMatchObject({ + +- status: "stopped", + +- providerName: "antigravity", + +- providerInstanceId: instanceId, + +- activeTurnId: null, + +- lastError: null, + +- }); + +- expect(thread?.messages.map((message) => message.text)).toEqual(["/logout"]); + +- expect(thread?.activities).toContainEqual( + +- expect.objectContaining({ kind: "provider.auth.signed-out", tone: "info", turnId: null }), + +- ); + +- expect(yield* Effect.promise(() => harness.readPendingTurnStarts())).toEqual([]); + +- expect(harness.tryHandlePromptCommand).toHaveBeenCalledWith({ + +- instanceId, + +- text: "/logout", + +- hasAttachments: false, + +- }); + +- expect(harness.pruneWorktrees).not.toHaveBeenCalled(); + +- expect(harness.createWorktree).not.toHaveBeenCalled(); + +- expect(harness.generateThreadTitle).not.toHaveBeenCalled(); + +- expect(harness.generateBranchName).not.toHaveBeenCalled(); + +- expect(harness.startSession).not.toHaveBeenCalled(); + +- expect(harness.sendTurn).not.toHaveBeenCalled(); + +- }), + +- ); + +- + +- effectIt.effect("clears a failed sign-out request without sending it as a prompt", () => + - Effect.gen(function* () { + -- const activation = yield* Deferred.make(); + -- const started = yield* Deferred.make(); + +- const instanceId = ProviderInstanceId.make("antigravity-personal"); + +- const handled = yield* Deferred.make(); + - const harness = yield* Effect.promise(() => + - createHarness({ + -- serverActivation: Deferred.await(activation), + -- startSessionEffect: (session) => + -- Deferred.succeed(started, session).pipe(Effect.as(session)), + +- threadModelSelection: { instanceId, model: "gemini-3.1-pro" }, + +- tryHandlePromptCommandEffect: () => + +- Deferred.succeed(handled, undefined).pipe( + +- Effect.andThen( + +- Effect.fail( + +- new ProviderSetupError({ + +- instanceId, + +- operation: "logout", + +- detail: "The provider could not sign out. Try again.", + +- }), + +- ), + +- ), + +- ), + - }), + - ); + +- const threadId = ThreadId.make("thread-1"); + - + - yield* harness.engine.dispatch({ + - type: "thread.turn.start", + -- commandId: CommandId.make("cmd-turn-start-before-activation"), + -- threadId: ThreadId.make("thread-1"), + +- commandId: CommandId.make("cmd-provider-sign-out-failed"), + +- threadId, + - message: { + -- messageId: MessageId.make("message-before-activation"), + +- messageId: MessageId.make("message-provider-sign-out-failed"), + - role: "user", + -- text: "Start after activation", + +- text: "/logout", + - attachments: [], + - }, + - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + - runtimeMode: "approval-required", + - createdAt: "2026-01-01T00:00:00.000Z", + - }); + -- expect(yield* Deferred.isDone(started)).toBe(false); + -- + -- yield* Deferred.succeed(activation, undefined); + -- const session = yield* Deferred.await(started); + +- yield* Deferred.await(handled); + - yield* Effect.promise(() => harness.drain()); + -- expect(session.threadId).toBe(ThreadId.make("thread-1")); + -- expect(harness.sendTurn.mock.calls[0]?.[0]).toMatchObject({ + -- threadId: ThreadId.make("thread-1"), + -- input: "Start after activation", + +- + +- const thread = (yield* Effect.promise(() => harness.readModel())).threads.find( + +- (entry) => entry.id === threadId, + +- ); + +- expect(thread?.session).toMatchObject({ + +- status: "error", + +- activeTurnId: null, + +- lastError: expect.stringContaining("The provider could not sign out. Try again."), + - }); + +- expect(thread?.activities).toContainEqual( + +- expect.objectContaining({ kind: "provider.turn.start.failed", tone: "error" }), + +- ); + +- expect( + +- thread?.activities.some((activity) => activity.kind === "provider.auth.signed-out"), + +- ).toBe(false); + +- expect(yield* Effect.promise(() => harness.readPendingTurnStarts())).toEqual([]); + +- expect(harness.startSession).not.toHaveBeenCalled(); + +- expect(harness.sendTurn).not.toHaveBeenCalled(); + - }), + - ); + - + -- effectIt.effect("projects starting before a slow provider session finishes", () => + +- effectIt.effect.each([ + +- { label: "a command mention", text: "What does /logout do?", attachments: [] }, + +- { + +- label: "a command with an attachment", + +- text: "/logout", + +- attachments: [ + +- { + +- type: "file" as const, + +- id: "attached-notes", + +- name: "notes.txt", + +- mimeType: "text/plain", + +- sizeBytes: 8, + +- }, + +- ], + +- }, + +- { label: "another provider's command", text: "/logout", attachments: [] }, + +- ])("sends $label when the provider auth handler leaves it unhandled", ({ text, attachments }) => + - Effect.gen(function* () { + -- const releaseStart = yield* Deferred.make(); + +- const started = yield* Deferred.make(); + - const harness = yield* Effect.promise(() => + - createHarness({ + -- startSessionEffect: (session) => Deferred.await(releaseStart).pipe(Effect.as(session)), + +- startSessionEffect: (session) => + +- Deferred.succeed(started, undefined).pipe(Effect.as(session)), + - }), + - ); + -- const now = "2026-01-01T00:00:00.000Z"; + - + - yield* harness.engine.dispatch({ + - type: "thread.turn.start", + -- commandId: CommandId.make("cmd-turn-start-slow-provider"), + +- commandId: CommandId.make("cmd-provider-command-unhandled"), + - threadId: ThreadId.make("thread-1"), + - message: { + -- messageId: asMessageId("user-message-slow-provider"), + +- messageId: MessageId.make("message-provider-command-unhandled"), + - role: "user", + -- text: "start slowly", + -- attachments: [], + +- text, + +- attachments, + - }, + - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + - runtimeMode: "approval-required", + -- createdAt: now, + +- createdAt: "2026-01-01T00:00:00.000Z", + - }); + +- yield* Deferred.await(started); + +- yield* Effect.promise(() => harness.drain()); + - + -- yield* Effect.promise(() => waitFor(() => harness.startSession.mock.calls.length === 1)); + -- const duringStartup = yield* Effect.promise(() => harness.readModel()); + -- expect( + -- duringStartup.threads.find((entry) => entry.id === ThreadId.make("thread-1"))?.session + -- ?.status, + -- ).toBe("starting"); + -- expect(harness.sendTurn).not.toHaveBeenCalled(); + -- + -- yield* Deferred.succeed(releaseStart, undefined); + -- yield* Effect.promise(() => waitFor(() => harness.sendTurn.mock.calls.length === 1)); + +- expect(harness.tryHandlePromptCommand).toHaveBeenCalledWith({ + +- instanceId: ProviderInstanceId.make("codex"), + +- text, + +- hasAttachments: attachments.length > 0, + +- }); + +- expect(harness.sendTurn).toHaveBeenCalledWith( + +- expect.objectContaining({ + +- input: text, + +- ...(attachments.length > 0 ? { attachments } : {}), + +- }), + +- ); + - }), + - ); + - + -- effectIt.effect("settles a failed provider startup and allows a clean retry", () => + -- Effect.gen(function* () { + -- let failStartup = true; + -- const harness = yield* Effect.promise(() => + -- createHarness({ + -- startSessionEffect: (session) => + -- failStartup + -- ? Effect.fail( + -- new ProviderAdapterRequestError({ + -- provider: "codex", + -- method: "thread.start", + -- detail: "deterministic startup failure", + -- }), + -- ) + -- : Effect.succeed(session), + + it("reacts to thread.turn.start by ensuring session and sending provider turn", async () => { + + const harness = await createHarness(); + + const now = "2026-01-01T00:00:00.000Z"; + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + + expect(thread?.session?.runtimeMode).toBe("approval-required"); + + }); + + + +- effectIt.effect("retains a turn dispatched immediately after start until activation", () => + +- Effect.gen(function* () { + +- const activation = yield* Deferred.make(); + +- const started = yield* Deferred.make(); + +- const harness = yield* Effect.promise(() => + +- createHarness({ + +- serverActivation: Deferred.await(activation), + +- startSessionEffect: (session) => + +- Deferred.succeed(started, session).pipe(Effect.as(session)), + - }), + - ); + -- const now = "2026-01-01T00:00:00.000Z"; + +- + +- yield* harness.engine.dispatch({ + +- type: "thread.turn.start", + +- commandId: CommandId.make("cmd-turn-start-before-activation"), + +- threadId: ThreadId.make("thread-1"), + +- message: { + +- messageId: MessageId.make("message-before-activation"), + +- role: "user", + +- text: "Start after activation", + +- attachments: [], + +- }, + +- interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + +- runtimeMode: "approval-required", + +- createdAt: "2026-01-01T00:00:00.000Z", + +- }); + +- expect(yield* Deferred.isDone(started)).toBe(false); + +- + +- yield* Deferred.succeed(activation, undefined); + +- const session = yield* Deferred.await(started); + +- yield* Effect.promise(() => harness.drain()); + +- expect(session.threadId).toBe(ThreadId.make("thread-1")); + +- expect(harness.sendTurn.mock.calls[0]?.[0]).toMatchObject({ + +- threadId: ThreadId.make("thread-1"), + +- input: "Start after activation", + +- }); + +- }), + +- ); + + it("records session lastError and clears active turn when provider turn start fails", async () => { + + const harness = await createHarness(); + + const now = new Date().toISOString(); + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("P + + ) as never, + + ); + + +- effectIt.effect("rejects /compact without conversation context", () => + +- Effect.gen(function* () { + +- const harness = yield* Effect.promise(() => createHarness()); + - yield* harness.engine.dispatch({ + + await Effect.runPromise( + + harness.engine.dispatch({ + type: "thread.turn.start", + -- commandId: CommandId.make("cmd-turn-start-provider-failure"), + +- commandId: CommandId.make("cmd-empty-compact"), + + commandId: CommandId.make("cmd-turn-start-session-error"), + threadId: ThreadId.make("thread-1"), + message: { + -- messageId: asMessageId("user-message-provider-failure"), + +- messageId: asMessageId("user-message-empty-compact"), + +- role: "user", + +- text: "/compact", + +- attachments: [], + +- }, + +- interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + +- runtimeMode: "approval-required", + +- createdAt: "2026-01-01T00:00:00.000Z", + +- }); + +- yield* Effect.promise(() => harness.drain()); + +- expect(harness.compactThread).not.toHaveBeenCalled(); + +- }), + +- ); + +- + +- effectIt.effect("keeps turns blocked until compaction restores the session", () => + +- Effect.gen(function* () { + +- const readyDispatchStarted = yield* Deferred.make(); + +- const releaseReadyDispatch = yield* Deferred.make(); + +- let blockReadyDispatch = false; + +- const harness = yield* Effect.promise(() => + +- createHarness({ + +- beforeReadySessionDispatch: () => + +- blockReadyDispatch + +- ? Deferred.succeed(readyDispatchStarted, undefined).pipe( + +- Effect.andThen(Deferred.await(releaseReadyDispatch)), + +- ) + +- : Effect.void, + +- }), + +- ); + +- const threadId = ThreadId.make("thread-1"); + +- const now = "2026-01-01T00:00:00.000Z"; + +- const dispatchTurn = (id: string, text: string, createdAt: string) => + +- harness.engine.dispatch({ + +- type: "thread.turn.start", + +- commandId: CommandId.make(`cmd-${id}`), + +- threadId, + +- message: { + +- messageId: asMessageId(`user-message-${id}`), + +- role: "user", + +- text, + +- attachments: [], + +- }, + +- interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + +- runtimeMode: "approval-required", + +- createdAt, + +- }); + +- + +- yield* dispatchTurn("before-blocked-compact", "hello", now); + +- yield* Effect.promise(() => waitFor(() => harness.sendTurn.mock.calls.length === 1)); + +- yield* harness.engine.dispatch({ + +- type: "thread.session.set", + +- commandId: CommandId.make("cmd-session-ready-before-blocked-compact"), + +- threadId, + +- session: { + +- threadId, + +- status: "ready", + +- providerName: "codex", + +- providerInstanceId: ProviderInstanceId.make("codex"), + +- runtimeMode: "approval-required", + +- activeTurnId: null, + +- lastError: null, + +- updatedAt: now, + +- }, + +- createdAt: now, + +- }); + +- + +- blockReadyDispatch = true; + +- yield* dispatchTurn("blocked-compact", "/compact", "2026-01-01T00:00:01.000Z"); + +- yield* Deferred.await(readyDispatchStarted); + +- + +- yield* dispatchTurn("during-compact-recovery", "too soon", "2026-01-01T00:00:02.000Z"); + +- yield* Effect.promise(() => + +- waitFor(async () => { + +- const thread = (await harness.readModel()).threads.find((entry) => entry.id === threadId); + +- return ( + +- thread?.activities.some( + +- (activity) => activity.kind === "provider.turn.start.failed", + +- ) === true + +- ); + +- }), + +- ); + +- expect(harness.sendTurn).toHaveBeenCalledTimes(1); + +- expect(yield* Effect.promise(() => harness.readPendingTurnStarts())).toEqual([ + +- { threadId: "thread-1" }, + +- ]); + +- + +- yield* Deferred.succeed(releaseReadyDispatch, undefined); + +- yield* Effect.promise(() => + +- waitFor(async () => { + +- const thread = (await harness.readModel()).threads.find((entry) => entry.id === threadId); + +- return thread?.session?.status === "ready"; + +- }), + +- ); + +- }), + +- ); + +- + +- effectIt.effect("does not overwrite concurrent session state after compaction failure", () => + +- Effect.gen(function* () { + +- const releaseCompaction = yield* Deferred.make(); + +- const releaseRunningCompaction = yield* Deferred.make(); + +- const releaseFailedStop = yield* Deferred.make(); + +- let compactionCount = 0; + +- const harness = yield* Effect.promise(() => + +- createHarness({ + +- compactThreadEffect: () => + +- Deferred.await( + +- compactionCount++ === 0 ? releaseCompaction : releaseRunningCompaction, + +- ).pipe(Effect.andThen(Effect.die("Compaction stopped"))), + +- stopSessionEffect: () => + +- Deferred.await(releaseFailedStop).pipe( + +- Effect.andThen( + +- Effect.fail( + +- new ProviderAdapterRequestError({ + +- provider: "codex", + +- method: "session.stop", + +- detail: "provider stop failed", + +- }), + +- ), + +- ), + +- ), + +- }), + +- ); + +- const threadId = ThreadId.make("thread-1"); + +- const now = "2026-01-01T00:00:00.000Z"; + +- const dispatchCompact = (suffix: string, createdAt: string) => + +- harness.engine.dispatch({ + +- type: "thread.turn.start", + +- commandId: CommandId.make(`cmd-compact-${suffix}`), + +- threadId, + +- message: { + +- messageId: asMessageId(`user-message-compact-${suffix}`), + +- role: "user", + +- text: "/compact", + +- attachments: [], + +- }, + +- interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + +- runtimeMode: "approval-required", + +- createdAt, + +- }); + +- + +- yield* harness.engine.dispatch({ + +- type: "thread.turn.start", + +- commandId: CommandId.make("cmd-message-before-compact"), + +- threadId, + +- message: { + +- messageId: asMessageId("user-message-before-compact"), + + messageId: asMessageId("user-message-session-error"), + role: "user", + -- text: "fail once", + -+ text: "hello", + + text: "hello", + attachments: [], + - }, + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + runtimeMode: "approval-required", + createdAt: now, + - }); + -+ }), + -+ ); + - + +- yield* Effect.promise(() => waitFor(() => harness.sendTurn.mock.calls.length === 1)); + +- yield* harness.engine.dispatch({ + +- type: "thread.session.set", + +- commandId: CommandId.make("cmd-session-ready-before-compact"), + +- threadId, + +- session: { + +- threadId, + +- status: "ready", + +- providerName: "codex", + +- providerInstanceId: ProviderInstanceId.make("codex"), + +- runtimeMode: "approval-required", + +- activeTurnId: null, + +- lastError: null, + +- updatedAt: now, + +- }, + +- createdAt: now, + +- }); + +- yield* dispatchCompact("before-stop", now); + +- yield* Effect.promise(() => waitFor(() => harness.compactThread.mock.calls.length === 1)); + +- const compactingThread = (yield* Effect.promise(() => harness.readModel())).threads.find( + +- (entry) => entry.id === threadId, + +- ); + +- expect(compactingThread?.session?.status).toBe("starting"); + +- yield* harness.engine.dispatch({ + +- type: "thread.session.stop", + +- commandId: CommandId.make("cmd-stop-during-compact"), + +- threadId, + +- createdAt: "2026-01-01T00:00:01.000Z", + +- }); + +- yield* Effect.promise(() => waitFor(() => harness.stopSession.mock.calls.length === 1)); + +- yield* Deferred.succeed(releaseCompaction, undefined); + - yield* Effect.promise(() => + - waitFor(async () => { + -- const readModel = await harness.readModel(); + +- const compactingThread = (await harness.readModel()).threads.find( + +- (entry) => entry.id === threadId, + +- ); + - return ( + -- readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"))?.session + -- ?.status === "error" + +- compactingThread?.activities.some( + +- (activity) => activity.kind === "provider.turn.start.failed", + +- ) === true + - ); + - }), + -+ await waitFor(async () => { + -+ const readModel = await Effect.runPromise(harness.engine.getReadModel()); + -+ const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); + -+ return ( + -+ thread?.session?.lastError === + -+ 'Provider adapter request failed (cursor) for session/set_config_option: Invalid value for session config option "model"' && + -+ thread?.session?.status === "ready" && + -+ thread?.session?.activeTurnId === null + - ); + -- let readModel = yield* Effect.promise(() => harness.readModel()); + -- let thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); + -- expect(thread?.session?.lastError).toContain("deterministic startup failure"); + -- expect(harness.sendTurn).not.toHaveBeenCalled(); + +- ); + +- const stoppingThread = (yield* Effect.promise(() => harness.readModel())).threads.find( + +- (entry) => entry.id === threadId, + +- ); + +- expect(stoppingThread?.session?.status).toBe("starting"); + +- yield* Deferred.succeed(releaseFailedStop, undefined); + +- yield* Effect.promise(() => harness.drain()); + +- + +- const recoveredThread = (yield* Effect.promise(() => harness.readModel())).threads.find( + +- (entry) => entry.id === threadId, + +- ); + +- expect(recoveredThread?.session?.status).toBe("ready"); + +- expect( + +- recoveredThread?.activities.find( + +- (activity) => activity.kind === "provider.session.stop.failed", + +- ), + +- ).toMatchObject({ + +- summary: "Provider session stop failed", + +- payload: { detail: "provider stop failed" }, + +- }); + +- + +- yield* dispatchCompact("before-running", "2026-01-01T00:00:02.000Z"); + +- yield* Effect.promise(() => waitFor(() => harness.compactThread.mock.calls.length === 2)); + +- yield* harness.engine.dispatch({ + +- type: "thread.session.stop", + +- commandId: CommandId.make("cmd-failed-stop-before-compaction-settles"), + +- threadId, + +- createdAt: "2026-01-01T00:00:02.500Z", + +- }); + +- yield* Effect.promise(() => + +- waitFor(async () => { + +- const thread = (await harness.readModel()).threads.find((entry) => entry.id === threadId); + +- return ( + +- thread?.activities.filter( + +- (activity) => activity.kind === "provider.session.stop.failed", + +- ).length === 2 + +- ); + +- }), + +- ); + +- const restartedThread = (yield* Effect.promise(() => harness.readModel())).threads.find( + +- (entry) => entry.id === threadId, + +- ); + +- expect(restartedThread?.session?.status).toBe("starting"); + +- const restartedSession = restartedThread?.session; + +- if (!restartedSession) return yield* Effect.die("Compaction session missing"); + +- yield* harness.engine.dispatch({ + +- type: "thread.session.set", + +- commandId: CommandId.make("cmd-running-during-compact"), + +- threadId, + +- session: { + +- ...restartedSession, + +- status: "running", + +- activeTurnId: asTurnId("compaction-turn"), + +- updatedAt: "2026-01-01T00:00:03.000Z", + +- }, + +- createdAt: "2026-01-01T00:00:03.000Z", + +- }); + +- yield* Deferred.succeed(releaseRunningCompaction, undefined); + +- yield* Effect.promise(() => harness.drain()); + +- const runningThread = (yield* Effect.promise(() => harness.readModel())).threads.find( + +- (entry) => entry.id === threadId, + +- ); + +- expect(runningThread?.session?.status).toBe("running"); + +- }), + +- ); + +- effectIt.effect("projects starting before a slow provider session finishes", () => + +- Effect.gen(function* () { + +- const releaseStart = yield* Deferred.make(); + +- const harness = yield* Effect.promise(() => + +- createHarness({ + +- startSessionEffect: (session) => Deferred.await(releaseStart).pipe(Effect.as(session)), + +- }), + +- ); + +- const now = "2026-01-01T00:00:00.000Z"; + - + -- failStartup = false; + - yield* harness.engine.dispatch({ + - type: "thread.turn.start", + -- commandId: CommandId.make("cmd-turn-start-provider-retry"), + +- commandId: CommandId.make("cmd-turn-start-slow-provider"), + - threadId: ThreadId.make("thread-1"), + - message: { + -- messageId: asMessageId("user-message-provider-retry"), + +- messageId: asMessageId("user-message-slow-provider"), + - role: "user", + -- text: "retry", + +- text: "start slowly", + - attachments: [], + - }, + - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + - runtimeMode: "approval-required", + -- createdAt: "2026-01-01T00:00:01.000Z", + +- createdAt: now, + - }); + -+ }); + - + +- + +- yield* Effect.promise(() => waitFor(() => harness.startSession.mock.calls.length === 1)); + +- const duringStartup = yield* Effect.promise(() => harness.readModel()); + +- expect( + +- duringStartup.threads.find((entry) => entry.id === ThreadId.make("thread-1"))?.session + +- ?.status, + +- ).toBe("starting"); + +- expect(harness.sendTurn).not.toHaveBeenCalled(); + +- + +- yield* Deferred.succeed(releaseStart, undefined); + - yield* Effect.promise(() => waitFor(() => harness.sendTurn.mock.calls.length === 1)); + -- readModel = yield* Effect.promise(() => harness.readModel()); + -- thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); + -- expect(thread?.session?.status).toBe("starting"); + -- expect(thread?.session?.lastError).toBeNull(); + - }), + - ); + -+ const readModel = await Effect.runPromise(harness.engine.getReadModel()); + -+ const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); + -+ expect(thread?.session).toMatchObject({ + -+ status: "ready", + -+ activeTurnId: null, + -+ lastError: + -+ 'Provider adapter request failed (cursor) for session/set_config_option: Invalid value for session config option "model"', + -+ }); + -+ }); + - + - it("retries thread title generation after a transient failure", async () => { + - const harness = await createHarness(); + -@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + - ).toBe(prompt); + - }); + - + -- it("recreates a missing worktree from the thread branch before starting a turn", async () => { + +- + +- effectIt.effect("settles a failed provider startup and allows a clean retry", () => + +- Effect.gen(function* () { + +- let failStartup = true; + +- const harness = yield* Effect.promise(() => + +- createHarness({ + +- startSessionEffect: (session) => + +- failStartup + +- ? Effect.fail( + +- new ProviderAdapterRequestError({ + +- provider: "codex", + +- method: "thread.start", + +- detail: "deterministic startup failure", + +- }), + +- ) + +- : Effect.succeed(session), + +- }), + +- ); + +- const now = "2026-01-01T00:00:00.000Z"; + +- + +- yield* harness.engine.dispatch({ + +- type: "thread.turn.start", + +- commandId: CommandId.make("cmd-turn-start-provider-failure"), + +- threadId: ThreadId.make("thread-1"), + +- message: { + +- messageId: asMessageId("user-message-provider-failure"), + +- role: "user", + +- text: "fail once", + +- attachments: [], + +- }, + +- interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + +- runtimeMode: "approval-required", + +- createdAt: now, + +- }); + ++ }), + ++ ); + + + +- yield* Effect.promise(() => + +- waitFor(async () => { + +- const readModel = await harness.readModel(); + +- return ( + +- readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"))?.session + +- ?.status === "error" + +- ); + +- }), + ++ await waitFor(async () => { + ++ const readModel = await Effect.runPromise(harness.engine.getReadModel()); + ++ const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); + ++ return ( + ++ thread?.session?.lastError === + ++ 'Provider adapter request failed (cursor) for session/set_config_option: Invalid value for session config option "model"' && + ++ thread?.session?.status === "ready" && + ++ thread?.session?.activeTurnId === null + + ); + +- let readModel = yield* Effect.promise(() => harness.readModel()); + +- let thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); + +- expect(thread?.session?.lastError).toContain("deterministic startup failure"); + +- expect(harness.sendTurn).not.toHaveBeenCalled(); + +- + +- failStartup = false; + +- yield* harness.engine.dispatch({ + +- type: "thread.turn.start", + +- commandId: CommandId.make("cmd-turn-start-provider-retry"), + +- threadId: ThreadId.make("thread-1"), + +- message: { + +- messageId: asMessageId("user-message-provider-retry"), + +- role: "user", + +- text: "retry", + +- attachments: [], + +- }, + +- interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + +- runtimeMode: "approval-required", + +- createdAt: "2026-01-01T00:00:01.000Z", + +- }); + ++ }); + + + +- yield* Effect.promise(() => waitFor(() => harness.sendTurn.mock.calls.length === 1)); + +- readModel = yield* Effect.promise(() => harness.readModel()); + +- thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); + +- expect(thread?.session?.status).toBe("starting"); + +- expect(thread?.session?.lastError).toBeNull(); + +- }), + +- ); + ++ const readModel = await Effect.runPromise(harness.engine.getReadModel()); + ++ const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); + ++ expect(thread?.session).toMatchObject({ + ++ status: "ready", + ++ activeTurnId: null, + ++ lastError: + ++ 'Provider adapter request failed (cursor) for session/set_config_option: Invalid value for session config option "model"', + ++ }); + ++ }); + + + + it("retries thread title generation after a transient failure", async () => { + + const harness = await createHarness(); + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + + readModel.threads + + .find((entry) => entry.id === ThreadId.make("thread-1")) + + ?.messages.find((entry) => entry.id === asMessageId("user-message-branch-model"))?.text, + +- ).toBe(prompt); + +- }); + +- + +- it("recreates a missing worktree from the thread branch before starting a turn", async () => { + - const harness = await createHarness(); + - const now = "2026-01-01T00:00:00.000Z"; + - const worktreePath = NodePath.join(harness.stateDir, "missing-worktree"); + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("P + - expect(harness.createWorktree.mock.invocationCallOrder[0]).toBeLessThan( + - harness.startSession.mock.invocationCallOrder[0]!, + - ); + -- }); + -- + ++ ).toBe(prompt); + + }); + + + it("forwards codex model options through session start and turn send", async () => { + - const harness = await createHarness(); + - const now = "2026-01-01T00:00:00.000Z"; + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + }); + }); + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("P + }), + ), + ); + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: describe("ProviderCommandReactor", () => { + + commandId: CommandId.make("cmd-auto-settle-with-session"), + + threadId: ThreadId.make("thread-1"), + + snapshotSequence: beforeSettlement.snapshotSequence, + +- settledAt: now, + + }); + + + + yield* Deferred.await(sessionStopped); + + ## apps/server/src/orchestration/Layers/ProviderCommandReactor.ts ## + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: import { isTemporaryWorktreeBranch, WORKTREE_BRANCH_PREFIX } from "@t3tools/shar + + import * as Cache from "effect/Cache"; + + import * as Cause from "effect/Cause"; + + import * as Crypto from "effect/Crypto"; + +-import * as DateTime from "effect/DateTime"; + + import * as Duration from "effect/Duration"; + + import * as Effect from "effect/Effect"; + + import * as Equal from "effect/Equal"; + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: import { makeDrainableWorker } from "@t3tools/shared/DrainableWorker"; + + + + import { resolveThreadWorkspaceCwd } from "../../checkpointing/Utils.ts"; + + import { increment, orchestrationEventsProcessedTotal } from "../../observability/Metrics.ts"; + +-import { + +- ProviderAdapterRequestError, + +- ProviderAdapterValidationError, + +-} from "../../provider/Errors.ts"; + ++import { ProviderAdapterRequestError } from "../../provider/Errors.ts"; + + import type { ProviderServiceError } from "../../provider/Errors.ts"; + + import { TextGeneration } from "../../textGeneration/TextGeneration.ts"; + +-import { ProviderAuthService } from "../../provider/Services/ProviderAuthService.ts"; + + import { ProviderService } from "../../provider/Services/ProviderService.ts"; + + import { ProviderRegistry } from "../../provider/Services/ProviderRegistry.ts"; + + import { OrchestrationEngineService } from "../Services/OrchestrationEngine.ts"; + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: import { + + import { VcsStatusBroadcaster } from "../../vcs/VcsStatusBroadcaster.ts"; + + import { GitWorkflowService } from "../../git/GitWorkflowService.ts"; + + const isProviderAdapterRequestError = Schema.is(ProviderAdapterRequestError); + +-const isProviderAdapterValidationError = Schema.is(ProviderAdapterValidationError); + + const isProviderDriverKind = Schema.is(ProviderDriverKind); + + + + type ProviderIntentEvent = Extract< + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: function toNonEmptyProviderInput(value: string | undefined): string | undefined + + return normalized && normalized.length > 0 ? normalized : undefined; + + } + + + +-const isCompactCommandMessage = (message: ThreadTitleMessage): boolean => + +- message.role === "user" && + +- (message.attachments?.length ?? 0) === 0 && + +- message.text.trim().toLowerCase() === "/compact"; + + function mapProviderSessionStatusToOrchestrationStatus( + + status: "connecting" | "ready" | "running" | "error" | "closed", + + ): OrchestrationSession["status"] { + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: function findProviderAdapterRequestError( + + function isUnknownPendingApprovalRequestError(cause: Cause.Cause): boolean { + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: function isUnkno + const message = Cause.pretty(cause).toLowerCase(); + return ( + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Effect.gen(function* () { + - ? failReason.error + - : undefined; + - if (providerError) { + -- return providerError.detail; + + const crypto = yield* Crypto.Crypto; + + const orchestrationEngine = yield* OrchestrationEngineService; + + const projectionSnapshotQuery = yield* ProjectionSnapshotQuery; + +- const providerAuthService = yield* ProviderAuthService; + + const providerService = yield* ProviderService; + + const providerRegistry = yield* ProviderRegistry; + + const gitWorkflow = yield* GitWorkflowService; + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Effect.gen(function* () { + + ); + + + + const threadModelSelections = new Map(); + +- const compactingThreadIds = new Set(); + +- const stoppingThreadIds = new Set(); + + + + const appendProviderFailureActivity = (input: { + + readonly threadId: ThreadId; + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Effect.gen(function* () { + + + + const formatFailureDetail = (cause: Cause.Cause): string => { + + const failReason = cause.reasons.find(Cause.isFailReason); + +- if (isProviderAdapterRequestError(failReason?.error)) { + +- return failReason.error.detail; + +- } + +- if (isProviderAdapterValidationError(failReason?.error)) { + +- return failReason.error.issue; + ++ const providerError = isProviderAdapterRequestError(failReason?.error) + ++ ? failReason.error + ++ : undefined; + ++ if (providerError) { + + return providerError.message; + } + return Cause.pretty(cause); + }; + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Effect.gen(function* () { + + }); + + }); + + + +- const restoreCompaction = Effect.fnUntraced(function* (threadId: ThreadId, fromRunning = false) { + +- if (stoppingThreadIds.has(threadId)) { + +- compactingThreadIds.delete(threadId); + +- return; + +- } + +- const thread = yield* resolveThread(threadId); + +- if (!thread?.session) return; + +- if ( + +- thread.session.status !== "starting" && + +- thread.session.status !== "ready" && + +- (!fromRunning || thread.session.status !== "running") + +- ) + +- return; + +- const completedAt = DateTime.formatIso(yield* DateTime.now); + +- if (stoppingThreadIds.has(threadId)) { + +- compactingThreadIds.delete(threadId); + +- return; + +- } + +- yield* setThreadSession({ + +- threadId, + +- session: { + +- ...thread.session, + +- status: "ready", + +- activeTurnId: null, + +- lastError: null, + +- updatedAt: completedAt, + +- }, + +- createdAt: completedAt, + +- }); + +- }); + +- + + const resolveProject = Effect.fnUntraced(function* (projectId: ProjectId) { + + return yield* projectionSnapshotQuery + + .getProjectShellById(projectId) + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Effect.gen(function* () { + thread.session && thread.session.status !== "stopped" && activeSession ? thread.id : null; + if (existingSessionThreadId) { + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Eff + instanceChanged, + shouldRestartForModelChange, + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Effect.gen(function* () { + + if (!thread) { + + return; + } + - + - const handleTurnStartFailure = (cause: Cause.Cause) => { + ++ + + const message = thread.messages.find((entry) => entry.id === event.payload.messageId); + + if (!message || message.role !== "user") { + + yield* appendProviderFailureActivity({ + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Effect.gen(function* () { + + detail: `User message '${event.payload.messageId}' was not found for turn start request.`, + + turnId: null, + + createdAt: event.payload.createdAt, + +- requestId: event.payload.messageId, + + }); + + return; + + } + +- const appendTurnStartFailure = (summary: string, detail: string) => + +- appendProviderFailureActivity({ + +- threadId: event.payload.threadId, + +- kind: "provider.turn.start.failed", + +- summary, + +- detail, + +- turnId: null, + +- createdAt: event.payload.createdAt, + +- requestId: event.payload.messageId, + +- }); + +- + +- const handleTurnStartFailure = (cause: Cause.Cause) => { + - if (Cause.hasInterruptsOnly(cause)) { + - return Effect.void; + - } + - const detail = formatFailureDetail(cause); + - return setThreadSessionErrorOnTurnStartFailure({ + - threadId: event.payload.threadId, + -@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Effect.gen(function* () { + - createdAt: event.payload.createdAt, + - }), + - ), + +- const detail = formatFailureDetail(cause); + +- return setThreadSessionErrorOnTurnStartFailure({ + +- threadId: event.payload.threadId, + +- detail, + +- createdAt: event.payload.createdAt, + +- }).pipe( + +- Effect.flatMap(() => appendTurnStartFailure("Provider turn start failed", detail)), + - Effect.asVoid, + - ); + - }; + - + +- ); + +- }; + +- + - const recoverTurnStartFailure = (cause: Cause.Cause) => + - handleTurnStartFailure(cause).pipe( + - Effect.catchCause((recoveryCause) => + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Eff + - ), + - ); + - + +- const authCommandHandled = yield* Effect.gen(function* () { + +- // Native account commands belong to the thread's existing provider session. + +- const instanceId = + +- thread.session?.providerInstanceId ?? + +- event.payload.modelSelection?.instanceId ?? + +- thread.modelSelection.instanceId; + +- const handled = yield* providerAuthService.tryHandlePromptCommand({ + +- instanceId, + +- text: message.text, + +- hasAttachments: (message.attachments?.length ?? 0) > 0, + +- }); + +- if (!handled) { + +- return false; + +- } + +- + +- const instanceInfo = yield* providerService.getInstanceInfo(instanceId); + +- yield* setThreadSession({ + +- threadId: thread.id, + +- session: { + +- threadId: thread.id, + +- status: "stopped", + +- providerName: instanceInfo.driverKind, + +- providerInstanceId: instanceId, + +- runtimeMode: thread.runtimeMode, + +- activeTurnId: null, + +- lastError: null, + +- updatedAt: event.payload.createdAt, + +- }, + +- createdAt: event.payload.createdAt, + +- }); + +- yield* orchestrationEngine.dispatch({ + +- type: "thread.activity.append", + +- commandId: yield* serverCommandId("provider-sign-out"), + +- threadId: thread.id, + +- activity: { + +- id: yield* serverEventId(), + +- tone: "info", + +- kind: "provider.auth.signed-out", + +- summary: "Provider signed out", + +- payload: { providerInstanceId: instanceId }, + +- turnId: null, + +- createdAt: event.payload.createdAt, + +- }, + +- createdAt: event.payload.createdAt, + +- }); + +- return true; + +- }).pipe(Effect.catchCause((cause) => recoverTurnStartFailure(cause).pipe(Effect.as(true)))); + +- if (authCommandHandled) { + +- return; + +- } + + + + yield* ensureThreadWorktree(thread); + + + +- const isCompactCommand = isCompactCommandMessage(message); + +- const nonCompactUserMessageCount = thread.messages.filter( + +- (entry) => entry.role === "user" && !isCompactCommandMessage(entry), + +- ).length; + +- if (nonCompactUserMessageCount === 1 && !isCompactCommand) { + ++ const isFirstUserMessageTurn = + ++ thread.messages.filter((entry) => entry.role === "user").length === 1; + ++ if (isFirstUserMessageTurn) { + + const project = yield* resolveProject(thread.projectId); + + const generationCwd = + + resolveThreadWorkspaceCwd({ + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Effect.gen(function* () { + + } + + } + + + +- let compactionSessionEnsured = false; + +- const handleCompactionFailure = (cause: Cause.Cause) => { + +- if (Cause.hasInterruptsOnly(cause)) { + +- return Effect.void; + +- } + ++ const handleTurnStartFailure = (cause: Cause.Cause) => { + + const detail = formatFailureDetail(cause); + +- if (!compactionSessionEnsured) { + +- return setThreadSessionErrorOnTurnStartFailure({ + +- threadId: event.payload.threadId, + +- detail, + +- createdAt: event.payload.createdAt, + +- }).pipe( + +- Effect.flatMap(() => appendTurnStartFailure("Context compaction failed", detail)), + +- Effect.asVoid, + +- ); + +- } + +- return appendTurnStartFailure("Context compaction failed", detail).pipe( + +- Effect.ensuring( + +- restoreCompaction(event.payload.threadId).pipe( + +- Effect.catchCause((restoreCause) => + +- Effect.logWarning("failed to restore provider session after compaction failure", { + +- threadId: event.payload.threadId, + +- cause: Cause.pretty(restoreCause), + +- }), + +- ), + +- ), + +- ), + +- Effect.asVoid, + +- ); + +- }; + +- const recoverCompactionFailure = (cause: Cause.Cause) => + +- handleCompactionFailure(cause).pipe( + +- Effect.catchCause((recoveryCause) => + +- Effect.logWarning("provider command reactor failed to recover compaction failure", { + +- eventType: event.type, + ++ return setThreadSessionErrorOnTurnStartFailure({ + ++ threadId: event.payload.threadId, + ++ detail, + ++ createdAt: event.payload.createdAt, + ++ }).pipe( + ++ Effect.flatMap(() => + ++ appendProviderFailureActivity({ + + threadId: event.payload.threadId, + +- cause: Cause.pretty(recoveryCause), + +- originalCause: Cause.pretty(cause), + ++ kind: "provider.turn.start.failed", + ++ summary: "Provider turn start failed", + ++ detail, + ++ turnId: null, + ++ createdAt: event.payload.createdAt, + + }), + + ), + + ); + +- if (isCompactCommand) { + +- if (nonCompactUserMessageCount === 0) { + +- return yield* appendTurnStartFailure( + +- "Context compaction failed", + +- "Context compaction requires an existing conversation.", + +- ); + +- } + +- const latestThread = yield* resolveThread(event.payload.threadId); + +- if ( + +- compactingThreadIds.has(event.payload.threadId) || + +- latestThread?.session?.status === "starting" || + +- latestThread?.session?.status === "running" + +- ) { + +- yield* appendTurnStartFailure( + +- "Context compaction failed", + +- "Context compaction is unavailable while a provider turn is running.", + +- ); + +- return; + +- } + +- compactingThreadIds.add(event.payload.threadId); + +- yield* Effect.gen(function* () { + +- yield* ensureSessionForThread( + +- event.payload.threadId, + +- event.payload.createdAt, + +- event.payload.modelSelection !== undefined + +- ? { modelSelection: event.payload.modelSelection, pendingTurnStart: true } + +- : { pendingTurnStart: true }, + +- ); + +- compactionSessionEnsured = true; + +- if (event.payload.modelSelection !== undefined) { + +- threadModelSelections.set(event.payload.threadId, event.payload.modelSelection); + +- } + +- yield* providerService.compactThread( + +- event.payload.threadId, + +- event.payload.modelSelection, + +- event.payload.messageId, + +- ); + +- }).pipe( + +- Effect.andThen(restoreCompaction(event.payload.threadId, true)), + +- Effect.catchCause(recoverCompactionFailure), + +- Effect.ensuring(Effect.sync(() => void compactingThreadIds.delete(event.payload.threadId))), + +- Effect.forkScoped, + +- ); + +- return; + +- } + +- if (compactingThreadIds.has(event.payload.threadId)) { + +- return yield* appendTurnStartFailure( + +- "Provider turn start failed", + +- "Wait for context compaction to finish before sending another message.", + +- ); + +- } + ++ }; + ++ + const sendTurnRequest = yield* buildSendTurnRequestForThread({ + threadId: event.payload.threadId, + messageText: message.text, + @@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Eff + + yield* providerService + .sendTurn(sendTurnRequest.value) + -- .pipe(Effect.catchCause(recoverTurnStartFailure), Effect.forkScoped); + +- .pipe(Effect.asVoid, Effect.catchCause(recoverTurnStartFailure), Effect.forkScoped); + + .pipe(Effect.catchCause(handleTurnStartFailure), Effect.forkScoped); + }); + + const processTurnInterruptRequested = Effect.fn("processTurnInterruptRequested")(function* ( + +@@ apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: const make = Effect.gen(function* () { + + } + + + + const now = event.payload.createdAt; + +- const wasCompacting = compactingThreadIds.has(thread.id); + +- stoppingThreadIds.add(thread.id); + +- const clearStopping = Effect.sync(() => void stoppingThreadIds.delete(thread.id)); + +- yield* ( + +- thread.session && thread.session.status !== "stopped" + +- ? providerService.stopSession({ threadId: thread.id }) + +- : Effect.void + +- ).pipe( + +- Effect.matchCauseEffect({ + +- onFailure: (cause) => { + +- if (Cause.hasInterruptsOnly(cause)) { + +- return Effect.interrupt; + +- } + +- const detail = formatFailureDetail(cause); + +- return Effect.sync(() => { + +- stoppingThreadIds.delete(thread.id); + +- return wasCompacting && !compactingThreadIds.has(thread.id); + +- }).pipe( + +- Effect.flatMap((compactionSettled) => + +- compactionSettled ? restoreCompaction(thread.id) : Effect.void, + +- ), + +- Effect.andThen( + +- appendProviderFailureActivity({ + +- threadId: thread.id, + +- kind: "provider.session.stop.failed", + +- summary: "Provider session stop failed", + +- detail, + +- turnId: null, + +- createdAt: now, + +- }), + +- ), + +- ); + +- }, + +- onSuccess: () => + +- setThreadSession({ + +- threadId: thread.id, + +- session: { + +- threadId: thread.id, + +- status: "stopped", + +- providerName: thread.session?.providerName ?? null, + +- ...(thread.session?.providerInstanceId !== undefined + +- ? { providerInstanceId: thread.session.providerInstanceId } + +- : {}), + +- runtimeMode: thread.session?.runtimeMode ?? DEFAULT_RUNTIME_MODE, + +- activeTurnId: null, + +- lastError: thread.session?.lastError ?? null, + +- updatedAt: now, + +- }, + +- createdAt: now, + +- }), + +- }), + +- Effect.ensuring(clearStopping), + +- ); + ++ if (thread.session && thread.session.status !== "stopped") { + ++ yield* providerService.stopSession({ threadId: thread.id }); + ++ } + ++ + ++ yield* setThreadSession({ + ++ threadId: thread.id, + ++ session: { + ++ threadId: thread.id, + ++ status: "stopped", + ++ providerName: thread.session?.providerName ?? null, + ++ ...(thread.session?.providerInstanceId !== undefined + ++ ? { providerInstanceId: thread.session.providerInstanceId } + ++ : {}), + ++ runtimeMode: thread.session?.runtimeMode ?? DEFAULT_RUNTIME_MODE, + ++ activeTurnId: null, + ++ lastError: thread.session?.lastError ?? null, + ++ updatedAt: now, + ++ }, + ++ createdAt: now, + ++ }); + + }); + + + + const processDomainEvent = Effect.fn("processDomainEvent")(function* ( + + ## apps/server/src/provider/Layers/ClaudeProvider.ts ## + @@ apps/server/src/provider/Layers/ClaudeProvider.ts: export const makePendingClaudeProvider = ( + @@ apps/server/src/provider/Layers/CodexAdapter.test.ts: lifecycleLayer("CodexAdapt + -); + + ## apps/server/src/provider/Layers/CodexAdapter.ts ## + +@@ + + * @module CodexAdapterLive + + */ + + import { + +- EventId, + + type CanonicalItemType, + + type CanonicalRequestType, + + type CodexSettings, + +@@ apps/server/src/provider/Layers/CodexAdapter.ts: import { + + type ProviderRuntimeEvent, + + type ProviderRequestKind, + + type ThreadTokenUsageSnapshot, + +- type ToolActivityIcon, + +- type ToolActivityNativeAppReference, + +- type ToolActivitySource, + + type ProviderUserInputAnswers, + + RuntimeItemId, + + RuntimeRequestId, + @@ apps/server/src/provider/Layers/CodexAdapter.ts: import { + ThreadId, + ProviderSendTurnInput, + } from "@t3tools/contracts"; + -import * as Effect from "effect/Effect"; + +-import * as NodeCrypto from "node:crypto"; + -import * as Crypto from "effect/Crypto"; + -import * as Exit from "effect/Exit"; + -import * as Fiber from "effect/Fiber"; + @@ apps/server/src/provider/Layers/CodexAdapter.ts: import { + +} from "../codex/CodexSessionRuntime.ts"; + import { type EventNdjsonLogger, makeEventNdjsonLogger } from "./EventNdjsonLogger.ts"; + import { resolveCodexLaunchArgs } from "./codexLaunchArgs.ts"; + +-import { codexRateLimitsToUpdate } from "./codexUsageLimits.ts"; + const isCodexAppServerProcessExitedError = Schema.is(CodexErrors.CodexAppServerProcessExitedError); + + const isCodexAppServerTransportError = Schema.is(CodexErrors.CodexAppServerTransportError); + + const isCodexSessionRuntimeThreadIdMissingError = Schema.is( + @@ apps/server/src/provider/Layers/CodexAdapter.ts: const isCodexResumeCursorSchema = Schema.is(CodexResumeCursorSchema); + const PROVIDER = ProviderDriverKind.make("codex"); + + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export interface CodexAdapterLi + - readonly scope: Scope.Closeable; + readonly runtime: CodexSessionRuntimeShape; + readonly eventFiber: Fiber.Fiber; + - stopped: boolean; + + readonly turnTokenUsage: CodexTurnTokenUsageState; + @@ apps/server/src/provider/Layers/CodexAdapter.ts: function mapCodexRuntimeError( + method: string, + error: CodexSessionRuntimeError, + @@ apps/server/src/provider/Layers/CodexAdapter.ts: function readPayload( + } + + function trimText(value: string | undefined | null): string | undefined { + -@@ apps/server/src/provider/Layers/CodexAdapter.ts: function normalizeCodexTokenUsage( + +@@ apps/server/src/provider/Layers/CodexAdapter.ts: function trimText(value: string | undefined | null): string | undefined { + + return trimmed && trimmed.length > 0 ? trimmed : undefined; + } + + - function toTurnStatus( + -- value: EffectCodexSchema.V2TurnCompletedNotification["turn"]["status"] | "cancelled", + -+ value: EffectCodexSchema.V2TurnCompletedNotification["turn"]["status"], + - ): "completed" | "failed" | "cancelled" | "interrupted" { + - switch (value) { + - case "completed": + - case "failed": + -- case "cancelled": + - case "interrupted": + - return value; + +-function asUnknownRecord(value: unknown): Record | undefined { + +- return value && typeof value === "object" ? (value as Record) : undefined; + +-} + +- + +-function normalizeMcpIntentTitle(value: unknown): string | undefined { + +- if (typeof value !== "string") return undefined; + +- const normalized = value.trim().replace(/\s+/gu, " "); + +- if (!normalized) return undefined; + +- const characters = Array.from(normalized); + +- return characters.length <= 80 ? normalized : `${characters.slice(0, 79).join("")}…`; + +-} + +- + +-function normalizedHttpUrl(value: unknown): string | undefined { + +- if (typeof value !== "string" || value.length > 4096) return undefined; + +- try { + +- const url = new URL(value); + +- const href = url.href; + +- return (url.protocol === "http:" || url.protocol === "https:") && href.length <= 4096 + +- ? href + +- : undefined; + +- } catch { + +- return undefined; + +- } + +-} + +- + +-function normalizedImageUrl(value: unknown): string | undefined { + +- if (typeof value !== "string" || value.length > 4096) return undefined; + +- try { + +- const url = new URL(value); + +- return url.protocol === "http:" || url.protocol === "https:" || url.protocol === "data:" + +- ? url.href + +- : undefined; + +- } catch { + +- return undefined; + +- } + +-} + +- + +-function normalizedAppId(value: unknown): string | undefined { + +- if (typeof value !== "string") return undefined; + +- const appId = value.trim(); + +- return appId.length > 0 && appId.length <= 512 && /^[A-Za-z0-9._-]+$/u.test(appId) + +- ? appId + +- : undefined; + +-} + +- + +-function normalizedDisplayName(value: unknown): string | undefined { + +- if (typeof value !== "string") return undefined; + +- const displayName = value.trim().replace(/\s+/gu, " "); + +- return displayName && displayName.length <= 160 ? displayName : undefined; + +-} + +- + +-function normalizedSourceKeyPart(value: string): string { + +- return value.trim().toLowerCase(); + +-} + +- + +-function nativeAppSourceKey(appId: string): string { + +- const key = `native-app:${appId.toLowerCase()}`; + +- if (key.length <= 512) return key; + +- const digest = NodeCrypto.createHash("sha256").update(key).digest("hex"); + +- return `${key.slice(0, 512 - digest.length - 1)}:${digest}`; + +-} + +- + +-function browserDisplayName(value: unknown): string | undefined { + +- const normalized = normalizedDisplayName(value)?.toLowerCase(); + +- if (!normalized) return undefined; + +- if (normalized.includes("chrome") || normalized === "chromium") return "Chrome"; + +- if (normalized.includes("edge")) return "Microsoft Edge"; + +- if (normalized.includes("firefox")) return "Firefox"; + +- if (normalized.includes("safari")) return "Safari"; + +- if (normalized.includes("arc")) return "Arc"; + +- if (normalized === "iab" || normalized.includes("in-app")) return "Browser"; + +- return normalizedDisplayName(value); + +-} + +- + +-function browserNativeAppReference(name: string): ToolActivityNativeAppReference | undefined { + +- switch (name) { + +- case "Chrome": + +- return { _tag: "display-name", displayName: "Google Chrome" }; + +- case "Microsoft Edge": + +- case "Firefox": + +- case "Safari": + +- case "Arc": + +- return { _tag: "display-name", displayName: name }; + +- default: + +- return undefined; + +- } + +-} + +- + +-function appDisplayNameFromId(appId: string): string | undefined { + +- const knownNames: Readonly> = { + +- "com.apple.finder": "Finder", + +- "com.apple.safari": "Safari", + +- "com.google.chrome": "Chrome", + +- "com.microsoft.edgemac": "Microsoft Edge", + +- "org.mozilla.firefox": "Firefox", + +- "company.thebrowser.browser": "Arc", + +- }; + +- return knownNames[appId.toLowerCase()]; + +-} + +- + +-function nativeAppReference(value: unknown): ToolActivityNativeAppReference | undefined { + +- const app = asUnknownRecord(value); + +- if (app?.kind === "appId") { + +- const appId = normalizedAppId(app.appId); + +- return appId ? { _tag: "app-id", appId } : undefined; + +- } + +- if (app?.kind === "displayName") { + +- const displayName = normalizedDisplayName(app.displayName); + +- return displayName ? { _tag: "display-name", displayName } : undefined; + +- } + +- return undefined; + +-} + +- + +-function themedLogoIcon( + +- ...records: ReadonlyArray | undefined> + +-): ToolActivityIcon | undefined { + +- for (const record of records) { + +- const logoUrl = normalizedImageUrl(record?.logoUrl); + +- if (!logoUrl) continue; + +- const logoUrlDark = normalizedImageUrl(record?.logoUrlDark ?? record?.logoDarkUrl); + +- return { + +- _tag: "themed-logo", + +- logoUrl, + +- ...(logoUrlDark ? { logoUrlDark } : {}), + +- }; + +- } + +- return undefined; + +-} + +- + +-interface McpToolPresentation { + +- readonly toolSurface?: "browser" | "computer"; + +- readonly toolIcon?: ToolActivityIcon; + +- readonly toolSource?: ToolActivitySource; + +-} + +- + +-function mcpToolPresentation( + +- item: Extract, + +-): McpToolPresentation { + +- const result = asUnknownRecord(item.result); + +- const metadata = asUnknownRecord(result?._meta); + +- const surface = asUnknownRecord(metadata?.["codex/toolSurface"]); + +- const sourceMetadata = asUnknownRecord(metadata?.source); + +- const appContext = asUnknownRecord(item.appContext); + +- const sourceLogo = themedLogoIcon(surface, sourceMetadata, appContext); + +- if (surface?.kind === "browserUse") { + +- const screenshot = asUnknownRecord(surface.screenshot); + +- const browserUse = asUnknownRecord(metadata?.browser_use); + +- const openTabs = Array.isArray(surface.openTabs) ? surface.openTabs : []; + +- const latestOpenTab = openTabs + +- .toReversed() + +- .map(asUnknownRecord) + +- .find((tab) => normalizedHttpUrl(tab?.url) !== undefined); + +- const selectedPage = [ + +- { record: screenshot, url: screenshot?.pageUrl }, + +- { record: browserUse, url: browserUse?.url }, + +- { record: latestOpenTab, url: latestOpenTab?.url }, + +- ] + +- .map((candidate) => ({ ...candidate, pageUrl: normalizedHttpUrl(candidate.url) })) + +- .find((candidate) => candidate.pageUrl !== undefined); + +- const pageUrl = selectedPage?.pageUrl; + +- const faviconUrl = normalizedImageUrl( + +- selectedPage?.record?.faviconUrl ?? selectedPage?.record?.favIconUrl, + +- ); + +- const faviconUrlDark = normalizedImageUrl( + +- selectedPage?.record?.faviconUrlDark ?? selectedPage?.record?.favIconUrlDark, + +- ); + +- const name = + +- browserDisplayName(appContext?.appName) ?? + +- browserDisplayName(surface.browserFamily) ?? + +- browserDisplayName(surface.backend) ?? + +- "Browser"; + +- const nativeBrowserIcon = browserNativeAppReference(name); + +- const sourceIcon = + +- sourceLogo ?? + +- (nativeBrowserIcon ? ({ _tag: "native-app", app: nativeBrowserIcon } as const) : undefined); + +- const sourceKeyPart = normalizedSourceKeyPart(name) || "browser"; + +- return { + +- toolSurface: "browser", + +- ...(pageUrl + +- ? { + +- toolIcon: { + +- _tag: "website", + +- pageUrl, + +- ...(faviconUrl ? { faviconUrl } : {}), + +- ...(faviconUrlDark ? { faviconUrlDark } : {}), + +- } as const, + +- } + +- : {}), + +- toolSource: { + +- key: `browser-use:${sourceKeyPart}`, + +- name, + +- kind: name === "Browser" ? "browser" : "integration", + +- ...(sourceIcon ? { icon: sourceIcon } : {}), + +- }, + +- }; + +- } + +- if (surface?.kind === "computerUse") { + +- const app = nativeAppReference(surface.app); + +- const args = asUnknownRecord(item.arguments); + +- const argumentAppName = + +- normalizedDisplayName(args?.appName) ?? + +- normalizedDisplayName(args?.application) ?? + +- normalizedDisplayName(typeof args?.app === "string" ? args.app : undefined); + +- const name = + +- normalizedDisplayName(appContext?.appName) ?? + +- argumentAppName ?? + +- (app?._tag === "display-name" ? app.displayName : undefined) ?? + +- (app?._tag === "app-id" ? appDisplayNameFromId(app.appId) : undefined) ?? + +- "Computer Use"; + +- const sourceIcon = sourceLogo ?? (app ? ({ _tag: "native-app", app } as const) : undefined); + +- const sourceKey = app + +- ? app._tag === "app-id" + +- ? nativeAppSourceKey(app.appId) + +- : `native-app-name:${normalizedSourceKeyPart(app.displayName)}` + +- : "computer-use"; + +- return { + +- toolSurface: "computer", + +- ...(app ? { toolIcon: { _tag: "native-app", app } as const } : {}), + +- toolSource: { + +- key: sourceKey, + +- name, + +- kind: "computer", + +- ...(sourceIcon ? { icon: sourceIcon } : {}), + +- }, + +- }; + +- } + +- + +- return {}; + +-} + +- + + const FATAL_CODEX_STDERR_SNIPPETS = ["failed to connect to websocket"]; + + + + function isFatalCodexProcessStderrMessage(message: string): boolean { + +@@ apps/server/src/provider/Layers/CodexAdapter.ts: function completeCodexTurnTokenUsage( + + } + + + + function toTurnStatus( + +- value: EffectCodexSchema.V2TurnCompletedNotification["turn"]["status"] | "cancelled", + ++ value: EffectCodexSchema.V2TurnCompletedNotification["turn"]["status"], + + ): "completed" | "failed" | "cancelled" | "interrupted" { + + switch (value) { + + case "completed": + + case "failed": + +- case "cancelled": + + case "interrupted": + + return value; + default: + -@@ apps/server/src/provider/Layers/CodexAdapter.ts: function itemTitle(itemType: CanonicalItemType, item?: CodexLifecycleItem): stri + +@@ apps/server/src/provider/Layers/CodexAdapter.ts: function toCanonicalItemType(raw: string | undefined | null): CanonicalItemType + + return "unknown"; + + } + + + +-function boundedToolArgument(value: unknown): string | undefined { + +- const normalized = typeof value === "string" ? value.trim().replace(/\s+/gu, " ") : ""; + +- if (!normalized) return undefined; + +- return normalized.length <= 48 ? normalized : `${normalized.slice(0, 47)}…`; + +-} + +- + +-function normalizedMcpToolName(value: string): string { + +- return ( + +- value + +- .split(/__|[./:]/u) + +- .at(-1) + +- ?.trim() ?? value.trim() + +- ); + +-} + +- + +-function computerUseToolTitle( + +- item: Extract, + +- presentation: McpToolPresentation, + +-): string | undefined { + +- if (normalizeItemType(item.server) !== "computer use") return undefined; + +- if (item.status === "failed") return undefined; + +- const tool = normalizeItemType(normalizedMcpToolName(item.tool)).replace(/ /gu, "_"); + +- const inProgress = item.status === "inProgress"; + +- const args = asUnknownRecord(item.arguments); + +- const appName = + +- (presentation.toolSource?.kind === "computer" && presentation.toolSource.name !== "Computer Use" + +- ? presentation.toolSource.name + +- : undefined) ?? + +- normalizedDisplayName(args?.appName) ?? + +- normalizedDisplayName(args?.application) ?? + +- normalizedDisplayName(typeof args?.app === "string" ? args.app : undefined); + +- const withApp = (label: string) => (appName ? `${label} in ${appName}` : label); + +- switch (tool) { + +- case "list_apps": + +- return inProgress ? "Listing apps" : "Listed apps"; + +- case "click": + +- return withApp(inProgress ? "Clicking" : "Clicked"); + +- case "drag": + +- return withApp(inProgress ? "Dragging" : "Dragged"); + +- case "get_app_state": + +- case "get_state": + +- return appName + +- ? `${inProgress ? "Looking at" : "Looked at"} ${appName}` + +- : inProgress + +- ? "Looking at the screen" + +- : "Looked at the screen"; + +- case "perform_accessibility_action": + +- case "perform_secondary_action": + +- return inProgress ? "Performing accessibility action" : "Performed accessibility action"; + +- case "press_key": + +- return withApp(inProgress ? "Pressing key" : "Pressed key"); + +- case "scroll": { + +- const direction = boundedToolArgument(args?.direction)?.toLowerCase(); + +- return withApp(`${inProgress ? "Scrolling" : "Scrolled"}${direction ? ` ${direction}` : ""}`); + +- } + +- case "set_value": + +- return withApp(inProgress ? "Setting value" : "Set value"); + +- case "type_text": + +- return withApp(inProgress ? "Typing text" : "Typed text"); + +- default: + +- return undefined; + +- } + +-} + +- + +-function itemTitle( + +- itemType: CanonicalItemType, + +- item?: CodexLifecycleItem, + +- presentation: McpToolPresentation = {}, + +-): string | undefined { + ++function itemTitle(itemType: CanonicalItemType, item?: CodexLifecycleItem): string | undefined { + + if (itemType === "mcp_tool_call" && item?.type === "mcpToolCall") { + +- if (normalizedMcpToolName(item.tool) === "js") { + +- const intentTitle = normalizeMcpIntentTitle(asUnknownRecord(item.arguments)?.title); + +- if (intentTitle) return intentTitle; + +- } + +- const computerUseTitle = computerUseToolTitle(item, presentation); + +- if (computerUseTitle) return computerUseTitle; + + return `${item.server} · ${item.tool}`; + + } + + switch (itemType) { + +@@ apps/server/src/provider/Layers/CodexAdapter.ts: function itemTitle( + } + } + + @@ apps/server/src/provider/Layers/CodexAdapter.ts: function mapItemLifecycle( + } + + - const detail = itemDetail(itemType, item); + +- const toolPresentation = item.type === "mcpToolCall" ? mcpToolPresentation(item) : {}; + +- const title = itemTitle(itemType, item, toolPresentation); + + const detail = itemDetail(item); + const status = + lifecycle === "item.started" + ? "inProgress" + +@@ apps/server/src/provider/Layers/CodexAdapter.ts: function mapItemLifecycle( + + payload: { + + itemType, + + ...(status ? { status } : {}), + +- ...(title ? { title } : {}), + ++ ...(itemTitle(itemType, item) ? { title: itemTitle(itemType, item) } : {}), + + ...(detail ? { detail } : {}), + +- ...toolPresentation, + + ...(event.payload !== undefined ? { data: event.payload } : {}), + + }, + + }; + @@ apps/server/src/provider/Layers/CodexAdapter.ts: function mapToRuntimeEvents( + + if (!item) { + + return []; + } + +- if (item.type === "agentMessage" && item.delivery === "async" && item.questions?.length) { + +- return [ + +- { + +- ...runtimeEventBase(event, canonicalThreadId), + +- type: "user-input.requested", + +- requestId: RuntimeRequestId.make(`codex-async:${canonicalThreadId}:${item.id}`), + +- eventId: EventId.make(`codex-async:${canonicalThreadId}:${item.id}`), + +- payload: { + +- responseMode: "message", + +- questions: item.questions.map((question, index) => ({ + +- id: String(index), + +- header: "Question", + +- question: question.title, + +- options: (question.options ?? []).map((label) => ({ label, description: "" })), + +- allowCustomAnswer: true, + +- multiSelect: false, + +- })), + +- }, + +- }, + +- ]; + +- } + const itemType = toCanonicalItemType(item.type); + if (itemType === "plan") { + - const detail = itemDetail(itemType, item); + @@ apps/server/src/provider/Layers/CodexAdapter.ts: function mapToRuntimeEvents( + if (!detail) { + return []; + } + +@@ apps/server/src/provider/Layers/CodexAdapter.ts: function mapToRuntimeEvents( + + ]; + + } + + const completed = mapItemLifecycle(event, canonicalThreadId, "item.completed"); + +- if (!completed || itemType !== "context_compaction") { + +- return completed ? [completed] : []; + +- } + +- return [ + +- completed, + +- { + +- ...runtimeEventBase(event, canonicalThreadId), + +- eventId: EventId.make(`${event.id}:thread-compacted`), + +- type: "thread.state.changed", + +- payload: { state: "compacted" }, + +- }, + +- ]; + ++ return completed ? [completed] : []; + + } + + + + if ( + +@@ apps/server/src/provider/Layers/CodexAdapter.ts: function mapToRuntimeEvents( + + } + + + + if (event.method === "account/rateLimits/updated") { + +- const payload = readPayload( + +- EffectCodexSchema.V2AccountRateLimitsUpdatedNotification, + +- event.payload, + +- ); + +- const limits = payload ? codexRateLimitsToUpdate(payload.rateLimits) : undefined; + +- if (!limits) { + ++ if (!readPayload(EffectCodexSchema.V2AccountRateLimitsUpdatedNotification, event.payload)) { + + return []; + + } + + return [ + + { + + type: "account.rate-limits.updated", + + ...runtimeEventBase(event, canonicalThreadId), + +- payload: { limits }, + ++ payload: { + ++ rateLimits: event.payload ?? {}, + ++ }, + + }, + + ]; + + } + @@ apps/server/src/provider/Layers/CodexAdapter.ts: function mapToRuntimeEvents( + type: "thread.realtime.started", + ...runtimeEventBase(event, canonicalThreadId), + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = + - issue: `Expected provider '${PROVIDER}' but received '${input.provider}'.`, + - }); + - } + +- + +- const existing = sessions.get(input.threadId); + +- if (existing && !existing.stopped) { + +- yield* Effect.suspend(() => stopSessionInternal(existing)); + +- } + + const startSession: CodexAdapterShape["startSession"] = Effect.fn("startSession")( + + function* (input) { + + if (input.provider !== undefined && input.provider !== PROVIDER) { + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = + + }); + + } + + -- const existing = sessions.get(input.threadId); + -- if (existing && !existing.stopped) { + -- yield* Effect.suspend(() => stopSessionInternal(existing)); + -- } + -+ const existing = sessions.get(input.threadId); + -+ if (existing && !existing.stopped) { + -+ yield* Effect.suspend(() => stopSessionInternal(existing)); + -+ } + - + - const serviceTier = + - input.modelSelection?.instanceId === boundInstanceId + - ? getCodexServiceTierOptionValue(input.modelSelection) + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = + - } + - : {}), + - }; + +- const turnTokenUsage = makeCodexTurnTokenUsageState(); + - const sessionScope = yield* Scope.make("sequential"); + - let sessionScopeTransferred = false; + - yield* Effect.addFinalizer(() => + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = + - }), + - ), + - ); + ++ const existing = sessions.get(input.threadId); + ++ if (existing && !existing.stopped) { + ++ yield* Effect.suspend(() => stopSessionInternal(existing)); + ++ } + + + +- // Fork into the session scope, not the calling fiber. `forkChild` makes + +- // this a child of `startSession`, and Effect interrupts a fiber's + +- // children when it completes, so the consumer died on return and every + +- // runtime event the session emitted afterwards was dropped. + +- const eventFiber = yield* Stream.runForEach(runtime.events, (event) => + +- Effect.gen(function* () { + +- yield* writeNativeEvent(event); + +- if (event.method === "turn/started" && event.turnId) { + +- if (turnTokenUsage.activeTurnId !== event.turnId) { + +- turnTokenUsage.byTurnId.clear(); + +- turnTokenUsage.activeTurnId = event.turnId; + +- getCodexTurnAccumulator(turnTokenUsage, event.turnId); + +- } + +- } else if (event.method === "thread/tokenUsage/updated") { + +- const payload = readPayload( + +- EffectCodexSchema.V2ThreadTokenUsageUpdatedNotification, + +- event.payload, + +- ); + +- if (payload) { + +- accumulateCodexTurnTokenUsage(turnTokenUsage, payload.turnId, payload.tokenUsage); + +- } + +- } else if (turnTokenUsage.activeTurnId) { + +- const collabPayload = + +- typeof event.payload === "object" && event.payload !== null + +- ? (event.payload as Record) + +- : undefined; + +- const isCollabSpawn = + +- event.method === "collabAgent/started" || + +- (event.method === "collabAgent/activity" && + +- collabPayload?.activityKind === "started"); + +- if (isCollabSpawn && event.turnId === turnTokenUsage.activeTurnId) { + +- getCodexTurnAccumulator(turnTokenUsage, turnTokenUsage.activeTurnId).hasSubagents = + +- true; + +- } + +- } + + const codexSettings = yield* serverSettingsService.getSettings.pipe( + + Effect.map((settings) => settings.providers.codex), + + Effect.mapError( + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = + + ), + + ); + + -- // Fork into the session scope, not the calling fiber. `forkChild` makes + -- // this a child of `startSession`, and Effect interrupts a fiber's + -- // children when it completes, so the consumer died on return and every + -- // runtime event the session emitted afterwards was dropped. + -- const eventFiber = yield* Stream.runForEach(runtime.events, (event) => + -- Effect.gen(function* () { + -- yield* writeNativeEvent(event); + -- const runtimeEvents = mapToRuntimeEvents(event, event.threadId); + +- const runtimeEvents = mapToRuntimeEvents(event, event.threadId).map((runtimeEvent) => { + +- if (runtimeEvent.type === "turn.completed" && runtimeEvent.turnId) { + +- return { + +- ...runtimeEvent, + +- payload: { + +- ...runtimeEvent.payload, + +- tokenUsage: completeCodexTurnTokenUsage( + +- turnTokenUsage, + +- String(runtimeEvent.turnId), + +- runtimeEvent.payload.state === "completed", + +- ), + +- }, + +- } satisfies ProviderRuntimeEvent; + +- } + +- if (runtimeEvent.type === "turn.aborted" && runtimeEvent.turnId) { + +- return { + +- ...runtimeEvent, + +- payload: { + +- ...runtimeEvent.payload, + +- tokenUsage: completeCodexTurnTokenUsage( + +- turnTokenUsage, + +- String(runtimeEvent.turnId), + +- false, + +- ), + +- }, + +- } satisfies ProviderRuntimeEvent; + +- } + +- return runtimeEvent; + ++ const eventFiber = yield* Stream.runForEach(runtime.events, (event) => + ++ Effect.gen(function* () { + ++ yield* writeNativeEvent(event); + ++ const runtimeEvents = mapToRuntimeEvents(event, event.threadId); + ++ if (runtimeEvents.length === 0) { + ++ yield* Effect.logDebug("ignoring unhandled Codex provider event", { + ++ method: event.method, + ++ threadId: event.threadId, + ++ turnId: event.turnId, + ++ itemId: event.itemId, + + }); + - if (runtimeEvents.length === 0) { + - yield* Effect.logDebug("ignoring unhandled Codex provider event", { + - method: event.method, + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = + - ), + - ), + - ); + -+ const eventFiber = yield* Stream.runForEach(runtime.events, (event) => + -+ Effect.gen(function* () { + -+ yield* writeNativeEvent(event); + -+ const runtimeEvents = mapToRuntimeEvents(event, event.threadId); + -+ if (runtimeEvents.length === 0) { + -+ yield* Effect.logDebug("ignoring unhandled Codex provider event", { + -+ method: event.method, + -+ threadId: event.threadId, + -+ turnId: event.turnId, + -+ itemId: event.itemId, + -+ }); + + return; + + } + + yield* Queue.offerAll(runtimeEventQueue, runtimeEvents); + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = + - scope: sessionScope, + - runtime, + - eventFiber, + +- turnTokenUsage, + - stopped: false, + - }); + - sessionScopeTransferred = true; + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = + ), + ); + + +- const compactThread: NonNullable = Effect.fn("compactThread")( + +- function* (threadId) { + +- const session = yield* requireSession(threadId); + +- yield* session.runtime.compactThread.pipe( + +- Effect.mapError((cause) => mapCodexRuntimeError(threadId, "thread/compact/start", cause)), + +- ); + +- }, + +- ); + +- + + const readThread: CodexAdapterShape["readThread"] = (threadId) => + + requireSession(threadId).pipe( + + Effect.flatMap((session) => session.runtime.readThread), + +@@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = Effect.fn("makeCodexAdapter")(function* ( + + ), + + ); + + + - const writeNativeEvent = Effect.fnUntraced(function* (event: ProviderEvent) { + + const writeNativeEvent = Effect.fn("writeNativeEvent")(function* (event: ProviderEvent) { + if (!nativeEventLogger) { + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = + ); + + return { + +@@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = Effect.fn("makeCodexAdapter")(function* ( + + }, + + startSession, + + sendTurn, + +- compactThread, + + interruptTurn, + + readThread, + + rollbackThread, + + - ## apps/server/src/provider/Layers/CodexProvider.ts ## + -@@ apps/server/src/provider/Layers/CodexProvider.ts: import * as CodexErrors from "effect-codex-app-server/errors"; + - import type { + - CodexSettings, + - ServerProvider, + -+ ServerProviderAuth, + -+ ServerProviderSkill, + - ServerProviderState, + - ModelCapabilities, + - ProviderOptionDescriptor, + - ServerProviderModel, + - ServerProviderSkill, + - } from "@t3tools/contracts"; + --import { PREFERRED_DEFAULT_CODEX_MODELS, ServerSettingsError } from "@t3tools/contracts"; + -+import { + -+ Cache, + -+ Data, + -+ Duration, + -+ Effect, + -+ Equal, + -+ FileSystem, + -+ Layer, + -+ Option, + -+ Path, + -+ Result, + -+ Stream, + -+} from "effect"; + -+import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; + + ## apps/server/src/provider/Layers/CursorAdapter.test.ts ## + +@@ apps/server/src/provider/Layers/CursorAdapter.test.ts: const mockAgentPath = NodePath.join(__dirname, "../../../scripts/acp-mock-agent. + + const mockAgentCommand = "node"; + + const mockAgentArgs = [mockAgentPath] as const; + + - import { createModelCapabilities } from "@t3tools/shared/model"; + - import { resolveSpawnCommand } from "@t3tools/shared/shell"; + -@@ apps/server/src/provider/Layers/CodexProvider.ts: import { + - buildServerProvider, + - type ServerProviderDraft, + - } from "../providerSnapshot.ts"; + --import { expandHomePath } from "../../pathExpansion.ts"; + --import packageJson from "../../../package.json" with { type: "json" }; + --const isCodexAppServerSpawnError = Schema.is(CodexErrors.CodexAppServerSpawnError); + -- + --const CODEX_APP_SERVER_PROBE_FORCE_KILL_AFTER = "2 seconds" as const; + -- + --const CODEX_PRESENTATION = { + -- displayName: "Codex", + -- showInteractionModeToggle: true, + --} as const; + -- + --export interface CodexAppServerProviderSnapshot { + -- readonly account: CodexSchema.V2GetAccountResponse; + -- readonly version: string | undefined; + -- readonly models: ReadonlyArray; + -- readonly skills: ReadonlyArray; + -+import { makeManagedServerProvider } from "../makeManagedServerProvider.ts"; + -+import { + -+ formatCodexCliUpgradeMessage, + -+ isCodexCliVersionSupported, + -+ parseCodexCliVersion, + -+} from "../codexCliVersion.ts"; + -+import { + -+ adjustCodexModelsForAccount, + -+ codexAuthSubLabel, + -+ codexAuthSubType, + -+ type CodexAccountSnapshot, + -+} from "../codexAccount.ts"; + -+import { type CodexDiscoverySnapshot, probeCodexDiscovery } from "../codexAppServer.ts"; + -+import { BUILT_IN_CODEX_MODELS, DEFAULT_CODEX_MODEL_CAPABILITIES } from "../codexModels.ts"; + -+import { CodexProvider } from "../Services/CodexProvider.ts"; + -+import { ServerSettingsService } from "../../serverSettings.ts"; + -+import { ServerSettingsError } from "@t3tools/contracts"; + -+ + -+const PROVIDER = "codex" as const; + -+const OPENAI_AUTH_PROVIDERS = new Set(["openai"]); + -+ + -+class CodexDiscoveryCacheKey extends Data.Class<{ + -+ readonly binaryPath: string; + -+ readonly homePath?: string; + -+ readonly cwd: string; + -+}> {} + -+ + -+function buildInitialCodexProviderSnapshot(codexSettings: CodexSettings): ServerProvider { + -+ const checkedAt = new Date().toISOString(); + -+ const models = providerModelsFromSettings( + -+ BUILT_IN_CODEX_MODELS, + -+ PROVIDER, + -+ codexSettings.customModels, + -+ DEFAULT_CODEX_MODEL_CAPABILITIES, + -+ ); + -+ + -+ if (!codexSettings.enabled) { + -+ return buildServerProvider({ + -+ provider: PROVIDER, + -+ enabled: false, + -+ checkedAt, + -+ models, + -+ skills: [], + -+ probe: { + -+ installed: false, + -+ version: null, + -+ status: "warning", + -+ auth: { status: "unknown" }, + -+ message: "Codex is disabled in T3 Code settings.", + -+ }, + -+ }); + -+ } + -+ + -+ return buildServerProvider({ + -+ provider: PROVIDER, + -+ enabled: true, + -+ checkedAt, + -+ models, + -+ skills: [], + -+ probe: { + -+ installed: true, + -+ version: null, + -+ status: "warning", + -+ auth: { status: "unknown" }, + -+ message: "Checking Codex CLI availability...", + -+ }, + -+ }); + - } + - + - const REASONING_EFFORT_LABELS: Readonly> = { + -@@ apps/server/src/provider/Layers/CodexProvider.ts: const probeCodexAppServerProvider = Effect.fn("probeCodexAppServerProvider")(fun + - readonly homePath?: string; + - readonly launchArgs?: string; + - readonly cwd: string; + -- readonly customModels?: ReadonlyArray; + -- readonly environment?: NodeJS.ProcessEnv; + --}) { + -- // `~` is not shell-expanded when env vars are set via `child_process.spawn`, + -- // so `CODEX_HOME=~/.codex_work` would reach codex verbatim and trip + -- // "CODEX_HOME points to '~/.codex_work', but that path does not exist". + -- // Expand here for parity with `CodexTextGeneration`/`CodexSessionRuntime`. + -- const resolvedHomePath = input.homePath ? expandHomePath(input.homePath) : undefined; + -- const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; + -- const environment = { + -- ...input.environment, + -- ...(resolvedHomePath ? { CODEX_HOME: resolvedHomePath } : {}), + -- }; + -- const spawnCommand = yield* resolveSpawnCommand( + -- input.binaryPath, + -- codexAppServerArgs(input.launchArgs), + -- { + -- env: environment, + -- extendEnv: true, + -- }, + -- ); + -- const child = yield* spawner + -- .spawn( + -- ChildProcess.make(spawnCommand.command, spawnCommand.args, { + -- cwd: input.cwd, + -- env: environment, + -- extendEnv: true, + -- forceKillAfter: CODEX_APP_SERVER_PROBE_FORCE_KILL_AFTER, + -- shell: spawnCommand.shell, + -- }), + -- ) + -- .pipe( + -- Effect.mapError( + -- (cause) => + -- new CodexErrors.CodexAppServerSpawnError({ + -- command: `${input.binaryPath} app-server`, + -- cause, + -- }), + -- ), + -- ); + -- const clientContext = yield* Layer.build(CodexClient.layerChildProcess(child)); + -- const client = yield* Effect.service(CodexClient.CodexAppServerClient).pipe( + -- Effect.provide(clientContext), + -+}) => + -+ probeCodexDiscovery(input).pipe( + -+ Effect.timeoutOption(CAPABILITIES_PROBE_TIMEOUT_MS), + -+ Effect.result, + -+ Effect.map((result) => { + -+ if (Result.isFailure(result)) return undefined; + -+ return Option.isSome(result.success) ? result.success.value : undefined; + -+ }), + - ); + - + - const initialize = yield* client.request("initialize", { + -@@ apps/server/src/provider/Layers/CodexProvider.ts: const probeCodexAppServerProvider = Effect.fn("probeCodexAppServerProvider")(fun + - } satisfies CodexAppServerProviderSnapshot; + - }); + - + --export const probeCodexSkillsForCwd = Effect.fn("probeCodexSkillsForCwd")(function* (input: { + -- readonly binaryPath: string; + -- readonly homePath?: string; + -- readonly launchArgs?: string; + -- readonly cwd: string; + -- readonly environment?: NodeJS.ProcessEnv; + --}) { + -- const resolvedHomePath = input.homePath ? expandHomePath(input.homePath) : undefined; + -- const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; + -- const environment = { + -- ...input.environment, + -- ...(resolvedHomePath ? { CODEX_HOME: resolvedHomePath } : {}), + -- }; + -- const spawnCommand = yield* resolveSpawnCommand( + -- input.binaryPath, + -- codexAppServerArgs(input.launchArgs), + -- { env: environment, extendEnv: true }, + -+export const checkCodexProviderStatus = Effect.fn("checkCodexProviderStatus")(function* ( + -+ resolveAccount?: (input: { + -+ readonly binaryPath: string; + -+ readonly homePath?: string; + -+ }) => Effect.Effect, + -+ resolveSkills?: (input: { + -+ readonly binaryPath: string; + -+ readonly homePath?: string; + -+ readonly cwd: string; + -+ }) => Effect.Effect | undefined>, + -+): Effect.fn.Return< + -+ ServerProvider, + -+ ServerSettingsError, + -+ | ChildProcessSpawner.ChildProcessSpawner + -+ | FileSystem.FileSystem + -+ | Path.Path + -+ | ServerSettingsService + -+> { + -+ const codexSettings = yield* Effect.service(ServerSettingsService).pipe( + -+ Effect.flatMap((service) => service.getSettings), + -+ Effect.map((settings) => settings.providers.codex), + - ); + -- const child = yield* spawner + -- .spawn( + -- ChildProcess.make(spawnCommand.command, spawnCommand.args, { + -- cwd: input.cwd, + -- env: environment, + -- extendEnv: true, + -- forceKillAfter: CODEX_APP_SERVER_PROBE_FORCE_KILL_AFTER, + -- shell: spawnCommand.shell, + -- }), + -- ) + -- .pipe( + -- Effect.mapError( + -- (cause) => + -- new CodexErrors.CodexAppServerSpawnError({ + -- command: `${input.binaryPath} app-server`, + -- cause, + -- }), + -- ), + -- ); + -- const clientContext = yield* Layer.build(CodexClient.layerChildProcess(child)); + -- const client = yield* Effect.service(CodexClient.CodexAppServerClient).pipe( + -- Effect.provide(clientContext), + -+ const checkedAt = new Date().toISOString(); + -+ const models = providerModelsFromSettings( + -+ BUILT_IN_CODEX_MODELS, + -+ PROVIDER, + -+ codexSettings.customModels, + -+ DEFAULT_CODEX_MODEL_CAPABILITIES, + - ); + -- yield* client.request("initialize", buildCodexInitializeParams()); + -- yield* client.notify("initialized", undefined); + -- const skillsResponse = yield* client.request("skills/list", { cwds: [input.cwd] }); + -- return parseCodexSkillsListResponse(skillsResponse, input.cwd); + --}); + - + --const emptyCodexModelsFromSettings = (codexSettings: CodexSettings): ServerProvider["models"] => { + -- const models = new Set(); + -- for (const model of codexSettings.customModels) { + -- const trimmed = model.trim(); + -- if (trimmed.length > 0) { + -- models.add(trimmed); + -- } + -+ if (!codexSettings.enabled) { + -+ return buildServerProvider({ + -+ provider: PROVIDER, + -+ enabled: false, + -+ checkedAt, + -+ models, + -+ probe: { + -+ installed: false, + -+ version: null, + -+ status: "warning", + -+ auth: { status: "unknown" }, + -+ message: "Codex is disabled in T3 Code settings.", + -+ }, + -+ }); + - } + -- return Array.from(models, (model) => ({ + -- slug: model, + -- name: model, + -- isCustom: true, + -- capabilities: null, + -- })); + --}; + - + --const makePendingCodexProvider = ( + -- codexSettings: CodexSettings, + --): Effect.Effect => + -- Effect.gen(function* () { + -- const checkedAt = yield* Effect.map(DateTime.now, DateTime.formatIso); + -- const models = emptyCodexModelsFromSettings(codexSettings); + -- + -- if (!codexSettings.enabled) { + -- return buildServerProvider({ + -- presentation: CODEX_PRESENTATION, + -- enabled: false, + -- checkedAt, + -- models, + -- skills: [], + -- probe: { + -- installed: false, + -- version: null, + -- status: "warning", + -- auth: { status: "unknown" }, + -- message: "Codex is disabled in T3 Code settings.", + -- }, + -- }); + -- } + -+ const versionProbe = yield* runCodexCommand(["--version"]).pipe( + -+ Effect.timeoutOption(DEFAULT_TIMEOUT_MS), + -+ Effect.result, + -+ ); + - + -+ if (Result.isFailure(versionProbe)) { + -+ const error = versionProbe.failure; + - return buildServerProvider({ + -- presentation: CODEX_PRESENTATION, + -- enabled: true, + -+ provider: PROVIDER, + -+ enabled: codexSettings.enabled, + - checkedAt, + - models, + -- skills: [], + - probe: { + -- installed: false, + -+ installed: !isCommandMissingCause(error), + - version: null, + -- status: "warning", + -+ status: "error", + - auth: { status: "unknown" }, + -- message: "Codex provider status has not been checked in this session yet.", + -+ message: isCommandMissingCause(error) + -+ ? "Codex CLI (`codex`) is not installed or not on PATH." + -+ : `Failed to execute Codex CLI health check: ${error.message}.`, + - }, + - }); + -- }); + -+ } + -+ + -+ if (Option.isNone(versionProbe.success)) { + -+ return buildServerProvider({ + -+ provider: PROVIDER, + -+ enabled: codexSettings.enabled, + -+ checkedAt, + -+ models, + -+ probe: { + -+ installed: true, + -+ version: null, + -+ status: "error", + -+ auth: { status: "unknown" }, + -+ message: "Codex CLI is installed but failed to run. Timed out while running command.", + -+ }, + -+ }); + -+ } + - + --function accountProbeStatus(account: CodexAppServerProviderSnapshot["account"]): { + -- readonly status: Exclude; + -- readonly auth: ServerProvider["auth"]; + -- readonly message?: string; + --} { + -- const authLabel = codexAccountAuthLabel(account.account); + -- const authEmail = codexAccountEmail(account.account); + -- const auth = { + -- status: account.account ? ("authenticated" as const) : ("unknown" as const), + -- ...(account.account?.type ? { type: account.account?.type } : {}), + -- ...(authLabel ? { label: authLabel } : {}), + -- ...(authEmail ? { email: authEmail } : {}), + -- } satisfies ServerProvider["auth"]; + -- + -- if (account.account) { + -- return { status: "ready", auth }; + -+ const version = versionProbe.success.value; + -+ const parsedVersion = + -+ parseCodexCliVersion(`${version.stdout}\n${version.stderr}`) ?? + -+ parseGenericCliVersion(`${version.stdout}\n${version.stderr}`); + -+ if (version.code !== 0) { + -+ const detail = detailFromResult(version); + -+ return buildServerProvider({ + -+ provider: PROVIDER, + -+ enabled: codexSettings.enabled, + -+ checkedAt, + -+ models, + -+ probe: { + -+ installed: true, + -+ version: parsedVersion, + -+ status: "error", + -+ auth: { status: "unknown" }, + -+ message: detail + -+ ? `Codex CLI is installed but failed to run. ${detail}` + -+ : "Codex CLI is installed but failed to run.", + -+ }, + -+ }); + - } + - + -- if (account.requiresOpenaiAuth) { + -- return { + -- status: "error", + -- auth: { status: "unauthenticated" }, + -- message: "Codex CLI is not authenticated. Run `codex login` and try again.", + -- }; + -+ if (parsedVersion && !isCodexCliVersionSupported(parsedVersion)) { + -+ return buildServerProvider({ + -+ provider: PROVIDER, + -+ enabled: codexSettings.enabled, + -+ checkedAt, + -+ models, + -+ probe: { + -+ installed: true, + -+ version: parsedVersion, + -+ status: "error", + -+ auth: { status: "unknown" }, + -+ message: formatCodexCliUpgradeMessage(parsedVersion), + -+ }, + -+ }); + - } + - + -- return { status: "ready", auth }; + --} + -+ const skills = + -+ (resolveSkills + -+ ? yield* resolveSkills({ + -+ binaryPath: codexSettings.binaryPath, + -+ homePath: codexSettings.homePath, + -+ cwd: process.cwd(), + -+ }).pipe(Effect.orElseSucceed(() => undefined)) + -+ : undefined) ?? []; + - + --export const checkCodexProviderStatus = Effect.fn("checkCodexProviderStatus")(function* ( + -- codexSettings: CodexSettings, + -- probe: (input: { + -- readonly binaryPath: string; + -- readonly homePath?: string; + -- readonly launchArgs?: string; + -- readonly cwd: string; + -- readonly customModels: ReadonlyArray; + -- readonly environment?: NodeJS.ProcessEnv; + -- }) => Effect.Effect< + -- CodexAppServerProviderSnapshot, + -- CodexErrors.CodexAppServerError, + -- ChildProcessSpawner.ChildProcessSpawner | Scope.Scope + -- > = probeCodexAppServerProvider, + -- environment?: NodeJS.ProcessEnv, + --): Effect.fn.Return< + -- ServerProviderDraft, + -- ServerSettingsError, + -- ChildProcessSpawner.ChildProcessSpawner + --> { + -- const resolvedEnvironment = environment ?? process.env; + -- const checkedAt = DateTime.formatIso(yield* DateTime.now); + -- const emptyModels = emptyCodexModelsFromSettings(codexSettings); + -+ if (yield* hasCustomModelProvider) { + -+ return buildServerProvider({ + -+ provider: PROVIDER, + -+ enabled: codexSettings.enabled, + -+ checkedAt, + -+ models, + -+ skills, + -+ probe: { + -+ installed: true, + -+ version: parsedVersion, + -+ status: "ready", + -+ auth: { status: "unknown" }, + -+ message: "Using a custom Codex model provider; OpenAI login check skipped.", + -+ }, + -+ }); + -+ } + - + -- if (!codexSettings.enabled) { + -+ const authProbe = yield* runCodexCommand(["login", "status"]).pipe( + -+ Effect.timeoutOption(DEFAULT_TIMEOUT_MS), + -+ Effect.result, + -+ ); + -+ const account = resolveAccount + -+ ? yield* resolveAccount({ + -+ binaryPath: codexSettings.binaryPath, + -+ homePath: codexSettings.homePath, + -+ }) + -+ : undefined; + -+ const resolvedModels = adjustCodexModelsForAccount(models, account); + -+ + -+ if (Result.isFailure(authProbe)) { + -+ const error = authProbe.failure; + - return buildServerProvider({ + -- presentation: CODEX_PRESENTATION, + -- enabled: false, + -+ provider: PROVIDER, + -+ enabled: codexSettings.enabled, + - checkedAt, + -- models: emptyModels, + -- skills: [], + -+ models: resolvedModels, + -+ skills, + - probe: { + -- installed: false, + -- version: null, + -+ installed: true, + -+ version: parsedVersion, + - status: "warning", + - auth: { status: "unknown" }, + -- message: "Codex is disabled in T3 Code settings.", + -+ message: `Could not verify Codex authentication status: ${error.message}.`, + -+ }, + -+ }); + -+ } + -+ + -+ if (Option.isNone(authProbe.success)) { + -+ return buildServerProvider({ + -+ provider: PROVIDER, + -+ enabled: codexSettings.enabled, + -+ checkedAt, + -+ models: resolvedModels, + -+ skills, + -+ probe: { + -+ installed: true, + -+ version: parsedVersion, + -+ status: "warning", + -+ auth: { status: "unknown" }, + -+ message: "Could not verify Codex authentication status. Timed out while running command.", + -+ }, + -+ }); + -+ } + -+ + -+ const parsed = parseAuthStatusFromOutput(authProbe.success.value); + -+ const authType = codexAuthSubType(account); + -+ const authLabel = codexAuthSubLabel(account); + -+ return buildServerProvider({ + -+ provider: PROVIDER, + -+ enabled: codexSettings.enabled, + -+ checkedAt, + -+ models: resolvedModels, + -+ skills, + -+ probe: { + -+ installed: true, + -+ version: parsedVersion, + -+ status: parsed.status, + -+ auth: { + -+ ...parsed.auth, + -+ ...(authType ? { type: authType } : {}), + -+ ...(authLabel ? { label: authLabel } : {}), + -+ }, + -+ ...(parsed.message ? { message: parsed.message } : {}), + -+ }, + -+ }); + -+}); + -+ + -+const applyCodexDiscoverySnapshot = ( + -+ snapshot: ServerProvider, + -+ discovery: CodexDiscoverySnapshot, + -+): ServerProvider => { + -+ const authType = codexAuthSubType(discovery.account); + -+ const authLabel = codexAuthSubLabel(discovery.account); + -+ + -+ return { + -+ ...snapshot, + -+ auth: { + -+ ...snapshot.auth, + -+ ...(authType ? { type: authType } : {}), + -+ ...(authLabel ? { label: authLabel } : {}), + -+ }, + -+ models: adjustCodexModelsForAccount(snapshot.models, discovery.account), + -+ skills: discovery.skills, + -+ }; + -+}; + -+ + -+const enrichCodexSnapshotViaDiscovery = (input: { + -+ readonly settings: CodexSettings; + -+ readonly snapshot: ServerProvider; + -+ readonly publishSnapshot: (snapshot: ServerProvider) => Effect.Effect; + -+ readonly getDiscovery: (input: { + -+ readonly binaryPath: string; + -+ readonly homePath?: string; + -+ readonly cwd: string; + -+ }) => Effect.Effect; + -+}) => + -+ (input.settings.enabled && input.snapshot.installed + -+ ? input + -+ .getDiscovery({ + -+ binaryPath: input.settings.binaryPath, + -+ homePath: input.settings.homePath, + -+ cwd: process.cwd(), + -+ }) + -+ .pipe( + -+ Effect.flatMap((discovery) => + -+ discovery + -+ ? input.publishSnapshot(applyCodexDiscoverySnapshot(input.snapshot, discovery)) + -+ : Effect.void, + -+ ), + -+ ) + -+ : Effect.void + -+ ).pipe(Effect.catchCause((cause) => Effect.logError(cause))); + -+ + -+export const CodexProviderLive = Layer.effect( + -+ CodexProvider, + -+ Effect.gen(function* () { + -+ const serverSettings = yield* ServerSettingsService; + -+ const fileSystem = yield* FileSystem.FileSystem; + -+ const path = yield* Path.Path; + -+ const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; + -+ const accountProbeCache = yield* Cache.make({ + -+ capacity: 4, + -+ timeToLive: Duration.minutes(5), + -+ lookup: (key: CodexDiscoveryCacheKey) => { + -+ const { binaryPath, homePath, cwd } = key; + -+ return probeCodexCapabilities({ + -+ binaryPath, + -+ cwd, + -+ ...(homePath ? { homePath } : {}), + -+ }); + - }, + - }); + -+ }); + -+ + -+ const getDiscovery = (input: { + -+ readonly binaryPath: string; + -+ readonly homePath?: string; + -+ readonly cwd: string; + -+ }) => Cache.get(accountProbeCache, new CodexDiscoveryCacheKey(input)); + -+ + -+ const checkProvider = checkCodexProviderStatus().pipe( + -+ Effect.provideService(ServerSettingsService, serverSettings), + -+ Effect.provideService(FileSystem.FileSystem, fileSystem), + -+ Effect.provideService(Path.Path, path), + -+ Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), + -+ ); + -+ + -+ return yield* makeManagedServerProvider({ + -+ getSettings: serverSettings.getSettings.pipe( + -+ Effect.map((settings) => settings.providers.codex), + -+ Effect.orDie, + -+ ), + -+ streamSettings: serverSettings.streamChanges.pipe( + -+ Stream.map((settings) => settings.providers.codex), + -+ ), + -+ haveSettingsChanged: (previous, next) => !Equal.equals(previous, next), + -+ buildInitialSnapshot: buildInitialCodexProviderSnapshot, + -+ checkProvider, + -+ enrichSnapshot: ({ settings, snapshot, publishSnapshot }) => + -+ enrichCodexSnapshotViaDiscovery({ + -+ settings, + -+ snapshot, + -+ publishSnapshot, + -+ getDiscovery, + -+ }), + -+ }); + - } + - + - const probeResult = yield* probe({ + - + - ## apps/server/src/provider/Layers/CursorAdapter.test.ts ## + -@@ apps/server/src/provider/Layers/CursorAdapter.test.ts: const mockAgentPath = NodePath.join(__dirname, "../../../scripts/acp-mock-agent. + - const mockAgentCommand = "node"; + - const mockAgentArgs = [mockAgentPath] as const; + - + --async function makeMockAgentWrapper( + -- extraEnv?: Record, + -- options?: { initialDelaySeconds?: number }, + --) { + -- const dir = await NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-acp-mock-")); + -- const wrapperPath = NodePath.join(dir, "fake-agent.sh"); + -+async function makeMockAgentWrapper(extraEnv?: Record) { + -+ const dir = await mkdtemp(path.join(os.tmpdir(), "cursor-acp-mock-")); + -+ const wrapperPath = path.join(dir, "fake-agent.sh"); + - const envExports = Object.entries(extraEnv ?? {}) + - .map(([key, value]) => `export ${key}=${JSON.stringify(value)}`) + - .join("\n"); + - const script = `#!/bin/sh + - ${envExports} + --${options?.initialDelaySeconds ? `sleep ${JSON.stringify(String(options.initialDelaySeconds))}` : ""} + --exec ${JSON.stringify(mockAgentCommand)} ${mockAgentArgs.map((arg) => JSON.stringify(arg)).join(" ")} "$@" + -+exec ${JSON.stringify(bunExe)} ${JSON.stringify(mockAgentPath)} "$@" + - `; + - await NodeFSP.writeFile(wrapperPath, script, "utf8"); + - await NodeFSP.chmod(wrapperPath, 0o755); + -@@ apps/server/src/provider/Layers/CursorAdapter.test.ts: async function readJsonLines(filePath: string) { + - .map((line) => JSON.parse(line) as Record); + +-async function makeMockAgentWrapper( + +- extraEnv?: Record, + +- options?: { initialDelaySeconds?: number }, + +-) { + +- const dir = await NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-acp-mock-")); + +- const wrapperPath = NodePath.join(dir, "fake-agent.sh"); + ++async function makeMockAgentWrapper(extraEnv?: Record) { + ++ const dir = await mkdtemp(path.join(os.tmpdir(), "cursor-acp-mock-")); + ++ const wrapperPath = path.join(dir, "fake-agent.sh"); + + const envExports = Object.entries(extraEnv ?? {}) + + .map(([key, value]) => `export ${key}=${JSON.stringify(value)}`) + + .join("\n"); + + const script = `#!/bin/sh + + ${envExports} + +-${options?.initialDelaySeconds ? `sleep ${JSON.stringify(String(options.initialDelaySeconds))}` : ""} + +-exec ${JSON.stringify(mockAgentCommand)} ${mockAgentArgs.map((arg) => JSON.stringify(arg)).join(" ")} "$@" + ++exec ${JSON.stringify(bunExe)} ${JSON.stringify(mockAgentPath)} "$@" + + `; + + await NodeFSP.writeFile(wrapperPath, script, "utf8"); + + await NodeFSP.chmod(wrapperPath, 0o755); + +@@ apps/server/src/provider/Layers/CursorAdapter.test.ts: async function readJsonLines(filePath: string) { + + .map((line) => JSON.parse(line) as Record); + } + + -async function waitForFileContent(filePath: string, attempts = 40) { + @@ apps/server/src/provider/Layers/CursorAdapter.test.ts: cursorAdapterTestLayer("C + }), + ); + + +- it.effect("sends selected project skills in Cursor's native slash form", () => + +- Effect.gen(function* () { + +- const adapter = yield* CursorAdapter; + +- const settings = yield* ServerSettingsService; + +- const threadId = ThreadId.make("cursor-skill-dispatch"); + +- const workspace = yield* Effect.promise(() => + +- NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-skill-dispatch-")), + +- ); + +- const requestLogPath = NodePath.join(workspace, "requests.ndjson"); + +- const argvLogPath = NodePath.join(workspace, "argv.txt"); + +- const skillDirectory = NodePath.join(workspace, ".cursor", "skills", "review"); + +- yield* Effect.promise(() => NodeFSP.mkdir(skillDirectory, { recursive: true })); + +- yield* Effect.promise(() => + +- NodeFSP.writeFile(NodePath.join(skillDirectory, "SKILL.md"), "# Review\n", "utf8"), + +- ); + +- yield* Effect.promise(() => NodeFSP.writeFile(requestLogPath, "", "utf8")); + +- const wrapperPath = yield* Effect.promise(() => + +- makeProbeWrapper(requestLogPath, argvLogPath), + +- ); + +- yield* settings.updateSettings({ providers: { cursor: { binaryPath: wrapperPath } } }); + +- + +- yield* adapter.startSession({ + +- threadId, + +- provider: ProviderDriverKind.make("cursor"), + +- cwd: workspace, + +- runtimeMode: "full-access", + +- modelSelection: { instanceId: ProviderInstanceId.make("cursor"), model: "default" }, + +- }); + +- yield* adapter.sendTurn({ + +- threadId, + +- input: "please $review this", + +- attachments: [], + +- }); + +- const snapshot = yield* adapter.readThread(threadId); + +- assert.deepStrictEqual( + +- snapshot.turns.map((turn) => turn.items), + +- [ + +- [ + +- { + +- prompt: [{ type: "text", text: "please /review this" }], + +- result: { stopReason: "end_turn" }, + +- }, + +- ], + +- ], + +- ); + +- yield* adapter.stopSession(threadId); + +- + +- const requests = yield* Effect.promise(() => readJsonLines(requestLogPath)); + +- const promptRequests = requests.filter((entry) => entry.method === "session/prompt"); + +- assert.deepStrictEqual( + +- promptRequests.map( + +- (request) => (request.params as Record | undefined)?.prompt, + +- ), + +- [ + +- [ + +- { type: "text", text: "please /review this" }, + +- { type: "text", text: buildRuntimeInstructions({ harness: "Cursor" }) }, + +- ], + +- ], + +- ); + +- }), + +- ); + +- + - it.effect("steers a running turn instead of opening a new one on mid-turn sendTurn", () => + - Effect.gen(function* () { + - const adapter = yield* CursorAdapter; + @@ apps/server/src/provider/Layers/CursorAdapter.test.ts: cursorAdapterTestLayer("C + it.effect( + "streams ACP tool calls and approvals on the active turn in approval-required mode", + () => + +@@ apps/server/src/provider/Layers/CursorAdapter.test.ts: cursorAdapterTestLayer("CursorAdapterLive", (it) => { + + ); + + assert.isDefined(permissionResponse); + + + +- const argvRuns = yield* Effect.promise(() => readArgvLog(argvLogPath)); + +- assert.deepStrictEqual(argvRuns, [["--force", "acp"]]); + +- + + yield* adapter.stopSession(threadId); + + }), + + ); + @@ apps/server/src/provider/Layers/CursorAdapter.test.ts: cursorAdapterTestLayer("CursorAdapterLive", (it) => { + }), + ); + @@ apps/server/src/provider/Layers/CursorAdapter.test.ts: cursorAdapterTestLayer("C + it.effect("switches model in-session via session/set_config_option", () => + Effect.gen(function* () { + const adapter = yield* CursorAdapter; + +@@ apps/server/src/provider/Layers/CursorAdapter.test.ts: cursorAdapterTestLayer("CursorAdapterLive", (it) => { + + + + const argvRuns = yield* Effect.promise(() => readArgvLog(argvLogPath)); + + assert.lengthOf(argvRuns, 1, "session should not restart — only one spawn"); + +- assert.deepStrictEqual(argvRuns[0], ["--force", "acp"]); + ++ assert.deepStrictEqual(argvRuns[0], ["acp"]); + + + + const requests = yield* Effect.promise(() => readJsonLines(requestLogPath)); + + const setConfigRequests = requests.filter( + + ## apps/server/src/provider/Layers/CursorAdapter.ts ## + @@ + @@ apps/server/src/provider/Layers/CursorAdapter.ts: import { + import type * as EffectAcpSchema from "effect-acp/schema"; + + import { resolveAttachmentPath } from "../../attachmentStore.ts"; + +@@ apps/server/src/provider/Layers/CursorAdapter.ts: import { + + import { type CursorAdapterShape } from "../Services/CursorAdapter.ts"; + + import { resolveCursorAcpBaseModelId } from "./CursorProvider.ts"; + + import { type EventNdjsonLogger, makeEventNdjsonLogger } from "./EventNdjsonLogger.ts"; + +-import { + +- discoverCursorSkills, + +- hasCursorSkillMention, + +- rewriteCursorSkillMentions, + +-} from "../Drivers/CursorSkills.ts"; + + const encodeUnknownJsonStringExit = Schema.encodeUnknownExit(Schema.fromJsonString(Schema.Unknown)); + + + + const PROVIDER = ProviderDriverKind.make("cursor"); + @@ apps/server/src/provider/Layers/CursorAdapter.ts: interface PendingUserInput { + interface CursorSessionContext { + readonly threadId: ThreadId; + @@ apps/server/src/provider/Layers/CursorAdapter.ts: interface PendingUserInput { + notificationFiber: Fiber.Fiber | undefined; + readonly pendingApprovals: Map; + readonly pendingUserInputs: Map; + + readonly turns: Array<{ id: TurnId; items: Array }>; + + lastPlanFingerprint: string | undefined; + + activeTurnId: TurnId | undefined; + +- cursorSkillNames: ReadonlySet | undefined; + + /** Number of sendTurn prompts currently in flight or being prepared. + + * >0 means a turn is actively running, so a new sendTurn is a steer that + + * continues it, and only the last remaining prompt settles the turn. */ + @@ apps/server/src/provider/Layers/CursorAdapter.ts: function resolveRequestedModeId(input: { + ); + } + @@ apps/server/src/provider/Layers/CursorAdapter.ts: export function makeCursorAdap + - ...(options?.environment ? { environment: options.environment } : {}), + - childProcessSpawner, + - cwd, + +- runtimeMode: input.runtimeMode, + - ...(resumeSessionId ? { resumeSessionId } : {}), + - clientInfo: { name: "t3-code", version: "0.0.0" }, + - ...(mcpSession + @@ apps/server/src/provider/Layers/CursorAdapter.ts: export function makeCursorAdap + - turns: [], + - lastPlanFingerprint: undefined, + - activeTurnId: undefined, + +- cursorSkillNames: undefined, + - promptsInFlight: 0, + - stopped: false, + - }; + @@ apps/server/src/provider/Layers/CursorAdapter.ts: export function makeCursorAdap + + if (steeringTurnId === undefined) { + yield* offerRuntimeEvent({ + +@@ apps/server/src/provider/Layers/CursorAdapter.ts: export function makeCursorAdapter( + + } + + + + const promptParts: Array = []; + +- const rawPrompt = input.input?.trim() ?? ""; + +- if (rawPrompt) { + +- let cursorSkillNames = ctx.cursorSkillNames; + +- if (hasCursorSkillMention(rawPrompt) && cursorSkillNames === undefined) { + +- const skills = yield* discoverCursorSkills( + +- ctx.session.cwd, + +- options?.environment, + +- ).pipe( + +- Effect.provideService(FileSystem.FileSystem, fileSystem), + +- Effect.provideService(Path.Path, path), + +- ); + +- cursorSkillNames = new Set( + +- skills + +- .filter((skill) => skill.enabled && skill.userInvocable !== false) + +- .map((skill) => skill.name), + +- ); + +- ctx.cursorSkillNames = cursorSkillNames; + +- } + +- const prompt = cursorSkillNames + +- ? rewriteCursorSkillMentions(rawPrompt, cursorSkillNames) + +- : rawPrompt; + +- promptParts.push({ type: "text", text: prompt }); + ++ if (input.input?.trim()) { + ++ promptParts.push({ type: "text", text: input.input.trim() }); + + } + + if (input.attachments && input.attachments.length > 0) { + + for (const attachment of input.attachments) { + @@ apps/server/src/provider/Layers/CursorAdapter.ts: export function makeCursorAdapter( + Effect.gen(function* () { + const ctx = yield* requireSession(threadId); + @@ apps/server/src/provider/Layers/CursorProvider.test.ts + getCursorParameterizedModelPickerUnsupportedMessage, + parseCursorAboutOutput, + @@ apps/server/src/provider/Layers/CursorProvider.test.ts: import { + + resolveCursorAcpBaseModelId, + resolveCursorAcpConfigUpdates, + } from "./CursorProvider.ts"; + - + +-import { + +- discoverCursorSkills, + +- hasCursorSkillMention, + +- probeCursorSkills, + +- rewriteCursorSkillMentions, + +-} from "../Drivers/CursorSkills.ts"; + +- + -const runNode = ( + - effect: Effect.Effect< + - A, + @@ apps/server/src/provider/Layers/CursorProvider.test.ts: import { + - }), + - }; + -}); + -- + + + const parameterizedGpt54ConfigOptions = [ + { + - type: "select", + @@ apps/server/src/provider/Layers/CursorProvider.test.ts: const parameterizedClaudeConfigOptions = [ + }, + ] satisfies ReadonlyArray; + + -const parameterizedClaudeModelOptionConfigOptions = [ + -- { + -- type: "select", + ++const sessionNewCursorConfigOptions = [ + + { + + type: "select", + - currentValue: "claude-opus-4-6", + - options: [{ name: "Opus 4.6", value: "claude-opus-4-6" }], + - category: "model", + - id: "model", + - name: "Model", + - }, + -+const sessionNewCursorConfigOptions = [ + - { + - type: "select", + +- { + +- type: "select", + - currentValue: "high", + + currentValue: "agent", + options: [ + @@ apps/server/src/provider/Layers/CursorProvider.test.ts: const parameterizedClaud + - `Install or enable the Cursor CLI, make sure \`${missingCursorBinaryPath}\` is on PATH, then restart T3 Code.`, + - "See https://cursor.com/docs/cli/installation.", + -].join(" "); + +- + +-describe("Cursor skills", () => { + +- it("discovers recursive project skills with project precedence", async () => + +- await runNode( + +- Effect.gen(function* () { + +- const fileSystem = yield* FileSystem.FileSystem; + +- const path = yield* Path.Path; + +- const userHome = yield* fileSystem.makeTempDirectory({ + +- directory: NodeOS.tmpdir(), + +- prefix: "cursor-skills-home-", + +- }); + +- const workspace = yield* fileSystem.makeTempDirectory({ + +- directory: NodeOS.tmpdir(), + +- prefix: "cursor-skills-workspace-", + +- }); + +- const writeSkill = Effect.fn("writeCursorSkill")(function* ( + +- root: string, + +- name: string, + +- contents: string, + +- ) { + +- const skillDirectory = path.join(root, name); + +- yield* fileSystem.makeDirectory(skillDirectory, { recursive: true }); + +- yield* fileSystem.writeFileString(path.join(skillDirectory, "SKILL.md"), contents); + +- }); + +- + +- yield* writeSkill( + +- path.join(userHome, ".cursor", "skills"), + +- "review", + +- "---\ndescription: user review\n---\n", + +- ); + +- yield* writeSkill( + +- path.join(workspace, ".agents", "skills", "nested"), + +- "review", + +- "---\nname: Review changes\ndescription: project review\n---\n", + +- ); + +- yield* writeSkill( + +- path.join(workspace, ".cursor", "skills"), + +- "internal", + +- "---\nuser-invocable: false\n---\n", + +- ); + +- yield* writeSkill( + +- path.join(workspace, ".cursor", "skills"), + +- "oversized", + +- "x".repeat(1_000_001), + +- ); + +- yield* fileSystem.makeDirectory(path.join(userHome, ".codex"), { recursive: true }); + +- yield* fileSystem.writeFileString( + +- path.join(userHome, ".codex", "skills"), + +- "not a directory", + +- ); + +- + +- const skills = yield* discoverCursorSkills(workspace, { HOME: userHome }); + +- expect(skills).toEqual([ + +- { + +- name: "internal", + +- path: path.join(workspace, ".cursor", "skills", "internal", "SKILL.md"), + +- scope: "project", + +- enabled: true, + +- userInvocable: false, + +- }, + +- { + +- name: "oversized", + +- path: path.join(workspace, ".cursor", "skills", "oversized", "SKILL.md"), + +- scope: "project", + +- enabled: true, + +- }, + +- { + +- name: "review", + +- displayName: "Review changes", + +- description: "project review", + +- path: path.join(workspace, ".agents", "skills", "nested", "review", "SKILL.md"), + +- scope: "project", + +- enabled: true, + +- }, + +- ]); + +- expect( + +- (yield* probeCursorSkills(workspace, { HOME: userHome }).pipe(Effect.result))._tag, + +- ).toBe("Failure"); + +- }), + +- )); + +- + +- it("rewrites only discovered skill mentions into Cursor slash invocations", () => { + +- expect(hasCursorSkillMention("use $Review_Pr:V2 here")).toBe(true); + +- expect(hasCursorSkillMention("please $review this")).toBe(true); + +- expect( + +- rewriteCursorSkillMentions("use $review, keep $HOME and 5$review", new Set(["review"])), + +- ).toBe("use $review, keep $HOME and 5$review"); + +- expect(rewriteCursorSkillMentions("please $review this", new Set(["review"]))).toBe( + +- "please /review this", + +- ); + +- }); + +-}); + - + describe("getCursorFallbackModels", () => { + it("does not publish any built-in cursor models before ACP discovery", () => { + @@ apps/server/src/provider/Layers/ProviderAdapterRegistry.test.ts: const fakeOpenC + - getSnapshot: Effect.succeed({} as unknown as ServerProvider), + - refresh: Effect.succeed({} as unknown as ServerProvider), + - streamChanges: Stream.empty, + +- applyUsageLimits: () => Effect.void, + - }, + - adapter, + - textGeneration: {} as unknown as TextGeneration.TextGeneration["Service"], + @@ apps/server/src/provider/acp/AcpRuntimeModel.test.ts: describe("AcpRuntimeModel" + + ## apps/server/src/provider/acp/AcpRuntimeModel.ts ## + @@ apps/server/src/provider/acp/AcpRuntimeModel.ts: export function parseSessionUpdateEvent(params: EffectAcpSchema.SessionNotificat + - + - switch (upd.sessionUpdate) { + + break; + + } + case "current_mode_update": { + - modeId = upd.currentModeId.trim(); + - if (modeId) { + @@ apps/server/src/provider/acp/AcpRuntimeModel.ts: export function parseSessionUpd + case "plan": { + + ## apps/server/src/provider/acp/AcpSessionRuntime.ts ## + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: import * as Crypto from "effect/Crypto"; + + import * as Deferred from "effect/Deferred"; + + import * as Duration from "effect/Duration"; + + import * as Effect from "effect/Effect"; + +-import * as Exit from "effect/Exit"; + + import * as Fiber from "effect/Fiber"; + + import * as Layer from "effect/Layer"; + + import * as Option from "effect/Option"; + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: import { resolveSpawnCommand } from "@t3tools/shared/shell"; + + import { + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: import { + function formatConfigOptionValue(value: string | boolean): string { + return JSON.stringify(value); + } + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export interface AcpSessionEventStreamBarrier { + + readonly acknowledge: Deferred.Deferred; + + } + + + +-export type AcpSessionRuntimeEvent = + +- | AcpParsedSessionEvent + +- | AcpSessionEventStreamBarrier + +- | { + +- readonly _tag: "ConnectionTerminated"; + +- readonly error: EffectAcpErrors.AcpError; + +- }; + ++export type AcpSessionRuntimeEvent = AcpParsedSessionEvent | AcpSessionEventStreamBarrier; + + + + const defaultSessionLoadTimeout = Duration.seconds(90); + + const defaultSessionLoadReplayIdleGap = Duration.seconds(2); + +-const defaultCancelTimeout = Duration.seconds(15); + +-const maxStartupMetadataUpdates = 32; + +-// Antigravity can emit an accepted 16 KiB Google authorization URL on stderr. + +-const maxStderrChunkLength = 32_768; + + + + export interface AcpSpawnInput { + + readonly command: string; + + readonly args: ReadonlyArray; + + readonly cwd?: string; + + readonly env?: NodeJS.ProcessEnv; + +- readonly extendEnv?: boolean; + + } + + + + export interface AcpSessionRuntimeOptions { + + readonly spawn: AcpSpawnInput; + + readonly cwd: string; + + readonly resumeSessionId?: string; + +- readonly resumeMethod?: "load" | "resume"; + + readonly sessionLoadTimeout?: Duration.Input; + + readonly sessionLoadReplayIdleGap?: Duration.Input; + +- /** Native cancellation waits for the prompt response and the getEvents consumer to drain. */ + +- readonly cancelBehavior?: "interrupt" | "wait-for-prompt"; + +- readonly cancelTimeout?: Duration.Input; + + readonly clientCapabilities?: EffectAcpSchema.InitializeRequest["clientCapabilities"]; + + readonly clientInfo: { + + readonly name: string; + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export interface AcpSessionRuntimeOptions { + + }; + + readonly authMethodId: string; + + readonly mcpServers?: ReadonlyArray; + +- /** Extra workspace roots the agent may read and write besides `cwd`. */ + +- readonly additionalDirectories?: ReadonlyArray; + +- /** Transforms provider stdout before protocol parsing and protocol logging. */ + +- readonly transformStdout?: EffectAcpClient.AcpClientOptions["transformStdout"]; + +- /** Normalizes provider-specific fields before notification queues or runtime state retain them. */ + +- readonly transformSessionUpdate?: ( + +- notification: EffectAcpSchema.SessionNotification, + +- ) => EffectAcpSchema.SessionNotification; + +- /** Receives bounded stderr chunks. Redact secrets before logging. A failure closes the runtime. */ + +- readonly onStderr?: (text: string) => Effect.Effect; + + readonly requestLogger?: (event: AcpSessionRequestLogEvent) => Effect.Effect; + + readonly protocolLogging?: { + + readonly logIncoming?: boolean; + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export interface AcpSessionRuntimeStartResult { + readonly modelConfigId: string | undefined; + } + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export interface AcpSessionRu + - * Concurrent calls share the same in-flight startup and a failed startup may be retried. + - */ + - readonly start: () => Effect.Effect; + -- /** Stream of parsed ACP session events emitted after startup. */ + +- /** Stream of parsed root-session events and connection failures. */ + - readonly getEvents: () => Stream.Stream; + -- /** Waits until the current event consumer has processed every queued event. */ + +- /** Waits for queued events to be processed, or for the runtime scope to close. */ + - readonly drainEvents: Effect.Effect; + - /** Latest mode state observed from session setup and `session/update` notifications. */ + - readonly getModeState: Effect.Effect; + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export interface AcpSessionRu + + interface AcpStartedState extends AcpSessionRuntimeStartResult {} + + -@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: interface EnsureActiveAssistantSegmentResult { + + readonly startedEvent?: Extract; + + } + + + +-interface AcpActivePrompt { + +- readonly fiber: Fiber.Fiber; + +- readonly completed: Deferred.Deferred; + +-} + +- + + export const make = ( + + options: AcpSessionRuntimeOptions, + ): Effect.Effect< + AcpSessionRuntime["Service"], + EffectAcpErrors.AcpError, + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + Effect.mapError( + (cause) => + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + - }); + - }), + + const assistantSegmentRef = yield* Ref.make({ nextSegmentIndex: 0 }); + + const configOptionsRef = yield* Ref.make(sessionConfigOptionsFromSetup(undefined)); + + const startStateRef = yield* Ref.make({ _tag: "NotStarted" }); + +- const startupMetadataRef = yield* Ref.make>( + +- [], + +- ); + +- const notificationSemaphore = yield* Semaphore.make(1); + +- const terminationErrorRef = yield* Ref.make>( + +- Option.none(), + +- ); + +- const stoppingRef = yield* Ref.make(false); + +- const stderrFailure = yield* Deferred.make(); + +- const runtimeClosed = yield* Deferred.make(); + + const promptSerializationSemaphore = yield* Semaphore.make(1); + +- const promptDispatchSemaphore = yield* Semaphore.make(1); + +- const activePromptRef = yield* Ref.make>(Option.none()); + ++ const activePromptFiberRef = yield* Ref.make< + ++ Option.Option> + ++ >(Option.none()); + + const sessionLoadGateRef = yield* Ref.make>(Option.none()); + + + +- const ensureConnected = Effect.gen(function* () { + +- const error = yield* Ref.get(terminationErrorRef); + +- if (Option.isSome(error)) { + +- return yield* error.value; + +- } + +- if (yield* Ref.get(stoppingRef)) { + +- return yield* new EffectAcpErrors.AcpTransportError({ + +- detail: "The ACP session runtime is closed.", + +- cause: undefined, + +- }); + +- } + +- }); + +- + +- const recordTermination = Effect.fn("AcpSessionRuntime.recordTermination")(function* ( + +- error: EffectAcpErrors.AcpError, + +- ) { + +- if (yield* Ref.get(stoppingRef)) { + +- return; + +- } + +- const firstTermination = yield* Ref.modify(terminationErrorRef, (current) => + +- Option.isSome(current) + +- ? ([false, current] as const) + +- : ([true, Option.some(error)] as const), + +- ); + +- if (!firstTermination) { + +- return; + +- } + +- yield* closeActiveAssistantSegment({ queue: eventQueue, assistantSegmentRef }); + +- yield* Queue.offer(eventQueue, { _tag: "ConnectionTerminated", error }); + +- }); + +- + + const logRequest = (event: AcpSessionRequestLogEvent) => + + options.requestLogger ? options.requestLogger(event) : Effect.void; + + + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + ): Effect.Effect => + + logRequest({ method, payload, status: "started" }).pipe( + + Effect.flatMap(() => + +- (options.onStderr + +- ? Effect.raceFirst(effect, Deferred.await(stderrFailure)) + +- : effect + +- ).pipe( + ++ effect.pipe( + + Effect.tap((result) => + + logRequest({ + + method, + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + ), + + ); + + + +- const spawnCommand = yield* resolveSpawnCommand(options.spawn.command, options.spawn.args, { + +- ...(options.spawn.env ? { env: options.spawn.env } : {}), + +- extendEnv: options.spawn.extendEnv ?? true, + +- }); + ++ const spawnCommand = yield* resolveSpawnCommand( + ++ options.spawn.command, + ++ options.spawn.args, + ++ options.spawn.env ? { env: options.spawn.env, extendEnv: true } : {}, + ++ ); + + const child = yield* spawner + + .spawn( + + ChildProcess.make(spawnCommand.command, spawnCommand.args, { + + ...(options.spawn.cwd ? { cwd: options.spawn.cwd } : {}), + +- ...(options.spawn.env ? { env: options.spawn.env } : {}), + +- extendEnv: options.spawn.extendEnv ?? true, + ++ ...(options.spawn.env ? { env: options.spawn.env, extendEnv: true } : {}), + + shell: spawnCommand.shell, + + }), + + ) + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + ), + + ); + + + +- yield* child.stderr.pipe( + +- Stream.decodeText(), + +- Stream.runForEach((chunk) => + +- (options.onStderr + +- ? options.onStderr(chunk.slice(-maxStderrChunkLength)) + +- : Effect.void + +- ).pipe( + +- Effect.catch((error) => + +- Effect.gen(function* () { + +- yield* Deferred.fail(stderrFailure, error); + +- yield* recordTermination(error); + +- yield* child.kill({ forceKillAfter: "1 second" }).pipe(Effect.ignore); + +- }), + +- ), + +- ), + +- ), + +- Effect.ignore, + +- Effect.forkIn(runtimeScope), + +- ); + +- + + const acpContext = yield* Layer.build( + + EffectAcpClient.layerChildProcess(child, { + +- ...(options.transformStdout ? { transformStdout: options.transformStdout } : {}), + +- ...(options.transformSessionUpdate + +- ? { transformSessionUpdate: options.transformSessionUpdate } + +- : {}), + +- onTermination: recordTermination, + + ...(options.protocolLogging?.logIncoming !== undefined + + ? { logIncoming: options.protocolLogging.logIncoming } + + : {}), + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + + + const acp = yield* Effect.service(EffectAcpClient.AcpClient).pipe(Effect.provide(acpContext)); + + + +- const processSessionUpdate = (notification: EffectAcpSchema.SessionNotification) => + +- handleSessionUpdate({ + +- queue: eventQueue, + +- modeStateRef, + +- configOptionsRef, + +- toolCallsRef, + +- assistantSegmentRef, + +- assistantItemRuntimeId, + +- params: notification, + +- }); + +- + + yield* acp.handleSessionUpdate((notification) => + +- notificationSemaphore.withPermit( + +- Effect.gen(function* () { + +- if (Option.isSome(yield* Ref.get(terminationErrorRef))) { + +- return; + +- } + +- const gate = yield* Ref.get(sessionLoadGateRef); + +- if ( + +- Option.isSome(gate) && + +- gate.value.active && + +- notification.sessionId === options.resumeSessionId + +- ) { + +- const lastActivityAtMillis = yield* Clock.currentTimeMillis; + +- yield* Ref.set( + +- sessionLoadGateRef, + +- Option.some({ + +- ...gate.value, + +- lastActivityAtMillis, + +- }), + +- ); + +- } + +- if (sessionUpdateIsReplay(notification)) { + +- return; + +- } + +- const startState = yield* Ref.get(startStateRef); + +- if (startState._tag === "Starting") { + +- if (isStartupMetadataUpdate(notification)) { + +- yield* Ref.update(startupMetadataRef, (current) => + +- [ + +- ...current.filter( + +- (previous) => + +- previous.sessionId !== notification.sessionId || + +- previous.update.sessionUpdate !== notification.update.sessionUpdate, + +- ), + +- notification, + +- ].slice(-maxStartupMetadataUpdates), + +- ); + +- } + +- return; + +- } + +- // One runtime projects one root ACP session. Child-session updates need + +- // explicit lineage routing and must never be flattened into this stream. + +- if ( + +- startState._tag !== "Started" || + +- notification.sessionId !== startState.result.sessionId + +- ) { + +- return; + +- } + +- yield* processSessionUpdate(notification); + +- }), + +- ), + +- ); + +- yield* Scope.addFinalizer( + +- runtimeScope, + +- Ref.set(stoppingRef, true).pipe(Effect.andThen(Deferred.succeed(runtimeClosed, undefined))), + ++ Effect.gen(function* () { + ++ const gate = yield* Ref.get(sessionLoadGateRef); + ++ if (Option.isSome(gate) && gate.value.active) { + ++ const lastActivityAtMillis = yield* Clock.currentTimeMillis; + ++ yield* Ref.set( + ++ sessionLoadGateRef, + ++ Option.some({ + ++ ...gate.value, + ++ lastActivityAtMillis, + ++ }), + ++ ); + ++ return; + ++ } + ++ if (sessionUpdateIsReplay(notification)) { + ++ return; + ++ } + ++ const startState = yield* Ref.get(startStateRef); + ++ // One runtime projects one root ACP session. Child-session updates need + ++ // explicit lineage routing and must never be flattened into this stream. + ++ if ( + ++ startState._tag !== "Started" || + ++ notification.sessionId !== startState.result.sessionId + ++ ) { + ++ return; + ++ } + ++ yield* handleSessionUpdate({ + ++ queue: eventQueue, + ++ modeStateRef, + ++ toolCallsRef, + ++ assistantSegmentRef, + ++ assistantItemRuntimeId, + ++ params: notification, + ++ }); + ++ }), + ); + + const close = Scope.close(runtimeScope, Exit.void).pipe(Effect.asVoid); + + + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + fs: { + readTextFile: false, + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + - | EffectAcpSchema.ResumeSessionResponse, + - ): Effect.Effect => Ref.set(configOptionsRef, sessionConfigOptionsFromSetup(response)); + + } satisfies NonNullable; + + + + const getStartedState = Effect.gen(function* () { + +- yield* ensureConnected; + + const state = yield* Ref.get(startStateRef); + + if (state._tag === "Started") { + + return state.result; + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + }); + + }); + + +- const updateConfigOptions = Effect.fn("AcpSessionRuntime.updateConfigOptions")(function* ( + +- response: EffectAcpSchema.SetSessionConfigOptionResponse, + +- ) { + +- const configOptions = sessionConfigOptionsFromSetup(response); + +- yield* Ref.set(configOptionsRef, configOptions); + +- yield* Queue.offer(eventQueue, { + +- _tag: "ConfigOptionsUpdated", + +- configOptions, + +- rawPayload: response, + +- }); + +- }); + +- + - const updateCurrentModeId = (modeId: string): Effect.Effect => + - Ref.update(modeStateRef, (current) => + - current ? { ...current, currentModeId: modeId } : current, + - ); + -- + ++ const updateConfigOptions = ( + ++ response: + ++ | EffectAcpSchema.SetSessionConfigOptionResponse + ++ | EffectAcpSchema.LoadSessionResponse + ++ | EffectAcpSchema.NewSessionResponse + ++ | EffectAcpSchema.ResumeSessionResponse, + ++ ): Effect.Effect => Ref.set(configOptionsRef, sessionConfigOptionsFromSetup(response)); + + + const setConfigOption = ( + configId: string, + - value: string | boolean, + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + ): Effect.Effect => + validateConfigOptionValue(configId, value).pipe( + Effect.flatMap(() => getStartedState), + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + const initializePayload = { + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + | EffectAcpSchema.LoadSessionResponse + + | EffectAcpSchema.NewSessionResponse + + | EffectAcpSchema.ResumeSessionResponse; + +- if (options.resumeSessionId && options.resumeMethod === "resume") { + +- if (!initializeResult.agentCapabilities?.sessionCapabilities?.resume) { + +- return yield* new EffectAcpErrors.AcpTransportError({ + +- method: "session/resume", + +- detail: "The ACP agent does not support session/resume.", + +- cause: undefined, + +- }); + +- } + +- const resumePayload = { + +- sessionId: options.resumeSessionId, + +- cwd: options.cwd, + +- mcpServers: options.mcpServers ?? [], + +- ...(options.additionalDirectories && options.additionalDirectories.length > 0 + +- ? { additionalDirectories: options.additionalDirectories } + +- : {}), + +- } satisfies EffectAcpSchema.ResumeSessionRequest; + +- sessionId = options.resumeSessionId; + +- sessionSetupResult = yield* runLoggedRequest( + +- "session/resume", + +- resumePayload, + +- acp.agent.resumeSession(resumePayload).pipe( + +- Effect.timeoutOption(options.sessionLoadTimeout ?? defaultSessionLoadTimeout), + +- Effect.flatMap((result) => + +- Option.isSome(result) + +- ? Effect.succeed(result.value) + +- : Effect.fail( + +- new EffectAcpErrors.AcpTransportError({ + +- operation: "call-rpc", + +- method: "session/resume", + +- detail: "session/resume timed out waiting for the agent response.", + +- cause: undefined, + +- }), + +- ), + +- ), + +- ), + +- ); + +- } else if (options.resumeSessionId) { + ++ if (options.resumeSessionId) { + + const loadPayload = { + + sessionId: options.resumeSessionId, + + cwd: options.cwd, + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + const createPayload = { + + cwd: options.cwd, + + mcpServers: options.mcpServers ?? [], + +- ...(options.additionalDirectories && options.additionalDirectories.length > 0 + +- ? { additionalDirectories: options.additionalDirectories } + +- : {}), + + } satisfies EffectAcpSchema.NewSessionRequest; + + const created = yield* runLoggedRequest( + + "session/new", + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + }); + + + + const start = Effect.gen(function* () { + +- yield* ensureConnected; + + const deferred = yield* Deferred.make< + + AcpSessionRuntimeStartResult, + + EffectAcpErrors.AcpError + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + return [ + + startOnce.pipe( + + Effect.tap((result) => + +- notificationSemaphore.withPermit( + +- Effect.gen(function* () { + +- const error = yield* Ref.get(terminationErrorRef); + +- if (Option.isSome(error)) { + +- return yield* error.value; + +- } + +- yield* Ref.set(startStateRef, { _tag: "Started", result }); + +- const metadata = yield* Ref.getAndSet(startupMetadataRef, []); + +- for (const notification of metadata) { + +- if (notification.sessionId === result.sessionId) { + +- yield* processSessionUpdate(notification); + +- } + +- } + +- yield* Deferred.succeed(deferred, result); + +- }), + ++ Ref.set(startStateRef, { _tag: "Started", result }).pipe( + ++ Effect.andThen(Deferred.succeed(deferred, result)), + + ), + + ), + + Effect.onError((cause) => + + Deferred.failCause(deferred, cause).pipe( + + Effect.andThen(Ref.set(startStateRef, { _tag: "NotStarted" })), + +- Effect.andThen(Ref.set(startupMetadataRef, [])), + + ), + + ), + + ), + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + return yield* effect; + + }); + + + +- const drainEvents = Effect.gen(function* () { + +- if (yield* Ref.get(stoppingRef)) { + +- return; + +- } + +- const acknowledge = yield* Deferred.make(); + +- yield* Queue.offer(eventQueue, { _tag: "EventStreamBarrier", acknowledge }); + +- yield* Effect.raceFirst(Deferred.await(acknowledge), Deferred.await(runtimeClosed)); + +- }); + +- + +- const retireRuntime = Effect.fn("AcpSessionRuntime.retireRuntime")(function* ( + +- error: EffectAcpErrors.AcpError, + +- ) { + +- yield* recordTermination(error); + +- yield* child.kill({ forceKillAfter: "1 second" }).pipe(Effect.ignore); + +- }); + +- + +- const cancel = Effect.gen(function* () { + +- const started = yield* getStartedState; + +- const activePrompt = yield* Ref.get(activePromptRef); + +- if (options.cancelBehavior !== "wait-for-prompt") { + +- if (Option.isSome(activePrompt)) { + +- yield* Fiber.interrupt(activePrompt.value.fiber).pipe(Effect.ignore); + +- } + +- // Write cancel before a replacement prompt can reach the agent. + +- yield* acp.agent.cancel({ sessionId: started.sessionId }).pipe(Effect.ignore); + +- return; + +- } + +- + +- yield* acp.agent.cancel({ sessionId: started.sessionId }); + +- if (Option.isNone(activePrompt)) { + +- return; + +- } + +- const completed = yield* Effect.gen(function* () { + +- const result = yield* Fiber.await(activePrompt.value.fiber); + +- yield* Deferred.await(activePrompt.value.completed); + +- if (Option.isNone(yield* Ref.get(terminationErrorRef))) { + +- yield* drainEvents; + +- } + +- return result; + +- }).pipe(Effect.timeoutOption(options.cancelTimeout ?? defaultCancelTimeout)); + +- if (Option.isNone(completed)) { + +- const error = new EffectAcpErrors.AcpTransportError({ + +- operation: "call-rpc", + +- method: "session/cancel", + +- detail: "The ACP agent did not finish cancellation. Its process was stopped.", + +- cause: undefined, + +- }); + +- yield* retireRuntime(error); + +- return yield* error; + +- } + +- if (Exit.isFailure(completed.value)) { + +- return yield* Effect.failCause(completed.value.cause); + +- } + +- }); + +- + + return { + + handleRequestPermission: acp.handleRequestPermission, + + handleElicitation: acp.handleElicitation, + +@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + handleUnknownExtNotification: acp.handleUnknownExtNotification, + + handleExtRequest: acp.handleExtRequest, + handleExtNotification: acp.handleExtNotification, + - initialize: () => sendInitialize, + +- initialize: () => ensureConnected.pipe(Effect.andThen(sendInitialize)), + ++ initialize: () => sendInitialize, + start: () => start, + - getEvents: () => Stream.fromQueue(eventQueue), + -- drainEvents: Effect.gen(function* () { + -- const acknowledge = yield* Deferred.make(); + -- yield* Queue.offer(eventQueue, { + -- _tag: "EventStreamBarrier", + -- acknowledge, + -- }); + -- yield* Deferred.await(acknowledge); + -- }), + +- drainEvents, + + events: Stream.fromQueue(eventQueue), + getModeState: Ref.get(modeStateRef), + getConfigOptions: Ref.get(configOptionsRef), + prompt: (payload, promptOptions?) => + -@@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + promptSerializationSemaphore.withPermit( + +- Effect.acquireUseRelease( + +- promptDispatchSemaphore.withPermit( + +- Effect.gen(function* () { + +- const started = yield* getStartedState; + +- yield* closeActiveAssistantSegment({ queue: eventQueue, assistantSegmentRef }); + +- const requestPayload = { + +- sessionId: started.sessionId, + +- ...payload, + +- } satisfies EffectAcpSchema.PromptRequest; + +- const completed = yield* Deferred.make(); + +- const fiber = yield* runLoggedRequest( + +- "session/prompt", + +- requestPayload, + +- acp.agent.prompt(requestPayload), + +- ).pipe(Effect.forkIn(runtimeScope)); + +- const active = { fiber, completed } satisfies AcpActivePrompt; + +- yield* Ref.set(activePromptRef, Option.some(active)); + +- if (promptOptions?.dispatched) { + +- yield* Deferred.succeed(promptOptions.dispatched, undefined); + +- } + +- return active; + +- }), + +- ), + +- (activePrompt) => + +- Fiber.join(activePrompt.fiber).pipe( + +- Effect.catchCause((cause) => + +- options.cancelBehavior !== "wait-for-prompt" && Cause.hasInterruptsOnly(cause) + +- ? Effect.succeed({ + +- stopReason: "cancelled", + +- } satisfies EffectAcpSchema.PromptResponse) + +- : Effect.failCause(cause), + +- ), + +- Effect.tap(() => + +- closeActiveAssistantSegment({ queue: eventQueue, assistantSegmentRef }), + +- ), + ++ Effect.gen(function* () { + ++ const started = yield* getStartedState; + ++ yield* closeActiveAssistantSegment({ + ++ queue: eventQueue, + ++ assistantSegmentRef, + ++ }); + ++ const requestPayload = { + ++ sessionId: started.sessionId, + ++ ...payload, + ++ } satisfies EffectAcpSchema.PromptRequest; + ++ const cancelledResponse = { + ++ stopReason: "cancelled", + ++ } satisfies EffectAcpSchema.PromptResponse; + ++ const promptRpcFiber = yield* runLoggedRequest( + ++ "session/prompt", + ++ requestPayload, + ++ acp.agent.prompt(requestPayload), + ++ ).pipe(Effect.forkIn(runtimeScope)); + ++ yield* Ref.set(activePromptFiberRef, Option.some(promptRpcFiber)); + ++ if (promptOptions?.dispatched) { + ++ yield* Deferred.succeed(promptOptions.dispatched, undefined); + ++ } + ++ return yield* Fiber.join(promptRpcFiber).pipe( + ++ Effect.catchCause((cause) => + ++ Cause.hasInterruptsOnly(cause) + ++ ? Effect.succeed(cancelledResponse) + ++ : Effect.failCause(cause), + + ), + +- (activePrompt, result) => + +- Effect.gen(function* () { + +- if ( + +- options.cancelBehavior === "wait-for-prompt" && + +- Exit.isFailure(result) && + +- Cause.hasInterrupts(result.cause) + +- ) { + +- yield* retireRuntime( + +- new EffectAcpErrors.AcpTransportError({ + +- method: "session/prompt", + +- detail: "The ACP prompt stopped before the agent confirmed completion.", + +- cause: undefined, + +- }), + +- ); + +- } + +- yield* Fiber.interrupt(activePrompt.fiber).pipe(Effect.ignore); + +- yield* Ref.set(activePromptRef, Option.none()); + +- yield* Deferred.succeed(activePrompt.completed, undefined); + +- }), + +- ), + ++ Effect.ensuring( + ++ Effect.gen(function* () { + ++ yield* Fiber.interrupt(promptRpcFiber).pipe(Effect.ignore); + ++ yield* Ref.set(activePromptFiberRef, Option.none()); + ++ }), + ++ ), + ++ Effect.tap(() => + ++ closeActiveAssistantSegment({ + ++ queue: eventQueue, + ++ assistantSegmentRef, + ++ }), + ++ ), + ++ ); + ++ }), + ), + - ), + - setMode: (modeId) => + +- cancel: + +- options.cancelBehavior === "wait-for-prompt" + +- ? promptDispatchSemaphore.withPermit(cancel) + +- : cancel, + +- setMode: (modeId) => + - Ref.get(modeStateRef).pipe( + - Effect.flatMap((modeState) => { + - if (modeState?.currentModeId === modeId) { + - return Effect.succeed({} satisfies EffectAcpSchema.SetSessionModeResponse); + -- } + ++ cancel: getStartedState.pipe( + ++ Effect.flatMap((started) => + ++ Effect.gen(function* () { + ++ const activePromptFiber = yield* Ref.get(activePromptFiberRef); + ++ if (Option.isSome(activePromptFiber)) { + ++ yield* Fiber.interrupt(activePromptFiber.value).pipe(Effect.ignore); + + } + - return setConfigOption("mode", modeId).pipe( + - Effect.tap(() => updateCurrentModeId(modeId)), + - Effect.as({} satisfies EffectAcpSchema.SetSessionModeResponse), + - ); + -- }), + -- ), + ++ // Await the notification write so a replacement session/prompt + ++ // cannot race ahead of session/cancel on the wire. + ++ yield* acp.agent.cancel({ sessionId: started.sessionId }).pipe(Effect.ignore); + + }), + + ), + ++ ), + ++ setMode: (modeId) => + + getStartedState.pipe(Effect.flatMap(() => setConfigOption("mode", modeId))), + setConfigOption, + setModel: (model) => + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + return runLoggedRequest( + "session/set_model", + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: export const make = ( + + }), + + ), + request: (method, payload) => + - runLoggedRequest(method, payload, acp.raw.request(method, payload)), + - notify: acp.raw.notify, + +- ensureConnected.pipe( + +- Effect.andThen(runLoggedRequest(method, payload, acp.raw.request(method, payload))), + +- ), + +- notify: (method, payload) => + +- ensureConnected.pipe(Effect.andThen(acp.raw.notify(method, payload))), + - } satisfies AcpSessionRuntime["Service"]; + ++ runLoggedRequest(method, payload, acp.raw.request(method, payload)), + ++ notify: acp.raw.notify, + + close, + + } satisfies AcpSessionRuntimeShape; + }); + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: function sessionConfigOptions + - } + - return currentValue.trim() === String(value).trim(); + -} + +- + +-function isStartupMetadataUpdate(notification: EffectAcpSchema.SessionNotification): boolean { + +- switch (notification.update.sessionUpdate) { + +- case "current_mode_update": + +- case "config_option_update": + +- case "available_commands_update": + +- return true; + +- default: + +- return false; + +- } + +-} + - + const handleSessionUpdate = ({ + queue, + modeStateRef, + +- configOptionsRef, + + toolCallsRef, + + assistantSegmentRef, + + assistantItemRuntimeId, + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: const handleSessionUpdate = ({ + }: { + readonly queue: Queue.Queue; + readonly modeStateRef: Ref.Ref; + +- readonly configOptionsRef: Ref.Ref>; + - readonly toolCallsRef: Ref.Ref>; + + readonly toolCallsRef: Ref.Ref>; + readonly assistantSegmentRef: Ref.Ref; + readonly assistantItemRuntimeId: string; + readonly params: EffectAcpSchema.SessionNotification; + + }): Effect.Effect => + + Effect.gen(function* () { + +- if (params.update.sessionUpdate === "config_option_update") { + +- yield* Ref.set(configOptionsRef, params.update.configOptions); + +- } + + const parsed = parseSessionUpdateEvent(params); + + if (parsed.modeId) { + + yield* Ref.update(modeStateRef, (current) => + @@ apps/server/src/provider/acp/AcpSessionRuntime.ts: const handleSessionUpdate = ({ + queue, + assistantSegmentRef, + @@ apps/server/src/provider/acp/CursorAcpCliProbe.test.ts: describe.runIf(process.e + + ## apps/server/src/provider/acp/CursorAcpSupport.ts ## + @@ + --import { type CursorSettings, type ProviderOptionSelection } from "@t3tools/contracts"; + +-import { + +- type CursorSettings, + +- type ProviderOptionSelection, + +- type RuntimeMode, + +-} from "@t3tools/contracts"; + -import * as Crypto from "effect/Crypto"; + -import * as Effect from "effect/Effect"; + -import * as Layer from "effect/Layer"; + @@ apps/server/src/provider/acp/CursorAcpSupport.ts + import type * as EffectAcpErrors from "effect-acp/errors"; + + import { + +@@ apps/server/src/provider/acp/CursorAcpSupport.ts: import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; + + + + type CursorAcpRuntimeCursorSettings = Pick; + + + +-function cursorAcpPermissionArgs(runtimeMode?: RuntimeMode): ReadonlyArray { + +- switch (runtimeMode) { + +- case "auto": + +- return ["--auto-review"]; + +- case "full-access": + +- return ["--force"]; + +- default: + +- return []; + +- } + +-} + +- + + export interface CursorAcpRuntimeInput extends Omit< + + AcpSessionRuntime.AcpSessionRuntimeOptions, + + "authMethodId" | "clientCapabilities" | "spawn" + +@@ apps/server/src/provider/acp/CursorAcpSupport.ts: export interface CursorAcpRuntimeInput extends Omit< + + readonly childProcessSpawner: ChildProcessSpawner.ChildProcessSpawner["Service"]; + + readonly cursorSettings: CursorAcpRuntimeCursorSettings | null | undefined; + + readonly environment?: NodeJS.ProcessEnv; + +- readonly runtimeMode?: RuntimeMode; + + } + + + + export interface CursorAcpModelSelectionErrorContext { + +@@ apps/server/src/provider/acp/CursorAcpSupport.ts: export function buildCursorAcpSpawnInput( + + cursorSettings: CursorAcpRuntimeCursorSettings | null | undefined, + + cwd: string, + + environment?: NodeJS.ProcessEnv, + +- runtimeMode?: RuntimeMode, + + ): AcpSessionRuntime.AcpSpawnInput { + + return { + + command: cursorSettings?.binaryPath || "cursor-agent", + + args: [ + + ...(cursorSettings?.apiEndpoint ? (["-e", cursorSettings.apiEndpoint] as const) : []), + +- ...cursorAcpPermissionArgs(runtimeMode), + + "acp", + + ], + + cwd, + @@ apps/server/src/provider/acp/CursorAcpSupport.ts: export function buildCursorAcpSpawnInput( + + export const makeCursorAcpRuntime = ( + @@ apps/server/src/provider/acp/CursorAcpSupport.ts: export function buildCursorAcp + Effect.gen(function* () { + const acpContext = yield* Layer.build( + AcpSessionRuntime.layer({ + + ...input, + +- spawn: buildCursorAcpSpawnInput( + +- input.cursorSettings, + +- input.cwd, + +- input.environment, + +- input.runtimeMode, + +- ), + ++ spawn: buildCursorAcpSpawnInput(input.cursorSettings, input.cwd, input.environment), + + authMethodId: "cursor_login", + + clientCapabilities: CURSOR_PARAMETERIZED_MODEL_PICKER_CAPABILITIES, + + }).pipe( + @@ apps/server/src/provider/acp/CursorAcpSupport.ts: export const makeCursorAcpRuntime = ( + ), + ), + @@ apps/server/src/provider/codexModels.ts (new) + + ); + +} + + - ## apps/server/src/provider/makeManagedServerProvider.ts ## + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - readonly getSettings: Effect.Effect; + - readonly streamSettings: Stream.Stream; + - readonly haveSettingsChanged: (previous: Settings, next: Settings) => boolean; + -- readonly initialSnapshot: (settings: Settings) => Effect.Effect; + -+ readonly buildInitialSnapshot?: ((settings: Settings) => ServerProvider) | undefined; + -+ readonly initialSnapshot?: ((settings: Settings) => ServerProvider) | undefined; + - readonly checkProvider: Effect.Effect; + - readonly enrichSnapshot?: (input: { + - readonly settings: Settings; + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - > { + - const backgroundPolicy = yield* BackgroundPolicy.BackgroundPolicy; + - const serverSettings = yield* ServerSettingsService; + -+ type InitialRefreshState = "idle" | "running" | "done"; + - const refreshSemaphore = yield* Semaphore.make(1); + - const changesPubSub = yield* Effect.acquireRelease( + - PubSub.unbounded(), + - PubSub.shutdown, + - ); + - const initialSettings = yield* input.getSettings; + -- const initialSnapshot = yield* input.initialSnapshot(initialSettings); + -+ const initialSnapshotFactory = input.buildInitialSnapshot ?? input.initialSnapshot; + -+ if (!initialSnapshotFactory) { + -+ return yield* Effect.die( + -+ new Error("makeManagedServerProvider requires an initial snapshot factory."), + -+ ); + -+ } + -+ const initialSnapshot = initialSnapshotFactory(initialSettings); + - const snapshotStateRef = yield* Ref.make({ + - snapshot: initialSnapshot, + - enrichmentGeneration: 0, + - }); + - const settingsRef = yield* Ref.make(initialSettings); + -+ const initialRefreshStateRef = yield* Ref.make("idle"); + - const enrichmentFiberRef = yield* Ref.make | null>(null); + - const scope = yield* Effect.scope; + - + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - if (state.enrichmentGeneration !== generation || Equal.equals(state.snapshot, nextSnapshot)) { + - return [null, state] as const; + - } + -+ + - return [ + - nextSnapshot, + - { + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - ] as const; + - }); + - yield* Ref.set(settingsRef, nextSettings); + -+ yield* Ref.set(initialRefreshStateRef, "done"); + - yield* PubSub.publish(changesPubSub, nextSnapshot); + - yield* restartSnapshotEnrichment(nextSettings, nextSnapshot, nextGeneration); + - return nextSnapshot; + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - return yield* applySnapshot(nextSettings, { forceRefresh: true }); + - }); + - + -- const hasProviderStatusDemand = Effect.gen(function* () { + -- const state = yield* Ref.get(snapshotStateRef); + -- const instanceId = state.snapshot.instanceId; + -- const [genericDemand, instanceDemand] = yield* Effect.all([ + -- backgroundPolicy.shouldRunScopeWork({ type: "provider-status" }), + -- backgroundPolicy.shouldRunScopeWork({ type: "provider-status", instanceId }), + -- ]); + -- return genericDemand || instanceDemand; + -- }); + -+ const startInitialRefreshIfNeeded = Effect.fn("startInitialRefreshIfNeeded")(function* () { + -+ const shouldStart = yield* Ref.modify( + -+ initialRefreshStateRef, + -+ (state): readonly [boolean, InitialRefreshState] => + -+ state === "idle" ? [true, "running"] : [false, state], + -+ ); + - + -- const getRefreshInterval = + -- input.refreshInterval !== undefined + -- ? Effect.succeed(input.refreshInterval) + -- : serverSettings.getSettings.pipe( + -- Effect.map( + -- (settings) => + -- resolveServerBackgroundActivitySettings(settings).providerHealthRefreshInterval, + -- ), + -- Effect.orElseSucceed(() => DEFAULT_PROVIDER_HEALTH_REFRESH_INTERVAL), + -- ); + -- + -- const refreshIntervalChanges = yield* Queue.sliding(1); + -- if (input.refreshInterval === undefined) { + -- const serverSettingsChanges = yield* serverSettings.subscribeChanges; + -- yield* serverSettingsChanges.pipe( + -- Stream.map((settings) => + -- Duration.toMillis( + -- resolveServerBackgroundActivitySettings(settings).providerHealthRefreshInterval, + -- ), + -+ if (!shouldStart) { + -+ return; + -+ } + -+ + -+ yield* refreshSnapshot().pipe( + -+ Effect.onExit((exit) => + -+ exit._tag === "Failure" + -+ ? Ref.update(initialRefreshStateRef, (state) => (state === "running" ? "idle" : state)) + -+ : Effect.void, + - ), + -- Stream.changes, + -- Stream.runForEach(() => Queue.offer(refreshIntervalChanges, undefined).pipe(Effect.asVoid)), + -- Effect.forkScoped, + -+ Effect.ignoreCause({ log: true }), + -+ Effect.forkIn(scope), + - ); + -- } + -+ }); + - + - yield* Stream.runForEach(input.streamSettings, (nextSettings) => + - Effect.asVoid(applySnapshot(nextSettings)), + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - Effect.ignoreCause({ log: true }), + - ), + - ).pipe(Effect.forkScoped); + -- + -- yield* applySnapshot(initialSettings, { forceRefresh: true }).pipe( + -- Effect.ignoreCause({ log: true }), + -- Effect.forkScoped, + -- ); + -+ yield* startInitialRefreshIfNeeded(); + - + - return { + -- maintenanceCapabilities: input.maintenanceCapabilities, + -- getSnapshot: Ref.get(snapshotStateRef).pipe(Effect.map((state) => state.snapshot)), + -+ getSnapshot: startInitialRefreshIfNeeded().pipe( + -+ Effect.flatMap(() => + -+ input.getSettings.pipe( + -+ Effect.flatMap(applySnapshot), + -+ Effect.tapError(Effect.logError), + -+ Effect.orDie, + -+ ), + -+ ), + -+ ), + - refresh: refreshSnapshot().pipe(Effect.tapError(Effect.logError), Effect.orDie), + - get streamChanges() { + - return Stream.fromPubSub(changesPubSub); + - + ## apps/server/src/serverSettings.ts ## + @@ apps/server/src/serverSettings.ts: function restoreUsedProviders( + }; + @@ apps/web/src/components/chat/CompactComposerControlsMenu.browser.tsx (new) + + }); + +}); + + - ## apps/web/src/components/chat/ProviderModelPicker.tsx ## + -@@ + -+import { type ProviderKind, type ServerProvider } from "@t3tools/contracts"; + -+import { resolveModelSlugForProvider, resolveSelectableModel } from "@t3tools/shared/model"; + -+import { memo, useState } from "react"; + -+import type { VariantProps } from "class-variance-authority"; + -+import { type ProviderPickerKind, PROVIDER_OPTIONS } from "../../session-logic"; + -+import { ChevronDownIcon } from "lucide-react"; + -+import { Button, buttonVariants } from "../ui/button"; + - import { + - type ProviderInstanceId, + - type ProviderDriverKind, + -@@ apps/web/src/components/chat/ProviderModelPicker.tsx: import { + - getTriggerDisplayModelLabel, + - getTriggerDisplayModelName, + - } from "./providerIconUtils"; + --import { shouldShowInstanceBadge, type ProviderInstanceEntry } from "../../providerInstances"; + -+import type { ProviderInstanceEntry } from "../../providerInstances"; + - import { ComposerControl, ComposerControlChevron } from "./ComposerControl"; + - + - export const ProviderModelPicker = memo(function ProviderModelPicker(props: { + -@@ apps/web/src/components/chat/ProviderModelPicker.tsx: export const ProviderModelPicker = memo(function ProviderModelPicker(props: { + - open?: boolean; + - triggerVariant?: VariantProps["variant"]; + - triggerClassName?: string; + -- triggerAriaLabel?: string; + -- onOpenChange?: (open: boolean) => void; + -- getModelDisabledReason?: (instanceId: ProviderInstanceId, model: string) => string | null; + -- onInstanceModelChange: (instanceId: ProviderInstanceId, model: string) => void; + -+ disabledReason?: string; + -+ onProviderModelChange: (provider: ProviderKind, model: string) => void; + - }) { + - const [uncontrolledIsMenuOpen, setUncontrolledIsMenuOpen] = useState(false); + - const isMenuOpen = props.open ?? uncontrolledIsMenuOpen; + -@@ apps/web/src/components/chat/ProviderModelPicker.tsx: export const ProviderModelPicker = memo(function ProviderModelPicker(props: { + - + - const handleInstanceModelChange = (instanceId: ProviderInstanceId, model: string) => { + - if (props.disabled) return; + -- props.onInstanceModelChange(instanceId, model); + -+ if (!value) return; + -+ const resolvedModel = + -+ resolveSelectableModel(provider, value, props.modelOptionsByProvider[provider]) ?? + -+ resolveModelSlugForProvider(provider, value); + -+ if (!resolvedModel) return; + -+ props.onProviderModelChange(provider, resolvedModel); + - setIsMenuOpen(false); + - }; + - + -@@ apps/web/src/components/chat/ProviderModelPicker.tsx: export const ProviderModelPicker = memo(function ProviderModelPicker(props: { + - props.triggerClassName, + - )} + - disabled={props.disabled} + -+ title={props.disabled ? props.disabledReason : undefined} + - /> + - } + - > + -@@ apps/web/src/components/chat/ProviderModelPicker.tsx: export const ProviderModelPicker = memo(function ProviderModelPicker(props: { + - showBadge={showInstanceBadge} + - className="size-4" + - iconClassName={cn("size-4", props.activeProviderIconClassName)} + -- indicatorBackground="var(--contrast-input)" + -+ indicatorBackground="var(--input)" + - badgeClassName={cn( + - "right-[-0.125rem] bottom-[-0.125rem] h-3 min-w-3", + - "px-0.5 text-[7px]", + -@@ apps/web/src/components/chat/ProviderModelPicker.tsx: export const ProviderModelPicker = memo(function ProviderModelPicker(props: { + - + - ) : null} + - + -- + -- + -- + -- setIsMenuOpen(false)} + -- {...(props.getModelDisabledReason + -- ? { getModelDisabledReason: props.getModelDisabledReason } + -- : {})} + -- onInstanceModelChange={handleInstanceModelChange} + -- /> + -- + -- + -+ + -+ + -+ {props.lockedProvider !== null ? ( + -+ + -+ handleModelChange(props.lockedProvider!, value)} + -+ > + -+ {props.modelOptionsByProvider[props.lockedProvider].map((modelOption) => ( + -+ setIsMenuOpen(false)} + -+ > + -+ {modelOption.name} + -+ + -+ ))} + -+ + -+ + -+ ) : ( + -+ <> + -+ {AVAILABLE_PROVIDER_OPTIONS.map((option) => { + -+ const OptionIcon = PROVIDER_ICON_BY_PROVIDER[option.value]; + -+ const liveProvider = props.providers + -+ ? getProviderSnapshot(props.providers, option.value) + -+ : undefined; + -+ if (liveProvider && liveProvider.status !== "ready") { + -+ const unavailableLabel = !liveProvider.enabled + -+ ? "Disabled" + -+ : !liveProvider.installed + -+ ? "Not installed" + -+ : "Unavailable"; + -+ return ( + -+ + -+ + -+ ); + -+ } + -+ return ( + -+ + -+ + -+ + -+ + -+ + -+ handleModelChange(option.value, value)} + -+ > + -+ {props.modelOptionsByProvider[option.value].map((modelOption) => ( + -+ setIsMenuOpen(false)} + -+ > + -+ {modelOption.name} + -+ + -+ ))} + -+ + -+ + -+ + -+ + -+ ); + -+ })} + -+ {UNAVAILABLE_PROVIDER_OPTIONS.length > 0 && } + -+ {UNAVAILABLE_PROVIDER_OPTIONS.map((option) => { + -+ const OptionIcon = PROVIDER_ICON_BY_PROVIDER[option.value]; + -+ return ( + -+ + -+ + -+ ); + -+ })} + -+ {UNAVAILABLE_PROVIDER_OPTIONS.length === 0 && } + -+ {COMING_SOON_PROVIDER_OPTIONS.map((option) => { + -+ const OptionIcon = option.icon; + -+ return ( + -+ + -+ + -+ ); + -+ })} + -+ + -+ )} + -+ + -+ + - ); + - }); + - + ## apps/web/src/components/chat/TraitsPicker.browser.tsx (new) ## + @@ + +import "../../index.css"; + @@ apps/web/src/session-logic.test.ts: describe("derivePendingApprovals", () => { + it("derives dynamic tool requests as actionable generic approvals", () => { + const activities: OrchestrationThreadActivity[] = [ + makeActivity({ + +@@ apps/web/src/session-logic.test.ts: describe("derivePendingApprovals", () => { + + }); + + + + describe("derivePendingUserInputs", () => { + +- it("keeps free-text questions without suggested answers", () => { + +- const question = { + +- id: "0", + +- header: "Question", + +- question: "What should it be named?", + +- options: [], + +- allowCustomAnswer: true, + +- multiSelect: false, + +- }; + +- const activities = [ + +- makeActivity({ + +- id: "async-question", + +- kind: "user-input.requested", + +- summary: "User input requested", + +- payload: { requestId: "async-1", responseMode: "message", questions: [question] }, + +- }), + +- ]; + +- expect(derivePendingUserInputs(activities)[0]?.questions).toEqual([question]); + +- }); + +- + +- it("preserves native choice values and the custom-answer restriction", () => { + +- const question = { + +- id: "interaction-result", + +- header: "Result", + +- question: "Which result should be used?", + +- options: [ + +- { value: " first\t", label: "Result", description: "First result" }, + +- { value: "second", label: "Result", description: "Second result" }, + +- ], + +- allowCustomAnswer: false, + +- multiSelect: false, + +- }; + +- const activities = [ + +- makeActivity({ + +- id: "native-user-input", + +- kind: "user-input.requested", + +- summary: "User input requested", + +- payload: { requestId: "req-native-choice", questions: [question] }, + +- }), + +- ]; + +- + +- expect(derivePendingUserInputs(activities)[0]?.questions).toEqual([question]); + +- }); + +- + + it("tracks open structured prompts and removes resolved ones", () => { + + const activities: OrchestrationThreadActivity[] = [ + + makeActivity({ + @@ apps/web/src/session-logic.test.ts: describe("deriveActivePlanState", () => { + steps: [{ step: "Write tests", status: "completed" }], + }); + @@ apps/web/src/session-logic.test.ts: describe("deriveActivePlanState", () => { + makeActivity({ + id: "plan-set", + @@ apps/web/src/session-logic.test.ts: describe("deriveWorkLogEntries", () => { + + payload: { + + itemType: "mcp_tool_call", + + title: "t3-code · preview_status", + +- toolSurface: "browser", + +- toolIcon: { _tag: "website", pageUrl: "https://example.com/checkout" }, + +- toolSource: { + +- key: "browser-use:browser", + +- name: "Browser", + +- kind: "browser", + +- }, + + data: { item }, + + }, + + }), + +@@ apps/web/src/session-logic.test.ts: describe("deriveWorkLogEntries", () => { + + + + const [entry] = deriveWorkLogEntries(activities); + + expect(entry?.toolTitle).toBe("t3-code · preview_status"); + +- expect(entry?.toolSurface).toBe("browser"); + +- expect(entry?.toolIcon).toEqual({ + +- _tag: "website", + +- pageUrl: "https://example.com/checkout", + +- }); + +- expect(entry?.toolSource).toEqual({ + +- key: "browser-use:browser", + +- name: "Browser", + +- kind: "browser", + +- }); + + expect(entry?.toolData).toEqual(item); + + }); + + + +@@ apps/web/src/session-logic.test.ts: describe("deriveWorkLogEntries", () => { + + payload: { + + itemType: "mcp_tool_call", + + toolCallId: "call-1", + +- toolSurface: "browser", + + data: { item }, + + }, + + }), + +@@ apps/web/src/session-logic.test.ts: describe("deriveWorkLogEntries", () => { + + payload: { + + itemType: "mcp_tool_call", + + toolCallId: "call-1", + +- toolIcon: { _tag: "website", pageUrl: "https://example.com/result" }, + + }, + + }), + + ]; + + const [entry] = deriveWorkLogEntries(activities); + expect(entry?.toolData).toEqual(item); + - expect(entry?.toolCallId).toBe("call-1"); + +- expect(entry?.toolSurface).toBe("browser"); + +- expect(entry?.toolIcon).toEqual({ + +- _tag: "website", + +- pageUrl: "https://example.com/result", + +- }); + - expect(resolveWorkEntryToolPresentation(entry!)?.displayName).toBe( + - "Took a snapshot of the preview page", + - ); + @@ packages/contracts/src/model.ts: import { ProviderDriverKind } from "./providerI + label: TrimmedNonEmptyString, + description: Schema.optional(TrimmedNonEmptyString), + isDefault: Schema.optional(Schema.Boolean), + +@@ packages/contracts/src/model.ts: export const PREFERRED_DEFAULT_CODEX_MODELS: ReadonlyArray = [ + + "gpt-5.6-terra", + + ]; + + export const DEFAULT_TEXT_GENERATION_MODEL = "gpt-5.6-luna"; + +-/** Keep the official Antigravity session's current model. Never send this ID to ACP. */ + +-export const ANTIGRAVITY_DEFAULT_MODEL = "antigravity-default"; + + export const DEFAULT_TEXT_GENERATION_REASONING_EFFORT = "low"; + + + + export const DEFAULT_MODEL_BY_PROVIDER: Partial> = { + +@@ packages/contracts/src/model.ts: export const DEFAULT_MODEL_BY_PROVIDER: Partial + + > = { + + [CODEX_DRIVER_KIND]: DEFAULT_TEXT_GENERATION_MODEL, + +- [ProviderDriverKind.make("antigravity")]: ANTIGRAVITY_DEFAULT_MODEL, + + [CLAUDE_DRIVER_KIND]: "claude-haiku-4-5", + + [CURSOR_DRIVER_KIND]: "composer-2", + + [OPENCODE_DRIVER_KIND]: "openai/gpt-5", + @@ packages/contracts/src/model.ts: export const MODEL_SLUG_ALIASES_BY_PROVIDER: Partial< + [OPENCODE_DRIVER_KIND]: {}, + }; + @@ packages/contracts/src/model.ts: export const MODEL_SLUG_ALIASES_BY_PROVIDER: Pa + -// ── Provider display names ──────────────────────────────────────────── + - + -export const PROVIDER_DISPLAY_NAMES: Partial> = { + +- [ProviderDriverKind.make("antigravity")]: "Antigravity", + - [CODEX_DRIVER_KIND]: "Codex", + - [CLAUDE_DRIVER_KIND]: "Claude", + - [CURSOR_DRIVER_KIND]: "Cursor", + @@ packages/contracts/src/providerRuntime.ts: const RuntimeEventRawSource = Schema. + ]); + + ## packages/contracts/src/settings.ts ## + +@@ packages/contracts/src/settings.ts: import * as Effect from "effect/Effect"; + + import * as Duration from "effect/Duration"; + + import * as Schema from "effect/Schema"; + + import * as SchemaTransformation from "effect/SchemaTransformation"; + +-import { ForwardCompatibleNullable, TrimmedNonEmptyString, TrimmedString } from "./baseSchemas.ts"; + +-import { UsageLimitSourceId } from "./usageLimitSourceId.ts"; + +-import { EnvironmentMachineKind, ThreadEnvMode } from "./environment.ts"; + ++import { TrimmedNonEmptyString, TrimmedString } from "./baseSchemas.ts"; + ++import { ThreadEnvMode } from "./environment.ts"; + + import { + + DEFAULT_TEXT_GENERATION_MODEL, + + DEFAULT_TEXT_GENERATION_REASONING_EFFORT, + + ProviderOptionSelections, + + } from "./model.ts"; + + import { ModelSelection } from "./orchestration.ts"; + +-import { BrowserProfile, BrowserProfileId, DEFAULT_BROWSER_PROFILE_ID } from "./browserProfile.ts"; + + import { + + DEFAULT_PREVIEW_APPEARANCE, + + DEFAULT_PREVIEW_ZOOM_FACTOR, + @@ packages/contracts/src/settings.ts: import { + PreviewViewportSetting, + PreviewZoomFactor, + @@ packages/contracts/src/settings.ts: import { + + // ── Client Settings (local-only) ─────────────────────────────── + + +@@ packages/contracts/src/settings.ts: export const TimestampFormat = Schema.Literals(["locale", "12-hour", "24-hour"]) + + export type TimestampFormat = typeof TimestampFormat.Type; + + export const DEFAULT_TIMESTAMP_FORMAT: TimestampFormat = "locale"; + + + +-export const DiffLayout = Schema.Literals(["stacked", "split"]); + +-export type DiffLayout = typeof DiffLayout.Type; + +-export const DEFAULT_DIFF_LAYOUT: DiffLayout = "stacked"; + +- + + export const SidebarProjectSortOrder = Schema.Literals(["updated_at", "created_at", "manual"]); + + export type SidebarProjectSortOrder = typeof SidebarProjectSortOrder.Type; + + export const DEFAULT_SIDEBAR_PROJECT_SORT_ORDER: SidebarProjectSortOrder = "updated_at"; + @@ packages/contracts/src/settings.ts: export const GlassOpacity = Schema.Int.check( + ); + export type GlassOpacity = typeof GlassOpacity.Type; + @@ packages/contracts/src/settings.ts: export const GlassOpacity = Schema.Int.check + -); + -export type AppearanceContrast = typeof AppearanceContrast.Type; + -export const DEFAULT_APPEARANCE_CONTRAST: AppearanceContrast = 100; + +-export const MIN_PANEL_ANIMATION_DURATION_MS = 0; + +-export const MAX_PANEL_ANIMATION_DURATION_MS = 400; + +-export const PanelAnimationDurationMs = Schema.Int.check( + +- Schema.isBetween({ + +- minimum: MIN_PANEL_ANIMATION_DURATION_MS, + +- maximum: MAX_PANEL_ANIMATION_DURATION_MS, + +- }), + +-); + +-export type PanelAnimationDurationMs = typeof PanelAnimationDurationMs.Type; + +-export const DEFAULT_PANEL_ANIMATION_DURATION_MS: PanelAnimationDurationMs = 0; + /** + * Font size preferences, in CSS pixels. The ranges are deliberately narrow: + * the interface size scales every rem-based dimension in the app, so the + -@@ packages/contracts/src/settings.ts: export type BrowserRecordingFrameRate = typeof BrowserRecordingFrameRate.Type; + +@@ packages/contracts/src/settings.ts: export const BROWSER_RECORDING_FRAME_RATES = [30, 60] as const; + + export const BrowserRecordingFrameRate = Schema.Literals(BROWSER_RECORDING_FRAME_RATES); + + export type BrowserRecordingFrameRate = typeof BrowserRecordingFrameRate.Type; + export const DEFAULT_BROWSER_RECORDING_FRAME_RATE: BrowserRecordingFrameRate = 30; + +-/** + +- * Where a clicked link goes: the OS default browser, or a tab in the in-app + +- * browser beside the thread. "system" is the default because that is what + +- * every link did before the setting existed. + +- */ + +-export const BrowserLinkTarget = Schema.Literals(["system", "app"]); + +-export type BrowserLinkTarget = typeof BrowserLinkTarget.Type; + +-export const DEFAULT_BROWSER_LINK_TARGET: BrowserLinkTarget = "system"; + + export const ClientSettingsSchema = Schema.Struct({ + - appearanceContrast: AppearanceContrast.pipe( + - Schema.withDecodingDefault(Effect.succeed(DEFAULT_APPEARANCE_CONTRAST)), + +- ), + +- // Panel motion defaults to zero because width and height transitions cause + +- // layout work on every frame, which is noticeable on lower-power clients. + +- panelAnimationDurationMs: PanelAnimationDurationMs.pipe( + +- Schema.withDecodingDefault(Effect.succeed(DEFAULT_PANEL_ANIMATION_DURATION_MS)), + - ), + browserDefaultViewport: PreviewViewportSetting.pipe( + Schema.withDecodingDefault(Effect.succeed(DEFAULT_BROWSER_VIEWPORT)), + ), + +@@ packages/contracts/src/settings.ts: export const ClientSettingsSchema = Schema.Struct({ + + Schema.withDecodingDefault(Effect.succeed(DEFAULT_BROWSER_RECORDING_FRAME_RATE)), + + ), + + /** + +- * Where links clicked in a thread (chat markdown, terminal output) open. + +- * Only the desktop app has an in-app browser, so other clients ignore "app". + +- */ + +- browserLinkTarget: BrowserLinkTarget.pipe( + +- Schema.withDecodingDefault(Effect.succeed(DEFAULT_BROWSER_LINK_TARGET)), + +- ), + +- /** + +- * Whether an agent using a preview pops the floating mini player into + ++ * Whether an agent opening a preview pops the floating mini player into + + * view. Only applies when the agent didn't ask either way — an explicit + + * `open`/`show` on `preview_open` still wins, since that is the agent + + * deliberately showing or hiding its work. + +@@ packages/contracts/src/settings.ts: export const ClientSettingsSchema = Schema.Struct({ + + browserAutoShowFloatingPreview: Schema.Boolean.pipe( + + Schema.withDecodingDefault(Effect.succeed(DEFAULT_BROWSER_AUTO_SHOW_FLOATING_PREVIEW)), + + ), + +- /** + +- * User-created browser profiles. The built-in Default and Incognito profiles + +- * are synthesized by `resolveBrowserProfiles`, not stored here, so they + +- * cannot be renamed away or deleted. + +- */ + +- browserProfiles: Schema.Array(BrowserProfile).pipe( + +- Schema.withDecodingDefault(Effect.succeed([])), + +- ), + +- /** Profile new tabs open under. Falls back to Default if it no longer exists. */ + +- browserDefaultProfileId: BrowserProfileId.pipe( + +- Schema.withDecodingDefault(Effect.succeed(DEFAULT_BROWSER_PROFILE_ID)), + +- ), + + // Desktop-only. Boolean values from older settings files decode to their + + // equivalent mode and encode back as the canonical string value. + + confirmQuit: QuitConfirmationModeSetting.pipe( + @@ packages/contracts/src/settings.ts: export const ClientSettingsSchema = Schema.Struct({ + confirmThreadArchive: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), + confirmThreadDelete: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), + @@ packages/contracts/src/settings.ts: export const ClientSettingsSchema = Schema.S + dismissedProviderUpdateNotificationKeys: Schema.Array(TrimmedNonEmptyString).pipe( + Schema.withDecodingDefault(Effect.succeed([])), + ), + + diffIgnoreWhitespace: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), + +- diffLayout: DiffLayout.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_DIFF_LAYOUT))), + + environmentIdentificationMode: EnvironmentIdentificationMode.pipe( + + Schema.withDecodingDefault(Effect.succeed(DEFAULT_ENVIRONMENT_IDENTIFICATION_MODE)), + + ), + @@ packages/contracts/src/settings.ts: export const ClientSettingsSchema = Schema.Struct({ + // default UI; this beta flag restores it (plus the /plan and /default slash + // commands) for users who still rely on the old workflow. + @@ packages/contracts/src/settings.ts: export const ClientSettingsSchema = Schema.S + - // Legacy context window meter. The composer hides it by default; users who + - // still want the old usage indicator can restore it from Settings. + - contextWindowMeterEnabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), + +- // Desktop resting composer. Each trigger that settles an existing thread's + +- // composer into its single-line layout can be turned off on its own. + +- composerCollapseOnBlur: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), + +- composerCollapseOnScroll: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), + +- proactivePanelsEnabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), + - showSkillsInSlashMenu: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), + // Legacy sidebar (the original per-project tree). Deliberately a fresh key + // (was `sidebarV2Enabled` + `sidebarV2ConfiguredByUser`): decoding drops the + // old keys, so everyone, including prior beta opt-outs, resets to the new + +@@ packages/contracts/src/settings.ts: const makeBinaryPathSetting = (fallback: string) => + + Schema.withDecodingDefault(Effect.succeed(fallback)), + + ); + + + +-export type ProviderSettingsFormControl = "text" | "password" | "textarea" | "switch" | "select"; + +- + +-export interface ProviderSettingsFormOption { + +- readonly value: string; + +- readonly label: string; + +-} + ++export type ProviderSettingsFormControl = "text" | "password" | "textarea" | "switch"; + + + + export interface ProviderSettingsFormAnnotation { + + readonly control?: ProviderSettingsFormControl | undefined; + + readonly placeholder?: string | undefined; + + readonly hidden?: boolean | undefined; + + readonly clearWhenEmpty?: "omit" | "persist" | undefined; + +- /** Choices for a `select` control. The first entry is the default. */ + +- readonly options?: ReadonlyArray | undefined; + + } + + + + export interface ProviderSettingsFormSchemaAnnotation { + @@ packages/contracts/src/settings.ts: export const CodexSettings = makeProviderSettingsSchema( + ); + export type CodexSettings = typeof CodexSettings.Type; + @@ packages/contracts/src/settings.ts: export const ClaudeSettings = makeProviderSe + Schema.annotateKey({ providerSettingsForm: { hidden: true } }), + ), + binaryPath: makeBinaryPathSetting("grok").pipe( + -@@ packages/contracts/src/settings.ts: export type GrokSettings = typeof GrokSettings.Type; + +@@ packages/contracts/src/settings.ts: export const GrokSettings = makeProviderSettingsSchema( + + ); + + export type GrokSettings = typeof GrokSettings.Type; + + +-/** + +- * Antigravity ACP auth methods. Personal and Enterprise open a Google sign-in + +- * in the browser. The API key and Agent Platform methods take credentials from + +- * the instance config and never open a browser. + +- */ + +-export const ANTIGRAVITY_AUTH_METHODS = [ + +- { value: "oauth-personal", label: "Google account" }, + +- { value: "oauth-business", label: "Gemini Enterprise" }, + +- { value: "gemini-api-key", label: "Gemini API key" }, + +- { value: "agent-platform", label: "Agent Platform (Vertex AI)" }, + +-] as const satisfies ReadonlyArray; + +-export const AntigravityAuthMethod = Schema.Literals( + +- ANTIGRAVITY_AUTH_METHODS.map((method) => method.value), + +-); + +-export type AntigravityAuthMethod = typeof AntigravityAuthMethod.Type; + +- + +-export const AntigravitySettings = makeProviderSettingsSchema( + +- { + +- enabled: Schema.Boolean.pipe( + +- Schema.withDecodingDefault(Effect.succeed(false)), + +- Schema.annotateKey({ providerSettingsForm: { hidden: true } }), + +- ), + +- authMethod: AntigravityAuthMethod.pipe( + +- Schema.withDecodingDefault(Effect.succeed("oauth-personal" as const)), + +- Schema.annotateKey({ + +- title: "Sign-in method", + +- description: + +- "Google account uses your Antigravity subscription. Gemini Enterprise needs a GCP project and location. API key and Agent Platform bill the credential you enter.", + +- providerSettingsForm: { + +- control: "select", + +- options: ANTIGRAVITY_AUTH_METHODS, + +- clearWhenEmpty: "omit", + +- }, + +- }), + +- ), + +- apiKey: TrimmedString.pipe( + +- Schema.withDecodingDefault(Effect.succeed("")), + +- Schema.annotateKey({ + +- title: "API key", + +- description: + +- "Gemini API key, or a Vertex AI express key for Agent Platform. Stored in plain text on this environment.", + +- providerSettingsForm: { + +- control: "password", + +- placeholder: "Optional", + +- clearWhenEmpty: "omit", + +- }, + +- }), + +- ), + +- gcpProject: TrimmedString.pipe( + +- Schema.withDecodingDefault(Effect.succeed("")), + +- Schema.annotateKey({ + +- title: "GCP project", + +- description: + +- "Required for Gemini Enterprise. Agent Platform uses it when no API key is set.", + +- providerSettingsForm: { placeholder: "my-project-id", clearWhenEmpty: "omit" }, + +- }), + +- ), + +- gcpLocation: TrimmedString.pipe( + +- Schema.withDecodingDefault(Effect.succeed("")), + +- Schema.annotateKey({ + +- title: "GCP location", + +- description: "Region for Gemini Enterprise or Agent Platform, such as us-central1.", + +- providerSettingsForm: { placeholder: "us-central1", clearWhenEmpty: "omit" }, + +- }), + +- ), + +- binaryPath: TrimmedString.pipe( + +- Schema.withDecodingDefault(Effect.succeed("")), + +- Schema.annotateKey({ + +- title: "Binary path", + +- description: + +- "Optional path to the official Antigravity ACP executable. Leave empty for automatic selection.", + +- providerSettingsForm: { placeholder: "Automatic", clearWhenEmpty: "persist" }, + +- }), + +- ), + +- customModels: Schema.Array(Schema.String).pipe( + +- Schema.withDecodingDefault(Effect.succeed([])), + +- Schema.annotateKey({ providerSettingsForm: { hidden: true } }), + +- ), + +- }, + +- { order: ["authMethod", "apiKey", "gcpProject", "gcpLocation", "binaryPath"] }, + +-); + +-export type AntigravitySettings = typeof AntigravitySettings.Type; + +- + export const OpenCodeSettings = makeProviderSettingsSchema( + { + - // Off by default (like Cursor and Grok): the binding is not yet stable + @@ packages/contracts/src/settings.ts: export type GrokSettings = typeof GrokSettin + Schema.annotateKey({ providerSettingsForm: { hidden: true } }), + ), + binaryPath: makeBinaryPathSetting("opencode").pipe( + -@@ packages/contracts/src/settings.ts: export type ServerSettings = typeof ServerSettings.Type; + +@@ packages/contracts/src/settings.ts: export const OpenCodeSettings = makeProviderSettingsSchema( + + ); + + export type OpenCodeSettings = typeof OpenCodeSettings.Type; + + + +-/** + +- * A read-only quota source outside this environment's provider CLIs. The + +- * only kind today is a CLIProxyAPI hub, whose management API reports the + +- * windows of every pooled account. The key travels in settings for now, like + +- * provider environment secrets; it is redacted before reaching a client. + +- */ + +-export const UsageLimitSourceConfig = Schema.Struct({ + +- kind: Schema.Literal("cliproxy"), + +- label: Schema.optional(TrimmedNonEmptyString), + +- url: TrimmedNonEmptyString, + +- managementKey: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))), + +- enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), + +-}); + +-export type UsageLimitSourceConfig = typeof UsageLimitSourceConfig.Type; + +- + + export const ObservabilitySettings = Schema.Struct({ + + otlpTracesUrl: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))), + + otlpMetricsUrl: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))), + +@@ packages/contracts/src/settings.ts: export const ServerSettings = Schema.Struct({ + + defaultThemeSetAt: Schema.String.check(Schema.isMaxLength(64)).pipe( + + Schema.withDecodingDefault(Effect.succeed("")), + + ), + +- /** + +- * The icon clients draw for this environment. Null means "use what the + +- * server detected" (`environment.platform.machine`), falling back to a + +- * generic server. Lives on the server, not the client, so every device + +- * sees the same machine. A kind picked on a newer server decodes as null + +- * here rather than failing the whole settings snapshot for an older client. + +- */ + +- environmentIcon: ForwardCompatibleNullable(EnvironmentMachineKind).pipe( + +- Schema.withDecodingDefault(Effect.succeed(null)), + +- ), + + defaultThreadEnvMode: ThreadEnvMode.pipe( + + Schema.withDecodingDefault(Effect.succeed("local" as const satisfies ThreadEnvMode)), + + ), + +@@ packages/contracts/src/settings.ts: export const ServerSettings = Schema.Struct({ + + cursor: CursorSettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))), + + grok: GrokSettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))), + + opencode: OpenCodeSettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))), + +- antigravity: AntigravitySettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))), + + }).pipe(Schema.withDecodingDefault(Effect.succeed({}))), + + // New driver-agnostic instance map. Keyed by `ProviderInstanceId`; values + + // are `ProviderInstanceConfig` envelopes. The driver-specific config blob + +@@ packages/contracts/src/settings.ts: export const ServerSettings = Schema.Struct({ + + Schema.withDecodingDefault(Effect.succeed({})), + + ), + + observability: ObservabilitySettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))), + +- // Keyed by a user-chosen id so a source keeps its rows across edits. Entries + +- // this build cannot decode round-trip untouched, as provider instances do. + +- usageLimitSources: Schema.Record(UsageLimitSourceId, UsageLimitSourceConfig).pipe( + +- Schema.withDecodingDefault(Effect.succeed({})), + +- ), + + }); + + export type ServerSettings = typeof ServerSettings.Type; + + export const DEFAULT_SERVER_SETTINGS: ServerSettings = Schema.decodeSync(ServerSettings)({}); + + @@ packages/contracts/src/settings.ts: const ClaudeSettingsPatch = Schema.Struct({ + }); + + const CursorSettingsPatch = Schema.Struct({ + +@@ packages/contracts/src/settings.ts: const GrokSettingsPatch = Schema.Struct({ + + customModels: Schema.optionalKey(Schema.Array(Schema.String)), + + }); + + + +-const AntigravitySettingsPatch = Schema.Struct({ + +- enabled: Schema.optionalKey(Schema.Boolean), + +- authMethod: Schema.optionalKey(AntigravityAuthMethod), + +- apiKey: Schema.optionalKey(TrimmedString), + +- gcpProject: Schema.optionalKey(TrimmedString), + +- gcpLocation: Schema.optionalKey(TrimmedString), + +- binaryPath: Schema.optionalKey(TrimmedString), + +- customModels: Schema.optionalKey(Schema.Array(Schema.String)), + +-}); + +- + + const OpenCodeSettingsPatch = Schema.Struct({ + + enabled: Schema.optionalKey(Schema.Boolean), + + binaryPath: Schema.optionalKey(TrimmedString), + +@@ packages/contracts/src/settings.ts: export const ServerSettingsPatch = Schema.Struct({ + + automaticGitFetchInterval: Schema.optionalKey(Schema.DurationFromMillis), + + providerHealthRefreshInterval: Schema.optionalKey(Schema.DurationFromMillis), + + backgroundActivityProfile: Schema.optionalKey(BackgroundActivityProfile), + +- environmentIcon: Schema.optionalKey(Schema.NullOr(EnvironmentMachineKind)), + + defaultThreadEnvMode: Schema.optionalKey(ThreadEnvMode), + + newWorktreesStartFromOrigin: Schema.optionalKey(Schema.Boolean), + + addProjectBaseDirectory: Schema.optionalKey(TrimmedString), + +@@ packages/contracts/src/settings.ts: export const ServerSettingsPatch = Schema.Struct({ + + cursor: Schema.optionalKey(CursorSettingsPatch), + + grok: Schema.optionalKey(GrokSettingsPatch), + + opencode: Schema.optionalKey(OpenCodeSettingsPatch), + +- antigravity: Schema.optionalKey(AntigravitySettingsPatch), + + }), + + ), + + // Whole-map replacement for the new instance config. Patching individual + @@ packages/contracts/src/settings.ts: export const ServerSettingsPatch = Schema.Struct({ + + // patches risk leaving driver-specific config in a half-merged state. + + // The web UI sends a fully-formed map every time it edits this field. + + providerInstances: Schema.optionalKey(Schema.Record(ProviderInstanceId, ProviderInstanceConfig)), + +- // Per-entry, unlike `providerInstances`: a client only ever adds or removes + +- // one source, and sending the whole map races another edit that has not + +- // echoed back yet. `null` removes; the server merges into its current map. + +- usageLimitSources: Schema.optionalKey( + +- Schema.Record(UsageLimitSourceId, Schema.NullOr(UsageLimitSourceConfig)), + +- ), + + }); + export type ServerSettingsPatch = typeof ServerSettingsPatch.Type; + + export const ClientSettingsPatch = Schema.Struct({ + - appearanceContrast: Schema.optionalKey(AppearanceContrast), + +- panelAnimationDurationMs: Schema.optionalKey(PanelAnimationDurationMs), + browserDefaultViewport: Schema.optionalKey(PreviewViewportSetting), + browserDefaultZoomFactor: Schema.optionalKey(PreviewZoomFactor), + browserDefaultAppearance: Schema.optionalKey(PreviewAppearancePreference), + -@@ packages/contracts/src/settings.ts: export const ClientSettingsPatch = Schema.Struct({ + + browserRecordingFrameRate: Schema.optionalKey(BrowserRecordingFrameRate), + +- browserLinkTarget: Schema.optionalKey(BrowserLinkTarget), + + browserAutoShowFloatingPreview: Schema.optionalKey(Schema.Boolean), + +- browserProfiles: Schema.optionalKey(Schema.Array(BrowserProfile)), + +- browserDefaultProfileId: Schema.optionalKey(BrowserProfileId), + + confirmQuit: Schema.optionalKey(QuitConfirmationMode), + confirmThreadArchive: Schema.optionalKey(Schema.Boolean), + confirmThreadDelete: Schema.optionalKey(Schema.Boolean), + confirmThreadUnpin: Schema.optionalKey(Schema.Boolean), + - continueThreadsAfterServerUpdate: Schema.optionalKey(Schema.Boolean), + diffIgnoreWhitespace: Schema.optionalKey(Schema.Boolean), + +- diffLayout: Schema.optionalKey(DiffLayout), + environmentIdentificationMode: Schema.optionalKey(EnvironmentIdentificationMode), + glassOpacity: Schema.optionalKey(GlassOpacity), + + fontSizeInterface: Schema.optionalKey(InterfaceFontSize), + @@ packages/contracts/src/settings.ts: export const ClientSettingsPatch = Schema.Struct({ + ), + ), + planModeEnabled: Schema.optionalKey(Schema.Boolean), + - contextWindowMeterEnabled: Schema.optionalKey(Schema.Boolean), + +- composerCollapseOnBlur: Schema.optionalKey(Schema.Boolean), + +- composerCollapseOnScroll: Schema.optionalKey(Schema.Boolean), + +- proactivePanelsEnabled: Schema.optionalKey(Schema.Boolean), + - showSkillsInSlashMenu: Schema.optionalKey(Schema.Boolean), + legacySidebarEnabled: Schema.optionalKey(Schema.Boolean), + sidebarProjectGroupingMode: Schema.optionalKey(SidebarProjectGroupingMode), + @@ packages/effect-codex-app-server/scripts/generate.ts: function stripNullDefaults + + ) as typeof Schema.Json.Type; + } + + - function toPascalCaseMethod(method: string) { + + // Codex 0.153 adds async questions to agent messages. Keep older protocol + @@ packages/effect-codex-app-server/scripts/generate.ts: function resolveResponseTypeName( + const overrides: Record = { + "account/logout": "LogoutAccountResponse", + @@ packages/effect-codex-app-server/src/_generated/namespaces.gen.ts: export const + WindowsSandboxSetupStartParams: CodexSchema.V2WindowsSandboxSetupStartParams, + WindowsSandboxSetupStartResponse: CodexSchema.V2WindowsSandboxSetupStartResponse, + + - ## packages/effect-codex-app-server/src/_generated/schema.gen.ts ## + -@@ + - // This file is generated by the effect-codex-app-server package. Do not edit manually. + --// Upstream protocol ref: 678157acaa819d5510adfe359abb5d0392cfe461 + -+// Upstream protocol ref: dbfe855f4fd0f5dcdf079882652a8efe622b0595 + - + - import * as Schema from "effect/Schema"; + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__AbsolutePathBuf = Schema.String.annotate({ + - "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + - }); + - + --export type ClientRequest__AddCreditsNudgeCreditType = "credits" | "usage_limit"; + --export const ClientRequest__AddCreditsNudgeCreditType = Schema.Literals(["credits", "usage_limit"]); + -- + --export type ClientRequest__AdditionalContextKind = "untrusted" | "application"; + --export const ClientRequest__AdditionalContextKind = Schema.Literals(["untrusted", "application"]); + -- + --export type ClientRequest__AgentMessageInputContent = + -- | { readonly text: string; readonly type: "input_text" } + -- | { readonly encrypted_content: string; readonly type: "encrypted_content" }; + --export const ClientRequest__AgentMessageInputContent = Schema.Union( + -- [ + -- Schema.Struct({ + -- text: Schema.String, + -- type: Schema.Literal("input_text").annotate({ + -- title: "InputTextAgentMessageInputContentType", + -- }), + -- }).annotate({ title: "InputTextAgentMessageInputContent" }), + -- Schema.Struct({ + -- encrypted_content: Schema.String, + -- type: Schema.Literal("encrypted_content").annotate({ + -- title: "EncryptedContentAgentMessageInputContentType", + -- }), + -- }).annotate({ title: "EncryptedContentAgentMessageInputContent" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type ClientRequest__ApprovalsReviewer = "user" | "auto_review" | "guardian_subagent"; + -+export type ClientRequest__ApprovalsReviewer = "user" | "guardian_subagent"; + - export const ClientRequest__ApprovalsReviewer = Schema.Literals([ + - "user", + -- "auto_review", + - "guardian_subagent", + - ]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }); + - + --export type ClientRequest__AppsInstalledParams = { + -- readonly forceRefresh?: boolean; + -- readonly threadId?: string | null; + --}; + --export const ClientRequest__AppsInstalledParams = Schema.Struct({ + -- forceRefresh: Schema.optionalKey( + -- Schema.Boolean.annotate({ + -- description: + -- "When true and Apps are permitted, refresh and publish the hosted connector runtime tool snapshot first.", + -- }), + -- ), + -- threadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Optional loaded thread id used to evaluate effective app configuration.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}).annotate({ description: "Read the committed installed connector runtime snapshot." }); + -- + - export type ClientRequest__AppsListParams = { + - readonly cursor?: string | null; + - readonly forceRefetch?: boolean; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__AppsListParams = Schema.Struct({ + - ), + - }).annotate({ description: "EXPERIMENTAL - list available apps/connectors." }); + - + --export type ClientRequest__AppsReadParams = { + -- readonly appIds: ReadonlyArray; + -- readonly includeTools?: boolean; + --}; + --export const ClientRequest__AppsReadParams = Schema.Struct({ + -- appIds: Schema.Array(Schema.String).annotate({ + -- description: + -- "App ids to read. The server accepts at most 100 ids and deduplicates repeated ids while preserving their first-request order.", + -- }), + -- includeTools: Schema.optionalKey( + -- Schema.Boolean.annotate({ + -- description: + -- "When true, include display-only public tool summaries in the returned metadata.", + -- }), + -- ), + --}).annotate({ description: "EXPERIMENTAL - read metadata for specific apps/connectors." }); + -- + - export type ClientRequest__AskForApproval = + - | "untrusted" + -+ | "on-failure" + - | "on-request" + - | "never" + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest__AskForApproval = + - }; + - export const ClientRequest__AskForApproval = Schema.Union( + - [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -+ Schema.Literals(["untrusted", "on-failure", "on-request", "never"]), + - Schema.Struct({ + - granular: Schema.Struct({ + - mcp_elicitations: Schema.Boolean, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__CommandExecWriteParams = Schema.Struct({ + - description: "Write stdin bytes to a running `command/exec` session, close stdin, or both.", + - }); + - + --export type ClientRequest__CommandMigration = { readonly name: string }; + --export const ClientRequest__CommandMigration = Schema.Struct({ name: Schema.String }); + -- + - export type ClientRequest__ConfigReadParams = { + - readonly cwd?: string | null; + - readonly includeLayers?: boolean; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ConfigReadParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- includeLayers: Schema.optionalKey(Schema.Boolean), + --}); + -- + --export type ClientRequest__ConsumeAccountRateLimitResetCreditParams = { + -- readonly creditId?: string | null; + -- readonly idempotencyKey: string; + --}; + --export const ClientRequest__ConsumeAccountRateLimitResetCreditParams = Schema.Struct({ + -- creditId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Opaque reset-credit identifier to redeem. When omitted, the backend selects the next available credit.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- idempotencyKey: Schema.String.annotate({ + -- description: + -- "Identifies one logical reset attempt. A UUID is recommended; reuse the same value when retrying that attempt.", + -- }), + -+ includeLayers: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - }); + - + --export type ClientRequest__ConversationTextRole = "user" | "developer" | "assistant"; + --export const ClientRequest__ConversationTextRole = Schema.Literals([ + -- "user", + -- "developer", + -- "assistant", + --]); + -- + --export type ClientRequest__DynamicToolNamespaceTool = { + -- readonly deferLoading?: boolean; + -- readonly description: string; + -- readonly inputSchema: unknown; + -- readonly name: string; + -- readonly type: "function"; + --}; + --export const ClientRequest__DynamicToolNamespaceTool = Schema.Union( + -+export type ClientRequest__ContentItem = + -+ | { readonly text: string; readonly type: "input_text" } + -+ | { readonly image_url: string; readonly type: "input_image" } + -+ | { readonly text: string; readonly type: "output_text" }; + -+export const ClientRequest__ContentItem = Schema.Union( + - [ + - Schema.Struct({ + -- deferLoading: Schema.optionalKey(Schema.Boolean), + -- description: Schema.String, + -- inputSchema: Schema.Unknown, + -- name: Schema.String, + -- type: Schema.Literal("function").annotate({ title: "FunctionDynamicToolNamespaceToolType" }), + -- }).annotate({ title: "FunctionDynamicToolNamespaceTool" }), + -+ text: Schema.String, + -+ type: Schema.Literal("input_text").annotate({ title: "InputTextContentItemType" }), + -+ }).annotate({ title: "InputTextContentItem" }), + -+ Schema.Struct({ + -+ image_url: Schema.String, + -+ type: Schema.Literal("input_image").annotate({ title: "InputImageContentItemType" }), + -+ }).annotate({ title: "InputImageContentItem" }), + -+ Schema.Struct({ + -+ text: Schema.String, + -+ type: Schema.Literal("output_text").annotate({ title: "OutputTextContentItemType" }), + -+ }).annotate({ title: "OutputTextContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ExperimentalFeatureEnablementSetParams = Schema.Stru + - export type ClientRequest__ExperimentalFeatureListParams = { + - readonly cursor?: string | null; + - readonly limit?: number | null; + -- readonly threadId?: string | null; + - }; + - export const ClientRequest__ExperimentalFeatureListParams = Schema.Struct({ + - cursor: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ExperimentalFeatureListParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- threadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional loaded thread id. Pass this when showing feature state for an existing thread so enablement is computed from that thread's refreshed config, including project-local config for the thread's cwd.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - }); + - + - export type ClientRequest__ExternalAgentConfigDetectParams = { + - readonly cwds?: ReadonlyArray | null; + - readonly includeHome?: boolean; + -- readonly migrationSource?: string | null; + -- readonly source?: string | null; + - }; + - export const ClientRequest__ExternalAgentConfigDetectParams = Schema.Struct({ + - cwds: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ExternalAgentConfigDetectParams = Schema.Struct({ + - ), + - includeHome: Schema.optionalKey( + - Schema.Boolean.annotate({ + -- description: "If true, include detection under the user's home directory.", + -+ description: "If true, include detection under the user's home (~/.claude, ~/.codex, etc.).", + - }), + - ), + -- migrationSource: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional migration-source selector. Missing or unrecognized values use the default source.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- source: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Deprecated field retained for compatibility. This field is ignored; use `migrationSource` to select the migration source.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - }); + - + - export type ClientRequest__ExternalAgentConfigMigrationItemType = + - | "AGENTS_MD" + - | "CONFIG" + - | "SKILLS" + -- | "PLUGINS" + -- | "MCP_SERVER_CONFIG" + -- | "SUBAGENTS" + -- | "HOOKS" + -- | "COMMANDS" + -- | "MEMORY" + -- | "SESSIONS"; + -+ | "MCP_SERVER_CONFIG"; + - export const ClientRequest__ExternalAgentConfigMigrationItemType = Schema.Literals([ + - "AGENTS_MD", + - "CONFIG", + - "SKILLS", + -- "PLUGINS", + - "MCP_SERVER_CONFIG", + -- "SUBAGENTS", + -- "HOOKS", + -- "COMMANDS", + -- "MEMORY", + -- "SESSIONS", + - ]); + - + - export type ClientRequest__FeedbackUploadParams = { + - readonly classification: string; + - readonly extraLogFiles?: ReadonlyArray | null; + -- readonly includeLogs?: boolean; + -+ readonly includeLogs: boolean; + - readonly reason?: string | null; + -- readonly tags?: { readonly [x: string]: string } | null; + - readonly threadId?: string | null; + - }; + - export const ClientRequest__FeedbackUploadParams = Schema.Struct({ + - classification: Schema.String, + - extraLogFiles: Schema.optionalKey(Schema.Union([Schema.Array(Schema.String), Schema.Null])), + -- includeLogs: Schema.optionalKey(Schema.Boolean), + -+ includeLogs: Schema.Boolean, + - reason: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- tags: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.String), Schema.Null]), + -- ), + - threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__GetAccountParams = Schema.Struct({ + - Schema.Boolean.annotate({ + - description: + - "When `true`, requests a proactive token refresh before returning.\n\nIn managed auth mode this triggers the normal refresh-token flow. In external auth mode this flag is ignored. Clients should refresh tokens themselves and call `account/login/start` with `chatgptAuthTokens`.", + -+ default: false, + - }), + - ), + - }); + - + --export type ClientRequest__HookMigration = { readonly name: string }; + --export const ClientRequest__HookMigration = Schema.Struct({ name: Schema.String }); + -- + --export type ClientRequest__HooksListParams = { readonly cwds?: ReadonlyArray }; + --export const ClientRequest__HooksListParams = Schema.Struct({ + -- cwds: Schema.optionalKey( + -- Schema.Array(Schema.String).annotate({ + -- description: "When empty, defaults to the current session working directory.", + -- }), + -- ), + --}); + -+export type ClientRequest__GhostCommit = { + -+ readonly id: string; + -+ readonly parent?: string | null; + -+ readonly preexisting_untracked_dirs: ReadonlyArray; + -+ readonly preexisting_untracked_files: ReadonlyArray; + -+}; + -+export const ClientRequest__GhostCommit = Schema.Struct({ + -+ id: Schema.String, + -+ parent: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ preexisting_untracked_dirs: Schema.Array(Schema.String), + -+ preexisting_untracked_files: Schema.Array(Schema.String), + -+}).annotate({ description: "Details of a ghost commit created from a repository state." }); + - + - export type ClientRequest__ImageDetail = "auto" | "low" | "high" | "original"; + - export const ClientRequest__ImageDetail = Schema.Literals(["auto", "low", "high", "original"]); + - + - export type ClientRequest__InitializeCapabilities = { + - readonly experimentalApi?: boolean; + -- readonly mcpServerOpenaiFormElicitation?: boolean; + - readonly optOutNotificationMethods?: ReadonlyArray | null; + -- readonly requestAttestation?: boolean; + - }; + - export const ClientRequest__InitializeCapabilities = Schema.Struct({ + - experimentalApi: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__InitializeCapabilities = Schema.Struct({ + - default: false, + - }), + - ), + -- mcpServerOpenaiFormElicitation: Schema.optionalKey( + -- Schema.Boolean.annotate({ + -- description: "Allow downstream MCP servers to request OpenAI extended form elicitations.", + -- }), + -- ), + - optOutNotificationMethods: Schema.optionalKey( + - Schema.Union([ + - Schema.Array(Schema.String).annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__InitializeCapabilities = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- requestAttestation: Schema.optionalKey( + -- Schema.Boolean.annotate({ + -- description: "Opt into `attestation/generate` requests for upstream `x-oai-attestation`.", + -- default: false, + -- }), + -- ), + - }).annotate({ description: "Client-declared capabilities negotiated during initialize." }); + - + --export type ClientRequest__InternalChatMessageMetadataPassthrough = { + -- readonly turn_id?: string | null; + --}; + --export const ClientRequest__InternalChatMessageMetadataPassthrough = Schema.Struct({ + -- turn_id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}).annotate({ + -- description: + -- "Internal Responses API passthrough metadata copied into underlying chat messages.\n\nResponses API strongly types this payload. Do not modify it without first getting API approval and making the corresponding Responses API change.", + --}); + -- + --export type ClientRequest__LegacyAppPathString = string; + --export const ClientRequest__LegacyAppPathString = Schema.String; + -- + - export type ClientRequest__LocalShellAction = { + - readonly command: ReadonlyArray; + - readonly env?: { readonly [x: string]: string } | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__LocalShellStatus = Schema.Literals([ + - "incomplete", + - ]); + - + --export type ClientRequest__LoginAppBrand = "codex" | "chatgpt"; + --export const ClientRequest__LoginAppBrand = Schema.Literals(["codex", "chatgpt"]); + -- + --export type ClientRequest__MarketplaceAddParams = { + -- readonly refName?: string | null; + -- readonly source: string; + -- readonly sparsePaths?: ReadonlyArray | null; + --}; + --export const ClientRequest__MarketplaceAddParams = Schema.Struct({ + -- refName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- source: Schema.String, + -- sparsePaths: Schema.optionalKey(Schema.Union([Schema.Array(Schema.String), Schema.Null])), + --}); + -- + --export type ClientRequest__MarketplaceRemoveParams = { readonly marketplaceName: string }; + --export const ClientRequest__MarketplaceRemoveParams = Schema.Struct({ + -- marketplaceName: Schema.String, + --}); + -- + --export type ClientRequest__MarketplaceUpgradeParams = { readonly marketplaceName?: string | null }; + --export const ClientRequest__MarketplaceUpgradeParams = Schema.Struct({ + -- marketplaceName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -+export type ClientRequest__LoginAccountParams = + -+ | { readonly apiKey: string; readonly type: "apiKey" } + -+ | { readonly type: "chatgpt" } + -+ | { readonly type: "chatgptDeviceCode" } + -+ | { + -+ readonly accessToken: string; + -+ readonly chatgptAccountId: string; + -+ readonly chatgptPlanType?: string | null; + -+ readonly type: "chatgptAuthTokens"; + -+ }; + -+export const ClientRequest__LoginAccountParams = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ apiKey: Schema.String, + -+ type: Schema.Literal("apiKey").annotate({ title: "ApiKeyLoginAccountParamsType" }), + -+ }).annotate({ title: "ApiKeyLoginAccountParams" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("chatgpt").annotate({ title: "ChatgptLoginAccountParamsType" }), + -+ }).annotate({ title: "ChatgptLoginAccountParams" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("chatgptDeviceCode").annotate({ + -+ title: "ChatgptDeviceCodeLoginAccountParamsType", + -+ }), + -+ }).annotate({ title: "ChatgptDeviceCodeLoginAccountParams" }), + -+ Schema.Struct({ + -+ accessToken: Schema.String.annotate({ + -+ description: + -+ "Access token (JWT) supplied by the client. This token is used for backend API requests and email extraction.", + -+ }), + -+ chatgptAccountId: Schema.String.annotate({ + -+ description: "Workspace/account identifier supplied by the client.", + -+ }), + -+ chatgptPlanType: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ + -+ description: + -+ "Optional plan type supplied by the client.\n\nWhen `null`, Codex attempts to derive the plan type from access-token claims. If unavailable, the plan defaults to `unknown`.", + -+ }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ type: Schema.Literal("chatgptAuthTokens").annotate({ + -+ title: "ChatgptAuthTokensLoginAccountParamsType", + -+ }), + -+ }).annotate({ + -+ title: "ChatgptAuthTokensLoginAccountParams", + -+ description: + -+ "[UNSTABLE] FOR OPENAI INTERNAL USE ONLY - DO NOT USE. The access token must contain the same scopes that Codex-managed ChatGPT auth tokens have.", + -+ }), + -+ ], + -+ { mode: "oneOf" }, + -+); + - + - export type ClientRequest__McpResourceReadParams = { + - readonly server: string; + -- readonly threadId?: string | null; + -+ readonly threadId: string; + - readonly uri: string; + - }; + - export const ClientRequest__McpResourceReadParams = Schema.Struct({ + - server: Schema.String, + -- threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ threadId: Schema.String, + - uri: Schema.String, + - }); + - + --export type ClientRequest__McpServerMigration = { readonly name: string }; + --export const ClientRequest__McpServerMigration = Schema.Struct({ name: Schema.String }); + -- + - export type ClientRequest__McpServerOauthLoginParams = { + - readonly name: string; + - readonly scopes?: ReadonlyArray | null; + -- readonly threadId?: string | null; + - readonly timeoutSecs?: number | null; + - }; + - export const ClientRequest__McpServerOauthLoginParams = Schema.Struct({ + - name: Schema.String, + - scopes: Schema.optionalKey(Schema.Union([Schema.Array(Schema.String), Schema.Null])), + -- threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - timeoutSecs: Schema.optionalKey( + - Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ModelListParams = Schema.Struct({ + - ), + - }); + - + --export type ClientRequest__ModelProviderCapabilitiesReadParams = {}; + --export const ClientRequest__ModelProviderCapabilitiesReadParams = Schema.Struct({}); + -- + --export type ClientRequest__PermissionProfileListParams = { + -- readonly cursor?: string | null; + -- readonly cwd?: string | null; + -- readonly limit?: number | null; + --}; + --export const ClientRequest__PermissionProfileListParams = Schema.Struct({ + -- cursor: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Opaque pagination cursor returned by a previous call.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- cwd: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Optional working directory to resolve project config layers.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- limit: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Optional page size; defaults to the full result set.", + -- format: "uint32", + -- }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + - export type ClientRequest__Personality = "none" | "friendly" | "pragmatic"; + - export const ClientRequest__Personality = Schema.Literals(["none", "friendly", "pragmatic"]); + - + --export type ClientRequest__PluginListMarketplaceKind = + -- | "local" + -- | "vertical" + -- | "workspace-directory" + -- | "shared-with-me" + -- | "created-by-me-remote"; + --export const ClientRequest__PluginListMarketplaceKind = Schema.Literals([ + -- "local", + -- "vertical", + -- "workspace-directory", + -- "shared-with-me", + -- "created-by-me-remote", + --]); + -- + --export type ClientRequest__PluginShareCheckoutParams = { readonly remotePluginId: string }; + --export const ClientRequest__PluginShareCheckoutParams = Schema.Struct({ + -- remotePluginId: Schema.String, + --}); + -- + --export type ClientRequest__PluginShareDeleteParams = { readonly remotePluginId: string }; + --export const ClientRequest__PluginShareDeleteParams = Schema.Struct({ + -- remotePluginId: Schema.String, + --}); + -- + --export type ClientRequest__PluginShareDiscoverability = "LISTED" | "UNLISTED" | "PRIVATE"; + --export const ClientRequest__PluginShareDiscoverability = Schema.Literals([ + -- "LISTED", + -- "UNLISTED", + -- "PRIVATE", + --]); + -- + --export type ClientRequest__PluginShareListParams = {}; + --export const ClientRequest__PluginShareListParams = Schema.Struct({}); + -- + --export type ClientRequest__PluginSharePrincipalType = "user" | "group" | "workspace"; + --export const ClientRequest__PluginSharePrincipalType = Schema.Literals([ + -- "user", + -- "group", + -- "workspace", + --]); + -- + --export type ClientRequest__PluginShareTargetRole = "reader" | "editor"; + --export const ClientRequest__PluginShareTargetRole = Schema.Literals(["reader", "editor"]); + -- + --export type ClientRequest__PluginShareUpdateDiscoverability = "UNLISTED" | "PRIVATE" | "LISTED"; + --export const ClientRequest__PluginShareUpdateDiscoverability = Schema.Literals([ + -- "UNLISTED", + -- "PRIVATE", + -- "LISTED", + --]); + -- + --export type ClientRequest__PluginSkillReadParams = { + -- readonly remoteMarketplaceName: string; + -- readonly remotePluginId: string; + -- readonly skillName: string; + -+export type ClientRequest__PluginUninstallParams = { + -+ readonly forceRemoteSync?: boolean; + -+ readonly pluginId: string; + - }; + --export const ClientRequest__PluginSkillReadParams = Schema.Struct({ + -- remoteMarketplaceName: Schema.String, + -- remotePluginId: Schema.String, + -- skillName: Schema.String, + -+export const ClientRequest__PluginUninstallParams = Schema.Struct({ + -+ forceRemoteSync: Schema.optionalKey( + -+ Schema.Boolean.annotate({ + -+ description: "When true, apply the remote plugin change before the local uninstall flow.", + -+ }), + -+ ), + -+ pluginId: Schema.String, + - }); + - + --export type ClientRequest__PluginUninstallParams = { readonly pluginId: string }; + --export const ClientRequest__PluginUninstallParams = Schema.Struct({ pluginId: Schema.String }); + -- + --export type ClientRequest__PluginsMigration = { + -- readonly marketplaceName: string; + -- readonly pluginNames: ReadonlyArray; + --}; + --export const ClientRequest__PluginsMigration = Schema.Struct({ + -- marketplaceName: Schema.String, + -- pluginNames: Schema.Array(Schema.String), + -+export type ClientRequest__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const ClientRequest__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + - }); + - + --export type ClientRequest__ReasoningEffort = string; + --export const ClientRequest__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + - export type ClientRequest__ReasoningItemContent = + - | { readonly text: string; readonly type: "reasoning_text" } + - | { readonly text: string; readonly type: "text" }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__SandboxMode = Schema.Literals([ + - "danger-full-access", + - ]); + - + --export type ClientRequest__SessionMigration = { + -+export type ClientRequest__ServiceTier = "fast" | "flex"; + -+export const ClientRequest__ServiceTier = Schema.Literals(["fast", "flex"]); + -+ + -+export type ClientRequest__SkillsListExtraRootsForCwd = { + - readonly cwd: string; + -- readonly path: string; + -- readonly title?: string | null; + -+ readonly extraUserRoots: ReadonlyArray; + - }; + --export const ClientRequest__SessionMigration = Schema.Struct({ + -+export const ClientRequest__SkillsListExtraRootsForCwd = Schema.Struct({ + - cwd: Schema.String, + -- path: Schema.String, + -- title: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ extraUserRoots: Schema.Array(Schema.String), + - }); + - + --export type ClientRequest__SkillMigration = { readonly name: string }; + --export const ClientRequest__SkillMigration = Schema.Struct({ name: Schema.String }); + -- + --export type ClientRequest__SkillsListParams = { + -- readonly cwds?: ReadonlyArray; + -- readonly forceReload?: boolean; + --}; + --export const ClientRequest__SkillsListParams = Schema.Struct({ + -- cwds: Schema.optionalKey( + -- Schema.Array(Schema.String).annotate({ + -- description: "When empty, defaults to the current session working directory.", + -- }), + -- ), + -- forceReload: Schema.optionalKey( + -- Schema.Boolean.annotate({ + -- description: "When true, bypass the skills cache and re-scan skills from disk.", + -- }), + -- ), + --}); + -- + --export type ClientRequest__SortDirection = "asc" | "desc"; + --export const ClientRequest__SortDirection = Schema.Literals(["asc", "desc"]); + -- + --export type ClientRequest__SubagentMigration = { readonly name: string }; + --export const ClientRequest__SubagentMigration = Schema.Struct({ name: Schema.String }); + -- + - export type ClientRequest__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + - readonly placeholder?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__TextElement = Schema.Struct({ + - ), + - }); + - + --export type ClientRequest__ThreadApproveGuardianDeniedActionParams = { + -- readonly event: unknown; + -- readonly threadId: string; + --}; + --export const ClientRequest__ThreadApproveGuardianDeniedActionParams = Schema.Struct({ + -- event: Schema.Unknown.annotate({ + -- description: "Serialized `codex_protocol::protocol::GuardianAssessmentEvent`.", + -- }), + -- threadId: Schema.String, + --}); + -- + - export type ClientRequest__ThreadArchiveParams = { readonly threadId: string }; + - export const ClientRequest__ThreadArchiveParams = Schema.Struct({ threadId: Schema.String }); + - + - export type ClientRequest__ThreadCompactStartParams = { readonly threadId: string }; + - export const ClientRequest__ThreadCompactStartParams = Schema.Struct({ threadId: Schema.String }); + - + --export type ClientRequest__ThreadDeleteParams = { readonly threadId: string }; + --export const ClientRequest__ThreadDeleteParams = Schema.Struct({ threadId: Schema.String }); + -- + --export type ClientRequest__ThreadGoalClearParams = { readonly threadId: string }; + --export const ClientRequest__ThreadGoalClearParams = Schema.Struct({ threadId: Schema.String }); + -- + --export type ClientRequest__ThreadGoalGetParams = { readonly threadId: string }; + --export const ClientRequest__ThreadGoalGetParams = Schema.Struct({ threadId: Schema.String }); + -- + --export type ClientRequest__ThreadGoalStatus = + -- | "active" + -- | "paused" + -- | "blocked" + -- | "usageLimited" + -- | "budgetLimited" + -- | "complete"; + --export const ClientRequest__ThreadGoalStatus = Schema.Literals([ + -- "active", + -- "paused", + -- "blocked", + -- "usageLimited", + -- "budgetLimited", + -- "complete", + --]); + -- + --export type ClientRequest__ThreadInjectItemsParams = { + -- readonly items: ReadonlyArray; + -- readonly threadId: string; + --}; + --export const ClientRequest__ThreadInjectItemsParams = Schema.Struct({ + -- items: Schema.Array(Schema.Unknown).annotate({ + -- description: "Raw Responses API items to append to the thread's model-visible history.", + -- }), + -- threadId: Schema.String, + --}); + -- + --export type ClientRequest__ThreadListCwdFilter = string | ReadonlyArray; + --export const ClientRequest__ThreadListCwdFilter = Schema.Union([ + -- Schema.String, + -- Schema.Array(Schema.String), + --]); + -- + - export type ClientRequest__ThreadLoadedListParams = { + - readonly cursor?: string | null; + - readonly limit?: number | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ThreadReadParams = Schema.Struct({ + - includeTurns: Schema.optionalKey( + - Schema.Boolean.annotate({ + - description: "When true, include turns and their items from rollout history.", + -+ default: false, + - }), + - ), + - threadId: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ThreadRollbackParams = Schema.Struct({ + - .check(Schema.isInt()) + - .check(Schema.isGreaterThanOrEqualTo(0)), + - threadId: Schema.String, + --}).annotate({ description: "DEPRECATED: `thread/rollback` will be removed soon." }); + -+}); + - + - export type ClientRequest__ThreadSetNameParams = { + - readonly name: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ThreadShellCommandParams = Schema.Struct({ + - threadId: Schema.String, + - }); + - + --export type ClientRequest__ThreadSortKey = "created_at" | "updated_at" | "recency_at"; + --export const ClientRequest__ThreadSortKey = Schema.Literals([ + -- "created_at", + -- "updated_at", + -- "recency_at", + --]); + -- + --export type ClientRequest__ThreadSource = string; + --export const ClientRequest__ThreadSource = Schema.String; + -+export type ClientRequest__ThreadSortKey = "created_at" | "updated_at"; + -+export const ClientRequest__ThreadSortKey = Schema.Literals(["created_at", "updated_at"]); + - + - export type ClientRequest__ThreadSourceKind = + - | "cli" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__TurnInterruptParams = Schema.Struct({ + - turnId: Schema.String, + - }); + - + --export type ClientRequest__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const ClientRequest__TurnItemsView = Schema.Literals(["notLoaded", "summary", "full"]); + -- + - export type ClientRequest__WindowsSandboxSetupMode = "elevated" | "unelevated"; + - export const ClientRequest__WindowsSandboxSetupMode = Schema.Literals(["elevated", "unelevated"]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const CommandExecutionRequestApprovalParams__AdditionalNetworkPermissions + - enabled: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - }); + - + --export type CommandExecutionRequestApprovalParams__FileSystemAccessMode = "read" | "write" | "deny"; + --export const CommandExecutionRequestApprovalParams__FileSystemAccessMode = Schema.Literals([ + -- "read", + -- "write", + -- "deny", + --]); + -- + --export type CommandExecutionRequestApprovalParams__LegacyAppPathString = string; + --export const CommandExecutionRequestApprovalParams__LegacyAppPathString = Schema.String; + -+export type CommandExecutionRequestApprovalParams__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const CommandExecutionRequestApprovalParams__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + - + - export type CommandExecutionRequestApprovalParams__NetworkApprovalProtocol = + - | "http" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const CommandExecutionRequestApprovalResponse__NetworkPolicyRuleAction = + - + - export type DynamicToolCallResponse__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const DynamicToolCallResponse__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const DynamicToolCallResponse__DynamicToolCallOutputContentItem = Schema. + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const PermissionsRequestApprovalParams__AdditionalNetworkPermissions = Sc + - enabled: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - }); + - + --export type PermissionsRequestApprovalParams__FileSystemAccessMode = "read" | "write" | "deny"; + --export const PermissionsRequestApprovalParams__FileSystemAccessMode = Schema.Literals([ + -- "read", + -- "write", + -- "deny", + --]); + -- + --export type PermissionsRequestApprovalParams__LegacyAppPathString = string; + --export const PermissionsRequestApprovalParams__LegacyAppPathString = Schema.String; + -+export type PermissionsRequestApprovalResponse__AbsolutePathBuf = string; + -+export const PermissionsRequestApprovalResponse__AbsolutePathBuf = Schema.String.annotate({ + -+ description: + -+ "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -+}); + - + - export type PermissionsRequestApprovalResponse__AdditionalNetworkPermissions = { + - readonly enabled?: boolean | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const PermissionsRequestApprovalResponse__AdditionalNetworkPermissions = + - enabled: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - }); + - + --export type PermissionsRequestApprovalResponse__FileSystemAccessMode = "read" | "write" | "deny"; + --export const PermissionsRequestApprovalResponse__FileSystemAccessMode = Schema.Literals([ + -- "read", + -- "write", + -- "deny", + --]); + -- + --export type PermissionsRequestApprovalResponse__LegacyAppPathString = string; + --export const PermissionsRequestApprovalResponse__LegacyAppPathString = Schema.String; + -- + - export type ServerNotification__AbsolutePathBuf = string; + - export const ServerNotification__AbsolutePathBuf = Schema.String.annotate({ + - description: + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__AccountLoginCompletedNotification = Schema.Stru + - success: Schema.Boolean, + - }); + - + --export type ServerNotification__ActivePermissionProfile = { + -- readonly extends?: string | null; + -- readonly id: string; + --}; + --export const ServerNotification__ActivePermissionProfile = Schema.Struct({ + -- extends: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Parent profile identifier from the selected permissions profile's `extends` setting, when present.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- id: Schema.String.annotate({ + -- description: + -- "Identifier from `default_permissions` or the implicit built-in default, such as `:workspace` or a user-defined `[permissions.]` profile.", + -- }), + --}); + -- + --export type ServerNotification__AdditionalNetworkPermissions = { + -- readonly enabled?: boolean | null; + --}; + --export const ServerNotification__AdditionalNetworkPermissions = Schema.Struct({ + -- enabled: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + --}); + -- + - export type ServerNotification__AgentMessageDeltaNotification = { + - readonly delta: string; + - readonly itemId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__AppScreenshot = Schema.Struct({ + - userPrompt: Schema.String, + - }); + - + --export type ServerNotification__ApprovalsReviewer = "user" | "auto_review" | "guardian_subagent"; + --export const ServerNotification__ApprovalsReviewer = Schema.Literals([ + -- "user", + -- "auto_review", + -- "guardian_subagent", + --]).annotate({ + -- description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + --}); + -- + --export type ServerNotification__AskForApproval = + -- | "untrusted" + -- | "on-request" + -- | "never" + -- | { + -- readonly granular: { + -- readonly mcp_elicitations: boolean; + -- readonly request_permissions?: boolean; + -- readonly rules: boolean; + -- readonly sandbox_approval: boolean; + -- readonly skill_approval?: boolean; + -- }; + -- }; + --export const ServerNotification__AskForApproval = Schema.Union( + -- [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -- Schema.Struct({ + -- granular: Schema.Struct({ + -- mcp_elicitations: Schema.Boolean, + -- request_permissions: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- rules: Schema.Boolean, + -- sandbox_approval: Schema.Boolean, + -- skill_approval: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- }), + -- }).annotate({ title: "GranularAskForApproval" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type ServerNotification__AuthMode = + -- | "apikey" + -- | "chatgpt" + -- | "chatgptAuthTokens" + -- | "headers" + -- | "agentIdentity" + -- | "personalAccessToken" + -- | "bedrockApiKey"; + -+export type ServerNotification__AuthMode = "apikey" | "chatgpt" | "chatgptAuthTokens"; + - export const ServerNotification__AuthMode = Schema.Literals([ + - "apikey", + - "chatgpt", + - "chatgptAuthTokens", + -- "headers", + -- "agentIdentity", + -- "personalAccessToken", + -- "bedrockApiKey", + - ]).annotate({ description: "Authentication mode for OpenAI-backed providers." }); + - + - export type ServerNotification__AutoReviewDecisionSource = "agent"; + - export const ServerNotification__AutoReviewDecisionSource = Schema.Literal("agent").annotate({ + -- description: "[UNSTABLE] Source that produced a terminal approval auto-review decision.", + -+ description: "[UNSTABLE] Source that produced a terminal guardian approval review decision.", + - }); + - + - export type ServerNotification__CollabAgentStatus = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type ServerNotification__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const ServerNotification__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type ServerNotification__CommandExecOutputDeltaNotification = { + - readonly capReached: boolean; + - readonly deltaBase64: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__DeprecationNoticeNotification = Schema.Struct({ + - + - export type ServerNotification__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const ServerNotification__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__DynamicToolCallOutputContentItem = Schema.Union + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__DynamicToolCallStatus = Schema.Literals([ + - "failed", + - ]); + - + --export type ServerNotification__EnvironmentConnectionNotification = { + -- readonly environmentId: string; + -- readonly threadId: string; + --}; + --export const ServerNotification__EnvironmentConnectionNotification = Schema.Struct({ + -- environmentId: Schema.String, + -- threadId: Schema.String, + --}); + -- + --export type ServerNotification__ExternalAgentConfigMigrationItemType = + -- | "AGENTS_MD" + -- | "CONFIG" + -- | "SKILLS" + -- | "PLUGINS" + -- | "MCP_SERVER_CONFIG" + -- | "SUBAGENTS" + -- | "HOOKS" + -- | "COMMANDS" + -- | "MEMORY" + -- | "SESSIONS"; + --export const ServerNotification__ExternalAgentConfigMigrationItemType = Schema.Literals([ + -- "AGENTS_MD", + -- "CONFIG", + -- "SKILLS", + -- "PLUGINS", + -- "MCP_SERVER_CONFIG", + -- "SUBAGENTS", + -- "HOOKS", + -- "COMMANDS", + -- "MEMORY", + -- "SESSIONS", + --]); + -- + - export type ServerNotification__FileChangeOutputDeltaNotification = { + - readonly delta: string; + - readonly itemId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__FileChangeOutputDeltaNotification = Schema.Stru + - itemId: Schema.String, + - threadId: Schema.String, + - turnId: Schema.String, + --}).annotate({ + -- description: + -- "Deprecated legacy notification for `apply_patch` textual output.\n\nThe server no longer emits this notification.", + - }); + - + --export type ServerNotification__FileSystemAccessMode = "read" | "write" | "deny"; + --export const ServerNotification__FileSystemAccessMode = Schema.Literals(["read", "write", "deny"]); + -- + - export type ServerNotification__FuzzyFileSearchMatchType = "file" | "directory"; + - export const ServerNotification__FuzzyFileSearchMatchType = Schema.Literals(["file", "directory"]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__GuardianApprovalReviewStatus = Schema.Literals( + - "denied", + - "timedOut", + - "aborted", + --]).annotate({ description: "[UNSTABLE] Lifecycle state for an approval auto-review." }); + -+]).annotate({ description: "[UNSTABLE] Lifecycle state for a guardian approval review." }); + - + - export type ServerNotification__GuardianCommandSource = "shell" | "unifiedExec"; + - export const ServerNotification__GuardianCommandSource = Schema.Literals(["shell", "unifiedExec"]); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__GuardianRiskLevel = Schema.Literals([ + - "medium", + - "high", + - "critical", + --]).annotate({ description: "[UNSTABLE] Risk level assigned by approval auto-review." }); + -+]).annotate({ description: "[UNSTABLE] Risk level assigned by guardian approval review." }); + - + - export type ServerNotification__GuardianUserAuthorization = "unknown" | "low" | "medium" | "high"; + - export const ServerNotification__GuardianUserAuthorization = Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__GuardianUserAuthorization = Schema.Literals([ + - "low", + - "medium", + - "high", + --]).annotate({ description: "[UNSTABLE] Authorization level assigned by approval auto-review." }); + -- + --export type ServerNotification__GuardianWarningNotification = { + -- readonly message: string; + -- readonly threadId: string; + --}; + --export const ServerNotification__GuardianWarningNotification = Schema.Struct({ + -- message: Schema.String.annotate({ + -- description: "Concise guardian warning message for the user.", + -- }), + -- threadId: Schema.String.annotate({ description: "Thread target for the guardian warning." }), + -+]).annotate({ + -+ description: "[UNSTABLE] Authorization level assigned by guardian approval review.", + - }); + - + - export type ServerNotification__HookEventName = + - | "preToolUse" + -- | "permissionRequest" + - | "postToolUse" + -- | "preCompact" + -- | "postCompact" + - | "sessionStart" + -- | "sessionEnd" + - | "userPromptSubmit" + -- | "subagentStart" + -- | "subagentStop" + - | "stop"; + - export const ServerNotification__HookEventName = Schema.Literals([ + - "preToolUse", + -- "permissionRequest", + - "postToolUse", + -- "preCompact", + -- "postCompact", + - "sessionStart", + -- "sessionEnd", + - "userPromptSubmit", + -- "subagentStart", + -- "subagentStop", + - "stop", + - ]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__HookRunStatus = Schema.Literals([ + - export type ServerNotification__HookScope = "thread" | "turn"; + - export const ServerNotification__HookScope = Schema.Literals(["thread", "turn"]); + - + --export type ServerNotification__ImageDetail = "auto" | "low" | "high" | "original"; + --export const ServerNotification__ImageDetail = Schema.Literals(["auto", "low", "high", "original"]); + -- + --export type ServerNotification__LegacyAppPathString = string; + --export const ServerNotification__LegacyAppPathString = Schema.String; + -- + - export type ServerNotification__McpServerOauthLoginCompletedNotification = { + - readonly error?: string | null; + - readonly name: string; + - readonly success: boolean; + -- readonly threadId?: string | null; + - }; + - export const ServerNotification__McpServerOauthLoginCompletedNotification = Schema.Struct({ + - error: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - name: Schema.String, + - success: Schema.Boolean, + -- threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type ServerNotification__McpServerStartupFailureReason = "reauthenticationRequired"; + --export const ServerNotification__McpServerStartupFailureReason = Schema.Literal( + -- "reauthenticationRequired", + --); + -- + - export type ServerNotification__McpServerStartupState = + - | "starting" + - | "ready" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__McpServerStartupState = Schema.Literals([ + - "cancelled", + - ]); + - + --export type ServerNotification__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const ServerNotification__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type ServerNotification__McpToolCallError = { readonly message: string }; + - export const ServerNotification__McpToolCallError = Schema.Struct({ message: Schema.String }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__MessagePhase = Schema.Literals([ + - 'Classifies an assistant message as interim commentary or final answer text.\n\nProviders do not emit this consistently, so callers must treat `None` as "phase unknown" and keep compatibility behavior for legacy models.', + - }); + - + --export type ServerNotification__ModeKind = "plan" | "default"; + --export const ServerNotification__ModeKind = Schema.Literals(["plan", "default"]).annotate({ + -- description: "Initial collaboration mode to use when the TUI starts.", + --}); + -- + - export type ServerNotification__ModelRerouteReason = "highRiskCyberActivity"; + - export const ServerNotification__ModelRerouteReason = Schema.Literal("highRiskCyberActivity"); + - + --export type ServerNotification__ModelSafetyBufferingUpdatedNotification = { + -- readonly fasterModel?: string | null; + -- readonly model: string; + -- readonly reasons: ReadonlyArray; + -- readonly showBufferingUi: boolean; + -- readonly threadId: string; + -- readonly turnId: string; + -- readonly useCases: ReadonlyArray; + --}; + --export const ServerNotification__ModelSafetyBufferingUpdatedNotification = Schema.Struct({ + -- fasterModel: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- model: Schema.String, + -- reasons: Schema.Array(Schema.String), + -- showBufferingUi: Schema.Boolean, + -- threadId: Schema.String, + -- turnId: Schema.String, + -- useCases: Schema.Array(Schema.String), + --}); + -- + --export type ServerNotification__ModelVerification = "trustedAccessForCyber"; + --export const ServerNotification__ModelVerification = Schema.Literal("trustedAccessForCyber"); + -- + - export type ServerNotification__NetworkApprovalProtocol = + - | "http" + - | "https" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type ServerNotification__Personality = "none" | "friendly" | "pragmatic"; + --export const ServerNotification__Personality = Schema.Literals(["none", "friendly", "pragmatic"]); + -- + - export type ServerNotification__PlanDeltaNotification = { + - readonly delta: string; + - readonly itemId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerNotification__PlanType = + - | "go" + - | "plus" + - | "pro" + -- | "prolite" + - | "team" + -- | "self_serve_business_prolite" + - | "self_serve_business_usage_based" + - | "business" + -- | "ent26" + -- | "enterprise_cbp_automation" + - | "enterprise_cbp_usage_based" + - | "enterprise" + - | "edu" + -- | "edu_plus" + -- | "edu_pro" + - | "unknown"; + - export const ServerNotification__PlanType = Schema.Literals([ + - "free", + - "go", + - "plus", + - "pro", + -- "prolite", + - "team", + -- "self_serve_business_prolite", + - "self_serve_business_usage_based", + - "business", + -- "ent26", + -- "enterprise_cbp_automation", + - "enterprise_cbp_usage_based", + - "enterprise", + - "edu", + -- "edu_plus", + -- "edu_pro", + - "unknown", + - ]); + - + --export type ServerNotification__ProcessExitedNotification = { + -- readonly exitCode: number; + -- readonly processHandle: string; + -- readonly stderr: string; + -- readonly stderrCapReached: boolean; + -- readonly stdout: string; + -- readonly stdoutCapReached: boolean; + --}; + --export const ServerNotification__ProcessExitedNotification = Schema.Struct({ + -- exitCode: Schema.Number.annotate({ description: "Process exit code.", format: "int32" }).check( + -- Schema.isInt(), + -- ), + -- processHandle: Schema.String.annotate({ + -- description: "Client-supplied, connection-scoped `processHandle` from `process/spawn`.", + -- }), + -- stderr: Schema.String.annotate({ + -- description: + -- "Buffered stderr capture.\n\nEmpty when stderr was streamed via `process/outputDelta`.", + -- }), + -- stderrCapReached: Schema.Boolean.annotate({ + -- description: + -- "Whether stderr reached `outputBytesCap`.\n\nIn streaming mode, stderr is empty and cap state is also reported on the final stderr `process/outputDelta` notification.", + -- }), + -- stdout: Schema.String.annotate({ + -- description: + -- "Buffered stdout capture.\n\nEmpty when stdout was streamed via `process/outputDelta`.", + -- }), + -- stdoutCapReached: Schema.Boolean.annotate({ + -- description: + -- "Whether stdout reached `outputBytesCap`.\n\nIn streaming mode, stdout is empty and cap state is also reported on the final stdout `process/outputDelta` notification.", + -- }), + --}).annotate({ description: "Final process exit notification for `process/spawn`." }); + -- + --export type ServerNotification__ProcessOutputDeltaNotification = { + -- readonly capReached: boolean; + -- readonly deltaBase64: string; + -- readonly processHandle: string; + -- readonly stream: "stdout" | "stderr"; + --}; + --export const ServerNotification__ProcessOutputDeltaNotification = Schema.Struct({ + -- capReached: Schema.Boolean.annotate({ + -- description: + -- "True on the final streamed chunk for this stream when output was truncated by `outputBytesCap`.", + -- }), + -- deltaBase64: Schema.String.annotate({ description: "Base64-encoded output bytes." }), + -- processHandle: Schema.String.annotate({ + -- description: "Client-supplied, connection-scoped `processHandle` from `process/spawn`.", + -- }), + -- stream: Schema.Literals(["stdout", "stderr"]).annotate({ + -- description: "Stream label for `process/outputDelta` notifications.", + -- }), + --}).annotate({ + -- description: "Base64-encoded output chunk emitted for a streaming `process/spawn` request.", + --}); + -- + --export type ServerNotification__RateLimitReachedType = + -- | "rate_limit_reached" + -- | "workspace_owner_credits_depleted" + -- | "workspace_member_credits_depleted" + -- | "workspace_owner_usage_limit_reached" + -- | "workspace_member_usage_limit_reached"; + --export const ServerNotification__RateLimitReachedType = Schema.Literals([ + -- "rate_limit_reached", + -- "workspace_owner_credits_depleted", + -- "workspace_member_credits_depleted", + -- "workspace_owner_usage_limit_reached", + -- "workspace_member_usage_limit_reached", + --]); + -- + - export type ServerNotification__RateLimitWindow = { + - readonly resetsAt?: number | null; + - readonly usedPercent: number; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__RateLimitWindow = Schema.Struct({ + - ), + - }); + - + --export type ServerNotification__RealtimeConversationVersion = "v1" | "v2" | "v3"; + --export const ServerNotification__RealtimeConversationVersion = Schema.Literals(["v1", "v2", "v3"]); + -- + --export type ServerNotification__ReasoningEffort = string; + --export const ServerNotification__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -+export type ServerNotification__RealtimeConversationVersion = "v1" | "v2"; + -+export const ServerNotification__RealtimeConversationVersion = Schema.Literals(["v1", "v2"]); + - + --export type ServerNotification__ReasoningSummary = "auto" | "concise" | "detailed" | "none"; + --export const ServerNotification__ReasoningSummary = Schema.Union( + -- [ + -- Schema.Literals(["auto", "concise", "detailed"]), + -- Schema.Literal("none").annotate({ description: "Option to disable reasoning summaries." }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ + -+export type ServerNotification__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const ServerNotification__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + - description: + -- "A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries", + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + - }); + - + - export type ServerNotification__ReasoningSummaryPartAddedNotification = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ReasoningTextDeltaNotification = Schema.Struct( + - turnId: Schema.String, + - }); + - + --export type ServerNotification__RemoteControlConnectionStatus = + -- | "disabled" + -- | "connecting" + -- | "connected" + -- | "errored"; + --export const ServerNotification__RemoteControlConnectionStatus = Schema.Literals([ + -- "disabled", + -- "connecting", + -- "connected", + -- "errored", + --]); + -- + - export type ServerNotification__RequestId = string | number; + - export const ServerNotification__RequestId = Schema.Union([ + - Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__SkillsChangedNotification = Schema.Struct({}).a + - "Notification emitted when watched local skill files change.\n\nTreat this as an invalidation signal and re-run `skills/list` with the client's current parameters when refreshed skill metadata is needed.", + - }); + - + --export type ServerNotification__SpendControlLimitSnapshot = { + -- readonly limit: string; + -- readonly remainingPercent: number; + -- readonly resetsAt: number; + -- readonly used: string; + --}; + --export const ServerNotification__SpendControlLimitSnapshot = Schema.Struct({ + -- limit: Schema.String, + -- remainingPercent: Schema.Number.annotate({ format: "int32" }).check(Schema.isInt()), + -- resetsAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- used: Schema.String, + --}); + -- + --export type ServerNotification__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const ServerNotification__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -- + - export type ServerNotification__TerminalInteractionNotification = { + - readonly itemId: string; + - readonly processId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ThreadClosedNotification = Schema.Struct({ + - threadId: Schema.String, + - }); + - + --export type ServerNotification__ThreadDeletedNotification = { readonly threadId: string }; + --export const ServerNotification__ThreadDeletedNotification = Schema.Struct({ + -- threadId: Schema.String, + --}); + -- + --export type ServerNotification__ThreadGoalClearedNotification = { readonly threadId: string }; + --export const ServerNotification__ThreadGoalClearedNotification = Schema.Struct({ + -- threadId: Schema.String, + --}); + -- + --export type ServerNotification__ThreadGoalStatus = + -- | "active" + -- | "paused" + -- | "blocked" + -- | "usageLimited" + -- | "budgetLimited" + -- | "complete"; + --export const ServerNotification__ThreadGoalStatus = Schema.Literals([ + -- "active", + -- "paused", + -- "blocked", + -- "usageLimited", + -- "budgetLimited", + -- "complete", + --]); + -- + - export type ServerNotification__ThreadId = string; + - export const ServerNotification__ThreadId = Schema.String; + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ThreadRealtimeSdpNotification = Schema.Struct({ + - description: "EXPERIMENTAL - emitted with the remote SDP for a WebRTC realtime session.", + - }); + - + --export type ServerNotification__ThreadRealtimeTranscriptDeltaNotification = { + -- readonly delta: string; + -- readonly role: string; + -- readonly threadId: string; + --}; + --export const ServerNotification__ThreadRealtimeTranscriptDeltaNotification = Schema.Struct({ + -- delta: Schema.String.annotate({ description: "Live transcript delta from the realtime event." }), + -- role: Schema.String, + -- threadId: Schema.String, + --}).annotate({ + -- description: + -- "EXPERIMENTAL - flat transcript delta emitted whenever realtime transcript text changes.", + --}); + -- + --export type ServerNotification__ThreadRealtimeTranscriptDoneNotification = { + -+export type ServerNotification__ThreadRealtimeTranscriptUpdatedNotification = { + - readonly role: string; + - readonly text: string; + - readonly threadId: string; + - }; + --export const ServerNotification__ThreadRealtimeTranscriptDoneNotification = Schema.Struct({ + -+export const ServerNotification__ThreadRealtimeTranscriptUpdatedNotification = Schema.Struct({ + - role: Schema.String, + -- text: Schema.String.annotate({ description: "Final complete text for the transcript part." }), + -+ text: Schema.String, + - threadId: Schema.String, + - }).annotate({ + - description: + -- "EXPERIMENTAL - final transcript text emitted when realtime completes a transcript part.", + -+ "EXPERIMENTAL - flat transcript delta emitted whenever realtime transcript text changes.", + - }); + - + --export type ServerNotification__ThreadSource = string; + --export const ServerNotification__ThreadSource = Schema.String; + -- + - export type ServerNotification__ThreadUnarchivedNotification = { readonly threadId: string }; + - export const ServerNotification__ThreadUnarchivedNotification = Schema.Struct({ + - threadId: Schema.String, + - }); + - + - export type ServerNotification__TokenUsageBreakdown = { + -- readonly cacheWriteInputTokens?: number; + - readonly cachedInputTokens: number; + - readonly inputTokens: number; + - readonly outputTokens: number; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerNotification__TokenUsageBreakdown = { + - readonly totalTokens: number; + - }; + - export const ServerNotification__TokenUsageBreakdown = Schema.Struct({ + -- cacheWriteInputTokens: Schema.optionalKey( + -- Schema.Number.annotate({ default: 0, format: "int64" }).check(Schema.isInt()), + -- ), + - cachedInputTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + - inputTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + - outputTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__TurnDiffUpdatedNotification = Schema.Struct({ + - "Notification that the turn-level unified diff has changed. Contains the latest aggregated diff across all file changes in the turn.", + - }); + - + --export type ServerNotification__TurnModerationMetadataNotification = { + -- readonly metadata: unknown; + -- readonly threadId: string; + -- readonly turnId: string; + --}; + --export const ServerNotification__TurnModerationMetadataNotification = Schema.Struct({ + -- metadata: Schema.Unknown, + -- threadId: Schema.String, + -- turnId: Schema.String, + --}); + -- + - export type ServerNotification__TurnPlanStepStatus = "pending" | "inProgress" | "completed"; + - export const ServerNotification__TurnPlanStepStatus = Schema.Literals([ + - "pending", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__TurnStatus = Schema.Literals([ + - "inProgress", + - ]); + - + --export type ServerNotification__WarningNotification = { + -- readonly message: string; + -- readonly threadId?: string | null; + --}; + --export const ServerNotification__WarningNotification = Schema.Struct({ + -- message: Schema.String.annotate({ description: "Concise warning message for the user." }), + -- threadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Optional thread target when the warning applies to a specific thread.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + - export type ServerNotification__WebSearchAction = + - | { + - readonly queries?: ReadonlyArray | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerRequest__AdditionalNetworkPermissions = Schema.Struct({ + - enabled: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - }); + - + --export type ServerRequest__AttestationGenerateParams = {}; + --export const ServerRequest__AttestationGenerateParams = Schema.Struct({}); + -- + - export type ServerRequest__ChatgptAuthTokensRefreshReason = "unauthorized"; + - export const ServerRequest__ChatgptAuthTokensRefreshReason = Schema.Literal("unauthorized"); + - + -+export type ServerRequest__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const ServerRequest__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type ServerRequest__DynamicToolCallParams = { + - readonly arguments: unknown; + - readonly callId: string; + -- readonly namespace?: string | null; + - readonly threadId: string; + - readonly tool: string; + - readonly turnId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerRequest__DynamicToolCallParams = { + - export const ServerRequest__DynamicToolCallParams = Schema.Struct({ + - arguments: Schema.Unknown, + - callId: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - threadId: Schema.String, + - tool: Schema.String, + - turnId: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerRequest__FileChangeRequestApprovalParams = { + - readonly grantRoot?: string | null; + - readonly itemId: string; + - readonly reason?: string | null; + -- readonly startedAtMs: number; + - readonly threadId: string; + - readonly turnId: string; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerRequest__FileChangeRequestApprovalParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this approval request started.", + -- format: "int64", + -- }).check(Schema.isInt()), + - threadId: Schema.String, + - turnId: Schema.String, + - }); + - + --export type ServerRequest__FileSystemAccessMode = "read" | "write" | "deny"; + --export const ServerRequest__FileSystemAccessMode = Schema.Literals(["read", "write", "deny"]); + -- + --export type ServerRequest__LegacyAppPathString = string; + --export const ServerRequest__LegacyAppPathString = Schema.String; + -- + - export type ServerRequest__McpElicitationArrayType = "array"; + - export const ServerRequest__McpElicitationArrayType = Schema.Literal("array"); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V1InitializeParams__ClientInfo = Schema.Struct({ + - + - export type V1InitializeParams__InitializeCapabilities = { + - readonly experimentalApi?: boolean; + -- readonly mcpServerOpenaiFormElicitation?: boolean; + - readonly optOutNotificationMethods?: ReadonlyArray | null; + -- readonly requestAttestation?: boolean; + - }; + - export const V1InitializeParams__InitializeCapabilities = Schema.Struct({ + - experimentalApi: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V1InitializeParams__InitializeCapabilities = Schema.Struct({ + - default: false, + - }), + - ), + -- mcpServerOpenaiFormElicitation: Schema.optionalKey( + -- Schema.Boolean.annotate({ + -- description: "Allow downstream MCP servers to request OpenAI extended form elicitations.", + -- }), + -- ), + - optOutNotificationMethods: Schema.optionalKey( + - Schema.Union([ + - Schema.Array(Schema.String).annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V1InitializeParams__InitializeCapabilities = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- requestAttestation: Schema.optionalKey( + -- Schema.Boolean.annotate({ + -- description: "Opt into `attestation/generate` requests for upstream `x-oai-attestation`.", + -- default: false, + -- }), + -- ), + - }).annotate({ description: "Client-declared capabilities negotiated during initialize." }); + - + - export type V2AccountRateLimitsUpdatedNotification__CreditsSnapshot = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2AccountRateLimitsUpdatedNotification__PlanType = + - | "go" + - | "plus" + - | "pro" + -- | "prolite" + - | "team" + -- | "self_serve_business_prolite" + - | "self_serve_business_usage_based" + - | "business" + -- | "ent26" + -- | "enterprise_cbp_automation" + - | "enterprise_cbp_usage_based" + - | "enterprise" + - | "edu" + -- | "edu_plus" + -- | "edu_pro" + - | "unknown"; + - export const V2AccountRateLimitsUpdatedNotification__PlanType = Schema.Literals([ + - "free", + - "go", + - "plus", + - "pro", + -- "prolite", + - "team", + -- "self_serve_business_prolite", + - "self_serve_business_usage_based", + - "business", + -- "ent26", + -- "enterprise_cbp_automation", + - "enterprise_cbp_usage_based", + - "enterprise", + - "edu", + -- "edu_plus", + -- "edu_pro", + - "unknown", + - ]); + - + --export type V2AccountRateLimitsUpdatedNotification__RateLimitReachedType = + -- | "rate_limit_reached" + -- | "workspace_owner_credits_depleted" + -- | "workspace_member_credits_depleted" + -- | "workspace_owner_usage_limit_reached" + -- | "workspace_member_usage_limit_reached"; + --export const V2AccountRateLimitsUpdatedNotification__RateLimitReachedType = Schema.Literals([ + -- "rate_limit_reached", + -- "workspace_owner_credits_depleted", + -- "workspace_member_credits_depleted", + -- "workspace_owner_usage_limit_reached", + -- "workspace_member_usage_limit_reached", + --]); + -- + - export type V2AccountRateLimitsUpdatedNotification__RateLimitWindow = { + - readonly resetsAt?: number | null; + - readonly usedPercent: number; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2AccountRateLimitsUpdatedNotification__RateLimitWindow = Schema.St + - ), + - }); + - + --export type V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot = { + -- readonly limit: string; + -- readonly remainingPercent: number; + -- readonly resetsAt: number; + -- readonly used: string; + --}; + --export const V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot = Schema.Struct({ + -- limit: Schema.String, + -- remainingPercent: Schema.Number.annotate({ format: "int32" }).check(Schema.isInt()), + -- resetsAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- used: Schema.String, + --}); + -- + --export type V2AccountUpdatedNotification__AuthMode = + -- | "apikey" + -- | "chatgpt" + -- | "chatgptAuthTokens" + -- | "headers" + -- | "agentIdentity" + -- | "personalAccessToken" + -- | "bedrockApiKey"; + -+export type V2AccountUpdatedNotification__AuthMode = "apikey" | "chatgpt" | "chatgptAuthTokens"; + - export const V2AccountUpdatedNotification__AuthMode = Schema.Literals([ + - "apikey", + - "chatgpt", + - "chatgptAuthTokens", + -- "headers", + -- "agentIdentity", + -- "personalAccessToken", + -- "bedrockApiKey", + - ]).annotate({ description: "Authentication mode for OpenAI-backed providers." }); + - + - export type V2AccountUpdatedNotification__PlanType = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2AccountUpdatedNotification__PlanType = + - | "go" + - | "plus" + - | "pro" + -- | "prolite" + - | "team" + -- | "self_serve_business_prolite" + - | "self_serve_business_usage_based" + - | "business" + -- | "ent26" + -- | "enterprise_cbp_automation" + - | "enterprise_cbp_usage_based" + - | "enterprise" + - | "edu" + -- | "edu_plus" + -- | "edu_pro" + - | "unknown"; + - export const V2AccountUpdatedNotification__PlanType = Schema.Literals([ + - "free", + - "go", + - "plus", + - "pro", + -- "prolite", + - "team", + -- "self_serve_business_prolite", + - "self_serve_business_usage_based", + - "business", + -- "ent26", + -- "enterprise_cbp_automation", + - "enterprise_cbp_usage_based", + - "enterprise", + - "edu", + -- "edu_plus", + -- "edu_pro", + - "unknown", + - ]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2AppListUpdatedNotification__AppScreenshot = Schema.Struct({ + - userPrompt: Schema.String, + - }); + - + --export type V2AppsInstalledResponse__InstalledApp = { + -- readonly callable: boolean; + -- readonly enabled: boolean; + -- readonly id: string; + -- readonly runtimeName?: string | null; + --}; + --export const V2AppsInstalledResponse__InstalledApp = Schema.Struct({ + -- callable: Schema.Boolean.annotate({ + -- description: + -- "Whether the connector is enabled and has a non-synthetic, model-visible tool allowed by effective MCP and app/tool policy in the committed runtime snapshot.", + -- }), + -- enabled: Schema.Boolean.annotate({ + -- description: + -- "Effective enabled state after applying global, workspace, local, and managed configuration at read time.", + -- }), + -- id: Schema.String, + -- runtimeName: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Best-effort name carried by the runtime tool catalog. Canonical app metadata remains owned by `app/read`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}).annotate({ description: "Installed connector runtime state." }); + -- + - export type V2AppsListResponse__AppBranding = { + - readonly category?: string | null; + - readonly developer?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2AppsListResponse__AppScreenshot = Schema.Struct({ + - userPrompt: Schema.String, + - }); + - + --export type V2AppsReadResponse__AppToolSummary = { + -- readonly description: string; + -- readonly name: string; + -- readonly title?: string | null; + --}; + --export const V2AppsReadResponse__AppToolSummary = Schema.Struct({ + -- description: Schema.String, + -- name: Schema.String, + -- title: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}).annotate({ description: "EXPERIMENTAL - metadata returned by app/read." }); + -- + - export type V2CancelLoginAccountResponse__CancelLoginAccountStatus = "canceled" | "notFound"; + - export const V2CancelLoginAccountResponse__CancelLoginAccountStatus = Schema.Literals([ + - "canceled", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadResponse__AnalyticsConfig = Schema.StructWithRest( + - [Schema.Record(Schema.String, Schema.Unknown)], + - ); + - + --export type V2ConfigReadResponse__AppToolApproval = "auto" | "prompt" | "writes" | "approve"; + --export const V2ConfigReadResponse__AppToolApproval = Schema.Literals([ + -- "auto", + -- "prompt", + -- "writes", + -- "approve", + --]); + -+export type V2ConfigReadResponse__AppToolApproval = "auto" | "prompt" | "approve"; + -+export const V2ConfigReadResponse__AppToolApproval = Schema.Literals(["auto", "prompt", "approve"]); + - + - export type V2ConfigReadResponse__AppToolsConfig = {}; + - export const V2ConfigReadResponse__AppToolsConfig = Schema.Struct({}); + - + --export type V2ConfigReadResponse__ApprovalsReviewer = "user" | "auto_review" | "guardian_subagent"; + -+export type V2ConfigReadResponse__ApprovalsReviewer = "user" | "guardian_subagent"; + - export const V2ConfigReadResponse__ApprovalsReviewer = Schema.Literals([ + - "user", + -- "auto_review", + - "guardian_subagent", + - ]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + -+}); + -+ + -+export type V2ConfigReadResponse__AppsDefaultConfig = { + -+ readonly destructive_enabled?: boolean; + -+ readonly enabled?: boolean; + -+ readonly open_world_enabled?: boolean; + -+}; + -+export const V2ConfigReadResponse__AppsDefaultConfig = Schema.Struct({ + -+ destructive_enabled: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + -+ enabled: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + -+ open_world_enabled: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + - }); + - + - export type V2ConfigReadResponse__AskForApproval = + - | "untrusted" + -+ | "on-failure" + - | "on-request" + - | "never" + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ConfigReadResponse__AskForApproval = + - }; + - export const V2ConfigReadResponse__AskForApproval = Schema.Union( + - [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -+ Schema.Literals(["untrusted", "on-failure", "on-request", "never"]), + - Schema.Struct({ + - granular: Schema.Struct({ + - mcp_elicitations: Schema.Boolean, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadResponse__AskForApproval = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ConfigReadResponse__AutoCompactTokenLimitScope = "total" | "body_after_prefix"; + --export const V2ConfigReadResponse__AutoCompactTokenLimitScope = Schema.Literals([ + -- "total", + -- "body_after_prefix", + --]).annotate({ + -- description: + -- "Selects which part of the active context is charged against `model_auto_compact_token_limit`.", + --}); + -- + --export type V2ConfigReadResponse__ForcedChatgptWorkspaceIds = string | ReadonlyArray; + --export const V2ConfigReadResponse__ForcedChatgptWorkspaceIds = Schema.Union([ + -- Schema.String, + -- Schema.Array(Schema.String), + --]).annotate({ + -- description: "Backward-compatible API shape for ChatGPT workspace login restrictions.", + --}); + -- + - export type V2ConfigReadResponse__ForcedLoginMethod = "chatgpt" | "api"; + - export const V2ConfigReadResponse__ForcedLoginMethod = Schema.Literals(["chatgpt", "api"]); + - + --export type V2ConfigReadResponse__ReasoningEffort = string; + --export const V2ConfigReadResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -+export type V2ConfigReadResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ConfigReadResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2ConfigReadResponse__ReasoningSummary = "auto" | "concise" | "detailed" | "none"; + - export const V2ConfigReadResponse__ReasoningSummary = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadResponse__SandboxWorkspaceWrite = Schema.Struct({ + - writable_roots: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + - }); + - + -+export type V2ConfigReadResponse__ServiceTier = "fast" | "flex"; + -+export const V2ConfigReadResponse__ServiceTier = Schema.Literals(["fast", "flex"]); + -+ + - export type V2ConfigReadResponse__Verbosity = "low" | "medium" | "high"; + - export const V2ConfigReadResponse__Verbosity = Schema.Literals(["low", "medium", "high"]).annotate({ + - description: + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadResponse__WebSearchLocation = Schema.Struct({ + - timezone: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type V2ConfigReadResponse__WebSearchMode = "disabled" | "cached" | "indexed" | "live"; + --export const V2ConfigReadResponse__WebSearchMode = Schema.Literals([ + -- "disabled", + -- "cached", + -- "indexed", + -- "live", + --]); + -+export type V2ConfigReadResponse__WebSearchMode = "disabled" | "cached" | "live"; + -+export const V2ConfigReadResponse__WebSearchMode = Schema.Literals(["disabled", "cached", "live"]); + - + - export type V2ConfigRequirementsReadResponse__AskForApproval = + - | "untrusted" + -+ | "on-failure" + - | "on-request" + - | "never" + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ConfigRequirementsReadResponse__AskForApproval = + - }; + - export const V2ConfigRequirementsReadResponse__AskForApproval = Schema.Union( + - [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -+ Schema.Literals(["untrusted", "on-failure", "on-request", "never"]), + - Schema.Struct({ + - granular: Schema.Struct({ + - mcp_elicitations: Schema.Boolean, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigRequirementsReadResponse__AskForApproval = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ConfigRequirementsReadResponse__ComputerUseRequirements = { + -- readonly allowLockedComputerUse?: boolean | null; + --}; + --export const V2ConfigRequirementsReadResponse__ComputerUseRequirements = Schema.Struct({ + -- allowLockedComputerUse: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + --}); + -- + --export type V2ConfigRequirementsReadResponse__ConfiguredHookHandler = + -- | { + -- readonly async: boolean; + -- readonly command: string; + -- readonly commandWindows?: string | null; + -- readonly statusMessage?: string | null; + -- readonly timeoutSec?: number | null; + -- readonly type: "command"; + -- } + -- | { readonly type: "prompt" } + -- | { readonly type: "agent" }; + --export const V2ConfigRequirementsReadResponse__ConfiguredHookHandler = Schema.Union( + -- [ + -- Schema.Struct({ + -- async: Schema.Boolean, + -- command: Schema.String, + -- commandWindows: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- statusMessage: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- timeoutSec: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- Schema.Null, + -- ]), + -- ), + -- type: Schema.Literal("command").annotate({ title: "CommandConfiguredHookHandlerType" }), + -- }).annotate({ title: "CommandConfiguredHookHandler" }), + -- Schema.Struct({ + -- type: Schema.Literal("prompt").annotate({ title: "PromptConfiguredHookHandlerType" }), + -- }).annotate({ title: "PromptConfiguredHookHandler" }), + -- Schema.Struct({ + -- type: Schema.Literal("agent").annotate({ title: "AgentConfiguredHookHandlerType" }), + -- }).annotate({ title: "AgentConfiguredHookHandler" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2ConfigRequirementsReadResponse__NetworkDomainPermission = "allow" | "deny"; + - export const V2ConfigRequirementsReadResponse__NetworkDomainPermission = Schema.Literals([ + - "allow", + - "deny", + - ]); + - + --export type V2ConfigRequirementsReadResponse__NetworkUnixSocketPermission = "allow" | "deny"; + -+export type V2ConfigRequirementsReadResponse__NetworkUnixSocketPermission = "allow" | "none"; + - export const V2ConfigRequirementsReadResponse__NetworkUnixSocketPermission = Schema.Literals([ + - "allow", + -- "deny", + -+ "none", + - ]); + - + --export type V2ConfigRequirementsReadResponse__ReasoningEffort = string; + --export const V2ConfigRequirementsReadResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + - export type V2ConfigRequirementsReadResponse__ResidencyRequirement = "us"; + - export const V2ConfigRequirementsReadResponse__ResidencyRequirement = Schema.Literal("us"); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigRequirementsReadResponse__SandboxMode = Schema.Literals([ + - "danger-full-access", + - ]); + - + --export type V2ConfigRequirementsReadResponse__WebSearchMode = + -- | "disabled" + -- | "cached" + -- | "indexed" + -- | "live"; + -+export type V2ConfigRequirementsReadResponse__WebSearchMode = "disabled" | "cached" | "live"; + - export const V2ConfigRequirementsReadResponse__WebSearchMode = Schema.Literals([ + - "disabled", + - "cached", + -- "indexed", + - "live", + - ]); + - + --export type V2ConfigRequirementsReadResponse__WindowsSandboxSetupMode = "elevated" | "unelevated"; + --export const V2ConfigRequirementsReadResponse__WindowsSandboxSetupMode = Schema.Literals([ + -- "elevated", + -- "unelevated", + --]); + -- + - export type V2ConfigValueWriteParams__MergeStrategy = "replace" | "upsert"; + - export const V2ConfigValueWriteParams__MergeStrategy = Schema.Literals(["replace", "upsert"]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigWriteResponse__AbsolutePathBuf = Schema.String.annotate({ + - export type V2ConfigWriteResponse__WriteStatus = "ok" | "okOverridden"; + - export const V2ConfigWriteResponse__WriteStatus = Schema.Literals(["ok", "okOverridden"]); + - + --export type V2ConsumeAccountRateLimitResetCreditResponse__ConsumeAccountRateLimitResetCreditOutcome = + -- "reset" | "nothingToReset" | "noCredit" | "alreadyRedeemed"; + --export const V2ConsumeAccountRateLimitResetCreditResponse__ConsumeAccountRateLimitResetCreditOutcome = + -- Schema.Literals(["reset", "nothingToReset", "noCredit", "alreadyRedeemed"]); + -- + - export type V2ErrorNotification__NonSteerableTurnKind = "review" | "compact"; + - export const V2ErrorNotification__NonSteerableTurnKind = Schema.Literals(["review", "compact"]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ExperimentalFeatureListResponse__ExperimentalFeature = Schema.Str + - }), + - }); + - + --export type V2ExternalAgentConfigDetectResponse__CommandMigration = { readonly name: string }; + --export const V2ExternalAgentConfigDetectResponse__CommandMigration = Schema.Struct({ + -- name: Schema.String, + --}); + -- + - export type V2ExternalAgentConfigDetectResponse__ExternalAgentConfigMigrationItemType = + - | "AGENTS_MD" + - | "CONFIG" + - | "SKILLS" + -- | "PLUGINS" + -- | "MCP_SERVER_CONFIG" + -- | "SUBAGENTS" + -- | "HOOKS" + -- | "COMMANDS" + -- | "MEMORY" + -- | "SESSIONS"; + -+ | "MCP_SERVER_CONFIG"; + - export const V2ExternalAgentConfigDetectResponse__ExternalAgentConfigMigrationItemType = + -- Schema.Literals([ + -- "AGENTS_MD", + -- "CONFIG", + -- "SKILLS", + -- "PLUGINS", + -- "MCP_SERVER_CONFIG", + -- "SUBAGENTS", + -- "HOOKS", + -- "COMMANDS", + -- "MEMORY", + -- "SESSIONS", + -- ]); + -- + --export type V2ExternalAgentConfigDetectResponse__HookMigration = { readonly name: string }; + --export const V2ExternalAgentConfigDetectResponse__HookMigration = Schema.Struct({ + -- name: Schema.String, + --}); + -- + --export type V2ExternalAgentConfigDetectResponse__McpServerMigration = { readonly name: string }; + --export const V2ExternalAgentConfigDetectResponse__McpServerMigration = Schema.Struct({ + -- name: Schema.String, + --}); + -- + --export type V2ExternalAgentConfigDetectResponse__PluginsMigration = { + -- readonly marketplaceName: string; + -- readonly pluginNames: ReadonlyArray; + --}; + --export const V2ExternalAgentConfigDetectResponse__PluginsMigration = Schema.Struct({ + -- marketplaceName: Schema.String, + -- pluginNames: Schema.Array(Schema.String), + --}); + -- + --export type V2ExternalAgentConfigDetectResponse__SessionMigration = { + -- readonly cwd: string; + -- readonly path: string; + -- readonly title?: string | null; + --}; + --export const V2ExternalAgentConfigDetectResponse__SessionMigration = Schema.Struct({ + -- cwd: Schema.String, + -- path: Schema.String, + -- title: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + --export type V2ExternalAgentConfigDetectResponse__SkillMigration = { readonly name: string }; + --export const V2ExternalAgentConfigDetectResponse__SkillMigration = Schema.Struct({ + -- name: Schema.String, + --}); + -- + --export type V2ExternalAgentConfigDetectResponse__SubagentMigration = { readonly name: string }; + --export const V2ExternalAgentConfigDetectResponse__SubagentMigration = Schema.Struct({ + -- name: Schema.String, + --}); + -- + --export type V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigMigrationItemType = + -- | "AGENTS_MD" + -- | "CONFIG" + -- | "SKILLS" + -- | "PLUGINS" + -- | "MCP_SERVER_CONFIG" + -- | "SUBAGENTS" + -- | "HOOKS" + -- | "COMMANDS" + -- | "MEMORY" + -- | "SESSIONS"; + --export const V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigMigrationItemType = + -- Schema.Literals([ + -- "AGENTS_MD", + -- "CONFIG", + -- "SKILLS", + -- "PLUGINS", + -- "MCP_SERVER_CONFIG", + -- "SUBAGENTS", + -- "HOOKS", + -- "COMMANDS", + -- "MEMORY", + -- "SESSIONS", + -- ]); + -- + --export type V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigMigrationItemType = + -- | "AGENTS_MD" + -- | "CONFIG" + -- | "SKILLS" + -- | "PLUGINS" + -- | "MCP_SERVER_CONFIG" + -- | "SUBAGENTS" + -- | "HOOKS" + -- | "COMMANDS" + -- | "MEMORY" + -- | "SESSIONS"; + --export const V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigMigrationItemType = + -- Schema.Literals([ + -- "AGENTS_MD", + -- "CONFIG", + -- "SKILLS", + -- "PLUGINS", + -- "MCP_SERVER_CONFIG", + -- "SUBAGENTS", + -- "HOOKS", + -- "COMMANDS", + -- "MEMORY", + -- "SESSIONS", + -- ]); + -- + --export type V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentImportedConnectorSource = + -- "remoteMcpServersConfig"; + --export const V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentImportedConnectorSource = + -- Schema.Literal("remoteMcpServersConfig"); + -- + --export type V2ExternalAgentConfigImportParams__CommandMigration = { readonly name: string }; + --export const V2ExternalAgentConfigImportParams__CommandMigration = Schema.Struct({ + -- name: Schema.String, + --}); + -+ Schema.Literals(["AGENTS_MD", "CONFIG", "SKILLS", "MCP_SERVER_CONFIG"]); + - + - export type V2ExternalAgentConfigImportParams__ExternalAgentConfigMigrationItemType = + - | "AGENTS_MD" + - | "CONFIG" + - | "SKILLS" + -- | "PLUGINS" + -- | "MCP_SERVER_CONFIG" + -- | "SUBAGENTS" + -- | "HOOKS" + -- | "COMMANDS" + -- | "MEMORY" + -- | "SESSIONS"; + -+ | "MCP_SERVER_CONFIG"; + - export const V2ExternalAgentConfigImportParams__ExternalAgentConfigMigrationItemType = + -- Schema.Literals([ + -- "AGENTS_MD", + -- "CONFIG", + -- "SKILLS", + -- "PLUGINS", + -- "MCP_SERVER_CONFIG", + -- "SUBAGENTS", + -- "HOOKS", + -- "COMMANDS", + -- "MEMORY", + -- "SESSIONS", + -- ]); + -- + --export type V2ExternalAgentConfigImportParams__HookMigration = { readonly name: string }; + --export const V2ExternalAgentConfigImportParams__HookMigration = Schema.Struct({ + -- name: Schema.String, + --}); + -- + --export type V2ExternalAgentConfigImportParams__McpServerMigration = { readonly name: string }; + --export const V2ExternalAgentConfigImportParams__McpServerMigration = Schema.Struct({ + -- name: Schema.String, + --}); + -- + --export type V2ExternalAgentConfigImportParams__PluginsMigration = { + -- readonly marketplaceName: string; + -- readonly pluginNames: ReadonlyArray; + --}; + --export const V2ExternalAgentConfigImportParams__PluginsMigration = Schema.Struct({ + -- marketplaceName: Schema.String, + -- pluginNames: Schema.Array(Schema.String), + --}); + -- + --export type V2ExternalAgentConfigImportParams__SessionMigration = { + -- readonly cwd: string; + -- readonly path: string; + -- readonly title?: string | null; + --}; + --export const V2ExternalAgentConfigImportParams__SessionMigration = Schema.Struct({ + -- cwd: Schema.String, + -- path: Schema.String, + -- title: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + --export type V2ExternalAgentConfigImportParams__SkillMigration = { readonly name: string }; + --export const V2ExternalAgentConfigImportParams__SkillMigration = Schema.Struct({ + -- name: Schema.String, + --}); + -- + --export type V2ExternalAgentConfigImportParams__SubagentMigration = { readonly name: string }; + --export const V2ExternalAgentConfigImportParams__SubagentMigration = Schema.Struct({ + -- name: Schema.String, + --}); + -- + --export type V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigMigrationItemType = + -- | "AGENTS_MD" + -- | "CONFIG" + -- | "SKILLS" + -- | "PLUGINS" + -- | "MCP_SERVER_CONFIG" + -- | "SUBAGENTS" + -- | "HOOKS" + -- | "COMMANDS" + -- | "MEMORY" + -- | "SESSIONS"; + --export const V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigMigrationItemType = + -- Schema.Literals([ + -- "AGENTS_MD", + -- "CONFIG", + -- "SKILLS", + -- "PLUGINS", + -- "MCP_SERVER_CONFIG", + -- "SUBAGENTS", + -- "HOOKS", + -- "COMMANDS", + -- "MEMORY", + -- "SESSIONS", + -- ]); + -- + --export type V2FileChangePatchUpdatedNotification__PatchChangeKind = + -- | { readonly type: "add" } + -- | { readonly type: "delete" } + -- | { readonly move_path?: string | null; readonly type: "update" }; + --export const V2FileChangePatchUpdatedNotification__PatchChangeKind = Schema.Union( + -- [ + -- Schema.Struct({ + -- type: Schema.Literal("add").annotate({ title: "AddPatchChangeKindType" }), + -- }).annotate({ title: "AddPatchChangeKind" }), + -- Schema.Struct({ + -- type: Schema.Literal("delete").annotate({ title: "DeletePatchChangeKindType" }), + -- }).annotate({ title: "DeletePatchChangeKind" }), + -- Schema.Struct({ + -- move_path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("update").annotate({ title: "UpdatePatchChangeKindType" }), + -- }).annotate({ title: "UpdatePatchChangeKind" }), + -- ], + -- { mode: "oneOf" }, + --); + -+ Schema.Literals(["AGENTS_MD", "CONFIG", "SKILLS", "MCP_SERVER_CONFIG"]); + - + - export type V2FsChangedNotification__AbsolutePathBuf = string; + - export const V2FsChangedNotification__AbsolutePathBuf = Schema.String.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2GetAccountRateLimitsResponse__PlanType = + - | "go" + - | "plus" + - | "pro" + -- | "prolite" + - | "team" + -- | "self_serve_business_prolite" + - | "self_serve_business_usage_based" + - | "business" + -- | "ent26" + -- | "enterprise_cbp_automation" + - | "enterprise_cbp_usage_based" + - | "enterprise" + - | "edu" + -- | "edu_plus" + -- | "edu_pro" + - | "unknown"; + - export const V2GetAccountRateLimitsResponse__PlanType = Schema.Literals([ + - "free", + - "go", + - "plus", + - "pro", + -- "prolite", + - "team", + -- "self_serve_business_prolite", + - "self_serve_business_usage_based", + - "business", + -- "ent26", + -- "enterprise_cbp_automation", + - "enterprise_cbp_usage_based", + - "enterprise", + - "edu", + -- "edu_plus", + -- "edu_pro", + -- "unknown", + --]); + -- + --export type V2GetAccountRateLimitsResponse__RateLimitReachedType = + -- | "rate_limit_reached" + -- | "workspace_owner_credits_depleted" + -- | "workspace_member_credits_depleted" + -- | "workspace_owner_usage_limit_reached" + -- | "workspace_member_usage_limit_reached"; + --export const V2GetAccountRateLimitsResponse__RateLimitReachedType = Schema.Literals([ + -- "rate_limit_reached", + -- "workspace_owner_credits_depleted", + -- "workspace_member_credits_depleted", + -- "workspace_owner_usage_limit_reached", + -- "workspace_member_usage_limit_reached", + --]); + -- + --export type V2GetAccountRateLimitsResponse__RateLimitResetCreditStatus = + -- | "available" + -- | "redeeming" + -- | "redeemed" + -- | "unknown"; + --export const V2GetAccountRateLimitsResponse__RateLimitResetCreditStatus = Schema.Literals([ + -- "available", + -- "redeeming", + -- "redeemed", + -- "unknown", + --]); + -- + --export type V2GetAccountRateLimitsResponse__RateLimitResetType = "codexRateLimits" | "unknown"; + --export const V2GetAccountRateLimitsResponse__RateLimitResetType = Schema.Literals([ + -- "codexRateLimits", + - "unknown", + - ]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2GetAccountRateLimitsResponse__RateLimitWindow = Schema.Struct({ + - ), + - }); + - + --export type V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot = { + -- readonly limit: string; + -- readonly remainingPercent: number; + -- readonly resetsAt: number; + -- readonly used: string; + --}; + --export const V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot = Schema.Struct({ + -- limit: Schema.String, + -- remainingPercent: Schema.Number.annotate({ format: "int32" }).check(Schema.isInt()), + -- resetsAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- used: Schema.String, + --}); + -- + - export type V2GetAccountResponse__PlanType = + - | "free" + - | "go" + - | "plus" + - | "pro" + -- | "prolite" + - | "team" + -- | "self_serve_business_prolite" + - | "self_serve_business_usage_based" + - | "business" + -- | "ent26" + -- | "enterprise_cbp_automation" + - | "enterprise_cbp_usage_based" + - | "enterprise" + - | "edu" + -- | "edu_plus" + -- | "edu_pro" + - | "unknown"; + - export const V2GetAccountResponse__PlanType = Schema.Literals([ + - "free", + - "go", + - "plus", + - "pro", + -- "prolite", + - "team", + -- "self_serve_business_prolite", + - "self_serve_business_usage_based", + - "business", + -- "ent26", + -- "enterprise_cbp_automation", + - "enterprise_cbp_usage_based", + - "enterprise", + - "edu", + -- "edu_plus", + -- "edu_pro", + -- "unknown", + --]); + -- + --export type V2GetAccountTokenUsageResponse__AccountTokenUsageDailyBucket = { + -- readonly startDate: string; + -- readonly tokens: number; + --}; + --export const V2GetAccountTokenUsageResponse__AccountTokenUsageDailyBucket = Schema.Struct({ + -- startDate: Schema.String, + -- tokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + --}); + -- + --export type V2GetAccountTokenUsageResponse__AccountTokenUsageSummary = { + -- readonly currentStreakDays?: number | null; + -- readonly lifetimeTokens?: number | null; + -- readonly longestRunningTurnSec?: number | null; + -- readonly longestStreakDays?: number | null; + -- readonly peakDailyTokens?: number | null; + --}; + --export const V2GetAccountTokenUsageResponse__AccountTokenUsageSummary = Schema.Struct({ + -- currentStreakDays: Schema.optionalKey( + -- Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + -- ), + -- lifetimeTokens: Schema.optionalKey( + -- Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + -- ), + -- longestRunningTurnSec: Schema.optionalKey( + -- Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + -- ), + -- longestStreakDays: Schema.optionalKey( + -- Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + -- ), + -- peakDailyTokens: Schema.optionalKey( + -- Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + -- ), + --}); + -- + --export type V2GetWorkspaceMessagesResponse__WorkspaceMessageType = + -- | "headline" + -- | "announcement" + -- | "unknown"; + --export const V2GetWorkspaceMessagesResponse__WorkspaceMessageType = Schema.Literals([ + -- "headline", + -- "announcement", + - "unknown", + - ]); + - + --export type V2HookCompletedNotification__AbsolutePathBuf = string; + --export const V2HookCompletedNotification__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2HookCompletedNotification__HookEventName = + - | "preToolUse" + -- | "permissionRequest" + - | "postToolUse" + -- | "preCompact" + -- | "postCompact" + - | "sessionStart" + -- | "sessionEnd" + - | "userPromptSubmit" + -- | "subagentStart" + -- | "subagentStop" + - | "stop"; + - export const V2HookCompletedNotification__HookEventName = Schema.Literals([ + - "preToolUse", + -- "permissionRequest", + - "postToolUse", + -- "preCompact", + -- "postCompact", + - "sessionStart", + -- "sessionEnd", + - "userPromptSubmit", + -- "subagentStart", + -- "subagentStop", + - "stop", + - ]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2HookCompletedNotification__HookRunStatus = Schema.Literals([ + - export type V2HookCompletedNotification__HookScope = "thread" | "turn"; + - export const V2HookCompletedNotification__HookScope = Schema.Literals(["thread", "turn"]); + - + --export type V2HooksListResponse__AbsolutePathBuf = string; + --export const V2HooksListResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2HooksListResponse__HookErrorInfo = { + -- readonly message: string; + -- readonly path: string; + --}; + --export const V2HooksListResponse__HookErrorInfo = Schema.Struct({ + -- message: Schema.String, + -- path: Schema.String, + --}); + -- + --export type V2HooksListResponse__HookEventName = + -- | "preToolUse" + -- | "permissionRequest" + -- | "postToolUse" + -- | "preCompact" + -- | "postCompact" + -- | "sessionStart" + -- | "sessionEnd" + -- | "userPromptSubmit" + -- | "subagentStart" + -- | "subagentStop" + -- | "stop"; + --export const V2HooksListResponse__HookEventName = Schema.Literals([ + -- "preToolUse", + -- "permissionRequest", + -- "postToolUse", + -- "preCompact", + -- "postCompact", + -- "sessionStart", + -- "sessionEnd", + -- "userPromptSubmit", + -- "subagentStart", + -- "subagentStop", + -- "stop", + --]); + -- + --export type V2HooksListResponse__HookHandlerType = "command" | "prompt" | "agent"; + --export const V2HooksListResponse__HookHandlerType = Schema.Literals(["command", "prompt", "agent"]); + -- + --export type V2HooksListResponse__HookSource = + -- | "system" + -- | "user" + -- | "project" + -- | "mdm" + -- | "sessionFlags" + -- | "plugin" + -- | "cloudRequirements" + -- | "cloudManagedConfig" + -- | "legacyManagedConfigFile" + -- | "legacyManagedConfigMdm" + -- | "unknown"; + --export const V2HooksListResponse__HookSource = Schema.Literals([ + -- "system", + -- "user", + -- "project", + -- "mdm", + -- "sessionFlags", + -- "plugin", + -- "cloudRequirements", + -- "cloudManagedConfig", + -- "legacyManagedConfigFile", + -- "legacyManagedConfigMdm", + -- "unknown", + --]); + -- + --export type V2HooksListResponse__HookTrustStatus = "managed" | "untrusted" | "trusted" | "modified"; + --export const V2HooksListResponse__HookTrustStatus = Schema.Literals([ + -- "managed", + -- "untrusted", + -- "trusted", + -- "modified", + --]); + -- + --export type V2HookStartedNotification__AbsolutePathBuf = string; + --export const V2HookStartedNotification__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2HookStartedNotification__HookEventName = + - | "preToolUse" + -- | "permissionRequest" + - | "postToolUse" + -- | "preCompact" + -- | "postCompact" + - | "sessionStart" + -- | "sessionEnd" + - | "userPromptSubmit" + -- | "subagentStart" + -- | "subagentStop" + - | "stop"; + - export const V2HookStartedNotification__HookEventName = Schema.Literals([ + - "preToolUse", + -- "permissionRequest", + - "postToolUse", + -- "preCompact", + -- "postCompact", + - "sessionStart", + -- "sessionEnd", + - "userPromptSubmit", + -- "subagentStart", + -- "subagentStop", + - "stop", + - ]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2HookStartedNotification__HookRunStatus = Schema.Literals([ + - export type V2HookStartedNotification__HookScope = "thread" | "turn"; + - export const V2HookStartedNotification__HookScope = Schema.Literals(["thread", "turn"]); + - + --export type V2ItemCompletedNotification__AbsolutePathBuf = string; + --export const V2ItemCompletedNotification__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2ItemCompletedNotification__CollabAgentStatus = + - | "pendingInit" + - | "running" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2ItemCompletedNotification__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ItemCompletedNotification__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ItemCompletedNotification__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__CommandExecutionStatus = Schema.Litera + - + - export type V2ItemCompletedNotification__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ItemCompletedNotification__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__DynamicToolCallOutputContentItem = Sch + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ItemCompletedNotification__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ItemCompletedNotification__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ItemCompletedNotification__LegacyAppPathString = string; + --export const V2ItemCompletedNotification__LegacyAppPathString = Schema.String; + -- + --export type V2ItemCompletedNotification__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ItemCompletedNotification__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ItemCompletedNotification__McpToolCallError = { readonly message: string }; + - export const V2ItemCompletedNotification__McpToolCallError = Schema.Struct({ + - message: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ItemCompletedNotification__ReasoningEffort = string; + --export const V2ItemCompletedNotification__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2ItemCompletedNotification__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ItemCompletedNotification__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ItemCompletedNotification__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ItemCompletedNotification__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2ItemCompletedNotification__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__WebSearchAction = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ItemGuardianApprovalReviewCompletedNotification__AbsolutePathBuf = string; + --export const V2ItemGuardianApprovalReviewCompletedNotification__AbsolutePathBuf = + -- Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }); + -- + --export type V2ItemGuardianApprovalReviewCompletedNotification__AdditionalNetworkPermissions = { + -- readonly enabled?: boolean | null; + --}; + --export const V2ItemGuardianApprovalReviewCompletedNotification__AdditionalNetworkPermissions = + -- Schema.Struct({ enabled: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])) }); + -- + - export type V2ItemGuardianApprovalReviewCompletedNotification__AutoReviewDecisionSource = "agent"; + - export const V2ItemGuardianApprovalReviewCompletedNotification__AutoReviewDecisionSource = + - Schema.Literal("agent").annotate({ + -- description: "[UNSTABLE] Source that produced a terminal approval auto-review decision.", + -+ description: "[UNSTABLE] Source that produced a terminal guardian approval review decision.", + - }); + - + --export type V2ItemGuardianApprovalReviewCompletedNotification__FileSystemAccessMode = + -- | "read" + -- | "write" + -- | "deny"; + --export const V2ItemGuardianApprovalReviewCompletedNotification__FileSystemAccessMode = + -- Schema.Literals(["read", "write", "deny"]); + -- + - export type V2ItemGuardianApprovalReviewCompletedNotification__GuardianApprovalReviewStatus = + - | "inProgress" + - | "approved" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemGuardianApprovalReviewCompletedNotification__GuardianApprovalR + - | "aborted"; + - export const V2ItemGuardianApprovalReviewCompletedNotification__GuardianApprovalReviewStatus = + - Schema.Literals(["inProgress", "approved", "denied", "timedOut", "aborted"]).annotate({ + -- description: "[UNSTABLE] Lifecycle state for an approval auto-review.", + -+ description: "[UNSTABLE] Lifecycle state for a guardian approval review.", + - }); + - + - export type V2ItemGuardianApprovalReviewCompletedNotification__GuardianCommandSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemGuardianApprovalReviewCompletedNotification__GuardianRiskLevel + - | "critical"; + - export const V2ItemGuardianApprovalReviewCompletedNotification__GuardianRiskLevel = Schema.Literals( + - ["low", "medium", "high", "critical"], + --).annotate({ description: "[UNSTABLE] Risk level assigned by approval auto-review." }); + -+).annotate({ description: "[UNSTABLE] Risk level assigned by guardian approval review." }); + - + - export type V2ItemGuardianApprovalReviewCompletedNotification__GuardianUserAuthorization = + - | "unknown" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemGuardianApprovalReviewCompletedNotification__GuardianUserAutho + - | "high"; + - export const V2ItemGuardianApprovalReviewCompletedNotification__GuardianUserAuthorization = + - Schema.Literals(["unknown", "low", "medium", "high"]).annotate({ + -- description: "[UNSTABLE] Authorization level assigned by approval auto-review.", + -+ description: "[UNSTABLE] Authorization level assigned by guardian approval review.", + - }); + - + --export type V2ItemGuardianApprovalReviewCompletedNotification__LegacyAppPathString = string; + --export const V2ItemGuardianApprovalReviewCompletedNotification__LegacyAppPathString = Schema.String; + -- + - export type V2ItemGuardianApprovalReviewCompletedNotification__NetworkApprovalProtocol = + - | "http" + - | "https" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemGuardianApprovalReviewCompletedNotification__NetworkApprovalPr + - export const V2ItemGuardianApprovalReviewCompletedNotification__NetworkApprovalProtocol = + - Schema.Literals(["http", "https", "socks5Tcp", "socks5Udp"]); + - + --export type V2ItemGuardianApprovalReviewStartedNotification__AbsolutePathBuf = string; + --export const V2ItemGuardianApprovalReviewStartedNotification__AbsolutePathBuf = + -- Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }); + -- + --export type V2ItemGuardianApprovalReviewStartedNotification__AdditionalNetworkPermissions = { + -- readonly enabled?: boolean | null; + --}; + --export const V2ItemGuardianApprovalReviewStartedNotification__AdditionalNetworkPermissions = + -- Schema.Struct({ enabled: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])) }); + -- + --export type V2ItemGuardianApprovalReviewStartedNotification__FileSystemAccessMode = + -- | "read" + -- | "write" + -- | "deny"; + --export const V2ItemGuardianApprovalReviewStartedNotification__FileSystemAccessMode = + -- Schema.Literals(["read", "write", "deny"]); + -- + - export type V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalReviewStatus = + - | "inProgress" + - | "approved" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalRev + - | "aborted"; + - export const V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalReviewStatus = + - Schema.Literals(["inProgress", "approved", "denied", "timedOut", "aborted"]).annotate({ + -- description: "[UNSTABLE] Lifecycle state for an approval auto-review.", + -+ description: "[UNSTABLE] Lifecycle state for a guardian approval review.", + - }); + - + - export type V2ItemGuardianApprovalReviewStartedNotification__GuardianCommandSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemGuardianApprovalReviewStartedNotification__GuardianRiskLevel + - "medium", + - "high", + - "critical", + --]).annotate({ description: "[UNSTABLE] Risk level assigned by approval auto-review." }); + -+]).annotate({ description: "[UNSTABLE] Risk level assigned by guardian approval review." }); + - + - export type V2ItemGuardianApprovalReviewStartedNotification__GuardianUserAuthorization = + - | "unknown" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemGuardianApprovalReviewStartedNotification__GuardianUserAuthori + - | "high"; + - export const V2ItemGuardianApprovalReviewStartedNotification__GuardianUserAuthorization = + - Schema.Literals(["unknown", "low", "medium", "high"]).annotate({ + -- description: "[UNSTABLE] Authorization level assigned by approval auto-review.", + -+ description: "[UNSTABLE] Authorization level assigned by guardian approval review.", + - }); + - + --export type V2ItemGuardianApprovalReviewStartedNotification__LegacyAppPathString = string; + --export const V2ItemGuardianApprovalReviewStartedNotification__LegacyAppPathString = Schema.String; + -- + - export type V2ItemGuardianApprovalReviewStartedNotification__NetworkApprovalProtocol = + - | "http" + - | "https" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemGuardianApprovalReviewStartedNotification__NetworkApprovalProt + - export const V2ItemGuardianApprovalReviewStartedNotification__NetworkApprovalProtocol = + - Schema.Literals(["http", "https", "socks5Tcp", "socks5Udp"]); + - + --export type V2ItemStartedNotification__AbsolutePathBuf = string; + --export const V2ItemStartedNotification__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2ItemStartedNotification__CollabAgentStatus = + - | "pendingInit" + - | "running" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemStartedNotification__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2ItemStartedNotification__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ItemStartedNotification__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ItemStartedNotification__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemStartedNotification__CommandExecutionStatus = Schema.Literals + - + - export type V2ItemStartedNotification__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ItemStartedNotification__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemStartedNotification__DynamicToolCallOutputContentItem = Schem + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemStartedNotification__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ItemStartedNotification__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ItemStartedNotification__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ItemStartedNotification__LegacyAppPathString = string; + --export const V2ItemStartedNotification__LegacyAppPathString = Schema.String; + -- + --export type V2ItemStartedNotification__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ItemStartedNotification__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ItemStartedNotification__McpToolCallError = { readonly message: string }; + - export const V2ItemStartedNotification__McpToolCallError = Schema.Struct({ + - message: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemStartedNotification__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ItemStartedNotification__ReasoningEffort = string; + --export const V2ItemStartedNotification__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2ItemStartedNotification__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ItemStartedNotification__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ItemStartedNotification__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ItemStartedNotification__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2ItemStartedNotification__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ListMcpServerStatusResponse__McpAuthStatus = Schema.Literals([ + - "oAuth", + - ]); + - + --export type V2ListMcpServerStatusResponse__McpServerInfo = { + -- readonly description?: string | null; + -- readonly icons?: ReadonlyArray | null; + -- readonly name: string; + -- readonly title?: string | null; + -- readonly version: string; + -- readonly websiteUrl?: string | null; + --}; + --export const V2ListMcpServerStatusResponse__McpServerInfo = Schema.Struct({ + -- description: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- icons: Schema.optionalKey(Schema.Union([Schema.Array(Schema.Unknown), Schema.Null])), + -- name: Schema.String, + -- title: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- version: Schema.String, + -- websiteUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}).annotate({ description: "Presentation metadata advertised by an initialized MCP server." }); + -- + - export type V2ListMcpServerStatusResponse__Resource = { + - readonly _meta?: unknown; + - readonly annotations?: unknown; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ListMcpServerStatusResponse__Tool = Schema.Struct({ + - title: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }).annotate({ description: "Definition for a tool the client can call." }); + - + --export type V2LoginAccountParams__LoginAppBrand = "codex" | "chatgpt"; + --export const V2LoginAccountParams__LoginAppBrand = Schema.Literals(["codex", "chatgpt"]); + -- + --export type V2MarketplaceAddResponse__AbsolutePathBuf = string; + --export const V2MarketplaceAddResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2MarketplaceRemoveResponse__AbsolutePathBuf = string; + --export const V2MarketplaceRemoveResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2MarketplaceUpgradeResponse__AbsolutePathBuf = string; + --export const V2MarketplaceUpgradeResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2MarketplaceUpgradeResponse__MarketplaceUpgradeErrorInfo = { + -- readonly marketplaceName: string; + -- readonly message: string; + --}; + --export const V2MarketplaceUpgradeResponse__MarketplaceUpgradeErrorInfo = Schema.Struct({ + -- marketplaceName: Schema.String, + -- message: Schema.String, + --}); + -- + - export type V2McpResourceReadResponse__ResourceContent = + - | { + - readonly _meta?: unknown; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2McpResourceReadResponse__ResourceContent = Schema.Union([ + - }), + - ]).annotate({ description: "Contents returned when reading a resource from an MCP server." }); + - + --export type V2McpServerStatusUpdatedNotification__McpServerStartupFailureReason = + -- "reauthenticationRequired"; + --export const V2McpServerStatusUpdatedNotification__McpServerStartupFailureReason = Schema.Literal( + -- "reauthenticationRequired", + --); + -- + - export type V2McpServerStatusUpdatedNotification__McpServerStartupState = + - | "starting" + - | "ready" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2McpServerStatusUpdatedNotification__McpServerStartupState = Schem + - "cancelled", + - ]); + - + --export type V2ModelListResponse__InputModality = "text" | "image" | "audio"; + --export const V2ModelListResponse__InputModality = Schema.Literals([ + -- "text", + -- "image", + -- "audio", + --]).annotate({ description: "Canonical user-input modality tags advertised by a model." }); + -+export type V2ModelListResponse__InputModality = "text" | "image"; + -+export const V2ModelListResponse__InputModality = Schema.Literals(["text", "image"]).annotate({ + -+ description: "Canonical user-input modality tags advertised by a model.", + -+}); + - + - export type V2ModelListResponse__ModelAvailabilityNux = { readonly message: string }; + - export const V2ModelListResponse__ModelAvailabilityNux = Schema.Struct({ message: Schema.String }); + - + --export type V2ModelListResponse__ModelServiceTier = { + -- readonly description: string; + -- readonly id: string; + -- readonly name: string; + --}; + --export const V2ModelListResponse__ModelServiceTier = Schema.Struct({ + -- description: Schema.String, + -- id: Schema.String, + -- name: Schema.String, + --}); + -- + - export type V2ModelListResponse__ModelUpgradeInfo = { + - readonly migrationMarkdown?: string | null; + - readonly model: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ModelListResponse__ModelUpgradeInfo = Schema.Struct({ + - upgradeCopy: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type V2ModelListResponse__ReasoningEffort = string; + --export const V2ModelListResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -+export type V2ModelListResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ModelListResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2ModelReroutedNotification__ModelRerouteReason = "highRiskCyberActivity"; + - export const V2ModelReroutedNotification__ModelRerouteReason = + - Schema.Literal("highRiskCyberActivity"); + - + --export type V2ModelVerificationNotification__ModelVerification = "trustedAccessForCyber"; + --export const V2ModelVerificationNotification__ModelVerification = + -- Schema.Literal("trustedAccessForCyber"); + -- + --export type V2PermissionProfileListResponse__PermissionProfileSummary = { + -- readonly allowed: boolean; + -- readonly description?: string | null; + -- readonly id: string; + --}; + --export const V2PermissionProfileListResponse__PermissionProfileSummary = Schema.Struct({ + -- allowed: Schema.Boolean.annotate({ + -- description: "Whether the effective requirements allow selecting this profile.", + -- }), + -- description: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Optional user-facing description for display in clients.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- id: Schema.String.annotate({ description: "Available permission profile identifier." }), + --}); + -- + --export type V2PluginInstalledParams__AbsolutePathBuf = string; + --export const V2PluginInstalledParams__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2PluginInstalledResponse__AbsolutePathBuf = string; + --export const V2PluginInstalledResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2PluginInstalledResponse__MarketplaceInterface = { + -- readonly displayName?: string | null; + --}; + --export const V2PluginInstalledResponse__MarketplaceInterface = Schema.Struct({ + -- displayName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + --export type V2PluginInstalledResponse__PluginAuthPolicy = "ON_INSTALL" | "ON_USE"; + --export const V2PluginInstalledResponse__PluginAuthPolicy = Schema.Literals([ + -- "ON_INSTALL", + -- "ON_USE", + --]); + -- + --export type V2PluginInstalledResponse__PluginInstallPolicy = + -- | "NOT_AVAILABLE" + -- | "AVAILABLE" + -- | "INSTALLED_BY_DEFAULT"; + --export const V2PluginInstalledResponse__PluginInstallPolicy = Schema.Literals([ + -- "NOT_AVAILABLE", + -- "AVAILABLE", + -- "INSTALLED_BY_DEFAULT", + --]); + -- + --export type V2PluginInstalledResponse__PluginInstallPolicySource = + -- | "WORKSPACE_SETTING" + -- | "IMPLICIT_CANONICAL_APP"; + --export const V2PluginInstalledResponse__PluginInstallPolicySource = Schema.Literals([ + -- "WORKSPACE_SETTING", + -- "IMPLICIT_CANONICAL_APP", + --]); + -- + --export type V2PluginInstalledResponse__PluginShareDiscoverability = + -- | "LISTED" + -- | "UNLISTED" + -- | "PRIVATE"; + --export const V2PluginInstalledResponse__PluginShareDiscoverability = Schema.Literals([ + -- "LISTED", + -- "UNLISTED", + -- "PRIVATE", + --]); + -- + --export type V2PluginInstalledResponse__PluginSharePrincipalRole = "reader" | "editor" | "owner"; + --export const V2PluginInstalledResponse__PluginSharePrincipalRole = Schema.Literals([ + -- "reader", + -- "editor", + -- "owner", + --]); + -- + --export type V2PluginInstalledResponse__PluginSharePrincipalType = "user" | "group" | "workspace"; + --export const V2PluginInstalledResponse__PluginSharePrincipalType = Schema.Literals([ + -- "user", + -- "group", + -- "workspace", + --]); + -- + - export type V2PluginInstallParams__AbsolutePathBuf = string; + - export const V2PluginInstallParams__AbsolutePathBuf = Schema.String.annotate({ + - description: + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginInstallParams__AbsolutePathBuf = Schema.String.annotate({ + - }); + - + - export type V2PluginInstallResponse__AppSummary = { + -- readonly category?: string | null; + - readonly description?: string | null; + - readonly id: string; + - readonly installUrl?: string | null; + - readonly name: string; + -+ readonly needsAuth: boolean; + - }; + - export const V2PluginInstallResponse__AppSummary = Schema.Struct({ + -- category: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - description: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - id: Schema.String, + - installUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - name: Schema.String, + -+ needsAuth: Schema.Boolean, + - }).annotate({ description: "EXPERIMENTAL - app metadata summary for plugin responses." }); + - + - export type V2PluginInstallResponse__PluginAuthPolicy = "ON_INSTALL" | "ON_USE"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginListParams__AbsolutePathBuf = Schema.String.annotate({ + - "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + - }); + - + --export type V2PluginListParams__PluginListMarketplaceKind = + -- | "local" + -- | "vertical" + -- | "workspace-directory" + -- | "shared-with-me" + -- | "created-by-me-remote"; + --export const V2PluginListParams__PluginListMarketplaceKind = Schema.Literals([ + -- "local", + -- "vertical", + -- "workspace-directory", + -- "shared-with-me", + -- "created-by-me-remote", + --]); + -- + - export type V2PluginListResponse__AbsolutePathBuf = string; + - export const V2PluginListResponse__AbsolutePathBuf = Schema.String.annotate({ + - description: + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginListResponse__PluginInstallPolicy = Schema.Literals([ + - "INSTALLED_BY_DEFAULT", + - ]); + - + --export type V2PluginListResponse__PluginInstallPolicySource = + -- | "WORKSPACE_SETTING" + -- | "IMPLICIT_CANONICAL_APP"; + --export const V2PluginListResponse__PluginInstallPolicySource = Schema.Literals([ + -- "WORKSPACE_SETTING", + -- "IMPLICIT_CANONICAL_APP", + --]); + -- + --export type V2PluginListResponse__PluginShareDiscoverability = "LISTED" | "UNLISTED" | "PRIVATE"; + --export const V2PluginListResponse__PluginShareDiscoverability = Schema.Literals([ + -- "LISTED", + -- "UNLISTED", + -- "PRIVATE", + --]); + -- + --export type V2PluginListResponse__PluginSharePrincipalRole = "reader" | "editor" | "owner"; + --export const V2PluginListResponse__PluginSharePrincipalRole = Schema.Literals([ + -- "reader", + -- "editor", + -- "owner", + --]); + -- + --export type V2PluginListResponse__PluginSharePrincipalType = "user" | "group" | "workspace"; + --export const V2PluginListResponse__PluginSharePrincipalType = Schema.Literals([ + -- "user", + -- "group", + -- "workspace", + --]); + -- + - export type V2PluginReadParams__AbsolutePathBuf = string; + - export const V2PluginReadParams__AbsolutePathBuf = Schema.String.annotate({ + - description: + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginReadResponse__AbsolutePathBuf = Schema.String.annotate({ + - }); + - + - export type V2PluginReadResponse__AppSummary = { + -- readonly category?: string | null; + - readonly description?: string | null; + - readonly id: string; + - readonly installUrl?: string | null; + - readonly name: string; + -+ readonly needsAuth: boolean; + - }; + - export const V2PluginReadResponse__AppSummary = Schema.Struct({ + -- category: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - description: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - id: Schema.String, + - installUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - name: Schema.String, + -+ needsAuth: Schema.Boolean, + - }).annotate({ description: "EXPERIMENTAL - app metadata summary for plugin responses." }); + - + --export type V2PluginReadResponse__AppTemplateUnavailableReason = + -- | "NOT_CONFIGURED_FOR_WORKSPACE" + -- | "NO_ACTIVE_WORKSPACE"; + --export const V2PluginReadResponse__AppTemplateUnavailableReason = Schema.Literals([ + -- "NOT_CONFIGURED_FOR_WORKSPACE", + -- "NO_ACTIVE_WORKSPACE", + --]); + -- + --export type V2PluginReadResponse__HookEventName = + -- | "preToolUse" + -- | "permissionRequest" + -- | "postToolUse" + -- | "preCompact" + -- | "postCompact" + -- | "sessionStart" + -- | "sessionEnd" + -- | "userPromptSubmit" + -- | "subagentStart" + -- | "subagentStop" + -- | "stop"; + --export const V2PluginReadResponse__HookEventName = Schema.Literals([ + -- "preToolUse", + -- "permissionRequest", + -- "postToolUse", + -- "preCompact", + -- "postCompact", + -- "sessionStart", + -- "sessionEnd", + -- "userPromptSubmit", + -- "subagentStart", + -- "subagentStop", + -- "stop", + --]); + -- + - export type V2PluginReadResponse__PluginAuthPolicy = "ON_INSTALL" | "ON_USE"; + - export const V2PluginReadResponse__PluginAuthPolicy = Schema.Literals(["ON_INSTALL", "ON_USE"]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginReadResponse__PluginInstallPolicy = Schema.Literals([ + - "INSTALLED_BY_DEFAULT", + - ]); + - + --export type V2PluginReadResponse__PluginInstallPolicySource = + -- | "WORKSPACE_SETTING" + -- | "IMPLICIT_CANONICAL_APP"; + --export const V2PluginReadResponse__PluginInstallPolicySource = Schema.Literals([ + -- "WORKSPACE_SETTING", + -- "IMPLICIT_CANONICAL_APP", + --]); + -- + --export type V2PluginReadResponse__PluginShareDiscoverability = "LISTED" | "UNLISTED" | "PRIVATE"; + --export const V2PluginReadResponse__PluginShareDiscoverability = Schema.Literals([ + -- "LISTED", + -- "UNLISTED", + -- "PRIVATE", + --]); + -- + --export type V2PluginReadResponse__PluginSharePrincipalRole = "reader" | "editor" | "owner"; + --export const V2PluginReadResponse__PluginSharePrincipalRole = Schema.Literals([ + -- "reader", + -- "editor", + -- "owner", + --]); + -- + --export type V2PluginReadResponse__PluginSharePrincipalType = "user" | "group" | "workspace"; + --export const V2PluginReadResponse__PluginSharePrincipalType = Schema.Literals([ + -- "user", + -- "group", + -- "workspace", + --]); + -- + --export type V2PluginReadResponse__ScheduledTaskWeekday = + -- | "MO" + -- | "TU" + -- | "WE" + -- | "TH" + -- | "FR" + -- | "SA" + -- | "SU"; + --export const V2PluginReadResponse__ScheduledTaskWeekday = Schema.Literals([ + -- "MO", + -- "TU", + -- "WE", + -- "TH", + -- "FR", + -- "SA", + -- "SU", + --]); + -- + --export type V2PluginShareCheckoutResponse__AbsolutePathBuf = string; + --export const V2PluginShareCheckoutResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2PluginShareListResponse__AbsolutePathBuf = string; + --export const V2PluginShareListResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2PluginShareListResponse__PluginAuthPolicy = "ON_INSTALL" | "ON_USE"; + --export const V2PluginShareListResponse__PluginAuthPolicy = Schema.Literals([ + -- "ON_INSTALL", + -- "ON_USE", + --]); + -- + --export type V2PluginShareListResponse__PluginInstallPolicy = + -- | "NOT_AVAILABLE" + -- | "AVAILABLE" + -- | "INSTALLED_BY_DEFAULT"; + --export const V2PluginShareListResponse__PluginInstallPolicy = Schema.Literals([ + -- "NOT_AVAILABLE", + -- "AVAILABLE", + -- "INSTALLED_BY_DEFAULT", + --]); + -- + --export type V2PluginShareListResponse__PluginInstallPolicySource = + -- | "WORKSPACE_SETTING" + -- | "IMPLICIT_CANONICAL_APP"; + --export const V2PluginShareListResponse__PluginInstallPolicySource = Schema.Literals([ + -- "WORKSPACE_SETTING", + -- "IMPLICIT_CANONICAL_APP", + --]); + -- + --export type V2PluginShareListResponse__PluginShareDiscoverability = + -- | "LISTED" + -- | "UNLISTED" + -- | "PRIVATE"; + --export const V2PluginShareListResponse__PluginShareDiscoverability = Schema.Literals([ + -- "LISTED", + -- "UNLISTED", + -- "PRIVATE", + --]); + -- + --export type V2PluginShareListResponse__PluginSharePrincipalRole = "reader" | "editor" | "owner"; + --export const V2PluginShareListResponse__PluginSharePrincipalRole = Schema.Literals([ + -- "reader", + -- "editor", + -- "owner", + --]); + -- + --export type V2PluginShareListResponse__PluginSharePrincipalType = "user" | "group" | "workspace"; + --export const V2PluginShareListResponse__PluginSharePrincipalType = Schema.Literals([ + -- "user", + -- "group", + -- "workspace", + --]); + -- + --export type V2PluginShareSaveParams__AbsolutePathBuf = string; + --export const V2PluginShareSaveParams__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2PluginShareSaveParams__PluginShareDiscoverability = "LISTED" | "UNLISTED" | "PRIVATE"; + --export const V2PluginShareSaveParams__PluginShareDiscoverability = Schema.Literals([ + -- "LISTED", + -- "UNLISTED", + -- "PRIVATE", + --]); + -- + --export type V2PluginShareSaveParams__PluginSharePrincipalType = "user" | "group" | "workspace"; + --export const V2PluginShareSaveParams__PluginSharePrincipalType = Schema.Literals([ + -- "user", + -- "group", + -- "workspace", + --]); + -- + --export type V2PluginShareSaveParams__PluginShareTargetRole = "reader" | "editor"; + --export const V2PluginShareSaveParams__PluginShareTargetRole = Schema.Literals(["reader", "editor"]); + -- + --export type V2PluginShareUpdateTargetsParams__PluginSharePrincipalType = + -- | "user" + -- | "group" + -- | "workspace"; + --export const V2PluginShareUpdateTargetsParams__PluginSharePrincipalType = Schema.Literals([ + -- "user", + -- "group", + -- "workspace", + --]); + -- + --export type V2PluginShareUpdateTargetsParams__PluginShareTargetRole = "reader" | "editor"; + --export const V2PluginShareUpdateTargetsParams__PluginShareTargetRole = Schema.Literals([ + -- "reader", + -- "editor", + --]); + -- + --export type V2PluginShareUpdateTargetsParams__PluginShareUpdateDiscoverability = + -- | "UNLISTED" + -- | "PRIVATE" + -- | "LISTED"; + --export const V2PluginShareUpdateTargetsParams__PluginShareUpdateDiscoverability = Schema.Literals([ + -- "UNLISTED", + -- "PRIVATE", + -- "LISTED", + --]); + -- + --export type V2PluginShareUpdateTargetsResponse__PluginShareDiscoverability = + -- | "LISTED" + -- | "UNLISTED" + -- | "PRIVATE"; + --export const V2PluginShareUpdateTargetsResponse__PluginShareDiscoverability = Schema.Literals([ + -- "LISTED", + -- "UNLISTED", + -- "PRIVATE", + --]); + -- + --export type V2PluginShareUpdateTargetsResponse__PluginSharePrincipalRole = + -- | "reader" + -- | "editor" + -- | "owner"; + --export const V2PluginShareUpdateTargetsResponse__PluginSharePrincipalRole = Schema.Literals([ + -- "reader", + -- "editor", + -- "owner", + --]); + -- + --export type V2PluginShareUpdateTargetsResponse__PluginSharePrincipalType = + -- | "user" + -- | "group" + -- | "workspace"; + --export const V2PluginShareUpdateTargetsResponse__PluginSharePrincipalType = Schema.Literals([ + -- "user", + -- "group", + -- "workspace", + --]); + -- + --export type V2RawResponseCompletedNotification__TokenUsageBreakdown = { + -- readonly cacheWriteInputTokens?: number; + -- readonly cachedInputTokens: number; + -- readonly inputTokens: number; + -- readonly outputTokens: number; + -- readonly reasoningOutputTokens: number; + -- readonly totalTokens: number; + -+export type V2PluginReadResponse__SkillInterface = { + -+ readonly brandColor?: string | null; + -+ readonly defaultPrompt?: string | null; + -+ readonly displayName?: string | null; + -+ readonly iconLarge?: string | null; + -+ readonly iconSmall?: string | null; + -+ readonly shortDescription?: string | null; + - }; + --export const V2RawResponseCompletedNotification__TokenUsageBreakdown = Schema.Struct({ + -- cacheWriteInputTokens: Schema.optionalKey( + -- Schema.Number.annotate({ default: 0, format: "int64" }).check(Schema.isInt()), + -- ), + -- cachedInputTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- inputTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- outputTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- reasoningOutputTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- totalTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -+export const V2PluginReadResponse__SkillInterface = Schema.Struct({ + -+ brandColor: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ defaultPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ displayName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ iconLarge: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ iconSmall: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ shortDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type V2RawResponseItemCompletedNotification__AgentMessageInputContent = + -+export type V2RawResponseItemCompletedNotification__ContentItem = + - | { readonly text: string; readonly type: "input_text" } + -- | { readonly encrypted_content: string; readonly type: "encrypted_content" }; + --export const V2RawResponseItemCompletedNotification__AgentMessageInputContent = Schema.Union( + -+ | { readonly image_url: string; readonly type: "input_image" } + -+ | { readonly text: string; readonly type: "output_text" }; + -+export const V2RawResponseItemCompletedNotification__ContentItem = Schema.Union( + - [ + - Schema.Struct({ + - text: Schema.String, + -- type: Schema.Literal("input_text").annotate({ + -- title: "InputTextAgentMessageInputContentType", + -- }), + -- }).annotate({ title: "InputTextAgentMessageInputContent" }), + -+ type: Schema.Literal("input_text").annotate({ title: "InputTextContentItemType" }), + -+ }).annotate({ title: "InputTextContentItem" }), + - Schema.Struct({ + -- encrypted_content: Schema.String, + -- type: Schema.Literal("encrypted_content").annotate({ + -- title: "EncryptedContentAgentMessageInputContentType", + -- }), + -- }).annotate({ title: "EncryptedContentAgentMessageInputContent" }), + -+ image_url: Schema.String, + -+ type: Schema.Literal("input_image").annotate({ title: "InputImageContentItemType" }), + -+ }).annotate({ title: "InputImageContentItem" }), + -+ Schema.Struct({ + -+ text: Schema.String, + -+ type: Schema.Literal("output_text").annotate({ title: "OutputTextContentItemType" }), + -+ }).annotate({ title: "OutputTextContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + - + -+export type V2RawResponseItemCompletedNotification__GhostCommit = { + -+ readonly id: string; + -+ readonly parent?: string | null; + -+ readonly preexisting_untracked_dirs: ReadonlyArray; + -+ readonly preexisting_untracked_files: ReadonlyArray; + -+}; + -+export const V2RawResponseItemCompletedNotification__GhostCommit = Schema.Struct({ + -+ id: Schema.String, + -+ parent: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ preexisting_untracked_dirs: Schema.Array(Schema.String), + -+ preexisting_untracked_files: Schema.Array(Schema.String), + -+}).annotate({ description: "Details of a ghost commit created from a repository state." }); + -+ + - export type V2RawResponseItemCompletedNotification__ImageDetail = + - | "auto" + - | "low" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ImageDetail = Schema.Litera + - "original", + - ]); + - + --export type V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough = { + -- readonly turn_id?: string | null; + --}; + --export const V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough = + -- Schema.Struct({ + -- turn_id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- }).annotate({ + -- description: + -- "Internal Responses API passthrough metadata copied into underlying chat messages.\n\nResponses API strongly types this payload. Do not modify it without first getting API approval and making the corresponding Responses API change.", + -- }); + -- + - export type V2RawResponseItemCompletedNotification__LocalShellAction = { + - readonly command: ReadonlyArray; + - readonly env?: { readonly [x: string]: string } | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponsesApiWebSearchAction + - { mode: "oneOf" }, + - ); + - + --export type V2RemoteControlStatusChangedNotification__RemoteControlConnectionStatus = + -- | "disabled" + -- | "connecting" + -- | "connected" + -- | "errored"; + --export const V2RemoteControlStatusChangedNotification__RemoteControlConnectionStatus = + -- Schema.Literals(["disabled", "connecting", "connected", "errored"]); + -- + - export type V2ReviewStartParams__ReviewDelivery = "inline" | "detached"; + - export const V2ReviewStartParams__ReviewDelivery = Schema.Literals(["inline", "detached"]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartParams__ReviewTarget = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ReviewStartResponse__AbsolutePathBuf = string; + --export const V2ReviewStartResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2ReviewStartResponse__CollabAgentStatus = + - | "pendingInit" + - | "running" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2ReviewStartResponse__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ReviewStartResponse__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ReviewStartResponse__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__CommandExecutionStatus = Schema.Literals([ + - + - export type V2ReviewStartResponse__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ReviewStartResponse__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__DynamicToolCallOutputContentItem = Schema.Un + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ReviewStartResponse__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ReviewStartResponse__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ReviewStartResponse__LegacyAppPathString = string; + --export const V2ReviewStartResponse__LegacyAppPathString = Schema.String; + -- + --export type V2ReviewStartResponse__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ReviewStartResponse__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ReviewStartResponse__McpToolCallError = { readonly message: string }; + - export const V2ReviewStartResponse__McpToolCallError = Schema.Struct({ message: Schema.String }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ReviewStartResponse__ReasoningEffort = string; + --export const V2ReviewStartResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2ReviewStartResponse__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ReviewStartResponse__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ReviewStartResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ReviewStartResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2ReviewStartResponse__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__WebSearchAction = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2SendAddCreditsNudgeEmailParams__AddCreditsNudgeCreditType = "credits" | "usage_limit"; + --export const V2SendAddCreditsNudgeEmailParams__AddCreditsNudgeCreditType = Schema.Literals([ + -- "credits", + -- "usage_limit", + --]); + -- + --export type V2SendAddCreditsNudgeEmailResponse__AddCreditsNudgeEmailStatus = + -- | "sent" + -- | "cooldown_active"; + --export const V2SendAddCreditsNudgeEmailResponse__AddCreditsNudgeEmailStatus = Schema.Literals([ + -- "sent", + -- "cooldown_active", + --]); + -- + - export type V2ServerRequestResolvedNotification__RequestId = string | number; + - export const V2ServerRequestResolvedNotification__RequestId = Schema.Union([ + - Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2SkillsConfigWriteParams__AbsolutePathBuf = Schema.String.annotate + - "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + - }); + - + --export type V2SkillsExtraRootsSetParams__AbsolutePathBuf = string; + --export const V2SkillsExtraRootsSetParams__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2SkillsListResponse__AbsolutePathBuf = string; + --export const V2SkillsListResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -+export type V2SkillsListParams__SkillsListExtraRootsForCwd = { + -+ readonly cwd: string; + -+ readonly extraUserRoots: ReadonlyArray; + -+}; + -+export const V2SkillsListParams__SkillsListExtraRootsForCwd = Schema.Struct({ + -+ cwd: Schema.String, + -+ extraUserRoots: Schema.Array(Schema.String), + - }); + - + - export type V2SkillsListResponse__SkillErrorInfo = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2SkillsListResponse__SkillErrorInfo = Schema.Struct({ + - path: Schema.String, + - }); + - + -+export type V2SkillsListResponse__SkillInterface = { + -+ readonly brandColor?: string | null; + -+ readonly defaultPrompt?: string | null; + -+ readonly displayName?: string | null; + -+ readonly iconLarge?: string | null; + -+ readonly iconSmall?: string | null; + -+ readonly shortDescription?: string | null; + -+}; + -+export const V2SkillsListResponse__SkillInterface = Schema.Struct({ + -+ brandColor: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ defaultPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ displayName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ iconLarge: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ iconSmall: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ shortDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+}); + -+ + - export type V2SkillsListResponse__SkillScope = "user" | "repo" | "system" | "admin"; + - export const V2SkillsListResponse__SkillScope = Schema.Literals([ + - "user", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2SkillsListResponse__SkillToolDependency = Schema.Struct({ + - value: Schema.String, + - }); + - + --export type V2ThreadForkParams__ApprovalsReviewer = "user" | "auto_review" | "guardian_subagent"; + -+export type V2ThreadForkParams__ApprovalsReviewer = "user" | "guardian_subagent"; + - export const V2ThreadForkParams__ApprovalsReviewer = Schema.Literals([ + - "user", + -- "auto_review", + - "guardian_subagent", + - ]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }); + - + - export type V2ThreadForkParams__AskForApproval = + - | "untrusted" + -+ | "on-failure" + - | "on-request" + - | "never" + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkParams__AskForApproval = + - }; + - export const V2ThreadForkParams__AskForApproval = Schema.Union( + - [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -+ Schema.Literals(["untrusted", "on-failure", "on-request", "never"]), + - Schema.Struct({ + - granular: Schema.Struct({ + - mcp_elicitations: Schema.Boolean, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkParams__SandboxMode = Schema.Literals([ + - "danger-full-access", + - ]); + - + --export type V2ThreadForkParams__ThreadSource = string; + --export const V2ThreadForkParams__ThreadSource = Schema.String; + -+export type V2ThreadForkParams__ServiceTier = "fast" | "flex"; + -+export const V2ThreadForkParams__ServiceTier = Schema.Literals(["fast", "flex"]); + - + - export type V2ThreadForkResponse__AbsolutePathBuf = string; + - export const V2ThreadForkResponse__AbsolutePathBuf = Schema.String.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__AgentPath = Schema.String; + - + - export type V2ThreadForkResponse__AskForApproval = + - | "untrusted" + -+ | "on-failure" + - | "on-request" + - | "never" + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkResponse__AskForApproval = + - }; + - export const V2ThreadForkResponse__AskForApproval = Schema.Union( + - [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -+ Schema.Literals(["untrusted", "on-failure", "on-request", "never"]), + - Schema.Struct({ + - granular: Schema.Struct({ + - mcp_elicitations: Schema.Boolean, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2ThreadForkResponse__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ThreadForkResponse__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ThreadForkResponse__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__CommandExecutionStatus = Schema.Literals([ + - + - export type V2ThreadForkResponse__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ThreadForkResponse__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__DynamicToolCallOutputContentItem = Schema.Uni + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ThreadForkResponse__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ThreadForkResponse__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ThreadForkResponse__LegacyAppPathString = string; + --export const V2ThreadForkResponse__LegacyAppPathString = Schema.String; + -- + --export type V2ThreadForkResponse__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ThreadForkResponse__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ThreadForkResponse__McpToolCallError = { readonly message: string }; + - export const V2ThreadForkResponse__McpToolCallError = Schema.Struct({ message: Schema.String }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadForkResponse__ReasoningEffort = string; + --export const V2ThreadForkResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -+export type V2ThreadForkResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ThreadForkResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + --export type V2ThreadForkResponse__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ThreadForkResponse__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ThreadForkResponse__ServiceTier = "fast" | "flex"; + -+export const V2ThreadForkResponse__ServiceTier = Schema.Literals(["fast", "flex"]); + - + - export type V2ThreadForkResponse__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__ThreadActiveFlag = Schema.Literals([ + - export type V2ThreadForkResponse__ThreadId = string; + - export const V2ThreadForkResponse__ThreadId = Schema.String; + - + --export type V2ThreadForkResponse__ThreadSource = string; + --export const V2ThreadForkResponse__ThreadSource = Schema.String; + -- + - export type V2ThreadForkResponse__TurnStatus = + - | "completed" + - | "interrupted" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__WebSearchAction = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadGoalGetResponse__ThreadGoalStatus = + -- | "active" + -- | "paused" + -- | "blocked" + -- | "usageLimited" + -- | "budgetLimited" + -- | "complete"; + --export const V2ThreadGoalGetResponse__ThreadGoalStatus = Schema.Literals([ + -- "active", + -- "paused", + -- "blocked", + -- "usageLimited", + -- "budgetLimited", + -- "complete", + --]); + -- + --export type V2ThreadGoalSetParams__ThreadGoalStatus = + -- | "active" + -- | "paused" + -- | "blocked" + -- | "usageLimited" + -- | "budgetLimited" + -- | "complete"; + --export const V2ThreadGoalSetParams__ThreadGoalStatus = Schema.Literals([ + -- "active", + -- "paused", + -- "blocked", + -- "usageLimited", + -- "budgetLimited", + -- "complete", + --]); + -- + --export type V2ThreadGoalSetResponse__ThreadGoalStatus = + -- | "active" + -- | "paused" + -- | "blocked" + -- | "usageLimited" + -- | "budgetLimited" + -- | "complete"; + --export const V2ThreadGoalSetResponse__ThreadGoalStatus = Schema.Literals([ + -- "active", + -- "paused", + -- "blocked", + -- "usageLimited", + -- "budgetLimited", + -- "complete", + --]); + -- + --export type V2ThreadGoalUpdatedNotification__ThreadGoalStatus = + -- | "active" + -- | "paused" + -- | "blocked" + -- | "usageLimited" + -- | "budgetLimited" + -- | "complete"; + --export const V2ThreadGoalUpdatedNotification__ThreadGoalStatus = Schema.Literals([ + -- "active", + -- "paused", + -- "blocked", + -- "usageLimited", + -- "budgetLimited", + -- "complete", + --]); + -- + --export type V2ThreadListParams__SortDirection = "asc" | "desc"; + --export const V2ThreadListParams__SortDirection = Schema.Literals(["asc", "desc"]); + -- + --export type V2ThreadListParams__ThreadListCwdFilter = string | ReadonlyArray; + --export const V2ThreadListParams__ThreadListCwdFilter = Schema.Union([ + -- Schema.String, + -- Schema.Array(Schema.String), + --]); + -- + --export type V2ThreadListParams__ThreadSortKey = "created_at" | "updated_at" | "recency_at"; + --export const V2ThreadListParams__ThreadSortKey = Schema.Literals([ + -- "created_at", + -- "updated_at", + -- "recency_at", + --]); + -+export type V2ThreadListParams__ThreadSortKey = "created_at" | "updated_at"; + -+export const V2ThreadListParams__ThreadSortKey = Schema.Literals(["created_at", "updated_at"]); + - + - export type V2ThreadListParams__ThreadSourceKind = + - | "cli" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListParams__ThreadSourceKind = Schema.Literals([ + - "unknown", + - ]); + - + --export type V2ThreadListResponse__AbsolutePathBuf = string; + --export const V2ThreadListResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2ThreadListResponse__AgentPath = string; + - export const V2ThreadListResponse__AgentPath = Schema.String; + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2ThreadListResponse__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ThreadListResponse__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ThreadListResponse__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__CommandExecutionStatus = Schema.Literals([ + - + - export type V2ThreadListResponse__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ThreadListResponse__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__DynamicToolCallOutputContentItem = Schema.Uni + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ThreadListResponse__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ThreadListResponse__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ThreadListResponse__LegacyAppPathString = string; + --export const V2ThreadListResponse__LegacyAppPathString = Schema.String; + -- + --export type V2ThreadListResponse__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ThreadListResponse__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ThreadListResponse__McpToolCallError = { readonly message: string }; + - export const V2ThreadListResponse__McpToolCallError = Schema.Struct({ message: Schema.String }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadListResponse__ReasoningEffort = string; + --export const V2ThreadListResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2ThreadListResponse__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ThreadListResponse__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ThreadListResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ThreadListResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2ThreadListResponse__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__ThreadActiveFlag = Schema.Literals([ + - export type V2ThreadListResponse__ThreadId = string; + - export const V2ThreadListResponse__ThreadId = Schema.String; + - + --export type V2ThreadListResponse__ThreadSource = string; + --export const V2ThreadListResponse__ThreadSource = Schema.String; + -- + - export type V2ThreadListResponse__TurnStatus = + - | "completed" + - | "interrupted" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateParams__ThreadMetadataGitInfoUpdateParams = S + - ), + - }); + - + --export type V2ThreadMetadataUpdateResponse__AbsolutePathBuf = string; + --export const V2ThreadMetadataUpdateResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2ThreadMetadataUpdateResponse__AgentPath = string; + - export const V2ThreadMetadataUpdateResponse__AgentPath = Schema.String; + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__CollabAgentStatus = Schema.Literals + - "notFound", + - ]); + - + -+export type V2ThreadMetadataUpdateResponse__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ThreadMetadataUpdateResponse__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ThreadMetadataUpdateResponse__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__CommandExecutionStatus = Schema.Lit + - + - export type V2ThreadMetadataUpdateResponse__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ThreadMetadataUpdateResponse__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__DynamicToolCallOutputContentItem = + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__HookPromptFragment = Schema.Struct( + - text: Schema.String, + - }); + - + --export type V2ThreadMetadataUpdateResponse__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ThreadMetadataUpdateResponse__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ThreadMetadataUpdateResponse__LegacyAppPathString = string; + --export const V2ThreadMetadataUpdateResponse__LegacyAppPathString = Schema.String; + -- + --export type V2ThreadMetadataUpdateResponse__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ThreadMetadataUpdateResponse__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ThreadMetadataUpdateResponse__McpToolCallError = { readonly message: string }; + - export const V2ThreadMetadataUpdateResponse__McpToolCallError = Schema.Struct({ + - message: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadMetadataUpdateResponse__ReasoningEffort = string; + --export const V2ThreadMetadataUpdateResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2ThreadMetadataUpdateResponse__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ThreadMetadataUpdateResponse__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ThreadMetadataUpdateResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ThreadMetadataUpdateResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2ThreadMetadataUpdateResponse__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__ThreadActiveFlag = Schema.Literals( + - export type V2ThreadMetadataUpdateResponse__ThreadId = string; + - export const V2ThreadMetadataUpdateResponse__ThreadId = Schema.String; + - + --export type V2ThreadMetadataUpdateResponse__ThreadSource = string; + --export const V2ThreadMetadataUpdateResponse__ThreadSource = Schema.String; + -- + - export type V2ThreadMetadataUpdateResponse__TurnStatus = + - | "completed" + - | "interrupted" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__WebSearchAction = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadReadResponse__AbsolutePathBuf = string; + --export const V2ThreadReadResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2ThreadReadResponse__AgentPath = string; + - export const V2ThreadReadResponse__AgentPath = Schema.String; + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2ThreadReadResponse__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ThreadReadResponse__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ThreadReadResponse__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__CommandExecutionStatus = Schema.Literals([ + - + - export type V2ThreadReadResponse__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ThreadReadResponse__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__DynamicToolCallOutputContentItem = Schema.Uni + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ThreadReadResponse__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ThreadReadResponse__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ThreadReadResponse__LegacyAppPathString = string; + --export const V2ThreadReadResponse__LegacyAppPathString = Schema.String; + -- + --export type V2ThreadReadResponse__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ThreadReadResponse__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ThreadReadResponse__McpToolCallError = { readonly message: string }; + - export const V2ThreadReadResponse__McpToolCallError = Schema.Struct({ message: Schema.String }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadReadResponse__ReasoningEffort = string; + --export const V2ThreadReadResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2ThreadReadResponse__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ThreadReadResponse__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ThreadReadResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ThreadReadResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2ThreadReadResponse__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__ThreadActiveFlag = Schema.Literals([ + - export type V2ThreadReadResponse__ThreadId = string; + - export const V2ThreadReadResponse__ThreadId = Schema.String; + - + --export type V2ThreadReadResponse__ThreadSource = string; + --export const V2ThreadReadResponse__ThreadSource = Schema.String; + -- + - export type V2ThreadReadResponse__TurnStatus = + - | "completed" + - | "interrupted" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRealtimeOutputAudioDeltaNotification__ThreadRealtimeAudioCh + - }, + - ).annotate({ description: "EXPERIMENTAL - thread realtime audio chunk." }); + - + --export type V2ThreadRealtimeStartedNotification__RealtimeConversationVersion = "v1" | "v2" | "v3"; + -+export type V2ThreadRealtimeStartedNotification__RealtimeConversationVersion = "v1" | "v2"; + - export const V2ThreadRealtimeStartedNotification__RealtimeConversationVersion = Schema.Literals([ + - "v1", + - "v2", + -- "v3", + - ]); + - + --export type V2ThreadResumeParams__AgentMessageInputContent = + -- | { readonly text: string; readonly type: "input_text" } + -- | { readonly encrypted_content: string; readonly type: "encrypted_content" }; + --export const V2ThreadResumeParams__AgentMessageInputContent = Schema.Union( + -- [ + -- Schema.Struct({ + -- text: Schema.String, + -- type: Schema.Literal("input_text").annotate({ + -- title: "InputTextAgentMessageInputContentType", + -- }), + -- }).annotate({ title: "InputTextAgentMessageInputContent" }), + -- Schema.Struct({ + -- encrypted_content: Schema.String, + -- type: Schema.Literal("encrypted_content").annotate({ + -- title: "EncryptedContentAgentMessageInputContentType", + -- }), + -- }).annotate({ title: "EncryptedContentAgentMessageInputContent" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type V2ThreadResumeParams__ApprovalsReviewer = "user" | "auto_review" | "guardian_subagent"; + -+export type V2ThreadResumeParams__ApprovalsReviewer = "user" | "guardian_subagent"; + - export const V2ThreadResumeParams__ApprovalsReviewer = Schema.Literals([ + - "user", + -- "auto_review", + - "guardian_subagent", + - ]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }); + - + - export type V2ThreadResumeParams__AskForApproval = + - | "untrusted" + -+ | "on-failure" + - | "on-request" + - | "never" + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeParams__AskForApproval = + - }; + - export const V2ThreadResumeParams__AskForApproval = Schema.Union( + - [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -+ Schema.Literals(["untrusted", "on-failure", "on-request", "never"]), + - Schema.Struct({ + - granular: Schema.Struct({ + - mcp_elicitations: Schema.Boolean, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__AskForApproval = Schema.Union( + - { mode: "oneOf" }, + - ); + - + -+export type V2ThreadResumeParams__ContentItem = + -+ | { readonly text: string; readonly type: "input_text" } + -+ | { readonly image_url: string; readonly type: "input_image" } + -+ | { readonly text: string; readonly type: "output_text" }; + -+export const V2ThreadResumeParams__ContentItem = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ text: Schema.String, + -+ type: Schema.Literal("input_text").annotate({ title: "InputTextContentItemType" }), + -+ }).annotate({ title: "InputTextContentItem" }), + -+ Schema.Struct({ + -+ image_url: Schema.String, + -+ type: Schema.Literal("input_image").annotate({ title: "InputImageContentItemType" }), + -+ }).annotate({ title: "InputImageContentItem" }), + -+ Schema.Struct({ + -+ text: Schema.String, + -+ type: Schema.Literal("output_text").annotate({ title: "OutputTextContentItemType" }), + -+ }).annotate({ title: "OutputTextContentItem" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + -+export type V2ThreadResumeParams__GhostCommit = { + -+ readonly id: string; + -+ readonly parent?: string | null; + -+ readonly preexisting_untracked_dirs: ReadonlyArray; + -+ readonly preexisting_untracked_files: ReadonlyArray; + -+}; + -+export const V2ThreadResumeParams__GhostCommit = Schema.Struct({ + -+ id: Schema.String, + -+ parent: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ preexisting_untracked_dirs: Schema.Array(Schema.String), + -+ preexisting_untracked_files: Schema.Array(Schema.String), + -+}).annotate({ description: "Details of a ghost commit created from a repository state." }); + -+ + - export type V2ThreadResumeParams__ImageDetail = "auto" | "low" | "high" | "original"; + - export const V2ThreadResumeParams__ImageDetail = Schema.Literals([ + - "auto", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__ImageDetail = Schema.Literals([ + - "original", + - ]); + - + --export type V2ThreadResumeParams__InternalChatMessageMetadataPassthrough = { + -- readonly turn_id?: string | null; + --}; + --export const V2ThreadResumeParams__InternalChatMessageMetadataPassthrough = Schema.Struct({ + -- turn_id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}).annotate({ + -- description: + -- "Internal Responses API passthrough metadata copied into underlying chat messages.\n\nResponses API strongly types this payload. Do not modify it without first getting API approval and making the corresponding Responses API change.", + --}); + -- + - export type V2ThreadResumeParams__LocalShellAction = { + - readonly command: ReadonlyArray; + - readonly env?: { readonly [x: string]: string } | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__SandboxMode = Schema.Literals([ + - "danger-full-access", + - ]); + - + --export type V2ThreadResumeParams__SortDirection = "asc" | "desc"; + --export const V2ThreadResumeParams__SortDirection = Schema.Literals(["asc", "desc"]); + -- + --export type V2ThreadResumeParams__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2ThreadResumeParams__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -+export type V2ThreadResumeParams__ServiceTier = "fast" | "flex"; + -+export const V2ThreadResumeParams__ServiceTier = Schema.Literals(["fast", "flex"]); + - + - export type V2ThreadResumeResponse__AbsolutePathBuf = string; + - export const V2ThreadResumeResponse__AbsolutePathBuf = Schema.String.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__AgentPath = Schema.String; + - + - export type V2ThreadResumeResponse__AskForApproval = + - | "untrusted" + -+ | "on-failure" + - | "on-request" + - | "never" + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeResponse__AskForApproval = + - }; + - export const V2ThreadResumeResponse__AskForApproval = Schema.Union( + - [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -+ Schema.Literals(["untrusted", "on-failure", "on-request", "never"]), + - Schema.Struct({ + - granular: Schema.Struct({ + - mcp_elicitations: Schema.Boolean, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2ThreadResumeResponse__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ThreadResumeResponse__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ThreadResumeResponse__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__CommandExecutionStatus = Schema.Literals([ + - + - export type V2ThreadResumeResponse__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ThreadResumeResponse__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__DynamicToolCallOutputContentItem = Schema.U + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ThreadResumeResponse__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ThreadResumeResponse__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ThreadResumeResponse__LegacyAppPathString = string; + --export const V2ThreadResumeResponse__LegacyAppPathString = Schema.String; + -- + --export type V2ThreadResumeResponse__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ThreadResumeResponse__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ThreadResumeResponse__McpToolCallError = { readonly message: string }; + - export const V2ThreadResumeResponse__McpToolCallError = Schema.Struct({ message: Schema.String }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadResumeResponse__ReasoningEffort = string; + --export const V2ThreadResumeResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -+export type V2ThreadResumeResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ThreadResumeResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + --export type V2ThreadResumeResponse__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ThreadResumeResponse__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ThreadResumeResponse__ServiceTier = "fast" | "flex"; + -+export const V2ThreadResumeResponse__ServiceTier = Schema.Literals(["fast", "flex"]); + - + - export type V2ThreadResumeResponse__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__ThreadActiveFlag = Schema.Literals([ + - export type V2ThreadResumeResponse__ThreadId = string; + - export const V2ThreadResumeResponse__ThreadId = Schema.String; + - + --export type V2ThreadResumeResponse__ThreadSource = string; + --export const V2ThreadResumeResponse__ThreadSource = Schema.String; + -- + - export type V2ThreadResumeResponse__TurnStatus = + - | "completed" + - | "interrupted" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__WebSearchAction = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadRollbackResponse__AbsolutePathBuf = string; + --export const V2ThreadRollbackResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2ThreadRollbackResponse__AgentPath = string; + - export const V2ThreadRollbackResponse__AgentPath = Schema.String; + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2ThreadRollbackResponse__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ThreadRollbackResponse__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ThreadRollbackResponse__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__CommandExecutionStatus = Schema.Literals( + - + - export type V2ThreadRollbackResponse__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ThreadRollbackResponse__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__DynamicToolCallOutputContentItem = Schema + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ThreadRollbackResponse__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ThreadRollbackResponse__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ThreadRollbackResponse__LegacyAppPathString = string; + --export const V2ThreadRollbackResponse__LegacyAppPathString = Schema.String; + -- + --export type V2ThreadRollbackResponse__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ThreadRollbackResponse__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ThreadRollbackResponse__McpToolCallError = { readonly message: string }; + - export const V2ThreadRollbackResponse__McpToolCallError = Schema.Struct({ message: Schema.String }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadRollbackResponse__ReasoningEffort = string; + --export const V2ThreadRollbackResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2ThreadRollbackResponse__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ThreadRollbackResponse__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ThreadRollbackResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ThreadRollbackResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2ThreadRollbackResponse__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__ThreadActiveFlag = Schema.Literals([ + - export type V2ThreadRollbackResponse__ThreadId = string; + - export const V2ThreadRollbackResponse__ThreadId = Schema.String; + - + --export type V2ThreadRollbackResponse__ThreadSource = string; + --export const V2ThreadRollbackResponse__ThreadSource = Schema.String; + -- + - export type V2ThreadRollbackResponse__TurnStatus = + - | "completed" + - | "interrupted" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__WebSearchAction = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadSettingsUpdatedNotification__AbsolutePathBuf = string; + --export const V2ThreadSettingsUpdatedNotification__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2ThreadSettingsUpdatedNotification__ActivePermissionProfile = { + -- readonly extends?: string | null; + -- readonly id: string; + --}; + --export const V2ThreadSettingsUpdatedNotification__ActivePermissionProfile = Schema.Struct({ + -- extends: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Parent profile identifier from the selected permissions profile's `extends` setting, when present.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- id: Schema.String.annotate({ + -- description: + -- "Identifier from `default_permissions` or the implicit built-in default, such as `:workspace` or a user-defined `[permissions.]` profile.", + -- }), + --}); + -- + --export type V2ThreadSettingsUpdatedNotification__ApprovalsReviewer = + -- | "user" + -- | "auto_review" + -- | "guardian_subagent"; + --export const V2ThreadSettingsUpdatedNotification__ApprovalsReviewer = Schema.Literals([ + -- "user", + -- "auto_review", + -- "guardian_subagent", + --]).annotate({ + -- description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + --}); + -- + --export type V2ThreadSettingsUpdatedNotification__AskForApproval = + -- | "untrusted" + -- | "on-request" + -- | "never" + -- | { + -- readonly granular: { + -- readonly mcp_elicitations: boolean; + -- readonly request_permissions?: boolean; + -- readonly rules: boolean; + -- readonly sandbox_approval: boolean; + -- readonly skill_approval?: boolean; + -- }; + -- }; + --export const V2ThreadSettingsUpdatedNotification__AskForApproval = Schema.Union( + -- [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -- Schema.Struct({ + -- granular: Schema.Struct({ + -- mcp_elicitations: Schema.Boolean, + -- request_permissions: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- rules: Schema.Boolean, + -- sandbox_approval: Schema.Boolean, + -- skill_approval: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- }), + -- }).annotate({ title: "GranularAskForApproval" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type V2ThreadSettingsUpdatedNotification__ModeKind = "plan" | "default"; + --export const V2ThreadSettingsUpdatedNotification__ModeKind = Schema.Literals([ + -- "plan", + -- "default", + --]).annotate({ description: "Initial collaboration mode to use when the TUI starts." }); + -- + --export type V2ThreadSettingsUpdatedNotification__Personality = "none" | "friendly" | "pragmatic"; + --export const V2ThreadSettingsUpdatedNotification__Personality = Schema.Literals([ + -- "none", + -- "friendly", + -- "pragmatic", + --]); + -- + --export type V2ThreadSettingsUpdatedNotification__ReasoningEffort = string; + --export const V2ThreadSettingsUpdatedNotification__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2ThreadSettingsUpdatedNotification__ReasoningSummary = + -- | "auto" + -- | "concise" + -- | "detailed" + -- | "none"; + --export const V2ThreadSettingsUpdatedNotification__ReasoningSummary = Schema.Union( + -- [ + -- Schema.Literals(["auto", "concise", "detailed"]), + -- Schema.Literal("none").annotate({ description: "Option to disable reasoning summaries." }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ + -- description: + -- "A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries", + --}); + -- + --export type V2ThreadStartedNotification__AbsolutePathBuf = string; + --export const V2ThreadStartedNotification__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2ThreadStartedNotification__AgentPath = string; + - export const V2ThreadStartedNotification__AgentPath = Schema.String; + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2ThreadStartedNotification__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ThreadStartedNotification__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ThreadStartedNotification__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__CommandExecutionStatus = Schema.Litera + - + - export type V2ThreadStartedNotification__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ThreadStartedNotification__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__DynamicToolCallOutputContentItem = Sch + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ThreadStartedNotification__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ThreadStartedNotification__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ThreadStartedNotification__LegacyAppPathString = string; + --export const V2ThreadStartedNotification__LegacyAppPathString = Schema.String; + -- + --export type V2ThreadStartedNotification__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ThreadStartedNotification__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ThreadStartedNotification__McpToolCallError = { readonly message: string }; + - export const V2ThreadStartedNotification__McpToolCallError = Schema.Struct({ + - message: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadStartedNotification__ReasoningEffort = string; + --export const V2ThreadStartedNotification__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2ThreadStartedNotification__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ThreadStartedNotification__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ThreadStartedNotification__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ThreadStartedNotification__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2ThreadStartedNotification__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__ThreadActiveFlag = Schema.Literals([ + - export type V2ThreadStartedNotification__ThreadId = string; + - export const V2ThreadStartedNotification__ThreadId = Schema.String; + - + --export type V2ThreadStartedNotification__ThreadSource = string; + --export const V2ThreadStartedNotification__ThreadSource = Schema.String; + -- + - export type V2ThreadStartedNotification__TurnStatus = + - | "completed" + - | "interrupted" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__WebSearchAction = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadStartParams__ApprovalsReviewer = "user" | "auto_review" | "guardian_subagent"; + -+export type V2ThreadStartParams__ApprovalsReviewer = "user" | "guardian_subagent"; + - export const V2ThreadStartParams__ApprovalsReviewer = Schema.Literals([ + - "user", + -- "auto_review", + - "guardian_subagent", + - ]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }); + - + - export type V2ThreadStartParams__AskForApproval = + - | "untrusted" + -+ | "on-failure" + - | "on-request" + - | "never" + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartParams__AskForApproval = + - }; + - export const V2ThreadStartParams__AskForApproval = Schema.Union( + - [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -+ Schema.Literals(["untrusted", "on-failure", "on-request", "never"]), + - Schema.Struct({ + - granular: Schema.Struct({ + - mcp_elicitations: Schema.Boolean, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartParams__AskForApproval = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadStartParams__DynamicToolNamespaceTool = { + -- readonly deferLoading?: boolean; + -- readonly description: string; + -- readonly inputSchema: unknown; + -- readonly name: string; + -- readonly type: "function"; + --}; + --export const V2ThreadStartParams__DynamicToolNamespaceTool = Schema.Union( + -- [ + -- Schema.Struct({ + -- deferLoading: Schema.optionalKey(Schema.Boolean), + -- description: Schema.String, + -- inputSchema: Schema.Unknown, + -- name: Schema.String, + -- type: Schema.Literal("function").annotate({ title: "FunctionDynamicToolNamespaceToolType" }), + -- }).annotate({ title: "FunctionDynamicToolNamespaceTool" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type V2ThreadStartParams__LegacyAppPathString = string; + --export const V2ThreadStartParams__LegacyAppPathString = Schema.String; + -- + - export type V2ThreadStartParams__Personality = "none" | "friendly" | "pragmatic"; + - export const V2ThreadStartParams__Personality = Schema.Literals(["none", "friendly", "pragmatic"]); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartParams__SandboxMode = Schema.Literals([ + - "danger-full-access", + - ]); + - + --export type V2ThreadStartParams__ThreadSource = string; + --export const V2ThreadStartParams__ThreadSource = Schema.String; + -+export type V2ThreadStartParams__ServiceTier = "fast" | "flex"; + -+export const V2ThreadStartParams__ServiceTier = Schema.Literals(["fast", "flex"]); + - + - export type V2ThreadStartParams__ThreadStartSource = "startup" | "clear"; + - export const V2ThreadStartParams__ThreadStartSource = Schema.Literals(["startup", "clear"]); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__AgentPath = Schema.String; + - + - export type V2ThreadStartResponse__AskForApproval = + - | "untrusted" + -+ | "on-failure" + - | "on-request" + - | "never" + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartResponse__AskForApproval = + - }; + - export const V2ThreadStartResponse__AskForApproval = Schema.Union( + - [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -+ Schema.Literals(["untrusted", "on-failure", "on-request", "never"]), + - Schema.Struct({ + - granular: Schema.Struct({ + - mcp_elicitations: Schema.Boolean, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2ThreadStartResponse__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ThreadStartResponse__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ThreadStartResponse__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__CommandExecutionStatus = Schema.Literals([ + - + - export type V2ThreadStartResponse__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ThreadStartResponse__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__DynamicToolCallOutputContentItem = Schema.Un + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ThreadStartResponse__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ThreadStartResponse__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ThreadStartResponse__LegacyAppPathString = string; + --export const V2ThreadStartResponse__LegacyAppPathString = Schema.String; + -- + --export type V2ThreadStartResponse__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ThreadStartResponse__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ThreadStartResponse__McpToolCallError = { readonly message: string }; + - export const V2ThreadStartResponse__McpToolCallError = Schema.Struct({ message: Schema.String }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadStartResponse__ReasoningEffort = string; + --export const V2ThreadStartResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -+export type V2ThreadStartResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ThreadStartResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + --export type V2ThreadStartResponse__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ThreadStartResponse__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ThreadStartResponse__ServiceTier = "fast" | "flex"; + -+export const V2ThreadStartResponse__ServiceTier = Schema.Literals(["fast", "flex"]); + - + - export type V2ThreadStartResponse__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__ThreadActiveFlag = Schema.Literals([ + - export type V2ThreadStartResponse__ThreadId = string; + - export const V2ThreadStartResponse__ThreadId = Schema.String; + - + --export type V2ThreadStartResponse__ThreadSource = string; + --export const V2ThreadStartResponse__ThreadSource = Schema.String; + -- + - export type V2ThreadStartResponse__TurnStatus = + - | "completed" + - | "interrupted" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStatusChangedNotification__ThreadActiveFlag = Schema.Litera + - ]); + - + - export type V2ThreadTokenUsageUpdatedNotification__TokenUsageBreakdown = { + -- readonly cacheWriteInputTokens?: number; + - readonly cachedInputTokens: number; + - readonly inputTokens: number; + - readonly outputTokens: number; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadTokenUsageUpdatedNotification__TokenUsageBreakdown = { + - readonly totalTokens: number; + - }; + - export const V2ThreadTokenUsageUpdatedNotification__TokenUsageBreakdown = Schema.Struct({ + -- cacheWriteInputTokens: Schema.optionalKey( + -- Schema.Number.annotate({ default: 0, format: "int64" }).check(Schema.isInt()), + -- ), + - cachedInputTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + - inputTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + - outputTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadTokenUsageUpdatedNotification__TokenUsageBreakdown = Schema + - totalTokens: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + - }); + - + --export type V2ThreadUnarchiveResponse__AbsolutePathBuf = string; + --export const V2ThreadUnarchiveResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2ThreadUnarchiveResponse__AgentPath = string; + - export const V2ThreadUnarchiveResponse__AgentPath = Schema.String; + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2ThreadUnarchiveResponse__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2ThreadUnarchiveResponse__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2ThreadUnarchiveResponse__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__CommandExecutionStatus = Schema.Literals + - + - export type V2ThreadUnarchiveResponse__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2ThreadUnarchiveResponse__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__DynamicToolCallOutputContentItem = Schem + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ThreadUnarchiveResponse__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2ThreadUnarchiveResponse__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2ThreadUnarchiveResponse__LegacyAppPathString = string; + --export const V2ThreadUnarchiveResponse__LegacyAppPathString = Schema.String; + -- + --export type V2ThreadUnarchiveResponse__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2ThreadUnarchiveResponse__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ThreadUnarchiveResponse__McpToolCallError = { readonly message: string }; + - export const V2ThreadUnarchiveResponse__McpToolCallError = Schema.Struct({ + - message: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadUnarchiveResponse__ReasoningEffort = string; + --export const V2ThreadUnarchiveResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2ThreadUnarchiveResponse__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2ThreadUnarchiveResponse__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2ThreadUnarchiveResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2ThreadUnarchiveResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2ThreadUnarchiveResponse__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__ThreadActiveFlag = Schema.Literals([ + - export type V2ThreadUnarchiveResponse__ThreadId = string; + - export const V2ThreadUnarchiveResponse__ThreadId = Schema.String; + - + --export type V2ThreadUnarchiveResponse__ThreadSource = string; + --export const V2ThreadUnarchiveResponse__ThreadSource = Schema.String; + -- + - export type V2ThreadUnarchiveResponse__TurnStatus = + - | "completed" + - | "interrupted" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnsubscribeResponse__ThreadUnsubscribeStatus = Schema.Liter + - "unsubscribed", + - ]); + - + --export type V2TurnCompletedNotification__AbsolutePathBuf = string; + --export const V2TurnCompletedNotification__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2TurnCompletedNotification__CollabAgentStatus = + - | "pendingInit" + - | "running" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2TurnCompletedNotification__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2TurnCompletedNotification__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2TurnCompletedNotification__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__CommandExecutionStatus = Schema.Litera + - + - export type V2TurnCompletedNotification__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2TurnCompletedNotification__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__DynamicToolCallOutputContentItem = Sch + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2TurnCompletedNotification__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2TurnCompletedNotification__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2TurnCompletedNotification__LegacyAppPathString = string; + --export const V2TurnCompletedNotification__LegacyAppPathString = Schema.String; + -- + --export type V2TurnCompletedNotification__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2TurnCompletedNotification__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2TurnCompletedNotification__McpToolCallError = { readonly message: string }; + - export const V2TurnCompletedNotification__McpToolCallError = Schema.Struct({ + - message: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2TurnCompletedNotification__ReasoningEffort = string; + --export const V2TurnCompletedNotification__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2TurnCompletedNotification__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2TurnCompletedNotification__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2TurnCompletedNotification__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2TurnCompletedNotification__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2TurnCompletedNotification__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnPlanUpdatedNotification__TurnPlanStepStatus = Schema.Literals + - "completed", + - ]); + - + --export type V2TurnStartedNotification__AbsolutePathBuf = string; + --export const V2TurnStartedNotification__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2TurnStartedNotification__CollabAgentStatus = + - | "pendingInit" + - | "running" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartedNotification__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2TurnStartedNotification__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2TurnStartedNotification__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2TurnStartedNotification__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartedNotification__CommandExecutionStatus = Schema.Literals + - + - export type V2TurnStartedNotification__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2TurnStartedNotification__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartedNotification__DynamicToolCallOutputContentItem = Schem + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartedNotification__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2TurnStartedNotification__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2TurnStartedNotification__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2TurnStartedNotification__LegacyAppPathString = string; + --export const V2TurnStartedNotification__LegacyAppPathString = Schema.String; + -- + --export type V2TurnStartedNotification__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2TurnStartedNotification__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2TurnStartedNotification__McpToolCallError = { readonly message: string }; + - export const V2TurnStartedNotification__McpToolCallError = Schema.Struct({ + - message: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartedNotification__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2TurnStartedNotification__ReasoningEffort = string; + --export const V2TurnStartedNotification__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2TurnStartedNotification__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2TurnStartedNotification__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2TurnStartedNotification__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2TurnStartedNotification__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2TurnStartedNotification__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams__AbsolutePathBuf = Schema.String.annotate({ + - "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + - }); + - + --export type V2TurnStartParams__AdditionalContextKind = "untrusted" | "application"; + --export const V2TurnStartParams__AdditionalContextKind = Schema.Literals([ + -- "untrusted", + -- "application", + --]); + -- + --export type V2TurnStartParams__ApprovalsReviewer = "user" | "auto_review" | "guardian_subagent"; + -+export type V2TurnStartParams__ApprovalsReviewer = "user" | "guardian_subagent"; + - export const V2TurnStartParams__ApprovalsReviewer = Schema.Literals([ + - "user", + -- "auto_review", + - "guardian_subagent", + - ]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }); + - + - export type V2TurnStartParams__AskForApproval = + - | "untrusted" + -+ | "on-failure" + - | "on-request" + - | "never" + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartParams__AskForApproval = + - }; + - export const V2TurnStartParams__AskForApproval = Schema.Union( + - [ + -- Schema.Literals(["untrusted", "on-request", "never"]), + -+ Schema.Literals(["untrusted", "on-failure", "on-request", "never"]), + - Schema.Struct({ + - granular: Schema.Struct({ + - mcp_elicitations: Schema.Boolean, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams__AskForApproval = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2TurnStartParams__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2TurnStartParams__ImageDetail = Schema.Literals(["auto", "low", "high", "original"]); + -- + --export type V2TurnStartParams__LegacyAppPathString = string; + --export const V2TurnStartParams__LegacyAppPathString = Schema.String; + -- + - export type V2TurnStartParams__ModeKind = "plan" | "default"; + - export const V2TurnStartParams__ModeKind = Schema.Literals(["plan", "default"]).annotate({ + - description: "Initial collaboration mode to use when the TUI starts.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams__ModeKind = Schema.Literals(["plan", "default"]). + - export type V2TurnStartParams__Personality = "none" | "friendly" | "pragmatic"; + - export const V2TurnStartParams__Personality = Schema.Literals(["none", "friendly", "pragmatic"]); + - + --export type V2TurnStartParams__ReasoningEffort = string; + --export const V2TurnStartParams__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -+export type V2TurnStartParams__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2TurnStartParams__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2TurnStartParams__ReasoningSummary = "auto" | "concise" | "detailed" | "none"; + - export const V2TurnStartParams__ReasoningSummary = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams__ReasoningSummary = Schema.Union( + - "A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries", + - }); + - + -+export type V2TurnStartParams__ServiceTier = "fast" | "flex"; + -+export const V2TurnStartParams__ServiceTier = Schema.Literals(["fast", "flex"]); + -+ + - export type V2TurnStartParams__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + - readonly placeholder?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams__TextElement = Schema.Struct({ + - ), + - }); + - + --export type V2TurnStartResponse__AbsolutePathBuf = string; + --export const V2TurnStartResponse__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + - export type V2TurnStartResponse__CollabAgentStatus = + - | "pendingInit" + - | "running" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__CollabAgentStatus = Schema.Literals([ + - "notFound", + - ]); + - + -+export type V2TurnStartResponse__CommandAction = + -+ | { + -+ readonly command: string; + -+ readonly name: string; + -+ readonly path: string; + -+ readonly type: "read"; + -+ } + -+ | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { + -+ readonly command: string; + -+ readonly path?: string | null; + -+ readonly query?: string | null; + -+ readonly type: "search"; + -+ } + -+ | { readonly command: string; readonly type: "unknown" }; + -+export const V2TurnStartResponse__CommandAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ name: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -+ }).annotate({ title: "ReadCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -+ }).annotate({ title: "ListFilesCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -+ }).annotate({ title: "SearchCommandAction" }), + -+ Schema.Struct({ + -+ command: Schema.String, + -+ type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -+ }).annotate({ title: "UnknownCommandAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2TurnStartResponse__CommandExecutionStatus = + - | "inProgress" + - | "completed" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__CommandExecutionStatus = Schema.Literals([ + - + - export type V2TurnStartResponse__DynamicToolCallOutputContentItem = + - | { readonly text: string; readonly type: "inputText" } + -- | { readonly imageUrl: string; readonly type: "inputImage" } + -- | { readonly audioUrl: string; readonly type: "inputAudio" }; + -+ | { readonly imageUrl: string; readonly type: "inputImage" }; + - export const V2TurnStartResponse__DynamicToolCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__DynamicToolCallOutputContentItem = Schema.Unio + - title: "InputImageDynamicToolCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageDynamicToolCallOutputContentItem" }), + -- Schema.Struct({ + -- audioUrl: Schema.String, + -- type: Schema.Literal("inputAudio").annotate({ + -- title: "InputAudioDynamicToolCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioDynamicToolCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__HookPromptFragment = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2TurnStartResponse__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2TurnStartResponse__ImageDetail = Schema.Literals([ + -- "auto", + -- "low", + -- "high", + -- "original", + --]); + -- + --export type V2TurnStartResponse__LegacyAppPathString = string; + --export const V2TurnStartResponse__LegacyAppPathString = Schema.String; + -- + --export type V2TurnStartResponse__McpToolCallAppContext = { + -- readonly actionName?: string | null; + -- readonly appName?: string | null; + -- readonly connectorId: string; + -- readonly linkId?: string | null; + -- readonly resourceUri?: string | null; + --}; + --export const V2TurnStartResponse__McpToolCallAppContext = Schema.Struct({ + -- actionName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- appName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorId: Schema.String, + -- linkId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- resourceUri: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2TurnStartResponse__McpToolCallError = { readonly message: string }; + - export const V2TurnStartResponse__McpToolCallError = Schema.Struct({ message: Schema.String }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__PatchChangeKind = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2TurnStartResponse__ReasoningEffort = string; + --export const V2TurnStartResponse__ReasoningEffort = Schema.String.annotate({ + -- description: "A non-empty reasoning effort value advertised by the model.", + --}).check(Schema.isMinLength(1)); + -- + --export type V2TurnStartResponse__SubAgentActivityKind = + -- | "started" + -- | "interacted" + -- | "interrupted" + -- | "completed"; + --export const V2TurnStartResponse__SubAgentActivityKind = Schema.Literals([ + -- "started", + -- "interacted", + -- "interrupted", + -- "completed", + --]); + -+export type V2TurnStartResponse__ReasoningEffort = + -+ | "none" + -+ | "minimal" + -+ | "low" + -+ | "medium" + -+ | "high" + -+ | "xhigh"; + -+export const V2TurnStartResponse__ReasoningEffort = Schema.Literals([ + -+ "none", + -+ "minimal", + -+ "low", + -+ "medium", + -+ "high", + -+ "xhigh", + -+]).annotate({ + -+ description: + -+ "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", + -+}); + - + - export type V2TurnStartResponse__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__WebSearchAction = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2TurnSteerParams__AdditionalContextKind = "untrusted" | "application"; + --export const V2TurnSteerParams__AdditionalContextKind = Schema.Literals([ + -- "untrusted", + -- "application", + --]); + -- + --export type V2TurnSteerParams__ImageDetail = "auto" | "low" | "high" | "original"; + --export const V2TurnSteerParams__ImageDetail = Schema.Literals(["auto", "low", "high", "original"]); + -- + - export type V2TurnSteerParams__TextElement = { + - readonly byteRange: { readonly end: number; readonly start: number }; + - readonly placeholder?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnSteerParams__TextElement = Schema.Struct({ + - ), + - }); + - + --export type V2WindowsSandboxReadinessResponse__WindowsSandboxReadiness = + -- | "ready" + -- | "notConfigured" + -- | "updateRequired"; + --export const V2WindowsSandboxReadinessResponse__WindowsSandboxReadiness = Schema.Literals([ + -- "ready", + -- "notConfigured", + -- "updateRequired", + --]); + -- + - export type V2WindowsSandboxSetupCompletedNotification__WindowsSandboxSetupMode = + - | "elevated" + - | "unelevated"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ApplyPatchApprovalResponse__NetworkPolicyAmendment = Schema.Struct( + - }); + - + - export type ClientRequest__PluginInstallParams = { + -- readonly marketplacePath?: ClientRequest__AbsolutePathBuf | null; + -+ readonly forceRemoteSync?: boolean; + -+ readonly marketplacePath: ClientRequest__AbsolutePathBuf; + - readonly pluginName: string; + -- readonly remoteMarketplaceName?: string | null; + - }; + - export const ClientRequest__PluginInstallParams = Schema.Struct({ + -- marketplacePath: Schema.optionalKey(Schema.Union([ClientRequest__AbsolutePathBuf, Schema.Null])), + -+ forceRemoteSync: Schema.optionalKey( + -+ Schema.Boolean.annotate({ + -+ description: "When true, apply the remote plugin change before the local install flow.", + -+ }), + -+ ), + -+ marketplacePath: ClientRequest__AbsolutePathBuf, + - pluginName: Schema.String, + -- remoteMarketplaceName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type ClientRequest__PluginInstalledParams = { + -+export type ClientRequest__PluginListParams = { + - readonly cwds?: ReadonlyArray | null; + -- readonly installSuggestionPluginNames?: ReadonlyArray | null; + -+ readonly forceRemoteSync?: boolean; + - }; + --export const ClientRequest__PluginInstalledParams = Schema.Struct({ + -+export const ClientRequest__PluginListParams = Schema.Struct({ + - cwds: Schema.optionalKey( + - Schema.Union([ + - Schema.Array(ClientRequest__AbsolutePathBuf).annotate({ + -- description: "Optional working directories used to discover repo marketplaces.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- installSuggestionPluginNames: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.String).annotate({ + - description: + -- "Additional uninstalled plugin names that should be returned when present locally. This is used by mention surfaces that intentionally expose install entrypoints.", + -+ "Optional working directories used to discover repo marketplaces. When omitted, only home-scoped marketplaces and the official curated marketplace are considered.", + - }), + - Schema.Null, + - ]), + - ), + -+ forceRemoteSync: Schema.optionalKey( + -+ Schema.Boolean.annotate({ + -+ description: + -+ "When true, reconcile the official curated marketplace against the remote plugin state before listing marketplaces.", + -+ }), + -+ ), + - }); + - + - export type ClientRequest__PluginReadParams = { + -- readonly marketplacePath?: ClientRequest__AbsolutePathBuf | null; + -+ readonly marketplacePath: ClientRequest__AbsolutePathBuf; + - readonly pluginName: string; + -- readonly remoteMarketplaceName?: string | null; + - }; + - export const ClientRequest__PluginReadParams = Schema.Struct({ + -- marketplacePath: Schema.optionalKey(Schema.Union([ClientRequest__AbsolutePathBuf, Schema.Null])), + -+ marketplacePath: ClientRequest__AbsolutePathBuf, + - pluginName: Schema.String, + -- remoteMarketplaceName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + - export type ClientRequest__SandboxPolicy = + - | { readonly type: "dangerFullAccess" } + -- | { readonly networkAccess?: boolean; readonly type: "readOnly" } + -+ | { + -+ readonly access?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+ readonly networkAccess?: boolean; + -+ readonly type: "readOnly"; + -+ } + - | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + - | { + - readonly excludeSlashTmp?: boolean; + - readonly excludeTmpdirEnvVar?: boolean; + - readonly networkAccess?: boolean; + -+ readonly readOnlyAccess?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + - readonly type: "workspaceWrite"; + - readonly writableRoots?: ReadonlyArray; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__SandboxPolicy = Schema.Union( + - }), + - }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + - Schema.Struct({ + -+ access: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(ClientRequest__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + - networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + - }).annotate({ title: "ReadOnlySandboxPolicy" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__SandboxPolicy = Schema.Union( + - excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ readOnlyAccess: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(ClientRequest__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + - type: Schema.Literal("workspaceWrite").annotate({ title: "WorkspaceWriteSandboxPolicyType" }), + - writableRoots: Schema.optionalKey( + - Schema.Array(ClientRequest__AbsolutePathBuf).annotate({ default: [] }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__SkillsConfigWriteParams = Schema.Struct({ + - ), + - }); + - + --export type ClientRequest__SkillsExtraRootsSetParams = { + -- readonly extraRoots: ReadonlyArray; + --}; + --export const ClientRequest__SkillsExtraRootsSetParams = Schema.Struct({ + -- extraRoots: Schema.Array(ClientRequest__AbsolutePathBuf), + --}); + -- + --export type ClientRequest__SendAddCreditsNudgeEmailParams = { + -- readonly creditType: ClientRequest__AddCreditsNudgeCreditType; + -+export type ClientRequest__ExternalAgentConfigMigrationItem = { + -+ readonly cwd?: string | null; + -+ readonly description: string; + -+ readonly itemType: ClientRequest__ExternalAgentConfigMigrationItemType; + - }; + --export const ClientRequest__SendAddCreditsNudgeEmailParams = Schema.Struct({ + -- creditType: ClientRequest__AddCreditsNudgeCreditType, + -+export const ClientRequest__ExternalAgentConfigMigrationItem = Schema.Struct({ + -+ cwd: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ + -+ description: + -+ "Null or empty means home-scoped migration; non-empty means repo-scoped migration.", + -+ }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ description: Schema.String, + -+ itemType: ClientRequest__ExternalAgentConfigMigrationItemType, + - }); + - + --export type ClientRequest__ContentItem = + -- | { readonly text: string; readonly type: "input_text" } + -- | { + -- readonly detail?: ClientRequest__ImageDetail | null; + -- readonly image_url: string; + -- readonly type: "input_image"; + -- } + -- | { readonly audio_url: string; readonly type: "input_audio" } + -- | { readonly text: string; readonly type: "output_text" }; + --export const ClientRequest__ContentItem = Schema.Union( + -- [ + -- Schema.Struct({ + -- text: Schema.String, + -- type: Schema.Literal("input_text").annotate({ title: "InputTextContentItemType" }), + -- }).annotate({ title: "InputTextContentItem" }), + -- Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([ClientRequest__ImageDetail, Schema.Null])), + -- image_url: Schema.String, + -- type: Schema.Literal("input_image").annotate({ title: "InputImageContentItemType" }), + -- }).annotate({ title: "InputImageContentItem" }), + -- Schema.Struct({ + -- audio_url: Schema.String, + -- type: Schema.Literal("input_audio").annotate({ title: "InputAudioContentItemType" }), + -- }).annotate({ title: "InputAudioContentItem" }), + -- Schema.Struct({ + -- text: Schema.String, + -- type: Schema.Literal("output_text").annotate({ title: "OutputTextContentItemType" }), + -- }).annotate({ title: "OutputTextContentItem" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type ClientRequest__FunctionCallOutputContentItem = + - | { readonly text: string; readonly type: "input_text" } + - | { + - readonly detail?: ClientRequest__ImageDetail | null; + - readonly image_url: string; + - readonly type: "input_image"; + -- } + -- | { readonly audio_url: string; readonly type: "input_audio" } + -- | { readonly encrypted_content: string; readonly type: "encrypted_content" }; + -+ }; + - export const ClientRequest__FunctionCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__FunctionCallOutputContentItem = Schema.Union( + - title: "InputImageFunctionCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageFunctionCallOutputContentItem" }), + -- Schema.Struct({ + -- audio_url: Schema.String, + -- type: Schema.Literal("input_audio").annotate({ + -- title: "InputAudioFunctionCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioFunctionCallOutputContentItem" }), + -- Schema.Struct({ + -- encrypted_content: Schema.String, + -- type: Schema.Literal("encrypted_content").annotate({ + -- title: "EncryptedContentFunctionCallOutputContentItemType", + -- }), + -- }).annotate({ title: "EncryptedContentFunctionCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ).annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__InitializeParams = Schema.Struct({ + - clientInfo: ClientRequest__ClientInfo, + - }); + - + --export type ClientRequest__LoginAccountParams = + -- | { readonly apiKey: string; readonly type: "apiKey" } + -- | { + -- readonly appBrand?: ClientRequest__LoginAppBrand | null; + -- readonly codexStreamlinedLogin?: boolean; + -- readonly type: "chatgpt"; + -- readonly useHostedLoginSuccessPage?: boolean; + -- } + -- | { readonly type: "chatgptDeviceCode" } + -- | { + -- readonly accessToken: string; + -- readonly chatgptAccountId: string; + -- readonly chatgptPlanType?: string | null; + -- readonly type: "chatgptAuthTokens"; + -- } + -- | { readonly apiKey: string; readonly region: string; readonly type: "amazonBedrock" }; + --export const ClientRequest__LoginAccountParams = Schema.Union( + -- [ + -- Schema.Struct({ + -- apiKey: Schema.String, + -- type: Schema.Literal("apiKey").annotate({ title: "ApiKeyLoginAccountParamsType" }), + -- }).annotate({ title: "ApiKeyLoginAccountParams" }), + -- Schema.Struct({ + -- appBrand: Schema.optionalKey(Schema.Union([ClientRequest__LoginAppBrand, Schema.Null])), + -- codexStreamlinedLogin: Schema.optionalKey(Schema.Boolean), + -- type: Schema.Literal("chatgpt").annotate({ title: "ChatgptLoginAccountParamsType" }), + -- useHostedLoginSuccessPage: Schema.optionalKey(Schema.Boolean), + -- }).annotate({ title: "ChatgptLoginAccountParams" }), + -- Schema.Struct({ + -- type: Schema.Literal("chatgptDeviceCode").annotate({ + -- title: "ChatgptDeviceCodeLoginAccountParamsType", + -- }), + -- }).annotate({ title: "ChatgptDeviceCodeLoginAccountParams" }), + -- Schema.Struct({ + -- accessToken: Schema.String.annotate({ + -- description: + -- "Access token (JWT) supplied by the client. This token is used for backend API requests and email extraction.", + -- }), + -- chatgptAccountId: Schema.String.annotate({ + -- description: "Workspace/account identifier supplied by the client.", + -- }), + -- chatgptPlanType: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional plan type supplied by the client.\n\nWhen `null`, Codex attempts to derive the plan type from access-token claims. If unavailable, the plan defaults to `unknown`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- type: Schema.Literal("chatgptAuthTokens").annotate({ + -- title: "ChatgptAuthTokensLoginAccountParamsType", + -- }), + -- }).annotate({ + -- title: "ChatgptAuthTokensLoginAccountParams", + -- description: + -- "[UNSTABLE] FOR OPENAI INTERNAL USE ONLY - DO NOT USE. The access token must contain the same scopes that Codex-managed ChatGPT auth tokens have.", + -- }), + -- Schema.Struct({ + -- apiKey: Schema.String, + -- region: Schema.String, + -- type: Schema.Literal("amazonBedrock").annotate({ + -- title: "AmazonBedrockLoginAccountParamsType", + -- }), + -- }).annotate({ + -- title: "AmazonBedrockLoginAccountParams", + -- description: "[UNSTABLE] Managed Amazon Bedrock login is experimental.", + -- }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type ClientRequest__ListMcpServerStatusParams = { + - readonly cursor?: string | null; + - readonly detail?: ClientRequest__McpServerStatusDetail | null; + - readonly limit?: number | null; + -- readonly threadId?: string | null; + - }; + - export const ClientRequest__ListMcpServerStatusParams = Schema.Struct({ + - cursor: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ListMcpServerStatusParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + - export type ClientRequest__ConfigEdit = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ConfigValueWriteParams = Schema.Struct({ + - value: Schema.Unknown, + - }); + - + --export type ClientRequest__PluginListParams = { + -- readonly cwds?: ReadonlyArray | null; + -- readonly marketplaceKinds?: ReadonlyArray | null; + --}; + --export const ClientRequest__PluginListParams = Schema.Struct({ + -- cwds: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(ClientRequest__AbsolutePathBuf).annotate({ + -- description: + -- "Optional working directories used to discover repo marketplaces. When omitted, only home-scoped marketplaces and the official curated marketplace are considered.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- marketplaceKinds: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(ClientRequest__PluginListMarketplaceKind).annotate({ + -- description: + -- "Optional marketplace kind filter. When omitted, only local marketplaces are queried, plus the default remote catalog when enabled by feature flag.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + --export type ClientRequest__PluginShareTarget = { + -- readonly principalId: string; + -- readonly principalType: ClientRequest__PluginSharePrincipalType; + -- readonly role: ClientRequest__PluginShareTargetRole; + --}; + --export const ClientRequest__PluginShareTarget = Schema.Struct({ + -- principalId: Schema.String, + -- principalType: ClientRequest__PluginSharePrincipalType, + -- role: ClientRequest__PluginShareTargetRole, + --}); + -- + - export type ClientRequest__Settings = { + - readonly developer_instructions?: string | null; + - readonly model: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ReviewStartParams = Schema.Struct({ + - threadId: Schema.String, + - }); + - + -+export type ClientRequest__ThreadForkParams = { + -+ readonly approvalPolicy?: ClientRequest__AskForApproval | null; + -+ readonly approvalsReviewer?: ClientRequest__ApprovalsReviewer | null; + -+ readonly baseInstructions?: string | null; + -+ readonly config?: { readonly [x: string]: unknown } | null; + -+ readonly cwd?: string | null; + -+ readonly developerInstructions?: string | null; + -+ readonly ephemeral?: boolean; + -+ readonly model?: string | null; + -+ readonly modelProvider?: string | null; + -+ readonly sandbox?: ClientRequest__SandboxMode | null; + -+ readonly serviceTier?: ClientRequest__ServiceTier | null | null; + -+ readonly threadId: string; + -+}; + -+export const ClientRequest__ThreadForkParams = Schema.Struct({ + -+ approvalPolicy: Schema.optionalKey(Schema.Union([ClientRequest__AskForApproval, Schema.Null])), + -+ approvalsReviewer: Schema.optionalKey( + -+ Schema.Union([ClientRequest__ApprovalsReviewer, Schema.Null]).annotate({ + -+ description: + -+ "Override where approval requests are routed for review on this thread and subsequent turns.", + -+ }), + -+ ), + -+ baseInstructions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ config: Schema.optionalKey( + -+ Schema.Union([Schema.Record(Schema.String, Schema.Unknown), Schema.Null]), + -+ ), + -+ cwd: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ developerInstructions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ ephemeral: Schema.optionalKey(Schema.Boolean), + -+ model: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ + -+ description: "Configuration overrides for the forked thread, if any.", + -+ }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ modelProvider: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ sandbox: Schema.optionalKey(Schema.Union([ClientRequest__SandboxMode, Schema.Null])), + -+ serviceTier: Schema.optionalKey( + -+ Schema.Union([Schema.Union([ClientRequest__ServiceTier, Schema.Null]), Schema.Null]), + -+ ), + -+ threadId: Schema.String, + -+}).annotate({ + -+ description: + -+ "There are two ways to fork a thread: 1. By thread_id: load the thread from disk by thread_id and fork it into a new thread. 2. By path: load the thread from disk by path and fork it into a new thread.\n\nIf using path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.", + -+}); + -+ + - export type ClientRequest__ThreadResumeParams = { + - readonly approvalPolicy?: ClientRequest__AskForApproval | null; + - readonly approvalsReviewer?: ClientRequest__ApprovalsReviewer | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest__ThreadResumeParams = { + - readonly modelProvider?: string | null; + - readonly personality?: ClientRequest__Personality | null; + - readonly sandbox?: ClientRequest__SandboxMode | null; + -- readonly serviceTier?: string | null; + -+ readonly serviceTier?: ClientRequest__ServiceTier | null | null; + - readonly threadId: string; + - }; + - export const ClientRequest__ThreadResumeParams = Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ThreadResumeParams = Schema.Struct({ + - modelProvider: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - personality: Schema.optionalKey(Schema.Union([ClientRequest__Personality, Schema.Null])), + - sandbox: Schema.optionalKey(Schema.Union([ClientRequest__SandboxMode, Schema.Null])), + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ serviceTier: Schema.optionalKey( + -+ Schema.Union([Schema.Union([ClientRequest__ServiceTier, Schema.Null]), Schema.Null]), + -+ ), + - threadId: Schema.String, + - }).annotate({ + - description: + -- "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nFor non-running threads, the precedence is: history > non-empty path > thread_id. If using history or a non-empty path for a non-running thread, the thread_id param will be ignored.\n\nIf thread_id identifies a running thread, app-server rejoins that thread and treats a non-empty path as a consistency check against the active rollout path. Empty string path values are treated as absent.\n\nPrefer using thread_id whenever possible.", + -+ "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.", + - }); + - + --export type ClientRequest__MigrationDetails = { + -- readonly commands?: ReadonlyArray; + -- readonly hooks?: ReadonlyArray; + -- readonly mcpServers?: ReadonlyArray; + -- readonly memory?: ReadonlyArray; + -- readonly plugins?: ReadonlyArray; + -- readonly sessions?: ReadonlyArray; + -- readonly skills?: ReadonlyArray; + -- readonly subagents?: ReadonlyArray; + -+export type ClientRequest__SkillsListParams = { + -+ readonly cwds?: ReadonlyArray; + -+ readonly forceReload?: boolean; + -+ readonly perCwdExtraUserRoots?: ReadonlyArray | null; + - }; + --export const ClientRequest__MigrationDetails = Schema.Struct({ + -- commands: Schema.optionalKey( + -- Schema.Array(ClientRequest__CommandMigration).annotate({ default: [] }), + -- ), + -- hooks: Schema.optionalKey(Schema.Array(ClientRequest__HookMigration).annotate({ default: [] })), + -- mcpServers: Schema.optionalKey( + -- Schema.Array(ClientRequest__McpServerMigration).annotate({ default: [] }), + -- ), + -- memory: Schema.optionalKey(Schema.Array(Schema.String)), + -- plugins: Schema.optionalKey( + -- Schema.Array(ClientRequest__PluginsMigration).annotate({ default: [] }), + -+export const ClientRequest__SkillsListParams = Schema.Struct({ + -+ cwds: Schema.optionalKey( + -+ Schema.Array(Schema.String).annotate({ + -+ description: "When empty, defaults to the current session working directory.", + -+ }), + - ), + -- sessions: Schema.optionalKey( + -- Schema.Array(ClientRequest__SessionMigration).annotate({ default: [] }), + -+ forceReload: Schema.optionalKey( + -+ Schema.Boolean.annotate({ + -+ description: "When true, bypass the skills cache and re-scan skills from disk.", + -+ }), + - ), + -- skills: Schema.optionalKey(Schema.Array(ClientRequest__SkillMigration).annotate({ default: [] })), + -- subagents: Schema.optionalKey( + -- Schema.Array(ClientRequest__SubagentMigration).annotate({ default: [] }), + -+ perCwdExtraUserRoots: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.Array(ClientRequest__SkillsListExtraRootsForCwd).annotate({ + -+ description: "Optional per-cwd extra roots to scan as user-scoped skills.", + -+ }), + -+ Schema.Null, + -+ ]), + - ), + - }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: ClientRequest__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: ClientRequest__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const ClientRequest__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([ClientRequest__ImageDetail, Schema.Null])), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([ClientRequest__ImageDetail, Schema.Null])), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__UserInput = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type ClientRequest__ThreadGoalSetParams = { + -- readonly objective?: string | null; + -- readonly status?: ClientRequest__ThreadGoalStatus | null; + -- readonly threadId: string; + -- readonly tokenBudget?: number | null; + --}; + --export const ClientRequest__ThreadGoalSetParams = Schema.Struct({ + -- objective: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- status: Schema.optionalKey(Schema.Union([ClientRequest__ThreadGoalStatus, Schema.Null])), + -- threadId: Schema.String, + -- tokenBudget: Schema.optionalKey( + -- Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + -- ), + --}); + -- + - export type ClientRequest__ThreadMetadataUpdateParams = { + - readonly gitInfo?: ClientRequest__ThreadMetadataGitInfoUpdateParams | null; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ThreadMetadataUpdateParams = Schema.Struct({ + - threadId: Schema.String, + - }); + - + --export type ClientRequest__ThreadForkParams = { + -- readonly approvalPolicy?: ClientRequest__AskForApproval | null; + -- readonly approvalsReviewer?: ClientRequest__ApprovalsReviewer | null; + -- readonly baseInstructions?: string | null; + -- readonly config?: { readonly [x: string]: unknown } | null; + -- readonly cwd?: string | null; + -- readonly developerInstructions?: string | null; + -- readonly ephemeral?: boolean; + -- readonly lastTurnId?: string | null; + -- readonly model?: string | null; + -- readonly modelProvider?: string | null; + -- readonly sandbox?: ClientRequest__SandboxMode | null; + -- readonly serviceTier?: string | null; + -- readonly threadId: string; + -- readonly threadSource?: ClientRequest__ThreadSource | null; + --}; + --export const ClientRequest__ThreadForkParams = Schema.Struct({ + -- approvalPolicy: Schema.optionalKey(Schema.Union([ClientRequest__AskForApproval, Schema.Null])), + -- approvalsReviewer: Schema.optionalKey( + -- Schema.Union([ClientRequest__ApprovalsReviewer, Schema.Null]).annotate({ + -- description: + -- "Override where approval requests are routed for review on this thread and subsequent turns.", + -- }), + -- ), + -- baseInstructions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- config: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.Unknown), Schema.Null]), + -- ), + -- cwd: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- developerInstructions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- ephemeral: Schema.optionalKey(Schema.Boolean), + -- lastTurnId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional last turn id to fork through, inclusive.\n\nWhen specified, turns after `last_turn_id` are omitted from the fork. The referenced turn cannot be in progress.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- model: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Configuration overrides for the forked thread, if any.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- modelProvider: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- sandbox: Schema.optionalKey(Schema.Union([ClientRequest__SandboxMode, Schema.Null])), + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- threadId: Schema.String, + -- threadSource: Schema.optionalKey( + -- Schema.Union([ClientRequest__ThreadSource, Schema.Null]).annotate({ + -- description: + -- "Optional client-supplied analytics source classification for this forked thread.", + -- }), + -- ), + --}).annotate({ + -- description: + -- "There are two ways to fork a thread: 1. By thread_id: load the thread from disk by thread_id and fork it into a new thread. 2. By path: load the thread from disk by path and fork it into a new thread.\n\nIf using a non-empty path, the thread_id param will be ignored. Empty string path values are treated as absent.\n\nPrefer using thread_id whenever possible.", + --}); + -- + - export type ClientRequest__ThreadListParams = { + - readonly archived?: boolean | null; + - readonly cursor?: string | null; + -- readonly cwd?: ClientRequest__ThreadListCwdFilter | null; + -+ readonly cwd?: string | null; + - readonly limit?: number | null; + - readonly modelProviders?: ReadonlyArray | null; + - readonly searchTerm?: string | null; + -- readonly sortDirection?: ClientRequest__SortDirection | null; + - readonly sortKey?: ClientRequest__ThreadSortKey | null; + - readonly sourceKinds?: ReadonlyArray | null; + -- readonly useStateDbOnly?: boolean; + - }; + - export const ClientRequest__ThreadListParams = Schema.Struct({ + - archived: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ThreadListParams = Schema.Struct({ + - ]), + - ), + - cwd: Schema.optionalKey( + -- Schema.Union([ClientRequest__ThreadListCwdFilter, Schema.Null]).annotate({ + -- description: + -- "Optional cwd filter or filters; when set, only threads whose session cwd exactly matches one of these paths are returned.", + -- }), + -+ Schema.Union([ + -+ Schema.String.annotate({ + -+ description: + -+ "Optional cwd filter; when set, only threads whose session cwd exactly matches this path are returned.", + -+ }), + -+ Schema.Null, + -+ ]), + - ), + - limit: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ThreadListParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- sortDirection: Schema.optionalKey( + -- Schema.Union([ClientRequest__SortDirection, Schema.Null]).annotate({ + -- description: "Optional sort direction; defaults to descending (newest first).", + -- }), + -- ), + - sortKey: Schema.optionalKey( + - Schema.Union([ClientRequest__ThreadSortKey, Schema.Null]).annotate({ + - description: "Optional sort key; defaults to created_at.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ThreadListParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- useStateDbOnly: Schema.optionalKey( + -- Schema.Boolean.annotate({ + -- description: + -- "If true, return from the state DB without scanning JSONL rollouts to repair thread metadata. Omitted or false preserves scan-and-repair behavior.", + -- }), + -- ), + - }); + - + - export type ClientRequest__ThreadStartParams = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest__ThreadStartParams = { + - readonly personality?: ClientRequest__Personality | null; + - readonly sandbox?: ClientRequest__SandboxMode | null; + - readonly serviceName?: string | null; + -- readonly serviceTier?: string | null; + -+ readonly serviceTier?: ClientRequest__ServiceTier | null | null; + - readonly sessionStartSource?: ClientRequest__ThreadStartSource | null; + -- readonly threadSource?: ClientRequest__ThreadSource | null; + - }; + - export const ClientRequest__ThreadStartParams = Schema.Struct({ + - approvalPolicy: Schema.optionalKey(Schema.Union([ClientRequest__AskForApproval, Schema.Null])), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ThreadStartParams = Schema.Struct({ + - personality: Schema.optionalKey(Schema.Union([ClientRequest__Personality, Schema.Null])), + - sandbox: Schema.optionalKey(Schema.Union([ClientRequest__SandboxMode, Schema.Null])), + - serviceName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ serviceTier: Schema.optionalKey( + -+ Schema.Union([Schema.Union([ClientRequest__ServiceTier, Schema.Null]), Schema.Null]), + -+ ), + - sessionStartSource: Schema.optionalKey( + - Schema.Union([ClientRequest__ThreadStartSource, Schema.Null]), + - ), + -- threadSource: Schema.optionalKey( + -- Schema.Union([ClientRequest__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional client-supplied analytics source classification for this thread.", + -- }), + -- ), + - }); + - + - export type ClientRequest__WindowsSandboxSetupStartParams = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__WindowsSandboxSetupStartParams = Schema.Struct({ + - mode: ClientRequest__WindowsSandboxSetupMode, + - }); + - + --export type CommandExecutionRequestApprovalParams__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: CommandExecutionRequestApprovalParams__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const CommandExecutionRequestApprovalParams__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: CommandExecutionRequestApprovalParams__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type CommandExecutionRequestApprovalParams__FileSystemSpecialPath = + -- | { readonly kind: "root" } + -- | { readonly kind: "minimal" } + -- | { + -- readonly kind: "project_roots"; + -- readonly subpath?: CommandExecutionRequestApprovalParams__LegacyAppPathString | null; + -- } + -- | { readonly kind: "tmpdir" } + -- | { readonly kind: "slash_tmp" } + -- | { + -- readonly kind: "unknown"; + -- readonly path: string; + -- readonly subpath?: CommandExecutionRequestApprovalParams__LegacyAppPathString | null; + -- }; + --export const CommandExecutionRequestApprovalParams__FileSystemSpecialPath = Schema.Union( + -- [ + -- Schema.Struct({ kind: Schema.Literal("root") }).annotate({ + -- title: "RootFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("minimal") }).annotate({ + -- title: "MinimalFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("project_roots"), + -- subpath: Schema.optionalKey( + -- Schema.Union([CommandExecutionRequestApprovalParams__LegacyAppPathString, Schema.Null]), + -- ), + -- }).annotate({ title: "KindFileSystemSpecialPath" }), + -- Schema.Struct({ kind: Schema.Literal("tmpdir") }).annotate({ + -- title: "TmpdirFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("slash_tmp") }).annotate({ + -- title: "SlashTmpFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("unknown"), + -- path: Schema.String, + -- subpath: Schema.optionalKey( + -- Schema.Union([CommandExecutionRequestApprovalParams__LegacyAppPathString, Schema.Null]), + -- ), + -- }), + -- ], + -- { mode: "oneOf" }, + -+export type CommandExecutionRequestApprovalParams__AdditionalFileSystemPermissions = { + -+ readonly read?: ReadonlyArray | null; + -+ readonly write?: ReadonlyArray | null; + -+}; + -+export const CommandExecutionRequestApprovalParams__AdditionalFileSystemPermissions = Schema.Struct( + -+ { + -+ read: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.Array(CommandExecutionRequestApprovalParams__AbsolutePathBuf), + -+ Schema.Null, + -+ ]), + -+ ), + -+ write: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.Array(CommandExecutionRequestApprovalParams__AbsolutePathBuf), + -+ Schema.Null, + -+ ]), + -+ ), + -+ }, + - ); + - + - export type CommandExecutionRequestApprovalParams__NetworkApprovalContext = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const McpServerElicitationRequestParams__McpElicitationUntitledSingleSele + - type: McpServerElicitationRequestParams__McpElicitationStringType, + - }); + - + --export type PermissionsRequestApprovalParams__FileSystemSpecialPath = + -- | { readonly kind: "root" } + -- | { readonly kind: "minimal" } + -- | { + -- readonly kind: "project_roots"; + -- readonly subpath?: PermissionsRequestApprovalParams__LegacyAppPathString | null; + -- } + -- | { readonly kind: "tmpdir" } + -- | { readonly kind: "slash_tmp" } + -- | { + -- readonly kind: "unknown"; + -- readonly path: string; + -- readonly subpath?: PermissionsRequestApprovalParams__LegacyAppPathString | null; + -- }; + --export const PermissionsRequestApprovalParams__FileSystemSpecialPath = Schema.Union( + -- [ + -- Schema.Struct({ kind: Schema.Literal("root") }).annotate({ + -- title: "RootFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("minimal") }).annotate({ + -- title: "MinimalFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("project_roots"), + -- subpath: Schema.optionalKey( + -- Schema.Union([PermissionsRequestApprovalParams__LegacyAppPathString, Schema.Null]), + -- ), + -- }).annotate({ title: "KindFileSystemSpecialPath" }), + -- Schema.Struct({ kind: Schema.Literal("tmpdir") }).annotate({ + -- title: "TmpdirFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("slash_tmp") }).annotate({ + -- title: "SlashTmpFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("unknown"), + -- path: Schema.String, + -- subpath: Schema.optionalKey( + -- Schema.Union([PermissionsRequestApprovalParams__LegacyAppPathString, Schema.Null]), + -- ), + -- }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type PermissionsRequestApprovalResponse__FileSystemSpecialPath = + -- | { readonly kind: "root" } + -- | { readonly kind: "minimal" } + -- | { + -- readonly kind: "project_roots"; + -- readonly subpath?: PermissionsRequestApprovalResponse__LegacyAppPathString | null; + -- } + -- | { readonly kind: "tmpdir" } + -- | { readonly kind: "slash_tmp" } + -- | { + -- readonly kind: "unknown"; + -- readonly path: string; + -- readonly subpath?: PermissionsRequestApprovalResponse__LegacyAppPathString | null; + -- }; + --export const PermissionsRequestApprovalResponse__FileSystemSpecialPath = Schema.Union( + -- [ + -- Schema.Struct({ kind: Schema.Literal("root") }).annotate({ + -- title: "RootFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("minimal") }).annotate({ + -- title: "MinimalFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("project_roots"), + -- subpath: Schema.optionalKey( + -- Schema.Union([PermissionsRequestApprovalResponse__LegacyAppPathString, Schema.Null]), + -- ), + -- }).annotate({ title: "KindFileSystemSpecialPath" }), + -- Schema.Struct({ kind: Schema.Literal("tmpdir") }).annotate({ + -- title: "TmpdirFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("slash_tmp") }).annotate({ + -- title: "SlashTmpFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("unknown"), + -- path: Schema.String, + -- subpath: Schema.optionalKey( + -- Schema.Union([PermissionsRequestApprovalResponse__LegacyAppPathString, Schema.Null]), + -- ), + -- }), + -- ], + -- { mode: "oneOf" }, + --); + -+export type PermissionsRequestApprovalParams__AdditionalFileSystemPermissions = { + -+ readonly read?: ReadonlyArray | null; + -+ readonly write?: ReadonlyArray | null; + -+}; + -+export const PermissionsRequestApprovalParams__AdditionalFileSystemPermissions = Schema.Struct({ + -+ read: Schema.optionalKey( + -+ Schema.Union([Schema.Array(PermissionsRequestApprovalParams__AbsolutePathBuf), Schema.Null]), + -+ ), + -+ write: Schema.optionalKey( + -+ Schema.Union([Schema.Array(PermissionsRequestApprovalParams__AbsolutePathBuf), Schema.Null]), + -+ ), + -+}); + - + --export type ServerNotification__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: ServerNotification__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const ServerNotification__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: ServerNotification__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -+export type PermissionsRequestApprovalResponse__AdditionalFileSystemPermissions = { + -+ readonly read?: ReadonlyArray | null; + -+ readonly write?: ReadonlyArray | null; + -+}; + -+export const PermissionsRequestApprovalResponse__AdditionalFileSystemPermissions = Schema.Struct({ + -+ read: Schema.optionalKey( + -+ Schema.Union([Schema.Array(PermissionsRequestApprovalResponse__AbsolutePathBuf), Schema.Null]), + -+ ), + -+ write: Schema.optionalKey( + -+ Schema.Union([Schema.Array(PermissionsRequestApprovalResponse__AbsolutePathBuf), Schema.Null]), + -+ ), + -+}); + - + - export type ServerNotification__FsChangedNotification = { + - readonly changedPaths: ReadonlyArray; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__FsChangedNotification = Schema.Struct({ + - }), + - }).annotate({ description: "Filesystem watch notification emitted for `fs/watch` subscribers." }); + - + --export type ServerNotification__SandboxPolicy = + -- | { readonly type: "dangerFullAccess" } + -- | { readonly networkAccess?: boolean; readonly type: "readOnly" } + -- | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + -- | { + -- readonly excludeSlashTmp?: boolean; + -- readonly excludeTmpdirEnvVar?: boolean; + -- readonly networkAccess?: boolean; + -- readonly type: "workspaceWrite"; + -- readonly writableRoots?: ReadonlyArray; + -- }; + --export const ServerNotification__SandboxPolicy = Schema.Union( + -- [ + -- Schema.Struct({ + -- type: Schema.Literal("dangerFullAccess").annotate({ + -- title: "DangerFullAccessSandboxPolicyType", + -- }), + -- }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + -- }).annotate({ title: "ReadOnlySandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey( + -- Schema.Literals(["restricted", "enabled"]).annotate({ default: "restricted" }), + -- ), + -- type: Schema.Literal("externalSandbox").annotate({ + -- title: "ExternalSandboxSandboxPolicyType", + -- }), + -- }).annotate({ title: "ExternalSandboxSandboxPolicy" }), + -- Schema.Struct({ + -- excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("workspaceWrite").annotate({ title: "WorkspaceWriteSandboxPolicyType" }), + -- writableRoots: Schema.optionalKey( + -- Schema.Array(ServerNotification__AbsolutePathBuf).annotate({ default: [] }), + -- ), + -- }).annotate({ title: "WorkspaceWriteSandboxPolicy" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type ServerNotification__AppMetadata = { + - readonly categories?: ReadonlyArray | null; + - readonly developer?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__CollabAgentState = Schema.Struct({ + - status: ServerNotification__CollabAgentStatus, + - }); + - + --export type ServerNotification__ExternalAgentConfigImportItemTypeFailure = { + -- readonly cwd?: string | null; + -- readonly errorType?: string | null; + -- readonly failureStage: string; + -- readonly itemType: ServerNotification__ExternalAgentConfigMigrationItemType; + -- readonly message: string; + -- readonly source?: string | null; + -- readonly subErrorType?: string | null; + --}; + --export const ServerNotification__ExternalAgentConfigImportItemTypeFailure = Schema.Struct({ + -- cwd: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- errorType: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- failureStage: Schema.String, + -- itemType: ServerNotification__ExternalAgentConfigMigrationItemType, + -- message: Schema.String, + -- source: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- subErrorType: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + --export type ServerNotification__ExternalAgentConfigImportItemTypeSuccess = { + -- readonly cwd?: string | null; + -- readonly itemType: ServerNotification__ExternalAgentConfigMigrationItemType; + -- readonly source?: string | null; + -- readonly target?: string | null; + --}; + --export const ServerNotification__ExternalAgentConfigImportItemTypeSuccess = Schema.Struct({ + -- cwd: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- itemType: ServerNotification__ExternalAgentConfigMigrationItemType, + -- source: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- target: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type ServerNotification__FuzzyFileSearchResult = { + - readonly file_name: string; + - readonly indices?: ReadonlyArray | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__GuardianApprovalReview = Schema.Struct({ + - ), + - }).annotate({ + - description: + -- "[UNSTABLE] Temporary approval auto-review payload used by `item/autoApprovalReview/*` notifications. This shape is expected to change soon.", + -+ "[UNSTABLE] Temporary guardian approval review payload used by `item/autoApprovalReview/*` notifications. This shape is expected to change soon.", + - }); + - + - export type ServerNotification__HookOutputEntry = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__HookOutputEntry = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type ServerNotification__FileSystemSpecialPath = + -- | { readonly kind: "root" } + -- | { readonly kind: "minimal" } + -- | { + -- readonly kind: "project_roots"; + -- readonly subpath?: ServerNotification__LegacyAppPathString | null; + -- } + -- | { readonly kind: "tmpdir" } + -- | { readonly kind: "slash_tmp" } + -- | { + -- readonly kind: "unknown"; + -- readonly path: string; + -- readonly subpath?: ServerNotification__LegacyAppPathString | null; + -- }; + --export const ServerNotification__FileSystemSpecialPath = Schema.Union( + -- [ + -- Schema.Struct({ kind: Schema.Literal("root") }).annotate({ + -- title: "RootFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("minimal") }).annotate({ + -- title: "MinimalFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("project_roots"), + -- subpath: Schema.optionalKey( + -- Schema.Union([ServerNotification__LegacyAppPathString, Schema.Null]), + -- ), + -- }).annotate({ title: "KindFileSystemSpecialPath" }), + -- Schema.Struct({ kind: Schema.Literal("tmpdir") }).annotate({ + -- title: "TmpdirFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("slash_tmp") }).annotate({ + -- title: "SlashTmpFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("unknown"), + -- path: Schema.String, + -- subpath: Schema.optionalKey( + -- Schema.Union([ServerNotification__LegacyAppPathString, Schema.Null]), + -- ), + -- }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type ServerNotification__McpServerStatusUpdatedNotification = { + - readonly error?: string | null; + -- readonly failureReason?: ServerNotification__McpServerStartupFailureReason | null; + - readonly name: string; + - readonly status: ServerNotification__McpServerStartupState; + -- readonly threadId?: string | null; + - }; + - export const ServerNotification__McpServerStatusUpdatedNotification = Schema.Struct({ + - error: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- failureReason: Schema.optionalKey( + -- Schema.Union([ServerNotification__McpServerStartupFailureReason, Schema.Null]), + -- ), + - name: Schema.String, + - status: ServerNotification__McpServerStartupState, + -- threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + - export type ServerNotification__MemoryCitation = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ModelReroutedNotification = Schema.Struct({ + - turnId: Schema.String, + - }); + - + --export type ServerNotification__ModelVerificationNotification = { + -- readonly threadId: string; + -- readonly turnId: string; + -- readonly verifications: ReadonlyArray; + --}; + --export const ServerNotification__ModelVerificationNotification = Schema.Struct({ + -- threadId: Schema.String, + -- turnId: Schema.String, + -- verifications: Schema.Array(ServerNotification__ModelVerification), + --}); + -+export type ServerNotification__GuardianApprovalReviewAction = + -+ | { + -+ readonly command: string; + -+ readonly cwd: string; + -+ readonly source: ServerNotification__GuardianCommandSource; + -+ readonly type: "command"; + -+ } + -+ | { + -+ readonly argv: ReadonlyArray; + -+ readonly cwd: string; + -+ readonly program: string; + -+ readonly source: ServerNotification__GuardianCommandSource; + -+ readonly type: "execve"; + -+ } + -+ | { readonly cwd: string; readonly files: ReadonlyArray; readonly type: "applyPatch" } + -+ | { + -+ readonly host: string; + -+ readonly port: number; + -+ readonly protocol: ServerNotification__NetworkApprovalProtocol; + -+ readonly target: string; + -+ readonly type: "networkAccess"; + -+ } + -+ | { + -+ readonly connectorId?: string | null; + -+ readonly connectorName?: string | null; + -+ readonly server: string; + -+ readonly toolName: string; + -+ readonly toolTitle?: string | null; + -+ readonly type: "mcpToolCall"; + -+ }; + -+export const ServerNotification__GuardianApprovalReviewAction = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ cwd: Schema.String, + -+ source: ServerNotification__GuardianCommandSource, + -+ type: Schema.Literal("command").annotate({ + -+ title: "CommandGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "CommandGuardianApprovalReviewAction" }), + -+ Schema.Struct({ + -+ argv: Schema.Array(Schema.String), + -+ cwd: Schema.String, + -+ program: Schema.String, + -+ source: ServerNotification__GuardianCommandSource, + -+ type: Schema.Literal("execve").annotate({ title: "ExecveGuardianApprovalReviewActionType" }), + -+ }).annotate({ title: "ExecveGuardianApprovalReviewAction" }), + -+ Schema.Struct({ + -+ cwd: Schema.String, + -+ files: Schema.Array(Schema.String), + -+ type: Schema.Literal("applyPatch").annotate({ + -+ title: "ApplyPatchGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "ApplyPatchGuardianApprovalReviewAction" }), + -+ Schema.Struct({ + -+ host: Schema.String, + -+ port: Schema.Number.annotate({ format: "uint16" }) + -+ .check(Schema.isInt()) + -+ .check(Schema.isGreaterThanOrEqualTo(0)), + -+ protocol: ServerNotification__NetworkApprovalProtocol, + -+ target: Schema.String, + -+ type: Schema.Literal("networkAccess").annotate({ + -+ title: "NetworkAccessGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "NetworkAccessGuardianApprovalReviewAction" }), + -+ Schema.Struct({ + -+ connectorId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ connectorName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ server: Schema.String, + -+ toolName: Schema.String, + -+ toolTitle: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("mcpToolCall").annotate({ + -+ title: "McpToolCallGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "McpToolCallGuardianApprovalReviewAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + - + - export type ServerNotification__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__AccountUpdatedNotification = Schema.Struct({ + - planType: Schema.optionalKey(Schema.Union([ServerNotification__PlanType, Schema.Null])), + - }); + - + -+export type ServerNotification__RateLimitSnapshot = { + -+ readonly credits?: ServerNotification__CreditsSnapshot | null; + -+ readonly limitId?: string | null; + -+ readonly limitName?: string | null; + -+ readonly planType?: ServerNotification__PlanType | null; + -+ readonly primary?: ServerNotification__RateLimitWindow | null; + -+ readonly secondary?: ServerNotification__RateLimitWindow | null; + -+}; + -+export const ServerNotification__RateLimitSnapshot = Schema.Struct({ + -+ credits: Schema.optionalKey(Schema.Union([ServerNotification__CreditsSnapshot, Schema.Null])), + -+ limitId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ limitName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ planType: Schema.optionalKey(Schema.Union([ServerNotification__PlanType, Schema.Null])), + -+ primary: Schema.optionalKey(Schema.Union([ServerNotification__RateLimitWindow, Schema.Null])), + -+ secondary: Schema.optionalKey(Schema.Union([ServerNotification__RateLimitWindow, Schema.Null])), + -+}); + -+ + - export type ServerNotification__ThreadRealtimeStartedNotification = { + -- readonly realtimeSessionId?: string | null; + -+ readonly sessionId?: string | null; + - readonly threadId: string; + - readonly version: ServerNotification__RealtimeConversationVersion; + - }; + - export const ServerNotification__ThreadRealtimeStartedNotification = Schema.Struct({ + -- realtimeSessionId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ sessionId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - threadId: Schema.String, + - version: ServerNotification__RealtimeConversationVersion, + - }).annotate({ description: "EXPERIMENTAL - emitted when thread realtime startup is accepted." }); + - + --export type ServerNotification__Settings = { + -- readonly developer_instructions?: string | null; + -- readonly model: string; + -- readonly reasoning_effort?: ServerNotification__ReasoningEffort | null; + --}; + --export const ServerNotification__Settings = Schema.Struct({ + -- developer_instructions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- model: Schema.String, + -- reasoning_effort: Schema.optionalKey( + -- Schema.Union([ServerNotification__ReasoningEffort, Schema.Null]), + -- ), + --}).annotate({ description: "Settings for a collaboration mode." }); + -- + --export type ServerNotification__RemoteControlStatusChangedNotification = { + -- readonly environmentId?: string | null; + -- readonly installationId: string; + -- readonly serverName: string; + -- readonly status: ServerNotification__RemoteControlConnectionStatus; + --}; + --export const ServerNotification__RemoteControlStatusChangedNotification = Schema.Struct({ + -- environmentId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- installationId: Schema.String, + -- serverName: Schema.String, + -- status: ServerNotification__RemoteControlConnectionStatus, + --}).annotate({ + -- description: "Current remote-control connection status and remote identity exposed to clients.", + --}); + -- + - export type ServerNotification__ServerRequestResolvedNotification = { + - readonly requestId: ServerNotification__RequestId; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ServerRequestResolvedNotification = Schema.Stru + - threadId: Schema.String, + - }); + - + --export type ServerNotification__RateLimitSnapshot = { + -- readonly credits?: ServerNotification__CreditsSnapshot | null; + -- readonly individualLimit?: ServerNotification__SpendControlLimitSnapshot | null; + -- readonly limitId?: string | null; + -- readonly limitName?: string | null; + -- readonly planType?: ServerNotification__PlanType | null; + -- readonly primary?: ServerNotification__RateLimitWindow | null; + -- readonly rateLimitReachedType?: ServerNotification__RateLimitReachedType | null; + -- readonly secondary?: ServerNotification__RateLimitWindow | null; + -- readonly spendControlReached?: boolean | null; + --}; + --export const ServerNotification__RateLimitSnapshot = Schema.Struct({ + -- credits: Schema.optionalKey(Schema.Union([ServerNotification__CreditsSnapshot, Schema.Null])), + -- individualLimit: Schema.optionalKey( + -- Schema.Union([ServerNotification__SpendControlLimitSnapshot, Schema.Null]), + -- ), + -- limitId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- limitName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- planType: Schema.optionalKey(Schema.Union([ServerNotification__PlanType, Schema.Null])), + -- primary: Schema.optionalKey(Schema.Union([ServerNotification__RateLimitWindow, Schema.Null])), + -- rateLimitReachedType: Schema.optionalKey( + -- Schema.Union([ServerNotification__RateLimitReachedType, Schema.Null]), + -- ), + -- secondary: Schema.optionalKey(Schema.Union([ServerNotification__RateLimitWindow, Schema.Null])), + -- spendControlReached: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Boolean.annotate({ + -- description: + -- "Backend-reported spend-control state. `None` is unavailable, not a sparse-update recovery.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + - export type ServerNotification__UserInput = + - | { + - readonly text: string; + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: ServerNotification__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: ServerNotification__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const ServerNotification__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([ServerNotification__ImageDetail, Schema.Null])), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([ServerNotification__ImageDetail, Schema.Null])), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ThreadStatus = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type ServerNotification__ThreadGoal = { + -- readonly createdAt: number; + -- readonly objective: string; + -- readonly status: ServerNotification__ThreadGoalStatus; + -- readonly threadId: string; + -- readonly timeUsedSeconds: number; + -- readonly tokenBudget?: number | null; + -- readonly tokensUsed: number; + -- readonly updatedAt: number; + --}; + --export const ServerNotification__ThreadGoal = Schema.Struct({ + -- createdAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- objective: Schema.String, + -- status: ServerNotification__ThreadGoalStatus, + -- threadId: Schema.String, + -- timeUsedSeconds: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- tokenBudget: Schema.optionalKey( + -- Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + -- ), + -- tokensUsed: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- updatedAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + --}); + -- + - export type ServerNotification__SubAgentSource = + - | "review" + - | "compact" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__WindowsSandboxSetupCompletedNotification = Sche + - success: Schema.Boolean, + - }); + - + --export type ServerRequest__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: ServerRequest__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const ServerRequest__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: ServerRequest__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -+export type ServerRequest__AdditionalFileSystemPermissions = { + -+ readonly read?: ReadonlyArray | null; + -+ readonly write?: ReadonlyArray | null; + -+}; + -+export const ServerRequest__AdditionalFileSystemPermissions = Schema.Struct({ + -+ read: Schema.optionalKey( + -+ Schema.Union([Schema.Array(ServerRequest__AbsolutePathBuf), Schema.Null]), + -+ ), + -+ write: Schema.optionalKey( + -+ Schema.Union([Schema.Array(ServerRequest__AbsolutePathBuf), Schema.Null]), + -+ ), + -+}); + - + - export type ServerRequest__ChatgptAuthTokensRefreshParams = { + - readonly previousAccountId?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerRequest__ChatgptAuthTokensRefreshParams = Schema.Struct({ + - reason: ServerRequest__ChatgptAuthTokensRefreshReason, + - }); + - + --export type ServerRequest__FileSystemSpecialPath = + -- | { readonly kind: "root" } + -- | { readonly kind: "minimal" } + -- | { readonly kind: "project_roots"; readonly subpath?: ServerRequest__LegacyAppPathString | null } + -- | { readonly kind: "tmpdir" } + -- | { readonly kind: "slash_tmp" } + -- | { + -- readonly kind: "unknown"; + -- readonly path: string; + -- readonly subpath?: ServerRequest__LegacyAppPathString | null; + -- }; + --export const ServerRequest__FileSystemSpecialPath = Schema.Union( + -- [ + -- Schema.Struct({ kind: Schema.Literal("root") }).annotate({ + -- title: "RootFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("minimal") }).annotate({ + -- title: "MinimalFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("project_roots"), + -- subpath: Schema.optionalKey(Schema.Union([ServerRequest__LegacyAppPathString, Schema.Null])), + -- }).annotate({ title: "KindFileSystemSpecialPath" }), + -- Schema.Struct({ kind: Schema.Literal("tmpdir") }).annotate({ + -- title: "TmpdirFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("slash_tmp") }).annotate({ + -- title: "SlashTmpFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("unknown"), + -- path: Schema.String, + -- subpath: Schema.optionalKey(Schema.Union([ServerRequest__LegacyAppPathString, Schema.Null])), + -- }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type ServerRequest__McpElicitationBooleanSchema = { + - readonly default?: boolean | null; + - readonly description?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ToolRequestUserInputParams__ToolRequestUserInputQuestion = Schema.S + - + - export type V2AccountRateLimitsUpdatedNotification__RateLimitSnapshot = { + - readonly credits?: V2AccountRateLimitsUpdatedNotification__CreditsSnapshot | null; + -- readonly individualLimit?: V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot | null; + - readonly limitId?: string | null; + - readonly limitName?: string | null; + - readonly planType?: V2AccountRateLimitsUpdatedNotification__PlanType | null; + - readonly primary?: V2AccountRateLimitsUpdatedNotification__RateLimitWindow | null; + -- readonly rateLimitReachedType?: V2AccountRateLimitsUpdatedNotification__RateLimitReachedType | null; + - readonly secondary?: V2AccountRateLimitsUpdatedNotification__RateLimitWindow | null; + -- readonly spendControlReached?: boolean | null; + - }; + - export const V2AccountRateLimitsUpdatedNotification__RateLimitSnapshot = Schema.Struct({ + - credits: Schema.optionalKey( + - Schema.Union([V2AccountRateLimitsUpdatedNotification__CreditsSnapshot, Schema.Null]), + - ), + -- individualLimit: Schema.optionalKey( + -- Schema.Union([V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot, Schema.Null]), + -- ), + - limitId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - limitName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - planType: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2AccountRateLimitsUpdatedNotification__RateLimitSnapshot = Schema. + - primary: Schema.optionalKey( + - Schema.Union([V2AccountRateLimitsUpdatedNotification__RateLimitWindow, Schema.Null]), + - ), + -- rateLimitReachedType: Schema.optionalKey( + -- Schema.Union([V2AccountRateLimitsUpdatedNotification__RateLimitReachedType, Schema.Null]), + -- ), + - secondary: Schema.optionalKey( + - Schema.Union([V2AccountRateLimitsUpdatedNotification__RateLimitWindow, Schema.Null]), + - ), + -- spendControlReached: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Boolean.annotate({ + -- description: + -- "Backend-reported spend-control state. `None` is unavailable, not a sparse-update recovery.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - }); + - + - export type V2AppListUpdatedNotification__AppMetadata = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2AppsListResponse__AppMetadata = Schema.Struct({ + - versionNotes: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type V2AppsReadResponse__ConnectorMetadata = { + -- readonly description?: string | null; + -- readonly iconUrl?: string | null; + -- readonly id: string; + -- readonly name: string; + -- readonly toolSummaries?: ReadonlyArray | null; + --}; + --export const V2AppsReadResponse__ConnectorMetadata = Schema.Struct({ + -- description: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- iconUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- id: Schema.String, + -- name: Schema.String, + -- toolSummaries: Schema.optionalKey( + -- Schema.Union([Schema.Array(V2AppsReadResponse__AppToolSummary), Schema.Null]), + -- ), + --}).annotate({ description: "EXPERIMENTAL - metadata returned by app/read." }); + -- + - export type V2CommandExecParams__SandboxPolicy = + - | { readonly type: "dangerFullAccess" } + -- | { readonly networkAccess?: boolean; readonly type: "readOnly" } + -+ | { + -+ readonly access?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+ readonly networkAccess?: boolean; + -+ readonly type: "readOnly"; + -+ } + - | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + - | { + - readonly excludeSlashTmp?: boolean; + - readonly excludeTmpdirEnvVar?: boolean; + - readonly networkAccess?: boolean; + -+ readonly readOnlyAccess?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + - readonly type: "workspaceWrite"; + - readonly writableRoots?: ReadonlyArray; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2CommandExecParams__SandboxPolicy = Schema.Union( + - }), + - }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + - Schema.Struct({ + -+ access: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2CommandExecParams__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + - networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + - }).annotate({ title: "ReadOnlySandboxPolicy" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2CommandExecParams__SandboxPolicy = Schema.Union( + - excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ readOnlyAccess: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2CommandExecParams__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + - type: Schema.Literal("workspaceWrite").annotate({ title: "WorkspaceWriteSandboxPolicyType" }), + - writableRoots: Schema.optionalKey( + - Schema.Array(V2CommandExecParams__AbsolutePathBuf).annotate({ default: [] }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigBatchWriteParams__ConfigEdit = Schema.Struct({ + - export type V2ConfigReadResponse__ConfigLayerSource = + - | { readonly domain: string; readonly key: string; readonly type: "mdm" } + - | { readonly file: string; readonly type: "system" } + -- | { readonly id: string; readonly name: string; readonly type: "enterpriseManaged" } + -- | { readonly file: string; readonly profile?: string | null; readonly type: "user" } + -+ | { readonly file: string; readonly type: "user" } + - | { readonly dotCodexFolder: V2ConfigReadResponse__AbsolutePathBuf; readonly type: "project" } + - | { readonly type: "sessionFlags" } + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadResponse__ConfigLayerSource = Schema.Union( + - title: "SystemConfigLayerSource", + - description: "Managed config layer from a file (usually `managed_config.toml`).", + - }), + -- Schema.Struct({ + -- id: Schema.String.annotate({ description: "Stable identifier for the delivered layer." }), + -- name: Schema.String.annotate({ + -- description: + -- "Admin-facing name for the delivered layer. This is surfaced in diagnostics so users know which cloud layer needs administrator attention.", + -- }), + -- type: Schema.Literal("enterpriseManaged").annotate({ + -- title: "EnterpriseManagedConfigLayerSourceType", + -- }), + -- }).annotate({ + -- title: "EnterpriseManagedConfigLayerSource", + -- description: "Enterprise-managed config layer delivered by the cloud config bundle.", + -- }), + - Schema.Struct({ + - file: Schema.String.annotate({ + - description: + - "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + - }), + -- profile: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Name of the selected profile-v2 config layered on top of the base user config, when this layer represents one.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("user").annotate({ title: "UserConfigLayerSourceType" }), + - }).annotate({ + - title: "UserConfigLayerSource", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadResponse__ConfigLayerSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ConfigReadResponse__AppsDefaultConfig = { + -- readonly approvals_reviewer?: V2ConfigReadResponse__ApprovalsReviewer | null; + -- readonly default_tools_approval_mode?: V2ConfigReadResponse__AppToolApproval | null; + -- readonly destructive_enabled?: boolean; + -- readonly enabled?: boolean; + -- readonly open_world_enabled?: boolean; + --}; + --export const V2ConfigReadResponse__AppsDefaultConfig = Schema.Struct({ + -- approvals_reviewer: Schema.optionalKey( + -- Schema.Union([V2ConfigReadResponse__ApprovalsReviewer, Schema.Null]), + -- ), + -- default_tools_approval_mode: Schema.optionalKey( + -- Schema.Union([V2ConfigReadResponse__AppToolApproval, Schema.Null]), + -- ), + -- destructive_enabled: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + -- enabled: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + -- open_world_enabled: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + --}); + -- + - export type V2ConfigReadResponse__WebSearchToolConfig = { + - readonly allowed_domains?: ReadonlyArray | null; + - readonly context_size?: V2ConfigReadResponse__WebSearchContextSize | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadResponse__WebSearchToolConfig = Schema.Struct({ + - ), + - }); + - + --export type V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup = { + -- readonly hooks: ReadonlyArray; + -- readonly matcher?: string | null; + --}; + --export const V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup = Schema.Struct({ + -- hooks: Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookHandler), + -- matcher: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + --export type V2ConfigRequirementsReadResponse__NewThreadModelDefaults = { + -- readonly model?: string | null; + -- readonly modelReasoningEffort?: V2ConfigRequirementsReadResponse__ReasoningEffort | null; + -- readonly serviceTier?: string | null; + -+export type V2ConfigRequirementsReadResponse__ConfigRequirements = { + -+ readonly allowedApprovalPolicies?: ReadonlyArray | null; + -+ readonly allowedSandboxModes?: ReadonlyArray | null; + -+ readonly allowedWebSearchModes?: ReadonlyArray | null; + -+ readonly enforceResidency?: V2ConfigRequirementsReadResponse__ResidencyRequirement | null; + -+ readonly featureRequirements?: { readonly [x: string]: boolean } | null; + - }; + --export const V2ConfigRequirementsReadResponse__NewThreadModelDefaults = Schema.Struct({ + -- model: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- modelReasoningEffort: Schema.optionalKey( + -- Schema.Union([V2ConfigRequirementsReadResponse__ReasoningEffort, Schema.Null]), + -+export const V2ConfigRequirementsReadResponse__ConfigRequirements = Schema.Struct({ + -+ allowedApprovalPolicies: Schema.optionalKey( + -+ Schema.Union([Schema.Array(V2ConfigRequirementsReadResponse__AskForApproval), Schema.Null]), + -+ ), + -+ allowedSandboxModes: Schema.optionalKey( + -+ Schema.Union([Schema.Array(V2ConfigRequirementsReadResponse__SandboxMode), Schema.Null]), + -+ ), + -+ allowedWebSearchModes: Schema.optionalKey( + -+ Schema.Union([Schema.Array(V2ConfigRequirementsReadResponse__WebSearchMode), Schema.Null]), + -+ ), + -+ enforceResidency: Schema.optionalKey( + -+ Schema.Union([V2ConfigRequirementsReadResponse__ResidencyRequirement, Schema.Null]), + -+ ), + -+ featureRequirements: Schema.optionalKey( + -+ Schema.Union([Schema.Record(Schema.String, Schema.Boolean), Schema.Null]), + - ), + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + - export type V2ConfigWarningNotification__TextRange = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigWarningNotification__TextRange = Schema.Struct({ + - export type V2ConfigWriteResponse__ConfigLayerSource = + - | { readonly domain: string; readonly key: string; readonly type: "mdm" } + - | { readonly file: string; readonly type: "system" } + -- | { readonly id: string; readonly name: string; readonly type: "enterpriseManaged" } + -- | { readonly file: string; readonly profile?: string | null; readonly type: "user" } + -+ | { readonly file: string; readonly type: "user" } + - | { readonly dotCodexFolder: V2ConfigWriteResponse__AbsolutePathBuf; readonly type: "project" } + - | { readonly type: "sessionFlags" } + - | { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigWriteResponse__ConfigLayerSource = Schema.Union( + - title: "SystemConfigLayerSource", + - description: "Managed config layer from a file (usually `managed_config.toml`).", + - }), + -- Schema.Struct({ + -- id: Schema.String.annotate({ description: "Stable identifier for the delivered layer." }), + -- name: Schema.String.annotate({ + -- description: + -- "Admin-facing name for the delivered layer. This is surfaced in diagnostics so users know which cloud layer needs administrator attention.", + -- }), + -- type: Schema.Literal("enterpriseManaged").annotate({ + -- title: "EnterpriseManagedConfigLayerSourceType", + -- }), + -- }).annotate({ + -- title: "EnterpriseManagedConfigLayerSource", + -- description: "Enterprise-managed config layer delivered by the cloud config bundle.", + -- }), + - Schema.Struct({ + - file: Schema.String.annotate({ + - description: + - "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + - }), + -- profile: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Name of the selected profile-v2 config layered on top of the base user config, when this layer represents one.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("user").annotate({ title: "UserConfigLayerSourceType" }), + - }).annotate({ + - title: "UserConfigLayerSource", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigWriteResponse__ConfigLayerSource = Schema.Union( + - + - export type V2ErrorNotification__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ErrorNotification__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ErrorNotification__CodexErrorInfo = Schema.Union( + - "This translation layer make sure that we expose codex error code in camel case.\n\nWhen an upstream HTTP status is available (for example, from the Responses API or a provider), it is forwarded in `httpStatusCode` on the relevant `codexErrorInfo` variant.", + - }); + - + --export type V2ExternalAgentConfigDetectResponse__MigrationDetails = { + -- readonly commands?: ReadonlyArray; + -- readonly hooks?: ReadonlyArray; + -- readonly mcpServers?: ReadonlyArray; + -- readonly memory?: ReadonlyArray; + -- readonly plugins?: ReadonlyArray; + -- readonly sessions?: ReadonlyArray; + -- readonly skills?: ReadonlyArray; + -- readonly subagents?: ReadonlyArray; + --}; + --export const V2ExternalAgentConfigDetectResponse__MigrationDetails = Schema.Struct({ + -- commands: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigDetectResponse__CommandMigration).annotate({ default: [] }), + -- ), + -- hooks: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigDetectResponse__HookMigration).annotate({ default: [] }), + -- ), + -- mcpServers: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigDetectResponse__McpServerMigration).annotate({ default: [] }), + -- ), + -- memory: Schema.optionalKey(Schema.Array(Schema.String)), + -- plugins: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigDetectResponse__PluginsMigration).annotate({ default: [] }), + -- ), + -- sessions: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigDetectResponse__SessionMigration).annotate({ default: [] }), + -- ), + -- skills: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigDetectResponse__SkillMigration).annotate({ default: [] }), + -- ), + -- subagents: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigDetectResponse__SubagentMigration).annotate({ default: [] }), + -- ), + --}); + -- + --export type V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigImportItemTypeFailure = + -- { + -- readonly cwd?: string | null; + -- readonly errorType?: string | null; + -- readonly failureStage: string; + -- readonly itemType: V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigMigrationItemType; + -- readonly message: string; + -- readonly source?: string | null; + -- readonly subErrorType?: string | null; + -- }; + --export const V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigImportItemTypeFailure = + -- Schema.Struct({ + -- cwd: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- errorType: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- failureStage: Schema.String, + -- itemType: + -- V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigMigrationItemType, + -- message: Schema.String, + -- source: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- subErrorType: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- }); + -- + --export type V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigImportItemTypeSuccess = + -- { + -- readonly cwd?: string | null; + -- readonly itemType: V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigMigrationItemType; + -- readonly source?: string | null; + -- readonly target?: string | null; + -- }; + --export const V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigImportItemTypeSuccess = + -- Schema.Struct({ + -- cwd: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- itemType: + -- V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigMigrationItemType, + -- source: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- target: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- }); + -- + --export type V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigImportItemTypeFailure = + -- { + -- readonly cwd?: string | null; + -- readonly errorType?: string | null; + -- readonly failureStage: string; + -- readonly itemType: V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigMigrationItemType; + -- readonly message: string; + -- readonly source?: string | null; + -- readonly subErrorType?: string | null; + -- }; + --export const V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigImportItemTypeFailure = + -- Schema.Struct({ + -- cwd: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- errorType: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- failureStage: Schema.String, + -- itemType: + -- V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigMigrationItemType, + -- message: Schema.String, + -- source: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- subErrorType: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- }); + -- + --export type V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigImportItemTypeSuccess = + -- { + -- readonly cwd?: string | null; + -- readonly itemType: V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigMigrationItemType; + -- readonly source?: string | null; + -- readonly target?: string | null; + -- }; + --export const V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigImportItemTypeSuccess = + -- Schema.Struct({ + -- cwd: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- itemType: + -- V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigMigrationItemType, + -- source: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- target: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- }); + -- + --export type V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentImportedConnectorCandidate = + -- { + -- readonly name: string; + -- readonly sessionCount: number; + -- readonly source: V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentImportedConnectorSource; + -- }; + --export const V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentImportedConnectorCandidate = + -- Schema.Struct({ + -- name: Schema.String, + -- sessionCount: Schema.Number.annotate({ format: "uint32" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- source: V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentImportedConnectorSource, + -- }); + -- + --export type V2ExternalAgentConfigImportParams__MigrationDetails = { + -- readonly commands?: ReadonlyArray; + -- readonly hooks?: ReadonlyArray; + -- readonly mcpServers?: ReadonlyArray; + -- readonly memory?: ReadonlyArray; + -- readonly plugins?: ReadonlyArray; + -- readonly sessions?: ReadonlyArray; + -- readonly skills?: ReadonlyArray; + -- readonly subagents?: ReadonlyArray; + --}; + --export const V2ExternalAgentConfigImportParams__MigrationDetails = Schema.Struct({ + -- commands: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigImportParams__CommandMigration).annotate({ default: [] }), + -- ), + -- hooks: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigImportParams__HookMigration).annotate({ default: [] }), + -- ), + -- mcpServers: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigImportParams__McpServerMigration).annotate({ default: [] }), + -- ), + -- memory: Schema.optionalKey(Schema.Array(Schema.String)), + -- plugins: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigImportParams__PluginsMigration).annotate({ default: [] }), + -- ), + -- sessions: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigImportParams__SessionMigration).annotate({ default: [] }), + -- ), + -- skills: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigImportParams__SkillMigration).annotate({ default: [] }), + -- ), + -- subagents: Schema.optionalKey( + -- Schema.Array(V2ExternalAgentConfigImportParams__SubagentMigration).annotate({ default: [] }), + -- ), + --}); + -- + --export type V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigImportItemTypeFailure = + -- { + -- readonly cwd?: string | null; + -- readonly errorType?: string | null; + -- readonly failureStage: string; + -- readonly itemType: V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigMigrationItemType; + -- readonly message: string; + -- readonly source?: string | null; + -- readonly subErrorType?: string | null; + -- }; + --export const V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigImportItemTypeFailure = + -- Schema.Struct({ + -- cwd: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- errorType: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- failureStage: Schema.String, + -- itemType: V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigMigrationItemType, + -- message: Schema.String, + -- source: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- subErrorType: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- }); + -- + --export type V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigImportItemTypeSuccess = + -- { + -- readonly cwd?: string | null; + -- readonly itemType: V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigMigrationItemType; + -- readonly source?: string | null; + -- readonly target?: string | null; + -- }; + --export const V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigImportItemTypeSuccess = + -- Schema.Struct({ + -- cwd: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- itemType: V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigMigrationItemType, + -- source: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- target: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- }); + -- + --export type V2FileChangePatchUpdatedNotification__FileUpdateChange = { + -- readonly diff: string; + -- readonly kind: V2FileChangePatchUpdatedNotification__PatchChangeKind; + -- readonly path: string; + --}; + --export const V2FileChangePatchUpdatedNotification__FileUpdateChange = Schema.Struct({ + -- diff: Schema.String, + -- kind: V2FileChangePatchUpdatedNotification__PatchChangeKind, + -- path: Schema.String, + --}); + -- + --export type V2GetAccountRateLimitsResponse__RateLimitResetCredit = { + -- readonly description?: string | null; + -- readonly expiresAt?: number | null; + -- readonly grantedAt: number; + -- readonly id: string; + -- readonly resetType: V2GetAccountRateLimitsResponse__RateLimitResetType; + -- readonly status: V2GetAccountRateLimitsResponse__RateLimitResetCreditStatus; + -- readonly title?: string | null; + -+export type V2ExternalAgentConfigDetectResponse__ExternalAgentConfigMigrationItem = { + -+ readonly cwd?: string | null; + -+ readonly description: string; + -+ readonly itemType: V2ExternalAgentConfigDetectResponse__ExternalAgentConfigMigrationItemType; + - }; + --export const V2GetAccountRateLimitsResponse__RateLimitResetCredit = Schema.Struct({ + -- description: Schema.optionalKey( + -+export const V2ExternalAgentConfigDetectResponse__ExternalAgentConfigMigrationItem = Schema.Struct({ + -+ cwd: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ + - description: + -- "Backend-provided display description for this credit, or `null` when unavailable.", + -+ "Null or empty means home-scoped migration; non-empty means repo-scoped migration.", + - }), + - Schema.Null, + - ]), + - ), + -- expiresAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp in seconds when the credit expires, or `null` if it does not expire.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- grantedAt: Schema.Number.annotate({ + -- description: "Unix timestamp in seconds when the credit was granted.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- id: Schema.String.annotate({ description: "Opaque backend identifier for this reset credit." }), + -- resetType: V2GetAccountRateLimitsResponse__RateLimitResetType, + -- status: V2GetAccountRateLimitsResponse__RateLimitResetCreditStatus, + -- title: Schema.optionalKey( + -+ description: Schema.String, + -+ itemType: V2ExternalAgentConfigDetectResponse__ExternalAgentConfigMigrationItemType, + -+}); + -+ + -+export type V2ExternalAgentConfigImportParams__ExternalAgentConfigMigrationItem = { + -+ readonly cwd?: string | null; + -+ readonly description: string; + -+ readonly itemType: V2ExternalAgentConfigImportParams__ExternalAgentConfigMigrationItemType; + -+}; + -+export const V2ExternalAgentConfigImportParams__ExternalAgentConfigMigrationItem = Schema.Struct({ + -+ cwd: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ + -- description: "Backend-provided display title for this credit, or `null` when unavailable.", + -+ description: + -+ "Null or empty means home-scoped migration; non-empty means repo-scoped migration.", + - }), + - Schema.Null, + - ]), + - ), + -+ description: Schema.String, + -+ itemType: V2ExternalAgentConfigImportParams__ExternalAgentConfigMigrationItemType, + - }); + - + - export type V2GetAccountRateLimitsResponse__RateLimitSnapshot = { + - readonly credits?: V2GetAccountRateLimitsResponse__CreditsSnapshot | null; + -- readonly individualLimit?: V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot | null; + - readonly limitId?: string | null; + - readonly limitName?: string | null; + - readonly planType?: V2GetAccountRateLimitsResponse__PlanType | null; + - readonly primary?: V2GetAccountRateLimitsResponse__RateLimitWindow | null; + -- readonly rateLimitReachedType?: V2GetAccountRateLimitsResponse__RateLimitReachedType | null; + - readonly secondary?: V2GetAccountRateLimitsResponse__RateLimitWindow | null; + -- readonly spendControlReached?: boolean | null; + - }; + - export const V2GetAccountRateLimitsResponse__RateLimitSnapshot = Schema.Struct({ + - credits: Schema.optionalKey( + - Schema.Union([V2GetAccountRateLimitsResponse__CreditsSnapshot, Schema.Null]), + - ), + -- individualLimit: Schema.optionalKey( + -- Schema.Union([V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot, Schema.Null]), + -- ), + - limitId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - limitName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - planType: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2GetAccountRateLimitsResponse__RateLimitSnapshot = Schema.Struct({ + - primary: Schema.optionalKey( + - Schema.Union([V2GetAccountRateLimitsResponse__RateLimitWindow, Schema.Null]), + - ), + -- rateLimitReachedType: Schema.optionalKey( + -- Schema.Union([V2GetAccountRateLimitsResponse__RateLimitReachedType, Schema.Null]), + -- ), + - secondary: Schema.optionalKey( + - Schema.Union([V2GetAccountRateLimitsResponse__RateLimitWindow, Schema.Null]), + - ), + -- spendControlReached: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Boolean.annotate({ + -- description: + -- "Backend-reported spend-control state. `None` is unavailable, not a sparse-update recovery.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - }); + - + - export type V2GetAccountResponse__Account = + - | { readonly type: "apiKey" } + - | { + -- readonly email: string | null; + -+ readonly email: string; + - readonly planType: V2GetAccountResponse__PlanType; + - readonly type: "chatgpt"; + -- } + -- | { readonly type: "amazonBedrock"; readonly usesCodexManagedCredentials?: boolean }; + -+ }; + - export const V2GetAccountResponse__Account = Schema.Union( + - [ + - Schema.Struct({ + - type: Schema.Literal("apiKey").annotate({ title: "ApiKeyAccountType" }), + - }).annotate({ title: "ApiKeyAccount" }), + - Schema.Struct({ + -- email: Schema.Union([Schema.String, Schema.Null]), + -+ email: Schema.String, + - planType: V2GetAccountResponse__PlanType, + - type: Schema.Literal("chatgpt").annotate({ title: "ChatgptAccountType" }), + - }).annotate({ title: "ChatgptAccount" }), + -- Schema.Struct({ + -- type: Schema.Literal("amazonBedrock").annotate({ title: "AmazonBedrockAccountType" }), + -- usesCodexManagedCredentials: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- }).annotate({ title: "AmazonBedrockAccount" }), + - ], + - { mode: "oneOf" }, + - ); + - + --export type V2GetWorkspaceMessagesResponse__WorkspaceMessage = { + -- readonly archivedAt?: number | null; + -- readonly createdAt?: number | null; + -- readonly messageBody: string; + -- readonly messageId: string; + -- readonly messageType: V2GetWorkspaceMessagesResponse__WorkspaceMessageType; + --}; + --export const V2GetWorkspaceMessagesResponse__WorkspaceMessage = Schema.Struct({ + -- archivedAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) when the message was archived.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- createdAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) when the message was created.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- messageBody: Schema.String, + -- messageId: Schema.String, + -- messageType: V2GetWorkspaceMessagesResponse__WorkspaceMessageType, + --}); + -- + - export type V2HookCompletedNotification__HookOutputEntry = { + - readonly kind: V2HookCompletedNotification__HookOutputEntryKind; + - readonly text: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2HookCompletedNotification__HookOutputEntry = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2HooksListResponse__HookMetadata = { + -- readonly command?: string | null; + -- readonly currentHash: string; + -- readonly displayOrder: number; + -- readonly enabled: boolean; + -- readonly eventName: V2HooksListResponse__HookEventName; + -- readonly handlerType: V2HooksListResponse__HookHandlerType; + -- readonly isManaged: boolean; + -- readonly key: string; + -- readonly matcher?: string | null; + -- readonly pluginId?: string | null; + -- readonly source: V2HooksListResponse__HookSource; + -- readonly sourcePath: V2HooksListResponse__AbsolutePathBuf; + -- readonly statusMessage?: string | null; + -- readonly timeoutSec: number; + -- readonly trustStatus: V2HooksListResponse__HookTrustStatus; + --}; + --export const V2HooksListResponse__HookMetadata = Schema.Struct({ + -- command: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- currentHash: Schema.String, + -- displayOrder: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- enabled: Schema.Boolean, + -- eventName: V2HooksListResponse__HookEventName, + -- handlerType: V2HooksListResponse__HookHandlerType, + -- isManaged: Schema.Boolean, + -- key: Schema.String, + -- matcher: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- source: V2HooksListResponse__HookSource, + -- sourcePath: V2HooksListResponse__AbsolutePathBuf, + -- statusMessage: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- timeoutSec: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- trustStatus: V2HooksListResponse__HookTrustStatus, + --}); + -- + - export type V2HookStartedNotification__HookOutputEntry = { + - readonly kind: V2HookStartedNotification__HookOutputEntryKind; + - readonly text: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2HookStartedNotification__HookOutputEntry = Schema.Struct({ + - text: Schema.String, + - }); + - + --export type V2ItemCompletedNotification__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ItemCompletedNotification__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ItemCompletedNotification__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ItemCompletedNotification__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2ItemCompletedNotification__CollabAgentState = { + - readonly message?: string | null; + - readonly status: V2ItemCompletedNotification__CollabAgentStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemCompletedNotification__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ItemCompletedNotification__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ItemCompletedNotification__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ItemCompletedNotification__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ItemCompletedNotification__ImageDetail, Schema.Null]), + -- ), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ItemCompletedNotification__ImageDetail, Schema.Null]), + -- ), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemGuardianApprovalReviewCompletedNotification__GuardianApproval + - ), + - }).annotate({ + - description: + -- "[UNSTABLE] Temporary approval auto-review payload used by `item/autoApprovalReview/*` notifications. This shape is expected to change soon.", + -+ "[UNSTABLE] Temporary guardian approval review payload used by `item/autoApprovalReview/*` notifications. This shape is expected to change soon.", + - }); + - + --export type V2ItemGuardianApprovalReviewCompletedNotification__FileSystemSpecialPath = + -- | { readonly kind: "root" } + -- | { readonly kind: "minimal" } + -+export type V2ItemGuardianApprovalReviewCompletedNotification__GuardianApprovalReviewAction = + -+ | { + -+ readonly command: string; + -+ readonly cwd: string; + -+ readonly source: V2ItemGuardianApprovalReviewCompletedNotification__GuardianCommandSource; + -+ readonly type: "command"; + -+ } + - | { + -- readonly kind: "project_roots"; + -- readonly subpath?: V2ItemGuardianApprovalReviewCompletedNotification__LegacyAppPathString | null; + -+ readonly argv: ReadonlyArray; + -+ readonly cwd: string; + -+ readonly program: string; + -+ readonly source: V2ItemGuardianApprovalReviewCompletedNotification__GuardianCommandSource; + -+ readonly type: "execve"; + - } + -- | { readonly kind: "tmpdir" } + -- | { readonly kind: "slash_tmp" } + -+ | { readonly cwd: string; readonly files: ReadonlyArray; readonly type: "applyPatch" } + - | { + -- readonly kind: "unknown"; + -- readonly path: string; + -- readonly subpath?: V2ItemGuardianApprovalReviewCompletedNotification__LegacyAppPathString | null; + -+ readonly host: string; + -+ readonly port: number; + -+ readonly protocol: V2ItemGuardianApprovalReviewCompletedNotification__NetworkApprovalProtocol; + -+ readonly target: string; + -+ readonly type: "networkAccess"; + -+ } + -+ | { + -+ readonly connectorId?: string | null; + -+ readonly connectorName?: string | null; + -+ readonly server: string; + -+ readonly toolName: string; + -+ readonly toolTitle?: string | null; + -+ readonly type: "mcpToolCall"; + - }; + --export const V2ItemGuardianApprovalReviewCompletedNotification__FileSystemSpecialPath = + -+export const V2ItemGuardianApprovalReviewCompletedNotification__GuardianApprovalReviewAction = + - Schema.Union( + - [ + -- Schema.Struct({ kind: Schema.Literal("root") }).annotate({ + -- title: "RootFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("minimal") }).annotate({ + -- title: "MinimalFileSystemSpecialPath", + -- }), + - Schema.Struct({ + -- kind: Schema.Literal("project_roots"), + -- subpath: Schema.optionalKey( + -- Schema.Union([ + -- V2ItemGuardianApprovalReviewCompletedNotification__LegacyAppPathString, + -- Schema.Null, + -- ]), + -- ), + -- }).annotate({ title: "KindFileSystemSpecialPath" }), + -- Schema.Struct({ kind: Schema.Literal("tmpdir") }).annotate({ + -- title: "TmpdirFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("slash_tmp") }).annotate({ + -- title: "SlashTmpFileSystemSpecialPath", + -- }), + -+ command: Schema.String, + -+ cwd: Schema.String, + -+ source: V2ItemGuardianApprovalReviewCompletedNotification__GuardianCommandSource, + -+ type: Schema.Literal("command").annotate({ + -+ title: "CommandGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "CommandGuardianApprovalReviewAction" }), + - Schema.Struct({ + -- kind: Schema.Literal("unknown"), + -- path: Schema.String, + -- subpath: Schema.optionalKey( + -- Schema.Union([ + -- V2ItemGuardianApprovalReviewCompletedNotification__LegacyAppPathString, + -- Schema.Null, + -- ]), + -- ), + -- }), + -+ argv: Schema.Array(Schema.String), + -+ cwd: Schema.String, + -+ program: Schema.String, + -+ source: V2ItemGuardianApprovalReviewCompletedNotification__GuardianCommandSource, + -+ type: Schema.Literal("execve").annotate({ + -+ title: "ExecveGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "ExecveGuardianApprovalReviewAction" }), + -+ Schema.Struct({ + -+ cwd: Schema.String, + -+ files: Schema.Array(Schema.String), + -+ type: Schema.Literal("applyPatch").annotate({ + -+ title: "ApplyPatchGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "ApplyPatchGuardianApprovalReviewAction" }), + -+ Schema.Struct({ + -+ host: Schema.String, + -+ port: Schema.Number.annotate({ format: "uint16" }) + -+ .check(Schema.isInt()) + -+ .check(Schema.isGreaterThanOrEqualTo(0)), + -+ protocol: V2ItemGuardianApprovalReviewCompletedNotification__NetworkApprovalProtocol, + -+ target: Schema.String, + -+ type: Schema.Literal("networkAccess").annotate({ + -+ title: "NetworkAccessGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "NetworkAccessGuardianApprovalReviewAction" }), + -+ Schema.Struct({ + -+ connectorId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ connectorName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ server: Schema.String, + -+ toolName: Schema.String, + -+ toolTitle: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("mcpToolCall").annotate({ + -+ title: "McpToolCallGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "McpToolCallGuardianApprovalReviewAction" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalRe + - ), + - }).annotate({ + - description: + -- "[UNSTABLE] Temporary approval auto-review payload used by `item/autoApprovalReview/*` notifications. This shape is expected to change soon.", + -+ "[UNSTABLE] Temporary guardian approval review payload used by `item/autoApprovalReview/*` notifications. This shape is expected to change soon.", + - }); + - + --export type V2ItemGuardianApprovalReviewStartedNotification__FileSystemSpecialPath = + -- | { readonly kind: "root" } + -- | { readonly kind: "minimal" } + -+export type V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalReviewAction = + - | { + -- readonly kind: "project_roots"; + -- readonly subpath?: V2ItemGuardianApprovalReviewStartedNotification__LegacyAppPathString | null; + -+ readonly command: string; + -+ readonly cwd: string; + -+ readonly source: V2ItemGuardianApprovalReviewStartedNotification__GuardianCommandSource; + -+ readonly type: "command"; + - } + -- | { readonly kind: "tmpdir" } + -- | { readonly kind: "slash_tmp" } + -- | { + -- readonly kind: "unknown"; + -- readonly path: string; + -- readonly subpath?: V2ItemGuardianApprovalReviewStartedNotification__LegacyAppPathString | null; + -- }; + --export const V2ItemGuardianApprovalReviewStartedNotification__FileSystemSpecialPath = Schema.Union( + -- [ + -- Schema.Struct({ kind: Schema.Literal("root") }).annotate({ + -- title: "RootFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("minimal") }).annotate({ + -- title: "MinimalFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("project_roots"), + -- subpath: Schema.optionalKey( + -- Schema.Union([ + -- V2ItemGuardianApprovalReviewStartedNotification__LegacyAppPathString, + -- Schema.Null, + -- ]), + -- ), + -- }).annotate({ title: "KindFileSystemSpecialPath" }), + -- Schema.Struct({ kind: Schema.Literal("tmpdir") }).annotate({ + -- title: "TmpdirFileSystemSpecialPath", + -- }), + -- Schema.Struct({ kind: Schema.Literal("slash_tmp") }).annotate({ + -- title: "SlashTmpFileSystemSpecialPath", + -- }), + -- Schema.Struct({ + -- kind: Schema.Literal("unknown"), + -- path: Schema.String, + -- subpath: Schema.optionalKey( + -- Schema.Union([ + -- V2ItemGuardianApprovalReviewStartedNotification__LegacyAppPathString, + -- Schema.Null, + -- ]), + -- ), + -- }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type V2ItemStartedNotification__CommandAction = + - | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ItemStartedNotification__AbsolutePathBuf; + -- readonly type: "read"; + -+ readonly argv: ReadonlyArray; + -+ readonly cwd: string; + -+ readonly program: string; + -+ readonly source: V2ItemGuardianApprovalReviewStartedNotification__GuardianCommandSource; + -+ readonly type: "execve"; + - } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { readonly cwd: string; readonly files: ReadonlyArray; readonly type: "applyPatch" } + - | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -+ readonly host: string; + -+ readonly port: number; + -+ readonly protocol: V2ItemGuardianApprovalReviewStartedNotification__NetworkApprovalProtocol; + -+ readonly target: string; + -+ readonly type: "networkAccess"; + - } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ItemStartedNotification__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ItemStartedNotification__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -+ | { + -+ readonly connectorId?: string | null; + -+ readonly connectorName?: string | null; + -+ readonly server: string; + -+ readonly toolName: string; + -+ readonly toolTitle?: string | null; + -+ readonly type: "mcpToolCall"; + -+ }; + -+export const V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalReviewAction = + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ command: Schema.String, + -+ cwd: Schema.String, + -+ source: V2ItemGuardianApprovalReviewStartedNotification__GuardianCommandSource, + -+ type: Schema.Literal("command").annotate({ + -+ title: "CommandGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "CommandGuardianApprovalReviewAction" }), + -+ Schema.Struct({ + -+ argv: Schema.Array(Schema.String), + -+ cwd: Schema.String, + -+ program: Schema.String, + -+ source: V2ItemGuardianApprovalReviewStartedNotification__GuardianCommandSource, + -+ type: Schema.Literal("execve").annotate({ + -+ title: "ExecveGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "ExecveGuardianApprovalReviewAction" }), + -+ Schema.Struct({ + -+ cwd: Schema.String, + -+ files: Schema.Array(Schema.String), + -+ type: Schema.Literal("applyPatch").annotate({ + -+ title: "ApplyPatchGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "ApplyPatchGuardianApprovalReviewAction" }), + -+ Schema.Struct({ + -+ host: Schema.String, + -+ port: Schema.Number.annotate({ format: "uint16" }) + -+ .check(Schema.isInt()) + -+ .check(Schema.isGreaterThanOrEqualTo(0)), + -+ protocol: V2ItemGuardianApprovalReviewStartedNotification__NetworkApprovalProtocol, + -+ target: Schema.String, + -+ type: Schema.Literal("networkAccess").annotate({ + -+ title: "NetworkAccessGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "NetworkAccessGuardianApprovalReviewAction" }), + -+ Schema.Struct({ + -+ connectorId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ connectorName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ server: Schema.String, + -+ toolName: Schema.String, + -+ toolTitle: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ type: Schema.Literal("mcpToolCall").annotate({ + -+ title: "McpToolCallGuardianApprovalReviewActionType", + -+ }), + -+ }).annotate({ title: "McpToolCallGuardianApprovalReviewAction" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ); + - + - export type V2ItemStartedNotification__CollabAgentState = { + - readonly message?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemStartedNotification__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ItemStartedNotification__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ItemStartedNotification__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ItemStartedNotification__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemStartedNotification__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ItemStartedNotification__ImageDetail, Schema.Null]), + -- ), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ItemStartedNotification__ImageDetail, Schema.Null]), + -- ), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ListMcpServerStatusResponse__McpServerStatus = { + - readonly name: string; + - readonly resourceTemplates: ReadonlyArray; + - readonly resources: ReadonlyArray; + -- readonly serverInfo?: V2ListMcpServerStatusResponse__McpServerInfo | null; + - readonly tools: { readonly [x: string]: V2ListMcpServerStatusResponse__Tool }; + - }; + - export const V2ListMcpServerStatusResponse__McpServerStatus = Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ListMcpServerStatusResponse__McpServerStatus = Schema.Struct({ + - name: Schema.String, + - resourceTemplates: Schema.Array(V2ListMcpServerStatusResponse__ResourceTemplate), + - resources: Schema.Array(V2ListMcpServerStatusResponse__Resource), + -- serverInfo: Schema.optionalKey( + -- Schema.Union([V2ListMcpServerStatusResponse__McpServerInfo, Schema.Null]), + -- ), + - tools: Schema.Record(Schema.String, V2ListMcpServerStatusResponse__Tool), + - }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ModelListResponse__ReasoningEffortOption = Schema.Struct({ + - reasoningEffort: V2ModelListResponse__ReasoningEffort, + - }); + - + --export type V2PluginInstalledResponse__MarketplaceLoadErrorInfo = { + -- readonly marketplacePath: V2PluginInstalledResponse__AbsolutePathBuf; + -- readonly message: string; + --}; + --export const V2PluginInstalledResponse__MarketplaceLoadErrorInfo = Schema.Struct({ + -- marketplacePath: V2PluginInstalledResponse__AbsolutePathBuf, + -- message: Schema.String, + --}); + -- + --export type V2PluginInstalledResponse__PluginInterface = { + -- readonly brandColor?: string | null; + -- readonly capabilities: ReadonlyArray; + -- readonly category?: string | null; + -- readonly composerIcon?: V2PluginInstalledResponse__AbsolutePathBuf | null; + -- readonly composerIconUrl?: string | null; + -- readonly defaultPrompt?: ReadonlyArray | null; + -- readonly developerName?: string | null; + -- readonly displayName?: string | null; + -- readonly logo?: V2PluginInstalledResponse__AbsolutePathBuf | null; + -- readonly logoDark?: V2PluginInstalledResponse__AbsolutePathBuf | null; + -- readonly logoUrl?: string | null; + -- readonly logoUrlDark?: string | null; + -- readonly longDescription?: string | null; + -- readonly privacyPolicyUrl?: string | null; + -- readonly screenshotUrls: ReadonlyArray; + -- readonly screenshots: ReadonlyArray; + -- readonly shortDescription?: string | null; + -- readonly termsOfServiceUrl?: string | null; + -- readonly websiteUrl?: string | null; + --}; + --export const V2PluginInstalledResponse__PluginInterface = Schema.Struct({ + -- brandColor: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- capabilities: Schema.Array(Schema.String), + -- category: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- composerIcon: Schema.optionalKey( + -- Schema.Union([V2PluginInstalledResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local composer icon path, resolved from the installed plugin package.", + -- }), + -- ), + -- composerIconUrl: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote composer icon URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -- ), + -- defaultPrompt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.String).annotate({ + -- description: + -- "Starter prompts for the plugin. Capped at 3 entries with a maximum of 128 characters per entry.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- developerName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- displayName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- logo: Schema.optionalKey( + -- Schema.Union([V2PluginInstalledResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local logo path, resolved from the installed plugin package.", + -- }), + -- ), + -- logoDark: Schema.optionalKey( + -- Schema.Union([V2PluginInstalledResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local dark-mode logo path, resolved from the installed plugin package.", + -- }), + -- ), + -- logoUrl: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote logo URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -- ), + -- logoUrlDark: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote dark-mode logo URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -- ), + -- longDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- privacyPolicyUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- screenshotUrls: Schema.Array(Schema.String).annotate({ + -- description: "Remote screenshot URLs from the plugin catalog.", + -- }), + -- screenshots: Schema.Array(V2PluginInstalledResponse__AbsolutePathBuf).annotate({ + -- description: "Local screenshot paths, resolved from the installed plugin package.", + -- }), + -- shortDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- termsOfServiceUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- websiteUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + --export type V2PluginInstalledResponse__PluginSource = + -- | { readonly path: V2PluginInstalledResponse__AbsolutePathBuf; readonly type: "local" } + -- | { + -- readonly path?: string | null; + -- readonly refName?: string | null; + -- readonly sha?: string | null; + -- readonly type: "git"; + -- readonly url: string; + -- } + -- | { + -- readonly package: string; + -- readonly registry?: string | null; + -- readonly type: "npm"; + -- readonly version?: string | null; + -- } + -- | { readonly type: "remote" }; + --export const V2PluginInstalledResponse__PluginSource = Schema.Union( + -- [ + -- Schema.Struct({ + -- path: V2PluginInstalledResponse__AbsolutePathBuf, + -- type: Schema.Literal("local").annotate({ title: "LocalPluginSourceType" }), + -- }).annotate({ title: "LocalPluginSource" }), + -- Schema.Struct({ + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- refName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- sha: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("git").annotate({ title: "GitPluginSourceType" }), + -- url: Schema.String, + -- }).annotate({ title: "GitPluginSource" }), + -- Schema.Struct({ + -- package: Schema.String, + -- registry: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional HTTPS registry URL. Authentication stays in the user's npm config.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- type: Schema.Literal("npm").annotate({ title: "NpmPluginSourceType" }), + -- version: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Optional npm version or version range." }), + -- Schema.Null, + -- ]), + -- ), + -- }).annotate({ title: "NpmPluginSource" }), + -- Schema.Struct({ + -- type: Schema.Literal("remote").annotate({ title: "RemotePluginSourceType" }), + -- }).annotate({ + -- title: "RemotePluginSource", + -- description: + -- "The plugin is available in the remote catalog. Download metadata is kept server-side and is not exposed through the app-server API.", + -- }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type V2PluginInstalledResponse__PluginSharePrincipal = { + -- readonly name: string; + -- readonly principalId: string; + -- readonly principalType: V2PluginInstalledResponse__PluginSharePrincipalType; + -- readonly role: V2PluginInstalledResponse__PluginSharePrincipalRole; + --}; + --export const V2PluginInstalledResponse__PluginSharePrincipal = Schema.Struct({ + -- name: Schema.String, + -- principalId: Schema.String, + -- principalType: V2PluginInstalledResponse__PluginSharePrincipalType, + -- role: V2PluginInstalledResponse__PluginSharePrincipalRole, + --}); + -- + - export type V2PluginListResponse__MarketplaceLoadErrorInfo = { + - readonly marketplacePath: V2PluginListResponse__AbsolutePathBuf; + - readonly message: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2PluginListResponse__PluginInterface = { + - readonly capabilities: ReadonlyArray; + - readonly category?: string | null; + - readonly composerIcon?: V2PluginListResponse__AbsolutePathBuf | null; + -- readonly composerIconUrl?: string | null; + - readonly defaultPrompt?: ReadonlyArray | null; + - readonly developerName?: string | null; + - readonly displayName?: string | null; + - readonly logo?: V2PluginListResponse__AbsolutePathBuf | null; + -- readonly logoDark?: V2PluginListResponse__AbsolutePathBuf | null; + -- readonly logoUrl?: string | null; + -- readonly logoUrlDark?: string | null; + - readonly longDescription?: string | null; + - readonly privacyPolicyUrl?: string | null; + -- readonly screenshotUrls: ReadonlyArray; + - readonly screenshots: ReadonlyArray; + - readonly shortDescription?: string | null; + - readonly termsOfServiceUrl?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginListResponse__PluginInterface = Schema.Struct({ + - capabilities: Schema.Array(Schema.String), + - category: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - composerIcon: Schema.optionalKey( + -- Schema.Union([V2PluginListResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local composer icon path, resolved from the installed plugin package.", + -- }), + -- ), + -- composerIconUrl: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote composer icon URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -+ Schema.Union([V2PluginListResponse__AbsolutePathBuf, Schema.Null]), + - ), + - defaultPrompt: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginListResponse__PluginInterface = Schema.Struct({ + - ), + - developerName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - displayName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- logo: Schema.optionalKey( + -- Schema.Union([V2PluginListResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local logo path, resolved from the installed plugin package.", + -- }), + -- ), + -- logoDark: Schema.optionalKey( + -- Schema.Union([V2PluginListResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local dark-mode logo path, resolved from the installed plugin package.", + -- }), + -- ), + -- logoUrl: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote logo URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -- ), + -- logoUrlDark: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote dark-mode logo URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -- ), + -+ logo: Schema.optionalKey(Schema.Union([V2PluginListResponse__AbsolutePathBuf, Schema.Null])), + - longDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - privacyPolicyUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- screenshotUrls: Schema.Array(Schema.String).annotate({ + -- description: "Remote screenshot URLs from the plugin catalog.", + -- }), + -- screenshots: Schema.Array(V2PluginListResponse__AbsolutePathBuf).annotate({ + -- description: "Local screenshot paths, resolved from the installed plugin package.", + -- }), + -+ screenshots: Schema.Array(V2PluginListResponse__AbsolutePathBuf), + - shortDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - termsOfServiceUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - websiteUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type V2PluginListResponse__PluginSource = + -- | { readonly path: V2PluginListResponse__AbsolutePathBuf; readonly type: "local" } + -- | { + -- readonly path?: string | null; + -- readonly refName?: string | null; + -- readonly sha?: string | null; + -- readonly type: "git"; + -- readonly url: string; + -- } + -- | { + -- readonly package: string; + -- readonly registry?: string | null; + -- readonly type: "npm"; + -- readonly version?: string | null; + -- } + -- | { readonly type: "remote" }; + -+export type V2PluginListResponse__PluginSource = { + -+ readonly path: V2PluginListResponse__AbsolutePathBuf; + -+ readonly type: "local"; + -+}; + - export const V2PluginListResponse__PluginSource = Schema.Union( + - [ + - Schema.Struct({ + - path: V2PluginListResponse__AbsolutePathBuf, + - type: Schema.Literal("local").annotate({ title: "LocalPluginSourceType" }), + - }).annotate({ title: "LocalPluginSource" }), + -- Schema.Struct({ + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- refName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- sha: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("git").annotate({ title: "GitPluginSourceType" }), + -- url: Schema.String, + -- }).annotate({ title: "GitPluginSource" }), + -- Schema.Struct({ + -- package: Schema.String, + -- registry: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional HTTPS registry URL. Authentication stays in the user's npm config.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- type: Schema.Literal("npm").annotate({ title: "NpmPluginSourceType" }), + -- version: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Optional npm version or version range." }), + -- Schema.Null, + -- ]), + -- ), + -- }).annotate({ title: "NpmPluginSource" }), + -- Schema.Struct({ + -- type: Schema.Literal("remote").annotate({ title: "RemotePluginSourceType" }), + -- }).annotate({ + -- title: "RemotePluginSource", + -- description: + -- "The plugin is available in the remote catalog. Download metadata is kept server-side and is not exposed through the app-server API.", + -- }), + - ], + - { mode: "oneOf" }, + - ); + - + --export type V2PluginListResponse__PluginSharePrincipal = { + -- readonly name: string; + -- readonly principalId: string; + -- readonly principalType: V2PluginListResponse__PluginSharePrincipalType; + -- readonly role: V2PluginListResponse__PluginSharePrincipalRole; + --}; + --export const V2PluginListResponse__PluginSharePrincipal = Schema.Struct({ + -- name: Schema.String, + -- principalId: Schema.String, + -- principalType: V2PluginListResponse__PluginSharePrincipalType, + -- role: V2PluginListResponse__PluginSharePrincipalRole, + --}); + -- + - export type V2PluginReadResponse__PluginInterface = { + - readonly brandColor?: string | null; + - readonly capabilities: ReadonlyArray; + - readonly category?: string | null; + - readonly composerIcon?: V2PluginReadResponse__AbsolutePathBuf | null; + -- readonly composerIconUrl?: string | null; + - readonly defaultPrompt?: ReadonlyArray | null; + - readonly developerName?: string | null; + - readonly displayName?: string | null; + - readonly logo?: V2PluginReadResponse__AbsolutePathBuf | null; + -- readonly logoDark?: V2PluginReadResponse__AbsolutePathBuf | null; + -- readonly logoUrl?: string | null; + -- readonly logoUrlDark?: string | null; + - readonly longDescription?: string | null; + - readonly privacyPolicyUrl?: string | null; + -- readonly screenshotUrls: ReadonlyArray; + - readonly screenshots: ReadonlyArray; + - readonly shortDescription?: string | null; + - readonly termsOfServiceUrl?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginReadResponse__PluginInterface = Schema.Struct({ + - capabilities: Schema.Array(Schema.String), + - category: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - composerIcon: Schema.optionalKey( + -- Schema.Union([V2PluginReadResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local composer icon path, resolved from the installed plugin package.", + -- }), + -- ), + -- composerIconUrl: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote composer icon URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -+ Schema.Union([V2PluginReadResponse__AbsolutePathBuf, Schema.Null]), + - ), + - defaultPrompt: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginReadResponse__PluginInterface = Schema.Struct({ + - ), + - developerName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - displayName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- logo: Schema.optionalKey( + -- Schema.Union([V2PluginReadResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local logo path, resolved from the installed plugin package.", + -- }), + -- ), + -- logoDark: Schema.optionalKey( + -- Schema.Union([V2PluginReadResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local dark-mode logo path, resolved from the installed plugin package.", + -- }), + -- ), + -- logoUrl: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote logo URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -- ), + -- logoUrlDark: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote dark-mode logo URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -- ), + -+ logo: Schema.optionalKey(Schema.Union([V2PluginReadResponse__AbsolutePathBuf, Schema.Null])), + - longDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - privacyPolicyUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- screenshotUrls: Schema.Array(Schema.String).annotate({ + -- description: "Remote screenshot URLs from the plugin catalog.", + -- }), + -- screenshots: Schema.Array(V2PluginReadResponse__AbsolutePathBuf).annotate({ + -- description: "Local screenshot paths, resolved from the installed plugin package.", + -- }), + -+ screenshots: Schema.Array(V2PluginReadResponse__AbsolutePathBuf), + - shortDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - termsOfServiceUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - websiteUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type V2PluginReadResponse__PluginSource = + -- | { readonly path: V2PluginReadResponse__AbsolutePathBuf; readonly type: "local" } + -- | { + -- readonly path?: string | null; + -- readonly refName?: string | null; + -- readonly sha?: string | null; + -- readonly type: "git"; + -- readonly url: string; + -- } + -- | { + -- readonly package: string; + -- readonly registry?: string | null; + -- readonly type: "npm"; + -- readonly version?: string | null; + -- } + -- | { readonly type: "remote" }; + -+export type V2PluginReadResponse__PluginSource = { + -+ readonly path: V2PluginReadResponse__AbsolutePathBuf; + -+ readonly type: "local"; + -+}; + - export const V2PluginReadResponse__PluginSource = Schema.Union( + - [ + - Schema.Struct({ + - path: V2PluginReadResponse__AbsolutePathBuf, + - type: Schema.Literal("local").annotate({ title: "LocalPluginSourceType" }), + - }).annotate({ title: "LocalPluginSource" }), + -- Schema.Struct({ + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- refName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- sha: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("git").annotate({ title: "GitPluginSourceType" }), + -- url: Schema.String, + -- }).annotate({ title: "GitPluginSource" }), + -- Schema.Struct({ + -- package: Schema.String, + -- registry: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional HTTPS registry URL. Authentication stays in the user's npm config.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- type: Schema.Literal("npm").annotate({ title: "NpmPluginSourceType" }), + -- version: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Optional npm version or version range." }), + -- Schema.Null, + -- ]), + -- ), + -- }).annotate({ title: "NpmPluginSource" }), + -- Schema.Struct({ + -- type: Schema.Literal("remote").annotate({ title: "RemotePluginSourceType" }), + -- }).annotate({ + -- title: "RemotePluginSource", + -- description: + -- "The plugin is available in the remote catalog. Download metadata is kept server-side and is not exposed through the app-server API.", + -- }), + - ], + - { mode: "oneOf" }, + - ); + - + --export type V2PluginReadResponse__SkillInterface = { + -- readonly brandColor?: string | null; + -- readonly defaultPrompt?: string | null; + -- readonly displayName?: string | null; + -- readonly iconLarge?: V2PluginReadResponse__AbsolutePathBuf | null; + -- readonly iconSmall?: V2PluginReadResponse__AbsolutePathBuf | null; + -- readonly shortDescription?: string | null; + --}; + --export const V2PluginReadResponse__SkillInterface = Schema.Struct({ + -- brandColor: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- defaultPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- displayName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- iconLarge: Schema.optionalKey(Schema.Union([V2PluginReadResponse__AbsolutePathBuf, Schema.Null])), + -- iconSmall: Schema.optionalKey(Schema.Union([V2PluginReadResponse__AbsolutePathBuf, Schema.Null])), + -- shortDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + --export type V2PluginReadResponse__AppTemplateSummary = { + -- readonly canonicalConnectorId?: string | null; + -- readonly category?: string | null; + -- readonly description?: string | null; + -- readonly logoUrl?: string | null; + -- readonly logoUrlDark?: string | null; + -- readonly materializedAppIds: ReadonlyArray; + -- readonly name: string; + -- readonly reason?: V2PluginReadResponse__AppTemplateUnavailableReason | null; + -- readonly templateId: string; + --}; + --export const V2PluginReadResponse__AppTemplateSummary = Schema.Struct({ + -- canonicalConnectorId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- category: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- description: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- logoUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- logoUrlDark: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- materializedAppIds: Schema.Array(Schema.String), + -- name: Schema.String, + -- reason: Schema.optionalKey( + -- Schema.Union([V2PluginReadResponse__AppTemplateUnavailableReason, Schema.Null]), + -- ), + -- templateId: Schema.String, + --}); + -- + --export type V2PluginReadResponse__PluginHookSummary = { + -- readonly eventName: V2PluginReadResponse__HookEventName; + -- readonly key: string; + --}; + --export const V2PluginReadResponse__PluginHookSummary = Schema.Struct({ + -- eventName: V2PluginReadResponse__HookEventName, + -- key: Schema.String, + --}); + -- + --export type V2PluginReadResponse__PluginSharePrincipal = { + -+export type V2PluginReadResponse__SkillSummary = { + -+ readonly description: string; + -+ readonly enabled: boolean; + -+ readonly interface?: V2PluginReadResponse__SkillInterface | null; + - readonly name: string; + -- readonly principalId: string; + -- readonly principalType: V2PluginReadResponse__PluginSharePrincipalType; + -- readonly role: V2PluginReadResponse__PluginSharePrincipalRole; + -+ readonly path: string; + -+ readonly shortDescription?: string | null; + - }; + --export const V2PluginReadResponse__PluginSharePrincipal = Schema.Struct({ + -+export const V2PluginReadResponse__SkillSummary = Schema.Struct({ + -+ description: Schema.String, + -+ enabled: Schema.Boolean, + -+ interface: Schema.optionalKey(Schema.Union([V2PluginReadResponse__SkillInterface, Schema.Null])), + - name: Schema.String, + -- principalId: Schema.String, + -- principalType: V2PluginReadResponse__PluginSharePrincipalType, + -- role: V2PluginReadResponse__PluginSharePrincipalRole, + -+ path: Schema.String, + -+ shortDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type V2PluginReadResponse__ScheduledTaskSchedule = + -- | { + -- readonly days?: ReadonlyArray | null; + -- readonly intervalHours: number; + -- readonly type: "hourly"; + -- } + -- | { readonly time: string; readonly type: "daily" } + -- | { readonly time: string; readonly type: "weekdays" } + -+export type V2RawResponseItemCompletedNotification__FunctionCallOutputContentItem = + -+ | { readonly text: string; readonly type: "input_text" } + - | { + -- readonly days: ReadonlyArray; + -- readonly time: string; + -- readonly type: "weekly"; + -+ readonly detail?: V2RawResponseItemCompletedNotification__ImageDetail | null; + -+ readonly image_url: string; + -+ readonly type: "input_image"; + - }; + --export const V2PluginReadResponse__ScheduledTaskSchedule = Schema.Union( + -+export const V2RawResponseItemCompletedNotification__FunctionCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -- days: Schema.optionalKey( + -- Schema.Union([Schema.Array(V2PluginReadResponse__ScheduledTaskWeekday), Schema.Null]), + -- ), + -- intervalHours: Schema.Number.annotate({ format: "uint32" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- type: Schema.Literal("hourly").annotate({ title: "HourlyScheduledTaskScheduleType" }), + -- }).annotate({ title: "HourlyScheduledTaskSchedule" }), + -- Schema.Struct({ + -- time: Schema.String, + -- type: Schema.Literal("daily").annotate({ title: "DailyScheduledTaskScheduleType" }), + -- }).annotate({ title: "DailyScheduledTaskSchedule" }), + -- Schema.Struct({ + -- time: Schema.String, + -- type: Schema.Literal("weekdays").annotate({ title: "WeekdaysScheduledTaskScheduleType" }), + -- }).annotate({ title: "WeekdaysScheduledTaskSchedule" }), + -+ text: Schema.String, + -+ type: Schema.Literal("input_text").annotate({ + -+ title: "InputTextFunctionCallOutputContentItemType", + -+ }), + -+ }).annotate({ title: "InputTextFunctionCallOutputContentItem" }), + - Schema.Struct({ + -- days: Schema.Array(V2PluginReadResponse__ScheduledTaskWeekday), + -- time: Schema.String, + -- type: Schema.Literal("weekly").annotate({ title: "WeeklyScheduledTaskScheduleType" }), + -- }).annotate({ title: "WeeklyScheduledTaskSchedule" }), + -+ detail: Schema.optionalKey( + -+ Schema.Union([V2RawResponseItemCompletedNotification__ImageDetail, Schema.Null]), + -+ ), + -+ image_url: Schema.String, + -+ type: Schema.Literal("input_image").annotate({ + -+ title: "InputImageFunctionCallOutputContentItemType", + -+ }), + -+ }).annotate({ title: "InputImageFunctionCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + --); + -- + --export type V2PluginShareListResponse__PluginInterface = { + -- readonly brandColor?: string | null; + -- readonly capabilities: ReadonlyArray; + -- readonly category?: string | null; + -- readonly composerIcon?: V2PluginShareListResponse__AbsolutePathBuf | null; + -- readonly composerIconUrl?: string | null; + -- readonly defaultPrompt?: ReadonlyArray | null; + -- readonly developerName?: string | null; + -- readonly displayName?: string | null; + -- readonly logo?: V2PluginShareListResponse__AbsolutePathBuf | null; + -- readonly logoDark?: V2PluginShareListResponse__AbsolutePathBuf | null; + -- readonly logoUrl?: string | null; + -- readonly logoUrlDark?: string | null; + -- readonly longDescription?: string | null; + -- readonly privacyPolicyUrl?: string | null; + -- readonly screenshotUrls: ReadonlyArray; + -- readonly screenshots: ReadonlyArray; + -- readonly shortDescription?: string | null; + -- readonly termsOfServiceUrl?: string | null; + -- readonly websiteUrl?: string | null; + --}; + --export const V2PluginShareListResponse__PluginInterface = Schema.Struct({ + -- brandColor: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- capabilities: Schema.Array(Schema.String), + -- category: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- composerIcon: Schema.optionalKey( + -- Schema.Union([V2PluginShareListResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local composer icon path, resolved from the installed plugin package.", + -- }), + -- ), + -- composerIconUrl: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote composer icon URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -- ), + -- defaultPrompt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.String).annotate({ + -- description: + -- "Starter prompts for the plugin. Capped at 3 entries with a maximum of 128 characters per entry.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- developerName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- displayName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- logo: Schema.optionalKey( + -- Schema.Union([V2PluginShareListResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local logo path, resolved from the installed plugin package.", + -- }), + -- ), + -- logoDark: Schema.optionalKey( + -- Schema.Union([V2PluginShareListResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: "Local dark-mode logo path, resolved from the installed plugin package.", + -- }), + -- ), + -- logoUrl: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote logo URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -- ), + -- logoUrlDark: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Remote dark-mode logo URL from the plugin catalog." }), + -- Schema.Null, + -- ]), + -- ), + -- longDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- privacyPolicyUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- screenshotUrls: Schema.Array(Schema.String).annotate({ + -- description: "Remote screenshot URLs from the plugin catalog.", + -- }), + -- screenshots: Schema.Array(V2PluginShareListResponse__AbsolutePathBuf).annotate({ + -- description: "Local screenshot paths, resolved from the installed plugin package.", + -- }), + -- shortDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- termsOfServiceUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- websiteUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + --export type V2PluginShareListResponse__PluginSource = + -- | { readonly path: V2PluginShareListResponse__AbsolutePathBuf; readonly type: "local" } + -- | { + -- readonly path?: string | null; + -- readonly refName?: string | null; + -- readonly sha?: string | null; + -- readonly type: "git"; + -- readonly url: string; + -- } + -- | { + -- readonly package: string; + -- readonly registry?: string | null; + -- readonly type: "npm"; + -- readonly version?: string | null; + -- } + -- | { readonly type: "remote" }; + --export const V2PluginShareListResponse__PluginSource = Schema.Union( + -- [ + -- Schema.Struct({ + -- path: V2PluginShareListResponse__AbsolutePathBuf, + -- type: Schema.Literal("local").annotate({ title: "LocalPluginSourceType" }), + -- }).annotate({ title: "LocalPluginSource" }), + -- Schema.Struct({ + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- refName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- sha: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("git").annotate({ title: "GitPluginSourceType" }), + -- url: Schema.String, + -- }).annotate({ title: "GitPluginSource" }), + -- Schema.Struct({ + -- package: Schema.String, + -- registry: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional HTTPS registry URL. Authentication stays in the user's npm config.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- type: Schema.Literal("npm").annotate({ title: "NpmPluginSourceType" }), + -- version: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Optional npm version or version range." }), + -- Schema.Null, + -- ]), + -- ), + -- }).annotate({ title: "NpmPluginSource" }), + -- Schema.Struct({ + -- type: Schema.Literal("remote").annotate({ title: "RemotePluginSourceType" }), + -- }).annotate({ + -- title: "RemotePluginSource", + -- description: + -- "The plugin is available in the remote catalog. Download metadata is kept server-side and is not exposed through the app-server API.", + -- }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type V2PluginShareListResponse__PluginSharePrincipal = { + -- readonly name: string; + -- readonly principalId: string; + -- readonly principalType: V2PluginShareListResponse__PluginSharePrincipalType; + -- readonly role: V2PluginShareListResponse__PluginSharePrincipalRole; + --}; + --export const V2PluginShareListResponse__PluginSharePrincipal = Schema.Struct({ + -- name: Schema.String, + -- principalId: Schema.String, + -- principalType: V2PluginShareListResponse__PluginSharePrincipalType, + -- role: V2PluginShareListResponse__PluginSharePrincipalRole, + --}); + -- + --export type V2PluginShareSaveParams__PluginShareTarget = { + -- readonly principalId: string; + -- readonly principalType: V2PluginShareSaveParams__PluginSharePrincipalType; + -- readonly role: V2PluginShareSaveParams__PluginShareTargetRole; + --}; + --export const V2PluginShareSaveParams__PluginShareTarget = Schema.Struct({ + -- principalId: Schema.String, + -- principalType: V2PluginShareSaveParams__PluginSharePrincipalType, + -- role: V2PluginShareSaveParams__PluginShareTargetRole, + --}); + -- + --export type V2PluginShareUpdateTargetsParams__PluginShareTarget = { + -- readonly principalId: string; + -- readonly principalType: V2PluginShareUpdateTargetsParams__PluginSharePrincipalType; + -- readonly role: V2PluginShareUpdateTargetsParams__PluginShareTargetRole; + --}; + --export const V2PluginShareUpdateTargetsParams__PluginShareTarget = Schema.Struct({ + -- principalId: Schema.String, + -- principalType: V2PluginShareUpdateTargetsParams__PluginSharePrincipalType, + -- role: V2PluginShareUpdateTargetsParams__PluginShareTargetRole, + --}); + -- + --export type V2PluginShareUpdateTargetsResponse__PluginSharePrincipal = { + -- readonly name: string; + -- readonly principalId: string; + -- readonly principalType: V2PluginShareUpdateTargetsResponse__PluginSharePrincipalType; + -- readonly role: V2PluginShareUpdateTargetsResponse__PluginSharePrincipalRole; + --}; + --export const V2PluginShareUpdateTargetsResponse__PluginSharePrincipal = Schema.Struct({ + -- name: Schema.String, + -- principalId: Schema.String, + -- principalType: V2PluginShareUpdateTargetsResponse__PluginSharePrincipalType, + -- role: V2PluginShareUpdateTargetsResponse__PluginSharePrincipalRole, + --}); + -- + --export type V2RawResponseItemCompletedNotification__ContentItem = + -- | { readonly text: string; readonly type: "input_text" } + -- | { + -- readonly detail?: V2RawResponseItemCompletedNotification__ImageDetail | null; + -- readonly image_url: string; + -- readonly type: "input_image"; + -- } + -- | { readonly audio_url: string; readonly type: "input_audio" } + -- | { readonly text: string; readonly type: "output_text" }; + --export const V2RawResponseItemCompletedNotification__ContentItem = Schema.Union( + -- [ + -- Schema.Struct({ + -- text: Schema.String, + -- type: Schema.Literal("input_text").annotate({ title: "InputTextContentItemType" }), + -- }).annotate({ title: "InputTextContentItem" }), + -- Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2RawResponseItemCompletedNotification__ImageDetail, Schema.Null]), + -- ), + -- image_url: Schema.String, + -- type: Schema.Literal("input_image").annotate({ title: "InputImageContentItemType" }), + -- }).annotate({ title: "InputImageContentItem" }), + -- Schema.Struct({ + -- audio_url: Schema.String, + -- type: Schema.Literal("input_audio").annotate({ title: "InputAudioContentItemType" }), + -- }).annotate({ title: "InputAudioContentItem" }), + -- Schema.Struct({ + -- text: Schema.String, + -- type: Schema.Literal("output_text").annotate({ title: "OutputTextContentItemType" }), + -- }).annotate({ title: "OutputTextContentItem" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type V2RawResponseItemCompletedNotification__FunctionCallOutputContentItem = + -- | { readonly text: string; readonly type: "input_text" } + -- | { + -- readonly detail?: V2RawResponseItemCompletedNotification__ImageDetail | null; + -- readonly image_url: string; + -- readonly type: "input_image"; + -- } + -- | { readonly audio_url: string; readonly type: "input_audio" } + -- | { readonly encrypted_content: string; readonly type: "encrypted_content" }; + --export const V2RawResponseItemCompletedNotification__FunctionCallOutputContentItem = Schema.Union( + -- [ + -- Schema.Struct({ + -- text: Schema.String, + -- type: Schema.Literal("input_text").annotate({ + -- title: "InputTextFunctionCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputTextFunctionCallOutputContentItem" }), + -- Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2RawResponseItemCompletedNotification__ImageDetail, Schema.Null]), + -- ), + -- image_url: Schema.String, + -- type: Schema.Literal("input_image").annotate({ + -- title: "InputImageFunctionCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputImageFunctionCallOutputContentItem" }), + -- Schema.Struct({ + -- audio_url: Schema.String, + -- type: Schema.Literal("input_audio").annotate({ + -- title: "InputAudioFunctionCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioFunctionCallOutputContentItem" }), + -- Schema.Struct({ + -- encrypted_content: Schema.String, + -- type: Schema.Literal("encrypted_content").annotate({ + -- title: "EncryptedContentFunctionCallOutputContentItemType", + -- }), + -- }).annotate({ title: "EncryptedContentFunctionCallOutputContentItem" }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ + -- description: + -- "Responses API compatible content items that can be returned by a tool call. This is a subset of ContentItem with the types we support as function call outputs.", + --}); + -- + --export type V2ReviewStartResponse__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ReviewStartResponse__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ReviewStartResponse__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ReviewStartResponse__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -+).annotate({ + -+ description: + -+ "Responses API compatible content items that can be returned by a tool call. This is a subset of ContentItem with the types we support as function call outputs.", + -+}); + - + - export type V2ReviewStartResponse__CollabAgentState = { + - readonly message?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__MemoryCitation = Schema.Struct({ + - + - export type V2ReviewStartResponse__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ReviewStartResponse__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ReviewStartResponse__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ReviewStartResponse__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ReviewStartResponse__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ReviewStartResponse__ImageDetail, Schema.Null])), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ReviewStartResponse__ImageDetail, Schema.Null])), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__UserInput = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2SkillsListResponse__SkillInterface = { + -- readonly brandColor?: string | null; + -- readonly defaultPrompt?: string | null; + -- readonly displayName?: string | null; + -- readonly iconLarge?: V2SkillsListResponse__AbsolutePathBuf | null; + -- readonly iconSmall?: V2SkillsListResponse__AbsolutePathBuf | null; + -- readonly shortDescription?: string | null; + --}; + --export const V2SkillsListResponse__SkillInterface = Schema.Struct({ + -- brandColor: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- defaultPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- displayName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- iconLarge: Schema.optionalKey(Schema.Union([V2SkillsListResponse__AbsolutePathBuf, Schema.Null])), + -- iconSmall: Schema.optionalKey(Schema.Union([V2SkillsListResponse__AbsolutePathBuf, Schema.Null])), + -- shortDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2SkillsListResponse__SkillDependencies = { + - readonly tools: ReadonlyArray; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2SkillsListResponse__SkillDependencies = Schema.Struct({ + - tools: Schema.Array(V2SkillsListResponse__SkillToolDependency), + - }); + - + --export type V2ThreadForkResponse__CommandAction = + -+export type V2ThreadForkResponse__SandboxPolicy = + -+ | { readonly type: "dangerFullAccess" } + - | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ThreadForkResponse__AbsolutePathBuf; + -- readonly type: "read"; + -+ readonly access?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+ readonly networkAccess?: boolean; + -+ readonly type: "readOnly"; + - } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + - | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ThreadForkResponse__CommandAction = Schema.Union( + -+ readonly excludeSlashTmp?: boolean; + -+ readonly excludeTmpdirEnvVar?: boolean; + -+ readonly networkAccess?: boolean; + -+ readonly readOnlyAccess?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+ readonly type: "workspaceWrite"; + -+ readonly writableRoots?: ReadonlyArray; + -+ }; + -+export const V2ThreadForkResponse__SandboxPolicy = Schema.Union( + - [ + - Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ThreadForkResponse__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -+ type: Schema.Literal("dangerFullAccess").annotate({ + -+ title: "DangerFullAccessSandboxPolicyType", + -+ }), + -+ }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + - Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -+ access: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2ThreadForkResponse__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + -+ networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + -+ }).annotate({ title: "ReadOnlySandboxPolicy" }), + - Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -+ networkAccess: Schema.optionalKey( + -+ Schema.Literals(["restricted", "enabled"]).annotate({ default: "restricted" }), + -+ ), + -+ type: Schema.Literal("externalSandbox").annotate({ + -+ title: "ExternalSandboxSandboxPolicyType", + -+ }), + -+ }).annotate({ title: "ExternalSandboxSandboxPolicy" }), + - Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -+ excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ readOnlyAccess: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2ThreadForkResponse__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + -+ type: Schema.Literal("workspaceWrite").annotate({ title: "WorkspaceWriteSandboxPolicyType" }), + -+ writableRoots: Schema.optionalKey( + -+ Schema.Array(V2ThreadForkResponse__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ }).annotate({ title: "WorkspaceWriteSandboxPolicy" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__MemoryCitation = Schema.Struct({ + - + - export type V2ThreadForkResponse__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkResponse__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ThreadForkResponse__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ThreadForkResponse__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ThreadForkResponse__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ThreadForkResponse__ImageDetail, Schema.Null])), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ThreadForkResponse__ImageDetail, Schema.Null])), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__SubAgentSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadGoalGetResponse__ThreadGoal = { + -- readonly createdAt: number; + -- readonly objective: string; + -- readonly status: V2ThreadGoalGetResponse__ThreadGoalStatus; + -- readonly threadId: string; + -- readonly timeUsedSeconds: number; + -- readonly tokenBudget?: number | null; + -- readonly tokensUsed: number; + -- readonly updatedAt: number; + --}; + --export const V2ThreadGoalGetResponse__ThreadGoal = Schema.Struct({ + -- createdAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- objective: Schema.String, + -- status: V2ThreadGoalGetResponse__ThreadGoalStatus, + -- threadId: Schema.String, + -- timeUsedSeconds: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- tokenBudget: Schema.optionalKey( + -- Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + -- ), + -- tokensUsed: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- updatedAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + --}); + -- + --export type V2ThreadGoalSetResponse__ThreadGoal = { + -- readonly createdAt: number; + -- readonly objective: string; + -- readonly status: V2ThreadGoalSetResponse__ThreadGoalStatus; + -- readonly threadId: string; + -- readonly timeUsedSeconds: number; + -- readonly tokenBudget?: number | null; + -- readonly tokensUsed: number; + -- readonly updatedAt: number; + --}; + --export const V2ThreadGoalSetResponse__ThreadGoal = Schema.Struct({ + -- createdAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- objective: Schema.String, + -- status: V2ThreadGoalSetResponse__ThreadGoalStatus, + -- threadId: Schema.String, + -- timeUsedSeconds: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- tokenBudget: Schema.optionalKey( + -- Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + -- ), + -- tokensUsed: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- updatedAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + --}); + -- + --export type V2ThreadGoalUpdatedNotification__ThreadGoal = { + -- readonly createdAt: number; + -- readonly objective: string; + -- readonly status: V2ThreadGoalUpdatedNotification__ThreadGoalStatus; + -- readonly threadId: string; + -- readonly timeUsedSeconds: number; + -- readonly tokenBudget?: number | null; + -- readonly tokensUsed: number; + -- readonly updatedAt: number; + --}; + --export const V2ThreadGoalUpdatedNotification__ThreadGoal = Schema.Struct({ + -- createdAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- objective: Schema.String, + -- status: V2ThreadGoalUpdatedNotification__ThreadGoalStatus, + -- threadId: Schema.String, + -- timeUsedSeconds: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- tokenBudget: Schema.optionalKey( + -- Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + -- ), + -- tokensUsed: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- updatedAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + --}); + -- + --export type V2ThreadListResponse__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ThreadListResponse__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ThreadListResponse__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ThreadListResponse__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2ThreadListResponse__CollabAgentState = { + - readonly message?: string | null; + - readonly status: V2ThreadListResponse__CollabAgentStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__MemoryCitation = Schema.Struct({ + - + - export type V2ThreadListResponse__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadListResponse__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ThreadListResponse__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ThreadListResponse__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ThreadListResponse__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ThreadListResponse__ImageDetail, Schema.Null])), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ThreadListResponse__ImageDetail, Schema.Null])), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__SubAgentSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadMetadataUpdateResponse__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ThreadMetadataUpdateResponse__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ThreadMetadataUpdateResponse__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ThreadMetadataUpdateResponse__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2ThreadMetadataUpdateResponse__CollabAgentState = { + - readonly message?: string | null; + - readonly status: V2ThreadMetadataUpdateResponse__CollabAgentStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__MemoryCitation = Schema.Struct({ + - + - export type V2ThreadMetadataUpdateResponse__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadMetadataUpdateResponse__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ThreadMetadataUpdateResponse__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ThreadMetadataUpdateResponse__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ThreadMetadataUpdateResponse__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ThreadMetadataUpdateResponse__ImageDetail, Schema.Null]), + -- ), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ThreadMetadataUpdateResponse__ImageDetail, Schema.Null]), + -- ), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__SubAgentSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadReadResponse__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ThreadReadResponse__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ThreadReadResponse__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ThreadReadResponse__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2ThreadReadResponse__CollabAgentState = { + - readonly message?: string | null; + - readonly status: V2ThreadReadResponse__CollabAgentStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__MemoryCitation = Schema.Struct({ + - + - export type V2ThreadReadResponse__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadReadResponse__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ThreadReadResponse__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ThreadReadResponse__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ThreadReadResponse__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ThreadReadResponse__ImageDetail, Schema.Null])), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ThreadReadResponse__ImageDetail, Schema.Null])), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__SubAgentSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadResumeParams__ContentItem = + -- | { readonly text: string; readonly type: "input_text" } + -- | { + -- readonly detail?: V2ThreadResumeParams__ImageDetail | null; + -- readonly image_url: string; + -- readonly type: "input_image"; + -- } + -- | { readonly audio_url: string; readonly type: "input_audio" } + -- | { readonly text: string; readonly type: "output_text" }; + --export const V2ThreadResumeParams__ContentItem = Schema.Union( + -- [ + -- Schema.Struct({ + -- text: Schema.String, + -- type: Schema.Literal("input_text").annotate({ title: "InputTextContentItemType" }), + -- }).annotate({ title: "InputTextContentItem" }), + -- Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ThreadResumeParams__ImageDetail, Schema.Null])), + -- image_url: Schema.String, + -- type: Schema.Literal("input_image").annotate({ title: "InputImageContentItemType" }), + -- }).annotate({ title: "InputImageContentItem" }), + -- Schema.Struct({ + -- audio_url: Schema.String, + -- type: Schema.Literal("input_audio").annotate({ title: "InputAudioContentItemType" }), + -- }).annotate({ title: "InputAudioContentItem" }), + -- Schema.Struct({ + -- text: Schema.String, + -- type: Schema.Literal("output_text").annotate({ title: "OutputTextContentItemType" }), + -- }).annotate({ title: "OutputTextContentItem" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2ThreadResumeParams__FunctionCallOutputContentItem = + - | { readonly text: string; readonly type: "input_text" } + - | { + - readonly detail?: V2ThreadResumeParams__ImageDetail | null; + - readonly image_url: string; + - readonly type: "input_image"; + -- } + -- | { readonly audio_url: string; readonly type: "input_audio" } + -- | { readonly encrypted_content: string; readonly type: "encrypted_content" }; + -+ }; + - export const V2ThreadResumeParams__FunctionCallOutputContentItem = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__FunctionCallOutputContentItem = Schema.Union( + - title: "InputImageFunctionCallOutputContentItemType", + - }), + - }).annotate({ title: "InputImageFunctionCallOutputContentItem" }), + -- Schema.Struct({ + -- audio_url: Schema.String, + -- type: Schema.Literal("input_audio").annotate({ + -- title: "InputAudioFunctionCallOutputContentItemType", + -- }), + -- }).annotate({ title: "InputAudioFunctionCallOutputContentItem" }), + -- Schema.Struct({ + -- encrypted_content: Schema.String, + -- type: Schema.Literal("encrypted_content").annotate({ + -- title: "EncryptedContentFunctionCallOutputContentItemType", + -- }), + -- }).annotate({ title: "EncryptedContentFunctionCallOutputContentItem" }), + - ], + - { mode: "oneOf" }, + - ).annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__FunctionCallOutputContentItem = Schema.Union( + - "Responses API compatible content items that can be returned by a tool call. This is a subset of ContentItem with the types we support as function call outputs.", + - }); + - + --export type V2ThreadResumeResponse__CommandAction = + -+export type V2ThreadResumeResponse__SandboxPolicy = + -+ | { readonly type: "dangerFullAccess" } + - | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ThreadResumeResponse__AbsolutePathBuf; + -- readonly type: "read"; + -+ readonly access?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+ readonly networkAccess?: boolean; + -+ readonly type: "readOnly"; + - } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + - | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ThreadResumeResponse__CommandAction = Schema.Union( + -+ readonly excludeSlashTmp?: boolean; + -+ readonly excludeTmpdirEnvVar?: boolean; + -+ readonly networkAccess?: boolean; + -+ readonly readOnlyAccess?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+ readonly type: "workspaceWrite"; + -+ readonly writableRoots?: ReadonlyArray; + -+ }; + -+export const V2ThreadResumeResponse__SandboxPolicy = Schema.Union( + - [ + - Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ThreadResumeResponse__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -+ type: Schema.Literal("dangerFullAccess").annotate({ + -+ title: "DangerFullAccessSandboxPolicyType", + -+ }), + -+ }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + - Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -+ access: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2ThreadResumeResponse__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + -+ networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + -+ }).annotate({ title: "ReadOnlySandboxPolicy" }), + - Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -+ networkAccess: Schema.optionalKey( + -+ Schema.Literals(["restricted", "enabled"]).annotate({ default: "restricted" }), + -+ ), + -+ type: Schema.Literal("externalSandbox").annotate({ + -+ title: "ExternalSandboxSandboxPolicyType", + -+ }), + -+ }).annotate({ title: "ExternalSandboxSandboxPolicy" }), + - Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -+ excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ readOnlyAccess: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2ThreadResumeResponse__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + -+ type: Schema.Literal("workspaceWrite").annotate({ title: "WorkspaceWriteSandboxPolicyType" }), + -+ writableRoots: Schema.optionalKey( + -+ Schema.Array(V2ThreadResumeResponse__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ }).annotate({ title: "WorkspaceWriteSandboxPolicy" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__MemoryCitation = Schema.Struct({ + - + - export type V2ThreadResumeResponse__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeResponse__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ThreadResumeResponse__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ThreadResumeResponse__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ThreadResumeResponse__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ThreadResumeResponse__ImageDetail, Schema.Null])), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ThreadResumeResponse__ImageDetail, Schema.Null])), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__SubAgentSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadRollbackResponse__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ThreadRollbackResponse__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ThreadRollbackResponse__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ThreadRollbackResponse__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2ThreadRollbackResponse__CollabAgentState = { + - readonly message?: string | null; + - readonly status: V2ThreadRollbackResponse__CollabAgentStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__MemoryCitation = Schema.Struct({ + - + - export type V2ThreadRollbackResponse__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadRollbackResponse__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ThreadRollbackResponse__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ThreadRollbackResponse__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ThreadRollbackResponse__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ThreadRollbackResponse__ImageDetail, Schema.Null]), + -- ), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ThreadRollbackResponse__ImageDetail, Schema.Null]), + -- ), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__SubAgentSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadSettingsUpdatedNotification__SandboxPolicy = + -- | { readonly type: "dangerFullAccess" } + -- | { readonly networkAccess?: boolean; readonly type: "readOnly" } + -- | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + -- | { + -- readonly excludeSlashTmp?: boolean; + -- readonly excludeTmpdirEnvVar?: boolean; + -- readonly networkAccess?: boolean; + -- readonly type: "workspaceWrite"; + -- readonly writableRoots?: ReadonlyArray; + -- }; + --export const V2ThreadSettingsUpdatedNotification__SandboxPolicy = Schema.Union( + -- [ + -- Schema.Struct({ + -- type: Schema.Literal("dangerFullAccess").annotate({ + -- title: "DangerFullAccessSandboxPolicyType", + -- }), + -- }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + -- }).annotate({ title: "ReadOnlySandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey( + -- Schema.Literals(["restricted", "enabled"]).annotate({ default: "restricted" }), + -- ), + -- type: Schema.Literal("externalSandbox").annotate({ + -- title: "ExternalSandboxSandboxPolicyType", + -- }), + -- }).annotate({ title: "ExternalSandboxSandboxPolicy" }), + -- Schema.Struct({ + -- excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("workspaceWrite").annotate({ title: "WorkspaceWriteSandboxPolicyType" }), + -- writableRoots: Schema.optionalKey( + -- Schema.Array(V2ThreadSettingsUpdatedNotification__AbsolutePathBuf).annotate({ + -- default: [], + -- }), + -- ), + -- }).annotate({ title: "WorkspaceWriteSandboxPolicy" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type V2ThreadSettingsUpdatedNotification__Settings = { + -- readonly developer_instructions?: string | null; + -- readonly model: string; + -- readonly reasoning_effort?: V2ThreadSettingsUpdatedNotification__ReasoningEffort | null; + --}; + --export const V2ThreadSettingsUpdatedNotification__Settings = Schema.Struct({ + -- developer_instructions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- model: Schema.String, + -- reasoning_effort: Schema.optionalKey( + -- Schema.Union([V2ThreadSettingsUpdatedNotification__ReasoningEffort, Schema.Null]), + -- ), + --}).annotate({ description: "Settings for a collaboration mode." }); + -- + --export type V2ThreadStartedNotification__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ThreadStartedNotification__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ThreadStartedNotification__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ThreadStartedNotification__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2ThreadStartedNotification__CollabAgentState = { + - readonly message?: string | null; + - readonly status: V2ThreadStartedNotification__CollabAgentStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__MemoryCitation = Schema.Struct({ + - + - export type V2ThreadStartedNotification__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartedNotification__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ThreadStartedNotification__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ThreadStartedNotification__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ThreadStartedNotification__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ThreadStartedNotification__ImageDetail, Schema.Null]), + -- ), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ThreadStartedNotification__ImageDetail, Schema.Null]), + -- ), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__SubAgentSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadStartResponse__CommandAction = + -+export type V2ThreadStartResponse__SandboxPolicy = + -+ | { readonly type: "dangerFullAccess" } + - | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ThreadStartResponse__AbsolutePathBuf; + -- readonly type: "read"; + -+ readonly access?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+ readonly networkAccess?: boolean; + -+ readonly type: "readOnly"; + - } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -+ | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + - | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ThreadStartResponse__CommandAction = Schema.Union( + -+ readonly excludeSlashTmp?: boolean; + -+ readonly excludeTmpdirEnvVar?: boolean; + -+ readonly networkAccess?: boolean; + -+ readonly readOnlyAccess?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+ readonly type: "workspaceWrite"; + -+ readonly writableRoots?: ReadonlyArray; + -+ }; + -+export const V2ThreadStartResponse__SandboxPolicy = Schema.Union( + - [ + - Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ThreadStartResponse__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -+ type: Schema.Literal("dangerFullAccess").annotate({ + -+ title: "DangerFullAccessSandboxPolicyType", + -+ }), + -+ }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + - Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -+ access: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2ThreadStartResponse__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + -+ networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + -+ }).annotate({ title: "ReadOnlySandboxPolicy" }), + - Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -+ networkAccess: Schema.optionalKey( + -+ Schema.Literals(["restricted", "enabled"]).annotate({ default: "restricted" }), + -+ ), + -+ type: Schema.Literal("externalSandbox").annotate({ + -+ title: "ExternalSandboxSandboxPolicyType", + -+ }), + -+ }).annotate({ title: "ExternalSandboxSandboxPolicy" }), + - Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -+ excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ readOnlyAccess: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2ThreadStartResponse__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + -+ type: Schema.Literal("workspaceWrite").annotate({ title: "WorkspaceWriteSandboxPolicyType" }), + -+ writableRoots: Schema.optionalKey( + -+ Schema.Array(V2ThreadStartResponse__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ }).annotate({ title: "WorkspaceWriteSandboxPolicy" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__MemoryCitation = Schema.Struct({ + - + - export type V2ThreadStartResponse__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartResponse__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ThreadStartResponse__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ThreadStartResponse__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ThreadStartResponse__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ThreadStartResponse__ImageDetail, Schema.Null])), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2ThreadStartResponse__ImageDetail, Schema.Null])), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadTokenUsageUpdatedNotification__ThreadTokenUsage = Schema.St + - total: V2ThreadTokenUsageUpdatedNotification__TokenUsageBreakdown, + - }); + - + --export type V2ThreadUnarchiveResponse__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2ThreadUnarchiveResponse__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2ThreadUnarchiveResponse__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2ThreadUnarchiveResponse__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2ThreadUnarchiveResponse__CollabAgentState = { + - readonly message?: string | null; + - readonly status: V2ThreadUnarchiveResponse__CollabAgentStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__MemoryCitation = Schema.Struct({ + - + - export type V2ThreadUnarchiveResponse__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadUnarchiveResponse__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2ThreadUnarchiveResponse__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2ThreadUnarchiveResponse__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2ThreadUnarchiveResponse__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ThreadUnarchiveResponse__ImageDetail, Schema.Null]), + -- ), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2ThreadUnarchiveResponse__ImageDetail, Schema.Null]), + -- ), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__SubAgentSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2TurnCompletedNotification__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2TurnCompletedNotification__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2TurnCompletedNotification__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2TurnCompletedNotification__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2TurnCompletedNotification__CollabAgentState = { + - readonly message?: string | null; + - readonly status: V2TurnCompletedNotification__CollabAgentStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__MemoryCitation = Schema.Struct({ + - + - export type V2TurnCompletedNotification__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnCompletedNotification__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2TurnCompletedNotification__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2TurnCompletedNotification__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2TurnCompletedNotification__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2TurnCompletedNotification__ImageDetail, Schema.Null]), + -- ), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2TurnCompletedNotification__ImageDetail, Schema.Null]), + -- ), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnPlanUpdatedNotification__TurnPlanStep = Schema.Struct({ + - step: Schema.String, + - }); + - + --export type V2TurnStartedNotification__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2TurnStartedNotification__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2TurnStartedNotification__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2TurnStartedNotification__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2TurnStartedNotification__CollabAgentState = { + - readonly message?: string | null; + - readonly status: V2TurnStartedNotification__CollabAgentStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartedNotification__MemoryCitation = Schema.Struct({ + - + - export type V2TurnStartedNotification__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartedNotification__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartedNotification__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2TurnStartedNotification__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2TurnStartedNotification__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2TurnStartedNotification__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartedNotification__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2TurnStartedNotification__ImageDetail, Schema.Null]), + -- ), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey( + -- Schema.Union([V2TurnStartedNotification__ImageDetail, Schema.Null]), + -- ), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartedNotification__UserInput = Schema.Union( + - + - export type V2TurnStartParams__SandboxPolicy = + - | { readonly type: "dangerFullAccess" } + -- | { readonly networkAccess?: boolean; readonly type: "readOnly" } + -+ | { + -+ readonly access?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+ readonly networkAccess?: boolean; + -+ readonly type: "readOnly"; + -+ } + - | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + - | { + - readonly excludeSlashTmp?: boolean; + - readonly excludeTmpdirEnvVar?: boolean; + - readonly networkAccess?: boolean; + -+ readonly readOnlyAccess?: + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + - readonly type: "workspaceWrite"; + - readonly writableRoots?: ReadonlyArray; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams__SandboxPolicy = Schema.Union( + - }), + - }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + - Schema.Struct({ + -+ access: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2TurnStartParams__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + - networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + - }).annotate({ title: "ReadOnlySandboxPolicy" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams__SandboxPolicy = Schema.Union( + - excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -+ readOnlyAccess: Schema.optionalKey( + -+ Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey( + -+ Schema.Boolean.annotate({ default: true }), + -+ ), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2TurnStartParams__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ + -+ title: "RestrictedReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ + -+ title: "FullAccessReadOnlyAccessType", + -+ }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ default: { type: "fullAccess" } }), + -+ ), + - type: Schema.Literal("workspaceWrite").annotate({ title: "WorkspaceWriteSandboxPolicyType" }), + - writableRoots: Schema.optionalKey( + - Schema.Array(V2TurnStartParams__AbsolutePathBuf).annotate({ default: [] }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartParams__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2TurnStartParams__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2TurnStartParams__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2TurnStartParams__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2TurnStartParams__ImageDetail, Schema.Null])), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2TurnStartParams__ImageDetail, Schema.Null])), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams__UserInput = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2TurnStartResponse__CommandAction = + -- | { + -- readonly command: string; + -- readonly name: string; + -- readonly path: V2TurnStartResponse__AbsolutePathBuf; + -- readonly type: "read"; + -- } + -- | { readonly command: string; readonly path?: string | null; readonly type: "listFiles" } + -- | { + -- readonly command: string; + -- readonly path?: string | null; + -- readonly query?: string | null; + -- readonly type: "search"; + -- } + -- | { readonly command: string; readonly type: "unknown" }; + --export const V2TurnStartResponse__CommandAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- name: Schema.String, + -- path: V2TurnStartResponse__AbsolutePathBuf, + -- type: Schema.Literal("read").annotate({ title: "ReadCommandActionType" }), + -- }).annotate({ title: "ReadCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("listFiles").annotate({ title: "ListFilesCommandActionType" }), + -- }).annotate({ title: "ListFilesCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- path: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- query: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("search").annotate({ title: "SearchCommandActionType" }), + -- }).annotate({ title: "SearchCommandAction" }), + -- Schema.Struct({ + -- command: Schema.String, + -- type: Schema.Literal("unknown").annotate({ title: "UnknownCommandActionType" }), + -- }).annotate({ title: "UnknownCommandAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2TurnStartResponse__CollabAgentState = { + - readonly message?: string | null; + - readonly status: V2TurnStartResponse__CollabAgentStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__MemoryCitation = Schema.Struct({ + - + - export type V2TurnStartResponse__CodexErrorInfo = + - | "contextWindowExceeded" + -- | "sessionBudgetExceeded" + - | "usageLimitExceeded" + - | "serverOverloaded" + -- | "cyberPolicy" + - | "internalServerError" + - | "unauthorized" + - | "badRequest" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__CodexErrorInfo = Schema.Union( + - [ + - Schema.Literals([ + - "contextWindowExceeded", + -- "sessionBudgetExceeded", + - "usageLimitExceeded", + - "serverOverloaded", + -- "cyberPolicy", + - "internalServerError", + - "unauthorized", + - "badRequest", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartResponse__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2TurnStartResponse__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2TurnStartResponse__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2TurnStartResponse__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2TurnStartResponse__ImageDetail, Schema.Null])), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2TurnStartResponse__ImageDetail, Schema.Null])), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnSteerParams__UserInput = + - readonly text_elements?: ReadonlyArray; + - readonly type: "text"; + - } + -- | { + -- readonly detail?: V2TurnSteerParams__ImageDetail | null; + -- readonly type: "image"; + -- readonly url: string; + -- } + -- | { + -- readonly detail?: V2TurnSteerParams__ImageDetail | null; + -- readonly path: string; + -- readonly type: "localImage"; + -- } + -- | { readonly type: "audio"; readonly url: string } + -- | { readonly path: string; readonly type: "localAudio" } + -+ | { readonly type: "image"; readonly url: string } + -+ | { readonly path: string; readonly type: "localImage" } + - | { readonly name: string; readonly path: string; readonly type: "skill" } + - | { readonly name: string; readonly path: string; readonly type: "mention" }; + - export const V2TurnSteerParams__UserInput = Schema.Union( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnSteerParams__UserInput = Schema.Union( + - type: Schema.Literal("text").annotate({ title: "TextUserInputType" }), + - }).annotate({ title: "TextUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2TurnSteerParams__ImageDetail, Schema.Null])), + - type: Schema.Literal("image").annotate({ title: "ImageUserInputType" }), + - url: Schema.String, + - }).annotate({ title: "ImageUserInput" }), + - Schema.Struct({ + -- detail: Schema.optionalKey(Schema.Union([V2TurnSteerParams__ImageDetail, Schema.Null])), + - path: Schema.String, + - type: Schema.Literal("localImage").annotate({ title: "LocalImageUserInputType" }), + - }).annotate({ title: "LocalImageUserInput" }), + -- Schema.Struct({ + -- type: Schema.Literal("audio").annotate({ title: "AudioUserInputType" }), + -- url: Schema.String, + -- }).annotate({ title: "AudioUserInput" }), + -- Schema.Struct({ + -- path: Schema.String, + -- type: Schema.Literal("localAudio").annotate({ title: "LocalAudioUserInputType" }), + -- }).annotate({ title: "LocalAudioUserInput" }), + - Schema.Struct({ + - name: Schema.String, + - path: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__CommandExecParams = Schema.Struct({ + - sandboxPolicy: Schema.optionalKey( + - Schema.Union([ClientRequest__SandboxPolicy, Schema.Null]).annotate({ + - description: + -- "Optional sandbox policy for this command.\n\nUses the same shape as thread/turn execution sandbox configuration and defaults to the user's configured policy when omitted. Cannot be combined with `permissionProfile`.", + -+ "Optional sandbox policy for this command.\n\nUses the same shape as thread/turn execution sandbox configuration and defaults to the user's configured policy when omitted.", + - }), + - ), + - size: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__CommandExecParams = Schema.Struct({ + - "Run a standalone command (argv vector) in the server sandbox without creating a thread or turn.\n\nThe final `command/exec` response is deferred until the process exits and is sent only after all `command/exec/outputDelta` notifications for that connection have been emitted.", + - }); + - + -+export type ClientRequest__ExternalAgentConfigImportParams = { + -+ readonly migrationItems: ReadonlyArray; + -+}; + -+export const ClientRequest__ExternalAgentConfigImportParams = Schema.Struct({ + -+ migrationItems: Schema.Array(ClientRequest__ExternalAgentConfigMigrationItem), + -+}); + -+ + - export type ClientRequest__FunctionCallOutputBody = + - | string + - | ReadonlyArray; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ConfigBatchWriteParams = Schema.Struct({ + - ), + - }); + - + --export type ClientRequest__PluginShareSaveParams = { + -- readonly discoverability?: ClientRequest__PluginShareDiscoverability | null; + -- readonly pluginPath: ClientRequest__AbsolutePathBuf; + -- readonly remotePluginId?: string | null; + -- readonly shareTargets?: ReadonlyArray | null; + --}; + --export const ClientRequest__PluginShareSaveParams = Schema.Struct({ + -- discoverability: Schema.optionalKey( + -- Schema.Union([ClientRequest__PluginShareDiscoverability, Schema.Null]), + -- ), + -- pluginPath: ClientRequest__AbsolutePathBuf, + -- remotePluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- shareTargets: Schema.optionalKey( + -- Schema.Union([Schema.Array(ClientRequest__PluginShareTarget), Schema.Null]), + -- ), + --}); + -- + --export type ClientRequest__PluginShareUpdateTargetsParams = { + -- readonly discoverability: ClientRequest__PluginShareUpdateDiscoverability; + -- readonly remotePluginId: string; + -- readonly shareTargets: ReadonlyArray; + --}; + --export const ClientRequest__PluginShareUpdateTargetsParams = Schema.Struct({ + -- discoverability: ClientRequest__PluginShareUpdateDiscoverability, + -- remotePluginId: Schema.String, + -- shareTargets: Schema.Array(ClientRequest__PluginShareTarget), + --}); + -- + --export type ClientRequest__ExternalAgentConfigMigrationItem = { + -- readonly cwd?: string | null; + -- readonly description: string; + -- readonly details?: ClientRequest__MigrationDetails | null; + -- readonly itemType: ClientRequest__ExternalAgentConfigMigrationItemType; + --}; + --export const ClientRequest__ExternalAgentConfigMigrationItem = Schema.Struct({ + -- cwd: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Null or empty means home-scoped migration; non-empty means repo-scoped migration.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- description: Schema.String, + -- details: Schema.optionalKey(Schema.Union([ClientRequest__MigrationDetails, Schema.Null])), + -- itemType: ClientRequest__ExternalAgentConfigMigrationItemType, + --}); + -- + - export type ClientRequest__TurnStartParams = { + - readonly approvalPolicy?: ClientRequest__AskForApproval | null; + - readonly approvalsReviewer?: ClientRequest__ApprovalsReviewer | null; + -- readonly clientUserMessageId?: string | null; + - readonly cwd?: string | null; + - readonly effort?: ClientRequest__ReasoningEffort | null; + - readonly input: ReadonlyArray; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest__TurnStartParams = { + - readonly outputSchema?: unknown; + - readonly personality?: ClientRequest__Personality | null; + - readonly sandboxPolicy?: ClientRequest__SandboxPolicy | null; + -- readonly serviceTier?: string | null; + -+ readonly serviceTier?: ClientRequest__ServiceTier | null | null; + - readonly summary?: ClientRequest__ReasoningSummary | null; + - readonly threadId: string; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__TurnStartParams = Schema.Struct({ + - "Override where approval requests are routed for review on this turn and subsequent turns.", + - }), + - ), + -- clientUserMessageId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - cwd: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__TurnStartParams = Schema.Struct({ + - }), + - ), + - serviceTier: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Override the service tier for this turn and subsequent turns.", + -- }), + -- Schema.Null, + -- ]), + -+ Schema.Union([Schema.Union([ClientRequest__ServiceTier, Schema.Null]), Schema.Null]).annotate({ + -+ description: "Override the service tier for this turn and subsequent turns.", + -+ }), + - ), + - summary: Schema.optionalKey( + - Schema.Union([ClientRequest__ReasoningSummary, Schema.Null]).annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__TurnStartParams = Schema.Struct({ + - }); + - + - export type ClientRequest__TurnSteerParams = { + -- readonly clientUserMessageId?: string | null; + - readonly expectedTurnId: string; + - readonly input: ReadonlyArray; + - readonly threadId: string; + - }; + - export const ClientRequest__TurnSteerParams = Schema.Struct({ + -- clientUserMessageId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - expectedTurnId: Schema.String.annotate({ + - description: + - "Required active turn id precondition. The request fails when it does not match the currently active turn.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__TurnSteerParams = Schema.Struct({ + - threadId: Schema.String, + - }); + - + --export type CommandExecutionRequestApprovalParams__FileSystemPath = + -- | { + -- readonly path: CommandExecutionRequestApprovalParams__LegacyAppPathString; + -- readonly type: "path"; + -- } + -- | { readonly pattern: string; readonly type: "glob_pattern" } + -- | { + -- readonly type: "special"; + -- readonly value: CommandExecutionRequestApprovalParams__FileSystemSpecialPath; + -- }; + --export const CommandExecutionRequestApprovalParams__FileSystemPath = Schema.Union( + -- [ + -- Schema.Struct({ + -- path: CommandExecutionRequestApprovalParams__LegacyAppPathString, + -- type: Schema.Literal("path").annotate({ title: "PathFileSystemPathType" }), + -- }).annotate({ title: "PathFileSystemPath" }), + -- Schema.Struct({ + -- pattern: Schema.String, + -- type: Schema.Literal("glob_pattern").annotate({ title: "GlobPatternFileSystemPathType" }), + -- }).annotate({ title: "GlobPatternFileSystemPath" }), + -- Schema.Struct({ + -- type: Schema.Literal("special").annotate({ title: "SpecialFileSystemPathType" }), + -- value: CommandExecutionRequestApprovalParams__FileSystemSpecialPath, + -- }).annotate({ title: "SpecialFileSystemPath" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type CommandExecutionRequestApprovalResponse__CommandExecutionApprovalDecision = + - | "accept" + - | "acceptForSession" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const McpServerElicitationRequestParams__McpElicitationSingleSelectEnumSc + - ], + - ); + - + --export type PermissionsRequestApprovalParams__FileSystemPath = + -- | { readonly path: PermissionsRequestApprovalParams__LegacyAppPathString; readonly type: "path" } + -- | { readonly pattern: string; readonly type: "glob_pattern" } + -- | { + -- readonly type: "special"; + -- readonly value: PermissionsRequestApprovalParams__FileSystemSpecialPath; + -- }; + --export const PermissionsRequestApprovalParams__FileSystemPath = Schema.Union( + -- [ + -- Schema.Struct({ + -- path: PermissionsRequestApprovalParams__LegacyAppPathString, + -- type: Schema.Literal("path").annotate({ title: "PathFileSystemPathType" }), + -- }).annotate({ title: "PathFileSystemPath" }), + -- Schema.Struct({ + -- pattern: Schema.String, + -- type: Schema.Literal("glob_pattern").annotate({ title: "GlobPatternFileSystemPathType" }), + -- }).annotate({ title: "GlobPatternFileSystemPath" }), + -- Schema.Struct({ + -- type: Schema.Literal("special").annotate({ title: "SpecialFileSystemPathType" }), + -- value: PermissionsRequestApprovalParams__FileSystemSpecialPath, + -- }).annotate({ title: "SpecialFileSystemPath" }), + -- ], + -- { mode: "oneOf" }, + --); + -+export type PermissionsRequestApprovalParams__RequestPermissionProfile = { + -+ readonly fileSystem?: PermissionsRequestApprovalParams__AdditionalFileSystemPermissions | null; + -+ readonly network?: PermissionsRequestApprovalParams__AdditionalNetworkPermissions | null; + -+}; + -+export const PermissionsRequestApprovalParams__RequestPermissionProfile = Schema.Struct({ + -+ fileSystem: Schema.optionalKey( + -+ Schema.Union([PermissionsRequestApprovalParams__AdditionalFileSystemPermissions, Schema.Null]), + -+ ), + -+ network: Schema.optionalKey( + -+ Schema.Union([PermissionsRequestApprovalParams__AdditionalNetworkPermissions, Schema.Null]), + -+ ), + -+}); + - + --export type PermissionsRequestApprovalResponse__FileSystemPath = + -- | { + -- readonly path: PermissionsRequestApprovalResponse__LegacyAppPathString; + -- readonly type: "path"; + -- } + -- | { readonly pattern: string; readonly type: "glob_pattern" } + -- | { + -- readonly type: "special"; + -- readonly value: PermissionsRequestApprovalResponse__FileSystemSpecialPath; + -- }; + --export const PermissionsRequestApprovalResponse__FileSystemPath = Schema.Union( + -- [ + -- Schema.Struct({ + -- path: PermissionsRequestApprovalResponse__LegacyAppPathString, + -- type: Schema.Literal("path").annotate({ title: "PathFileSystemPathType" }), + -- }).annotate({ title: "PathFileSystemPath" }), + -- Schema.Struct({ + -- pattern: Schema.String, + -- type: Schema.Literal("glob_pattern").annotate({ title: "GlobPatternFileSystemPathType" }), + -- }).annotate({ title: "GlobPatternFileSystemPath" }), + -- Schema.Struct({ + -- type: Schema.Literal("special").annotate({ title: "SpecialFileSystemPathType" }), + -- value: PermissionsRequestApprovalResponse__FileSystemSpecialPath, + -- }).annotate({ title: "SpecialFileSystemPath" }), + -- ], + -- { mode: "oneOf" }, + --); + -+export type PermissionsRequestApprovalResponse__GrantedPermissionProfile = { + -+ readonly fileSystem?: PermissionsRequestApprovalResponse__AdditionalFileSystemPermissions | null; + -+ readonly network?: PermissionsRequestApprovalResponse__AdditionalNetworkPermissions | null; + -+}; + -+export const PermissionsRequestApprovalResponse__GrantedPermissionProfile = Schema.Struct({ + -+ fileSystem: Schema.optionalKey( + -+ Schema.Union([ + -+ PermissionsRequestApprovalResponse__AdditionalFileSystemPermissions, + -+ Schema.Null, + -+ ]), + -+ ), + -+ network: Schema.optionalKey( + -+ Schema.Union([PermissionsRequestApprovalResponse__AdditionalNetworkPermissions, Schema.Null]), + -+ ), + -+}); + - + - export type ServerNotification__AppInfo = { + - readonly appMetadata?: ServerNotification__AppMetadata | null; + - readonly branding?: ServerNotification__AppBranding | null; + - readonly description?: string | null; + - readonly distributionChannel?: string | null; + -- readonly iconAssets?: { readonly [x: string]: string } | null; + -- readonly iconDarkAssets?: { readonly [x: string]: string } | null; + - readonly id: string; + - readonly installUrl?: string | null; + - readonly isAccessible?: boolean; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__AppInfo = Schema.Struct({ + - branding: Schema.optionalKey(Schema.Union([ServerNotification__AppBranding, Schema.Null])), + - description: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - distributionChannel: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- iconAssets: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.String), Schema.Null]), + -- ), + -- iconDarkAssets: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.String), Schema.Null]), + -- ), + - id: Schema.String, + - installUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - isAccessible: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__AppInfo = Schema.Struct({ + - pluginDisplayNames: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + - }).annotate({ description: "EXPERIMENTAL - app metadata returned by app-list APIs." }); + - + --export type ServerNotification__ExternalAgentConfigImportTypeResult = { + -- readonly failures: ReadonlyArray; + -- readonly itemType: ServerNotification__ExternalAgentConfigMigrationItemType; + -- readonly successes: ReadonlyArray; + --}; + --export const ServerNotification__ExternalAgentConfigImportTypeResult = Schema.Struct({ + -- failures: Schema.Array(ServerNotification__ExternalAgentConfigImportItemTypeFailure), + -- itemType: ServerNotification__ExternalAgentConfigMigrationItemType, + -- successes: Schema.Array(ServerNotification__ExternalAgentConfigImportItemTypeSuccess), + --}); + -- + - export type ServerNotification__FuzzyFileSearchSessionUpdatedNotification = { + - readonly files: ReadonlyArray; + - readonly query: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerNotification__HookRunSummary = { + - readonly handlerType: ServerNotification__HookHandlerType; + - readonly id: string; + - readonly scope: ServerNotification__HookScope; + -- readonly source?: + -- | "system" + -- | "user" + -- | "project" + -- | "mdm" + -- | "sessionFlags" + -- | "plugin" + -- | "cloudRequirements" + -- | "cloudManagedConfig" + -- | "legacyManagedConfigFile" + -- | "legacyManagedConfigMdm" + -- | "unknown"; + -- readonly sourcePath: ServerNotification__AbsolutePathBuf; + -+ readonly sourcePath: string; + - readonly startedAt: number; + - readonly status: ServerNotification__HookRunStatus; + - readonly statusMessage?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__HookRunSummary = Schema.Struct({ + - handlerType: ServerNotification__HookHandlerType, + - id: Schema.String, + - scope: ServerNotification__HookScope, + -- source: Schema.optionalKey( + -- Schema.Literals([ + -- "system", + -- "user", + -- "project", + -- "mdm", + -- "sessionFlags", + -- "plugin", + -- "cloudRequirements", + -- "cloudManagedConfig", + -- "legacyManagedConfigFile", + -- "legacyManagedConfigMdm", + -- "unknown", + -- ]).annotate({ default: "unknown" }), + -- ), + -- sourcePath: ServerNotification__AbsolutePathBuf, + -+ sourcePath: Schema.String, + - startedAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + - status: ServerNotification__HookRunStatus, + - statusMessage: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type ServerNotification__FileSystemPath = + -- | { readonly path: ServerNotification__LegacyAppPathString; readonly type: "path" } + -- | { readonly pattern: string; readonly type: "glob_pattern" } + -- | { readonly type: "special"; readonly value: ServerNotification__FileSystemSpecialPath }; + --export const ServerNotification__FileSystemPath = Schema.Union( + -- [ + -- Schema.Struct({ + -- path: ServerNotification__LegacyAppPathString, + -- type: Schema.Literal("path").annotate({ title: "PathFileSystemPathType" }), + -- }).annotate({ title: "PathFileSystemPath" }), + -- Schema.Struct({ + -- pattern: Schema.String, + -- type: Schema.Literal("glob_pattern").annotate({ title: "GlobPatternFileSystemPathType" }), + -- }).annotate({ title: "GlobPatternFileSystemPath" }), + -- Schema.Struct({ + -- type: Schema.Literal("special").annotate({ title: "SpecialFileSystemPathType" }), + -- value: ServerNotification__FileSystemSpecialPath, + -- }).annotate({ title: "SpecialFileSystemPath" }), + -- ], + -- { mode: "oneOf" }, + --); + -+export type ServerNotification__ItemGuardianApprovalReviewCompletedNotification = { + -+ readonly action: ServerNotification__GuardianApprovalReviewAction; + -+ readonly decisionSource: ServerNotification__AutoReviewDecisionSource; + -+ readonly review: ServerNotification__GuardianApprovalReview; + -+ readonly reviewId: string; + -+ readonly targetItemId?: string | null; + -+ readonly threadId: string; + -+ readonly turnId: string; + -+}; + -+export const ServerNotification__ItemGuardianApprovalReviewCompletedNotification = Schema.Struct({ + -+ action: ServerNotification__GuardianApprovalReviewAction, + -+ decisionSource: ServerNotification__AutoReviewDecisionSource, + -+ review: ServerNotification__GuardianApprovalReview, + -+ reviewId: Schema.String.annotate({ description: "Stable identifier for this review." }), + -+ targetItemId: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ + -+ description: + -+ "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", + -+ }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ threadId: Schema.String, + -+ turnId: Schema.String, + -+}).annotate({ + -+ description: + -+ "[UNSTABLE] Temporary notification payload for guardian automatic approval review. This shape is expected to change soon.", + -+}); + -+ + -+export type ServerNotification__ItemGuardianApprovalReviewStartedNotification = { + -+ readonly action: ServerNotification__GuardianApprovalReviewAction; + -+ readonly review: ServerNotification__GuardianApprovalReview; + -+ readonly reviewId: string; + -+ readonly targetItemId?: string | null; + -+ readonly threadId: string; + -+ readonly turnId: string; + -+}; + -+export const ServerNotification__ItemGuardianApprovalReviewStartedNotification = Schema.Struct({ + -+ action: ServerNotification__GuardianApprovalReviewAction, + -+ review: ServerNotification__GuardianApprovalReview, + -+ reviewId: Schema.String.annotate({ description: "Stable identifier for this review." }), + -+ targetItemId: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ + -+ description: + -+ "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", + -+ }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ threadId: Schema.String, + -+ turnId: Schema.String, + -+}).annotate({ + -+ description: + -+ "[UNSTABLE] Temporary notification payload for guardian automatic approval review. This shape is expected to change soon.", + -+}); + - + - export type ServerNotification__TurnError = { + - readonly additionalDetails?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__TurnError = Schema.Struct({ + - message: Schema.String, + - }); + - + --export type ServerNotification__FileChangePatchUpdatedNotification = { + -- readonly changes: ReadonlyArray; + -- readonly itemId: string; + -- readonly threadId: string; + -- readonly turnId: string; + --}; + --export const ServerNotification__FileChangePatchUpdatedNotification = Schema.Struct({ + -- changes: Schema.Array(ServerNotification__FileUpdateChange), + -- itemId: Schema.String, + -- threadId: Schema.String, + -- turnId: Schema.String, + --}); + -- + --export type ServerNotification__CollaborationMode = { + -- readonly mode: ServerNotification__ModeKind; + -- readonly settings: ServerNotification__Settings; + --}; + --export const ServerNotification__CollaborationMode = Schema.Struct({ + -- mode: ServerNotification__ModeKind, + -- settings: ServerNotification__Settings, + --}).annotate({ description: "Collaboration mode for a Codex session." }); + -- + - export type ServerNotification__AccountRateLimitsUpdatedNotification = { + - readonly rateLimits: ServerNotification__RateLimitSnapshot; + - }; + - export const ServerNotification__AccountRateLimitsUpdatedNotification = Schema.Struct({ + - rateLimits: ServerNotification__RateLimitSnapshot, + --}).annotate({ + -- description: + -- "Sparse rolling rate-limit update.\n\nClients should merge available values into the most recent `account/rateLimits/read` response or refetch that snapshot. Nullable account metadata may be unavailable in a rolling update and does not clear a previously observed value.", + - }); + - + - export type ServerNotification__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerNotification__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: ServerNotification__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: ServerNotification__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: ServerNotification__McpToolCallResult | null; + - readonly server: string; + - readonly status: ServerNotification__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerNotification__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: ServerNotification__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerNotification__ThreadItem = + - readonly reasoningEffort?: ServerNotification__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: ServerNotification__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: ServerNotification__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: ServerNotification__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: ServerNotification__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerNotification__ThreadItem = + - export const ServerNotification__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(ServerNotification__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([ServerNotification__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ThreadItem = Schema.Union( + - ), + - error: Schema.optionalKey(Schema.Union([ServerNotification__McpToolCallError, Schema.Null])), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([ServerNotification__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: ServerNotification__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: ServerNotification__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey(Schema.Union([ServerNotification__WebSearchAction, Schema.Null])), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: ServerNotification__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([ServerNotification__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ThreadStatusChangedNotification = Schema.Struct + - threadId: Schema.String, + - }); + - + --export type ServerNotification__ThreadGoalUpdatedNotification = { + -- readonly goal: ServerNotification__ThreadGoal; + -- readonly threadId: string; + -- readonly turnId?: string | null; + --}; + --export const ServerNotification__ThreadGoalUpdatedNotification = Schema.Struct({ + -- goal: ServerNotification__ThreadGoal, + -- threadId: Schema.String, + -- turnId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type ServerNotification__ThreadTokenUsageUpdatedNotification = { + - readonly threadId: string; + - readonly tokenUsage: ServerNotification__ThreadTokenUsage; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__TurnPlanUpdatedNotification = Schema.Struct({ + - turnId: Schema.String, + - }); + - + --export type ServerRequest__FileSystemPath = + -- | { readonly path: ServerRequest__LegacyAppPathString; readonly type: "path" } + -- | { readonly pattern: string; readonly type: "glob_pattern" } + -- | { readonly type: "special"; readonly value: ServerRequest__FileSystemSpecialPath }; + --export const ServerRequest__FileSystemPath = Schema.Union( + -- [ + -- Schema.Struct({ + -- path: ServerRequest__LegacyAppPathString, + -- type: Schema.Literal("path").annotate({ title: "PathFileSystemPathType" }), + -- }).annotate({ title: "PathFileSystemPath" }), + -- Schema.Struct({ + -- pattern: Schema.String, + -- type: Schema.Literal("glob_pattern").annotate({ title: "GlobPatternFileSystemPathType" }), + -- }).annotate({ title: "GlobPatternFileSystemPath" }), + -- Schema.Struct({ + -- type: Schema.Literal("special").annotate({ title: "SpecialFileSystemPathType" }), + -- value: ServerRequest__FileSystemSpecialPath, + -- }).annotate({ title: "SpecialFileSystemPath" }), + -- ], + -- { mode: "oneOf" }, + --); + -+export type ServerRequest__RequestPermissionProfile = { + -+ readonly fileSystem?: ServerRequest__AdditionalFileSystemPermissions | null; + -+ readonly network?: ServerRequest__AdditionalNetworkPermissions | null; + -+}; + -+export const ServerRequest__RequestPermissionProfile = Schema.Struct({ + -+ fileSystem: Schema.optionalKey( + -+ Schema.Union([ServerRequest__AdditionalFileSystemPermissions, Schema.Null]), + -+ ), + -+ network: Schema.optionalKey( + -+ Schema.Union([ServerRequest__AdditionalNetworkPermissions, Schema.Null]), + -+ ), + -+}); + - + - export type ServerRequest__McpElicitationTitledMultiSelectEnumSchema = { + - readonly default?: ReadonlyArray | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerRequest__CommandExecutionRequestApprovalParams = { + - readonly approvalId?: string | null; + - readonly command?: string | null; + - readonly commandActions?: ReadonlyArray | null; + -- readonly cwd?: ServerRequest__LegacyAppPathString | null; + -- readonly environmentId?: string | null; + -+ readonly cwd?: string | null; + - readonly itemId: string; + - readonly networkApprovalContext?: ServerRequest__NetworkApprovalContext | null; + - readonly proposedExecpolicyAmendment?: ReadonlyArray | null; + - readonly proposedNetworkPolicyAmendments?: ReadonlyArray | null; + - readonly reason?: string | null; + -- readonly startedAtMs: number; + - readonly threadId: string; + - readonly turnId: string; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerRequest__CommandExecutionRequestApprovalParams = Schema.Struc + - ]), + - ), + - cwd: Schema.optionalKey( + -- Schema.Union([ServerRequest__LegacyAppPathString, Schema.Null]).annotate({ + -- description: "The command's working directory.", + -- }), + -- ), + -- environmentId: Schema.optionalKey( + - Schema.Union([ + -- Schema.String.annotate({ description: "Environment in which the command will run." }), + -+ Schema.String.annotate({ description: "The command's working directory." }), + - Schema.Null, + - ]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerRequest__CommandExecutionRequestApprovalParams = Schema.Struc + - Schema.Null, + - ]), + - ), + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this approval request started.", + -- format: "int64", + -- }).check(Schema.isInt()), + - threadId: Schema.String, + - turnId: Schema.String, + - }); + - + - export type ServerRequest__ToolRequestUserInputParams = { + -- readonly autoResolutionMs?: number | null; + - readonly itemId: string; + - readonly questions: ReadonlyArray; + - readonly threadId: string; + - readonly turnId: string; + - }; + - export const ServerRequest__ToolRequestUserInputParams = Schema.Struct({ + -- autoResolutionMs: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- Schema.Null, + -- ]), + -- ), + - itemId: Schema.String, + - questions: Schema.Array(ServerRequest__ToolRequestUserInputQuestion), + - threadId: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2AppListUpdatedNotification__AppInfo = { + - readonly branding?: V2AppListUpdatedNotification__AppBranding | null; + - readonly description?: string | null; + - readonly distributionChannel?: string | null; + -- readonly iconAssets?: { readonly [x: string]: string } | null; + -- readonly iconDarkAssets?: { readonly [x: string]: string } | null; + - readonly id: string; + - readonly installUrl?: string | null; + - readonly isAccessible?: boolean; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2AppListUpdatedNotification__AppInfo = Schema.Struct({ + - ), + - description: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - distributionChannel: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- iconAssets: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.String), Schema.Null]), + -- ), + -- iconDarkAssets: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.String), Schema.Null]), + -- ), + - id: Schema.String, + - installUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - isAccessible: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2AppsListResponse__AppInfo = { + - readonly branding?: V2AppsListResponse__AppBranding | null; + - readonly description?: string | null; + - readonly distributionChannel?: string | null; + -- readonly iconAssets?: { readonly [x: string]: string } | null; + -- readonly iconDarkAssets?: { readonly [x: string]: string } | null; + - readonly id: string; + - readonly installUrl?: string | null; + - readonly isAccessible?: boolean; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2AppsListResponse__AppInfo = Schema.Struct({ + - branding: Schema.optionalKey(Schema.Union([V2AppsListResponse__AppBranding, Schema.Null])), + - description: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - distributionChannel: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- iconAssets: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.String), Schema.Null]), + -- ), + -- iconDarkAssets: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.String), Schema.Null]), + -- ), + - id: Schema.String, + - installUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - isAccessible: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadResponse__ConfigLayerMetadata = Schema.Struct({ + - }); + - + - export type V2ConfigReadResponse__ToolsV2 = { + -+ readonly view_image?: boolean | null; + - readonly web_search?: V2ConfigReadResponse__WebSearchToolConfig | null; + - }; + - export const V2ConfigReadResponse__ToolsV2 = Schema.Struct({ + -+ view_image: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - web_search: Schema.optionalKey( + - Schema.Union([V2ConfigReadResponse__WebSearchToolConfig, Schema.Null]), + - ), + - }); + - + --export type V2ConfigRequirementsReadResponse__ModelsRequirements = { + -- readonly newThread?: V2ConfigRequirementsReadResponse__NewThreadModelDefaults | null; + --}; + --export const V2ConfigRequirementsReadResponse__ModelsRequirements = Schema.Struct({ + -- newThread: Schema.optionalKey( + -- Schema.Union([V2ConfigRequirementsReadResponse__NewThreadModelDefaults, Schema.Null]), + -- ), + --}); + -- + - export type V2ConfigWriteResponse__ConfigLayerMetadata = { + - readonly name: V2ConfigWriteResponse__ConfigLayerSource; + - readonly version: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ErrorNotification__TurnError = Schema.Struct({ + - message: Schema.String, + - }); + - + --export type V2ExternalAgentConfigDetectResponse__ExternalAgentConfigMigrationItem = { + -- readonly cwd?: string | null; + -- readonly description: string; + -- readonly details?: V2ExternalAgentConfigDetectResponse__MigrationDetails | null; + -- readonly itemType: V2ExternalAgentConfigDetectResponse__ExternalAgentConfigMigrationItemType; + --}; + --export const V2ExternalAgentConfigDetectResponse__ExternalAgentConfigMigrationItem = Schema.Struct({ + -- cwd: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Null or empty means home-scoped migration; non-empty means repo-scoped migration.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- description: Schema.String, + -- details: Schema.optionalKey( + -- Schema.Union([V2ExternalAgentConfigDetectResponse__MigrationDetails, Schema.Null]), + -- ), + -- itemType: V2ExternalAgentConfigDetectResponse__ExternalAgentConfigMigrationItemType, + --}); + -- + --export type V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigImportTypeResult = + -- { + -- readonly failures: ReadonlyArray; + -- readonly itemType: V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigMigrationItemType; + -- readonly successes: ReadonlyArray; + -- }; + --export const V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigImportTypeResult = + -- Schema.Struct({ + -- failures: Schema.Array( + -- V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigImportItemTypeFailure, + -- ), + -- itemType: + -- V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigMigrationItemType, + -- successes: Schema.Array( + -- V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigImportItemTypeSuccess, + -- ), + -- }); + -- + --export type V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigImportHistory = { + -- readonly completedAtMs: number; + -- readonly failures: ReadonlyArray; + -- readonly importId: string; + -- readonly successes: ReadonlyArray; + --}; + --export const V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigImportHistory = + -- Schema.Struct({ + -- completedAtMs: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- failures: Schema.Array( + -- V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigImportItemTypeFailure, + -- ), + -- importId: Schema.String, + -- successes: Schema.Array( + -- V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigImportItemTypeSuccess, + -- ), + -- }); + -- + --export type V2ExternalAgentConfigImportParams__ExternalAgentConfigMigrationItem = { + -- readonly cwd?: string | null; + -- readonly description: string; + -- readonly details?: V2ExternalAgentConfigImportParams__MigrationDetails | null; + -- readonly itemType: V2ExternalAgentConfigImportParams__ExternalAgentConfigMigrationItemType; + --}; + --export const V2ExternalAgentConfigImportParams__ExternalAgentConfigMigrationItem = Schema.Struct({ + -- cwd: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Null or empty means home-scoped migration; non-empty means repo-scoped migration.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- description: Schema.String, + -- details: Schema.optionalKey( + -- Schema.Union([V2ExternalAgentConfigImportParams__MigrationDetails, Schema.Null]), + -- ), + -- itemType: V2ExternalAgentConfigImportParams__ExternalAgentConfigMigrationItemType, + --}); + -- + --export type V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigImportTypeResult = { + -- readonly failures: ReadonlyArray; + -- readonly itemType: V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigMigrationItemType; + -- readonly successes: ReadonlyArray; + --}; + --export const V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigImportTypeResult = + -- Schema.Struct({ + -- failures: Schema.Array( + -- V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigImportItemTypeFailure, + -- ), + -- itemType: V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigMigrationItemType, + -- successes: Schema.Array( + -- V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigImportItemTypeSuccess, + -- ), + -- }); + -- + --export type V2GetAccountRateLimitsResponse__RateLimitResetCreditsSummary = { + -- readonly availableCount: number; + -- readonly credits?: ReadonlyArray | null; + --}; + --export const V2GetAccountRateLimitsResponse__RateLimitResetCreditsSummary = Schema.Struct({ + -- availableCount: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- credits: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(V2GetAccountRateLimitsResponse__RateLimitResetCredit).annotate({ + -- description: + -- "Detail rows for available reset credits, when the backend provides them.\n\n`null` means only `availableCount` is known, while an empty array means details were fetched and no available credits were returned. The backend may cap this list, so its length can be less than `availableCount`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + - export type V2HookCompletedNotification__HookRunSummary = { + - readonly completedAt?: number | null; + - readonly displayOrder: number; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2HookCompletedNotification__HookRunSummary = { + - readonly handlerType: V2HookCompletedNotification__HookHandlerType; + - readonly id: string; + - readonly scope: V2HookCompletedNotification__HookScope; + -- readonly source?: + -- | "system" + -- | "user" + -- | "project" + -- | "mdm" + -- | "sessionFlags" + -- | "plugin" + -- | "cloudRequirements" + -- | "cloudManagedConfig" + -- | "legacyManagedConfigFile" + -- | "legacyManagedConfigMdm" + -- | "unknown"; + -- readonly sourcePath: V2HookCompletedNotification__AbsolutePathBuf; + -+ readonly sourcePath: string; + - readonly startedAt: number; + - readonly status: V2HookCompletedNotification__HookRunStatus; + - readonly statusMessage?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2HookCompletedNotification__HookRunSummary = Schema.Struct({ + - handlerType: V2HookCompletedNotification__HookHandlerType, + - id: Schema.String, + - scope: V2HookCompletedNotification__HookScope, + -- source: Schema.optionalKey( + -- Schema.Literals([ + -- "system", + -- "user", + -- "project", + -- "mdm", + -- "sessionFlags", + -- "plugin", + -- "cloudRequirements", + -- "cloudManagedConfig", + -- "legacyManagedConfigFile", + -- "legacyManagedConfigMdm", + -- "unknown", + -- ]).annotate({ default: "unknown" }), + -- ), + -- sourcePath: V2HookCompletedNotification__AbsolutePathBuf, + -+ sourcePath: Schema.String, + - startedAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + - status: V2HookCompletedNotification__HookRunStatus, + - statusMessage: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type V2HooksListResponse__HooksListEntry = { + -- readonly cwd: string; + -- readonly errors: ReadonlyArray; + -- readonly hooks: ReadonlyArray; + -- readonly warnings: ReadonlyArray; + --}; + --export const V2HooksListResponse__HooksListEntry = Schema.Struct({ + -- cwd: Schema.String, + -- errors: Schema.Array(V2HooksListResponse__HookErrorInfo), + -- hooks: Schema.Array(V2HooksListResponse__HookMetadata), + -- warnings: Schema.Array(Schema.String), + --}); + -- + - export type V2HookStartedNotification__HookRunSummary = { + - readonly completedAt?: number | null; + - readonly displayOrder: number; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2HookStartedNotification__HookRunSummary = { + - readonly handlerType: V2HookStartedNotification__HookHandlerType; + - readonly id: string; + - readonly scope: V2HookStartedNotification__HookScope; + -- readonly source?: + -- | "system" + -- | "user" + -- | "project" + -- | "mdm" + -- | "sessionFlags" + -- | "plugin" + -- | "cloudRequirements" + -- | "cloudManagedConfig" + -- | "legacyManagedConfigFile" + -- | "legacyManagedConfigMdm" + -- | "unknown"; + -- readonly sourcePath: V2HookStartedNotification__AbsolutePathBuf; + -+ readonly sourcePath: string; + - readonly startedAt: number; + - readonly status: V2HookStartedNotification__HookRunStatus; + - readonly statusMessage?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2HookStartedNotification__HookRunSummary = Schema.Struct({ + - handlerType: V2HookStartedNotification__HookHandlerType, + - id: Schema.String, + - scope: V2HookStartedNotification__HookScope, + -- source: Schema.optionalKey( + -- Schema.Literals([ + -- "system", + -- "user", + -- "project", + -- "mdm", + -- "sessionFlags", + -- "plugin", + -- "cloudRequirements", + -- "cloudManagedConfig", + -- "legacyManagedConfigFile", + -- "legacyManagedConfigMdm", + -- "unknown", + -- ]).annotate({ default: "unknown" }), + -- ), + -- sourcePath: V2HookStartedNotification__AbsolutePathBuf, + -+ sourcePath: Schema.String, + - startedAt: Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + - status: V2HookStartedNotification__HookRunStatus, + - statusMessage: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2HookStartedNotification__HookRunSummary = Schema.Struct({ + - + - export type V2ItemCompletedNotification__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemCompletedNotification__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ItemCompletedNotification__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ItemCompletedNotification__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ItemCompletedNotification__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ItemCompletedNotification__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemCompletedNotification__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ItemCompletedNotification__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemCompletedNotification__ThreadItem = + - readonly reasoningEffort?: V2ItemCompletedNotification__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ItemCompletedNotification__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ItemCompletedNotification__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ItemCompletedNotification__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ItemCompletedNotification__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemCompletedNotification__ThreadItem = + - export const V2ItemCompletedNotification__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ItemCompletedNotification__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ItemCompletedNotification__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__ThreadItem = Schema.Union( + - Schema.Union([V2ItemCompletedNotification__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ItemCompletedNotification__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ItemCompletedNotification__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ItemCompletedNotification__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ItemCompletedNotification__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ItemCompletedNotification__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ItemCompletedNotification__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__ThreadItem = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ItemGuardianApprovalReviewCompletedNotification__FileSystemPath = + -- | { + -- readonly path: V2ItemGuardianApprovalReviewCompletedNotification__LegacyAppPathString; + -- readonly type: "path"; + -- } + -- | { readonly pattern: string; readonly type: "glob_pattern" } + -- | { + -- readonly type: "special"; + -- readonly value: V2ItemGuardianApprovalReviewCompletedNotification__FileSystemSpecialPath; + -- }; + --export const V2ItemGuardianApprovalReviewCompletedNotification__FileSystemPath = Schema.Union( + -- [ + -- Schema.Struct({ + -- path: V2ItemGuardianApprovalReviewCompletedNotification__LegacyAppPathString, + -- type: Schema.Literal("path").annotate({ title: "PathFileSystemPathType" }), + -- }).annotate({ title: "PathFileSystemPath" }), + -- Schema.Struct({ + -- pattern: Schema.String, + -- type: Schema.Literal("glob_pattern").annotate({ title: "GlobPatternFileSystemPathType" }), + -- }).annotate({ title: "GlobPatternFileSystemPath" }), + -- Schema.Struct({ + -- type: Schema.Literal("special").annotate({ title: "SpecialFileSystemPathType" }), + -- value: V2ItemGuardianApprovalReviewCompletedNotification__FileSystemSpecialPath, + -- }).annotate({ title: "SpecialFileSystemPath" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type V2ItemGuardianApprovalReviewStartedNotification__FileSystemPath = + -- | { + -- readonly path: V2ItemGuardianApprovalReviewStartedNotification__LegacyAppPathString; + -- readonly type: "path"; + -- } + -- | { readonly pattern: string; readonly type: "glob_pattern" } + -- | { + -- readonly type: "special"; + -- readonly value: V2ItemGuardianApprovalReviewStartedNotification__FileSystemSpecialPath; + -- }; + --export const V2ItemGuardianApprovalReviewStartedNotification__FileSystemPath = Schema.Union( + -- [ + -- Schema.Struct({ + -- path: V2ItemGuardianApprovalReviewStartedNotification__LegacyAppPathString, + -- type: Schema.Literal("path").annotate({ title: "PathFileSystemPathType" }), + -- }).annotate({ title: "PathFileSystemPath" }), + -- Schema.Struct({ + -- pattern: Schema.String, + -- type: Schema.Literal("glob_pattern").annotate({ title: "GlobPatternFileSystemPathType" }), + -- }).annotate({ title: "GlobPatternFileSystemPath" }), + -- Schema.Struct({ + -- type: Schema.Literal("special").annotate({ title: "SpecialFileSystemPathType" }), + -- value: V2ItemGuardianApprovalReviewStartedNotification__FileSystemSpecialPath, + -- }).annotate({ title: "SpecialFileSystemPath" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + - export type V2ItemStartedNotification__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemStartedNotification__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ItemStartedNotification__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ItemStartedNotification__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ItemStartedNotification__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ItemStartedNotification__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemStartedNotification__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ItemStartedNotification__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemStartedNotification__ThreadItem = + - readonly reasoningEffort?: V2ItemStartedNotification__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ItemStartedNotification__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ItemStartedNotification__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ItemStartedNotification__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ItemStartedNotification__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemStartedNotification__ThreadItem = + - export const V2ItemStartedNotification__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ItemStartedNotification__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemStartedNotification__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ItemStartedNotification__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemStartedNotification__ThreadItem = Schema.Union( + - Schema.Union([V2ItemStartedNotification__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ItemStartedNotification__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemStartedNotification__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ItemStartedNotification__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemStartedNotification__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemStartedNotification__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ItemStartedNotification__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ItemStartedNotification__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ItemStartedNotification__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ItemStartedNotification__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ModelListResponse__Model = { + - readonly additionalSpeedTiers?: ReadonlyArray; + - readonly availabilityNux?: V2ModelListResponse__ModelAvailabilityNux | null; + - readonly defaultReasoningEffort: V2ModelListResponse__ReasoningEffort; + -- readonly defaultServiceTier?: string | null; + - readonly description: string; + - readonly displayName: string; + - readonly hidden: boolean; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ModelListResponse__Model = { + - readonly inputModalities?: ReadonlyArray; + - readonly isDefault: boolean; + - readonly model: string; + -- readonly serviceTiers?: ReadonlyArray; + - readonly supportedReasoningEfforts: ReadonlyArray; + - readonly supportsPersonality?: boolean; + - readonly upgrade?: string | null; + - readonly upgradeInfo?: V2ModelListResponse__ModelUpgradeInfo | null; + - }; + - export const V2ModelListResponse__Model = Schema.Struct({ + -- additionalSpeedTiers: Schema.optionalKey( + -- Schema.Array(Schema.String).annotate({ + -- description: "Deprecated: use `serviceTiers` instead.", + -- default: [], + -- }), + -- ), + -+ additionalSpeedTiers: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + - availabilityNux: Schema.optionalKey( + - Schema.Union([V2ModelListResponse__ModelAvailabilityNux, Schema.Null]), + - ), + - defaultReasoningEffort: V2ModelListResponse__ReasoningEffort, + -- defaultServiceTier: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Catalog default service tier id for this model, when one is configured.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - description: Schema.String, + - displayName: Schema.String, + - hidden: Schema.Boolean, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ModelListResponse__Model = Schema.Struct({ + - ), + - isDefault: Schema.Boolean, + - model: Schema.String, + -- serviceTiers: Schema.optionalKey( + -- Schema.Array(V2ModelListResponse__ModelServiceTier).annotate({ default: [] }), + -- ), + - supportedReasoningEfforts: Schema.Array(V2ModelListResponse__ReasoningEffortOption), + - supportsPersonality: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - upgrade: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ModelListResponse__Model = Schema.Struct({ + - ), + - }); + - + --export type V2PluginInstalledResponse__PluginShareContext = { + -- readonly creatorAccountUserId?: string | null; + -- readonly creatorName?: string | null; + -- readonly discoverability?: V2PluginInstalledResponse__PluginShareDiscoverability | null; + -- readonly remotePluginId: string; + -- readonly remoteVersion?: string | null; + -- readonly sharePrincipals?: ReadonlyArray | null; + -- readonly shareUrl?: string | null; + --}; + --export const V2PluginInstalledResponse__PluginShareContext = Schema.Struct({ + -- creatorAccountUserId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- creatorName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- discoverability: Schema.optionalKey( + -- Schema.Union([V2PluginInstalledResponse__PluginShareDiscoverability, Schema.Null]), + -- ), + -- remotePluginId: Schema.String, + -- remoteVersion: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version of the remote shared plugin release when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- sharePrincipals: Schema.optionalKey( + -- Schema.Union([Schema.Array(V2PluginInstalledResponse__PluginSharePrincipal), Schema.Null]), + -- ), + -- shareUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + --export type V2PluginListResponse__PluginShareContext = { + -- readonly creatorAccountUserId?: string | null; + -- readonly creatorName?: string | null; + -- readonly discoverability?: V2PluginListResponse__PluginShareDiscoverability | null; + -- readonly remotePluginId: string; + -- readonly remoteVersion?: string | null; + -- readonly sharePrincipals?: ReadonlyArray | null; + -- readonly shareUrl?: string | null; + --}; + --export const V2PluginListResponse__PluginShareContext = Schema.Struct({ + -- creatorAccountUserId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- creatorName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- discoverability: Schema.optionalKey( + -- Schema.Union([V2PluginListResponse__PluginShareDiscoverability, Schema.Null]), + -- ), + -- remotePluginId: Schema.String, + -- remoteVersion: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version of the remote shared plugin release when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- sharePrincipals: Schema.optionalKey( + -- Schema.Union([Schema.Array(V2PluginListResponse__PluginSharePrincipal), Schema.Null]), + -- ), + -- shareUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + --export type V2PluginReadResponse__SkillSummary = { + -- readonly description: string; + -+export type V2PluginListResponse__PluginSummary = { + -+ readonly authPolicy: V2PluginListResponse__PluginAuthPolicy; + - readonly enabled: boolean; + -- readonly interface?: V2PluginReadResponse__SkillInterface | null; + -+ readonly id: string; + -+ readonly installPolicy: V2PluginListResponse__PluginInstallPolicy; + -+ readonly installed: boolean; + -+ readonly interface?: V2PluginListResponse__PluginInterface | null; + - readonly name: string; + -- readonly path?: V2PluginReadResponse__AbsolutePathBuf | null; + -- readonly shortDescription?: string | null; + -+ readonly source: V2PluginListResponse__PluginSource; + - }; + --export const V2PluginReadResponse__SkillSummary = Schema.Struct({ + -- description: Schema.String, + -+export const V2PluginListResponse__PluginSummary = Schema.Struct({ + -+ authPolicy: V2PluginListResponse__PluginAuthPolicy, + - enabled: Schema.Boolean, + -- interface: Schema.optionalKey(Schema.Union([V2PluginReadResponse__SkillInterface, Schema.Null])), + -+ id: Schema.String, + -+ installPolicy: V2PluginListResponse__PluginInstallPolicy, + -+ installed: Schema.Boolean, + -+ interface: Schema.optionalKey(Schema.Union([V2PluginListResponse__PluginInterface, Schema.Null])), + - name: Schema.String, + -- path: Schema.optionalKey(Schema.Union([V2PluginReadResponse__AbsolutePathBuf, Schema.Null])), + -- shortDescription: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + --export type V2PluginReadResponse__PluginShareContext = { + -- readonly creatorAccountUserId?: string | null; + -- readonly creatorName?: string | null; + -- readonly discoverability?: V2PluginReadResponse__PluginShareDiscoverability | null; + -- readonly remotePluginId: string; + -- readonly remoteVersion?: string | null; + -- readonly sharePrincipals?: ReadonlyArray | null; + -- readonly shareUrl?: string | null; + --}; + --export const V2PluginReadResponse__PluginShareContext = Schema.Struct({ + -- creatorAccountUserId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- creatorName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- discoverability: Schema.optionalKey( + -- Schema.Union([V2PluginReadResponse__PluginShareDiscoverability, Schema.Null]), + -- ), + -- remotePluginId: Schema.String, + -- remoteVersion: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version of the remote shared plugin release when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- sharePrincipals: Schema.optionalKey( + -- Schema.Union([Schema.Array(V2PluginReadResponse__PluginSharePrincipal), Schema.Null]), + -- ), + -- shareUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ source: V2PluginListResponse__PluginSource, + - }); + - + --export type V2PluginReadResponse__ScheduledTaskSummary = { + -- readonly key: string; + -+export type V2PluginReadResponse__PluginSummary = { + -+ readonly authPolicy: V2PluginReadResponse__PluginAuthPolicy; + -+ readonly enabled: boolean; + -+ readonly id: string; + -+ readonly installPolicy: V2PluginReadResponse__PluginInstallPolicy; + -+ readonly installed: boolean; + -+ readonly interface?: V2PluginReadResponse__PluginInterface | null; + - readonly name: string; + -- readonly prompt: string; + -- readonly schedule: V2PluginReadResponse__ScheduledTaskSchedule; + -+ readonly source: V2PluginReadResponse__PluginSource; + - }; + --export const V2PluginReadResponse__ScheduledTaskSummary = Schema.Struct({ + -- key: Schema.String, + -+export const V2PluginReadResponse__PluginSummary = Schema.Struct({ + -+ authPolicy: V2PluginReadResponse__PluginAuthPolicy, + -+ enabled: Schema.Boolean, + -+ id: Schema.String, + -+ installPolicy: V2PluginReadResponse__PluginInstallPolicy, + -+ installed: Schema.Boolean, + -+ interface: Schema.optionalKey(Schema.Union([V2PluginReadResponse__PluginInterface, Schema.Null])), + - name: Schema.String, + -- prompt: Schema.String, + -- schedule: V2PluginReadResponse__ScheduledTaskSchedule, + --}); + -- + --export type V2PluginShareListResponse__PluginShareContext = { + -- readonly creatorAccountUserId?: string | null; + -- readonly creatorName?: string | null; + -- readonly discoverability?: V2PluginShareListResponse__PluginShareDiscoverability | null; + -- readonly remotePluginId: string; + -- readonly remoteVersion?: string | null; + -- readonly sharePrincipals?: ReadonlyArray | null; + -- readonly shareUrl?: string | null; + --}; + --export const V2PluginShareListResponse__PluginShareContext = Schema.Struct({ + -- creatorAccountUserId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- creatorName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- discoverability: Schema.optionalKey( + -- Schema.Union([V2PluginShareListResponse__PluginShareDiscoverability, Schema.Null]), + -- ), + -- remotePluginId: Schema.String, + -- remoteVersion: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version of the remote shared plugin release when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- sharePrincipals: Schema.optionalKey( + -- Schema.Union([Schema.Array(V2PluginShareListResponse__PluginSharePrincipal), Schema.Null]), + -- ), + -- shareUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ source: V2PluginReadResponse__PluginSource, + - }); + - + - export type V2RawResponseItemCompletedNotification__FunctionCallOutputBody = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__TurnError = Schema.Struct({ + - + - export type V2ReviewStartResponse__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ReviewStartResponse__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ReviewStartResponse__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ReviewStartResponse__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ReviewStartResponse__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ReviewStartResponse__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ReviewStartResponse__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ReviewStartResponse__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ReviewStartResponse__ThreadItem = + - readonly reasoningEffort?: V2ReviewStartResponse__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ReviewStartResponse__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ReviewStartResponse__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ReviewStartResponse__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ReviewStartResponse__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ReviewStartResponse__ThreadItem = + - export const V2ReviewStartResponse__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ReviewStartResponse__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ReviewStartResponse__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__ThreadItem = Schema.Union( + - Schema.Union([V2ReviewStartResponse__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ReviewStartResponse__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ReviewStartResponse__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ReviewStartResponse__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ReviewStartResponse__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ReviewStartResponse__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ReviewStartResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2SkillsListResponse__SkillMetadata = { + - readonly enabled: boolean; + - readonly interface?: V2SkillsListResponse__SkillInterface | null; + - readonly name: string; + -- readonly path: V2SkillsListResponse__AbsolutePathBuf; + -+ readonly path: string; + - readonly scope: V2SkillsListResponse__SkillScope; + - readonly shortDescription?: string | null; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2SkillsListResponse__SkillMetadata = Schema.Struct({ + - enabled: Schema.Boolean, + - interface: Schema.optionalKey(Schema.Union([V2SkillsListResponse__SkillInterface, Schema.Null])), + - name: Schema.String, + -- path: V2SkillsListResponse__AbsolutePathBuf, + -+ path: Schema.String, + - scope: V2SkillsListResponse__SkillScope, + - shortDescription: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__TurnError = Schema.Struct({ + - + - export type V2ThreadForkResponse__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkResponse__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ThreadForkResponse__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ThreadForkResponse__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ThreadForkResponse__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ThreadForkResponse__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkResponse__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ThreadForkResponse__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkResponse__ThreadItem = + - readonly reasoningEffort?: V2ThreadForkResponse__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ThreadForkResponse__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ThreadForkResponse__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ThreadForkResponse__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ThreadForkResponse__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkResponse__ThreadItem = + - export const V2ThreadForkResponse__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ThreadForkResponse__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ThreadForkResponse__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__ThreadItem = Schema.Union( + - Schema.Union([V2ThreadForkResponse__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ThreadForkResponse__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ThreadForkResponse__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ThreadForkResponse__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ThreadForkResponse__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ThreadForkResponse__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ThreadForkResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__TurnError = Schema.Struct({ + - + - export type V2ThreadListResponse__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadListResponse__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ThreadListResponse__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ThreadListResponse__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ThreadListResponse__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ThreadListResponse__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadListResponse__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ThreadListResponse__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadListResponse__ThreadItem = + - readonly reasoningEffort?: V2ThreadListResponse__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ThreadListResponse__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ThreadListResponse__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ThreadListResponse__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ThreadListResponse__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadListResponse__ThreadItem = + - export const V2ThreadListResponse__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ThreadListResponse__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ThreadListResponse__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__ThreadItem = Schema.Union( + - Schema.Union([V2ThreadListResponse__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ThreadListResponse__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ThreadListResponse__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ThreadListResponse__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ThreadListResponse__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ThreadListResponse__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ThreadListResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__TurnError = Schema.Struct({ + - + - export type V2ThreadMetadataUpdateResponse__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadMetadataUpdateResponse__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ThreadMetadataUpdateResponse__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ThreadMetadataUpdateResponse__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ThreadMetadataUpdateResponse__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ThreadMetadataUpdateResponse__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadMetadataUpdateResponse__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ThreadMetadataUpdateResponse__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadMetadataUpdateResponse__ThreadItem = + - readonly reasoningEffort?: V2ThreadMetadataUpdateResponse__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ThreadMetadataUpdateResponse__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ThreadMetadataUpdateResponse__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ThreadMetadataUpdateResponse__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ThreadMetadataUpdateResponse__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadMetadataUpdateResponse__ThreadItem = + - export const V2ThreadMetadataUpdateResponse__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ThreadMetadataUpdateResponse__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ThreadMetadataUpdateResponse__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__ThreadItem = Schema.Union( + - Schema.Union([V2ThreadMetadataUpdateResponse__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ThreadMetadataUpdateResponse__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ThreadMetadataUpdateResponse__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ThreadMetadataUpdateResponse__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ThreadMetadataUpdateResponse__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ThreadMetadataUpdateResponse__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ThreadMetadataUpdateResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__TurnError = Schema.Struct({ + - + - export type V2ThreadReadResponse__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadReadResponse__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ThreadReadResponse__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ThreadReadResponse__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ThreadReadResponse__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ThreadReadResponse__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadReadResponse__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ThreadReadResponse__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadReadResponse__ThreadItem = + - readonly reasoningEffort?: V2ThreadReadResponse__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ThreadReadResponse__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ThreadReadResponse__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ThreadReadResponse__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ThreadReadResponse__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadReadResponse__ThreadItem = + - export const V2ThreadReadResponse__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ThreadReadResponse__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ThreadReadResponse__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__ThreadItem = Schema.Union( + - Schema.Union([V2ThreadReadResponse__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ThreadReadResponse__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ThreadReadResponse__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ThreadReadResponse__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ThreadReadResponse__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ThreadReadResponse__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ThreadReadResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__TurnError = Schema.Struct({ + - + - export type V2ThreadResumeResponse__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeResponse__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ThreadResumeResponse__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ThreadResumeResponse__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ThreadResumeResponse__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ThreadResumeResponse__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeResponse__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ThreadResumeResponse__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeResponse__ThreadItem = + - readonly reasoningEffort?: V2ThreadResumeResponse__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ThreadResumeResponse__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ThreadResumeResponse__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ThreadResumeResponse__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ThreadResumeResponse__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeResponse__ThreadItem = + - export const V2ThreadResumeResponse__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ThreadResumeResponse__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeResponse__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__ThreadItem = Schema.Union( + - Schema.Union([V2ThreadResumeResponse__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ThreadResumeResponse__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ThreadResumeResponse__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ThreadResumeResponse__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ThreadResumeResponse__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ThreadResumeResponse__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__TurnError = Schema.Struct({ + - + - export type V2ThreadRollbackResponse__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadRollbackResponse__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ThreadRollbackResponse__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ThreadRollbackResponse__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ThreadRollbackResponse__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ThreadRollbackResponse__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadRollbackResponse__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ThreadRollbackResponse__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadRollbackResponse__ThreadItem = + - readonly reasoningEffort?: V2ThreadRollbackResponse__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ThreadRollbackResponse__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ThreadRollbackResponse__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ThreadRollbackResponse__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ThreadRollbackResponse__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadRollbackResponse__ThreadItem = + - export const V2ThreadRollbackResponse__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ThreadRollbackResponse__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ThreadRollbackResponse__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__ThreadItem = Schema.Union( + - Schema.Union([V2ThreadRollbackResponse__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ThreadRollbackResponse__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ThreadRollbackResponse__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ThreadRollbackResponse__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ThreadRollbackResponse__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ThreadRollbackResponse__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ThreadRollbackResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__ThreadItem = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadSettingsUpdatedNotification__CollaborationMode = { + -- readonly mode: V2ThreadSettingsUpdatedNotification__ModeKind; + -- readonly settings: V2ThreadSettingsUpdatedNotification__Settings; + --}; + --export const V2ThreadSettingsUpdatedNotification__CollaborationMode = Schema.Struct({ + -- mode: V2ThreadSettingsUpdatedNotification__ModeKind, + -- settings: V2ThreadSettingsUpdatedNotification__Settings, + --}).annotate({ description: "Collaboration mode for a Codex session." }); + -- + - export type V2ThreadStartedNotification__TurnError = { + - readonly additionalDetails?: string | null; + - readonly codexErrorInfo?: V2ThreadStartedNotification__CodexErrorInfo | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__TurnError = Schema.Struct({ + - + - export type V2ThreadStartedNotification__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartedNotification__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ThreadStartedNotification__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ThreadStartedNotification__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ThreadStartedNotification__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ThreadStartedNotification__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartedNotification__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ThreadStartedNotification__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartedNotification__ThreadItem = + - readonly reasoningEffort?: V2ThreadStartedNotification__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ThreadStartedNotification__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ThreadStartedNotification__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ThreadStartedNotification__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ThreadStartedNotification__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartedNotification__ThreadItem = + - export const V2ThreadStartedNotification__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ThreadStartedNotification__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ThreadStartedNotification__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__ThreadItem = Schema.Union( + - Schema.Union([V2ThreadStartedNotification__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ThreadStartedNotification__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ThreadStartedNotification__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ThreadStartedNotification__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ThreadStartedNotification__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ThreadStartedNotification__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ThreadStartedNotification__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__TurnError = Schema.Struct({ + - + - export type V2ThreadStartResponse__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartResponse__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ThreadStartResponse__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ThreadStartResponse__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ThreadStartResponse__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ThreadStartResponse__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartResponse__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ThreadStartResponse__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartResponse__ThreadItem = + - readonly reasoningEffort?: V2ThreadStartResponse__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ThreadStartResponse__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ThreadStartResponse__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ThreadStartResponse__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ThreadStartResponse__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartResponse__ThreadItem = + - export const V2ThreadStartResponse__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ThreadStartResponse__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ThreadStartResponse__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__ThreadItem = Schema.Union( + - Schema.Union([V2ThreadStartResponse__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ThreadStartResponse__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ThreadStartResponse__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ThreadStartResponse__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ThreadStartResponse__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ThreadStartResponse__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ThreadStartResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__TurnError = Schema.Struct({ + - + - export type V2ThreadUnarchiveResponse__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadUnarchiveResponse__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2ThreadUnarchiveResponse__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2ThreadUnarchiveResponse__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2ThreadUnarchiveResponse__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2ThreadUnarchiveResponse__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadUnarchiveResponse__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2ThreadUnarchiveResponse__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadUnarchiveResponse__ThreadItem = + - readonly reasoningEffort?: V2ThreadUnarchiveResponse__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2ThreadUnarchiveResponse__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2ThreadUnarchiveResponse__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2ThreadUnarchiveResponse__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2ThreadUnarchiveResponse__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadUnarchiveResponse__ThreadItem = + - export const V2ThreadUnarchiveResponse__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2ThreadUnarchiveResponse__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2ThreadUnarchiveResponse__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__ThreadItem = Schema.Union( + - Schema.Union([V2ThreadUnarchiveResponse__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2ThreadUnarchiveResponse__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2ThreadUnarchiveResponse__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2ThreadUnarchiveResponse__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2ThreadUnarchiveResponse__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2ThreadUnarchiveResponse__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2ThreadUnarchiveResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__TurnError = Schema.Struct({ + - + - export type V2TurnCompletedNotification__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnCompletedNotification__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2TurnCompletedNotification__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2TurnCompletedNotification__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2TurnCompletedNotification__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2TurnCompletedNotification__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnCompletedNotification__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2TurnCompletedNotification__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnCompletedNotification__ThreadItem = + - readonly reasoningEffort?: V2TurnCompletedNotification__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2TurnCompletedNotification__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2TurnCompletedNotification__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2TurnCompletedNotification__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2TurnCompletedNotification__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnCompletedNotification__ThreadItem = + - export const V2TurnCompletedNotification__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2TurnCompletedNotification__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2TurnCompletedNotification__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__ThreadItem = Schema.Union( + - Schema.Union([V2TurnCompletedNotification__McpToolCallError, Schema.Null]), + - ), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2TurnCompletedNotification__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2TurnCompletedNotification__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2TurnCompletedNotification__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey( + - Schema.Union([V2TurnCompletedNotification__WebSearchAction, Schema.Null]), + - ), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -+ type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + -+ }).annotate({ title: "WebSearchThreadItem" }), + -+ Schema.Struct({ + -+ id: Schema.String, + -+ path: Schema.String, + -+ type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + -+ }).annotate({ title: "ImageViewThreadItem" }), + -+ Schema.Struct({ + -+ id: Schema.String, + -+ result: Schema.String, + -+ revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ status: Schema.String, + -+ type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + -+ }).annotate({ title: "ImageGenerationThreadItem" }), + -+ Schema.Struct({ + -+ id: Schema.String, + -+ review: Schema.String, + -+ type: Schema.Literal("enteredReviewMode").annotate({ + -+ title: "EnteredReviewModeThreadItemType", + -+ }), + -+ }).annotate({ title: "EnteredReviewModeThreadItem" }), + -+ Schema.Struct({ + -+ id: Schema.String, + -+ review: Schema.String, + -+ type: Schema.Literal("exitedReviewMode").annotate({ + -+ title: "ExitedReviewModeThreadItemType", + -+ }), + -+ }).annotate({ title: "ExitedReviewModeThreadItem" }), + -+ Schema.Struct({ + -+ id: Schema.String, + -+ type: Schema.Literal("contextCompaction").annotate({ + -+ title: "ContextCompactionThreadItemType", + -+ }), + -+ }).annotate({ title: "ContextCompactionThreadItem" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + -+export type V2TurnStartedNotification__TurnError = { + -+ readonly additionalDetails?: string | null; + -+ readonly codexErrorInfo?: V2TurnStartedNotification__CodexErrorInfo | null; + -+ readonly message: string; + -+}; + -+export const V2TurnStartedNotification__TurnError = Schema.Struct({ + -+ additionalDetails: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ codexErrorInfo: Schema.optionalKey( + -+ Schema.Union([V2TurnStartedNotification__CodexErrorInfo, Schema.Null]), + -+ ), + -+ message: Schema.String, + -+}); + -+ + -+export type V2TurnStartedNotification__ThreadItem = + -+ | { + -+ readonly content: ReadonlyArray; + -+ readonly id: string; + -+ readonly type: "userMessage"; + -+ } + -+ | { + -+ readonly fragments: ReadonlyArray; + -+ readonly id: string; + -+ readonly type: "hookPrompt"; + -+ } + -+ | { + -+ readonly id: string; + -+ readonly memoryCitation?: V2TurnStartedNotification__MemoryCitation | null; + -+ readonly phase?: V2TurnStartedNotification__MessagePhase | null; + -+ readonly text: string; + -+ readonly type: "agentMessage"; + -+ } + -+ | { readonly id: string; readonly text: string; readonly type: "plan" } + -+ | { + -+ readonly content?: ReadonlyArray; + -+ readonly id: string; + -+ readonly summary?: ReadonlyArray; + -+ readonly type: "reasoning"; + -+ } + -+ | { + -+ readonly aggregatedOutput?: string | null; + -+ readonly command: string; + -+ readonly commandActions: ReadonlyArray; + -+ readonly cwd: string; + -+ readonly durationMs?: number | null; + -+ readonly exitCode?: number | null; + -+ readonly id: string; + -+ readonly processId?: string | null; + -+ readonly source?: "agent" | "userShell" | "unifiedExecStartup" | "unifiedExecInteraction"; + -+ readonly status: V2TurnStartedNotification__CommandExecutionStatus; + -+ readonly type: "commandExecution"; + -+ } + -+ | { + -+ readonly changes: ReadonlyArray; + -+ readonly id: string; + -+ readonly status: V2TurnStartedNotification__PatchApplyStatus; + -+ readonly type: "fileChange"; + -+ } + -+ | { + -+ readonly arguments: unknown; + -+ readonly durationMs?: number | null; + -+ readonly error?: V2TurnStartedNotification__McpToolCallError | null; + -+ readonly id: string; + -+ readonly result?: V2TurnStartedNotification__McpToolCallResult | null; + -+ readonly server: string; + -+ readonly status: V2TurnStartedNotification__McpToolCallStatus; + -+ readonly tool: string; + -+ readonly type: "mcpToolCall"; + -+ } + -+ | { + -+ readonly arguments: unknown; + -+ readonly contentItems?: ReadonlyArray | null; + -+ readonly durationMs?: number | null; + -+ readonly id: string; + -+ readonly status: V2TurnStartedNotification__DynamicToolCallStatus; + -+ readonly success?: boolean | null; + -+ readonly tool: string; + -+ readonly type: "dynamicToolCall"; + -+ } + -+ | { + -+ readonly agentsStates: { readonly [x: string]: V2TurnStartedNotification__CollabAgentState }; + -+ readonly id: string; + -+ readonly model?: string | null; + -+ readonly prompt?: string | null; + -+ readonly reasoningEffort?: V2TurnStartedNotification__ReasoningEffort | null; + -+ readonly receiverThreadIds: ReadonlyArray; + -+ readonly senderThreadId: string; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + -+ readonly type: "collabAgentToolCall"; + -+ } + -+ | { + -+ readonly action?: V2TurnStartedNotification__WebSearchAction | null; + -+ readonly id: string; + -+ readonly query: string; + -+ readonly type: "webSearch"; + -+ } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + -+ | { + -+ readonly id: string; + -+ readonly result: string; + -+ readonly revisedPrompt?: string | null; + -+ readonly savedPath?: string | null; + -+ readonly status: string; + -+ readonly type: "imageGeneration"; + -+ } + -+ | { readonly id: string; readonly review: string; readonly type: "enteredReviewMode" } + -+ | { readonly id: string; readonly review: string; readonly type: "exitedReviewMode" } + -+ | { readonly id: string; readonly type: "contextCompaction" }; + -+export const V2TurnStartedNotification__ThreadItem = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ content: Schema.Array(V2TurnStartedNotification__UserInput), + -+ id: Schema.String, + -+ type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -+ }).annotate({ title: "UserMessageThreadItem" }), + -+ Schema.Struct({ + -+ fragments: Schema.Array(V2TurnStartedNotification__HookPromptFragment), + -+ id: Schema.String, + -+ type: Schema.Literal("hookPrompt").annotate({ title: "HookPromptThreadItemType" }), + -+ }).annotate({ title: "HookPromptThreadItem" }), + -+ Schema.Struct({ + -+ id: Schema.String, + -+ memoryCitation: Schema.optionalKey( + -+ Schema.Union([V2TurnStartedNotification__MemoryCitation, Schema.Null]), + -+ ), + -+ phase: Schema.optionalKey( + -+ Schema.Union([V2TurnStartedNotification__MessagePhase, Schema.Null]), + -+ ), + -+ text: Schema.String, + -+ type: Schema.Literal("agentMessage").annotate({ title: "AgentMessageThreadItemType" }), + -+ }).annotate({ title: "AgentMessageThreadItem" }), + -+ Schema.Struct({ + -+ id: Schema.String, + -+ text: Schema.String, + -+ type: Schema.Literal("plan").annotate({ title: "PlanThreadItemType" }), + -+ }).annotate({ + -+ title: "PlanThreadItem", + -+ description: + -+ "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.", + -+ }), + -+ Schema.Struct({ + -+ content: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + -+ id: Schema.String, + -+ summary: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + -+ type: Schema.Literal("reasoning").annotate({ title: "ReasoningThreadItemType" }), + -+ }).annotate({ title: "ReasoningThreadItem" }), + -+ Schema.Struct({ + -+ aggregatedOutput: Schema.optionalKey( + - Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -+ Schema.String.annotate({ + -+ description: "The command's output, aggregated from stdout and stderr.", + - }), + - Schema.Null, + - ]), + - ), + -+ command: Schema.String.annotate({ description: "The command to be executed." }), + -+ commandActions: Schema.Array(V2TurnStartedNotification__CommandAction).annotate({ + -+ description: + -+ "A best-effort parsing of the command to understand the action(s) it will perform. This returns a list of CommandAction objects because a single shell command may be composed of many commands piped together.", + -+ }), + -+ cwd: Schema.String.annotate({ description: "The command's working directory." }), + -+ durationMs: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.Number.annotate({ + -+ description: "The duration of the command execution in milliseconds.", + -+ format: "int64", + -+ }).check(Schema.isInt()), + -+ Schema.Null, + -+ ]), + -+ ), + -+ exitCode: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.Number.annotate({ + -+ description: "The command's exit code.", + -+ format: "int32", + -+ }).check(Schema.isInt()), + -+ Schema.Null, + -+ ]), + -+ ), + -+ id: Schema.String, + -+ processId: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ + -+ description: "Identifier for the underlying PTY process (when available).", + -+ }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ source: Schema.optionalKey( + -+ Schema.Literals([ + -+ "agent", + -+ "userShell", + -+ "unifiedExecStartup", + -+ "unifiedExecInteraction", + -+ ]).annotate({ default: "agent" }), + -+ ), + -+ status: V2TurnStartedNotification__CommandExecutionStatus, + -+ type: Schema.Literal("commandExecution").annotate({ + -+ title: "CommandExecutionThreadItemType", + -+ }), + -+ }).annotate({ title: "CommandExecutionThreadItem" }), + -+ Schema.Struct({ + -+ changes: Schema.Array(V2TurnStartedNotification__FileUpdateChange), + -+ id: Schema.String, + -+ status: V2TurnStartedNotification__PatchApplyStatus, + -+ type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + -+ }).annotate({ title: "FileChangeThreadItem" }), + -+ Schema.Struct({ + -+ arguments: Schema.Unknown, + -+ durationMs: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.Number.annotate({ + -+ description: "The duration of the MCP tool call in milliseconds.", + -+ format: "int64", + -+ }).check(Schema.isInt()), + -+ Schema.Null, + -+ ]), + -+ ), + -+ error: Schema.optionalKey( + -+ Schema.Union([V2TurnStartedNotification__McpToolCallError, Schema.Null]), + -+ ), + -+ id: Schema.String, + -+ result: Schema.optionalKey( + -+ Schema.Union([V2TurnStartedNotification__McpToolCallResult, Schema.Null]), + -+ ), + -+ server: Schema.String, + -+ status: V2TurnStartedNotification__McpToolCallStatus, + -+ tool: Schema.String, + -+ type: Schema.Literal("mcpToolCall").annotate({ title: "McpToolCallThreadItemType" }), + -+ }).annotate({ title: "McpToolCallThreadItem" }), + -+ Schema.Struct({ + -+ arguments: Schema.Unknown, + -+ contentItems: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.Array(V2TurnStartedNotification__DynamicToolCallOutputContentItem), + -+ Schema.Null, + -+ ]), + -+ ), + -+ durationMs: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.Number.annotate({ + -+ description: "The duration of the dynamic tool call in milliseconds.", + -+ format: "int64", + -+ }).check(Schema.isInt()), + -+ Schema.Null, + -+ ]), + -+ ), + -+ id: Schema.String, + -+ status: V2TurnStartedNotification__DynamicToolCallStatus, + -+ success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + -+ tool: Schema.String, + -+ type: Schema.Literal("dynamicToolCall").annotate({ title: "DynamicToolCallThreadItemType" }), + -+ }).annotate({ title: "DynamicToolCallThreadItem" }), + -+ Schema.Struct({ + -+ agentsStates: Schema.Record( + -+ Schema.String, + -+ V2TurnStartedNotification__CollabAgentState, + -+ ).annotate({ description: "Last known status of the target agents, when available." }), + -+ id: Schema.String.annotate({ description: "Unique identifier for this collab tool call." }), + -+ model: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ + -+ description: "Model requested for the spawned agent, when applicable.", + -+ }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ prompt: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ + -+ description: "Prompt text sent as part of the collab tool call, when available.", + -+ }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ reasoningEffort: Schema.optionalKey( + -+ Schema.Union([V2TurnStartedNotification__ReasoningEffort, Schema.Null]).annotate({ + -+ description: "Reasoning effort requested for the spawned agent, when applicable.", + -+ }), + -+ ), + -+ receiverThreadIds: Schema.Array(Schema.String).annotate({ + -+ description: + -+ "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.", + -+ }), + -+ senderThreadId: Schema.String.annotate({ + -+ description: "Thread ID of the agent issuing the collab request.", + -+ }), + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + -+ description: "Current status of the collab tool call.", + -+ }), + -+ tool: Schema.Literals([ + -+ "spawnAgent", + -+ "sendInput", + -+ "resumeAgent", + -+ "wait", + -+ "closeAgent", + -+ ]).annotate({ description: "Name of the collab tool that was invoked." }), + -+ type: Schema.Literal("collabAgentToolCall").annotate({ + -+ title: "CollabAgentToolCallThreadItemType", + -+ }), + -+ }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -+ Schema.Struct({ + -+ action: Schema.optionalKey( + -+ Schema.Union([V2TurnStartedNotification__WebSearchAction, Schema.Null]), + -+ ), + -+ id: Schema.String, + -+ query: Schema.String, + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2TurnCompletedNotification__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2TurnCompletedNotification__AbsolutePathBuf, Schema.Null]), + -- ), + -- status: Schema.String, + -- type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + -- }).annotate({ title: "ImageGenerationThreadItem" }), + -- Schema.Struct({ + -- id: Schema.String, + -- review: Schema.String, + -- type: Schema.Literal("enteredReviewMode").annotate({ + -- title: "EnteredReviewModeThreadItemType", + -- }), + -- }).annotate({ title: "EnteredReviewModeThreadItem" }), + -- Schema.Struct({ + -- id: Schema.String, + -- review: Schema.String, + -- type: Schema.Literal("exitedReviewMode").annotate({ + -- title: "ExitedReviewModeThreadItemType", + -- }), + -- }).annotate({ title: "ExitedReviewModeThreadItem" }), + -- Schema.Struct({ + -- id: Schema.String, + -- type: Schema.Literal("contextCompaction").annotate({ + -- title: "ContextCompactionThreadItemType", + -- }), + -- }).annotate({ title: "ContextCompactionThreadItem" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type V2TurnStartedNotification__TurnError = { + -- readonly additionalDetails?: string | null; + -- readonly codexErrorInfo?: V2TurnStartedNotification__CodexErrorInfo | null; + -- readonly message: string; + --}; + --export const V2TurnStartedNotification__TurnError = Schema.Struct({ + -- additionalDetails: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- codexErrorInfo: Schema.optionalKey( + -- Schema.Union([V2TurnStartedNotification__CodexErrorInfo, Schema.Null]), + -- ), + -- message: Schema.String, + --}); + -- + --export type V2TurnStartedNotification__ThreadItem = + -- | { + -- readonly clientId?: string | null; + -- readonly content: ReadonlyArray; + -- readonly id: string; + -- readonly type: "userMessage"; + -- } + -- | { + -- readonly fragments: ReadonlyArray; + -- readonly id: string; + -- readonly type: "hookPrompt"; + -- } + -- | { + -- readonly id: string; + -- readonly memoryCitation?: V2TurnStartedNotification__MemoryCitation | null; + -- readonly phase?: V2TurnStartedNotification__MessagePhase | null; + -- readonly text: string; + -- readonly type: "agentMessage"; + -- } + -- | { readonly id: string; readonly text: string; readonly type: "plan" } + -- | { + -- readonly content?: ReadonlyArray; + -- readonly id: string; + -- readonly summary?: ReadonlyArray; + -- readonly type: "reasoning"; + -- } + -- | { + -- readonly aggregatedOutput?: string | null; + -- readonly command: string; + -- readonly commandActions: ReadonlyArray; + -- readonly cwd: string; + -- readonly durationMs?: number | null; + -- readonly exitCode?: number | null; + -- readonly id: string; + -- readonly processId?: string | null; + -- readonly source?: "agent" | "userShell" | "unifiedExecStartup" | "unifiedExecInteraction"; + -- readonly status: V2TurnStartedNotification__CommandExecutionStatus; + -- readonly type: "commandExecution"; + -- } + -- | { + -- readonly changes: ReadonlyArray; + -- readonly id: string; + -- readonly status: V2TurnStartedNotification__PatchApplyStatus; + -- readonly type: "fileChange"; + -- } + -- | { + -- readonly appContext?: V2TurnStartedNotification__McpToolCallAppContext | null; + -- readonly arguments: unknown; + -- readonly durationMs?: number | null; + -- readonly error?: V2TurnStartedNotification__McpToolCallError | null; + -- readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + -- readonly result?: V2TurnStartedNotification__McpToolCallResult | null; + -- readonly server: string; + -- readonly status: V2TurnStartedNotification__McpToolCallStatus; + -- readonly tool: string; + -- readonly type: "mcpToolCall"; + -- } + -- | { + -- readonly arguments: unknown; + -- readonly contentItems?: ReadonlyArray | null; + -- readonly durationMs?: number | null; + -- readonly id: string; + -- readonly namespace?: string | null; + -- readonly status: V2TurnStartedNotification__DynamicToolCallStatus; + -- readonly success?: boolean | null; + -- readonly tool: string; + -- readonly type: "dynamicToolCall"; + -- } + -- | { + -- readonly agentsStates: { readonly [x: string]: V2TurnStartedNotification__CollabAgentState }; + -- readonly id: string; + -- readonly model?: string | null; + -- readonly prompt?: string | null; + -- readonly reasoningEffort?: V2TurnStartedNotification__ReasoningEffort | null; + -- readonly receiverThreadIds: ReadonlyArray; + -- readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -- readonly type: "collabAgentToolCall"; + -- } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2TurnStartedNotification__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + -- | { + -- readonly action?: V2TurnStartedNotification__WebSearchAction | null; + -- readonly id: string; + -- readonly query: string; + -- readonly results?: ReadonlyArray | null; + -- readonly type: "webSearch"; + -- } + -- | { + -- readonly id: string; + -- readonly path: V2TurnStartedNotification__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -- | { + -- readonly id: string; + -- readonly result: string; + -- readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2TurnStartedNotification__AbsolutePathBuf | null; + -- readonly status: string; + -- readonly type: "imageGeneration"; + -- } + -- | { readonly id: string; readonly review: string; readonly type: "enteredReviewMode" } + -- | { readonly id: string; readonly review: string; readonly type: "exitedReviewMode" } + -- | { readonly id: string; readonly type: "contextCompaction" }; + --export const V2TurnStartedNotification__ThreadItem = Schema.Union( + -- [ + -- Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- content: Schema.Array(V2TurnStartedNotification__UserInput), + -- id: Schema.String, + -- type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -- }).annotate({ title: "UserMessageThreadItem" }), + -- Schema.Struct({ + -- fragments: Schema.Array(V2TurnStartedNotification__HookPromptFragment), + -- id: Schema.String, + -- type: Schema.Literal("hookPrompt").annotate({ title: "HookPromptThreadItemType" }), + -- }).annotate({ title: "HookPromptThreadItem" }), + -- Schema.Struct({ + -- id: Schema.String, + -- memoryCitation: Schema.optionalKey( + -- Schema.Union([V2TurnStartedNotification__MemoryCitation, Schema.Null]), + -- ), + -- phase: Schema.optionalKey( + -- Schema.Union([V2TurnStartedNotification__MessagePhase, Schema.Null]), + -- ), + -- text: Schema.String, + -- type: Schema.Literal("agentMessage").annotate({ title: "AgentMessageThreadItemType" }), + -- }).annotate({ title: "AgentMessageThreadItem" }), + -- Schema.Struct({ + -- id: Schema.String, + -- text: Schema.String, + -- type: Schema.Literal("plan").annotate({ title: "PlanThreadItemType" }), + -- }).annotate({ + -- title: "PlanThreadItem", + -- description: + -- "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.", + -- }), + -- Schema.Struct({ + -- content: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + -- id: Schema.String, + -- summary: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + -- type: Schema.Literal("reasoning").annotate({ title: "ReasoningThreadItemType" }), + -- }).annotate({ title: "ReasoningThreadItem" }), + -- Schema.Struct({ + -- aggregatedOutput: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "The command's output, aggregated from stdout and stderr.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- command: Schema.String.annotate({ description: "The command to be executed." }), + -- commandActions: Schema.Array(V2TurnStartedNotification__CommandAction).annotate({ + -- description: + -- "A best-effort parsing of the command to understand the action(s) it will perform. This returns a list of CommandAction objects because a single shell command may be composed of many commands piped together.", + -- }), + -- cwd: Schema.String.annotate({ description: "The command's working directory." }), + -- durationMs: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "The duration of the command execution in milliseconds.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- exitCode: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "The command's exit code.", + -- format: "int32", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- id: Schema.String, + -- processId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Identifier for the underlying PTY process (when available).", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- source: Schema.optionalKey( + -- Schema.Literals([ + -- "agent", + -- "userShell", + -- "unifiedExecStartup", + -- "unifiedExecInteraction", + -- ]).annotate({ default: "agent" }), + -- ), + -- status: V2TurnStartedNotification__CommandExecutionStatus, + -- type: Schema.Literal("commandExecution").annotate({ + -- title: "CommandExecutionThreadItemType", + -- }), + -- }).annotate({ title: "CommandExecutionThreadItem" }), + -- Schema.Struct({ + -- changes: Schema.Array(V2TurnStartedNotification__FileUpdateChange), + -- id: Schema.String, + -- status: V2TurnStartedNotification__PatchApplyStatus, + -- type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + -- }).annotate({ title: "FileChangeThreadItem" }), + -- Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2TurnStartedNotification__McpToolCallAppContext, Schema.Null]), + -- ), + -- arguments: Schema.Unknown, + -- durationMs: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "The duration of the MCP tool call in milliseconds.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- error: Schema.optionalKey( + -- Schema.Union([V2TurnStartedNotification__McpToolCallError, Schema.Null]), + -- ), + -- id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- result: Schema.optionalKey( + -- Schema.Union([V2TurnStartedNotification__McpToolCallResult, Schema.Null]), + -- ), + -- server: Schema.String, + -- status: V2TurnStartedNotification__McpToolCallStatus, + -- tool: Schema.String, + -- type: Schema.Literal("mcpToolCall").annotate({ title: "McpToolCallThreadItemType" }), + -- }).annotate({ title: "McpToolCallThreadItem" }), + -- Schema.Struct({ + -- arguments: Schema.Unknown, + -- contentItems: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(V2TurnStartedNotification__DynamicToolCallOutputContentItem), + -- Schema.Null, + -- ]), + -- ), + -- durationMs: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "The duration of the dynamic tool call in milliseconds.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- status: V2TurnStartedNotification__DynamicToolCallStatus, + -- success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + -- tool: Schema.String, + -- type: Schema.Literal("dynamicToolCall").annotate({ title: "DynamicToolCallThreadItemType" }), + -- }).annotate({ title: "DynamicToolCallThreadItem" }), + -- Schema.Struct({ + -- agentsStates: Schema.Record( + -- Schema.String, + -- V2TurnStartedNotification__CollabAgentState, + -- ).annotate({ description: "Last known status of the target agents, when available." }), + -- id: Schema.String.annotate({ description: "Unique identifier for this collab tool call." }), + -- model: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Model requested for the spawned agent, when applicable.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- prompt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Prompt text sent as part of the collab tool call, when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- reasoningEffort: Schema.optionalKey( + -- Schema.Union([V2TurnStartedNotification__ReasoningEffort, Schema.Null]).annotate({ + -- description: "Reasoning effort requested for the spawned agent, when applicable.", + -- }), + -- ), + -- receiverThreadIds: Schema.Array(Schema.String).annotate({ + -- description: + -- "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.", + -- }), + -- senderThreadId: Schema.String.annotate({ + -- description: "Thread ID of the agent issuing the collab request.", + -- }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -- description: "Current status of the collab tool call.", + -- }), + -- tool: Schema.Literals([ + -- "spawnAgent", + -- "sendInput", + -- "resumeAgent", + -- "wait", + -- "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + -- ]).annotate({ description: "Name of the collab tool that was invoked." }), + -- type: Schema.Literal("collabAgentToolCall").annotate({ + -- title: "CollabAgentToolCallThreadItemType", + -- }), + -- }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2TurnStartedNotification__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + -- Schema.Struct({ + -- action: Schema.optionalKey( + -- Schema.Union([V2TurnStartedNotification__WebSearchAction, Schema.Null]), + -- ), + -- id: Schema.String, + -- query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + -- }).annotate({ title: "WebSearchThreadItem" }), + -- Schema.Struct({ + -- id: Schema.String, + -- path: V2TurnStartedNotification__LegacyAppPathString, + -- type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + -- }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + -- Schema.Struct({ + -- id: Schema.String, + -- result: Schema.String, + -- revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2TurnStartedNotification__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__TurnError = Schema.Struct({ + - + - export type V2TurnStartResponse__ThreadItem = + - | { + -- readonly clientId?: string | null; + - readonly content: ReadonlyArray; + - readonly id: string; + - readonly type: "userMessage"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartResponse__ThreadItem = + - readonly type: "fileChange"; + - } + - | { + -- readonly appContext?: V2TurnStartResponse__McpToolCallAppContext | null; + - readonly arguments: unknown; + - readonly durationMs?: number | null; + - readonly error?: V2TurnStartResponse__McpToolCallError | null; + - readonly id: string; + -- readonly mcpAppResourceUri?: string | null; + -- readonly pluginId?: string | null; + - readonly result?: V2TurnStartResponse__McpToolCallResult | null; + - readonly server: string; + - readonly status: V2TurnStartResponse__McpToolCallStatus; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartResponse__ThreadItem = + - readonly contentItems?: ReadonlyArray | null; + - readonly durationMs?: number | null; + - readonly id: string; + -- readonly namespace?: string | null; + - readonly status: V2TurnStartResponse__DynamicToolCallStatus; + - readonly success?: boolean | null; + - readonly tool: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartResponse__ThreadItem = + - readonly reasoningEffort?: V2TurnStartResponse__ReasoningEffort | null; + - readonly receiverThreadIds: ReadonlyArray; + - readonly senderThreadId: string; + -- readonly status: "inProgress" | "completed" | "failed" | "interrupted"; + -- readonly tool: + -- | "spawnAgent" + -- | "sendInput" + -- | "resumeAgent" + -- | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ readonly status: "inProgress" | "completed" | "failed"; + -+ readonly tool: "spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"; + - readonly type: "collabAgentToolCall"; + - } + -- | { + -- readonly agentPath: string; + -- readonly agentThreadId: string; + -- readonly id: string; + -- readonly kind: V2TurnStartResponse__SubAgentActivityKind; + -- readonly type: "subAgentActivity"; + -- } + - | { + - readonly action?: V2TurnStartResponse__WebSearchAction | null; + - readonly id: string; + - readonly query: string; + -- readonly results?: ReadonlyArray | null; + - readonly type: "webSearch"; + - } + -- | { + -- readonly id: string; + -- readonly path: V2TurnStartResponse__LegacyAppPathString; + -- readonly type: "imageView"; + -- } + -- | { readonly durationMs: number; readonly id: string; readonly type: "sleep" } + -+ | { readonly id: string; readonly path: string; readonly type: "imageView" } + - | { + - readonly id: string; + - readonly result: string; + - readonly revisedPrompt?: string | null; + -- readonly savedPath?: V2TurnStartResponse__AbsolutePathBuf | null; + -+ readonly savedPath?: string | null; + - readonly status: string; + - readonly type: "imageGeneration"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartResponse__ThreadItem = + - export const V2TurnStartResponse__ThreadItem = Schema.Union( + - [ + - Schema.Struct({ + -- clientId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - content: Schema.Array(V2TurnStartResponse__UserInput), + - id: Schema.String, + - type: Schema.Literal("userMessage").annotate({ title: "UserMessageThreadItemType" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__ThreadItem = Schema.Union( + - type: Schema.Literal("fileChange").annotate({ title: "FileChangeThreadItemType" }), + - }).annotate({ title: "FileChangeThreadItem" }), + - Schema.Struct({ + -- appContext: Schema.optionalKey( + -- Schema.Union([V2TurnStartResponse__McpToolCallAppContext, Schema.Null]), + -- ), + - arguments: Schema.Unknown, + - durationMs: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__ThreadItem = Schema.Union( + - ), + - error: Schema.optionalKey(Schema.Union([V2TurnStartResponse__McpToolCallError, Schema.Null])), + - id: Schema.String, + -- mcpAppResourceUri: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Deprecated: use `appContext.resourceUri` instead.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- pluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - result: Schema.optionalKey( + - Schema.Union([V2TurnStartResponse__McpToolCallResult, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__ThreadItem = Schema.Union( + - ]), + - ), + - id: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: V2TurnStartResponse__DynamicToolCallStatus, + - success: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - tool: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__ThreadItem = Schema.Union( + - senderThreadId: Schema.String.annotate({ + - description: "Thread ID of the agent issuing the collab request.", + - }), + -- status: Schema.Literals(["inProgress", "completed", "failed", "interrupted"]).annotate({ + -+ status: Schema.Literals(["inProgress", "completed", "failed"]).annotate({ + - description: "Current status of the collab tool call.", + - }), + - tool: Schema.Literals([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__ThreadItem = Schema.Union( + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]).annotate({ description: "Name of the collab tool that was invoked." }), + - type: Schema.Literal("collabAgentToolCall").annotate({ + - title: "CollabAgentToolCallThreadItemType", + - }), + - }).annotate({ title: "CollabAgentToolCallThreadItem" }), + -- Schema.Struct({ + -- agentPath: Schema.String, + -- agentThreadId: Schema.String, + -- id: Schema.String, + -- kind: V2TurnStartResponse__SubAgentActivityKind, + -- type: Schema.Literal("subAgentActivity").annotate({ + -- title: "SubAgentActivityThreadItemType", + -- }), + -- }).annotate({ title: "SubAgentActivityThreadItem" }), + - Schema.Struct({ + - action: Schema.optionalKey(Schema.Union([V2TurnStartResponse__WebSearchAction, Schema.Null])), + - id: Schema.String, + - query: Schema.String, + -- results: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.Unknown).annotate({ + -- description: + -- "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("webSearch").annotate({ title: "WebSearchThreadItemType" }), + - }).annotate({ title: "WebSearchThreadItem" }), + - Schema.Struct({ + - id: Schema.String, + -- path: V2TurnStartResponse__LegacyAppPathString, + -+ path: Schema.String, + - type: Schema.Literal("imageView").annotate({ title: "ImageViewThreadItemType" }), + - }).annotate({ title: "ImageViewThreadItem" }), + -- Schema.Struct({ + -- durationMs: Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- id: Schema.String, + -- type: Schema.Literal("sleep").annotate({ title: "SleepThreadItemType" }), + -- }).annotate({ + -- title: "SleepThreadItem", + -- description: "Display item emitted by the interruptible `clock.sleep` tool.", + -- }), + - Schema.Struct({ + - id: Schema.String, + - result: Schema.String, + - revisedPrompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- savedPath: Schema.optionalKey( + -- Schema.Union([V2TurnStartResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -+ savedPath: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + - type: Schema.Literal("imageGeneration").annotate({ title: "ImageGenerationThreadItemType" }), + - }).annotate({ title: "ImageGenerationThreadItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__ThreadItem = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type ClientRequest__ExternalAgentConfigImportParams = { + -- readonly migrationItems: ReadonlyArray; + -- readonly migrationSource?: string | null; + -- readonly source?: string | null; + --}; + --export const ClientRequest__ExternalAgentConfigImportParams = Schema.Struct({ + -- migrationItems: Schema.Array(ClientRequest__ExternalAgentConfigMigrationItem), + -- migrationSource: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Migration-source selector used to produce the migration items. Pass the same value to detection and import; missing or unrecognized values use the default source.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- source: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Optional identifier for the product that initiated the import.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + --export type CommandExecutionRequestApprovalParams__FileSystemSandboxEntry = { + -- readonly access: CommandExecutionRequestApprovalParams__FileSystemAccessMode; + -- readonly path: CommandExecutionRequestApprovalParams__FileSystemPath; + --}; + --export const CommandExecutionRequestApprovalParams__FileSystemSandboxEntry = Schema.Struct({ + -- access: CommandExecutionRequestApprovalParams__FileSystemAccessMode, + -- path: CommandExecutionRequestApprovalParams__FileSystemPath, + --}); + -- + - export type McpServerElicitationRequestParams__McpElicitationMultiSelectEnumSchema = + - | McpServerElicitationRequestParams__McpElicitationUntitledMultiSelectEnumSchema + - | McpServerElicitationRequestParams__McpElicitationTitledMultiSelectEnumSchema; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const McpServerElicitationRequestParams__McpElicitationMultiSelectEnumSch + - McpServerElicitationRequestParams__McpElicitationTitledMultiSelectEnumSchema, + - ]); + - + --export type PermissionsRequestApprovalParams__FileSystemSandboxEntry = { + -- readonly access: PermissionsRequestApprovalParams__FileSystemAccessMode; + -- readonly path: PermissionsRequestApprovalParams__FileSystemPath; + --}; + --export const PermissionsRequestApprovalParams__FileSystemSandboxEntry = Schema.Struct({ + -- access: PermissionsRequestApprovalParams__FileSystemAccessMode, + -- path: PermissionsRequestApprovalParams__FileSystemPath, + --}); + -- + --export type PermissionsRequestApprovalResponse__FileSystemSandboxEntry = { + -- readonly access: PermissionsRequestApprovalResponse__FileSystemAccessMode; + -- readonly path: PermissionsRequestApprovalResponse__FileSystemPath; + --}; + --export const PermissionsRequestApprovalResponse__FileSystemSandboxEntry = Schema.Struct({ + -- access: PermissionsRequestApprovalResponse__FileSystemAccessMode, + -- path: PermissionsRequestApprovalResponse__FileSystemPath, + --}); + -- + - export type ServerNotification__AppListUpdatedNotification = { + - readonly data: ReadonlyArray; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__AppListUpdatedNotification = Schema.Struct({ + - data: Schema.Array(ServerNotification__AppInfo), + - }).annotate({ description: "EXPERIMENTAL - notification emitted when the app list changes." }); + - + --export type ServerNotification__ExternalAgentConfigImportCompletedNotification = { + -- readonly importId: string; + -- readonly itemTypeResults: ReadonlyArray; + --}; + --export const ServerNotification__ExternalAgentConfigImportCompletedNotification = Schema.Struct({ + -- importId: Schema.String, + -- itemTypeResults: Schema.Array(ServerNotification__ExternalAgentConfigImportTypeResult), + --}); + -- + --export type ServerNotification__ExternalAgentConfigImportProgressNotification = { + -- readonly importId: string; + -- readonly itemTypeResults: ReadonlyArray; + --}; + --export const ServerNotification__ExternalAgentConfigImportProgressNotification = Schema.Struct({ + -- importId: Schema.String, + -- itemTypeResults: Schema.Array(ServerNotification__ExternalAgentConfigImportTypeResult), + --}); + -- + - export type ServerNotification__HookCompletedNotification = { + - readonly run: ServerNotification__HookRunSummary; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__HookStartedNotification = Schema.Struct({ + - turnId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }); + - + --export type ServerNotification__FileSystemSandboxEntry = { + -- readonly access: ServerNotification__FileSystemAccessMode; + -- readonly path: ServerNotification__FileSystemPath; + --}; + --export const ServerNotification__FileSystemSandboxEntry = Schema.Struct({ + -- access: ServerNotification__FileSystemAccessMode, + -- path: ServerNotification__FileSystemPath, + --}); + -- + - export type ServerNotification__ErrorNotification = { + - readonly error: ServerNotification__TurnError; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ErrorNotification = Schema.Struct({ + - willRetry: Schema.Boolean, + - }); + - + --export type ServerNotification__ThreadSettings = { + -- readonly activePermissionProfile?: ServerNotification__ActivePermissionProfile | null; + -- readonly approvalPolicy: ServerNotification__AskForApproval; + -- readonly approvalsReviewer: ServerNotification__ApprovalsReviewer; + -- readonly collaborationMode: ServerNotification__CollaborationMode; + -- readonly cwd: ServerNotification__AbsolutePathBuf; + -- readonly effort?: ServerNotification__ReasoningEffort | null; + -- readonly model: string; + -- readonly modelProvider: string; + -- readonly personality?: ServerNotification__Personality | null; + -- readonly sandboxPolicy: ServerNotification__SandboxPolicy; + -- readonly serviceTier?: string | null; + -- readonly summary?: ServerNotification__ReasoningSummary | null; + --}; + --export const ServerNotification__ThreadSettings = Schema.Struct({ + -- activePermissionProfile: Schema.optionalKey( + -- Schema.Union([ServerNotification__ActivePermissionProfile, Schema.Null]), + -- ), + -- approvalPolicy: ServerNotification__AskForApproval, + -- approvalsReviewer: ServerNotification__ApprovalsReviewer, + -- collaborationMode: ServerNotification__CollaborationMode, + -- cwd: ServerNotification__AbsolutePathBuf, + -- effort: Schema.optionalKey(Schema.Union([ServerNotification__ReasoningEffort, Schema.Null])), + -- model: Schema.String, + -- modelProvider: Schema.String, + -- personality: Schema.optionalKey(Schema.Union([ServerNotification__Personality, Schema.Null])), + -- sandboxPolicy: ServerNotification__SandboxPolicy, + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- summary: Schema.optionalKey(Schema.Union([ServerNotification__ReasoningSummary, Schema.Null])), + --}); + -- + - export type ServerNotification__ItemCompletedNotification = { + -- readonly completedAtMs: number; + - readonly item: ServerNotification__ThreadItem; + - readonly threadId: string; + - readonly turnId: string; + - }; + - export const ServerNotification__ItemCompletedNotification = Schema.Struct({ + -- completedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this item lifecycle completed.", + -- format: "int64", + -- }).check(Schema.isInt()), + - item: ServerNotification__ThreadItem, + - threadId: Schema.String, + - turnId: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__ItemCompletedNotification = Schema.Struct({ + - + - export type ServerNotification__ItemStartedNotification = { + - readonly item: ServerNotification__ThreadItem; + -- readonly startedAtMs: number; + - readonly threadId: string; + - readonly turnId: string; + - }; + - export const ServerNotification__ItemStartedNotification = Schema.Struct({ + - item: ServerNotification__ThreadItem, + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this item lifecycle started.", + -- format: "int64", + -- }).check(Schema.isInt()), + - threadId: Schema.String, + - turnId: Schema.String, + - }); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerNotification__Turn = { + - readonly error?: ServerNotification__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: ServerNotification__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(ServerNotification__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__Turn = Schema.Struct({ + - status: ServerNotification__TurnStatus, + - }); + - + --export type ServerRequest__FileSystemSandboxEntry = { + -- readonly access: ServerRequest__FileSystemAccessMode; + -- readonly path: ServerRequest__FileSystemPath; + -+export type ServerRequest__PermissionsRequestApprovalParams = { + -+ readonly itemId: string; + -+ readonly permissions: ServerRequest__RequestPermissionProfile; + -+ readonly reason?: string | null; + -+ readonly threadId: string; + -+ readonly turnId: string; + - }; + --export const ServerRequest__FileSystemSandboxEntry = Schema.Struct({ + -- access: ServerRequest__FileSystemAccessMode, + -- path: ServerRequest__FileSystemPath, + -+export const ServerRequest__PermissionsRequestApprovalParams = Schema.Struct({ + -+ itemId: Schema.String, + -+ permissions: ServerRequest__RequestPermissionProfile, + -+ reason: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ threadId: Schema.String, + -+ turnId: Schema.String, + - }); + - + - export type ServerRequest__McpElicitationMultiSelectEnumSchema = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerRequest__McpElicitationMultiSelectEnumSchema = Schema.Union([ + - ServerRequest__McpElicitationTitledMultiSelectEnumSchema, + - ]); + - + --export type V2ConfigReadResponse__Config = { + -- readonly analytics?: V2ConfigReadResponse__AnalyticsConfig | null; + -+export type V2ConfigReadResponse__ProfileV2 = { + - readonly approval_policy?: V2ConfigReadResponse__AskForApproval | null; + - readonly approvals_reviewer?: V2ConfigReadResponse__ApprovalsReviewer | null; + -- readonly compact_prompt?: string | null; + -- readonly desktop?: { readonly [x: string]: unknown } | null; + -- readonly developer_instructions?: string | null; + -- readonly forced_chatgpt_workspace_id?: V2ConfigReadResponse__ForcedChatgptWorkspaceIds | null; + -- readonly forced_login_method?: V2ConfigReadResponse__ForcedLoginMethod | null; + -- readonly instructions?: string | null; + -+ readonly chatgpt_base_url?: string | null; + - readonly model?: string | null; + -- readonly model_auto_compact_token_limit?: number | null; + -- readonly model_auto_compact_token_limit_scope?: V2ConfigReadResponse__AutoCompactTokenLimitScope | null; + -- readonly model_context_window?: number | null; + - readonly model_provider?: string | null; + - readonly model_reasoning_effort?: V2ConfigReadResponse__ReasoningEffort | null; + - readonly model_reasoning_summary?: V2ConfigReadResponse__ReasoningSummary | null; + - readonly model_verbosity?: V2ConfigReadResponse__Verbosity | null; + -- readonly review_model?: string | null; + -- readonly sandbox_mode?: V2ConfigReadResponse__SandboxMode | null; + -- readonly sandbox_workspace_write?: V2ConfigReadResponse__SandboxWorkspaceWrite | null; + -- readonly service_tier?: string | null; + -+ readonly service_tier?: V2ConfigReadResponse__ServiceTier | null; + - readonly tools?: V2ConfigReadResponse__ToolsV2 | null; + - readonly web_search?: V2ConfigReadResponse__WebSearchMode | null; + - readonly [x: string]: unknown; + - }; + --export const V2ConfigReadResponse__Config = Schema.StructWithRest( + -+export const V2ConfigReadResponse__ProfileV2 = Schema.StructWithRest( + - Schema.Struct({ + -- analytics: Schema.optionalKey( + -- Schema.Union([V2ConfigReadResponse__AnalyticsConfig, Schema.Null]), + -- ), + - approval_policy: Schema.optionalKey( + - Schema.Union([V2ConfigReadResponse__AskForApproval, Schema.Null]), + - ), + - approvals_reviewer: Schema.optionalKey( + - Schema.Union([V2ConfigReadResponse__ApprovalsReviewer, Schema.Null]).annotate({ + - description: + -- "[UNSTABLE] Optional default for where approval requests are routed for review.", + -+ "[UNSTABLE] Optional profile-level override for where approval requests are routed for review. If omitted, the enclosing config default is used.", + - }), + - ), + -- compact_prompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- desktop: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.Unknown), Schema.Null]), + -- ), + -- developer_instructions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- forced_chatgpt_workspace_id: Schema.optionalKey( + -- Schema.Union([V2ConfigReadResponse__ForcedChatgptWorkspaceIds, Schema.Null]), + -- ), + -- forced_login_method: Schema.optionalKey( + -- Schema.Union([V2ConfigReadResponse__ForcedLoginMethod, Schema.Null]), + -- ), + -- instructions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ chatgpt_base_url: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - model: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- model_auto_compact_token_limit: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- model_auto_compact_token_limit_scope: Schema.optionalKey( + -- Schema.Union([V2ConfigReadResponse__AutoCompactTokenLimitScope, Schema.Null]), + -- ), + -- model_context_window: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + - model_provider: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - model_reasoning_effort: Schema.optionalKey( + - Schema.Union([V2ConfigReadResponse__ReasoningEffort, Schema.Null]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadResponse__Config = Schema.StructWithRest( + - model_verbosity: Schema.optionalKey( + - Schema.Union([V2ConfigReadResponse__Verbosity, Schema.Null]), + - ), + -- review_model: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- sandbox_mode: Schema.optionalKey( + -- Schema.Union([V2ConfigReadResponse__SandboxMode, Schema.Null]), + -- ), + -- sandbox_workspace_write: Schema.optionalKey( + -- Schema.Union([V2ConfigReadResponse__SandboxWorkspaceWrite, Schema.Null]), + -+ service_tier: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__ServiceTier, Schema.Null]), + - ), + -- service_tier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - tools: Schema.optionalKey(Schema.Union([V2ConfigReadResponse__ToolsV2, Schema.Null])), + - web_search: Schema.optionalKey( + - Schema.Union([V2ConfigReadResponse__WebSearchMode, Schema.Null]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadResponse__Config = Schema.StructWithRest( + - [Schema.Record(Schema.String, Schema.Unknown)], + - ); + - + --export type V2ConfigRequirementsReadResponse__ConfigRequirements = { + -- readonly allowAppshots?: boolean | null; + -- readonly allowManagedHooksOnly?: boolean | null; + -- readonly allowRemoteControl?: boolean | null; + -- readonly allowedApprovalPolicies?: ReadonlyArray | null; + -- readonly allowedPermissionProfiles?: { readonly [x: string]: boolean } | null; + -- readonly allowedSandboxModes?: ReadonlyArray | null; + -- readonly allowedWebSearchModes?: ReadonlyArray | null; + -- readonly allowedWindowsSandboxImplementations?: ReadonlyArray | null; + -- readonly computerUse?: V2ConfigRequirementsReadResponse__ComputerUseRequirements | null; + -- readonly defaultPermissions?: string | null; + -- readonly enforceResidency?: V2ConfigRequirementsReadResponse__ResidencyRequirement | null; + -- readonly featureRequirements?: { readonly [x: string]: boolean } | null; + -- readonly models?: V2ConfigRequirementsReadResponse__ModelsRequirements | null; + --}; + --export const V2ConfigRequirementsReadResponse__ConfigRequirements = Schema.Struct({ + -- allowAppshots: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + -- allowManagedHooksOnly: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + -- allowRemoteControl: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + -- allowedApprovalPolicies: Schema.optionalKey( + -- Schema.Union([Schema.Array(V2ConfigRequirementsReadResponse__AskForApproval), Schema.Null]), + -- ), + -- allowedPermissionProfiles: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.Boolean), Schema.Null]), + -- ), + -- allowedSandboxModes: Schema.optionalKey( + -- Schema.Union([Schema.Array(V2ConfigRequirementsReadResponse__SandboxMode), Schema.Null]), + -- ), + -- allowedWebSearchModes: Schema.optionalKey( + -- Schema.Union([Schema.Array(V2ConfigRequirementsReadResponse__WebSearchMode), Schema.Null]), + -- ), + -- allowedWindowsSandboxImplementations: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(V2ConfigRequirementsReadResponse__WindowsSandboxSetupMode), + -- Schema.Null, + -- ]), + -- ), + -- computerUse: Schema.optionalKey( + -- Schema.Union([V2ConfigRequirementsReadResponse__ComputerUseRequirements, Schema.Null]), + -- ), + -- defaultPermissions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- enforceResidency: Schema.optionalKey( + -- Schema.Union([V2ConfigRequirementsReadResponse__ResidencyRequirement, Schema.Null]), + -- ), + -- featureRequirements: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.Boolean), Schema.Null]), + -- ), + -- models: Schema.optionalKey( + -- Schema.Union([V2ConfigRequirementsReadResponse__ModelsRequirements, Schema.Null]), + -- ), + --}); + -- + - export type V2ConfigWriteResponse__OverriddenMetadata = { + - readonly effectiveValue: unknown; + - readonly message: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigWriteResponse__OverriddenMetadata = Schema.Struct({ + - overridingLayer: V2ConfigWriteResponse__ConfigLayerMetadata, + - }); + - + --export type V2ItemGuardianApprovalReviewCompletedNotification__FileSystemSandboxEntry = { + -- readonly access: V2ItemGuardianApprovalReviewCompletedNotification__FileSystemAccessMode; + -- readonly path: V2ItemGuardianApprovalReviewCompletedNotification__FileSystemPath; + --}; + --export const V2ItemGuardianApprovalReviewCompletedNotification__FileSystemSandboxEntry = + -- Schema.Struct({ + -- access: V2ItemGuardianApprovalReviewCompletedNotification__FileSystemAccessMode, + -- path: V2ItemGuardianApprovalReviewCompletedNotification__FileSystemPath, + -- }); + -- + --export type V2ItemGuardianApprovalReviewStartedNotification__FileSystemSandboxEntry = { + -- readonly access: V2ItemGuardianApprovalReviewStartedNotification__FileSystemAccessMode; + -- readonly path: V2ItemGuardianApprovalReviewStartedNotification__FileSystemPath; + --}; + --export const V2ItemGuardianApprovalReviewStartedNotification__FileSystemSandboxEntry = + -- Schema.Struct({ + -- access: V2ItemGuardianApprovalReviewStartedNotification__FileSystemAccessMode, + -- path: V2ItemGuardianApprovalReviewStartedNotification__FileSystemPath, + -- }); + -- + --export type V2PluginInstalledResponse__PluginSummary = { + -- readonly authPolicy: V2PluginInstalledResponse__PluginAuthPolicy; + -- readonly availability?: "DISABLED_BY_ADMIN" | "AVAILABLE"; + -- readonly enabled: boolean; + -- readonly id: string; + -- readonly installPolicy: V2PluginInstalledResponse__PluginInstallPolicy; + -- readonly installPolicySource?: V2PluginInstalledResponse__PluginInstallPolicySource | null; + -- readonly installed: boolean; + -- readonly interface?: V2PluginInstalledResponse__PluginInterface | null; + -- readonly keywords?: ReadonlyArray; + -- readonly localVersion?: string | null; + -- readonly mustShowInstallationInterstitial?: boolean | null; + -+export type V2PluginListResponse__PluginMarketplaceEntry = { + -+ readonly interface?: V2PluginListResponse__MarketplaceInterface | null; + - readonly name: string; + -- readonly remotePluginId?: string | null; + -- readonly shareContext?: V2PluginInstalledResponse__PluginShareContext | null; + -- readonly source: V2PluginInstalledResponse__PluginSource; + -- readonly version?: string | null; + -+ readonly path: V2PluginListResponse__AbsolutePathBuf; + -+ readonly plugins: ReadonlyArray; + - }; + --export const V2PluginInstalledResponse__PluginSummary = Schema.Struct({ + -- authPolicy: V2PluginInstalledResponse__PluginAuthPolicy, + -- availability: Schema.optionalKey( + -- Schema.Literals(["DISABLED_BY_ADMIN", "AVAILABLE"]).annotate({ + -- description: "Availability state for installing and using the plugin.", + -- default: "AVAILABLE", + -- }), + -- ), + -- enabled: Schema.Boolean, + -- id: Schema.String, + -- installPolicy: V2PluginInstalledResponse__PluginInstallPolicy, + -- installPolicySource: Schema.optionalKey( + -- Schema.Union([V2PluginInstalledResponse__PluginInstallPolicySource, Schema.Null]), + -- ), + -- installed: Schema.Boolean, + -+export const V2PluginListResponse__PluginMarketplaceEntry = Schema.Struct({ + - interface: Schema.optionalKey( + -- Schema.Union([V2PluginInstalledResponse__PluginInterface, Schema.Null]), + -- ), + -- keywords: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + -- localVersion: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version of the locally materialized plugin package when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- mustShowInstallationInterstitial: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + -- name: Schema.String, + -- remotePluginId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Backend remote plugin identifier when available." }), + -- Schema.Null, + -- ]), + -- ), + -- shareContext: Schema.optionalKey( + -- Schema.Union([V2PluginInstalledResponse__PluginShareContext, Schema.Null]).annotate({ + -- description: "Remote sharing context associated with this plugin when available.", + -- }), + -- ), + -- source: V2PluginInstalledResponse__PluginSource, + -- version: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version advertised by the remote marketplace backend when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + --export type V2PluginListResponse__PluginSummary = { + -- readonly authPolicy: V2PluginListResponse__PluginAuthPolicy; + -- readonly availability?: "DISABLED_BY_ADMIN" | "AVAILABLE"; + -- readonly enabled: boolean; + -- readonly id: string; + -- readonly installPolicy: V2PluginListResponse__PluginInstallPolicy; + -- readonly installPolicySource?: V2PluginListResponse__PluginInstallPolicySource | null; + -- readonly installed: boolean; + -- readonly interface?: V2PluginListResponse__PluginInterface | null; + -- readonly keywords?: ReadonlyArray; + -- readonly localVersion?: string | null; + -- readonly mustShowInstallationInterstitial?: boolean | null; + -- readonly name: string; + -- readonly remotePluginId?: string | null; + -- readonly shareContext?: V2PluginListResponse__PluginShareContext | null; + -- readonly source: V2PluginListResponse__PluginSource; + -- readonly version?: string | null; + --}; + --export const V2PluginListResponse__PluginSummary = Schema.Struct({ + -- authPolicy: V2PluginListResponse__PluginAuthPolicy, + -- availability: Schema.optionalKey( + -- Schema.Literals(["DISABLED_BY_ADMIN", "AVAILABLE"]).annotate({ + -- description: "Availability state for installing and using the plugin.", + -- default: "AVAILABLE", + -- }), + -- ), + -- enabled: Schema.Boolean, + -- id: Schema.String, + -- installPolicy: V2PluginListResponse__PluginInstallPolicy, + -- installPolicySource: Schema.optionalKey( + -- Schema.Union([V2PluginListResponse__PluginInstallPolicySource, Schema.Null]), + -- ), + -- installed: Schema.Boolean, + -- interface: Schema.optionalKey(Schema.Union([V2PluginListResponse__PluginInterface, Schema.Null])), + -- keywords: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + -- localVersion: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version of the locally materialized plugin package when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- mustShowInstallationInterstitial: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + -- name: Schema.String, + -- remotePluginId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Backend remote plugin identifier when available." }), + -- Schema.Null, + -- ]), + -- ), + -- shareContext: Schema.optionalKey( + -- Schema.Union([V2PluginListResponse__PluginShareContext, Schema.Null]).annotate({ + -- description: "Remote sharing context associated with this plugin when available.", + -- }), + -- ), + -- source: V2PluginListResponse__PluginSource, + -- version: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version advertised by the remote marketplace backend when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + --export type V2PluginReadResponse__PluginSummary = { + -- readonly authPolicy: V2PluginReadResponse__PluginAuthPolicy; + -- readonly availability?: "DISABLED_BY_ADMIN" | "AVAILABLE"; + -- readonly enabled: boolean; + -- readonly id: string; + -- readonly installPolicy: V2PluginReadResponse__PluginInstallPolicy; + -- readonly installPolicySource?: V2PluginReadResponse__PluginInstallPolicySource | null; + -- readonly installed: boolean; + -- readonly interface?: V2PluginReadResponse__PluginInterface | null; + -- readonly keywords?: ReadonlyArray; + -- readonly localVersion?: string | null; + -- readonly mustShowInstallationInterstitial?: boolean | null; + -- readonly name: string; + -- readonly remotePluginId?: string | null; + -- readonly shareContext?: V2PluginReadResponse__PluginShareContext | null; + -- readonly source: V2PluginReadResponse__PluginSource; + -- readonly version?: string | null; + --}; + --export const V2PluginReadResponse__PluginSummary = Schema.Struct({ + -- authPolicy: V2PluginReadResponse__PluginAuthPolicy, + -- availability: Schema.optionalKey( + -- Schema.Literals(["DISABLED_BY_ADMIN", "AVAILABLE"]).annotate({ + -- description: "Availability state for installing and using the plugin.", + -- default: "AVAILABLE", + -- }), + -- ), + -- enabled: Schema.Boolean, + -- id: Schema.String, + -- installPolicy: V2PluginReadResponse__PluginInstallPolicy, + -- installPolicySource: Schema.optionalKey( + -- Schema.Union([V2PluginReadResponse__PluginInstallPolicySource, Schema.Null]), + -- ), + -- installed: Schema.Boolean, + -- interface: Schema.optionalKey(Schema.Union([V2PluginReadResponse__PluginInterface, Schema.Null])), + -- keywords: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + -- localVersion: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version of the locally materialized plugin package when available.", + -- }), + -- Schema.Null, + -- ]), + -+ Schema.Union([V2PluginListResponse__MarketplaceInterface, Schema.Null]), + - ), + -- mustShowInstallationInterstitial: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - name: Schema.String, + -- remotePluginId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Backend remote plugin identifier when available." }), + -- Schema.Null, + -- ]), + -- ), + -- shareContext: Schema.optionalKey( + -- Schema.Union([V2PluginReadResponse__PluginShareContext, Schema.Null]).annotate({ + -- description: "Remote sharing context associated with this plugin when available.", + -- }), + -- ), + -- source: V2PluginReadResponse__PluginSource, + -- version: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version advertised by the remote marketplace backend when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -+ path: V2PluginListResponse__AbsolutePathBuf, + -+ plugins: Schema.Array(V2PluginListResponse__PluginSummary), + - }); + - + --export type V2PluginShareListResponse__PluginSummary = { + -- readonly authPolicy: V2PluginShareListResponse__PluginAuthPolicy; + -- readonly availability?: "DISABLED_BY_ADMIN" | "AVAILABLE"; + -- readonly enabled: boolean; + -- readonly id: string; + -- readonly installPolicy: V2PluginShareListResponse__PluginInstallPolicy; + -- readonly installPolicySource?: V2PluginShareListResponse__PluginInstallPolicySource | null; + -- readonly installed: boolean; + -- readonly interface?: V2PluginShareListResponse__PluginInterface | null; + -- readonly keywords?: ReadonlyArray; + -- readonly localVersion?: string | null; + -- readonly mustShowInstallationInterstitial?: boolean | null; + -- readonly name: string; + -- readonly remotePluginId?: string | null; + -- readonly shareContext?: V2PluginShareListResponse__PluginShareContext | null; + -- readonly source: V2PluginShareListResponse__PluginSource; + -- readonly version?: string | null; + -+export type V2PluginReadResponse__PluginDetail = { + -+ readonly apps: ReadonlyArray; + -+ readonly description?: string | null; + -+ readonly marketplaceName: string; + -+ readonly marketplacePath: V2PluginReadResponse__AbsolutePathBuf; + -+ readonly mcpServers: ReadonlyArray; + -+ readonly skills: ReadonlyArray; + -+ readonly summary: V2PluginReadResponse__PluginSummary; + - }; + --export const V2PluginShareListResponse__PluginSummary = Schema.Struct({ + -- authPolicy: V2PluginShareListResponse__PluginAuthPolicy, + -- availability: Schema.optionalKey( + -- Schema.Literals(["DISABLED_BY_ADMIN", "AVAILABLE"]).annotate({ + -- description: "Availability state for installing and using the plugin.", + -- default: "AVAILABLE", + -- }), + -- ), + -- enabled: Schema.Boolean, + -- id: Schema.String, + -- installPolicy: V2PluginShareListResponse__PluginInstallPolicy, + -- installPolicySource: Schema.optionalKey( + -- Schema.Union([V2PluginShareListResponse__PluginInstallPolicySource, Schema.Null]), + -- ), + -- installed: Schema.Boolean, + -- interface: Schema.optionalKey( + -- Schema.Union([V2PluginShareListResponse__PluginInterface, Schema.Null]), + -- ), + -- keywords: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + -- localVersion: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version of the locally materialized plugin package when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- mustShowInstallationInterstitial: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + -- name: Schema.String, + -- remotePluginId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Backend remote plugin identifier when available." }), + -- Schema.Null, + -- ]), + -- ), + -- shareContext: Schema.optionalKey( + -- Schema.Union([V2PluginShareListResponse__PluginShareContext, Schema.Null]).annotate({ + -- description: "Remote sharing context associated with this plugin when available.", + -- }), + -- ), + -- source: V2PluginShareListResponse__PluginSource, + -- version: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Version advertised by the remote marketplace backend when available.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -+export const V2PluginReadResponse__PluginDetail = Schema.Struct({ + -+ apps: Schema.Array(V2PluginReadResponse__AppSummary), + -+ description: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ marketplaceName: Schema.String, + -+ marketplacePath: V2PluginReadResponse__AbsolutePathBuf, + -+ mcpServers: Schema.Array(Schema.String), + -+ skills: Schema.Array(V2PluginReadResponse__SkillSummary), + -+ summary: V2PluginReadResponse__PluginSummary, + - }); + - + - export type V2RawResponseItemCompletedNotification__ResponseItem = + - | { + - readonly content: ReadonlyArray; + -+ readonly end_turn?: boolean | null; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + - readonly phase?: V2RawResponseItemCompletedNotification__MessagePhase | null; + - readonly role: string; + - readonly type: "message"; + - } + -- | { + -- readonly author: string; + -- readonly content: ReadonlyArray; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + -- readonly recipient: string; + -- readonly type: "agent_message"; + -- } + - | { + - readonly content?: ReadonlyArray | null; + - readonly encrypted_content?: string | null; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + - readonly summary: ReadonlyArray; + - readonly type: "reasoning"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2RawResponseItemCompletedNotification__ResponseItem = + - readonly action: V2RawResponseItemCompletedNotification__LocalShellAction; + - readonly call_id?: string | null; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + - readonly status: V2RawResponseItemCompletedNotification__LocalShellStatus; + - readonly type: "local_shell_call"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2RawResponseItemCompletedNotification__ResponseItem = + - readonly arguments: string; + - readonly call_id: string; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + - readonly name: string; + - readonly namespace?: string | null; + - readonly type: "function_call"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2RawResponseItemCompletedNotification__ResponseItem = + - readonly call_id?: string | null; + - readonly execution: string; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + - readonly status?: string | null; + - readonly type: "tool_search_call"; + - } + - | { + - readonly call_id: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + - readonly output: V2RawResponseItemCompletedNotification__FunctionCallOutputBody; + - readonly type: "function_call_output"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2RawResponseItemCompletedNotification__ResponseItem = + - readonly call_id: string; + - readonly id?: string | null; + - readonly input: string; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + - readonly name: string; + -- readonly namespace?: string | null; + - readonly status?: string | null; + - readonly type: "custom_tool_call"; + - } + - | { + - readonly call_id: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + - readonly name?: string | null; + - readonly output: V2RawResponseItemCompletedNotification__FunctionCallOutputBody; + - readonly type: "custom_tool_call_output"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2RawResponseItemCompletedNotification__ResponseItem = + - | { + - readonly call_id?: string | null; + - readonly execution: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + - readonly status: string; + - readonly tools: ReadonlyArray; + - readonly type: "tool_search_output"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2RawResponseItemCompletedNotification__ResponseItem = + - | { + - readonly action?: V2RawResponseItemCompletedNotification__ResponsesApiWebSearchAction | null; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + - readonly status?: string | null; + - readonly type: "web_search_call"; + - } + - | { + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + -+ readonly id: string; + - readonly result: string; + - readonly revised_prompt?: string | null; + - readonly status: string; + - readonly type: "image_generation_call"; + - } + - | { + -- readonly encrypted_content: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + -- readonly type: "compaction"; + -- } + -- | { readonly type: "compaction_trigger" } + -- | { + -- readonly encrypted_content?: string | null; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough | null; + -- readonly type: "context_compaction"; + -+ readonly ghost_commit: V2RawResponseItemCompletedNotification__GhostCommit; + -+ readonly type: "ghost_snapshot"; + - } + -+ | { readonly encrypted_content: string; readonly type: "compaction" } + - | { readonly type: "other" }; + - export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union( + - [ + - Schema.Struct({ + - content: Schema.Array(V2RawResponseItemCompletedNotification__ContentItem), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -+ end_turn: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - phase: Schema.optionalKey( + - Schema.Union([V2RawResponseItemCompletedNotification__MessagePhase, Schema.Null]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union + - role: Schema.String, + - type: Schema.Literal("message").annotate({ title: "MessageResponseItemType" }), + - }).annotate({ title: "MessageResponseItem" }), + -- Schema.Struct({ + -- author: Schema.String, + -- content: Schema.Array(V2RawResponseItemCompletedNotification__AgentMessageInputContent), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -- ), + -- recipient: Schema.String, + -- type: Schema.Literal("agent_message").annotate({ title: "AgentMessageResponseItemType" }), + -- }).annotate({ title: "AgentMessageResponseItem" }), + - Schema.Struct({ + - content: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union + - ]), + - ), + - encrypted_content: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -- ), + - summary: Schema.Array(V2RawResponseItemCompletedNotification__ReasoningItemReasoningSummary), + - type: Schema.Literal("reasoning").annotate({ title: "ReasoningResponseItemType" }), + - }).annotate({ title: "ReasoningResponseItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union + - Schema.Union([ + - Schema.String.annotate({ + - description: "Legacy id field retained for compatibility with older payloads.", + -+ writeOnly: true, + - }), + - Schema.Null, + - ]), + - ), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -- ), + - status: V2RawResponseItemCompletedNotification__LocalShellStatus, + - type: Schema.Literal("local_shell_call").annotate({ + - title: "LocalShellCallResponseItemType", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union + - Schema.Struct({ + - arguments: Schema.String, + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - name: Schema.String, + - namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union + - arguments: Schema.Unknown, + - call_id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - execution: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - status: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - type: Schema.Literal("tool_search_call").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union + - }).annotate({ title: "ToolSearchCallResponseItem" }), + - Schema.Struct({ + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -- ), + - output: V2RawResponseItemCompletedNotification__FunctionCallOutputBody, + - type: Schema.Literal("function_call_output").annotate({ + - title: "FunctionCallOutputResponseItemType", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union + - }).annotate({ title: "FunctionCallOutputResponseItem" }), + - Schema.Struct({ + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- input: Schema.String, + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + -+ input: Schema.String, + - name: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - type: Schema.Literal("custom_tool_call").annotate({ + - title: "CustomToolCallResponseItemType", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union + - }).annotate({ title: "CustomToolCallResponseItem" }), + - Schema.Struct({ + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -- ), + - name: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - output: V2RawResponseItemCompletedNotification__FunctionCallOutputBody, + - type: Schema.Literal("custom_tool_call_output").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union + - Schema.Struct({ + - call_id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - execution: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -- ), + - status: Schema.String, + - tools: Schema.Array(Schema.Unknown), + - type: Schema.Literal("tool_search_output").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union + - Schema.Null, + - ]), + - ), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - status: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - type: Schema.Literal("web_search_call").annotate({ title: "WebSearchCallResponseItemType" }), + - }).annotate({ title: "WebSearchCallResponseItem" }), + - Schema.Struct({ + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -- ), + -+ id: Schema.String, + - result: Schema.String, + - revised_prompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2RawResponseItemCompletedNotification__ResponseItem = Schema.Union + - title: "ImageGenerationCallResponseItemType", + - }), + - }).annotate({ title: "ImageGenerationCallResponseItem" }), + -+ Schema.Struct({ + -+ ghost_commit: V2RawResponseItemCompletedNotification__GhostCommit, + -+ type: Schema.Literal("ghost_snapshot").annotate({ title: "GhostSnapshotResponseItemType" }), + -+ }).annotate({ title: "GhostSnapshotResponseItem" }), + - Schema.Struct({ + - encrypted_content: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -- ), + - type: Schema.Literal("compaction").annotate({ title: "CompactionResponseItemType" }), + - }).annotate({ title: "CompactionResponseItem" }), + -- Schema.Struct({ + -- type: Schema.Literal("compaction_trigger").annotate({ + -- title: "CompactionTriggerResponseItemType", + -- }), + -- }).annotate({ title: "CompactionTriggerResponseItem" }), + -- Schema.Struct({ + -- encrypted_content: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ + -- V2RawResponseItemCompletedNotification__InternalChatMessageMetadataPassthrough, + -- Schema.Null, + -- ]), + -- ), + -- type: Schema.Literal("context_compaction").annotate({ + -- title: "ContextCompactionResponseItemType", + -- }), + -- }).annotate({ title: "ContextCompactionResponseItem" }), + - Schema.Struct({ + - type: Schema.Literal("other").annotate({ title: "OtherResponseItemType" }), + - }).annotate({ title: "OtherResponseItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ReviewStartResponse__Turn = { + - readonly error?: V2ReviewStartResponse__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2ReviewStartResponse__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2ReviewStartResponse__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkResponse__Turn = { + - readonly error?: V2ThreadForkResponse__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2ThreadForkResponse__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2ThreadForkResponse__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadListResponse__Turn = { + - readonly error?: V2ThreadListResponse__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2ThreadListResponse__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2ThreadListResponse__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadMetadataUpdateResponse__Turn = { + - readonly error?: V2ThreadMetadataUpdateResponse__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2ThreadMetadataUpdateResponse__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2ThreadMetadataUpdateResponse__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadReadResponse__Turn = { + - readonly error?: V2ThreadReadResponse__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2ThreadReadResponse__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2ThreadReadResponse__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeResponse__Turn = { + - readonly error?: V2ThreadResumeResponse__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2ThreadResumeResponse__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2ThreadResumeResponse__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadRollbackResponse__Turn = { + - readonly error?: V2ThreadRollbackResponse__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2ThreadRollbackResponse__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2ThreadRollbackResponse__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__Turn = Schema.Struct({ + - status: V2ThreadRollbackResponse__TurnStatus, + - }); + - + --export type V2ThreadSettingsUpdatedNotification__ThreadSettings = { + -- readonly activePermissionProfile?: V2ThreadSettingsUpdatedNotification__ActivePermissionProfile | null; + -- readonly approvalPolicy: V2ThreadSettingsUpdatedNotification__AskForApproval; + -- readonly approvalsReviewer: V2ThreadSettingsUpdatedNotification__ApprovalsReviewer; + -- readonly collaborationMode: V2ThreadSettingsUpdatedNotification__CollaborationMode; + -- readonly cwd: V2ThreadSettingsUpdatedNotification__AbsolutePathBuf; + -- readonly effort?: V2ThreadSettingsUpdatedNotification__ReasoningEffort | null; + -- readonly model: string; + -- readonly modelProvider: string; + -- readonly personality?: V2ThreadSettingsUpdatedNotification__Personality | null; + -- readonly sandboxPolicy: V2ThreadSettingsUpdatedNotification__SandboxPolicy; + -- readonly serviceTier?: string | null; + -- readonly summary?: V2ThreadSettingsUpdatedNotification__ReasoningSummary | null; + --}; + --export const V2ThreadSettingsUpdatedNotification__ThreadSettings = Schema.Struct({ + -- activePermissionProfile: Schema.optionalKey( + -- Schema.Union([V2ThreadSettingsUpdatedNotification__ActivePermissionProfile, Schema.Null]), + -- ), + -- approvalPolicy: V2ThreadSettingsUpdatedNotification__AskForApproval, + -- approvalsReviewer: V2ThreadSettingsUpdatedNotification__ApprovalsReviewer, + -- collaborationMode: V2ThreadSettingsUpdatedNotification__CollaborationMode, + -- cwd: V2ThreadSettingsUpdatedNotification__AbsolutePathBuf, + -- effort: Schema.optionalKey( + -- Schema.Union([V2ThreadSettingsUpdatedNotification__ReasoningEffort, Schema.Null]), + -- ), + -- model: Schema.String, + -- modelProvider: Schema.String, + -- personality: Schema.optionalKey( + -- Schema.Union([V2ThreadSettingsUpdatedNotification__Personality, Schema.Null]), + -- ), + -- sandboxPolicy: V2ThreadSettingsUpdatedNotification__SandboxPolicy, + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- summary: Schema.optionalKey( + -- Schema.Union([V2ThreadSettingsUpdatedNotification__ReasoningSummary, Schema.Null]), + -- ), + --}); + -- + - export type V2ThreadStartedNotification__Turn = { + - readonly completedAt?: number | null; + - readonly durationMs?: number | null; + - readonly error?: V2ThreadStartedNotification__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2ThreadStartedNotification__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2ThreadStartedNotification__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartResponse__Turn = { + - readonly error?: V2ThreadStartResponse__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2ThreadStartResponse__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2ThreadStartResponse__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadUnarchiveResponse__Turn = { + - readonly error?: V2ThreadUnarchiveResponse__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2ThreadUnarchiveResponse__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2ThreadUnarchiveResponse__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnCompletedNotification__Turn = { + - readonly error?: V2TurnCompletedNotification__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2TurnCompletedNotification__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2TurnCompletedNotification__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartedNotification__Turn = { + - readonly error?: V2TurnStartedNotification__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2TurnStartedNotification__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartedNotification__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2TurnStartedNotification__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartResponse__Turn = { + - readonly error?: V2TurnStartResponse__TurnError | null; + - readonly id: string; + - readonly items: ReadonlyArray; + -- readonly itemsView?: "notLoaded" | "summary" | "full"; + - readonly startedAt?: number | null; + - readonly status: V2TurnStartResponse__TurnStatus; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__Turn = Schema.Struct({ + - description: "Only populated when the Turn's status is failed.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this turn. Codex-generated turn IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - items: Schema.Array(V2TurnStartResponse__ThreadItem).annotate({ + -- description: "Thread items currently included in this turn payload.", + -+ description: + -+ "Only populated on a `thread/resume` or `thread/fork` response. For all other responses and notifications returning a Turn, the items field will be an empty list.", + - }), + -- itemsView: Schema.optionalKey( + -- Schema.Literals(["notLoaded", "summary", "full"]).annotate({ + -- description: "Describes how much of `items` has been loaded for this turn.", + -- default: "full", + -- }), + -- ), + - startedAt: Schema.optionalKey( + - Schema.Union([ + - Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__Turn = Schema.Struct({ + - status: V2TurnStartResponse__TurnStatus, + - }); + - + --export type CommandExecutionRequestApprovalParams__AdditionalFileSystemPermissions = { + -- readonly entries?: ReadonlyArray | null; + -- readonly globScanMaxDepth?: number | null; + -- readonly read?: ReadonlyArray | null; + -- readonly write?: ReadonlyArray | null; + --}; + --export const CommandExecutionRequestApprovalParams__AdditionalFileSystemPermissions = Schema.Struct( + -- { + -- entries: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(CommandExecutionRequestApprovalParams__FileSystemSandboxEntry), + -- Schema.Null, + -- ]), + -- ), + -- globScanMaxDepth: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ format: "uint" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(1)), + -- Schema.Null, + -- ]), + -- ), + -- read: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(CommandExecutionRequestApprovalParams__LegacyAppPathString).annotate({ + -- description: "This will be removed in favor of `entries`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- write: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(CommandExecutionRequestApprovalParams__LegacyAppPathString).annotate({ + -- description: "This will be removed in favor of `entries`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- }, + --); + -- + - export type McpServerElicitationRequestParams__McpElicitationEnumSchema = + - | McpServerElicitationRequestParams__McpElicitationSingleSelectEnumSchema + - | McpServerElicitationRequestParams__McpElicitationMultiSelectEnumSchema + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const McpServerElicitationRequestParams__McpElicitationEnumSchema = Schem + - McpServerElicitationRequestParams__McpElicitationLegacyTitledEnumSchema, + - ]); + - + --export type PermissionsRequestApprovalParams__AdditionalFileSystemPermissions = { + -- readonly entries?: ReadonlyArray | null; + -- readonly globScanMaxDepth?: number | null; + -- readonly read?: ReadonlyArray | null; + -- readonly write?: ReadonlyArray | null; + --}; + --export const PermissionsRequestApprovalParams__AdditionalFileSystemPermissions = Schema.Struct({ + -- entries: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(PermissionsRequestApprovalParams__FileSystemSandboxEntry), + -- Schema.Null, + -- ]), + -- ), + -- globScanMaxDepth: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ format: "uint" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(1)), + -- Schema.Null, + -- ]), + -- ), + -- read: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(PermissionsRequestApprovalParams__LegacyAppPathString).annotate({ + -- description: "This will be removed in favor of `entries`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- write: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(PermissionsRequestApprovalParams__LegacyAppPathString).annotate({ + -- description: "This will be removed in favor of `entries`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + --export type PermissionsRequestApprovalResponse__AdditionalFileSystemPermissions = { + -- readonly entries?: ReadonlyArray | null; + -- readonly globScanMaxDepth?: number | null; + -- readonly read?: ReadonlyArray | null; + -- readonly write?: ReadonlyArray | null; + --}; + --export const PermissionsRequestApprovalResponse__AdditionalFileSystemPermissions = Schema.Struct({ + -- entries: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(PermissionsRequestApprovalResponse__FileSystemSandboxEntry), + -- Schema.Null, + -- ]), + -- ), + -- globScanMaxDepth: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ format: "uint" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(1)), + -- Schema.Null, + -- ]), + -- ), + -- read: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(PermissionsRequestApprovalResponse__LegacyAppPathString).annotate({ + -- description: "This will be removed in favor of `entries`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- write: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(PermissionsRequestApprovalResponse__LegacyAppPathString).annotate({ + -- description: "This will be removed in favor of `entries`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + --export type ServerNotification__AdditionalFileSystemPermissions = { + -- readonly entries?: ReadonlyArray | null; + -- readonly globScanMaxDepth?: number | null; + -- readonly read?: ReadonlyArray | null; + -- readonly write?: ReadonlyArray | null; + --}; + --export const ServerNotification__AdditionalFileSystemPermissions = Schema.Struct({ + -- entries: Schema.optionalKey( + -- Schema.Union([Schema.Array(ServerNotification__FileSystemSandboxEntry), Schema.Null]), + -- ), + -- globScanMaxDepth: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ format: "uint" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(1)), + -- Schema.Null, + -- ]), + -- ), + -- read: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(ServerNotification__LegacyAppPathString).annotate({ + -- description: "This will be removed in favor of `entries`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- write: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(ServerNotification__LegacyAppPathString).annotate({ + -- description: "This will be removed in favor of `entries`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + --export type ServerNotification__ThreadSettingsUpdatedNotification = { + -- readonly threadId: string; + -- readonly threadSettings: ServerNotification__ThreadSettings; + --}; + --export const ServerNotification__ThreadSettingsUpdatedNotification = Schema.Struct({ + -- threadId: Schema.String, + -- threadSettings: ServerNotification__ThreadSettings, + --}); + -- + - export type ServerNotification__Thread = { + - readonly agentNickname?: string | null; + - readonly agentRole?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerNotification__Thread = { + - readonly id: string; + - readonly modelProvider: string; + - readonly name?: string | null; + -- readonly parentThreadId?: string | null; + - readonly path?: string | null; + - readonly preview: string; + -- readonly recencyAt?: number | null; + -- readonly sessionId: string; + - readonly source: + - | "cli" + - | "vscode" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerNotification__Thread = { + - readonly activeFlags: ReadonlyArray; + - readonly type: "active"; + - }; + -- readonly threadSource?: ServerNotification__ThreadSource | null; + - readonly turns: ReadonlyArray; + - readonly updatedAt: number; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__Thread = Schema.Struct({ + - description: "Unix timestamp (in seconds) when the thread was created.", + - format: "int64", + - }).check(Schema.isInt()), + -- cwd: Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }), + -+ cwd: Schema.String.annotate({ description: "Working directory captured for the thread." }), + - ephemeral: Schema.Boolean.annotate({ + - description: "Whether the thread is ephemeral and should not be materialized on disk.", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__Thread = Schema.Struct({ + - description: "Optional Git metadata captured when the thread was created.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this thread. Codex-generated thread IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - modelProvider: Schema.String.annotate({ + - description: "Model provider used for this thread (for example, 'openai').", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__Thread = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- parentThreadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "The ID of the parent thread. This will only be set if this thread is a subagent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - path: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__Thread = Schema.Struct({ + - preview: Schema.String.annotate({ + - description: "Usually the first user message in the thread, if available.", + - }), + -- recencyAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) used for thread recency ordering.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- sessionId: Schema.String.annotate({ + -- description: "Session id shared by threads that belong to the same session tree.", + -- }), + - source: Schema.Union( + - [ + - Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__Thread = Schema.Struct({ + - ], + - { mode: "oneOf" }, + - ).annotate({ description: "Current runtime status for the thread." }), + -- threadSource: Schema.optionalKey( + -- Schema.Union([ServerNotification__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional analytics source classification for this thread.", + -- }), + -- ), + - turns: Schema.Array(ServerNotification__Turn).annotate({ + - description: + - "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__TurnStartedNotification = Schema.Struct({ + - turn: ServerNotification__Turn, + - }); + - + --export type ServerRequest__AdditionalFileSystemPermissions = { + -- readonly entries?: ReadonlyArray | null; + -- readonly globScanMaxDepth?: number | null; + -- readonly read?: ReadonlyArray | null; + -- readonly write?: ReadonlyArray | null; + --}; + --export const ServerRequest__AdditionalFileSystemPermissions = Schema.Struct({ + -- entries: Schema.optionalKey( + -- Schema.Union([Schema.Array(ServerRequest__FileSystemSandboxEntry), Schema.Null]), + -- ), + -- globScanMaxDepth: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ format: "uint" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(1)), + -- Schema.Null, + -- ]), + -- ), + -- read: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(ServerRequest__LegacyAppPathString).annotate({ + -- description: "This will be removed in favor of `entries`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- write: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(ServerRequest__LegacyAppPathString).annotate({ + -- description: "This will be removed in favor of `entries`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + - export type ServerRequest__McpElicitationEnumSchema = + - | ServerRequest__McpElicitationSingleSelectEnumSchema + - | ServerRequest__McpElicitationMultiSelectEnumSchema + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerRequest__McpElicitationEnumSchema = Schema.Union([ + - ServerRequest__McpElicitationLegacyTitledEnumSchema, + - ]); + - + --export type V2ItemGuardianApprovalReviewCompletedNotification__AdditionalFileSystemPermissions = { + -- readonly entries?: ReadonlyArray | null; + -- readonly globScanMaxDepth?: number | null; + -- readonly read?: ReadonlyArray | null; + -- readonly write?: ReadonlyArray | null; + -+export type V2ConfigReadResponse__Config = { + -+ readonly analytics?: V2ConfigReadResponse__AnalyticsConfig | null; + -+ readonly approval_policy?: V2ConfigReadResponse__AskForApproval | null; + -+ readonly approvals_reviewer?: V2ConfigReadResponse__ApprovalsReviewer | null; + -+ readonly compact_prompt?: string | null; + -+ readonly developer_instructions?: string | null; + -+ readonly forced_chatgpt_workspace_id?: string | null; + -+ readonly forced_login_method?: V2ConfigReadResponse__ForcedLoginMethod | null; + -+ readonly instructions?: string | null; + -+ readonly model?: string | null; + -+ readonly model_auto_compact_token_limit?: number | null; + -+ readonly model_context_window?: number | null; + -+ readonly model_provider?: string | null; + -+ readonly model_reasoning_effort?: V2ConfigReadResponse__ReasoningEffort | null; + -+ readonly model_reasoning_summary?: V2ConfigReadResponse__ReasoningSummary | null; + -+ readonly model_verbosity?: V2ConfigReadResponse__Verbosity | null; + -+ readonly profile?: string | null; + -+ readonly profiles?: { readonly [x: string]: V2ConfigReadResponse__ProfileV2 }; + -+ readonly review_model?: string | null; + -+ readonly sandbox_mode?: V2ConfigReadResponse__SandboxMode | null; + -+ readonly sandbox_workspace_write?: V2ConfigReadResponse__SandboxWorkspaceWrite | null; + -+ readonly service_tier?: V2ConfigReadResponse__ServiceTier | null; + -+ readonly tools?: V2ConfigReadResponse__ToolsV2 | null; + -+ readonly web_search?: V2ConfigReadResponse__WebSearchMode | null; + -+ readonly [x: string]: unknown; + - }; + --export const V2ItemGuardianApprovalReviewCompletedNotification__AdditionalFileSystemPermissions = + -+export const V2ConfigReadResponse__Config = Schema.StructWithRest( + - Schema.Struct({ + -- entries: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(V2ItemGuardianApprovalReviewCompletedNotification__FileSystemSandboxEntry), + -- Schema.Null, + -- ]), + -+ analytics: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__AnalyticsConfig, Schema.Null]), + - ), + -- globScanMaxDepth: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ format: "uint" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(1)), + -- Schema.Null, + -- ]), + -+ approval_policy: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__AskForApproval, Schema.Null]), + - ), + -- read: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array( + -- V2ItemGuardianApprovalReviewCompletedNotification__LegacyAppPathString, + -- ).annotate({ description: "This will be removed in favor of `entries`." }), + -- Schema.Null, + -- ]), + -+ approvals_reviewer: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__ApprovalsReviewer, Schema.Null]).annotate({ + -+ description: + -+ "[UNSTABLE] Optional default for where approval requests are routed for review.", + -+ }), + - ), + -- write: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array( + -- V2ItemGuardianApprovalReviewCompletedNotification__LegacyAppPathString, + -- ).annotate({ description: "This will be removed in favor of `entries`." }), + -- Schema.Null, + -- ]), + -+ compact_prompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ developer_instructions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ forced_chatgpt_workspace_id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ forced_login_method: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__ForcedLoginMethod, Schema.Null]), + - ), + -- }); + -- + --export type V2ItemGuardianApprovalReviewStartedNotification__AdditionalFileSystemPermissions = { + -- readonly entries?: ReadonlyArray | null; + -- readonly globScanMaxDepth?: number | null; + -- readonly read?: ReadonlyArray | null; + -- readonly write?: ReadonlyArray | null; + --}; + --export const V2ItemGuardianApprovalReviewStartedNotification__AdditionalFileSystemPermissions = + -- Schema.Struct({ + -- entries: Schema.optionalKey( + -+ instructions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ model: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ model_auto_compact_token_limit: Schema.optionalKey( + - Schema.Union([ + -- Schema.Array(V2ItemGuardianApprovalReviewStartedNotification__FileSystemSandboxEntry), + -+ Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + - Schema.Null, + - ]), + - ), + -- globScanMaxDepth: Schema.optionalKey( + -+ model_context_window: Schema.optionalKey( + - Schema.Union([ + -- Schema.Number.annotate({ format: "uint" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(1)), + -+ Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), + - Schema.Null, + - ]), + - ), + -- read: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(V2ItemGuardianApprovalReviewStartedNotification__LegacyAppPathString).annotate( + -- { description: "This will be removed in favor of `entries`." }, + -- ), + -- Schema.Null, + -- ]), + -+ model_provider: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ model_reasoning_effort: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__ReasoningEffort, Schema.Null]), + - ), + -- write: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(V2ItemGuardianApprovalReviewStartedNotification__LegacyAppPathString).annotate( + -- { description: "This will be removed in favor of `entries`." }, + -- ), + -- Schema.Null, + -- ]), + -+ model_reasoning_summary: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__ReasoningSummary, Schema.Null]), + - ), + -- }); + -- + --export type V2PluginInstalledResponse__PluginMarketplaceEntry = { + -- readonly interface?: V2PluginInstalledResponse__MarketplaceInterface | null; + -- readonly name: string; + -- readonly path?: V2PluginInstalledResponse__AbsolutePathBuf | null; + -- readonly plugins: ReadonlyArray; + --}; + --export const V2PluginInstalledResponse__PluginMarketplaceEntry = Schema.Struct({ + -- interface: Schema.optionalKey( + -- Schema.Union([V2PluginInstalledResponse__MarketplaceInterface, Schema.Null]), + -- ), + -- name: Schema.String, + -- path: Schema.optionalKey( + -- Schema.Union([V2PluginInstalledResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: + -- "Local marketplace file path when the marketplace is backed by a local file. Remote-only catalog marketplaces do not have a local path.", + -- }), + -- ), + -- plugins: Schema.Array(V2PluginInstalledResponse__PluginSummary), + --}); + -- + --export type V2PluginListResponse__PluginMarketplaceEntry = { + -- readonly interface?: V2PluginListResponse__MarketplaceInterface | null; + -- readonly name: string; + -- readonly path?: V2PluginListResponse__AbsolutePathBuf | null; + -- readonly plugins: ReadonlyArray; + --}; + --export const V2PluginListResponse__PluginMarketplaceEntry = Schema.Struct({ + -- interface: Schema.optionalKey( + -- Schema.Union([V2PluginListResponse__MarketplaceInterface, Schema.Null]), + -- ), + -- name: Schema.String, + -- path: Schema.optionalKey( + -- Schema.Union([V2PluginListResponse__AbsolutePathBuf, Schema.Null]).annotate({ + -- description: + -- "Local marketplace file path when the marketplace is backed by a local file. Remote-only catalog marketplaces do not have a local path.", + -- }), + -- ), + -- plugins: Schema.Array(V2PluginListResponse__PluginSummary), + --}); + -- + --export type V2PluginReadResponse__PluginDetail = { + -- readonly appTemplates: ReadonlyArray; + -- readonly apps: ReadonlyArray; + -- readonly description?: string | null; + -- readonly hooks: ReadonlyArray; + -- readonly marketplaceName: string; + -- readonly marketplacePath?: V2PluginReadResponse__AbsolutePathBuf | null; + -- readonly mcpServers: ReadonlyArray; + -- readonly scheduledTasks?: ReadonlyArray | null; + -- readonly shareUrl?: string | null; + -- readonly skills: ReadonlyArray; + -- readonly summary: V2PluginReadResponse__PluginSummary; + --}; + --export const V2PluginReadResponse__PluginDetail = Schema.Struct({ + -- appTemplates: Schema.Array(V2PluginReadResponse__AppTemplateSummary), + -- apps: Schema.Array(V2PluginReadResponse__AppSummary), + -- description: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- hooks: Schema.Array(V2PluginReadResponse__PluginHookSummary), + -- marketplaceName: Schema.String, + -- marketplacePath: Schema.optionalKey( + -- Schema.Union([V2PluginReadResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -- mcpServers: Schema.Array(Schema.String), + -- scheduledTasks: Schema.optionalKey( + -- Schema.Union([Schema.Array(V2PluginReadResponse__ScheduledTaskSummary), Schema.Null]), + -- ), + -- shareUrl: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- skills: Schema.Array(V2PluginReadResponse__SkillSummary), + -- summary: V2PluginReadResponse__PluginSummary, + --}); + -- + --export type V2PluginShareListResponse__PluginShareListItem = { + -- readonly localPluginPath?: V2PluginShareListResponse__AbsolutePathBuf | null; + -- readonly plugin: V2PluginShareListResponse__PluginSummary; + --}; + --export const V2PluginShareListResponse__PluginShareListItem = Schema.Struct({ + -- localPluginPath: Schema.optionalKey( + -- Schema.Union([V2PluginShareListResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -- plugin: V2PluginShareListResponse__PluginSummary, + --}); + -+ model_verbosity: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__Verbosity, Schema.Null]), + -+ ), + -+ profile: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ profiles: Schema.optionalKey( + -+ Schema.Record(Schema.String, V2ConfigReadResponse__ProfileV2).annotate({ default: {} }), + -+ ), + -+ review_model: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ sandbox_mode: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__SandboxMode, Schema.Null]), + -+ ), + -+ sandbox_workspace_write: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__SandboxWorkspaceWrite, Schema.Null]), + -+ ), + -+ service_tier: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__ServiceTier, Schema.Null]), + -+ ), + -+ tools: Schema.optionalKey(Schema.Union([V2ConfigReadResponse__ToolsV2, Schema.Null])), + -+ web_search: Schema.optionalKey( + -+ Schema.Union([V2ConfigReadResponse__WebSearchMode, Schema.Null]), + -+ ), + -+ }), + -+ [Schema.Record(Schema.String, Schema.Unknown)], + -+); + - + - export type V2ThreadForkResponse__Thread = { + - readonly agentNickname?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkResponse__Thread = { + - readonly id: string; + - readonly modelProvider: string; + - readonly name?: string | null; + -- readonly parentThreadId?: string | null; + - readonly path?: string | null; + - readonly preview: string; + -- readonly recencyAt?: number | null; + -- readonly sessionId: string; + - readonly source: + - | "cli" + - | "vscode" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkResponse__Thread = { + - readonly activeFlags: ReadonlyArray; + - readonly type: "active"; + - }; + -- readonly threadSource?: V2ThreadForkResponse__ThreadSource | null; + - readonly turns: ReadonlyArray; + - readonly updatedAt: number; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__Thread = Schema.Struct({ + - description: "Unix timestamp (in seconds) when the thread was created.", + - format: "int64", + - }).check(Schema.isInt()), + -- cwd: Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }), + -+ cwd: Schema.String.annotate({ description: "Working directory captured for the thread." }), + - ephemeral: Schema.Boolean.annotate({ + - description: "Whether the thread is ephemeral and should not be materialized on disk.", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__Thread = Schema.Struct({ + - description: "Optional Git metadata captured when the thread was created.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this thread. Codex-generated thread IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - modelProvider: Schema.String.annotate({ + - description: "Model provider used for this thread (for example, 'openai').", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__Thread = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- parentThreadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "The ID of the parent thread. This will only be set if this thread is a subagent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - path: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__Thread = Schema.Struct({ + - preview: Schema.String.annotate({ + - description: "Usually the first user message in the thread, if available.", + - }), + -- recencyAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) used for thread recency ordering.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- sessionId: Schema.String.annotate({ + -- description: "Session id shared by threads that belong to the same session tree.", + -- }), + - source: Schema.Union( + - [ + - Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__Thread = Schema.Struct({ + - ], + - { mode: "oneOf" }, + - ).annotate({ description: "Current runtime status for the thread." }), + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadForkResponse__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional analytics source classification for this thread.", + -- }), + -- ), + - turns: Schema.Array(V2ThreadForkResponse__Turn).annotate({ + - description: + - "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadListResponse__Thread = { + - readonly id: string; + - readonly modelProvider: string; + - readonly name?: string | null; + -- readonly parentThreadId?: string | null; + - readonly path?: string | null; + - readonly preview: string; + -- readonly recencyAt?: number | null; + -- readonly sessionId: string; + - readonly source: + - | "cli" + - | "vscode" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadListResponse__Thread = { + - readonly activeFlags: ReadonlyArray; + - readonly type: "active"; + - }; + -- readonly threadSource?: V2ThreadListResponse__ThreadSource | null; + - readonly turns: ReadonlyArray; + - readonly updatedAt: number; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__Thread = Schema.Struct({ + - description: "Unix timestamp (in seconds) when the thread was created.", + - format: "int64", + - }).check(Schema.isInt()), + -- cwd: Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }), + -+ cwd: Schema.String.annotate({ description: "Working directory captured for the thread." }), + - ephemeral: Schema.Boolean.annotate({ + - description: "Whether the thread is ephemeral and should not be materialized on disk.", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__Thread = Schema.Struct({ + - description: "Optional Git metadata captured when the thread was created.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this thread. Codex-generated thread IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - modelProvider: Schema.String.annotate({ + - description: "Model provider used for this thread (for example, 'openai').", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__Thread = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- parentThreadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "The ID of the parent thread. This will only be set if this thread is a subagent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - path: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__Thread = Schema.Struct({ + - preview: Schema.String.annotate({ + - description: "Usually the first user message in the thread, if available.", + - }), + -- recencyAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) used for thread recency ordering.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- sessionId: Schema.String.annotate({ + -- description: "Session id shared by threads that belong to the same session tree.", + -- }), + - source: Schema.Union( + - [ + - Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__Thread = Schema.Struct({ + - ], + - { mode: "oneOf" }, + - ).annotate({ description: "Current runtime status for the thread." }), + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadListResponse__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional analytics source classification for this thread.", + -- }), + -- ), + - turns: Schema.Array(V2ThreadListResponse__Turn).annotate({ + - description: + - "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadMetadataUpdateResponse__Thread = { + - readonly id: string; + - readonly modelProvider: string; + - readonly name?: string | null; + -- readonly parentThreadId?: string | null; + - readonly path?: string | null; + - readonly preview: string; + -- readonly recencyAt?: number | null; + -- readonly sessionId: string; + - readonly source: + - | "cli" + - | "vscode" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadMetadataUpdateResponse__Thread = { + - readonly activeFlags: ReadonlyArray; + - readonly type: "active"; + - }; + -- readonly threadSource?: V2ThreadMetadataUpdateResponse__ThreadSource | null; + - readonly turns: ReadonlyArray; + - readonly updatedAt: number; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__Thread = Schema.Struct({ + - description: "Unix timestamp (in seconds) when the thread was created.", + - format: "int64", + - }).check(Schema.isInt()), + -- cwd: Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }), + -+ cwd: Schema.String.annotate({ description: "Working directory captured for the thread." }), + - ephemeral: Schema.Boolean.annotate({ + - description: "Whether the thread is ephemeral and should not be materialized on disk.", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__Thread = Schema.Struct({ + - description: "Optional Git metadata captured when the thread was created.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this thread. Codex-generated thread IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - modelProvider: Schema.String.annotate({ + - description: "Model provider used for this thread (for example, 'openai').", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__Thread = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- parentThreadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "The ID of the parent thread. This will only be set if this thread is a subagent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - path: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__Thread = Schema.Struct({ + - preview: Schema.String.annotate({ + - description: "Usually the first user message in the thread, if available.", + - }), + -- recencyAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) used for thread recency ordering.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- sessionId: Schema.String.annotate({ + -- description: "Session id shared by threads that belong to the same session tree.", + -- }), + - source: Schema.Union( + - [ + - Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__Thread = Schema.Struct({ + - ], + - { mode: "oneOf" }, + - ).annotate({ description: "Current runtime status for the thread." }), + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadMetadataUpdateResponse__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional analytics source classification for this thread.", + -- }), + -- ), + - turns: Schema.Array(V2ThreadMetadataUpdateResponse__Turn).annotate({ + - description: + - "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadReadResponse__Thread = { + - readonly id: string; + - readonly modelProvider: string; + - readonly name?: string | null; + -- readonly parentThreadId?: string | null; + - readonly path?: string | null; + - readonly preview: string; + -- readonly recencyAt?: number | null; + -- readonly sessionId: string; + - readonly source: + - | "cli" + - | "vscode" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadReadResponse__Thread = { + - readonly activeFlags: ReadonlyArray; + - readonly type: "active"; + - }; + -- readonly threadSource?: V2ThreadReadResponse__ThreadSource | null; + - readonly turns: ReadonlyArray; + - readonly updatedAt: number; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__Thread = Schema.Struct({ + - description: "Unix timestamp (in seconds) when the thread was created.", + - format: "int64", + - }).check(Schema.isInt()), + -- cwd: Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }), + -+ cwd: Schema.String.annotate({ description: "Working directory captured for the thread." }), + - ephemeral: Schema.Boolean.annotate({ + - description: "Whether the thread is ephemeral and should not be materialized on disk.", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__Thread = Schema.Struct({ + - description: "Optional Git metadata captured when the thread was created.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this thread. Codex-generated thread IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - modelProvider: Schema.String.annotate({ + - description: "Model provider used for this thread (for example, 'openai').", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__Thread = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- parentThreadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "The ID of the parent thread. This will only be set if this thread is a subagent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - path: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__Thread = Schema.Struct({ + - preview: Schema.String.annotate({ + - description: "Usually the first user message in the thread, if available.", + - }), + -- recencyAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) used for thread recency ordering.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- sessionId: Schema.String.annotate({ + -- description: "Session id shared by threads that belong to the same session tree.", + -- }), + - source: Schema.Union( + - [ + - Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__Thread = Schema.Struct({ + - ], + - { mode: "oneOf" }, + - ).annotate({ description: "Current runtime status for the thread." }), + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadReadResponse__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional analytics source classification for this thread.", + -- }), + -- ), + - turns: Schema.Array(V2ThreadReadResponse__Turn).annotate({ + - description: + - "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeResponse__Thread = { + - readonly id: string; + - readonly modelProvider: string; + - readonly name?: string | null; + -- readonly parentThreadId?: string | null; + - readonly path?: string | null; + - readonly preview: string; + -- readonly recencyAt?: number | null; + -- readonly sessionId: string; + - readonly source: + - | "cli" + - | "vscode" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeResponse__Thread = { + - readonly activeFlags: ReadonlyArray; + - readonly type: "active"; + - }; + -- readonly threadSource?: V2ThreadResumeResponse__ThreadSource | null; + - readonly turns: ReadonlyArray; + - readonly updatedAt: number; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__Thread = Schema.Struct({ + - description: "Unix timestamp (in seconds) when the thread was created.", + - format: "int64", + - }).check(Schema.isInt()), + -- cwd: Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }), + -+ cwd: Schema.String.annotate({ description: "Working directory captured for the thread." }), + - ephemeral: Schema.Boolean.annotate({ + - description: "Whether the thread is ephemeral and should not be materialized on disk.", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__Thread = Schema.Struct({ + - description: "Optional Git metadata captured when the thread was created.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this thread. Codex-generated thread IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - modelProvider: Schema.String.annotate({ + - description: "Model provider used for this thread (for example, 'openai').", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__Thread = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- parentThreadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "The ID of the parent thread. This will only be set if this thread is a subagent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - path: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__Thread = Schema.Struct({ + - preview: Schema.String.annotate({ + - description: "Usually the first user message in the thread, if available.", + - }), + -- recencyAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) used for thread recency ordering.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- sessionId: Schema.String.annotate({ + -- description: "Session id shared by threads that belong to the same session tree.", + -- }), + - source: Schema.Union( + - [ + - Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__Thread = Schema.Struct({ + - ], + - { mode: "oneOf" }, + - ).annotate({ description: "Current runtime status for the thread." }), + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeResponse__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional analytics source classification for this thread.", + -- }), + -- ), + - turns: Schema.Array(V2ThreadResumeResponse__Turn).annotate({ + - description: + - "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartedNotification__Thread = { + - readonly id: string; + - readonly modelProvider: string; + - readonly name?: string | null; + -- readonly parentThreadId?: string | null; + - readonly path?: string | null; + - readonly preview: string; + -- readonly recencyAt?: number | null; + -- readonly sessionId: string; + - readonly source: + - | "cli" + - | "vscode" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartedNotification__Thread = { + - readonly activeFlags: ReadonlyArray; + - readonly type: "active"; + - }; + -- readonly threadSource?: V2ThreadStartedNotification__ThreadSource | null; + - readonly turns: ReadonlyArray; + - readonly updatedAt: number; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__Thread = Schema.Struct({ + - description: "Unix timestamp (in seconds) when the thread was created.", + - format: "int64", + - }).check(Schema.isInt()), + -- cwd: Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }), + -+ cwd: Schema.String.annotate({ description: "Working directory captured for the thread." }), + - ephemeral: Schema.Boolean.annotate({ + - description: "Whether the thread is ephemeral and should not be materialized on disk.", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__Thread = Schema.Struct({ + - description: "Optional Git metadata captured when the thread was created.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this thread. Codex-generated thread IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - modelProvider: Schema.String.annotate({ + - description: "Model provider used for this thread (for example, 'openai').", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__Thread = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- parentThreadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "The ID of the parent thread. This will only be set if this thread is a subagent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - path: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__Thread = Schema.Struct({ + - preview: Schema.String.annotate({ + - description: "Usually the first user message in the thread, if available.", + - }), + -- recencyAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) used for thread recency ordering.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- sessionId: Schema.String.annotate({ + -- description: "Session id shared by threads that belong to the same session tree.", + -- }), + - source: Schema.Union( + - [ + - Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__Thread = Schema.Struct({ + - ], + - { mode: "oneOf" }, + - ).annotate({ description: "Current runtime status for the thread." }), + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadStartedNotification__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional analytics source classification for this thread.", + -- }), + -- ), + - turns: Schema.Array(V2ThreadStartedNotification__Turn).annotate({ + - description: + - "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartResponse__Thread = { + - readonly id: string; + - readonly modelProvider: string; + - readonly name?: string | null; + -- readonly parentThreadId?: string | null; + - readonly path?: string | null; + - readonly preview: string; + -- readonly recencyAt?: number | null; + -- readonly sessionId: string; + - readonly source: + - | "cli" + - | "vscode" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartResponse__Thread = { + - readonly activeFlags: ReadonlyArray; + - readonly type: "active"; + - }; + -- readonly threadSource?: V2ThreadStartResponse__ThreadSource | null; + - readonly turns: ReadonlyArray; + - readonly updatedAt: number; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__Thread = Schema.Struct({ + - description: "Unix timestamp (in seconds) when the thread was created.", + - format: "int64", + - }).check(Schema.isInt()), + -- cwd: Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }), + -+ cwd: Schema.String.annotate({ description: "Working directory captured for the thread." }), + - ephemeral: Schema.Boolean.annotate({ + - description: "Whether the thread is ephemeral and should not be materialized on disk.", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__Thread = Schema.Struct({ + - Schema.Union([V2ThreadStartResponse__GitInfo, Schema.Null]).annotate({ + - description: "Optional Git metadata captured when the thread was created.", + - }), + -- ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this thread. Codex-generated thread IDs are UUIDv7.", + -- }), + -- modelProvider: Schema.String.annotate({ + -- description: "Model provider used for this thread (for example, 'openai').", + -- }), + -- name: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Optional user-facing thread title." }), + -- Schema.Null, + -- ]), + -- ), + -- parentThreadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "The ID of the parent thread. This will only be set if this thread is a subagent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- path: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -- Schema.Null, + -- ]), + -- ), + -- preview: Schema.String.annotate({ + -- description: "Usually the first user message in the thread, if available.", + -- }), + -- recencyAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) used for thread recency ordering.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- sessionId: Schema.String.annotate({ + -- description: "Session id shared by threads that belong to the same session tree.", + -- }), + -- source: Schema.Union( + -- [ + -- Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -- Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomSessionSource" }), + -- Schema.Struct({ subAgent: V2ThreadStartResponse__SubAgentSource }).annotate({ + -- title: "SubAgentSessionSource", + -- }), + -- ], + -- { mode: "oneOf" }, + -- ).annotate({ + -- description: "Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.).", + -- }), + -- status: Schema.Union( + -- [ + -- Schema.Struct({ + -- type: Schema.Literal("notLoaded").annotate({ title: "NotLoadedThreadStatusType" }), + -- }).annotate({ title: "NotLoadedThreadStatus" }), + -- Schema.Struct({ + -- type: Schema.Literal("idle").annotate({ title: "IdleThreadStatusType" }), + -- }).annotate({ title: "IdleThreadStatus" }), + -- Schema.Struct({ + -- type: Schema.Literal("systemError").annotate({ title: "SystemErrorThreadStatusType" }), + -- }).annotate({ title: "SystemErrorThreadStatus" }), + -- Schema.Struct({ + -- activeFlags: Schema.Array(V2ThreadStartResponse__ThreadActiveFlag), + -- type: Schema.Literal("active").annotate({ title: "ActiveThreadStatusType" }), + -- }).annotate({ title: "ActiveThreadStatus" }), + -- ], + -- { mode: "oneOf" }, + -- ).annotate({ description: "Current runtime status for the thread." }), + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadStartResponse__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional analytics source classification for this thread.", + -- }), + -- ), + -- turns: Schema.Array(V2ThreadStartResponse__Turn).annotate({ + -- description: + -- "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -- }), + -- updatedAt: Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) when the thread was last updated.", + -- format: "int64", + -- }).check(Schema.isInt()), + --}); + -- + --export type V2ThreadUnarchiveResponse__Thread = { + -- readonly agentNickname?: string | null; + -- readonly agentRole?: string | null; + -- readonly cliVersion: string; + -- readonly createdAt: number; + -- readonly cwd: string; + -- readonly ephemeral: boolean; + -- readonly forkedFromId?: string | null; + -- readonly gitInfo?: V2ThreadUnarchiveResponse__GitInfo | null; + -- readonly id: string; + -- readonly modelProvider: string; + -- readonly name?: string | null; + -- readonly parentThreadId?: string | null; + -- readonly path?: string | null; + -- readonly preview: string; + -- readonly recencyAt?: number | null; + -- readonly sessionId: string; + -- readonly source: + -- | "cli" + -- | "vscode" + -- | "exec" + -- | "appServer" + -- | "unknown" + -- | { readonly custom: string } + -- | { readonly subAgent: V2ThreadUnarchiveResponse__SubAgentSource }; + -- readonly status: + -- | { readonly type: "notLoaded" } + -- | { readonly type: "idle" } + -- | { readonly type: "systemError" } + -- | { + -- readonly activeFlags: ReadonlyArray; + -- readonly type: "active"; + -- }; + -- readonly threadSource?: V2ThreadUnarchiveResponse__ThreadSource | null; + -- readonly turns: ReadonlyArray; + -- readonly updatedAt: number; + --}; + --export const V2ThreadUnarchiveResponse__Thread = Schema.Struct({ + -- agentNickname: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional random unique nickname assigned to an AgentControl-spawned sub-agent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- agentRole: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- cliVersion: Schema.String.annotate({ + -- description: "Version of the CLI that created the thread.", + -- }), + -- createdAt: Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) when the thread was created.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- cwd: Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }), + -- ephemeral: Schema.Boolean.annotate({ + -- description: "Whether the thread is ephemeral and should not be materialized on disk.", + -- }), + -- forkedFromId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Source thread id when this thread was created by forking another thread.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- gitInfo: Schema.optionalKey( + -- Schema.Union([V2ThreadUnarchiveResponse__GitInfo, Schema.Null]).annotate({ + -- description: "Optional Git metadata captured when the thread was created.", + -- }), + -- ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this thread. Codex-generated thread IDs are UUIDv7.", + -- }), + -- modelProvider: Schema.String.annotate({ + -- description: "Model provider used for this thread (for example, 'openai').", + -- }), + -- name: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Optional user-facing thread title." }), + -- Schema.Null, + -- ]), + -- ), + -- parentThreadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "The ID of the parent thread. This will only be set if this thread is a subagent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- path: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -- Schema.Null, + -- ]), + -- ), + -- preview: Schema.String.annotate({ + -- description: "Usually the first user message in the thread, if available.", + -- }), + -- recencyAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) used for thread recency ordering.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- sessionId: Schema.String.annotate({ + -- description: "Session id shared by threads that belong to the same session tree.", + -- }), + -- source: Schema.Union( + -- [ + -- Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -- Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomSessionSource" }), + -- Schema.Struct({ subAgent: V2ThreadUnarchiveResponse__SubAgentSource }).annotate({ + -- title: "SubAgentSessionSource", + -- }), + -- ], + -- { mode: "oneOf" }, + -- ).annotate({ + -- description: "Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.).", + -- }), + -- status: Schema.Union( + -- [ + -- Schema.Struct({ + -- type: Schema.Literal("notLoaded").annotate({ title: "NotLoadedThreadStatusType" }), + -- }).annotate({ title: "NotLoadedThreadStatus" }), + -- Schema.Struct({ + -- type: Schema.Literal("idle").annotate({ title: "IdleThreadStatusType" }), + -- }).annotate({ title: "IdleThreadStatus" }), + -- Schema.Struct({ + -- type: Schema.Literal("systemError").annotate({ title: "SystemErrorThreadStatusType" }), + -- }).annotate({ title: "SystemErrorThreadStatus" }), + -- Schema.Struct({ + -- activeFlags: Schema.Array(V2ThreadUnarchiveResponse__ThreadActiveFlag), + -- type: Schema.Literal("active").annotate({ title: "ActiveThreadStatusType" }), + -- }).annotate({ title: "ActiveThreadStatus" }), + -- ], + -- { mode: "oneOf" }, + -- ).annotate({ description: "Current runtime status for the thread." }), + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadUnarchiveResponse__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional analytics source classification for this thread.", + -- }), + -- ), + -- turns: Schema.Array(V2ThreadUnarchiveResponse__Turn).annotate({ + -- description: + -- "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -- }), + -- updatedAt: Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) when the thread was last updated.", + -- format: "int64", + -- }).check(Schema.isInt()), + --}); + -- + --export type McpServerElicitationRequestParams__McpElicitationPrimitiveSchema = + -- | McpServerElicitationRequestParams__McpElicitationEnumSchema + -- | McpServerElicitationRequestParams__McpElicitationStringSchema + -- | McpServerElicitationRequestParams__McpElicitationNumberSchema + -- | McpServerElicitationRequestParams__McpElicitationBooleanSchema; + --export const McpServerElicitationRequestParams__McpElicitationPrimitiveSchema = Schema.Union([ + -- McpServerElicitationRequestParams__McpElicitationEnumSchema, + -- McpServerElicitationRequestParams__McpElicitationStringSchema, + -- McpServerElicitationRequestParams__McpElicitationNumberSchema, + -- McpServerElicitationRequestParams__McpElicitationBooleanSchema, + --]); + -- + --export type PermissionsRequestApprovalParams__RequestPermissionProfile = { + -- readonly fileSystem?: PermissionsRequestApprovalParams__AdditionalFileSystemPermissions | null; + -- readonly network?: PermissionsRequestApprovalParams__AdditionalNetworkPermissions | null; + --}; + --export const PermissionsRequestApprovalParams__RequestPermissionProfile = Schema.Struct({ + -- fileSystem: Schema.optionalKey( + -- Schema.Union([PermissionsRequestApprovalParams__AdditionalFileSystemPermissions, Schema.Null]), + -- ), + -- network: Schema.optionalKey( + -- Schema.Union([PermissionsRequestApprovalParams__AdditionalNetworkPermissions, Schema.Null]), + -- ), + --}); + -- + --export type PermissionsRequestApprovalResponse__GrantedPermissionProfile = { + -- readonly fileSystem?: PermissionsRequestApprovalResponse__AdditionalFileSystemPermissions | null; + -- readonly network?: PermissionsRequestApprovalResponse__AdditionalNetworkPermissions | null; + --}; + --export const PermissionsRequestApprovalResponse__GrantedPermissionProfile = Schema.Struct({ + -- fileSystem: Schema.optionalKey( + -- Schema.Union([ + -- PermissionsRequestApprovalResponse__AdditionalFileSystemPermissions, + -- Schema.Null, + -- ]), + -- ), + -- network: Schema.optionalKey( + -- Schema.Union([PermissionsRequestApprovalResponse__AdditionalNetworkPermissions, Schema.Null]), + -- ), + --}); + -- + --export type ServerNotification__RequestPermissionProfile = { + -- readonly fileSystem?: ServerNotification__AdditionalFileSystemPermissions | null; + -- readonly network?: ServerNotification__AdditionalNetworkPermissions | null; + --}; + --export const ServerNotification__RequestPermissionProfile = Schema.Struct({ + -- fileSystem: Schema.optionalKey( + -- Schema.Union([ServerNotification__AdditionalFileSystemPermissions, Schema.Null]), + -- ), + -- network: Schema.optionalKey( + -- Schema.Union([ServerNotification__AdditionalNetworkPermissions, Schema.Null]), + -- ), + --}); + -- + --export type ServerNotification__ThreadStartedNotification = { + -- readonly thread: ServerNotification__Thread; + --}; + --export const ServerNotification__ThreadStartedNotification = Schema.Struct({ + -- thread: ServerNotification__Thread, + --}); + -- + --export type ServerRequest__RequestPermissionProfile = { + -- readonly fileSystem?: ServerRequest__AdditionalFileSystemPermissions | null; + -- readonly network?: ServerRequest__AdditionalNetworkPermissions | null; + --}; + --export const ServerRequest__RequestPermissionProfile = Schema.Struct({ + -- fileSystem: Schema.optionalKey( + -- Schema.Union([ServerRequest__AdditionalFileSystemPermissions, Schema.Null]), + -- ), + -- network: Schema.optionalKey( + -- Schema.Union([ServerRequest__AdditionalNetworkPermissions, Schema.Null]), + -- ), + --}); + -- + --export type ServerRequest__McpElicitationPrimitiveSchema = + -- | ServerRequest__McpElicitationEnumSchema + -- | ServerRequest__McpElicitationStringSchema + -- | ServerRequest__McpElicitationNumberSchema + -- | ServerRequest__McpElicitationBooleanSchema; + --export const ServerRequest__McpElicitationPrimitiveSchema = Schema.Union([ + -- ServerRequest__McpElicitationEnumSchema, + -- ServerRequest__McpElicitationStringSchema, + -- ServerRequest__McpElicitationNumberSchema, + -- ServerRequest__McpElicitationBooleanSchema, + --]); + -- + --export type V2ItemGuardianApprovalReviewCompletedNotification__RequestPermissionProfile = { + -- readonly fileSystem?: V2ItemGuardianApprovalReviewCompletedNotification__AdditionalFileSystemPermissions | null; + -- readonly network?: V2ItemGuardianApprovalReviewCompletedNotification__AdditionalNetworkPermissions | null; + --}; + --export const V2ItemGuardianApprovalReviewCompletedNotification__RequestPermissionProfile = + -- Schema.Struct({ + -- fileSystem: Schema.optionalKey( + -- Schema.Union([ + -- V2ItemGuardianApprovalReviewCompletedNotification__AdditionalFileSystemPermissions, + -- Schema.Null, + -- ]), + -- ), + -- network: Schema.optionalKey( + -- Schema.Union([ + -- V2ItemGuardianApprovalReviewCompletedNotification__AdditionalNetworkPermissions, + -- Schema.Null, + -- ]), + -- ), + -- }); + -- + --export type V2ItemGuardianApprovalReviewStartedNotification__RequestPermissionProfile = { + -- readonly fileSystem?: V2ItemGuardianApprovalReviewStartedNotification__AdditionalFileSystemPermissions | null; + -- readonly network?: V2ItemGuardianApprovalReviewStartedNotification__AdditionalNetworkPermissions | null; + --}; + --export const V2ItemGuardianApprovalReviewStartedNotification__RequestPermissionProfile = + -- Schema.Struct({ + -- fileSystem: Schema.optionalKey( + -- Schema.Union([ + -- V2ItemGuardianApprovalReviewStartedNotification__AdditionalFileSystemPermissions, + -- Schema.Null, + -- ]), + -- ), + -- network: Schema.optionalKey( + -- Schema.Union([ + -- V2ItemGuardianApprovalReviewStartedNotification__AdditionalNetworkPermissions, + -- Schema.Null, + -- ]), + -- ), + -- }); + -- + --export type McpServerElicitationRequestParams__McpElicitationSchema = { + -- readonly $schema?: string | null; + -- readonly properties: { + -- readonly [x: string]: McpServerElicitationRequestParams__McpElicitationPrimitiveSchema; + -- }; + -- readonly required?: ReadonlyArray | null; + -- readonly type: McpServerElicitationRequestParams__McpElicitationObjectType; + --}; + --export const McpServerElicitationRequestParams__McpElicitationSchema = Schema.Struct({ + -- $schema: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- properties: Schema.Record( + -- Schema.String, + -- McpServerElicitationRequestParams__McpElicitationPrimitiveSchema, + -- ), + -- required: Schema.optionalKey(Schema.Union([Schema.Array(Schema.String), Schema.Null])), + -- type: McpServerElicitationRequestParams__McpElicitationObjectType, + --}).annotate({ + -- description: + -- "Typed form schema for MCP `elicitation/create` requests.\n\nThis matches the `requestedSchema` shape from the MCP 2025-11-25 `ElicitRequestFormParams` schema.", + --}); + -- + --export type ServerNotification__GuardianApprovalReviewAction = + -- | { + -- readonly command: string; + -- readonly cwd: ServerNotification__AbsolutePathBuf; + -- readonly source: ServerNotification__GuardianCommandSource; + -- readonly type: "command"; + -- } + -- | { + -- readonly argv: ReadonlyArray; + -- readonly cwd: ServerNotification__AbsolutePathBuf; + -- readonly program: string; + -- readonly source: ServerNotification__GuardianCommandSource; + -- readonly type: "execve"; + -- } + -- | { + -- readonly cwd: ServerNotification__AbsolutePathBuf; + -- readonly files: ReadonlyArray; + -- readonly type: "applyPatch"; + -- } + -- | { + -- readonly host: string; + -- readonly port: number; + -- readonly protocol: ServerNotification__NetworkApprovalProtocol; + -- readonly target: string; + -- readonly type: "networkAccess"; + -- } + -- | { + -- readonly connectorId?: string | null; + -- readonly connectorName?: string | null; + -- readonly server: string; + -- readonly toolName: string; + -- readonly toolTitle?: string | null; + -- readonly type: "mcpToolCall"; + -- } + -- | { + -- readonly permissions: ServerNotification__RequestPermissionProfile; + -- readonly reason?: string | null; + -- readonly type: "requestPermissions"; + -- }; + --export const ServerNotification__GuardianApprovalReviewAction = Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- cwd: ServerNotification__AbsolutePathBuf, + -- source: ServerNotification__GuardianCommandSource, + -- type: Schema.Literal("command").annotate({ + -- title: "CommandGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "CommandGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- argv: Schema.Array(Schema.String), + -- cwd: ServerNotification__AbsolutePathBuf, + -- program: Schema.String, + -- source: ServerNotification__GuardianCommandSource, + -- type: Schema.Literal("execve").annotate({ title: "ExecveGuardianApprovalReviewActionType" }), + -- }).annotate({ title: "ExecveGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- cwd: ServerNotification__AbsolutePathBuf, + -- files: Schema.Array(ServerNotification__AbsolutePathBuf), + -- type: Schema.Literal("applyPatch").annotate({ + -- title: "ApplyPatchGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "ApplyPatchGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- host: Schema.String, + -- port: Schema.Number.annotate({ format: "uint16" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- protocol: ServerNotification__NetworkApprovalProtocol, + -- target: Schema.String, + -- type: Schema.Literal("networkAccess").annotate({ + -- title: "NetworkAccessGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "NetworkAccessGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- connectorId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- server: Schema.String, + -- toolName: Schema.String, + -- toolTitle: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("mcpToolCall").annotate({ + -- title: "McpToolCallGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "McpToolCallGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- permissions: ServerNotification__RequestPermissionProfile, + -- reason: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("requestPermissions").annotate({ + -- title: "RequestPermissionsGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "RequestPermissionsGuardianApprovalReviewAction" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type ServerRequest__PermissionsRequestApprovalParams = { + -- readonly cwd: ServerRequest__AbsolutePathBuf; + -- readonly environmentId?: string | null; + -- readonly itemId: string; + -- readonly permissions: ServerRequest__RequestPermissionProfile; + -- readonly reason?: string | null; + -- readonly startedAtMs: number; + -- readonly threadId: string; + -- readonly turnId: string; + --}; + --export const ServerRequest__PermissionsRequestApprovalParams = Schema.Struct({ + -- cwd: ServerRequest__AbsolutePathBuf, + -- environmentId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- itemId: Schema.String, + -- permissions: ServerRequest__RequestPermissionProfile, + -- reason: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this approval request started.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- threadId: Schema.String, + -- turnId: Schema.String, + --}); + -- + --export type ServerRequest__McpElicitationSchema = { + -- readonly $schema?: string | null; + -- readonly properties: { readonly [x: string]: ServerRequest__McpElicitationPrimitiveSchema }; + -- readonly required?: ReadonlyArray | null; + -- readonly type: ServerRequest__McpElicitationObjectType; + --}; + --export const ServerRequest__McpElicitationSchema = Schema.Struct({ + -- $schema: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- properties: Schema.Record(Schema.String, ServerRequest__McpElicitationPrimitiveSchema), + -- required: Schema.optionalKey(Schema.Union([Schema.Array(Schema.String), Schema.Null])), + -- type: ServerRequest__McpElicitationObjectType, + --}).annotate({ + -- description: + -- "Typed form schema for MCP `elicitation/create` requests.\n\nThis matches the `requestedSchema` shape from the MCP 2025-11-25 `ElicitRequestFormParams` schema.", + --}); + -- + --export type V2ItemGuardianApprovalReviewCompletedNotification__GuardianApprovalReviewAction = + -- | { + -- readonly command: string; + -- readonly cwd: V2ItemGuardianApprovalReviewCompletedNotification__AbsolutePathBuf; + -- readonly source: V2ItemGuardianApprovalReviewCompletedNotification__GuardianCommandSource; + -- readonly type: "command"; + -- } + -- | { + -- readonly argv: ReadonlyArray; + -- readonly cwd: V2ItemGuardianApprovalReviewCompletedNotification__AbsolutePathBuf; + -- readonly program: string; + -- readonly source: V2ItemGuardianApprovalReviewCompletedNotification__GuardianCommandSource; + -- readonly type: "execve"; + -- } + -- | { + -- readonly cwd: V2ItemGuardianApprovalReviewCompletedNotification__AbsolutePathBuf; + -- readonly files: ReadonlyArray; + -- readonly type: "applyPatch"; + -- } + -- | { + -- readonly host: string; + -- readonly port: number; + -- readonly protocol: V2ItemGuardianApprovalReviewCompletedNotification__NetworkApprovalProtocol; + -- readonly target: string; + -- readonly type: "networkAccess"; + -- } + -- | { + -- readonly connectorId?: string | null; + -- readonly connectorName?: string | null; + -- readonly server: string; + -- readonly toolName: string; + -- readonly toolTitle?: string | null; + -- readonly type: "mcpToolCall"; + -- } + -- | { + -- readonly permissions: V2ItemGuardianApprovalReviewCompletedNotification__RequestPermissionProfile; + -- readonly reason?: string | null; + -- readonly type: "requestPermissions"; + -- }; + --export const V2ItemGuardianApprovalReviewCompletedNotification__GuardianApprovalReviewAction = + -- Schema.Union( + -- [ + -- Schema.Struct({ + -- command: Schema.String, + -- cwd: V2ItemGuardianApprovalReviewCompletedNotification__AbsolutePathBuf, + -- source: V2ItemGuardianApprovalReviewCompletedNotification__GuardianCommandSource, + -- type: Schema.Literal("command").annotate({ + -- title: "CommandGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "CommandGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- argv: Schema.Array(Schema.String), + -- cwd: V2ItemGuardianApprovalReviewCompletedNotification__AbsolutePathBuf, + -- program: Schema.String, + -- source: V2ItemGuardianApprovalReviewCompletedNotification__GuardianCommandSource, + -- type: Schema.Literal("execve").annotate({ + -- title: "ExecveGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "ExecveGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- cwd: V2ItemGuardianApprovalReviewCompletedNotification__AbsolutePathBuf, + -- files: Schema.Array(V2ItemGuardianApprovalReviewCompletedNotification__AbsolutePathBuf), + -- type: Schema.Literal("applyPatch").annotate({ + -- title: "ApplyPatchGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "ApplyPatchGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- host: Schema.String, + -- port: Schema.Number.annotate({ format: "uint16" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- protocol: V2ItemGuardianApprovalReviewCompletedNotification__NetworkApprovalProtocol, + -- target: Schema.String, + -- type: Schema.Literal("networkAccess").annotate({ + -- title: "NetworkAccessGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "NetworkAccessGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- connectorId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- server: Schema.String, + -- toolName: Schema.String, + -- toolTitle: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("mcpToolCall").annotate({ + -- title: "McpToolCallGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "McpToolCallGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- permissions: V2ItemGuardianApprovalReviewCompletedNotification__RequestPermissionProfile, + -- reason: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("requestPermissions").annotate({ + -- title: "RequestPermissionsGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "RequestPermissionsGuardianApprovalReviewAction" }), + -- ], + -- { mode: "oneOf" }, + -- ); + -- + --export type V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalReviewAction = + -- | { + -- readonly command: string; + -- readonly cwd: V2ItemGuardianApprovalReviewStartedNotification__AbsolutePathBuf; + -- readonly source: V2ItemGuardianApprovalReviewStartedNotification__GuardianCommandSource; + -- readonly type: "command"; + -- } + -- | { + -- readonly argv: ReadonlyArray; + -- readonly cwd: V2ItemGuardianApprovalReviewStartedNotification__AbsolutePathBuf; + -- readonly program: string; + -- readonly source: V2ItemGuardianApprovalReviewStartedNotification__GuardianCommandSource; + -- readonly type: "execve"; + -- } + -- | { + -- readonly cwd: V2ItemGuardianApprovalReviewStartedNotification__AbsolutePathBuf; + -- readonly files: ReadonlyArray; + -- readonly type: "applyPatch"; + -- } + -- | { + -- readonly host: string; + -- readonly port: number; + -- readonly protocol: V2ItemGuardianApprovalReviewStartedNotification__NetworkApprovalProtocol; + -- readonly target: string; + -- readonly type: "networkAccess"; + -- } + -- | { + -- readonly connectorId?: string | null; + -- readonly connectorName?: string | null; + -- readonly server: string; + -- readonly toolName: string; + -- readonly toolTitle?: string | null; + -- readonly type: "mcpToolCall"; + -- } + -- | { + -- readonly permissions: V2ItemGuardianApprovalReviewStartedNotification__RequestPermissionProfile; + -- readonly reason?: string | null; + -- readonly type: "requestPermissions"; + -- }; + --export const V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalReviewAction = + -- Schema.Union( + -+ ), + -+ id: Schema.String, + -+ modelProvider: Schema.String.annotate({ + -+ description: "Model provider used for this thread (for example, 'openai').", + -+ }), + -+ name: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ description: "Optional user-facing thread title." }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ path: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ preview: Schema.String.annotate({ + -+ description: "Usually the first user message in the thread, if available.", + -+ }), + -+ source: Schema.Union( + -+ [ + -+ Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -+ Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomSessionSource" }), + -+ Schema.Struct({ subAgent: V2ThreadStartResponse__SubAgentSource }).annotate({ + -+ title: "SubAgentSessionSource", + -+ }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ + -+ description: "Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.).", + -+ }), + -+ status: Schema.Union( + - [ + - Schema.Struct({ + -- command: Schema.String, + -- cwd: V2ItemGuardianApprovalReviewStartedNotification__AbsolutePathBuf, + -- source: V2ItemGuardianApprovalReviewStartedNotification__GuardianCommandSource, + -- type: Schema.Literal("command").annotate({ + -- title: "CommandGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "CommandGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- argv: Schema.Array(Schema.String), + -- cwd: V2ItemGuardianApprovalReviewStartedNotification__AbsolutePathBuf, + -- program: Schema.String, + -- source: V2ItemGuardianApprovalReviewStartedNotification__GuardianCommandSource, + -- type: Schema.Literal("execve").annotate({ + -- title: "ExecveGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "ExecveGuardianApprovalReviewAction" }), + -- Schema.Struct({ + -- cwd: V2ItemGuardianApprovalReviewStartedNotification__AbsolutePathBuf, + -- files: Schema.Array(V2ItemGuardianApprovalReviewStartedNotification__AbsolutePathBuf), + -- type: Schema.Literal("applyPatch").annotate({ + -- title: "ApplyPatchGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "ApplyPatchGuardianApprovalReviewAction" }), + -+ type: Schema.Literal("notLoaded").annotate({ title: "NotLoadedThreadStatusType" }), + -+ }).annotate({ title: "NotLoadedThreadStatus" }), + - Schema.Struct({ + -- host: Schema.String, + -- port: Schema.Number.annotate({ format: "uint16" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- protocol: V2ItemGuardianApprovalReviewStartedNotification__NetworkApprovalProtocol, + -- target: Schema.String, + -- type: Schema.Literal("networkAccess").annotate({ + -- title: "NetworkAccessGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "NetworkAccessGuardianApprovalReviewAction" }), + -+ type: Schema.Literal("idle").annotate({ title: "IdleThreadStatusType" }), + -+ }).annotate({ title: "IdleThreadStatus" }), + - Schema.Struct({ + -- connectorId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- connectorName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- server: Schema.String, + -- toolName: Schema.String, + -- toolTitle: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("mcpToolCall").annotate({ + -- title: "McpToolCallGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "McpToolCallGuardianApprovalReviewAction" }), + -+ type: Schema.Literal("systemError").annotate({ title: "SystemErrorThreadStatusType" }), + -+ }).annotate({ title: "SystemErrorThreadStatus" }), + - Schema.Struct({ + -- permissions: V2ItemGuardianApprovalReviewStartedNotification__RequestPermissionProfile, + -- reason: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- type: Schema.Literal("requestPermissions").annotate({ + -- title: "RequestPermissionsGuardianApprovalReviewActionType", + -- }), + -- }).annotate({ title: "RequestPermissionsGuardianApprovalReviewAction" }), + -+ activeFlags: Schema.Array(V2ThreadStartResponse__ThreadActiveFlag), + -+ type: Schema.Literal("active").annotate({ title: "ActiveThreadStatusType" }), + -+ }).annotate({ title: "ActiveThreadStatus" }), + - ], + - { mode: "oneOf" }, + -- ); + -- + --export type ServerNotification__ItemGuardianApprovalReviewCompletedNotification = { + -- readonly action: ServerNotification__GuardianApprovalReviewAction; + -- readonly completedAtMs: number; + -- readonly decisionSource: ServerNotification__AutoReviewDecisionSource; + -- readonly review: ServerNotification__GuardianApprovalReview; + -- readonly reviewId: string; + -- readonly startedAtMs: number; + -- readonly targetItemId?: string | null; + -- readonly threadId: string; + -- readonly turnId: string; + --}; + --export const ServerNotification__ItemGuardianApprovalReviewCompletedNotification = Schema.Struct({ + -- action: ServerNotification__GuardianApprovalReviewAction, + -- completedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this review completed.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- decisionSource: ServerNotification__AutoReviewDecisionSource, + -- review: ServerNotification__GuardianApprovalReview, + -- reviewId: Schema.String.annotate({ description: "Stable identifier for this review." }), + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this review started.", + -+ ).annotate({ description: "Current runtime status for the thread." }), + -+ turns: Schema.Array(V2ThreadStartResponse__Turn).annotate({ + -+ description: + -+ "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -+ }), + -+ updatedAt: Schema.Number.annotate({ + -+ description: "Unix timestamp (in seconds) when the thread was last updated.", + - format: "int64", + - }).check(Schema.isInt()), + -- targetItemId: Schema.optionalKey( + -+}); + -+ + -+export type V2ThreadUnarchiveResponse__Thread = { + -+ readonly agentNickname?: string | null; + -+ readonly agentRole?: string | null; + -+ readonly cliVersion: string; + -+ readonly createdAt: number; + -+ readonly cwd: string; + -+ readonly ephemeral: boolean; + -+ readonly forkedFromId?: string | null; + -+ readonly gitInfo?: V2ThreadUnarchiveResponse__GitInfo | null; + -+ readonly id: string; + -+ readonly modelProvider: string; + -+ readonly name?: string | null; + -+ readonly path?: string | null; + -+ readonly preview: string; + -+ readonly source: + -+ | "cli" + -+ | "vscode" + -+ | "exec" + -+ | "appServer" + -+ | "unknown" + -+ | { readonly custom: string } + -+ | { readonly subAgent: V2ThreadUnarchiveResponse__SubAgentSource }; + -+ readonly status: + -+ | { readonly type: "notLoaded" } + -+ | { readonly type: "idle" } + -+ | { readonly type: "systemError" } + -+ | { + -+ readonly activeFlags: ReadonlyArray; + -+ readonly type: "active"; + -+ }; + -+ readonly turns: ReadonlyArray; + -+ readonly updatedAt: number; + -+}; + -+export const V2ThreadUnarchiveResponse__Thread = Schema.Struct({ + -+ agentNickname: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ + - description: + -- "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", + -+ "Optional random unique nickname assigned to an AgentControl-spawned sub-agent.", + - }), + - Schema.Null, + - ]), + - ), + -- threadId: Schema.String, + -- turnId: Schema.String, + --}).annotate({ + -- description: + -- "[UNSTABLE] Temporary notification payload for approval auto-review. This shape is expected to change soon.", + --}); + -- + --export type ServerNotification__ItemGuardianApprovalReviewStartedNotification = { + -- readonly action: ServerNotification__GuardianApprovalReviewAction; + -- readonly review: ServerNotification__GuardianApprovalReview; + -- readonly reviewId: string; + -- readonly startedAtMs: number; + -- readonly targetItemId?: string | null; + -- readonly threadId: string; + -- readonly turnId: string; + --}; + --export const ServerNotification__ItemGuardianApprovalReviewStartedNotification = Schema.Struct({ + -- action: ServerNotification__GuardianApprovalReviewAction, + -- review: ServerNotification__GuardianApprovalReview, + -- reviewId: Schema.String.annotate({ description: "Stable identifier for this review." }), + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this review started.", + -+ agentRole: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ + -+ description: "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.", + -+ }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ cliVersion: Schema.String.annotate({ + -+ description: "Version of the CLI that created the thread.", + -+ }), + -+ createdAt: Schema.Number.annotate({ + -+ description: "Unix timestamp (in seconds) when the thread was created.", + - format: "int64", + - }).check(Schema.isInt()), + -- targetItemId: Schema.optionalKey( + -+ cwd: Schema.String.annotate({ description: "Working directory captured for the thread." }), + -+ ephemeral: Schema.Boolean.annotate({ + -+ description: "Whether the thread is ephemeral and should not be materialized on disk.", + -+ }), + -+ forkedFromId: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ + -- description: + -- "Identifier for the reviewed item or tool call when one exists.\n\nIn most cases, one review maps to one target item. The exceptions are - execve reviews, where a single command may contain multiple execve calls to review (only possible when using the shell_zsh_fork feature) - network policy reviews, where there is no target item\n\nA network call is triggered by a CommandExecution item, so having a target_item_id set to the CommandExecution item would be misleading because the review is about the network call, not the command execution. Therefore, target_item_id is set to None for network policy reviews.", + -+ description: "Source thread id when this thread was created by forking another thread.", + - }), + - Schema.Null, + - ]), + - ), + -- threadId: Schema.String, + -- turnId: Schema.String, + -+ gitInfo: Schema.optionalKey( + -+ Schema.Union([V2ThreadUnarchiveResponse__GitInfo, Schema.Null]).annotate({ + -+ description: "Optional Git metadata captured when the thread was created.", + -+ }), + -+ ), + -+ id: Schema.String, + -+ modelProvider: Schema.String.annotate({ + -+ description: "Model provider used for this thread (for example, 'openai').", + -+ }), + -+ name: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ description: "Optional user-facing thread title." }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ path: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -+ Schema.Null, + -+ ]), + -+ ), + -+ preview: Schema.String.annotate({ + -+ description: "Usually the first user message in the thread, if available.", + -+ }), + -+ source: Schema.Union( + -+ [ + -+ Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -+ Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomSessionSource" }), + -+ Schema.Struct({ subAgent: V2ThreadUnarchiveResponse__SubAgentSource }).annotate({ + -+ title: "SubAgentSessionSource", + -+ }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ + -+ description: "Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.).", + -+ }), + -+ status: Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ type: Schema.Literal("notLoaded").annotate({ title: "NotLoadedThreadStatusType" }), + -+ }).annotate({ title: "NotLoadedThreadStatus" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("idle").annotate({ title: "IdleThreadStatusType" }), + -+ }).annotate({ title: "IdleThreadStatus" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("systemError").annotate({ title: "SystemErrorThreadStatusType" }), + -+ }).annotate({ title: "SystemErrorThreadStatus" }), + -+ Schema.Struct({ + -+ activeFlags: Schema.Array(V2ThreadUnarchiveResponse__ThreadActiveFlag), + -+ type: Schema.Literal("active").annotate({ title: "ActiveThreadStatusType" }), + -+ }).annotate({ title: "ActiveThreadStatus" }), + -+ ], + -+ { mode: "oneOf" }, + -+ ).annotate({ description: "Current runtime status for the thread." }), + -+ turns: Schema.Array(V2ThreadUnarchiveResponse__Turn).annotate({ + -+ description: + -+ "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -+ }), + -+ updatedAt: Schema.Number.annotate({ + -+ description: "Unix timestamp (in seconds) when the thread was last updated.", + -+ format: "int64", + -+ }).check(Schema.isInt()), + -+}); + -+ + -+export type McpServerElicitationRequestParams__McpElicitationPrimitiveSchema = + -+ | McpServerElicitationRequestParams__McpElicitationEnumSchema + -+ | McpServerElicitationRequestParams__McpElicitationStringSchema + -+ | McpServerElicitationRequestParams__McpElicitationNumberSchema + -+ | McpServerElicitationRequestParams__McpElicitationBooleanSchema; + -+export const McpServerElicitationRequestParams__McpElicitationPrimitiveSchema = Schema.Union([ + -+ McpServerElicitationRequestParams__McpElicitationEnumSchema, + -+ McpServerElicitationRequestParams__McpElicitationStringSchema, + -+ McpServerElicitationRequestParams__McpElicitationNumberSchema, + -+ McpServerElicitationRequestParams__McpElicitationBooleanSchema, + -+]); + -+ + -+export type ServerNotification__ThreadStartedNotification = { + -+ readonly thread: ServerNotification__Thread; + -+}; + -+export const ServerNotification__ThreadStartedNotification = Schema.Struct({ + -+ thread: ServerNotification__Thread, + -+}); + -+ + -+export type ServerRequest__McpElicitationPrimitiveSchema = + -+ | ServerRequest__McpElicitationEnumSchema + -+ | ServerRequest__McpElicitationStringSchema + -+ | ServerRequest__McpElicitationNumberSchema + -+ | ServerRequest__McpElicitationBooleanSchema; + -+export const ServerRequest__McpElicitationPrimitiveSchema = Schema.Union([ + -+ ServerRequest__McpElicitationEnumSchema, + -+ ServerRequest__McpElicitationStringSchema, + -+ ServerRequest__McpElicitationNumberSchema, + -+ ServerRequest__McpElicitationBooleanSchema, + -+]); + -+ + -+export type McpServerElicitationRequestParams__McpElicitationSchema = { + -+ readonly $schema?: string | null; + -+ readonly properties: { + -+ readonly [x: string]: McpServerElicitationRequestParams__McpElicitationPrimitiveSchema; + -+ }; + -+ readonly required?: ReadonlyArray | null; + -+ readonly type: McpServerElicitationRequestParams__McpElicitationObjectType; + -+}; + -+export const McpServerElicitationRequestParams__McpElicitationSchema = Schema.Struct({ + -+ $schema: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ properties: Schema.Record( + -+ Schema.String, + -+ McpServerElicitationRequestParams__McpElicitationPrimitiveSchema, + -+ ), + -+ required: Schema.optionalKey(Schema.Union([Schema.Array(Schema.String), Schema.Null])), + -+ type: McpServerElicitationRequestParams__McpElicitationObjectType, + -+}).annotate({ + -+ description: + -+ "Typed form schema for MCP `elicitation/create` requests.\n\nThis matches the `requestedSchema` shape from the MCP 2025-11-25 `ElicitRequestFormParams` schema.", + -+}); + -+ + -+export type ServerRequest__McpElicitationSchema = { + -+ readonly $schema?: string | null; + -+ readonly properties: { readonly [x: string]: ServerRequest__McpElicitationPrimitiveSchema }; + -+ readonly required?: ReadonlyArray | null; + -+ readonly type: ServerRequest__McpElicitationObjectType; + -+}; + -+export const ServerRequest__McpElicitationSchema = Schema.Struct({ + -+ $schema: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ properties: Schema.Record(Schema.String, ServerRequest__McpElicitationPrimitiveSchema), + -+ required: Schema.optionalKey(Schema.Union([Schema.Array(Schema.String), Schema.Null])), + -+ type: ServerRequest__McpElicitationObjectType, + - }).annotate({ + - description: + -- "[UNSTABLE] Temporary notification payload for approval auto-review. This shape is expected to change soon.", + -+ "Typed form schema for MCP `elicitation/create` requests.\n\nThis matches the `requestedSchema` shape from the MCP 2025-11-25 `ElicitRequestFormParams` schema.", + - }); + - + - export type ServerRequest__McpServerElicitationRequestParams = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerRequest__McpServerElicitationRequestParams = + - readonly threadId: string; + - readonly turnId?: string | null; + - } + -- | { + -- readonly _meta?: unknown; + -- readonly message: string; + -- readonly mode: "openai/form"; + -- readonly requestedSchema: unknown; + -- readonly serverName: string; + -- readonly threadId: string; + -- readonly turnId?: string | null; + -- } + - | { + - readonly _meta?: unknown; + - readonly elicitationId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerRequest__McpServerElicitationRequestParams = Schema.Union( + - ]), + - ), + - }), + -- Schema.Struct({ + -- _meta: Schema.optionalKey(Schema.Unknown), + -- message: Schema.String, + -- mode: Schema.Literal("openai/form"), + -- requestedSchema: Schema.Unknown, + -- serverName: Schema.String, + -- threadId: Schema.String, + -- turnId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Active Codex turn when this elicitation was observed, if app-server could correlate one.\n\nThis is nullable because MCP models elicitation as a standalone server-to-client request identified by the MCP server request id. It may be triggered during a turn, but turn context is app-server correlation rather than part of the protocol identity of the elicitation itself.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- }), + - Schema.Struct({ + - _meta: Schema.optionalKey(Schema.Unknown), + - elicitationId: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ApplyPatchApprovalResponse = Schema.Struct({ + - decision: ApplyPatchApprovalResponse__ReviewDecision, + - }).annotate({ title: "ApplyPatchApprovalResponse" }); + - + --export type AttestationGenerateParams = {}; + --export const AttestationGenerateParams = Schema.Struct({}).annotate({ + -- title: "AttestationGenerateParams", + --}); + -- + --export type AttestationGenerateResponse = { readonly token: string }; + --export const AttestationGenerateResponse = Schema.Struct({ + -- token: Schema.String.annotate({ description: "Opaque client attestation token." }), + --}).annotate({ title: "AttestationGenerateResponse" }); + -- + - export type ChatgptAuthTokensRefreshParams = { + - readonly previousAccountId?: string | null; + - readonly reason: ChatgptAuthTokensRefreshParams__ChatgptAuthTokensRefreshReason; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest = + - readonly method: "thread/archive"; + - readonly params: ClientRequest__ThreadArchiveParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "thread/delete"; + -- readonly params: ClientRequest__ThreadDeleteParams; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "thread/unsubscribe"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest = + - readonly method: "thread/name/set"; + - readonly params: ClientRequest__ThreadSetNameParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "thread/goal/set"; + -- readonly params: ClientRequest__ThreadGoalSetParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "thread/goal/get"; + -- readonly params: ClientRequest__ThreadGoalGetParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "thread/goal/clear"; + -- readonly params: ClientRequest__ThreadGoalClearParams; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "thread/metadata/update"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest = + - readonly method: "thread/shellCommand"; + - readonly params: ClientRequest__ThreadShellCommandParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "thread/approveGuardianDeniedAction"; + -- readonly params: ClientRequest__ThreadApproveGuardianDeniedActionParams; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "thread/rollback"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest = + - readonly method: "thread/read"; + - readonly params: ClientRequest__ThreadReadParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "thread/inject_items"; + -- readonly params: ClientRequest__ThreadInjectItemsParams; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "skills/list"; + - readonly params: ClientRequest__SkillsListParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "skills/extraRoots/set"; + -- readonly params: ClientRequest__SkillsExtraRootsSetParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "hooks/list"; + -- readonly params: ClientRequest__HooksListParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "marketplace/add"; + -- readonly params: ClientRequest__MarketplaceAddParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "marketplace/remove"; + -- readonly params: ClientRequest__MarketplaceRemoveParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "marketplace/upgrade"; + -- readonly params: ClientRequest__MarketplaceUpgradeParams; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "plugin/list"; + - readonly params: ClientRequest__PluginListParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "plugin/installed"; + -- readonly params: ClientRequest__PluginInstalledParams; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "plugin/read"; + - readonly params: ClientRequest__PluginReadParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "plugin/skill/read"; + -- readonly params: ClientRequest__PluginSkillReadParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "plugin/share/save"; + -- readonly params: ClientRequest__PluginShareSaveParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "plugin/share/updateTargets"; + -- readonly params: ClientRequest__PluginShareUpdateTargetsParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "plugin/share/list"; + -- readonly params: ClientRequest__PluginShareListParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "plugin/share/checkout"; + -- readonly params: ClientRequest__PluginShareCheckoutParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "plugin/share/delete"; + -- readonly params: ClientRequest__PluginShareDeleteParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "app/read"; + -- readonly params: ClientRequest__AppsReadParams; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "app/list"; + - readonly params: ClientRequest__AppsListParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "app/installed"; + -- readonly params: ClientRequest__AppsInstalledParams; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "fs/readFile"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest = + - readonly method: "model/list"; + - readonly params: ClientRequest__ModelListParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "modelProvider/capabilities/read"; + -- readonly params: ClientRequest__ModelProviderCapabilitiesReadParams; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "experimentalFeature/list"; + - readonly params: ClientRequest__ExperimentalFeatureListParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "permissionProfile/list"; + -- readonly params: ClientRequest__PermissionProfileListParams; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "experimentalFeature/enablement/set"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest = + - readonly method: "windowsSandbox/setupStart"; + - readonly params: ClientRequest__WindowsSandboxSetupStartParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "windowsSandbox/readiness"; + -- readonly params?: null; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "account/login/start"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest = + - readonly method: "account/rateLimits/read"; + - readonly params?: null; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "account/rateLimitResetCredit/consume"; + -- readonly params: ClientRequest__ConsumeAccountRateLimitResetCreditParams; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "account/usage/read"; + -- readonly params?: null; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "account/workspaceMessages/read"; + -- readonly params?: null; + -- } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "account/sendAddCreditsNudgeEmail"; + -- readonly params: ClientRequest__SendAddCreditsNudgeEmailParams; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "feedback/upload"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest = + - readonly method: "externalAgentConfig/import"; + - readonly params: ClientRequest__ExternalAgentConfigImportParams; + - } + -- | { + -- readonly id: ClientRequest__RequestId; + -- readonly method: "externalAgentConfig/import/readHistories"; + -- readonly params?: null; + -- } + - | { + - readonly id: ClientRequest__RequestId; + - readonly method: "config/value/write"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest = Schema.Union( + - method: Schema.Literal("thread/archive").annotate({ title: "Thread/archiveRequestMethod" }), + - params: ClientRequest__ThreadArchiveParams, + - }).annotate({ title: "Thread/archiveRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("thread/delete").annotate({ title: "Thread/deleteRequestMethod" }), + -- params: ClientRequest__ThreadDeleteParams, + -- }).annotate({ title: "Thread/deleteRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("thread/unsubscribe").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest = Schema.Union( + - method: Schema.Literal("thread/name/set").annotate({ title: "Thread/name/setRequestMethod" }), + - params: ClientRequest__ThreadSetNameParams, + - }).annotate({ title: "Thread/name/setRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("thread/goal/set").annotate({ title: "Thread/goal/setRequestMethod" }), + -- params: ClientRequest__ThreadGoalSetParams, + -- }).annotate({ title: "Thread/goal/setRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("thread/goal/get").annotate({ title: "Thread/goal/getRequestMethod" }), + -- params: ClientRequest__ThreadGoalGetParams, + -- }).annotate({ title: "Thread/goal/getRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("thread/goal/clear").annotate({ + -- title: "Thread/goal/clearRequestMethod", + -- }), + -- params: ClientRequest__ThreadGoalClearParams, + -- }).annotate({ title: "Thread/goal/clearRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("thread/metadata/update").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest = Schema.Union( + - }), + - params: ClientRequest__ThreadShellCommandParams, + - }).annotate({ title: "Thread/shellCommandRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("thread/approveGuardianDeniedAction").annotate({ + -- title: "Thread/approveGuardianDeniedActionRequestMethod", + -- }), + -- params: ClientRequest__ThreadApproveGuardianDeniedActionParams, + -- }).annotate({ title: "Thread/approveGuardianDeniedActionRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("thread/rollback").annotate({ title: "Thread/rollbackRequestMethod" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest = Schema.Union( + - method: Schema.Literal("thread/read").annotate({ title: "Thread/readRequestMethod" }), + - params: ClientRequest__ThreadReadParams, + - }).annotate({ title: "Thread/readRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("thread/inject_items").annotate({ + -- title: "Thread/injectItemsRequestMethod", + -- }), + -- params: ClientRequest__ThreadInjectItemsParams, + -- }).annotate({ + -- title: "Thread/injectItemsRequest", + -- description: + -- "Append raw Responses API items to the thread history without starting a user turn.", + -- }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("skills/list").annotate({ title: "Skills/listRequestMethod" }), + - params: ClientRequest__SkillsListParams, + - }).annotate({ title: "Skills/listRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("skills/extraRoots/set").annotate({ + -- title: "Skills/extraRoots/setRequestMethod", + -- }), + -- params: ClientRequest__SkillsExtraRootsSetParams, + -- }).annotate({ title: "Skills/extraRoots/setRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("hooks/list").annotate({ title: "Hooks/listRequestMethod" }), + -- params: ClientRequest__HooksListParams, + -- }).annotate({ title: "Hooks/listRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("marketplace/add").annotate({ title: "Marketplace/addRequestMethod" }), + -- params: ClientRequest__MarketplaceAddParams, + -- }).annotate({ title: "Marketplace/addRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("marketplace/remove").annotate({ + -- title: "Marketplace/removeRequestMethod", + -- }), + -- params: ClientRequest__MarketplaceRemoveParams, + -- }).annotate({ title: "Marketplace/removeRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("marketplace/upgrade").annotate({ + -- title: "Marketplace/upgradeRequestMethod", + -- }), + -- params: ClientRequest__MarketplaceUpgradeParams, + -- }).annotate({ title: "Marketplace/upgradeRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("plugin/list").annotate({ title: "Plugin/listRequestMethod" }), + - params: ClientRequest__PluginListParams, + - }).annotate({ title: "Plugin/listRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("plugin/installed").annotate({ + -- title: "Plugin/installedRequestMethod", + -- }), + -- params: ClientRequest__PluginInstalledParams, + -- }).annotate({ title: "Plugin/installedRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("plugin/read").annotate({ title: "Plugin/readRequestMethod" }), + - params: ClientRequest__PluginReadParams, + - }).annotate({ title: "Plugin/readRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("plugin/skill/read").annotate({ + -- title: "Plugin/skill/readRequestMethod", + -- }), + -- params: ClientRequest__PluginSkillReadParams, + -- }).annotate({ title: "Plugin/skill/readRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("plugin/share/save").annotate({ + -- title: "Plugin/share/saveRequestMethod", + -- }), + -- params: ClientRequest__PluginShareSaveParams, + -- }).annotate({ title: "Plugin/share/saveRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("plugin/share/updateTargets").annotate({ + -- title: "Plugin/share/updateTargetsRequestMethod", + -- }), + -- params: ClientRequest__PluginShareUpdateTargetsParams, + -- }).annotate({ title: "Plugin/share/updateTargetsRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("plugin/share/list").annotate({ + -- title: "Plugin/share/listRequestMethod", + -- }), + -- params: ClientRequest__PluginShareListParams, + -- }).annotate({ title: "Plugin/share/listRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("plugin/share/checkout").annotate({ + -- title: "Plugin/share/checkoutRequestMethod", + -- }), + -- params: ClientRequest__PluginShareCheckoutParams, + -- }).annotate({ title: "Plugin/share/checkoutRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("plugin/share/delete").annotate({ + -- title: "Plugin/share/deleteRequestMethod", + -- }), + -- params: ClientRequest__PluginShareDeleteParams, + -- }).annotate({ title: "Plugin/share/deleteRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("app/read").annotate({ title: "App/readRequestMethod" }), + -- params: ClientRequest__AppsReadParams, + -- }).annotate({ title: "App/readRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("app/list").annotate({ title: "App/listRequestMethod" }), + - params: ClientRequest__AppsListParams, + - }).annotate({ title: "App/listRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("app/installed").annotate({ title: "App/installedRequestMethod" }), + -- params: ClientRequest__AppsInstalledParams, + -- }).annotate({ title: "App/installedRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("fs/readFile").annotate({ title: "Fs/readFileRequestMethod" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest = Schema.Union( + - method: Schema.Literal("model/list").annotate({ title: "Model/listRequestMethod" }), + - params: ClientRequest__ModelListParams, + - }).annotate({ title: "Model/listRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("modelProvider/capabilities/read").annotate({ + -- title: "ModelProvider/capabilities/readRequestMethod", + -- }), + -- params: ClientRequest__ModelProviderCapabilitiesReadParams, + -- }).annotate({ title: "ModelProvider/capabilities/readRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("experimentalFeature/list").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest = Schema.Union( + - }), + - params: ClientRequest__ExperimentalFeatureListParams, + - }).annotate({ title: "ExperimentalFeature/listRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("permissionProfile/list").annotate({ + -- title: "PermissionProfile/listRequestMethod", + -- }), + -- params: ClientRequest__PermissionProfileListParams, + -- }).annotate({ title: "PermissionProfile/listRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("experimentalFeature/enablement/set").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest = Schema.Union( + - }), + - params: ClientRequest__WindowsSandboxSetupStartParams, + - }).annotate({ title: "WindowsSandbox/setupStartRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("windowsSandbox/readiness").annotate({ + -- title: "WindowsSandbox/readinessRequestMethod", + -- }), + -- params: Schema.optionalKey(Schema.Null), + -- }).annotate({ title: "WindowsSandbox/readinessRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("account/login/start").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest = Schema.Union( + - }), + - params: Schema.optionalKey(Schema.Null), + - }).annotate({ title: "Account/rateLimits/readRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("account/rateLimitResetCredit/consume").annotate({ + -- title: "Account/rateLimitResetCredit/consumeRequestMethod", + -- }), + -- params: ClientRequest__ConsumeAccountRateLimitResetCreditParams, + -- }).annotate({ title: "Account/rateLimitResetCredit/consumeRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("account/usage/read").annotate({ + -- title: "Account/usage/readRequestMethod", + -- }), + -- params: Schema.optionalKey(Schema.Null), + -- }).annotate({ title: "Account/usage/readRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("account/workspaceMessages/read").annotate({ + -- title: "Account/workspaceMessages/readRequestMethod", + -- }), + -- params: Schema.optionalKey(Schema.Null), + -- }).annotate({ title: "Account/workspaceMessages/readRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("account/sendAddCreditsNudgeEmail").annotate({ + -- title: "Account/sendAddCreditsNudgeEmailRequestMethod", + -- }), + -- params: ClientRequest__SendAddCreditsNudgeEmailParams, + -- }).annotate({ title: "Account/sendAddCreditsNudgeEmailRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("feedback/upload").annotate({ title: "Feedback/uploadRequestMethod" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest = Schema.Union( + - }), + - params: ClientRequest__ExternalAgentConfigImportParams, + - }).annotate({ title: "ExternalAgentConfig/importRequest" }), + -- Schema.Struct({ + -- id: ClientRequest__RequestId, + -- method: Schema.Literal("externalAgentConfig/import/readHistories").annotate({ + -- title: "ExternalAgentConfig/import/readHistoriesRequestMethod", + -- }), + -- params: Schema.optionalKey(Schema.Null), + -- }).annotate({ title: "ExternalAgentConfig/import/readHistoriesRequest" }), + - Schema.Struct({ + - id: ClientRequest__RequestId, + - method: Schema.Literal("config/value/write").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest = Schema.Union( + - { mode: "oneOf" }, + - ).annotate({ title: "ClientRequest", description: "Request from the client to the server." }); + - + --export type ClientRequest__AdditionalContextEntry = { + -- readonly kind: ClientRequest__AdditionalContextKind; + -- readonly value: string; + --}; + --export const ClientRequest__AdditionalContextEntry = Schema.Struct({ + -- kind: ClientRequest__AdditionalContextKind, + -- value: Schema.String, + --}); + -- + - export type ClientRequest__ByteRange = { readonly end: number; readonly start: number }; + - export const ClientRequest__ByteRange = Schema.Struct({ + - end: Schema.Number.annotate({ format: "uint" }) + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ByteRange = Schema.Struct({ + - .check(Schema.isGreaterThanOrEqualTo(0)), + - }); + - + --export type ClientRequest__CapabilityRootLocation = { + -- readonly environmentId: string; + -- readonly path: string; + -- readonly type: "environment"; + --}; + --export const ClientRequest__CapabilityRootLocation = Schema.Union( + -- [ + -- Schema.Struct({ + -- environmentId: Schema.String, + -- path: Schema.String.annotate({ + -- description: "Absolute path for the root in the selected environment.", + -- }), + -- type: Schema.Literal("environment").annotate({ + -- title: "EnvironmentCapabilityRootLocationType", + -- }), + -- }).annotate({ + -- title: "EnvironmentCapabilityRootLocation", + -- description: "A path owned by an execution environment.", + -- }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ description: "Location used to resolve a selected capability root." }); + -- + --export type ClientRequest__CodexResponseHandoffMode = "thinking" | "commentary" | "bemTags"; + --export const ClientRequest__CodexResponseHandoffMode = Schema.Literals([ + -- "thinking", + -- "commentary", + -- "bemTags", + --]); + -- + - export type ClientRequest__CollaborationMode = { + - readonly mode: ClientRequest__ModeKind; + - readonly settings: ClientRequest__Settings; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__CollaborationMode = Schema.Struct({ + - settings: ClientRequest__Settings, + - }).annotate({ description: "Collaboration mode for a Codex session." }); + - + --export type ClientRequest__DynamicToolSpec = + -+export type ClientRequest__DynamicToolSpec = { + -+ readonly deferLoading?: boolean; + -+ readonly description: string; + -+ readonly inputSchema: unknown; + -+ readonly name: string; + -+}; + -+export const ClientRequest__DynamicToolSpec = Schema.Struct({ + -+ deferLoading: Schema.optionalKey(Schema.Boolean), + -+ description: Schema.String, + -+ inputSchema: Schema.Unknown, + -+ name: Schema.String, + -+}); + -+ + -+export type ClientRequest__NetworkAccess = "restricted" | "enabled"; + -+export const ClientRequest__NetworkAccess = Schema.Literals(["restricted", "enabled"]); + -+ + -+export type ClientRequest__ReadOnlyAccess = + - | { + -- readonly deferLoading?: boolean; + -- readonly description: string; + -- readonly inputSchema: unknown; + -- readonly name: string; + -- readonly type: "function"; + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + - } + -- | { + -- readonly description: string; + -- readonly name: string; + -- readonly tools: ReadonlyArray; + -- readonly type: "namespace"; + -- }; + --export const ClientRequest__DynamicToolSpec = Schema.Union( + -+ | { readonly type: "fullAccess" }; + -+export const ClientRequest__ReadOnlyAccess = Schema.Union( + - [ + - Schema.Struct({ + -- deferLoading: Schema.optionalKey(Schema.Boolean), + -- description: Schema.String, + -- inputSchema: Schema.Unknown, + -- name: Schema.String, + -- type: Schema.Literal("function").annotate({ title: "FunctionDynamicToolSpecType" }), + -- }).annotate({ title: "FunctionDynamicToolSpec" }), + -+ includePlatformDefaults: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(ClientRequest__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ title: "RestrictedReadOnlyAccessType" }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + - Schema.Struct({ + -- description: Schema.String, + -- name: Schema.String, + -- tools: Schema.Array(ClientRequest__DynamicToolNamespaceTool), + -- type: Schema.Literal("namespace").annotate({ title: "NamespaceDynamicToolSpecType" }), + -- }).annotate({ title: "NamespaceDynamicToolSpec" }), + -+ type: Schema.Literal("fullAccess").annotate({ title: "FullAccessReadOnlyAccessType" }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + - ], + - { mode: "oneOf" }, + - ); + - + --export type ClientRequest__MultiAgentMode = + -- | "explicitRequestOnly" + -- | "proactive" + -- | { readonly custom: string }; + --export const ClientRequest__MultiAgentMode = Schema.Union( + -- [ + -- Schema.Literals(["explicitRequestOnly", "proactive"]), + -- Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomMultiAgentMode" }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ + -- description: + -- "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.", + --}); + -- + --export type ClientRequest__NetworkAccess = "restricted" | "enabled"; + --export const ClientRequest__NetworkAccess = Schema.Literals(["restricted", "enabled"]); + -- + --export type ClientRequest__ProcessTerminalSize = { readonly cols: number; readonly rows: number }; + --export const ClientRequest__ProcessTerminalSize = Schema.Struct({ + -- cols: Schema.Number.annotate({ + -- description: "Terminal width in character cells.", + -- format: "uint16", + -- }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- rows: Schema.Number.annotate({ + -- description: "Terminal height in character cells.", + -- format: "uint16", + -- }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + --}).annotate({ description: "PTY size in character cells for `process/spawn` PTY sessions." }); + -- + --export type ClientRequest__RealtimeConversationVersion = "v1" | "v2" | "v3"; + --export const ClientRequest__RealtimeConversationVersion = Schema.Literals(["v1", "v2", "v3"]); + -- + --export type ClientRequest__RealtimeOutputModality = "text" | "audio"; + --export const ClientRequest__RealtimeOutputModality = Schema.Literals(["text", "audio"]); + -- + - export type ClientRequest__RealtimeVoice = + - | "alloy" + - | "arbor" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__RealtimeVoice = Schema.Literals([ + - "verse", + - ]); + - + --export type ClientRequest__RemoteControlDisableParams = { readonly ephemeral?: boolean }; + --export const ClientRequest__RemoteControlDisableParams = Schema.Struct({ + -- ephemeral: Schema.optionalKey(Schema.Boolean), + --}); + -- + --export type ClientRequest__RemoteControlEnableParams = { readonly ephemeral?: boolean }; + --export const ClientRequest__RemoteControlEnableParams = Schema.Struct({ + -- ephemeral: Schema.optionalKey(Schema.Boolean), + --}); + -- + - export type ClientRequest__ResponseItem = + - | { + - readonly content: ReadonlyArray; + -+ readonly end_turn?: boolean | null; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + - readonly phase?: ClientRequest__MessagePhase | null; + - readonly role: string; + - readonly type: "message"; + - } + -- | { + -- readonly author: string; + -- readonly content: ReadonlyArray; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + -- readonly recipient: string; + -- readonly type: "agent_message"; + -- } + - | { + - readonly content?: ReadonlyArray | null; + - readonly encrypted_content?: string | null; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + - readonly summary: ReadonlyArray; + - readonly type: "reasoning"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest__ResponseItem = + - readonly action: ClientRequest__LocalShellAction; + - readonly call_id?: string | null; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + - readonly status: ClientRequest__LocalShellStatus; + - readonly type: "local_shell_call"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest__ResponseItem = + - readonly arguments: string; + - readonly call_id: string; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + - readonly name: string; + - readonly namespace?: string | null; + - readonly type: "function_call"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest__ResponseItem = + - readonly call_id?: string | null; + - readonly execution: string; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + - readonly status?: string | null; + - readonly type: "tool_search_call"; + - } + - | { + - readonly call_id: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + - readonly output: ClientRequest__FunctionCallOutputBody; + - readonly type: "function_call_output"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest__ResponseItem = + - readonly call_id: string; + - readonly id?: string | null; + - readonly input: string; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + - readonly name: string; + -- readonly namespace?: string | null; + - readonly status?: string | null; + - readonly type: "custom_tool_call"; + - } + - | { + - readonly call_id: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + - readonly name?: string | null; + - readonly output: ClientRequest__FunctionCallOutputBody; + - readonly type: "custom_tool_call_output"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest__ResponseItem = + - | { + - readonly call_id?: string | null; + - readonly execution: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + - readonly status: string; + - readonly tools: ReadonlyArray; + - readonly type: "tool_search_output"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ClientRequest__ResponseItem = + - | { + - readonly action?: ClientRequest__ResponsesApiWebSearchAction | null; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + - readonly status?: string | null; + - readonly type: "web_search_call"; + - } + - | { + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + -+ readonly id: string; + - readonly result: string; + - readonly revised_prompt?: string | null; + - readonly status: string; + - readonly type: "image_generation_call"; + - } + -- | { + -- readonly encrypted_content: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + -- readonly type: "compaction"; + -- } + -- | { readonly type: "compaction_trigger" } + -- | { + -- readonly encrypted_content?: string | null; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: ClientRequest__InternalChatMessageMetadataPassthrough | null; + -- readonly type: "context_compaction"; + -- } + -+ | { readonly ghost_commit: ClientRequest__GhostCommit; readonly type: "ghost_snapshot" } + -+ | { readonly encrypted_content: string; readonly type: "compaction" } + - | { readonly type: "other" }; + - export const ClientRequest__ResponseItem = Schema.Union( + - [ + - Schema.Struct({ + - content: Schema.Array(ClientRequest__ContentItem), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -+ end_turn: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - phase: Schema.optionalKey(Schema.Union([ClientRequest__MessagePhase, Schema.Null])), + - role: Schema.String, + - type: Schema.Literal("message").annotate({ title: "MessageResponseItemType" }), + - }).annotate({ title: "MessageResponseItem" }), + -- Schema.Struct({ + -- author: Schema.String, + -- content: Schema.Array(ClientRequest__AgentMessageInputContent), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + -- recipient: Schema.String, + -- type: Schema.Literal("agent_message").annotate({ title: "AgentMessageResponseItemType" }), + -- }).annotate({ title: "AgentMessageResponseItem" }), + - Schema.Struct({ + - content: Schema.optionalKey( + - Schema.Union([Schema.Array(ClientRequest__ReasoningItemContent), Schema.Null]), + - ), + - encrypted_content: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - summary: Schema.Array(ClientRequest__ReasoningItemReasoningSummary), + - type: Schema.Literal("reasoning").annotate({ title: "ReasoningResponseItemType" }), + - }).annotate({ title: "ReasoningResponseItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ResponseItem = Schema.Union( + - Schema.Union([ + - Schema.String.annotate({ + - description: "Legacy id field retained for compatibility with older payloads.", + -+ writeOnly: true, + - }), + - Schema.Null, + - ]), + - ), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - status: ClientRequest__LocalShellStatus, + - type: Schema.Literal("local_shell_call").annotate({ + - title: "LocalShellCallResponseItemType", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ResponseItem = Schema.Union( + - Schema.Struct({ + - arguments: Schema.String, + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - name: Schema.String, + - namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ResponseItem = Schema.Union( + - arguments: Schema.Unknown, + - call_id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - execution: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - status: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - type: Schema.Literal("tool_search_call").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ResponseItem = Schema.Union( + - }).annotate({ title: "ToolSearchCallResponseItem" }), + - Schema.Struct({ + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - output: ClientRequest__FunctionCallOutputBody, + - type: Schema.Literal("function_call_output").annotate({ + - title: "FunctionCallOutputResponseItemType", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ResponseItem = Schema.Union( + - }).annotate({ title: "FunctionCallOutputResponseItem" }), + - Schema.Struct({ + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- input: Schema.String, + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + -+ input: Schema.String, + - name: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - type: Schema.Literal("custom_tool_call").annotate({ + - title: "CustomToolCallResponseItemType", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ResponseItem = Schema.Union( + - }).annotate({ title: "CustomToolCallResponseItem" }), + - Schema.Struct({ + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - name: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - output: ClientRequest__FunctionCallOutputBody, + - type: Schema.Literal("custom_tool_call_output").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ResponseItem = Schema.Union( + - Schema.Struct({ + - call_id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - execution: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - status: Schema.String, + - tools: Schema.Array(Schema.Unknown), + - type: Schema.Literal("tool_search_output").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ResponseItem = Schema.Union( + - action: Schema.optionalKey( + - Schema.Union([ClientRequest__ResponsesApiWebSearchAction, Schema.Null]), + - ), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - status: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - type: Schema.Literal("web_search_call").annotate({ title: "WebSearchCallResponseItemType" }), + - }).annotate({ title: "WebSearchCallResponseItem" }), + - Schema.Struct({ + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + -+ id: Schema.String, + - result: Schema.String, + - revised_prompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ResponseItem = Schema.Union( + - title: "ImageGenerationCallResponseItemType", + - }), + - }).annotate({ title: "ImageGenerationCallResponseItem" }), + -+ Schema.Struct({ + -+ ghost_commit: ClientRequest__GhostCommit, + -+ type: Schema.Literal("ghost_snapshot").annotate({ title: "GhostSnapshotResponseItemType" }), + -+ }).annotate({ title: "GhostSnapshotResponseItem" }), + - Schema.Struct({ + - encrypted_content: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - type: Schema.Literal("compaction").annotate({ title: "CompactionResponseItemType" }), + - }).annotate({ title: "CompactionResponseItem" }), + -- Schema.Struct({ + -- type: Schema.Literal("compaction_trigger").annotate({ + -- title: "CompactionTriggerResponseItemType", + -- }), + -- }).annotate({ title: "CompactionTriggerResponseItem" }), + -- Schema.Struct({ + -- encrypted_content: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([ClientRequest__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + -- type: Schema.Literal("context_compaction").annotate({ + -- title: "ContextCompactionResponseItemType", + -- }), + -- }).annotate({ title: "ContextCompactionResponseItem" }), + - Schema.Struct({ + - type: Schema.Literal("other").annotate({ title: "OtherResponseItemType" }), + - }).annotate({ title: "OtherResponseItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ResponseItem = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type ClientRequest__SelectedCapabilityRoot = { + -- readonly id: string; + -- readonly location: { + -- readonly environmentId: string; + -- readonly path: string; + -- readonly type: "environment"; + -- }; + --}; + --export const ClientRequest__SelectedCapabilityRoot = Schema.Struct({ + -- id: Schema.String.annotate({ + -- description: "Stable identifier supplied by the capability selection platform.", + -- }), + -- location: Schema.Union( + -- [ + -- Schema.Struct({ + -- environmentId: Schema.String, + -- path: Schema.String.annotate({ + -- description: "Absolute path for the root in the selected environment.", + -- }), + -- type: Schema.Literal("environment").annotate({ + -- title: "EnvironmentCapabilityRootLocationType", + -- }), + -- }).annotate({ + -- title: "EnvironmentCapabilityRootLocation", + -- description: "A path owned by an execution environment.", + -- }), + -- ], + -- { mode: "oneOf" }, + -- ).annotate({ description: "Location used to resolve a selected capability root." }), + --}).annotate({ + -- description: "A user-selected root that can expose one or more runtime capabilities.", + --}); + -- + --export type ClientRequest__ThreadHistoryMode = "legacy" | "paginated"; + --export const ClientRequest__ThreadHistoryMode = Schema.Literals(["legacy", "paginated"]); + -- + --export type ClientRequest__ThreadMemoryMode = "enabled" | "disabled"; + --export const ClientRequest__ThreadMemoryMode = Schema.Literals(["enabled", "disabled"]); + -- + - export type ClientRequest__ThreadRealtimeAudioChunk = { + - readonly data: string; + - readonly itemId?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ThreadRealtimeAudioChunk = Schema.Struct({ + - ), + - }).annotate({ description: "EXPERIMENTAL - thread realtime audio chunk." }); + - + --export type ClientRequest__ThreadRealtimeInitialItem = { + -- readonly role: ClientRequest__ConversationTextRole; + -- readonly text: string; + --}; + --export const ClientRequest__ThreadRealtimeInitialItem = Schema.Struct({ + -- role: ClientRequest__ConversationTextRole, + -- text: Schema.String, + --}).annotate({ + -- description: "EXPERIMENTAL - role-bearing text item included when a realtime V3 session starts.", + --}); + -- + - export type ClientRequest__ThreadRealtimeStartTransport = + - | { readonly type: "websocket" } + - | { readonly sdp: string; readonly type: "webrtc" }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ClientRequest__ThreadRealtimeStartTransport = Schema.Union( + - { mode: "oneOf" }, + - ).annotate({ description: "EXPERIMENTAL - transport used by thread realtime." }); + - + --export type ClientRequest__ThreadResumeInitialTurnsPageParams = { + -- readonly itemsView?: ClientRequest__TurnItemsView | null; + -- readonly limit?: number | null; + -- readonly sortDirection?: ClientRequest__SortDirection | null; + --}; + --export const ClientRequest__ThreadResumeInitialTurnsPageParams = Schema.Struct({ + -- itemsView: Schema.optionalKey( + -- Schema.Union([ClientRequest__TurnItemsView, Schema.Null]).annotate({ + -- description: "How much item detail to include for each returned turn; defaults to summary.", + -- }), + -- ), + -- limit: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ description: "Optional turn page size.", format: "uint32" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- Schema.Null, + -- ]), + -- ), + -- sortDirection: Schema.optionalKey( + -- Schema.Union([ClientRequest__SortDirection, Schema.Null]).annotate({ + -- description: "Optional turn pagination direction; defaults to descending.", + -- }), + -- ), + --}); + -- + --export type ClientRequest__TurnEnvironmentParams = { + -- readonly cwd: ClientRequest__LegacyAppPathString; + -- readonly environmentId: string; + -- readonly runtimeWorkspaceRoots?: ReadonlyArray | null; + --}; + --export const ClientRequest__TurnEnvironmentParams = Schema.Struct({ + -- cwd: ClientRequest__LegacyAppPathString, + -- environmentId: Schema.String, + -- runtimeWorkspaceRoots: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(ClientRequest__LegacyAppPathString).annotate({ + -- description: "Environment-native runtime workspace roots. Omitted defaults to `cwd`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -- + - export type CommandExecutionRequestApprovalParams = { + - readonly approvalId?: string | null; + - readonly command?: string | null; + - readonly commandActions?: ReadonlyArray | null; + -- readonly cwd?: CommandExecutionRequestApprovalParams__LegacyAppPathString | null; + -- readonly environmentId?: string | null; + -+ readonly cwd?: string | null; + - readonly itemId: string; + - readonly networkApprovalContext?: CommandExecutionRequestApprovalParams__NetworkApprovalContext | null; + - readonly proposedExecpolicyAmendment?: ReadonlyArray | null; + - readonly proposedNetworkPolicyAmendments?: ReadonlyArray | null; + - readonly reason?: string | null; + -- readonly startedAtMs: number; + - readonly threadId: string; + - readonly turnId: string; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const CommandExecutionRequestApprovalParams = Schema.Struct({ + - ), + - cwd: Schema.optionalKey( + - Schema.Union([ + -- CommandExecutionRequestApprovalParams__LegacyAppPathString, + -- Schema.Null, + -- ]).annotate({ description: "The command's working directory." }), + -- ), + -- environmentId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ description: "Environment in which the command will run." }), + -+ Schema.String.annotate({ description: "The command's working directory." }), + - Schema.Null, + - ]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const CommandExecutionRequestApprovalParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this approval request started.", + -- format: "int64", + -- }).check(Schema.isInt()), + - threadId: Schema.String, + - turnId: Schema.String, + - }).annotate({ title: "CommandExecutionRequestApprovalParams" }); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const CommandExecutionRequestApprovalParams__AdditionalPermissionProfile + - Schema.Union([ + - CommandExecutionRequestApprovalParams__AdditionalNetworkPermissions, + - Schema.Null, + -- ]).annotate({ description: "Partial overlay used for per-command permission requests." }), + -+ ]), + - ), + - }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const CommandExecutionRequestApprovalResponse = Schema.Struct({ + - export type DynamicToolCallParams = { + - readonly arguments: unknown; + - readonly callId: string; + -- readonly namespace?: string | null; + - readonly threadId: string; + - readonly tool: string; + - readonly turnId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type DynamicToolCallParams = { + - export const DynamicToolCallParams = Schema.Struct({ + - arguments: Schema.Unknown, + - callId: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - threadId: Schema.String, + - tool: Schema.String, + - turnId: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type FileChangeRequestApprovalParams = { + - readonly grantRoot?: string | null; + - readonly itemId: string; + - readonly reason?: string | null; + -- readonly startedAtMs: number; + - readonly threadId: string; + - readonly turnId: string; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const FileChangeRequestApprovalParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this approval request started.", + -- format: "int64", + -- }).check(Schema.isInt()), + - threadId: Schema.String, + - turnId: Schema.String, + - }).annotate({ title: "FileChangeRequestApprovalParams" }); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type McpServerElicitationRequestParams = + - readonly threadId: string; + - readonly turnId?: string | null; + - } + -- | { + -- readonly _meta?: unknown; + -- readonly message: string; + -- readonly mode: "openai/form"; + -- readonly requestedSchema: unknown; + -- readonly serverName: string; + -- readonly threadId: string; + -- readonly turnId?: string | null; + -- } + - | { + - readonly _meta?: unknown; + - readonly elicitationId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const McpServerElicitationRequestParams = Schema.Union( + - ]), + - ), + - }).annotate({ title: "McpServerElicitationRequestParams" }), + -- Schema.Struct({ + -- _meta: Schema.optionalKey(Schema.Unknown), + -- message: Schema.String, + -- mode: Schema.Literal("openai/form"), + -- requestedSchema: Schema.Unknown, + -- serverName: Schema.String, + -- threadId: Schema.String, + -- turnId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Active Codex turn when this elicitation was observed, if app-server could correlate one.\n\nThis is nullable because MCP models elicitation as a standalone server-to-client request identified by the MCP server request id. It may be triggered during a turn, but turn context is app-server correlation rather than part of the protocol identity of the elicitation itself.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- }).annotate({ title: "McpServerElicitationRequestParams" }), + - Schema.Struct({ + - _meta: Schema.optionalKey(Schema.Unknown), + - elicitationId: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const McpServerElicitationRequestResponse = Schema.Struct({ + - }).annotate({ title: "McpServerElicitationRequestResponse" }); + - + - export type PermissionsRequestApprovalParams = { + -- readonly cwd: PermissionsRequestApprovalParams__AbsolutePathBuf; + -- readonly environmentId?: string | null; + - readonly itemId: string; + - readonly permissions: PermissionsRequestApprovalParams__RequestPermissionProfile; + - readonly reason?: string | null; + -- readonly startedAtMs: number; + - readonly threadId: string; + - readonly turnId: string; + - }; + - export const PermissionsRequestApprovalParams = Schema.Struct({ + -- cwd: PermissionsRequestApprovalParams__AbsolutePathBuf, + -- environmentId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - itemId: Schema.String, + - permissions: PermissionsRequestApprovalParams__RequestPermissionProfile, + - reason: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this approval request started.", + -- format: "int64", + -- }).check(Schema.isInt()), + - threadId: Schema.String, + - turnId: Schema.String, + - }).annotate({ title: "PermissionsRequestApprovalParams" }); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const PermissionsRequestApprovalParams = Schema.Struct({ + - export type PermissionsRequestApprovalResponse = { + - readonly permissions: PermissionsRequestApprovalResponse__GrantedPermissionProfile; + - readonly scope?: "turn" | "session"; + -- readonly strictAutoReview?: boolean | null; + - }; + - export const PermissionsRequestApprovalResponse = Schema.Struct({ + - permissions: PermissionsRequestApprovalResponse__GrantedPermissionProfile, + - scope: Schema.optionalKey(Schema.Literals(["turn", "session"]).annotate({ default: "turn" })), + -- strictAutoReview: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Boolean.annotate({ + -- description: + -- "Review every subsequent command in this turn before normal sandboxed execution.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - }).annotate({ title: "PermissionsRequestApprovalResponse" }); + - + - export type PermissionsRequestApprovalResponse__PermissionGrantScope = "turn" | "session"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const RequestId = Schema.Union([ + - ]).annotate({ title: "RequestId" }); + - + - export type ServerNotification = + -- | { + -- readonly method: "error"; + -- readonly params: ServerNotification__ErrorNotification; + -- readonly emittedAtMs?: number; + -- } + -+ | { readonly method: "error"; readonly params: ServerNotification__ErrorNotification } + - | { + - readonly method: "thread/started"; + - readonly params: ServerNotification__ThreadStartedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/status/changed"; + - readonly params: ServerNotification__ThreadStatusChangedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/archived"; + - readonly params: ServerNotification__ThreadArchivedNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "thread/deleted"; + -- readonly params: ServerNotification__ThreadDeletedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/unarchived"; + - readonly params: ServerNotification__ThreadUnarchivedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/closed"; + - readonly params: ServerNotification__ThreadClosedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "skills/changed"; + - readonly params: ServerNotification__SkillsChangedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/name/updated"; + - readonly params: ServerNotification__ThreadNameUpdatedNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "thread/goal/updated"; + -- readonly params: ServerNotification__ThreadGoalUpdatedNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "thread/goal/cleared"; + -- readonly params: ServerNotification__ThreadGoalClearedNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "thread/environment/connected"; + -- readonly params: ServerNotification__EnvironmentConnectionNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "thread/environment/disconnected"; + -- readonly params: ServerNotification__EnvironmentConnectionNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "thread/settings/updated"; + -- readonly params: ServerNotification__ThreadSettingsUpdatedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/tokenUsage/updated"; + - readonly params: ServerNotification__ThreadTokenUsageUpdatedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "turn/started"; + - readonly params: ServerNotification__TurnStartedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "hook/started"; + - readonly params: ServerNotification__HookStartedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "turn/completed"; + - readonly params: ServerNotification__TurnCompletedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "hook/completed"; + - readonly params: ServerNotification__HookCompletedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "turn/diff/updated"; + - readonly params: ServerNotification__TurnDiffUpdatedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "turn/plan/updated"; + - readonly params: ServerNotification__TurnPlanUpdatedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/started"; + - readonly params: ServerNotification__ItemStartedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/autoApprovalReview/started"; + - readonly params: ServerNotification__ItemGuardianApprovalReviewStartedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/autoApprovalReview/completed"; + - readonly params: ServerNotification__ItemGuardianApprovalReviewCompletedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/completed"; + - readonly params: ServerNotification__ItemCompletedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/agentMessage/delta"; + - readonly params: ServerNotification__AgentMessageDeltaNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/plan/delta"; + - readonly params: ServerNotification__PlanDeltaNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "command/exec/outputDelta"; + - readonly params: ServerNotification__CommandExecOutputDeltaNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "process/outputDelta"; + -- readonly params: ServerNotification__ProcessOutputDeltaNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "process/exited"; + -- readonly params: ServerNotification__ProcessExitedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/commandExecution/outputDelta"; + - readonly params: ServerNotification__CommandExecutionOutputDeltaNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/commandExecution/terminalInteraction"; + - readonly params: ServerNotification__TerminalInteractionNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/fileChange/outputDelta"; + - readonly params: ServerNotification__FileChangeOutputDeltaNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "item/fileChange/patchUpdated"; + -- readonly params: ServerNotification__FileChangePatchUpdatedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "serverRequest/resolved"; + - readonly params: ServerNotification__ServerRequestResolvedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/mcpToolCall/progress"; + - readonly params: ServerNotification__McpToolCallProgressNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "mcpServer/oauthLogin/completed"; + - readonly params: ServerNotification__McpServerOauthLoginCompletedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "mcpServer/startupStatus/updated"; + - readonly params: ServerNotification__McpServerStatusUpdatedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "account/updated"; + - readonly params: ServerNotification__AccountUpdatedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "account/rateLimits/updated"; + - readonly params: ServerNotification__AccountRateLimitsUpdatedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "app/list/updated"; + - readonly params: ServerNotification__AppListUpdatedNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "remoteControl/status/changed"; + -- readonly params: ServerNotification__RemoteControlStatusChangedNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "externalAgentConfig/import/progress"; + -- readonly params: ServerNotification__ExternalAgentConfigImportProgressNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "externalAgentConfig/import/completed"; + -- readonly params: ServerNotification__ExternalAgentConfigImportCompletedNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "fs/changed"; + -- readonly params: ServerNotification__FsChangedNotification; + -- readonly emittedAtMs?: number; + - } + -+ | { readonly method: "fs/changed"; readonly params: ServerNotification__FsChangedNotification } + - | { + - readonly method: "item/reasoning/summaryTextDelta"; + - readonly params: ServerNotification__ReasoningSummaryTextDeltaNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/reasoning/summaryPartAdded"; + - readonly params: ServerNotification__ReasoningSummaryPartAddedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "item/reasoning/textDelta"; + - readonly params: ServerNotification__ReasoningTextDeltaNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/compacted"; + - readonly params: ServerNotification__ContextCompactedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "model/rerouted"; + - readonly params: ServerNotification__ModelReroutedNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "model/verification"; + -- readonly params: ServerNotification__ModelVerificationNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "turn/moderationMetadata"; + -- readonly params: ServerNotification__TurnModerationMetadataNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "model/safetyBuffering/updated"; + -- readonly params: ServerNotification__ModelSafetyBufferingUpdatedNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "warning"; + -- readonly params: ServerNotification__WarningNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "guardianWarning"; + -- readonly params: ServerNotification__GuardianWarningNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "deprecationNotice"; + - readonly params: ServerNotification__DeprecationNoticeNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "configWarning"; + - readonly params: ServerNotification__ConfigWarningNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "fuzzyFileSearch/sessionUpdated"; + - readonly params: ServerNotification__FuzzyFileSearchSessionUpdatedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "fuzzyFileSearch/sessionCompleted"; + - readonly params: ServerNotification__FuzzyFileSearchSessionCompletedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/realtime/started"; + - readonly params: ServerNotification__ThreadRealtimeStartedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/realtime/itemAdded"; + - readonly params: ServerNotification__ThreadRealtimeItemAddedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + -- readonly method: "thread/realtime/transcript/delta"; + -- readonly params: ServerNotification__ThreadRealtimeTranscriptDeltaNotification; + -- readonly emittedAtMs?: number; + -- } + -- | { + -- readonly method: "thread/realtime/transcript/done"; + -- readonly params: ServerNotification__ThreadRealtimeTranscriptDoneNotification; + -- readonly emittedAtMs?: number; + -+ readonly method: "thread/realtime/transcriptUpdated"; + -+ readonly params: ServerNotification__ThreadRealtimeTranscriptUpdatedNotification; + - } + - | { + - readonly method: "thread/realtime/outputAudio/delta"; + - readonly params: ServerNotification__ThreadRealtimeOutputAudioDeltaNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/realtime/sdp"; + - readonly params: ServerNotification__ThreadRealtimeSdpNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/realtime/error"; + - readonly params: ServerNotification__ThreadRealtimeErrorNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "thread/realtime/closed"; + - readonly params: ServerNotification__ThreadRealtimeClosedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "windows/worldWritableWarning"; + - readonly params: ServerNotification__WindowsWorldWritableWarningNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "windowsSandbox/setupCompleted"; + - readonly params: ServerNotification__WindowsSandboxSetupCompletedNotification; + -- readonly emittedAtMs?: number; + - } + - | { + - readonly method: "account/login/completed"; + - readonly params: ServerNotification__AccountLoginCompletedNotification; + -- readonly emittedAtMs?: number; + - }; + - export const ServerNotification = Schema.Union( + - [ + - Schema.Struct({ + - method: Schema.Literal("error").annotate({ title: "ErrorNotificationMethod" }), + - params: ServerNotification__ErrorNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "ErrorNotification", description: "NEW NOTIFICATIONS" }), + - Schema.Struct({ + - method: Schema.Literal("thread/started").annotate({ + - title: "Thread/startedNotificationMethod", + - }), + - params: ServerNotification__ThreadStartedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Thread/startedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("thread/status/changed").annotate({ + - title: "Thread/status/changedNotificationMethod", + - }), + - params: ServerNotification__ThreadStatusChangedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Thread/status/changedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("thread/archived").annotate({ + - title: "Thread/archivedNotificationMethod", + - }), + -- params: ServerNotification__ThreadArchivedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("thread/deleted").annotate({ + -- title: "Thread/deletedNotificationMethod", + -- }), + -- params: ServerNotification__ThreadDeletedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("thread/unarchived").annotate({ + -- title: "Thread/unarchivedNotificationMethod", + -- }), + -- params: ServerNotification__ThreadUnarchivedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("thread/closed").annotate({ + -- title: "Thread/closedNotificationMethod", + -- }), + -- params: ServerNotification__ThreadClosedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("skills/changed").annotate({ + -- title: "Skills/changedNotificationMethod", + -- }), + -- params: ServerNotification__SkillsChangedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("thread/name/updated").annotate({ + -- title: "Thread/name/updatedNotificationMethod", + -- }), + -- params: ServerNotification__ThreadNameUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("thread/goal/updated").annotate({ + -- title: "Thread/goal/updatedNotificationMethod", + -- }), + -- params: ServerNotification__ThreadGoalUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ params: ServerNotification__ThreadArchivedNotification, + -+ }).annotate({ title: "Thread/archivedNotification" }), + - Schema.Struct({ + -- method: Schema.Literal("thread/goal/cleared").annotate({ + -- title: "Thread/goal/clearedNotificationMethod", + -+ method: Schema.Literal("thread/unarchived").annotate({ + -+ title: "Thread/unarchivedNotificationMethod", + - }), + -- params: ServerNotification__ThreadGoalClearedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ params: ServerNotification__ThreadUnarchivedNotification, + -+ }).annotate({ title: "Thread/unarchivedNotification" }), + - Schema.Struct({ + -- method: Schema.Literal("thread/environment/connected").annotate({ + -- title: "Thread/environment/connectedNotificationMethod", + -+ method: Schema.Literal("thread/closed").annotate({ + -+ title: "Thread/closedNotificationMethod", + - }), + -- params: ServerNotification__EnvironmentConnectionNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ params: ServerNotification__ThreadClosedNotification, + -+ }).annotate({ title: "Thread/closedNotification" }), + - Schema.Struct({ + -- method: Schema.Literal("thread/environment/disconnected").annotate({ + -- title: "Thread/environment/disconnectedNotificationMethod", + -+ method: Schema.Literal("skills/changed").annotate({ + -+ title: "Skills/changedNotificationMethod", + - }), + -- params: ServerNotification__EnvironmentConnectionNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ params: ServerNotification__SkillsChangedNotification, + -+ }).annotate({ title: "Skills/changedNotification" }), + - Schema.Struct({ + -- method: Schema.Literal("thread/settings/updated").annotate({ + -- title: "Thread/settings/updatedNotificationMethod", + -+ method: Schema.Literal("thread/name/updated").annotate({ + -+ title: "Thread/name/updatedNotificationMethod", + - }), + -- params: ServerNotification__ThreadSettingsUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ params: ServerNotification__ThreadNameUpdatedNotification, + -+ }).annotate({ title: "Thread/name/updatedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("thread/tokenUsage/updated").annotate({ + - title: "Thread/tokenUsage/updatedNotificationMethod", + - }), + - params: ServerNotification__ThreadTokenUsageUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Thread/tokenUsage/updatedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("turn/started").annotate({ title: "Turn/startedNotificationMethod" }), + - params: ServerNotification__TurnStartedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Turn/startedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("hook/started").annotate({ title: "Hook/startedNotificationMethod" }), + - params: ServerNotification__HookStartedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Hook/startedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("turn/completed").annotate({ + - title: "Turn/completedNotificationMethod", + - }), + - params: ServerNotification__TurnCompletedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Turn/completedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("hook/completed").annotate({ + - title: "Hook/completedNotificationMethod", + - }), + - params: ServerNotification__HookCompletedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Hook/completedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("turn/diff/updated").annotate({ + - title: "Turn/diff/updatedNotificationMethod", + - }), + - params: ServerNotification__TurnDiffUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Turn/diff/updatedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("turn/plan/updated").annotate({ + - title: "Turn/plan/updatedNotificationMethod", + - }), + - params: ServerNotification__TurnPlanUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Turn/plan/updatedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/started").annotate({ title: "Item/startedNotificationMethod" }), + - params: ServerNotification__ItemStartedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/startedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/autoApprovalReview/started").annotate({ + - title: "Item/autoApprovalReview/startedNotificationMethod", + - }), + - params: ServerNotification__ItemGuardianApprovalReviewStartedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/autoApprovalReview/startedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/autoApprovalReview/completed").annotate({ + - title: "Item/autoApprovalReview/completedNotificationMethod", + - }), + - params: ServerNotification__ItemGuardianApprovalReviewCompletedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/autoApprovalReview/completedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/completed").annotate({ + - title: "Item/completedNotificationMethod", + - }), + - params: ServerNotification__ItemCompletedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/completedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/agentMessage/delta").annotate({ + - title: "Item/agentMessage/deltaNotificationMethod", + - }), + - params: ServerNotification__AgentMessageDeltaNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/agentMessage/deltaNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/plan/delta").annotate({ + - title: "Item/plan/deltaNotificationMethod", + - }), + - params: ServerNotification__PlanDeltaNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + - }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -+ title: "Item/plan/deltaNotification", + -+ description: "EXPERIMENTAL - proposed plan streaming deltas for plan items.", + - }), + - Schema.Struct({ + - method: Schema.Literal("command/exec/outputDelta").annotate({ + - title: "Command/exec/outputDeltaNotificationMethod", + - }), + - params: ServerNotification__CommandExecOutputDeltaNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("process/outputDelta").annotate({ + -- title: "Process/outputDeltaNotificationMethod", + -- }), + -- params: ServerNotification__ProcessOutputDeltaNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("process/exited").annotate({ + -- title: "Process/exitedNotificationMethod", + -- }), + -- params: ServerNotification__ProcessExitedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + - }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -+ title: "Command/exec/outputDeltaNotification", + -+ description: + -+ "Stream base64-encoded stdout/stderr chunks for a running `command/exec` session.", + - }), + - Schema.Struct({ + - method: Schema.Literal("item/commandExecution/outputDelta").annotate({ + - title: "Item/commandExecution/outputDeltaNotificationMethod", + - }), + - params: ServerNotification__CommandExecutionOutputDeltaNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/commandExecution/outputDeltaNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/commandExecution/terminalInteraction").annotate({ + - title: "Item/commandExecution/terminalInteractionNotificationMethod", + - }), + - params: ServerNotification__TerminalInteractionNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/commandExecution/terminalInteractionNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/fileChange/outputDelta").annotate({ + - title: "Item/fileChange/outputDeltaNotificationMethod", + - }), + - params: ServerNotification__FileChangeOutputDeltaNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("item/fileChange/patchUpdated").annotate({ + -- title: "Item/fileChange/patchUpdatedNotificationMethod", + -- }), + -- params: ServerNotification__FileChangePatchUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/fileChange/outputDeltaNotification" }), + - Schema.Struct({ + - method: Schema.Literal("serverRequest/resolved").annotate({ + - title: "ServerRequest/resolvedNotificationMethod", + - }), + - params: ServerNotification__ServerRequestResolvedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "ServerRequest/resolvedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/mcpToolCall/progress").annotate({ + - title: "Item/mcpToolCall/progressNotificationMethod", + - }), + - params: ServerNotification__McpToolCallProgressNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/mcpToolCall/progressNotification" }), + - Schema.Struct({ + - method: Schema.Literal("mcpServer/oauthLogin/completed").annotate({ + - title: "McpServer/oauthLogin/completedNotificationMethod", + - }), + - params: ServerNotification__McpServerOauthLoginCompletedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "McpServer/oauthLogin/completedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("mcpServer/startupStatus/updated").annotate({ + - title: "McpServer/startupStatus/updatedNotificationMethod", + - }), + - params: ServerNotification__McpServerStatusUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "McpServer/startupStatus/updatedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("account/updated").annotate({ + - title: "Account/updatedNotificationMethod", + - }), + - params: ServerNotification__AccountUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Account/updatedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("account/rateLimits/updated").annotate({ + - title: "Account/rateLimits/updatedNotificationMethod", + - }), + - params: ServerNotification__AccountRateLimitsUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Account/rateLimits/updatedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("app/list/updated").annotate({ + - title: "App/list/updatedNotificationMethod", + - }), + - params: ServerNotification__AppListUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("remoteControl/status/changed").annotate({ + -- title: "RemoteControl/status/changedNotificationMethod", + -- }), + -- params: ServerNotification__RemoteControlStatusChangedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("externalAgentConfig/import/progress").annotate({ + -- title: "ExternalAgentConfig/import/progressNotificationMethod", + -- }), + -- params: ServerNotification__ExternalAgentConfigImportProgressNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("externalAgentConfig/import/completed").annotate({ + -- title: "ExternalAgentConfig/import/completedNotificationMethod", + -- }), + -- params: ServerNotification__ExternalAgentConfigImportCompletedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "App/list/updatedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("fs/changed").annotate({ title: "Fs/changedNotificationMethod" }), + - params: ServerNotification__FsChangedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Fs/changedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/reasoning/summaryTextDelta").annotate({ + - title: "Item/reasoning/summaryTextDeltaNotificationMethod", + - }), + - params: ServerNotification__ReasoningSummaryTextDeltaNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/reasoning/summaryTextDeltaNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/reasoning/summaryPartAdded").annotate({ + - title: "Item/reasoning/summaryPartAddedNotificationMethod", + - }), + - params: ServerNotification__ReasoningSummaryPartAddedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/reasoning/summaryPartAddedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("item/reasoning/textDelta").annotate({ + - title: "Item/reasoning/textDeltaNotificationMethod", + - }), + - params: ServerNotification__ReasoningTextDeltaNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Item/reasoning/textDeltaNotification" }), + - Schema.Struct({ + - method: Schema.Literal("thread/compacted").annotate({ + - title: "Thread/compactedNotificationMethod", + - }), + - params: ServerNotification__ContextCompactedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + - }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -+ title: "Thread/compactedNotification", + -+ description: "Deprecated: Use `ContextCompaction` item type instead.", + - }), + - Schema.Struct({ + - method: Schema.Literal("model/rerouted").annotate({ + - title: "Model/reroutedNotificationMethod", + - }), + - params: ServerNotification__ModelReroutedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("model/verification").annotate({ + -- title: "Model/verificationNotificationMethod", + -- }), + -- params: ServerNotification__ModelVerificationNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("turn/moderationMetadata").annotate({ + -- title: "Turn/moderationMetadataNotificationMethod", + -- }), + -- params: ServerNotification__TurnModerationMetadataNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("model/safetyBuffering/updated").annotate({ + -- title: "Model/safetyBuffering/updatedNotificationMethod", + -- }), + -- params: ServerNotification__ModelSafetyBufferingUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("warning").annotate({ title: "WarningNotificationMethod" }), + -- params: ServerNotification__WarningNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("guardianWarning").annotate({ + -- title: "GuardianWarningNotificationMethod", + -- }), + -- params: ServerNotification__GuardianWarningNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Model/reroutedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("deprecationNotice").annotate({ + - title: "DeprecationNoticeNotificationMethod", + - }), + - params: ServerNotification__DeprecationNoticeNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "DeprecationNoticeNotification" }), + - Schema.Struct({ + - method: Schema.Literal("configWarning").annotate({ + - title: "ConfigWarningNotificationMethod", + - }), + - params: ServerNotification__ConfigWarningNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "ConfigWarningNotification" }), + - Schema.Struct({ + - method: Schema.Literal("fuzzyFileSearch/sessionUpdated").annotate({ + - title: "FuzzyFileSearch/sessionUpdatedNotificationMethod", + - }), + - params: ServerNotification__FuzzyFileSearchSessionUpdatedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "FuzzyFileSearch/sessionUpdatedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("fuzzyFileSearch/sessionCompleted").annotate({ + - title: "FuzzyFileSearch/sessionCompletedNotificationMethod", + - }), + - params: ServerNotification__FuzzyFileSearchSessionCompletedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "FuzzyFileSearch/sessionCompletedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("thread/realtime/started").annotate({ + - title: "Thread/realtime/startedNotificationMethod", + - }), + - params: ServerNotification__ThreadRealtimeStartedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Thread/realtime/startedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("thread/realtime/itemAdded").annotate({ + - title: "Thread/realtime/itemAddedNotificationMethod", + - }), + - params: ServerNotification__ThreadRealtimeItemAddedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -- Schema.Struct({ + -- method: Schema.Literal("thread/realtime/transcript/delta").annotate({ + -- title: "Thread/realtime/transcript/deltaNotificationMethod", + -- }), + -- params: ServerNotification__ThreadRealtimeTranscriptDeltaNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Thread/realtime/itemAddedNotification" }), + - Schema.Struct({ + -- method: Schema.Literal("thread/realtime/transcript/done").annotate({ + -- title: "Thread/realtime/transcript/doneNotificationMethod", + -+ method: Schema.Literal("thread/realtime/transcriptUpdated").annotate({ + -+ title: "Thread/realtime/transcriptUpdatedNotificationMethod", + - }), + -- params: ServerNotification__ThreadRealtimeTranscriptDoneNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ params: ServerNotification__ThreadRealtimeTranscriptUpdatedNotification, + -+ }).annotate({ title: "Thread/realtime/transcriptUpdatedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("thread/realtime/outputAudio/delta").annotate({ + - title: "Thread/realtime/outputAudio/deltaNotificationMethod", + - }), + - params: ServerNotification__ThreadRealtimeOutputAudioDeltaNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Thread/realtime/outputAudio/deltaNotification" }), + - Schema.Struct({ + - method: Schema.Literal("thread/realtime/sdp").annotate({ + - title: "Thread/realtime/sdpNotificationMethod", + - }), + - params: ServerNotification__ThreadRealtimeSdpNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Thread/realtime/sdpNotification" }), + - Schema.Struct({ + - method: Schema.Literal("thread/realtime/error").annotate({ + - title: "Thread/realtime/errorNotificationMethod", + - }), + - params: ServerNotification__ThreadRealtimeErrorNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Thread/realtime/errorNotification" }), + - Schema.Struct({ + - method: Schema.Literal("thread/realtime/closed").annotate({ + - title: "Thread/realtime/closedNotificationMethod", + - }), + - params: ServerNotification__ThreadRealtimeClosedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Thread/realtime/closedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("windows/worldWritableWarning").annotate({ + - title: "Windows/worldWritableWarningNotificationMethod", + - }), + - params: ServerNotification__WindowsWorldWritableWarningNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + - }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -+ title: "Windows/worldWritableWarningNotification", + -+ description: + -+ "Notifies the user of world-writable directories on Windows, which cannot be protected by the sandbox.", + - }), + - Schema.Struct({ + - method: Schema.Literal("windowsSandbox/setupCompleted").annotate({ + - title: "WindowsSandbox/setupCompletedNotificationMethod", + - }), + - params: ServerNotification__WindowsSandboxSetupCompletedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "WindowsSandbox/setupCompletedNotification" }), + - Schema.Struct({ + - method: Schema.Literal("account/login/completed").annotate({ + - title: "Account/login/completedNotificationMethod", + - }), + - params: ServerNotification__AccountLoginCompletedNotification, + -- emittedAtMs: Schema.optionalKey( + -- Schema.Number.annotate({ + -- description: + -- "Unix timestamp (in milliseconds) when app-server emitted this notification.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- ), + -- }).annotate({ + -- title: "ServerNotification", + -- description: "Notification sent from the server to the client.", + -- }), + -+ }).annotate({ title: "Account/login/completedNotification" }), + - ], + - { mode: "oneOf" }, + --); + -+).annotate({ + -+ title: "ServerNotification", + -+ description: "Notification sent from the server to the client.", + -+}); + - + - export type ServerNotification__ByteRange = { readonly end: number; readonly start: number }; + - export const ServerNotification__ByteRange = Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerNotification__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const ServerNotification__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + --export type ServerNotification__CollabAgentToolCallStatus = + -- | "inProgress" + -- | "completed" + -- | "failed" + -- | "interrupted"; + -+export type ServerNotification__CollabAgentToolCallStatus = "inProgress" | "completed" | "failed"; + - export const ServerNotification__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type ServerNotification__CommandExecOutputStream = "stdout" | "stderr"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__CommandExecutionSource = Schema.Literals([ + - "unifiedExecInteraction", + - ]); + - + --export type ServerNotification__HookSource = + -- | "system" + -- | "user" + -- | "project" + -- | "mdm" + -- | "sessionFlags" + -- | "plugin" + -- | "cloudRequirements" + -- | "cloudManagedConfig" + -- | "legacyManagedConfigFile" + -- | "legacyManagedConfigMdm" + -- | "unknown"; + --export const ServerNotification__HookSource = Schema.Literals([ + -- "system", + -- "user", + -- "project", + -- "mdm", + -- "sessionFlags", + -- "plugin", + -- "cloudRequirements", + -- "cloudManagedConfig", + -- "legacyManagedConfigFile", + -- "legacyManagedConfigMdm", + -- "unknown", + --]); + -- + --export type ServerNotification__MultiAgentMode = + -- | "explicitRequestOnly" + -- | "proactive" + -- | { readonly custom: string }; + --export const ServerNotification__MultiAgentMode = Schema.Union( + -- [ + -- Schema.Literals(["explicitRequestOnly", "proactive"]), + -- Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomMultiAgentMode" }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ + -- description: + -- "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.", + --}); + -- + --export type ServerNotification__NetworkAccess = "restricted" | "enabled"; + --export const ServerNotification__NetworkAccess = Schema.Literals(["restricted", "enabled"]); + -- + --export type ServerNotification__ProcessOutputStream = "stdout" | "stderr"; + --export const ServerNotification__ProcessOutputStream = Schema.Literals([ + -- "stdout", + -- "stderr", + --]).annotate({ description: "Stream label for `process/outputDelta` notifications." }); + -- + - export type ServerNotification__SessionSource = + - | "cli" + - | "vscode" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerNotification__SessionSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type ServerNotification__ThreadExtra = {}; + --export const ServerNotification__ThreadExtra = Schema.Struct({}).annotate({ + -- description: "Extra app-server data for a thread.", + --}); + -- + --export type ServerNotification__ThreadHistoryMode = "legacy" | "paginated"; + --export const ServerNotification__ThreadHistoryMode = Schema.Literals(["legacy", "paginated"]); + -- + --export type ServerNotification__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const ServerNotification__TurnItemsView = Schema.Literals(["notLoaded", "summary", "full"]); + -- + - export type ServerRequest = + - | { + - readonly id: ServerRequest__RequestId; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type ServerRequest = + - readonly method: "account/chatgptAuthTokens/refresh"; + - readonly params: ServerRequest__ChatgptAuthTokensRefreshParams; + - } + -- | { + -- readonly id: ServerRequest__RequestId; + -- readonly method: "attestation/generate"; + -- readonly params: ServerRequest__AttestationGenerateParams; + -- } + - | { + - readonly id: ServerRequest__RequestId; + - readonly method: "applyPatchApproval"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerRequest = Schema.Union( + - }), + - params: ServerRequest__ChatgptAuthTokensRefreshParams, + - }).annotate({ title: "Account/chatgptAuthTokens/refreshRequest" }), + -- Schema.Struct({ + -- id: ServerRequest__RequestId, + -- method: Schema.Literal("attestation/generate").annotate({ + -- title: "Attestation/generateRequestMethod", + -- }), + -- params: ServerRequest__AttestationGenerateParams, + -- }).annotate({ + -- title: "Attestation/generateRequest", + -- description: "Generate a fresh upstream attestation result on demand.", + -- }), + - Schema.Struct({ + - id: ServerRequest__RequestId, + - method: Schema.Literal("applyPatchApproval").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerRequest__AdditionalPermissionProfile = Schema.Struct({ + - Schema.Union([ServerRequest__AdditionalFileSystemPermissions, Schema.Null]), + - ), + - network: Schema.optionalKey( + -- Schema.Union([ServerRequest__AdditionalNetworkPermissions, Schema.Null]).annotate({ + -- description: "Partial overlay used for per-command permission requests.", + -- }), + -+ Schema.Union([ServerRequest__AdditionalNetworkPermissions, Schema.Null]), + - ), + - }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const ServerRequest__CommandExecutionApprovalDecision = Schema.Union( + - ); + - + - export type ToolRequestUserInputParams = { + -- readonly autoResolutionMs?: number | null; + - readonly itemId: string; + - readonly questions: ReadonlyArray; + - readonly threadId: string; + - readonly turnId: string; + - }; + - export const ToolRequestUserInputParams = Schema.Struct({ + -- autoResolutionMs: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ format: "uint64" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- Schema.Null, + -- ]), + -- ), + - itemId: Schema.String, + - questions: Schema.Array(ToolRequestUserInputParams__ToolRequestUserInputQuestion), + - threadId: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2AccountRateLimitsUpdatedNotification = { + - }; + - export const V2AccountRateLimitsUpdatedNotification = Schema.Struct({ + - rateLimits: V2AccountRateLimitsUpdatedNotification__RateLimitSnapshot, + --}).annotate({ + -- title: "AccountRateLimitsUpdatedNotification", + -- description: + -- "Sparse rolling rate-limit update.\n\nClients should merge available values into the most recent `account/rateLimits/read` response or refetch that snapshot. Nullable account metadata may be unavailable in a rolling update and does not clear a previously observed value.", + --}); + -+}).annotate({ title: "AccountRateLimitsUpdatedNotification" }); + - + - export type V2AccountUpdatedNotification = { + - readonly authMode?: V2AccountUpdatedNotification__AuthMode | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2AppListUpdatedNotification = Schema.Struct({ + - description: "EXPERIMENTAL - notification emitted when the app list changes.", + - }); + - + --export type V2AppsInstalledParams = { + -- readonly forceRefresh?: boolean; + -- readonly threadId?: string | null; + --}; + --export const V2AppsInstalledParams = Schema.Struct({ + -- forceRefresh: Schema.optionalKey( + -- Schema.Boolean.annotate({ + -- description: + -- "When true and Apps are permitted, refresh and publish the hosted connector runtime tool snapshot first.", + -- }), + -- ), + -- threadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Optional loaded thread id used to evaluate effective app configuration.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}).annotate({ + -- title: "AppsInstalledParams", + -- description: "Read the committed installed connector runtime snapshot.", + --}); + -- + --export type V2AppsInstalledResponse = { + -- readonly apps: ReadonlyArray; + --}; + --export const V2AppsInstalledResponse = Schema.Struct({ + -- apps: Schema.Array(V2AppsInstalledResponse__InstalledApp), + --}).annotate({ + -- title: "AppsInstalledResponse", + -- description: "The installed connectors in one committed runtime snapshot.", + --}); + -- + - export type V2AppsListParams = { + - readonly cursor?: string | null; + - readonly forceRefetch?: boolean; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2AppsListResponse = Schema.Struct({ + - ), + - }).annotate({ title: "AppsListResponse", description: "EXPERIMENTAL - app list response." }); + - + --export type V2AppsReadParams = { + -- readonly appIds: ReadonlyArray; + -- readonly includeTools?: boolean; + --}; + --export const V2AppsReadParams = Schema.Struct({ + -- appIds: Schema.Array(Schema.String).annotate({ + -- description: + -- "App ids to read. The server accepts at most 100 ids and deduplicates repeated ids while preserving their first-request order.", + -- }), + -- includeTools: Schema.optionalKey( + -- Schema.Boolean.annotate({ + -- description: + -- "When true, include display-only public tool summaries in the returned metadata.", + -- }), + -- ), + --}).annotate({ + -- title: "AppsReadParams", + -- description: "EXPERIMENTAL - read metadata for specific apps/connectors.", + --}); + -- + --export type V2AppsReadResponse = { + -- readonly apps: ReadonlyArray; + -- readonly missingAppIds: ReadonlyArray; + --}; + --export const V2AppsReadResponse = Schema.Struct({ + -- apps: Schema.Array(V2AppsReadResponse__ConnectorMetadata), + -- missingAppIds: Schema.Array(Schema.String), + --}).annotate({ title: "AppsReadResponse", description: "EXPERIMENTAL - app/read response." }); + -- + - export type V2CancelLoginAccountParams = { readonly loginId: string }; + - export const V2CancelLoginAccountParams = Schema.Struct({ loginId: Schema.String }).annotate({ + - title: "CancelLoginAccountParams", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2CommandExecParams = Schema.Struct({ + - sandboxPolicy: Schema.optionalKey( + - Schema.Union([V2CommandExecParams__SandboxPolicy, Schema.Null]).annotate({ + - description: + -- "Optional sandbox policy for this command.\n\nUses the same shape as thread/turn execution sandbox configuration and defaults to the user's configured policy when omitted. Cannot be combined with `permissionProfile`.", + -+ "Optional sandbox policy for this command.\n\nUses the same shape as thread/turn execution sandbox configuration and defaults to the user's configured policy when omitted.", + - }), + - ), + - size: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2CommandExecParams = Schema.Struct({ + - export type V2CommandExecParams__NetworkAccess = "restricted" | "enabled"; + - export const V2CommandExecParams__NetworkAccess = Schema.Literals(["restricted", "enabled"]); + - + -+export type V2CommandExecParams__ReadOnlyAccess = + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+export const V2CommandExecParams__ReadOnlyAccess = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2CommandExecParams__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ title: "RestrictedReadOnlyAccessType" }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ title: "FullAccessReadOnlyAccessType" }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + -+ + - export type V2CommandExecResizeParams = { + - readonly processId: string; + - readonly size: { readonly cols: number; readonly rows: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- includeLayers: Schema.optionalKey(Schema.Boolean), + -+ includeLayers: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + - }).annotate({ title: "ConfigReadParams" }); + - + - export type V2ConfigReadResponse = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigReadResponse = Schema.Struct({ + - }).annotate({ title: "ConfigReadResponse" }); + - + - export type V2ConfigReadResponse__AppConfig = { + -- readonly approvals_reviewer?: V2ConfigReadResponse__ApprovalsReviewer | null; + - readonly default_tools_approval_mode?: V2ConfigReadResponse__AppToolApproval | null; + - readonly default_tools_enabled?: boolean | null; + - readonly destructive_enabled?: boolean | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ConfigReadResponse__AppConfig = { + - readonly tools?: V2ConfigReadResponse__AppToolsConfig | null; + - }; + - export const V2ConfigReadResponse__AppConfig = Schema.Struct({ + -- approvals_reviewer: Schema.optionalKey( + -- Schema.Union([V2ConfigReadResponse__ApprovalsReviewer, Schema.Null]), + -- ), + - default_tools_approval_mode: Schema.optionalKey( + - Schema.Union([V2ConfigReadResponse__AppToolApproval, Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigRequirementsReadResponse = Schema.Struct({ + - ), + - }).annotate({ title: "ConfigRequirementsReadResponse" }); + - + --export type V2ConfigRequirementsReadResponse__ApprovalsReviewer = + -- | "user" + -- | "auto_review" + -- | "guardian_subagent"; + -+export type V2ConfigRequirementsReadResponse__ApprovalsReviewer = "user" | "guardian_subagent"; + - export const V2ConfigRequirementsReadResponse__ApprovalsReviewer = Schema.Literals([ + - "user", + -- "auto_review", + - "guardian_subagent", + - ]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + --}); + -- + --export type V2ConfigRequirementsReadResponse__ManagedHooksRequirements = { + -- readonly PermissionRequest: ReadonlyArray; + -- readonly PostCompact: ReadonlyArray; + -- readonly PostToolUse: ReadonlyArray; + -- readonly PreCompact: ReadonlyArray; + -- readonly PreToolUse: ReadonlyArray; + -- readonly SessionEnd?: ReadonlyArray; + -- readonly SessionStart: ReadonlyArray; + -- readonly Stop: ReadonlyArray; + -- readonly SubagentStart: ReadonlyArray; + -- readonly SubagentStop: ReadonlyArray; + -- readonly UserPromptSubmit: ReadonlyArray; + -- readonly managedDir?: string | null; + -- readonly windowsManagedDir?: string | null; + --}; + --export const V2ConfigRequirementsReadResponse__ManagedHooksRequirements = Schema.Struct({ + -- PermissionRequest: Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup), + -- PostCompact: Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup), + -- PostToolUse: Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup), + -- PreCompact: Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup), + -- PreToolUse: Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup), + -- SessionEnd: Schema.optionalKey( + -- Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup).annotate({ + -- default: [], + -- }), + -- ), + -- SessionStart: Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup), + -- Stop: Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup), + -- SubagentStart: Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup), + -- SubagentStop: Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup), + -- UserPromptSubmit: Schema.Array(V2ConfigRequirementsReadResponse__ConfiguredHookMatcherGroup), + -- managedDir: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- windowsManagedDir: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }); + - + - export type V2ConfigRequirementsReadResponse__NetworkRequirements = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ConfigRequirementsReadResponse__NetworkRequirements = { + - readonly allowUnixSockets?: ReadonlyArray | null; + - readonly allowUpstreamProxy?: boolean | null; + - readonly allowedDomains?: ReadonlyArray | null; + -+ readonly dangerFullAccessDenylistOnly?: boolean | null; + - readonly dangerouslyAllowAllUnixSockets?: boolean | null; + - readonly dangerouslyAllowNonLoopbackProxy?: boolean | null; + - readonly deniedDomains?: ReadonlyArray | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigRequirementsReadResponse__NetworkRequirements = Schema.Stru + - Schema.Null, + - ]), + - ), + -+ dangerFullAccessDenylistOnly: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - dangerouslyAllowAllUnixSockets: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - dangerouslyAllowNonLoopbackProxy: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + - deniedDomains: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ConfigWriteResponse = Schema.Struct({ + - version: Schema.String, + - }).annotate({ title: "ConfigWriteResponse" }); + - + --export type V2ConsumeAccountRateLimitResetCreditParams = { + -- readonly creditId?: string | null; + -- readonly idempotencyKey: string; + --}; + --export const V2ConsumeAccountRateLimitResetCreditParams = Schema.Struct({ + -- creditId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Opaque reset-credit identifier to redeem. When omitted, the backend selects the next available credit.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- idempotencyKey: Schema.String.annotate({ + -- description: + -- "Identifies one logical reset attempt. A UUID is recommended; reuse the same value when retrying that attempt.", + -- }), + --}).annotate({ title: "ConsumeAccountRateLimitResetCreditParams" }); + -- + --export type V2ConsumeAccountRateLimitResetCreditResponse = { + -- readonly outcome: V2ConsumeAccountRateLimitResetCreditResponse__ConsumeAccountRateLimitResetCreditOutcome; + --}; + --export const V2ConsumeAccountRateLimitResetCreditResponse = Schema.Struct({ + -- outcome: V2ConsumeAccountRateLimitResetCreditResponse__ConsumeAccountRateLimitResetCreditOutcome, + --}).annotate({ title: "ConsumeAccountRateLimitResetCreditResponse" }); + -- + - export type V2ContextCompactedNotification = { readonly threadId: string; readonly turnId: string }; + - export const V2ContextCompactedNotification = Schema.Struct({ + - threadId: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2DeprecationNoticeNotification = Schema.Struct({ + - summary: Schema.String.annotate({ description: "Concise summary of what is deprecated." }), + - }).annotate({ title: "DeprecationNoticeNotification" }); + - + --export type V2EnvironmentConnectionNotification = { + -- readonly environmentId: string; + -- readonly threadId: string; + --}; + --export const V2EnvironmentConnectionNotification = Schema.Struct({ + -- environmentId: Schema.String, + -- threadId: Schema.String, + --}).annotate({ title: "EnvironmentConnectionNotification" }); + -- + - export type V2ErrorNotification = { + - readonly error: V2ErrorNotification__TurnError; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ExperimentalFeatureEnablementSetResponse = Schema.Struct({ + - export type V2ExperimentalFeatureListParams = { + - readonly cursor?: string | null; + - readonly limit?: number | null; + -- readonly threadId?: string | null; + - }; + - export const V2ExperimentalFeatureListParams = Schema.Struct({ + - cursor: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ExperimentalFeatureListParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- threadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional loaded thread id. Pass this when showing feature state for an existing thread so enablement is computed from that thread's refreshed config, including project-local config for the thread's cwd.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - }).annotate({ title: "ExperimentalFeatureListParams" }); + - + - export type V2ExperimentalFeatureListResponse = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ExperimentalFeatureListResponse__ExperimentalFeatureStage = Schem + - export type V2ExternalAgentConfigDetectParams = { + - readonly cwds?: ReadonlyArray | null; + - readonly includeHome?: boolean; + -- readonly migrationSource?: string | null; + -- readonly source?: string | null; + - }; + - export const V2ExternalAgentConfigDetectParams = Schema.Struct({ + - cwds: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ExternalAgentConfigDetectParams = Schema.Struct({ + - ), + - includeHome: Schema.optionalKey( + - Schema.Boolean.annotate({ + -- description: "If true, include detection under the user's home directory.", + -+ description: "If true, include detection under the user's home (~/.claude, ~/.codex, etc.).", + - }), + - ), + -- migrationSource: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional migration-source selector. Missing or unrecognized values use the default source.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- source: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Deprecated field retained for compatibility. This field is ignored; use `migrationSource` to select the migration source.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - }).annotate({ title: "ExternalAgentConfigDetectParams" }); + - + - export type V2ExternalAgentConfigDetectResponse = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ExternalAgentConfigDetectResponse = Schema.Struct({ + - items: Schema.Array(V2ExternalAgentConfigDetectResponse__ExternalAgentConfigMigrationItem), + - }).annotate({ title: "ExternalAgentConfigDetectResponse" }); + - + --export type V2ExternalAgentConfigImportCompletedNotification = { + -- readonly importId: string; + -- readonly itemTypeResults: ReadonlyArray; + --}; + --export const V2ExternalAgentConfigImportCompletedNotification = Schema.Struct({ + -- importId: Schema.String, + -- itemTypeResults: Schema.Array( + -- V2ExternalAgentConfigImportCompletedNotification__ExternalAgentConfigImportTypeResult, + -- ), + --}).annotate({ title: "ExternalAgentConfigImportCompletedNotification" }); + -- + --export type V2ExternalAgentConfigImportHistoriesReadResponse = { + -- readonly connectors: ReadonlyArray; + -- readonly data: ReadonlyArray; + --}; + --export const V2ExternalAgentConfigImportHistoriesReadResponse = Schema.Struct({ + -- connectors: Schema.Array( + -- V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentImportedConnectorCandidate, + -- ), + -- data: Schema.Array( + -- V2ExternalAgentConfigImportHistoriesReadResponse__ExternalAgentConfigImportHistory, + -- ), + --}).annotate({ title: "ExternalAgentConfigImportHistoriesReadResponse" }); + -- + - export type V2ExternalAgentConfigImportParams = { + - readonly migrationItems: ReadonlyArray; + -- readonly migrationSource?: string | null; + -- readonly source?: string | null; + - }; + - export const V2ExternalAgentConfigImportParams = Schema.Struct({ + - migrationItems: Schema.Array(V2ExternalAgentConfigImportParams__ExternalAgentConfigMigrationItem), + -- migrationSource: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Migration-source selector used to produce the migration items. Pass the same value to detection and import; missing or unrecognized values use the default source.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- source: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Optional identifier for the product that initiated the import.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - }).annotate({ title: "ExternalAgentConfigImportParams" }); + - + --export type V2ExternalAgentConfigImportProgressNotification = { + -- readonly importId: string; + -- readonly itemTypeResults: ReadonlyArray; + --}; + --export const V2ExternalAgentConfigImportProgressNotification = Schema.Struct({ + -- importId: Schema.String, + -- itemTypeResults: Schema.Array( + -- V2ExternalAgentConfigImportProgressNotification__ExternalAgentConfigImportTypeResult, + -- ), + --}).annotate({ title: "ExternalAgentConfigImportProgressNotification" }); + -- + --export type V2ExternalAgentConfigImportResponse = { readonly importId: string }; + --export const V2ExternalAgentConfigImportResponse = Schema.Struct({ + -- importId: Schema.String, + --}).annotate({ title: "ExternalAgentConfigImportResponse" }); + -+export type V2ExternalAgentConfigImportResponse = {}; + -+export const V2ExternalAgentConfigImportResponse = Schema.Struct({}).annotate({ + -+ title: "ExternalAgentConfigImportResponse", + -+}); + - + - export type V2FeedbackUploadParams = { + - readonly classification: string; + - readonly extraLogFiles?: ReadonlyArray | null; + -- readonly includeLogs?: boolean; + -+ readonly includeLogs: boolean; + - readonly reason?: string | null; + -- readonly tags?: { readonly [x: string]: string } | null; + - readonly threadId?: string | null; + - }; + - export const V2FeedbackUploadParams = Schema.Struct({ + - classification: Schema.String, + - extraLogFiles: Schema.optionalKey(Schema.Union([Schema.Array(Schema.String), Schema.Null])), + -- includeLogs: Schema.optionalKey(Schema.Boolean), + -+ includeLogs: Schema.Boolean, + - reason: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- tags: Schema.optionalKey( + -- Schema.Union([Schema.Record(Schema.String, Schema.String), Schema.Null]), + -- ), + - threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }).annotate({ title: "FeedbackUploadParams" }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2FileChangeOutputDeltaNotification = Schema.Struct({ + - itemId: Schema.String, + - threadId: Schema.String, + - turnId: Schema.String, + --}).annotate({ + -- title: "FileChangeOutputDeltaNotification", + -- description: + -- "Deprecated legacy notification for `apply_patch` textual output.\n\nThe server no longer emits this notification.", + --}); + -- + --export type V2FileChangePatchUpdatedNotification = { + -- readonly changes: ReadonlyArray; + -- readonly itemId: string; + -- readonly threadId: string; + -- readonly turnId: string; + --}; + --export const V2FileChangePatchUpdatedNotification = Schema.Struct({ + -- changes: Schema.Array(V2FileChangePatchUpdatedNotification__FileUpdateChange), + -- itemId: Schema.String, + -- threadId: Schema.String, + -- turnId: Schema.String, + --}).annotate({ title: "FileChangePatchUpdatedNotification" }); + -+}).annotate({ title: "FileChangeOutputDeltaNotification" }); + - + - export type V2FsChangedNotification = { + - readonly changedPaths: ReadonlyArray; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2FsGetMetadataResponse = { + - readonly createdAtMs: number; + - readonly isDirectory: boolean; + - readonly isFile: boolean; + -- readonly isSymlink: boolean; + - readonly modifiedAtMs: number; + - }; + - export const V2FsGetMetadataResponse = Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2FsGetMetadataResponse = Schema.Struct({ + - format: "int64", + - }).check(Schema.isInt()), + - isDirectory: Schema.Boolean.annotate({ + -- description: "Whether the path resolves to a directory.", + -+ description: "Whether the path currently resolves to a directory.", + - }), + -- isFile: Schema.Boolean.annotate({ description: "Whether the path resolves to a regular file." }), + -- isSymlink: Schema.Boolean.annotate({ + -- description: "Whether the path itself is a symbolic link.", + -+ isFile: Schema.Boolean.annotate({ + -+ description: "Whether the path currently resolves to a regular file.", + - }), + - modifiedAtMs: Schema.Number.annotate({ + - description: "File modification time in Unix milliseconds when available, otherwise `0`.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2GetAccountParams = Schema.Struct({ + - Schema.Boolean.annotate({ + - description: + - "When `true`, requests a proactive token refresh before returning.\n\nIn managed auth mode this triggers the normal refresh-token flow. In external auth mode this flag is ignored. Clients should refresh tokens themselves and call `account/login/start` with `chatgptAuthTokens`.", + -+ default: false, + - }), + - ), + - }).annotate({ title: "GetAccountParams" }); + - + - export type V2GetAccountRateLimitsResponse = { + -- readonly rateLimitResetCredits?: V2GetAccountRateLimitsResponse__RateLimitResetCreditsSummary | null; + - readonly rateLimits: { + - readonly credits?: V2GetAccountRateLimitsResponse__CreditsSnapshot | null; + -- readonly individualLimit?: V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot | null; + - readonly limitId?: string | null; + - readonly limitName?: string | null; + - readonly planType?: V2GetAccountRateLimitsResponse__PlanType | null; + - readonly primary?: V2GetAccountRateLimitsResponse__RateLimitWindow | null; + -- readonly rateLimitReachedType?: V2GetAccountRateLimitsResponse__RateLimitReachedType | null; + - readonly secondary?: V2GetAccountRateLimitsResponse__RateLimitWindow | null; + -- readonly spendControlReached?: boolean | null; + - }; + - readonly rateLimitsByLimitId?: { + - readonly [x: string]: V2GetAccountRateLimitsResponse__RateLimitSnapshot; + - } | null; + - }; + - export const V2GetAccountRateLimitsResponse = Schema.Struct({ + -- rateLimitResetCredits: Schema.optionalKey( + -- Schema.Union([V2GetAccountRateLimitsResponse__RateLimitResetCreditsSummary, Schema.Null]), + -- ), + - rateLimits: Schema.Struct({ + - credits: Schema.optionalKey( + - Schema.Union([V2GetAccountRateLimitsResponse__CreditsSnapshot, Schema.Null]), + - ), + -- individualLimit: Schema.optionalKey( + -- Schema.Union([V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot, Schema.Null]), + -- ), + - limitId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - limitName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - planType: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2GetAccountRateLimitsResponse = Schema.Struct({ + - primary: Schema.optionalKey( + - Schema.Union([V2GetAccountRateLimitsResponse__RateLimitWindow, Schema.Null]), + - ), + -- rateLimitReachedType: Schema.optionalKey( + -- Schema.Union([V2GetAccountRateLimitsResponse__RateLimitReachedType, Schema.Null]), + -- ), + - secondary: Schema.optionalKey( + - Schema.Union([V2GetAccountRateLimitsResponse__RateLimitWindow, Schema.Null]), + - ), + -- spendControlReached: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Boolean.annotate({ + -- description: + -- "Backend-reported spend-control state. `None` is unavailable, not a sparse-update recovery.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - }).annotate({ + - description: "Backward-compatible single-bucket view; mirrors the historical payload.", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2GetAccountResponse = Schema.Struct({ + - requiresOpenaiAuth: Schema.Boolean, + - }).annotate({ title: "GetAccountResponse" }); + - + --export type V2GetAccountTokenUsageResponse = { + -- readonly dailyUsageBuckets?: ReadonlyArray | null; + -- readonly summary: V2GetAccountTokenUsageResponse__AccountTokenUsageSummary; + --}; + --export const V2GetAccountTokenUsageResponse = Schema.Struct({ + -- dailyUsageBuckets: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(V2GetAccountTokenUsageResponse__AccountTokenUsageDailyBucket), + -- Schema.Null, + -- ]), + -- ), + -- summary: V2GetAccountTokenUsageResponse__AccountTokenUsageSummary, + --}).annotate({ title: "GetAccountTokenUsageResponse" }); + -- + --export type V2GetWorkspaceMessagesResponse = { + -- readonly featureEnabled: boolean; + -- readonly messages: ReadonlyArray; + --}; + --export const V2GetWorkspaceMessagesResponse = Schema.Struct({ + -- featureEnabled: Schema.Boolean.annotate({ + -- description: "Whether the workspace-message backend route is available for this client.", + -- }), + -- messages: Schema.Array(V2GetWorkspaceMessagesResponse__WorkspaceMessage).annotate({ + -- description: "Active workspace messages returned by the backend.", + -- }), + --}).annotate({ title: "GetWorkspaceMessagesResponse" }); + -- + --export type V2GuardianWarningNotification = { readonly message: string; readonly threadId: string }; + --export const V2GuardianWarningNotification = Schema.Struct({ + -- message: Schema.String.annotate({ + -- description: "Concise guardian warning message for the user.", + -- }), + -- threadId: Schema.String.annotate({ description: "Thread target for the guardian warning." }), + --}).annotate({ title: "GuardianWarningNotification" }); + -- + - export type V2HookCompletedNotification = { + - readonly run: V2HookCompletedNotification__HookRunSummary; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2HookCompletedNotification = Schema.Struct({ + - turnId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }).annotate({ title: "HookCompletedNotification" }); + - + --export type V2HookCompletedNotification__HookSource = + -- | "system" + -- | "user" + -- | "project" + -- | "mdm" + -- | "sessionFlags" + -- | "plugin" + -- | "cloudRequirements" + -- | "cloudManagedConfig" + -- | "legacyManagedConfigFile" + -- | "legacyManagedConfigMdm" + -- | "unknown"; + --export const V2HookCompletedNotification__HookSource = Schema.Literals([ + -- "system", + -- "user", + -- "project", + -- "mdm", + -- "sessionFlags", + -- "plugin", + -- "cloudRequirements", + -- "cloudManagedConfig", + -- "legacyManagedConfigFile", + -- "legacyManagedConfigMdm", + -- "unknown", + --]); + -- + --export type V2HooksListParams = { readonly cwds?: ReadonlyArray }; + --export const V2HooksListParams = Schema.Struct({ + -- cwds: Schema.optionalKey( + -- Schema.Array(Schema.String).annotate({ + -- description: "When empty, defaults to the current session working directory.", + -- }), + -- ), + --}).annotate({ title: "HooksListParams" }); + -- + --export type V2HooksListResponse = { + -- readonly data: ReadonlyArray; + --}; + --export const V2HooksListResponse = Schema.Struct({ + -- data: Schema.Array(V2HooksListResponse__HooksListEntry), + --}).annotate({ title: "HooksListResponse" }); + -- + - export type V2HookStartedNotification = { + - readonly run: V2HookStartedNotification__HookRunSummary; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2HookStartedNotification = Schema.Struct({ + - turnId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }).annotate({ title: "HookStartedNotification" }); + - + --export type V2HookStartedNotification__HookSource = + -- | "system" + -- | "user" + -- | "project" + -- | "mdm" + -- | "sessionFlags" + -- | "plugin" + -- | "cloudRequirements" + -- | "cloudManagedConfig" + -- | "legacyManagedConfigFile" + -- | "legacyManagedConfigMdm" + -- | "unknown"; + --export const V2HookStartedNotification__HookSource = Schema.Literals([ + -- "system", + -- "user", + -- "project", + -- "mdm", + -- "sessionFlags", + -- "plugin", + -- "cloudRequirements", + -- "cloudManagedConfig", + -- "legacyManagedConfigFile", + -- "legacyManagedConfigMdm", + -- "unknown", + --]); + -- + - export type V2ItemCompletedNotification = { + -- readonly completedAtMs: number; + - readonly item: V2ItemCompletedNotification__ThreadItem; + - readonly threadId: string; + - readonly turnId: string; + - }; + - export const V2ItemCompletedNotification = Schema.Struct({ + -- completedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this item lifecycle completed.", + -- format: "int64", + -- }).check(Schema.isInt()), + - item: V2ItemCompletedNotification__ThreadItem, + - threadId: Schema.String, + - turnId: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemCompletedNotification__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ItemCompletedNotification__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + - export type V2ItemCompletedNotification__CollabAgentToolCallStatus = + - | "inProgress" + - | "completed" + -- | "failed" + -- | "interrupted"; + -+ | "failed"; + - export const V2ItemCompletedNotification__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ItemCompletedNotification__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemCompletedNotification__CommandExecutionSource = Schema.Litera + - + - export type V2ItemGuardianApprovalReviewCompletedNotification = { + - readonly action: V2ItemGuardianApprovalReviewCompletedNotification__GuardianApprovalReviewAction; + -- readonly completedAtMs: number; + - readonly decisionSource: V2ItemGuardianApprovalReviewCompletedNotification__AutoReviewDecisionSource; + - readonly review: V2ItemGuardianApprovalReviewCompletedNotification__GuardianApprovalReview; + - readonly reviewId: string; + -- readonly startedAtMs: number; + - readonly targetItemId?: string | null; + - readonly threadId: string; + - readonly turnId: string; + - }; + - export const V2ItemGuardianApprovalReviewCompletedNotification = Schema.Struct({ + - action: V2ItemGuardianApprovalReviewCompletedNotification__GuardianApprovalReviewAction, + -- completedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this review completed.", + -- format: "int64", + -- }).check(Schema.isInt()), + - decisionSource: V2ItemGuardianApprovalReviewCompletedNotification__AutoReviewDecisionSource, + - review: V2ItemGuardianApprovalReviewCompletedNotification__GuardianApprovalReview, + - reviewId: Schema.String.annotate({ description: "Stable identifier for this review." }), + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this review started.", + -- format: "int64", + -- }).check(Schema.isInt()), + - targetItemId: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemGuardianApprovalReviewCompletedNotification = Schema.Struct({ + - }).annotate({ + - title: "ItemGuardianApprovalReviewCompletedNotification", + - description: + -- "[UNSTABLE] Temporary notification payload for approval auto-review. This shape is expected to change soon.", + -+ "[UNSTABLE] Temporary notification payload for guardian automatic approval review. This shape is expected to change soon.", + - }); + - + - export type V2ItemGuardianApprovalReviewStartedNotification = { + - readonly action: V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalReviewAction; + - readonly review: V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalReview; + - readonly reviewId: string; + -- readonly startedAtMs: number; + - readonly targetItemId?: string | null; + - readonly threadId: string; + - readonly turnId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemGuardianApprovalReviewStartedNotification = Schema.Struct({ + - action: V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalReviewAction, + - review: V2ItemGuardianApprovalReviewStartedNotification__GuardianApprovalReview, + - reviewId: Schema.String.annotate({ description: "Stable identifier for this review." }), + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this review started.", + -- format: "int64", + -- }).check(Schema.isInt()), + - targetItemId: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ItemGuardianApprovalReviewStartedNotification = Schema.Struct({ + - }).annotate({ + - title: "ItemGuardianApprovalReviewStartedNotification", + - description: + -- "[UNSTABLE] Temporary notification payload for approval auto-review. This shape is expected to change soon.", + -+ "[UNSTABLE] Temporary notification payload for guardian automatic approval review. This shape is expected to change soon.", + - }); + - + - export type V2ItemStartedNotification = { + - readonly item: V2ItemStartedNotification__ThreadItem; + -- readonly startedAtMs: number; + - readonly threadId: string; + - readonly turnId: string; + - }; + - export const V2ItemStartedNotification = Schema.Struct({ + - item: V2ItemStartedNotification__ThreadItem, + -- startedAtMs: Schema.Number.annotate({ + -- description: "Unix timestamp (in milliseconds) when this item lifecycle started.", + -- format: "int64", + -- }).check(Schema.isInt()), + - threadId: Schema.String, + - turnId: Schema.String, + - }).annotate({ title: "ItemStartedNotification" }); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ItemStartedNotification__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ItemStartedNotification__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + - export type V2ItemStartedNotification__CollabAgentToolCallStatus = + - | "inProgress" + - | "completed" + -- | "failed" + -- | "interrupted"; + -+ | "failed"; + - export const V2ItemStartedNotification__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ItemStartedNotification__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ListMcpServerStatusParams = { + - readonly cursor?: string | null; + - readonly detail?: V2ListMcpServerStatusParams__McpServerStatusDetail | null; + - readonly limit?: number | null; + -- readonly threadId?: string | null; + - }; + - export const V2ListMcpServerStatusParams = Schema.Struct({ + - cursor: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ListMcpServerStatusParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }).annotate({ title: "ListMcpServerStatusParams" }); + - + - export type V2ListMcpServerStatusResponse = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ListMcpServerStatusResponse = Schema.Struct({ + - + - export type V2LoginAccountParams = + - | { readonly apiKey: string; readonly type: "apiKey" } + -- | { + -- readonly appBrand?: V2LoginAccountParams__LoginAppBrand | null; + -- readonly codexStreamlinedLogin?: boolean; + -- readonly type: "chatgpt"; + -- readonly useHostedLoginSuccessPage?: boolean; + -- } + -+ | { readonly type: "chatgpt" } + - | { readonly type: "chatgptDeviceCode" } + - | { + - readonly accessToken: string; + - readonly chatgptAccountId: string; + - readonly chatgptPlanType?: string | null; + - readonly type: "chatgptAuthTokens"; + -- } + -- | { readonly apiKey: string; readonly region: string; readonly type: "amazonBedrock" }; + -+ }; + - export const V2LoginAccountParams = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2LoginAccountParams = Schema.Union( + - type: Schema.Literal("apiKey").annotate({ title: "ApiKeyv2::LoginAccountParamsType" }), + - }).annotate({ title: "ApiKeyv2::LoginAccountParams" }), + - Schema.Struct({ + -- appBrand: Schema.optionalKey( + -- Schema.Union([V2LoginAccountParams__LoginAppBrand, Schema.Null]), + -- ), + -- codexStreamlinedLogin: Schema.optionalKey(Schema.Boolean), + - type: Schema.Literal("chatgpt").annotate({ title: "Chatgptv2::LoginAccountParamsType" }), + -- useHostedLoginSuccessPage: Schema.optionalKey(Schema.Boolean), + - }).annotate({ title: "Chatgptv2::LoginAccountParams" }), + - Schema.Struct({ + - type: Schema.Literal("chatgptDeviceCode").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2LoginAccountParams = Schema.Union( + - description: + - "[UNSTABLE] FOR OPENAI INTERNAL USE ONLY - DO NOT USE. The access token must contain the same scopes that Codex-managed ChatGPT auth tokens have.", + - }), + -- Schema.Struct({ + -- apiKey: Schema.String, + -- region: Schema.String, + -- type: Schema.Literal("amazonBedrock").annotate({ + -- title: "AmazonBedrockv2::LoginAccountParamsType", + -- }), + -- }).annotate({ + -- title: "AmazonBedrockv2::LoginAccountParams", + -- description: "[UNSTABLE] Managed Amazon Bedrock login is experimental.", + -- }), + - ], + - { mode: "oneOf" }, + - ).annotate({ title: "LoginAccountParams" }); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2LoginAccountResponse = + - readonly userCode: string; + - readonly verificationUrl: string; + - } + -- | { readonly type: "chatgptAuthTokens" } + -- | { readonly type: "amazonBedrock" }; + -+ | { readonly type: "chatgptAuthTokens" }; + - export const V2LoginAccountResponse = Schema.Union( + - [ + - Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2LoginAccountResponse = Schema.Union( + - title: "ChatgptAuthTokensv2::LoginAccountResponseType", + - }), + - }).annotate({ title: "ChatgptAuthTokensv2::LoginAccountResponse" }), + -- Schema.Struct({ + -- type: Schema.Literal("amazonBedrock").annotate({ + -- title: "AmazonBedrockv2::LoginAccountResponseType", + -- }), + -- }).annotate({ title: "AmazonBedrockv2::LoginAccountResponse" }), + - ], + - { mode: "oneOf" }, + - ).annotate({ title: "LoginAccountResponse" }); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2LogoutAccountResponse = Schema.Struct({}).annotate({ + - title: "LogoutAccountResponse", + - }); + - + --export type V2MarketplaceAddParams = { + -- readonly refName?: string | null; + -- readonly source: string; + -- readonly sparsePaths?: ReadonlyArray | null; + --}; + --export const V2MarketplaceAddParams = Schema.Struct({ + -- refName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- source: Schema.String, + -- sparsePaths: Schema.optionalKey(Schema.Union([Schema.Array(Schema.String), Schema.Null])), + --}).annotate({ title: "MarketplaceAddParams" }); + -- + --export type V2MarketplaceAddResponse = { + -- readonly alreadyAdded: boolean; + -- readonly installedRoot: V2MarketplaceAddResponse__AbsolutePathBuf; + -- readonly marketplaceName: string; + --}; + --export const V2MarketplaceAddResponse = Schema.Struct({ + -- alreadyAdded: Schema.Boolean, + -- installedRoot: V2MarketplaceAddResponse__AbsolutePathBuf, + -- marketplaceName: Schema.String, + --}).annotate({ title: "MarketplaceAddResponse" }); + -- + --export type V2MarketplaceRemoveParams = { readonly marketplaceName: string }; + --export const V2MarketplaceRemoveParams = Schema.Struct({ marketplaceName: Schema.String }).annotate( + -- { title: "MarketplaceRemoveParams" }, + --); + -- + --export type V2MarketplaceRemoveResponse = { + -- readonly installedRoot?: V2MarketplaceRemoveResponse__AbsolutePathBuf | null; + -- readonly marketplaceName: string; + --}; + --export const V2MarketplaceRemoveResponse = Schema.Struct({ + -- installedRoot: Schema.optionalKey( + -- Schema.Union([V2MarketplaceRemoveResponse__AbsolutePathBuf, Schema.Null]), + -- ), + -- marketplaceName: Schema.String, + --}).annotate({ title: "MarketplaceRemoveResponse" }); + -- + --export type V2MarketplaceUpgradeParams = { readonly marketplaceName?: string | null }; + --export const V2MarketplaceUpgradeParams = Schema.Struct({ + -- marketplaceName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}).annotate({ title: "MarketplaceUpgradeParams" }); + -- + --export type V2MarketplaceUpgradeResponse = { + -- readonly errors: ReadonlyArray; + -- readonly selectedMarketplaces: ReadonlyArray; + -- readonly upgradedRoots: ReadonlyArray; + --}; + --export const V2MarketplaceUpgradeResponse = Schema.Struct({ + -- errors: Schema.Array(V2MarketplaceUpgradeResponse__MarketplaceUpgradeErrorInfo), + -- selectedMarketplaces: Schema.Array(Schema.String), + -- upgradedRoots: Schema.Array(V2MarketplaceUpgradeResponse__AbsolutePathBuf), + --}).annotate({ title: "MarketplaceUpgradeResponse" }); + -- + - export type V2McpResourceReadParams = { + - readonly server: string; + -- readonly threadId?: string | null; + -+ readonly threadId: string; + - readonly uri: string; + - }; + - export const V2McpResourceReadParams = Schema.Struct({ + - server: Schema.String, + -- threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ threadId: Schema.String, + - uri: Schema.String, + - }).annotate({ title: "McpResourceReadParams" }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2McpServerOauthLoginCompletedNotification = { + - readonly error?: string | null; + - readonly name: string; + - readonly success: boolean; + -- readonly threadId?: string | null; + - }; + - export const V2McpServerOauthLoginCompletedNotification = Schema.Struct({ + - error: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - name: Schema.String, + - success: Schema.Boolean, + -- threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }).annotate({ title: "McpServerOauthLoginCompletedNotification" }); + - + - export type V2McpServerOauthLoginParams = { + - readonly name: string; + - readonly scopes?: ReadonlyArray | null; + -- readonly threadId?: string | null; + - readonly timeoutSecs?: number | null; + - }; + - export const V2McpServerOauthLoginParams = Schema.Struct({ + - name: Schema.String, + - scopes: Schema.optionalKey(Schema.Union([Schema.Array(Schema.String), Schema.Null])), + -- threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - timeoutSecs: Schema.optionalKey( + - Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + - ), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2McpServerRefreshResponse = Schema.Struct({}).annotate({ + - + - export type V2McpServerStatusUpdatedNotification = { + - readonly error?: string | null; + -- readonly failureReason?: V2McpServerStatusUpdatedNotification__McpServerStartupFailureReason | null; + - readonly name: string; + - readonly status: V2McpServerStatusUpdatedNotification__McpServerStartupState; + -- readonly threadId?: string | null; + - }; + - export const V2McpServerStatusUpdatedNotification = Schema.Struct({ + - error: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- failureReason: Schema.optionalKey( + -- Schema.Union([ + -- V2McpServerStatusUpdatedNotification__McpServerStartupFailureReason, + -- Schema.Null, + -- ]), + -- ), + - name: Schema.String, + - status: V2McpServerStatusUpdatedNotification__McpServerStartupState, + -- threadId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }).annotate({ title: "McpServerStatusUpdatedNotification" }); + - + - export type V2McpServerToolCallParams = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ModelListResponse = Schema.Struct({ + - ), + - }).annotate({ title: "ModelListResponse" }); + - + --export type V2ModelProviderCapabilitiesReadParams = {}; + --export const V2ModelProviderCapabilitiesReadParams = Schema.Struct({}).annotate({ + -- title: "ModelProviderCapabilitiesReadParams", + --}); + -- + --export type V2ModelProviderCapabilitiesReadResponse = { + -- readonly imageGeneration: boolean; + -- readonly namespaceTools: boolean; + -- readonly webSearch: boolean; + --}; + --export const V2ModelProviderCapabilitiesReadResponse = Schema.Struct({ + -- imageGeneration: Schema.Boolean, + -- namespaceTools: Schema.Boolean, + -- webSearch: Schema.Boolean, + --}).annotate({ title: "ModelProviderCapabilitiesReadResponse" }); + -- + - export type V2ModelReroutedNotification = { + - readonly fromModel: string; + - readonly reason: V2ModelReroutedNotification__ModelRerouteReason; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ModelReroutedNotification = Schema.Struct({ + - turnId: Schema.String, + - }).annotate({ title: "ModelReroutedNotification" }); + - + --export type V2ModelSafetyBufferingUpdatedNotification = { + -- readonly fasterModel?: string | null; + -- readonly model: string; + -- readonly reasons: ReadonlyArray; + -- readonly showBufferingUi: boolean; + -- readonly threadId: string; + -- readonly turnId: string; + -- readonly useCases: ReadonlyArray; + --}; + --export const V2ModelSafetyBufferingUpdatedNotification = Schema.Struct({ + -- fasterModel: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- model: Schema.String, + -- reasons: Schema.Array(Schema.String), + -- showBufferingUi: Schema.Boolean, + -- threadId: Schema.String, + -- turnId: Schema.String, + -- useCases: Schema.Array(Schema.String), + --}).annotate({ title: "ModelSafetyBufferingUpdatedNotification" }); + -- + --export type V2ModelVerificationNotification = { + -- readonly threadId: string; + -- readonly turnId: string; + -- readonly verifications: ReadonlyArray; + --}; + --export const V2ModelVerificationNotification = Schema.Struct({ + -- threadId: Schema.String, + -- turnId: Schema.String, + -- verifications: Schema.Array(V2ModelVerificationNotification__ModelVerification), + --}).annotate({ title: "ModelVerificationNotification" }); + -- + --export type V2PermissionProfileListParams = { + -- readonly cursor?: string | null; + -- readonly cwd?: string | null; + -- readonly limit?: number | null; + --}; + --export const V2PermissionProfileListParams = Schema.Struct({ + -- cursor: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Opaque pagination cursor returned by a previous call.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- cwd: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Optional working directory to resolve project config layers.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- limit: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Optional page size; defaults to the full result set.", + -- format: "uint32", + -- }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- Schema.Null, + -- ]), + -- ), + --}).annotate({ title: "PermissionProfileListParams" }); + -- + --export type V2PermissionProfileListResponse = { + -- readonly data: ReadonlyArray; + -- readonly nextCursor?: string | null; + --}; + --export const V2PermissionProfileListResponse = Schema.Struct({ + -- data: Schema.Array(V2PermissionProfileListResponse__PermissionProfileSummary), + -- nextCursor: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Opaque cursor to pass to the next call to continue after the last item. If None, there are no more items to return.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}).annotate({ title: "PermissionProfileListResponse" }); + -- + - export type V2PlanDeltaNotification = { + - readonly delta: string; + - readonly itemId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PlanDeltaNotification = Schema.Struct({ + - "EXPERIMENTAL - proposed plan streaming deltas for plan items. Clients should not assume concatenated deltas match the completed plan item content.", + - }); + - + --export type V2PluginInstalledParams = { + -- readonly cwds?: ReadonlyArray | null; + -- readonly installSuggestionPluginNames?: ReadonlyArray | null; + --}; + --export const V2PluginInstalledParams = Schema.Struct({ + -- cwds: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(V2PluginInstalledParams__AbsolutePathBuf).annotate({ + -- description: "Optional working directories used to discover repo marketplaces.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- installSuggestionPluginNames: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(Schema.String).annotate({ + -- description: + -- "Additional uninstalled plugin names that should be returned when present locally. This is used by mention surfaces that intentionally expose install entrypoints.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}).annotate({ title: "PluginInstalledParams" }); + -- + --export type V2PluginInstalledResponse = { + -- readonly marketplaceLoadErrors?: ReadonlyArray; + -- readonly marketplaces: ReadonlyArray; + --}; + --export const V2PluginInstalledResponse = Schema.Struct({ + -- marketplaceLoadErrors: Schema.optionalKey( + -- Schema.Array(V2PluginInstalledResponse__MarketplaceLoadErrorInfo).annotate({ default: [] }), + -- ), + -- marketplaces: Schema.Array(V2PluginInstalledResponse__PluginMarketplaceEntry), + --}).annotate({ title: "PluginInstalledResponse" }); + -- + --export type V2PluginInstalledResponse__PluginAvailability = "DISABLED_BY_ADMIN" | "AVAILABLE"; + --export const V2PluginInstalledResponse__PluginAvailability = Schema.Literals([ + -- "DISABLED_BY_ADMIN", + -- "AVAILABLE", + --]); + -- + - export type V2PluginInstallParams = { + -- readonly marketplacePath?: V2PluginInstallParams__AbsolutePathBuf | null; + -+ readonly forceRemoteSync?: boolean; + -+ readonly marketplacePath: V2PluginInstallParams__AbsolutePathBuf; + - readonly pluginName: string; + -- readonly remoteMarketplaceName?: string | null; + - }; + - export const V2PluginInstallParams = Schema.Struct({ + -- marketplacePath: Schema.optionalKey( + -- Schema.Union([V2PluginInstallParams__AbsolutePathBuf, Schema.Null]), + -+ forceRemoteSync: Schema.optionalKey( + -+ Schema.Boolean.annotate({ + -+ description: "When true, apply the remote plugin change before the local install flow.", + -+ }), + - ), + -+ marketplacePath: V2PluginInstallParams__AbsolutePathBuf, + - pluginName: Schema.String, + -- remoteMarketplaceName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }).annotate({ title: "PluginInstallParams" }); + - + - export type V2PluginInstallResponse = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginInstallResponse = Schema.Struct({ + - + - export type V2PluginListParams = { + - readonly cwds?: ReadonlyArray | null; + -- readonly marketplaceKinds?: ReadonlyArray | null; + -+ readonly forceRemoteSync?: boolean; + - }; + - export const V2PluginListParams = Schema.Struct({ + - cwds: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginListParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- marketplaceKinds: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(V2PluginListParams__PluginListMarketplaceKind).annotate({ + -- description: + -- "Optional marketplace kind filter. When omitted, only local marketplaces are queried, plus the default remote catalog when enabled by feature flag.", + -- }), + -- Schema.Null, + -- ]), + -+ forceRemoteSync: Schema.optionalKey( + -+ Schema.Boolean.annotate({ + -+ description: + -+ "When true, reconcile the official curated marketplace against the remote plugin state before listing marketplaces.", + -+ }), + - ), + - }).annotate({ title: "PluginListParams" }); + - + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2PluginListResponse = { + - readonly featuredPluginIds?: ReadonlyArray; + - readonly marketplaceLoadErrors?: ReadonlyArray; + - readonly marketplaces: ReadonlyArray; + -+ readonly remoteSyncError?: string | null; + - }; + - export const V2PluginListResponse = Schema.Struct({ + - featuredPluginIds: Schema.optionalKey(Schema.Array(Schema.String).annotate({ default: [] })), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginListResponse = Schema.Struct({ + - Schema.Array(V2PluginListResponse__MarketplaceLoadErrorInfo).annotate({ default: [] }), + - ), + - marketplaces: Schema.Array(V2PluginListResponse__PluginMarketplaceEntry), + -+ remoteSyncError: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }).annotate({ title: "PluginListResponse" }); + - + --export type V2PluginListResponse__PluginAvailability = "DISABLED_BY_ADMIN" | "AVAILABLE"; + --export const V2PluginListResponse__PluginAvailability = Schema.Literals([ + -- "DISABLED_BY_ADMIN", + -- "AVAILABLE", + --]); + -- + - export type V2PluginReadParams = { + -- readonly marketplacePath?: V2PluginReadParams__AbsolutePathBuf | null; + -+ readonly marketplacePath: V2PluginReadParams__AbsolutePathBuf; + - readonly pluginName: string; + -- readonly remoteMarketplaceName?: string | null; + - }; + - export const V2PluginReadParams = Schema.Struct({ + -- marketplacePath: Schema.optionalKey( + -- Schema.Union([V2PluginReadParams__AbsolutePathBuf, Schema.Null]), + -- ), + -+ marketplacePath: V2PluginReadParams__AbsolutePathBuf, + - pluginName: Schema.String, + -- remoteMarketplaceName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - }).annotate({ title: "PluginReadParams" }); + - + - export type V2PluginReadResponse = { readonly plugin: V2PluginReadResponse__PluginDetail }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2PluginReadResponse = Schema.Struct({ + - plugin: V2PluginReadResponse__PluginDetail, + - }).annotate({ title: "PluginReadResponse" }); + - + --export type V2PluginReadResponse__PluginAvailability = "DISABLED_BY_ADMIN" | "AVAILABLE"; + --export const V2PluginReadResponse__PluginAvailability = Schema.Literals([ + -- "DISABLED_BY_ADMIN", + -- "AVAILABLE", + --]); + -- + --export type V2PluginShareCheckoutParams = { readonly remotePluginId: string }; + --export const V2PluginShareCheckoutParams = Schema.Struct({ + -- remotePluginId: Schema.String, + --}).annotate({ title: "PluginShareCheckoutParams" }); + -- + --export type V2PluginShareCheckoutResponse = { + -- readonly marketplaceName: string; + -- readonly marketplacePath: V2PluginShareCheckoutResponse__AbsolutePathBuf; + -+export type V2PluginUninstallParams = { + -+ readonly forceRemoteSync?: boolean; + - readonly pluginId: string; + -- readonly pluginName: string; + -- readonly pluginPath: V2PluginShareCheckoutResponse__AbsolutePathBuf; + -- readonly remotePluginId: string; + -- readonly remoteVersion?: string | null; + - }; + --export const V2PluginShareCheckoutResponse = Schema.Struct({ + -- marketplaceName: Schema.String, + -- marketplacePath: V2PluginShareCheckoutResponse__AbsolutePathBuf, + -+export const V2PluginUninstallParams = Schema.Struct({ + -+ forceRemoteSync: Schema.optionalKey( + -+ Schema.Boolean.annotate({ + -+ description: "When true, apply the remote plugin change before the local uninstall flow.", + -+ }), + -+ ), + - pluginId: Schema.String, + -- pluginName: Schema.String, + -- pluginPath: V2PluginShareCheckoutResponse__AbsolutePathBuf, + -- remotePluginId: Schema.String, + -- remoteVersion: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}).annotate({ title: "PluginShareCheckoutResponse" }); + -- + --export type V2PluginShareDeleteParams = { readonly remotePluginId: string }; + --export const V2PluginShareDeleteParams = Schema.Struct({ remotePluginId: Schema.String }).annotate({ + -- title: "PluginShareDeleteParams", + --}); + -- + --export type V2PluginShareDeleteResponse = {}; + --export const V2PluginShareDeleteResponse = Schema.Struct({}).annotate({ + -- title: "PluginShareDeleteResponse", + --}); + -- + --export type V2PluginShareListParams = {}; + --export const V2PluginShareListParams = Schema.Struct({}).annotate({ + -- title: "PluginShareListParams", + --}); + -- + --export type V2PluginShareListResponse = { + -- readonly data: ReadonlyArray; + --}; + --export const V2PluginShareListResponse = Schema.Struct({ + -- data: Schema.Array(V2PluginShareListResponse__PluginShareListItem), + --}).annotate({ title: "PluginShareListResponse" }); + -- + --export type V2PluginShareListResponse__PluginAvailability = "DISABLED_BY_ADMIN" | "AVAILABLE"; + --export const V2PluginShareListResponse__PluginAvailability = Schema.Literals([ + -- "DISABLED_BY_ADMIN", + -- "AVAILABLE", + --]); + -- + --export type V2PluginShareSaveParams = { + -- readonly discoverability?: V2PluginShareSaveParams__PluginShareDiscoverability | null; + -- readonly pluginPath: V2PluginShareSaveParams__AbsolutePathBuf; + -- readonly remotePluginId?: string | null; + -- readonly shareTargets?: ReadonlyArray | null; + --}; + --export const V2PluginShareSaveParams = Schema.Struct({ + -- discoverability: Schema.optionalKey( + -- Schema.Union([V2PluginShareSaveParams__PluginShareDiscoverability, Schema.Null]), + -- ), + -- pluginPath: V2PluginShareSaveParams__AbsolutePathBuf, + -- remotePluginId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- shareTargets: Schema.optionalKey( + -- Schema.Union([Schema.Array(V2PluginShareSaveParams__PluginShareTarget), Schema.Null]), + -- ), + --}).annotate({ title: "PluginShareSaveParams" }); + -- + --export type V2PluginShareSaveResponse = { + -- readonly remotePluginId: string; + -- readonly shareUrl: string; + --}; + --export const V2PluginShareSaveResponse = Schema.Struct({ + -- remotePluginId: Schema.String, + -- shareUrl: Schema.String, + --}).annotate({ title: "PluginShareSaveResponse" }); + -- + --export type V2PluginShareUpdateTargetsParams = { + -- readonly discoverability: V2PluginShareUpdateTargetsParams__PluginShareUpdateDiscoverability; + -- readonly remotePluginId: string; + -- readonly shareTargets: ReadonlyArray; + --}; + --export const V2PluginShareUpdateTargetsParams = Schema.Struct({ + -- discoverability: V2PluginShareUpdateTargetsParams__PluginShareUpdateDiscoverability, + -- remotePluginId: Schema.String, + -- shareTargets: Schema.Array(V2PluginShareUpdateTargetsParams__PluginShareTarget), + --}).annotate({ title: "PluginShareUpdateTargetsParams" }); + -- + --export type V2PluginShareUpdateTargetsResponse = { + -- readonly discoverability: V2PluginShareUpdateTargetsResponse__PluginShareDiscoverability; + -- readonly principals: ReadonlyArray; + --}; + --export const V2PluginShareUpdateTargetsResponse = Schema.Struct({ + -- discoverability: V2PluginShareUpdateTargetsResponse__PluginShareDiscoverability, + -- principals: Schema.Array(V2PluginShareUpdateTargetsResponse__PluginSharePrincipal), + --}).annotate({ title: "PluginShareUpdateTargetsResponse" }); + -- + --export type V2PluginSkillReadParams = { + -- readonly remoteMarketplaceName: string; + -- readonly remotePluginId: string; + -- readonly skillName: string; + --}; + --export const V2PluginSkillReadParams = Schema.Struct({ + -- remoteMarketplaceName: Schema.String, + -- remotePluginId: Schema.String, + -- skillName: Schema.String, + --}).annotate({ title: "PluginSkillReadParams" }); + -- + --export type V2PluginSkillReadResponse = { readonly contents?: string | null }; + --export const V2PluginSkillReadResponse = Schema.Struct({ + -- contents: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}).annotate({ title: "PluginSkillReadResponse" }); + -- + --export type V2PluginUninstallParams = { readonly pluginId: string }; + --export const V2PluginUninstallParams = Schema.Struct({ pluginId: Schema.String }).annotate({ + -- title: "PluginUninstallParams", + --}); + -+}).annotate({ title: "PluginUninstallParams" }); + - + - export type V2PluginUninstallResponse = {}; + - export const V2PluginUninstallResponse = Schema.Struct({}).annotate({ + - title: "PluginUninstallResponse", + - }); + - + --export type V2ProcessExitedNotification = { + -- readonly exitCode: number; + -- readonly processHandle: string; + -- readonly stderr: string; + -- readonly stderrCapReached: boolean; + -- readonly stdout: string; + -- readonly stdoutCapReached: boolean; + --}; + --export const V2ProcessExitedNotification = Schema.Struct({ + -- exitCode: Schema.Number.annotate({ description: "Process exit code.", format: "int32" }).check( + -- Schema.isInt(), + -- ), + -- processHandle: Schema.String.annotate({ + -- description: "Client-supplied, connection-scoped `processHandle` from `process/spawn`.", + -- }), + -- stderr: Schema.String.annotate({ + -- description: + -- "Buffered stderr capture.\n\nEmpty when stderr was streamed via `process/outputDelta`.", + -- }), + -- stderrCapReached: Schema.Boolean.annotate({ + -- description: + -- "Whether stderr reached `outputBytesCap`.\n\nIn streaming mode, stderr is empty and cap state is also reported on the final stderr `process/outputDelta` notification.", + -- }), + -- stdout: Schema.String.annotate({ + -- description: + -- "Buffered stdout capture.\n\nEmpty when stdout was streamed via `process/outputDelta`.", + -- }), + -- stdoutCapReached: Schema.Boolean.annotate({ + -- description: + -- "Whether stdout reached `outputBytesCap`.\n\nIn streaming mode, stdout is empty and cap state is also reported on the final stdout `process/outputDelta` notification.", + -- }), + --}).annotate({ + -- title: "ProcessExitedNotification", + -- description: "Final process exit notification for `process/spawn`.", + --}); + -- + --export type V2ProcessOutputDeltaNotification = { + -- readonly capReached: boolean; + -- readonly deltaBase64: string; + -- readonly processHandle: string; + -- readonly stream: "stdout" | "stderr"; + --}; + --export const V2ProcessOutputDeltaNotification = Schema.Struct({ + -- capReached: Schema.Boolean.annotate({ + -- description: + -- "True on the final streamed chunk for this stream when output was truncated by `outputBytesCap`.", + -- }), + -- deltaBase64: Schema.String.annotate({ description: "Base64-encoded output bytes." }), + -- processHandle: Schema.String.annotate({ + -- description: "Client-supplied, connection-scoped `processHandle` from `process/spawn`.", + -- }), + -- stream: Schema.Literals(["stdout", "stderr"]).annotate({ + -- description: "Stream label for `process/outputDelta` notifications.", + -- }), + --}).annotate({ + -- title: "ProcessOutputDeltaNotification", + -- description: "Base64-encoded output chunk emitted for a streaming `process/spawn` request.", + --}); + -- + --export type V2ProcessOutputDeltaNotification__ProcessOutputStream = "stdout" | "stderr"; + --export const V2ProcessOutputDeltaNotification__ProcessOutputStream = Schema.Literals([ + -- "stdout", + -- "stderr", + --]).annotate({ description: "Stream label for `process/outputDelta` notifications." }); + -- + --export type V2RawResponseCompletedNotification = { + -- readonly responseId: string; + -- readonly threadId: string; + -- readonly turnId: string; + -- readonly usage?: V2RawResponseCompletedNotification__TokenUsageBreakdown | null; + --}; + --export const V2RawResponseCompletedNotification = Schema.Struct({ + -- responseId: Schema.String, + -- threadId: Schema.String, + -- turnId: Schema.String, + -- usage: Schema.optionalKey( + -- Schema.Union([V2RawResponseCompletedNotification__TokenUsageBreakdown, Schema.Null]), + -- ), + --}).annotate({ + -- title: "RawResponseCompletedNotification", + -- description: + -- "Internal-only notification containing the exact usage from one upstream Responses API completion.", + --}); + -- + - export type V2RawResponseItemCompletedNotification = { + - readonly item: V2RawResponseItemCompletedNotification__ResponseItem; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReasoningTextDeltaNotification = Schema.Struct({ + - turnId: Schema.String, + - }).annotate({ title: "ReasoningTextDeltaNotification" }); + - + --export type V2RemoteControlStatusChangedNotification = { + -- readonly environmentId?: string | null; + -- readonly installationId: string; + -- readonly serverName: string; + -- readonly status: V2RemoteControlStatusChangedNotification__RemoteControlConnectionStatus; + --}; + --export const V2RemoteControlStatusChangedNotification = Schema.Struct({ + -- environmentId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- installationId: Schema.String, + -- serverName: Schema.String, + -- status: V2RemoteControlStatusChangedNotification__RemoteControlConnectionStatus, + --}).annotate({ + -- title: "RemoteControlStatusChangedNotification", + -- description: "Current remote-control connection status and remote identity exposed to clients.", + --}); + -- + - export type V2ReviewStartParams = { + - readonly delivery?: V2ReviewStartParams__ReviewDelivery | null; + - readonly target: V2ReviewStartParams__ReviewTarget; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ReviewStartResponse__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ReviewStartResponse__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + - export type V2ReviewStartResponse__CollabAgentToolCallStatus = + - | "inProgress" + - | "completed" + -- | "failed" + -- | "interrupted"; + -+ | "failed"; + - export const V2ReviewStartResponse__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ReviewStartResponse__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ReviewStartResponse__CommandExecutionSource = Schema.Literals([ + - "unifiedExecInteraction", + - ]); + - + --export type V2ReviewStartResponse__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2ReviewStartResponse__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + --export type V2SendAddCreditsNudgeEmailParams = { + -- readonly creditType: V2SendAddCreditsNudgeEmailParams__AddCreditsNudgeCreditType; + --}; + --export const V2SendAddCreditsNudgeEmailParams = Schema.Struct({ + -- creditType: V2SendAddCreditsNudgeEmailParams__AddCreditsNudgeCreditType, + --}).annotate({ title: "SendAddCreditsNudgeEmailParams" }); + -- + --export type V2SendAddCreditsNudgeEmailResponse = { + -- readonly status: V2SendAddCreditsNudgeEmailResponse__AddCreditsNudgeEmailStatus; + --}; + --export const V2SendAddCreditsNudgeEmailResponse = Schema.Struct({ + -- status: V2SendAddCreditsNudgeEmailResponse__AddCreditsNudgeEmailStatus, + --}).annotate({ title: "SendAddCreditsNudgeEmailResponse" }); + -- + - export type V2ServerRequestResolvedNotification = { + - readonly requestId: V2ServerRequestResolvedNotification__RequestId; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2SkillsConfigWriteResponse = Schema.Struct({ + - effectiveEnabled: Schema.Boolean, + - }).annotate({ title: "SkillsConfigWriteResponse" }); + - + --export type V2SkillsExtraRootsSetParams = { + -- readonly extraRoots: ReadonlyArray; + --}; + --export const V2SkillsExtraRootsSetParams = Schema.Struct({ + -- extraRoots: Schema.Array(V2SkillsExtraRootsSetParams__AbsolutePathBuf), + --}).annotate({ title: "SkillsExtraRootsSetParams" }); + -- + --export type V2SkillsExtraRootsSetResponse = {}; + --export const V2SkillsExtraRootsSetResponse = Schema.Struct({}).annotate({ + -- title: "SkillsExtraRootsSetResponse", + --}); + -- + - export type V2SkillsListParams = { + - readonly cwds?: ReadonlyArray; + - readonly forceReload?: boolean; + -+ readonly perCwdExtraUserRoots?: ReadonlyArray | null; + - }; + - export const V2SkillsListParams = Schema.Struct({ + - cwds: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2SkillsListParams = Schema.Struct({ + - description: "When true, bypass the skills cache and re-scan skills from disk.", + - }), + - ), + -+ perCwdExtraUserRoots: Schema.optionalKey( + -+ Schema.Union([ + -+ Schema.Array(V2SkillsListParams__SkillsListExtraRootsForCwd).annotate({ + -+ description: "Optional per-cwd extra roots to scan as user-scoped skills.", + -+ }), + -+ Schema.Null, + -+ ]), + -+ ), + - }).annotate({ title: "SkillsListParams" }); + - + - export type V2SkillsListResponse = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TerminalInteractionNotification = Schema.Struct({ + - turnId: Schema.String, + - }).annotate({ title: "TerminalInteractionNotification" }); + - + --export type V2ThreadApproveGuardianDeniedActionParams = { + -- readonly event: unknown; + -- readonly threadId: string; + --}; + --export const V2ThreadApproveGuardianDeniedActionParams = Schema.Struct({ + -- event: Schema.Unknown.annotate({ + -- description: "Serialized `codex_protocol::protocol::GuardianAssessmentEvent`.", + -- }), + -- threadId: Schema.String, + --}).annotate({ title: "ThreadApproveGuardianDeniedActionParams" }); + -- + --export type V2ThreadApproveGuardianDeniedActionResponse = {}; + --export const V2ThreadApproveGuardianDeniedActionResponse = Schema.Struct({}).annotate({ + -- title: "ThreadApproveGuardianDeniedActionResponse", + --}); + -- + - export type V2ThreadArchivedNotification = { readonly threadId: string }; + - export const V2ThreadArchivedNotification = Schema.Struct({ threadId: Schema.String }).annotate({ + - title: "ThreadArchivedNotification", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadCompactStartResponse = Schema.Struct({}).annotate({ + - title: "ThreadCompactStartResponse", + - }); + - + --export type V2ThreadDeletedNotification = { readonly threadId: string }; + --export const V2ThreadDeletedNotification = Schema.Struct({ threadId: Schema.String }).annotate({ + -- title: "ThreadDeletedNotification", + --}); + -- + --export type V2ThreadDeleteParams = { readonly threadId: string }; + --export const V2ThreadDeleteParams = Schema.Struct({ threadId: Schema.String }).annotate({ + -- title: "ThreadDeleteParams", + --}); + -- + --export type V2ThreadDeleteResponse = {}; + --export const V2ThreadDeleteResponse = Schema.Struct({}).annotate({ title: "ThreadDeleteResponse" }); + -- + - export type V2ThreadForkParams = { + - readonly approvalPolicy?: V2ThreadForkParams__AskForApproval | null; + - readonly approvalsReviewer?: V2ThreadForkParams__ApprovalsReviewer | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkParams = { + - readonly cwd?: string | null; + - readonly developerInstructions?: string | null; + - readonly ephemeral?: boolean; + -- readonly lastTurnId?: string | null; + - readonly model?: string | null; + - readonly modelProvider?: string | null; + - readonly sandbox?: V2ThreadForkParams__SandboxMode | null; + -- readonly serviceTier?: string | null; + -+ readonly serviceTier?: V2ThreadForkParams__ServiceTier | null | null; + - readonly threadId: string; + -- readonly threadSource?: V2ThreadForkParams__ThreadSource | null; + - }; + - export const V2ThreadForkParams = Schema.Struct({ + - approvalPolicy: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkParams = Schema.Struct({ + - cwd: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - developerInstructions: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - ephemeral: Schema.optionalKey(Schema.Boolean), + -- lastTurnId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Optional last turn id to fork through, inclusive.\n\nWhen specified, turns after `last_turn_id` are omitted from the fork. The referenced turn cannot be in progress.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - model: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkParams = Schema.Struct({ + - ), + - modelProvider: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - sandbox: Schema.optionalKey(Schema.Union([V2ThreadForkParams__SandboxMode, Schema.Null])), + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- threadId: Schema.String, + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadForkParams__ThreadSource, Schema.Null]).annotate({ + -- description: + -- "Optional client-supplied analytics source classification for this forked thread.", + -- }), + -+ serviceTier: Schema.optionalKey( + -+ Schema.Union([Schema.Union([V2ThreadForkParams__ServiceTier, Schema.Null]), Schema.Null]), + - ), + -+ threadId: Schema.String, + - }).annotate({ + - title: "ThreadForkParams", + - description: + -- "There are two ways to fork a thread: 1. By thread_id: load the thread from disk by thread_id and fork it into a new thread. 2. By path: load the thread from disk by path and fork it into a new thread.\n\nIf using a non-empty path, the thread_id param will be ignored. Empty string path values are treated as absent.\n\nPrefer using thread_id whenever possible.", + --}); + -- + --export type V2ThreadForkParams__AbsolutePathBuf = string; + --export const V2ThreadForkParams__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -+ "There are two ways to fork a thread: 1. By thread_id: load the thread from disk by thread_id and fork it into a new thread. 2. By path: load the thread from disk by path and fork it into a new thread.\n\nIf using path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.", + - }); + - + - export type V2ThreadForkResponse = { + - readonly approvalPolicy: V2ThreadForkResponse__AskForApproval; + -- readonly approvalsReviewer: "user" | "auto_review" | "guardian_subagent"; + -- readonly cwd: V2ThreadForkResponse__AbsolutePathBuf; + -- readonly instructionSources?: ReadonlyArray; + -+ readonly approvalsReviewer: "user" | "guardian_subagent"; + -+ readonly cwd: string; + - readonly model: string; + - readonly modelProvider: string; + - readonly reasoningEffort?: V2ThreadForkResponse__ReasoningEffort | null; + -- readonly sandbox: + -- | { readonly type: "dangerFullAccess" } + -- | { readonly networkAccess?: boolean; readonly type: "readOnly" } + -- | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + -- | { + -- readonly excludeSlashTmp?: boolean; + -- readonly excludeTmpdirEnvVar?: boolean; + -- readonly networkAccess?: boolean; + -- readonly type: "workspaceWrite"; + -- readonly writableRoots?: ReadonlyArray; + -- }; + -- readonly serviceTier?: string | null; + -+ readonly sandbox: V2ThreadForkResponse__SandboxPolicy; + -+ readonly serviceTier?: V2ThreadForkResponse__ServiceTier | null; + - readonly thread: V2ThreadForkResponse__Thread; + - }; + - export const V2ThreadForkResponse = Schema.Struct({ + - approvalPolicy: V2ThreadForkResponse__AskForApproval, + -- approvalsReviewer: Schema.Literals(["user", "auto_review", "guardian_subagent"]).annotate({ + -+ approvalsReviewer: Schema.Literals(["user", "guardian_subagent"]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }), + -- cwd: V2ThreadForkResponse__AbsolutePathBuf, + -- instructionSources: Schema.optionalKey( + -- Schema.Array(V2ThreadForkResponse__LegacyAppPathString).annotate({ + -- description: + -- "Environment-native paths to instruction source files currently loaded for this thread.", + -- default: [], + -- }), + -- ), + -+ cwd: Schema.String, + - model: Schema.String, + - modelProvider: Schema.String, + - reasoningEffort: Schema.optionalKey( + - Schema.Union([V2ThreadForkResponse__ReasoningEffort, Schema.Null]), + - ), + -- sandbox: Schema.Union( + -- [ + -- Schema.Struct({ + -- type: Schema.Literal("dangerFullAccess").annotate({ + -- title: "DangerFullAccessSandboxPolicyType", + -- }), + -- }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + -- }).annotate({ title: "ReadOnlySandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey( + -- Schema.Literals(["restricted", "enabled"]).annotate({ default: "restricted" }), + -- ), + -- type: Schema.Literal("externalSandbox").annotate({ + -- title: "ExternalSandboxSandboxPolicyType", + -- }), + -- }).annotate({ title: "ExternalSandboxSandboxPolicy" }), + -- Schema.Struct({ + -- excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("workspaceWrite").annotate({ + -- title: "WorkspaceWriteSandboxPolicyType", + -- }), + -- writableRoots: Schema.optionalKey( + -- Schema.Array(V2ThreadForkResponse__AbsolutePathBuf).annotate({ default: [] }), + -- ), + -- }).annotate({ title: "WorkspaceWriteSandboxPolicy" }), + -- ], + -- { mode: "oneOf" }, + -- ).annotate({ + -- description: + -- "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance.", + -- }), + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ sandbox: V2ThreadForkResponse__SandboxPolicy, + -+ serviceTier: Schema.optionalKey(Schema.Union([V2ThreadForkResponse__ServiceTier, Schema.Null])), + - thread: V2ThreadForkResponse__Thread, + - }).annotate({ title: "ThreadForkResponse" }); + - + --export type V2ThreadForkResponse__ActivePermissionProfile = { + -- readonly extends?: string | null; + -- readonly id: string; + --}; + --export const V2ThreadForkResponse__ActivePermissionProfile = Schema.Struct({ + -- extends: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Parent profile identifier from the selected permissions profile's `extends` setting, when present.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- id: Schema.String.annotate({ + -- description: + -- "Identifier from `default_permissions` or the implicit built-in default, such as `:workspace` or a user-defined `[permissions.]` profile.", + -- }), + --}); + -- + --export type V2ThreadForkResponse__ApprovalsReviewer = "user" | "auto_review" | "guardian_subagent"; + -+export type V2ThreadForkResponse__ApprovalsReviewer = "user" | "guardian_subagent"; + - export const V2ThreadForkResponse__ApprovalsReviewer = Schema.Literals([ + - "user", + -- "auto_review", + - "guardian_subagent", + - ]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }); + - + - export type V2ThreadForkResponse__ByteRange = { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadForkResponse__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ThreadForkResponse__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + --export type V2ThreadForkResponse__CollabAgentToolCallStatus = + -- | "inProgress" + -- | "completed" + -- | "failed" + -- | "interrupted"; + -+export type V2ThreadForkResponse__CollabAgentToolCallStatus = "inProgress" | "completed" | "failed"; + - export const V2ThreadForkResponse__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ThreadForkResponse__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__CommandExecutionSource = Schema.Literals([ + - "unifiedExecInteraction", + - ]); + - + --export type V2ThreadForkResponse__MultiAgentMode = + -- | "explicitRequestOnly" + -- | "proactive" + -- | { readonly custom: string }; + --export const V2ThreadForkResponse__MultiAgentMode = Schema.Union( + -- [ + -- Schema.Literals(["explicitRequestOnly", "proactive"]), + -- Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomMultiAgentMode" }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ + -- description: + -- "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.", + --}); + -- + - export type V2ThreadForkResponse__NetworkAccess = "restricted" | "enabled"; + - export const V2ThreadForkResponse__NetworkAccess = Schema.Literals(["restricted", "enabled"]); + - + --export type V2ThreadForkResponse__SandboxPolicy = + -- | { readonly type: "dangerFullAccess" } + -- | { readonly networkAccess?: boolean; readonly type: "readOnly" } + -- | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + -+export type V2ThreadForkResponse__ReadOnlyAccess = + - | { + -- readonly excludeSlashTmp?: boolean; + -- readonly excludeTmpdirEnvVar?: boolean; + -- readonly networkAccess?: boolean; + -- readonly type: "workspaceWrite"; + -- readonly writableRoots?: ReadonlyArray; + -- }; + --export const V2ThreadForkResponse__SandboxPolicy = Schema.Union( + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+export const V2ThreadForkResponse__ReadOnlyAccess = Schema.Union( + - [ + - Schema.Struct({ + -- type: Schema.Literal("dangerFullAccess").annotate({ + -- title: "DangerFullAccessSandboxPolicyType", + -- }), + -- }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + -- }).annotate({ title: "ReadOnlySandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey( + -- Schema.Literals(["restricted", "enabled"]).annotate({ default: "restricted" }), + -- ), + -- type: Schema.Literal("externalSandbox").annotate({ + -- title: "ExternalSandboxSandboxPolicyType", + -- }), + -- }).annotate({ title: "ExternalSandboxSandboxPolicy" }), + -- Schema.Struct({ + -- excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("workspaceWrite").annotate({ title: "WorkspaceWriteSandboxPolicyType" }), + -- writableRoots: Schema.optionalKey( + -+ includePlatformDefaults: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + -+ readableRoots: Schema.optionalKey( + - Schema.Array(V2ThreadForkResponse__AbsolutePathBuf).annotate({ default: [] }), + - ), + -- }).annotate({ title: "WorkspaceWriteSandboxPolicy" }), + -+ type: Schema.Literal("restricted").annotate({ title: "RestrictedReadOnlyAccessType" }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ title: "FullAccessReadOnlyAccessType" }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__SessionSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadForkResponse__ThreadExtra = {}; + --export const V2ThreadForkResponse__ThreadExtra = Schema.Struct({}).annotate({ + -- description: "Extra app-server data for a thread.", + --}); + -- + --export type V2ThreadForkResponse__ThreadHistoryMode = "legacy" | "paginated"; + --export const V2ThreadForkResponse__ThreadHistoryMode = Schema.Literals(["legacy", "paginated"]); + -- + - export type V2ThreadForkResponse__ThreadStatus = + - | { readonly type: "notLoaded" } + - | { readonly type: "idle" } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadForkResponse__ThreadStatus = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadForkResponse__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2ThreadForkResponse__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + --export type V2ThreadGoalClearedNotification = { readonly threadId: string }; + --export const V2ThreadGoalClearedNotification = Schema.Struct({ threadId: Schema.String }).annotate({ + -- title: "ThreadGoalClearedNotification", + --}); + -- + --export type V2ThreadGoalClearParams = { readonly threadId: string }; + --export const V2ThreadGoalClearParams = Schema.Struct({ threadId: Schema.String }).annotate({ + -- title: "ThreadGoalClearParams", + --}); + -- + --export type V2ThreadGoalClearResponse = { readonly cleared: boolean }; + --export const V2ThreadGoalClearResponse = Schema.Struct({ cleared: Schema.Boolean }).annotate({ + -- title: "ThreadGoalClearResponse", + --}); + -- + --export type V2ThreadGoalGetParams = { readonly threadId: string }; + --export const V2ThreadGoalGetParams = Schema.Struct({ threadId: Schema.String }).annotate({ + -- title: "ThreadGoalGetParams", + --}); + -- + --export type V2ThreadGoalGetResponse = { + -- readonly goal?: V2ThreadGoalGetResponse__ThreadGoal | null; + --}; + --export const V2ThreadGoalGetResponse = Schema.Struct({ + -- goal: Schema.optionalKey(Schema.Union([V2ThreadGoalGetResponse__ThreadGoal, Schema.Null])), + --}).annotate({ title: "ThreadGoalGetResponse" }); + -- + --export type V2ThreadGoalSetParams = { + -- readonly objective?: string | null; + -- readonly status?: V2ThreadGoalSetParams__ThreadGoalStatus | null; + -- readonly threadId: string; + -- readonly tokenBudget?: number | null; + --}; + --export const V2ThreadGoalSetParams = Schema.Struct({ + -- objective: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- status: Schema.optionalKey(Schema.Union([V2ThreadGoalSetParams__ThreadGoalStatus, Schema.Null])), + -- threadId: Schema.String, + -- tokenBudget: Schema.optionalKey( + -- Schema.Union([Schema.Number.annotate({ format: "int64" }).check(Schema.isInt()), Schema.Null]), + -- ), + --}).annotate({ title: "ThreadGoalSetParams" }); + -- + --export type V2ThreadGoalSetResponse = { readonly goal: V2ThreadGoalSetResponse__ThreadGoal }; + --export const V2ThreadGoalSetResponse = Schema.Struct({ + -- goal: V2ThreadGoalSetResponse__ThreadGoal, + --}).annotate({ title: "ThreadGoalSetResponse" }); + -- + --export type V2ThreadGoalUpdatedNotification = { + -- readonly goal: V2ThreadGoalUpdatedNotification__ThreadGoal; + -- readonly threadId: string; + -- readonly turnId?: string | null; + --}; + --export const V2ThreadGoalUpdatedNotification = Schema.Struct({ + -- goal: V2ThreadGoalUpdatedNotification__ThreadGoal, + -- threadId: Schema.String, + -- turnId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}).annotate({ title: "ThreadGoalUpdatedNotification" }); + -- + --export type V2ThreadInjectItemsParams = { + -- readonly items: ReadonlyArray; + -- readonly threadId: string; + --}; + --export const V2ThreadInjectItemsParams = Schema.Struct({ + -- items: Schema.Array(Schema.Unknown).annotate({ + -- description: "Raw Responses API items to append to the thread's model-visible history.", + -- }), + -- threadId: Schema.String, + --}).annotate({ title: "ThreadInjectItemsParams" }); + -- + --export type V2ThreadInjectItemsResponse = {}; + --export const V2ThreadInjectItemsResponse = Schema.Struct({}).annotate({ + -- title: "ThreadInjectItemsResponse", + --}); + -- + - export type V2ThreadListParams = { + - readonly archived?: boolean | null; + - readonly cursor?: string | null; + -- readonly cwd?: V2ThreadListParams__ThreadListCwdFilter | null; + -+ readonly cwd?: string | null; + - readonly limit?: number | null; + - readonly modelProviders?: ReadonlyArray | null; + - readonly searchTerm?: string | null; + -- readonly sortDirection?: V2ThreadListParams__SortDirection | null; + - readonly sortKey?: V2ThreadListParams__ThreadSortKey | null; + - readonly sourceKinds?: ReadonlyArray | null; + -- readonly useStateDbOnly?: boolean; + - }; + - export const V2ThreadListParams = Schema.Struct({ + - archived: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListParams = Schema.Struct({ + - ]), + - ), + - cwd: Schema.optionalKey( + -- Schema.Union([V2ThreadListParams__ThreadListCwdFilter, Schema.Null]).annotate({ + -- description: + -- "Optional cwd filter or filters; when set, only threads whose session cwd exactly matches one of these paths are returned.", + -- }), + -+ Schema.Union([ + -+ Schema.String.annotate({ + -+ description: + -+ "Optional cwd filter; when set, only threads whose session cwd exactly matches this path are returned.", + -+ }), + -+ Schema.Null, + -+ ]), + - ), + - limit: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- sortDirection: Schema.optionalKey( + -- Schema.Union([V2ThreadListParams__SortDirection, Schema.Null]).annotate({ + -- description: "Optional sort direction; defaults to descending (newest first).", + -- }), + -- ), + - sortKey: Schema.optionalKey( + - Schema.Union([V2ThreadListParams__ThreadSortKey, Schema.Null]).annotate({ + - description: "Optional sort key; defaults to created_at.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListParams = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- useStateDbOnly: Schema.optionalKey( + -- Schema.Boolean.annotate({ + -- description: + -- "If true, return from the state DB without scanning JSONL rollouts to repair thread metadata. Omitted or false preserves scan-and-repair behavior.", + -- }), + -- ), + - }).annotate({ title: "ThreadListParams" }); + - + - export type V2ThreadListResponse = { + -- readonly backwardsCursor?: string | null; + - readonly data: ReadonlyArray; + - readonly nextCursor?: string | null; + - }; + - export const V2ThreadListResponse = Schema.Struct({ + -- backwardsCursor: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Opaque cursor to pass as `cursor` when reversing `sortDirection`. This is only populated when the page contains at least one thread. Use it with the opposite `sortDirection`; for timestamp sorts it anchors at the start of the page timestamp so same-second updates are not skipped.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - data: Schema.Array(V2ThreadListResponse__Thread), + - nextCursor: Schema.optionalKey( + - Schema.Union([ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadListResponse__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ThreadListResponse__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + --export type V2ThreadListResponse__CollabAgentToolCallStatus = + -- | "inProgress" + -- | "completed" + -- | "failed" + -- | "interrupted"; + -+export type V2ThreadListResponse__CollabAgentToolCallStatus = "inProgress" | "completed" | "failed"; + - export const V2ThreadListResponse__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ThreadListResponse__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__SessionSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadListResponse__ThreadExtra = {}; + --export const V2ThreadListResponse__ThreadExtra = Schema.Struct({}).annotate({ + -- description: "Extra app-server data for a thread.", + --}); + -- + --export type V2ThreadListResponse__ThreadHistoryMode = "legacy" | "paginated"; + --export const V2ThreadListResponse__ThreadHistoryMode = Schema.Literals(["legacy", "paginated"]); + -- + - export type V2ThreadListResponse__ThreadStatus = + - | { readonly type: "notLoaded" } + - | { readonly type: "idle" } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadListResponse__ThreadStatus = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadListResponse__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2ThreadListResponse__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + - export type V2ThreadLoadedListParams = { + - readonly cursor?: string | null; + - readonly limit?: number | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadMetadataUpdateResponse__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ThreadMetadataUpdateResponse__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + - export type V2ThreadMetadataUpdateResponse__CollabAgentToolCallStatus = + - | "inProgress" + - | "completed" + -- | "failed" + -- | "interrupted"; + -+ | "failed"; + - export const V2ThreadMetadataUpdateResponse__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ThreadMetadataUpdateResponse__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__SessionSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadMetadataUpdateResponse__ThreadExtra = {}; + --export const V2ThreadMetadataUpdateResponse__ThreadExtra = Schema.Struct({}).annotate({ + -- description: "Extra app-server data for a thread.", + --}); + -- + --export type V2ThreadMetadataUpdateResponse__ThreadHistoryMode = "legacy" | "paginated"; + --export const V2ThreadMetadataUpdateResponse__ThreadHistoryMode = Schema.Literals([ + -- "legacy", + -- "paginated", + --]); + -- + - export type V2ThreadMetadataUpdateResponse__ThreadStatus = + - | { readonly type: "notLoaded" } + - | { readonly type: "idle" } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadMetadataUpdateResponse__ThreadStatus = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadMetadataUpdateResponse__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2ThreadMetadataUpdateResponse__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + - export type V2ThreadNameUpdatedNotification = { + - readonly threadId: string; + - readonly threadName?: string | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadParams = Schema.Struct({ + - includeTurns: Schema.optionalKey( + - Schema.Boolean.annotate({ + - description: "When true, include turns and their items from rollout history.", + -+ default: false, + - }), + - ), + - threadId: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadReadResponse__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ThreadReadResponse__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + --export type V2ThreadReadResponse__CollabAgentToolCallStatus = + -- | "inProgress" + -- | "completed" + -- | "failed" + -- | "interrupted"; + -+export type V2ThreadReadResponse__CollabAgentToolCallStatus = "inProgress" | "completed" | "failed"; + - export const V2ThreadReadResponse__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ThreadReadResponse__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__SessionSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadReadResponse__ThreadExtra = {}; + --export const V2ThreadReadResponse__ThreadExtra = Schema.Struct({}).annotate({ + -- description: "Extra app-server data for a thread.", + --}); + -- + --export type V2ThreadReadResponse__ThreadHistoryMode = "legacy" | "paginated"; + --export const V2ThreadReadResponse__ThreadHistoryMode = Schema.Literals(["legacy", "paginated"]); + -- + - export type V2ThreadReadResponse__ThreadStatus = + - | { readonly type: "notLoaded" } + - | { readonly type: "idle" } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadReadResponse__ThreadStatus = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadReadResponse__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2ThreadReadResponse__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + - export type V2ThreadRealtimeClosedNotification = { + - readonly reason?: string | null; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRealtimeSdpNotification = Schema.Struct({ + - }); + - + - export type V2ThreadRealtimeStartedNotification = { + -- readonly realtimeSessionId?: string | null; + -+ readonly sessionId?: string | null; + - readonly threadId: string; + - readonly version: V2ThreadRealtimeStartedNotification__RealtimeConversationVersion; + - }; + - export const V2ThreadRealtimeStartedNotification = Schema.Struct({ + -- realtimeSessionId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ sessionId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - threadId: Schema.String, + - version: V2ThreadRealtimeStartedNotification__RealtimeConversationVersion, + - }).annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRealtimeStartedNotification = Schema.Struct({ + - description: "EXPERIMENTAL - emitted when thread realtime startup is accepted.", + - }); + - + --export type V2ThreadRealtimeTranscriptDeltaNotification = { + -- readonly delta: string; + -- readonly role: string; + -- readonly threadId: string; + --}; + --export const V2ThreadRealtimeTranscriptDeltaNotification = Schema.Struct({ + -- delta: Schema.String.annotate({ description: "Live transcript delta from the realtime event." }), + -- role: Schema.String, + -- threadId: Schema.String, + --}).annotate({ + -- title: "ThreadRealtimeTranscriptDeltaNotification", + -- description: + -- "EXPERIMENTAL - flat transcript delta emitted whenever realtime transcript text changes.", + --}); + -- + --export type V2ThreadRealtimeTranscriptDoneNotification = { + -+export type V2ThreadRealtimeTranscriptUpdatedNotification = { + - readonly role: string; + - readonly text: string; + - readonly threadId: string; + - }; + --export const V2ThreadRealtimeTranscriptDoneNotification = Schema.Struct({ + -+export const V2ThreadRealtimeTranscriptUpdatedNotification = Schema.Struct({ + - role: Schema.String, + -- text: Schema.String.annotate({ description: "Final complete text for the transcript part." }), + -+ text: Schema.String, + - threadId: Schema.String, + - }).annotate({ + -- title: "ThreadRealtimeTranscriptDoneNotification", + -+ title: "ThreadRealtimeTranscriptUpdatedNotification", + - description: + -- "EXPERIMENTAL - final transcript text emitted when realtime completes a transcript part.", + -+ "EXPERIMENTAL - flat transcript delta emitted whenever realtime transcript text changes.", + - }); + - + - export type V2ThreadResumeParams = { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeParams = { + - readonly modelProvider?: string | null; + - readonly personality?: V2ThreadResumeParams__Personality | null; + - readonly sandbox?: V2ThreadResumeParams__SandboxMode | null; + -- readonly serviceTier?: string | null; + -+ readonly serviceTier?: V2ThreadResumeParams__ServiceTier | null | null; + - readonly threadId: string; + - }; + - export const V2ThreadResumeParams = Schema.Struct({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams = Schema.Struct({ + - modelProvider: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - personality: Schema.optionalKey(Schema.Union([V2ThreadResumeParams__Personality, Schema.Null])), + - sandbox: Schema.optionalKey(Schema.Union([V2ThreadResumeParams__SandboxMode, Schema.Null])), + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ serviceTier: Schema.optionalKey( + -+ Schema.Union([Schema.Union([V2ThreadResumeParams__ServiceTier, Schema.Null]), Schema.Null]), + -+ ), + - threadId: Schema.String, + - }).annotate({ + - title: "ThreadResumeParams", + - description: + -- "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nFor non-running threads, the precedence is: history > non-empty path > thread_id. If using history or a non-empty path for a non-running thread, the thread_id param will be ignored.\n\nIf thread_id identifies a running thread, app-server rejoins that thread and treats a non-empty path as a consistency check against the active rollout path. Empty string path values are treated as absent.\n\nPrefer using thread_id whenever possible.", + --}); + -- + --export type V2ThreadResumeParams__AbsolutePathBuf = string; + --export const V2ThreadResumeParams__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -+ "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.", + - }); + - + - export type V2ThreadResumeParams__ResponseItem = + - | { + - readonly content: ReadonlyArray; + -+ readonly end_turn?: boolean | null; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + - readonly phase?: V2ThreadResumeParams__MessagePhase | null; + - readonly role: string; + - readonly type: "message"; + - } + -- | { + -- readonly author: string; + -- readonly content: ReadonlyArray; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + -- readonly recipient: string; + -- readonly type: "agent_message"; + -- } + - | { + - readonly content?: ReadonlyArray | null; + - readonly encrypted_content?: string | null; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + - readonly summary: ReadonlyArray; + - readonly type: "reasoning"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeParams__ResponseItem = + - readonly action: V2ThreadResumeParams__LocalShellAction; + - readonly call_id?: string | null; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + - readonly status: V2ThreadResumeParams__LocalShellStatus; + - readonly type: "local_shell_call"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeParams__ResponseItem = + - readonly arguments: string; + - readonly call_id: string; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + - readonly name: string; + - readonly namespace?: string | null; + - readonly type: "function_call"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeParams__ResponseItem = + - readonly call_id?: string | null; + - readonly execution: string; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + - readonly status?: string | null; + - readonly type: "tool_search_call"; + - } + - | { + - readonly call_id: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + - readonly output: V2ThreadResumeParams__FunctionCallOutputBody; + - readonly type: "function_call_output"; + - } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeParams__ResponseItem = + - readonly call_id: string; + - readonly id?: string | null; + - readonly input: string; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + - readonly name: string; + -- readonly namespace?: string | null; + - readonly status?: string | null; + - readonly type: "custom_tool_call"; + - } + - | { + - readonly call_id: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + - readonly name?: string | null; + - readonly output: V2ThreadResumeParams__FunctionCallOutputBody; + - readonly type: "custom_tool_call_output"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeParams__ResponseItem = + - | { + - readonly call_id?: string | null; + - readonly execution: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + - readonly status: string; + - readonly tools: ReadonlyArray; + - readonly type: "tool_search_output"; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeParams__ResponseItem = + - | { + - readonly action?: V2ThreadResumeParams__ResponsesApiWebSearchAction | null; + - readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + - readonly status?: string | null; + - readonly type: "web_search_call"; + - } + - | { + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + -+ readonly id: string; + - readonly result: string; + - readonly revised_prompt?: string | null; + - readonly status: string; + - readonly type: "image_generation_call"; + - } + -- | { + -- readonly encrypted_content: string; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + -- readonly type: "compaction"; + -- } + -- | { readonly type: "compaction_trigger" } + -- | { + -- readonly encrypted_content?: string | null; + -- readonly id?: string | null; + -- readonly internal_chat_message_metadata_passthrough?: V2ThreadResumeParams__InternalChatMessageMetadataPassthrough | null; + -- readonly type: "context_compaction"; + -- } + -+ | { readonly ghost_commit: V2ThreadResumeParams__GhostCommit; readonly type: "ghost_snapshot" } + -+ | { readonly encrypted_content: string; readonly type: "compaction" } + - | { readonly type: "other" }; + - export const V2ThreadResumeParams__ResponseItem = Schema.Union( + - [ + - Schema.Struct({ + - content: Schema.Array(V2ThreadResumeParams__ContentItem), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -+ end_turn: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - phase: Schema.optionalKey(Schema.Union([V2ThreadResumeParams__MessagePhase, Schema.Null])), + - role: Schema.String, + - type: Schema.Literal("message").annotate({ title: "MessageResponseItemType" }), + - }).annotate({ title: "MessageResponseItem" }), + -- Schema.Struct({ + -- author: Schema.String, + -- content: Schema.Array(V2ThreadResumeParams__AgentMessageInputContent), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + -- recipient: Schema.String, + -- type: Schema.Literal("agent_message").annotate({ title: "AgentMessageResponseItemType" }), + -- }).annotate({ title: "AgentMessageResponseItem" }), + - Schema.Struct({ + - content: Schema.optionalKey( + - Schema.Union([Schema.Array(V2ThreadResumeParams__ReasoningItemContent), Schema.Null]), + - ), + - encrypted_content: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - summary: Schema.Array(V2ThreadResumeParams__ReasoningItemReasoningSummary), + - type: Schema.Literal("reasoning").annotate({ title: "ReasoningResponseItemType" }), + - }).annotate({ title: "ReasoningResponseItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__ResponseItem = Schema.Union( + - Schema.Union([ + - Schema.String.annotate({ + - description: "Legacy id field retained for compatibility with older payloads.", + -+ writeOnly: true, + - }), + - Schema.Null, + - ]), + - ), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - status: V2ThreadResumeParams__LocalShellStatus, + - type: Schema.Literal("local_shell_call").annotate({ + - title: "LocalShellCallResponseItemType", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__ResponseItem = Schema.Union( + - Schema.Struct({ + - arguments: Schema.String, + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - name: Schema.String, + - namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__ResponseItem = Schema.Union( + - arguments: Schema.Unknown, + - call_id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - execution: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - status: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - type: Schema.Literal("tool_search_call").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__ResponseItem = Schema.Union( + - }).annotate({ title: "ToolSearchCallResponseItem" }), + - Schema.Struct({ + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - output: V2ThreadResumeParams__FunctionCallOutputBody, + - type: Schema.Literal("function_call_output").annotate({ + - title: "FunctionCallOutputResponseItemType", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__ResponseItem = Schema.Union( + - }).annotate({ title: "FunctionCallOutputResponseItem" }), + - Schema.Struct({ + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- input: Schema.String, + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + -+ input: Schema.String, + - name: Schema.String, + -- namespace: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - type: Schema.Literal("custom_tool_call").annotate({ + - title: "CustomToolCallResponseItemType", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__ResponseItem = Schema.Union( + - }).annotate({ title: "CustomToolCallResponseItem" }), + - Schema.Struct({ + - call_id: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - name: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - output: V2ThreadResumeParams__FunctionCallOutputBody, + - type: Schema.Literal("custom_tool_call_output").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__ResponseItem = Schema.Union( + - Schema.Struct({ + - call_id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - execution: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - status: Schema.String, + - tools: Schema.Array(Schema.Unknown), + - type: Schema.Literal("tool_search_output").annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__ResponseItem = Schema.Union( + - action: Schema.optionalKey( + - Schema.Union([V2ThreadResumeParams__ResponsesApiWebSearchAction, Schema.Null]), + - ), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -+ id: Schema.optionalKey( + -+ Schema.Union([Schema.String.annotate({ writeOnly: true }), Schema.Null]), + - ), + - status: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - type: Schema.Literal("web_search_call").annotate({ title: "WebSearchCallResponseItemType" }), + - }).annotate({ title: "WebSearchCallResponseItem" }), + - Schema.Struct({ + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + -+ id: Schema.String, + - result: Schema.String, + - revised_prompt: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - status: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__ResponseItem = Schema.Union( + - title: "ImageGenerationCallResponseItemType", + - }), + - }).annotate({ title: "ImageGenerationCallResponseItem" }), + -+ Schema.Struct({ + -+ ghost_commit: V2ThreadResumeParams__GhostCommit, + -+ type: Schema.Literal("ghost_snapshot").annotate({ title: "GhostSnapshotResponseItemType" }), + -+ }).annotate({ title: "GhostSnapshotResponseItem" }), + - Schema.Struct({ + - encrypted_content: Schema.String, + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + - type: Schema.Literal("compaction").annotate({ title: "CompactionResponseItemType" }), + - }).annotate({ title: "CompactionResponseItem" }), + -- Schema.Struct({ + -- type: Schema.Literal("compaction_trigger").annotate({ + -- title: "CompactionTriggerResponseItemType", + -- }), + -- }).annotate({ title: "CompactionTriggerResponseItem" }), + -- Schema.Struct({ + -- encrypted_content: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- id: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- internal_chat_message_metadata_passthrough: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__InternalChatMessageMetadataPassthrough, Schema.Null]), + -- ), + -- type: Schema.Literal("context_compaction").annotate({ + -- title: "ContextCompactionResponseItemType", + -- }), + -- }).annotate({ title: "ContextCompactionResponseItem" }), + - Schema.Struct({ + - type: Schema.Literal("other").annotate({ title: "OtherResponseItemType" }), + - }).annotate({ title: "OtherResponseItem" }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeParams__ResponseItem = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadResumeParams__ThreadResumeInitialTurnsPageParams = { + -- readonly itemsView?: V2ThreadResumeParams__TurnItemsView | null; + -- readonly limit?: number | null; + -- readonly sortDirection?: V2ThreadResumeParams__SortDirection | null; + --}; + --export const V2ThreadResumeParams__ThreadResumeInitialTurnsPageParams = Schema.Struct({ + -- itemsView: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__TurnItemsView, Schema.Null]).annotate({ + -- description: "How much item detail to include for each returned turn; defaults to summary.", + -- }), + -- ), + -- limit: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ description: "Optional turn page size.", format: "uint32" }) + -- .check(Schema.isInt()) + -- .check(Schema.isGreaterThanOrEqualTo(0)), + -- Schema.Null, + -- ]), + -- ), + -- sortDirection: Schema.optionalKey( + -- Schema.Union([V2ThreadResumeParams__SortDirection, Schema.Null]).annotate({ + -- description: "Optional turn pagination direction; defaults to descending.", + -- }), + -- ), + --}); + -- + - export type V2ThreadResumeResponse = { + - readonly approvalPolicy: V2ThreadResumeResponse__AskForApproval; + -- readonly approvalsReviewer: "user" | "auto_review" | "guardian_subagent"; + -- readonly cwd: V2ThreadResumeResponse__AbsolutePathBuf; + -- readonly instructionSources?: ReadonlyArray; + -+ readonly approvalsReviewer: "user" | "guardian_subagent"; + -+ readonly cwd: string; + - readonly model: string; + - readonly modelProvider: string; + - readonly reasoningEffort?: V2ThreadResumeResponse__ReasoningEffort | null; + -- readonly sandbox: + -- | { readonly type: "dangerFullAccess" } + -- | { readonly networkAccess?: boolean; readonly type: "readOnly" } + -- | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + -- | { + -- readonly excludeSlashTmp?: boolean; + -- readonly excludeTmpdirEnvVar?: boolean; + -- readonly networkAccess?: boolean; + -- readonly type: "workspaceWrite"; + -- readonly writableRoots?: ReadonlyArray; + -- }; + -- readonly serviceTier?: string | null; + -+ readonly sandbox: V2ThreadResumeResponse__SandboxPolicy; + -+ readonly serviceTier?: V2ThreadResumeResponse__ServiceTier | null; + - readonly thread: V2ThreadResumeResponse__Thread; + - }; + - export const V2ThreadResumeResponse = Schema.Struct({ + - approvalPolicy: V2ThreadResumeResponse__AskForApproval, + -- approvalsReviewer: Schema.Literals(["user", "auto_review", "guardian_subagent"]).annotate({ + -+ approvalsReviewer: Schema.Literals(["user", "guardian_subagent"]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }), + -- cwd: V2ThreadResumeResponse__AbsolutePathBuf, + -- instructionSources: Schema.optionalKey( + -- Schema.Array(V2ThreadResumeResponse__LegacyAppPathString).annotate({ + -- description: + -- "Environment-native paths to instruction source files currently loaded for this thread.", + -- default: [], + -- }), + -- ), + -+ cwd: Schema.String, + - model: Schema.String, + - modelProvider: Schema.String, + - reasoningEffort: Schema.optionalKey( + - Schema.Union([V2ThreadResumeResponse__ReasoningEffort, Schema.Null]), + - ), + -- sandbox: Schema.Union( + -- [ + -- Schema.Struct({ + -- type: Schema.Literal("dangerFullAccess").annotate({ + -- title: "DangerFullAccessSandboxPolicyType", + -- }), + -- }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + -- }).annotate({ title: "ReadOnlySandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey( + -- Schema.Literals(["restricted", "enabled"]).annotate({ default: "restricted" }), + -- ), + -- type: Schema.Literal("externalSandbox").annotate({ + -- title: "ExternalSandboxSandboxPolicyType", + -- }), + -- }).annotate({ title: "ExternalSandboxSandboxPolicy" }), + -- Schema.Struct({ + -- excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("workspaceWrite").annotate({ + -- title: "WorkspaceWriteSandboxPolicyType", + -- }), + -- writableRoots: Schema.optionalKey( + -- Schema.Array(V2ThreadResumeResponse__AbsolutePathBuf).annotate({ default: [] }), + -- ), + -- }).annotate({ title: "WorkspaceWriteSandboxPolicy" }), + -- ], + -- { mode: "oneOf" }, + -- ).annotate({ + -- description: + -- "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance.", + -- }), + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ sandbox: V2ThreadResumeResponse__SandboxPolicy, + -+ serviceTier: Schema.optionalKey(Schema.Union([V2ThreadResumeResponse__ServiceTier, Schema.Null])), + - thread: V2ThreadResumeResponse__Thread, + - }).annotate({ title: "ThreadResumeResponse" }); + - + --export type V2ThreadResumeResponse__ActivePermissionProfile = { + -- readonly extends?: string | null; + -- readonly id: string; + --}; + --export const V2ThreadResumeResponse__ActivePermissionProfile = Schema.Struct({ + -- extends: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Parent profile identifier from the selected permissions profile's `extends` setting, when present.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- id: Schema.String.annotate({ + -- description: + -- "Identifier from `default_permissions` or the implicit built-in default, such as `:workspace` or a user-defined `[permissions.]` profile.", + -- }), + --}); + -- + --export type V2ThreadResumeResponse__ApprovalsReviewer = + -- | "user" + -- | "auto_review" + -- | "guardian_subagent"; + -+export type V2ThreadResumeResponse__ApprovalsReviewer = "user" | "guardian_subagent"; + - export const V2ThreadResumeResponse__ApprovalsReviewer = Schema.Literals([ + - "user", + -- "auto_review", + - "guardian_subagent", + - ]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }); + - + - export type V2ThreadResumeResponse__ByteRange = { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadResumeResponse__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ThreadResumeResponse__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + - export type V2ThreadResumeResponse__CollabAgentToolCallStatus = + - | "inProgress" + - | "completed" + -- | "failed" + -- | "interrupted"; + -+ | "failed"; + - export const V2ThreadResumeResponse__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ThreadResumeResponse__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__CommandExecutionSource = Schema.Literals([ + - "unifiedExecInteraction", + - ]); + - + --export type V2ThreadResumeResponse__MultiAgentMode = + -- | "explicitRequestOnly" + -- | "proactive" + -- | { readonly custom: string }; + --export const V2ThreadResumeResponse__MultiAgentMode = Schema.Union( + -- [ + -- Schema.Literals(["explicitRequestOnly", "proactive"]), + -- Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomMultiAgentMode" }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ + -- description: + -- "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.", + --}); + -- + - export type V2ThreadResumeResponse__NetworkAccess = "restricted" | "enabled"; + - export const V2ThreadResumeResponse__NetworkAccess = Schema.Literals(["restricted", "enabled"]); + - + --export type V2ThreadResumeResponse__SandboxPolicy = + -- | { readonly type: "dangerFullAccess" } + -- | { readonly networkAccess?: boolean; readonly type: "readOnly" } + -- | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + -+export type V2ThreadResumeResponse__ReadOnlyAccess = + - | { + -- readonly excludeSlashTmp?: boolean; + -- readonly excludeTmpdirEnvVar?: boolean; + -- readonly networkAccess?: boolean; + -- readonly type: "workspaceWrite"; + -- readonly writableRoots?: ReadonlyArray; + -- }; + --export const V2ThreadResumeResponse__SandboxPolicy = Schema.Union( + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+export const V2ThreadResumeResponse__ReadOnlyAccess = Schema.Union( + - [ + - Schema.Struct({ + -- type: Schema.Literal("dangerFullAccess").annotate({ + -- title: "DangerFullAccessSandboxPolicyType", + -- }), + -- }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + -- }).annotate({ title: "ReadOnlySandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey( + -- Schema.Literals(["restricted", "enabled"]).annotate({ default: "restricted" }), + -- ), + -- type: Schema.Literal("externalSandbox").annotate({ + -- title: "ExternalSandboxSandboxPolicyType", + -- }), + -- }).annotate({ title: "ExternalSandboxSandboxPolicy" }), + -- Schema.Struct({ + -- excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("workspaceWrite").annotate({ title: "WorkspaceWriteSandboxPolicyType" }), + -- writableRoots: Schema.optionalKey( + -+ includePlatformDefaults: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + -+ readableRoots: Schema.optionalKey( + - Schema.Array(V2ThreadResumeResponse__AbsolutePathBuf).annotate({ default: [] }), + - ), + -- }).annotate({ title: "WorkspaceWriteSandboxPolicy" }), + -+ type: Schema.Literal("restricted").annotate({ title: "RestrictedReadOnlyAccessType" }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ title: "FullAccessReadOnlyAccessType" }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__SessionSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadResumeResponse__ThreadExtra = {}; + --export const V2ThreadResumeResponse__ThreadExtra = Schema.Struct({}).annotate({ + -- description: "Extra app-server data for a thread.", + --}); + -- + --export type V2ThreadResumeResponse__ThreadHistoryMode = "legacy" | "paginated"; + --export const V2ThreadResumeResponse__ThreadHistoryMode = Schema.Literals(["legacy", "paginated"]); + -- + - export type V2ThreadResumeResponse__ThreadStatus = + - | { readonly type: "notLoaded" } + - | { readonly type: "idle" } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadResumeResponse__ThreadStatus = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadResumeResponse__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2ThreadResumeResponse__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + --export type V2ThreadResumeResponse__TurnsPage = { + -- readonly backwardsCursor?: string | null; + -- readonly data: ReadonlyArray; + -- readonly nextCursor?: string | null; + --}; + --export const V2ThreadResumeResponse__TurnsPage = Schema.Struct({ + -- backwardsCursor: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- data: Schema.Array(V2ThreadResumeResponse__Turn), + -- nextCursor: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + --}); + -- + - export type V2ThreadRollbackParams = { readonly numTurns: number; readonly threadId: string }; + - export const V2ThreadRollbackParams = Schema.Struct({ + - numTurns: Schema.Number.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackParams = Schema.Struct({ + - .check(Schema.isInt()) + - .check(Schema.isGreaterThanOrEqualTo(0)), + - threadId: Schema.String, + --}).annotate({ + -- title: "ThreadRollbackParams", + -- description: "DEPRECATED: `thread/rollback` will be removed soon.", + --}); + -+}).annotate({ title: "ThreadRollbackParams" }); + - + - export type V2ThreadRollbackResponse = { + - readonly thread: { + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadRollbackResponse = { + - readonly id: string; + - readonly modelProvider: string; + - readonly name?: string | null; + -- readonly parentThreadId?: string | null; + - readonly path?: string | null; + - readonly preview: string; + -- readonly recencyAt?: number | null; + -- readonly sessionId: string; + - readonly source: + - | "cli" + - | "vscode" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadRollbackResponse = { + - readonly activeFlags: ReadonlyArray; + - readonly type: "active"; + - }; + -- readonly threadSource?: V2ThreadRollbackResponse__ThreadSource | null; + - readonly turns: ReadonlyArray; + - readonly updatedAt: number; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse = Schema.Struct({ + - description: "Unix timestamp (in seconds) when the thread was created.", + - format: "int64", + - }).check(Schema.isInt()), + -- cwd: Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }), + -+ cwd: Schema.String.annotate({ description: "Working directory captured for the thread." }), + - ephemeral: Schema.Boolean.annotate({ + - description: "Whether the thread is ephemeral and should not be materialized on disk.", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse = Schema.Struct({ + - description: "Optional Git metadata captured when the thread was created.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this thread. Codex-generated thread IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - modelProvider: Schema.String.annotate({ + - description: "Model provider used for this thread (for example, 'openai').", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- parentThreadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "The ID of the parent thread. This will only be set if this thread is a subagent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - path: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse = Schema.Struct({ + - preview: Schema.String.annotate({ + - description: "Usually the first user message in the thread, if available.", + - }), + -- recencyAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) used for thread recency ordering.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- sessionId: Schema.String.annotate({ + -- description: "Session id shared by threads that belong to the same session tree.", + -- }), + - source: Schema.Union( + - [ + - Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse = Schema.Struct({ + - ], + - { mode: "oneOf" }, + - ).annotate({ description: "Current runtime status for the thread." }), + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadRollbackResponse__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional analytics source classification for this thread.", + -- }), + -- ), + - turns: Schema.Array(V2ThreadRollbackResponse__Turn).annotate({ + - description: + - "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadRollbackResponse__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ThreadRollbackResponse__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + - export type V2ThreadRollbackResponse__CollabAgentToolCallStatus = + - | "inProgress" + - | "completed" + -- | "failed" + -- | "interrupted"; + -+ | "failed"; + - export const V2ThreadRollbackResponse__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ThreadRollbackResponse__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadRollbackResponse__Thread = { + - readonly id: string; + - readonly modelProvider: string; + - readonly name?: string | null; + -- readonly parentThreadId?: string | null; + - readonly path?: string | null; + - readonly preview: string; + -- readonly recencyAt?: number | null; + -- readonly sessionId: string; + - readonly source: + - | "cli" + - | "vscode" + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadRollbackResponse__Thread = { + - readonly activeFlags: ReadonlyArray; + - readonly type: "active"; + - }; + -- readonly threadSource?: V2ThreadRollbackResponse__ThreadSource | null; + - readonly turns: ReadonlyArray; + - readonly updatedAt: number; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__Thread = Schema.Struct({ + - description: "Unix timestamp (in seconds) when the thread was created.", + - format: "int64", + - }).check(Schema.isInt()), + -- cwd: Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + -- }), + -+ cwd: Schema.String.annotate({ description: "Working directory captured for the thread." }), + - ephemeral: Schema.Boolean.annotate({ + - description: "Whether the thread is ephemeral and should not be materialized on disk.", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__Thread = Schema.Struct({ + - description: "Optional Git metadata captured when the thread was created.", + - }), + - ), + -- id: Schema.String.annotate({ + -- description: "Identifier for this thread. Codex-generated thread IDs are UUIDv7.", + -- }), + -+ id: Schema.String, + - modelProvider: Schema.String.annotate({ + - description: "Model provider used for this thread (for example, 'openai').", + - }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__Thread = Schema.Struct({ + - Schema.Null, + - ]), + - ), + -- parentThreadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "The ID of the parent thread. This will only be set if this thread is a subagent.", + -- }), + -- Schema.Null, + -- ]), + -- ), + - path: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ description: "[UNSTABLE] Path to the thread on disk." }), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__Thread = Schema.Struct({ + - preview: Schema.String.annotate({ + - description: "Usually the first user message in the thread, if available.", + - }), + -- recencyAt: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Number.annotate({ + -- description: "Unix timestamp (in seconds) used for thread recency ordering.", + -- format: "int64", + -- }).check(Schema.isInt()), + -- Schema.Null, + -- ]), + -- ), + -- sessionId: Schema.String.annotate({ + -- description: "Session id shared by threads that belong to the same session tree.", + -- }), + - source: Schema.Union( + - [ + - Schema.Literals(["cli", "vscode", "exec", "appServer", "unknown"]), + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__Thread = Schema.Struct({ + - ], + - { mode: "oneOf" }, + - ).annotate({ description: "Current runtime status for the thread." }), + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadRollbackResponse__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional analytics source classification for this thread.", + -- }), + -- ), + - turns: Schema.Array(V2ThreadRollbackResponse__Turn).annotate({ + - description: + - "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__Thread = Schema.Struct({ + - }).check(Schema.isInt()), + - }); + - + --export type V2ThreadRollbackResponse__ThreadExtra = {}; + --export const V2ThreadRollbackResponse__ThreadExtra = Schema.Struct({}).annotate({ + -- description: "Extra app-server data for a thread.", + --}); + -- + --export type V2ThreadRollbackResponse__ThreadHistoryMode = "legacy" | "paginated"; + --export const V2ThreadRollbackResponse__ThreadHistoryMode = Schema.Literals(["legacy", "paginated"]); + -- + - export type V2ThreadRollbackResponse__ThreadStatus = + - | { readonly type: "notLoaded" } + - | { readonly type: "idle" } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadRollbackResponse__ThreadStatus = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadRollbackResponse__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2ThreadRollbackResponse__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + - export type V2ThreadSetNameParams = { readonly name: string; readonly threadId: string }; + - export const V2ThreadSetNameParams = Schema.Struct({ + - name: Schema.String, + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadSetNameResponse = Schema.Struct({}).annotate({ + - title: "ThreadSetNameResponse", + - }); + - + --export type V2ThreadSettingsUpdatedNotification = { + -- readonly threadId: string; + -- readonly threadSettings: V2ThreadSettingsUpdatedNotification__ThreadSettings; + --}; + --export const V2ThreadSettingsUpdatedNotification = Schema.Struct({ + -- threadId: Schema.String, + -- threadSettings: V2ThreadSettingsUpdatedNotification__ThreadSettings, + --}).annotate({ title: "ThreadSettingsUpdatedNotification" }); + -- + --export type V2ThreadSettingsUpdatedNotification__MultiAgentMode = + -- | "explicitRequestOnly" + -- | "proactive" + -- | { readonly custom: string }; + --export const V2ThreadSettingsUpdatedNotification__MultiAgentMode = Schema.Union( + -- [ + -- Schema.Literals(["explicitRequestOnly", "proactive"]), + -- Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomMultiAgentMode" }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ + -- description: + -- "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.", + --}); + -- + --export type V2ThreadSettingsUpdatedNotification__NetworkAccess = "restricted" | "enabled"; + --export const V2ThreadSettingsUpdatedNotification__NetworkAccess = Schema.Literals([ + -- "restricted", + -- "enabled", + --]); + -- + - export type V2ThreadShellCommandParams = { readonly command: string; readonly threadId: string }; + - export const V2ThreadShellCommandParams = Schema.Struct({ + - command: Schema.String.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartedNotification__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ThreadStartedNotification__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + - export type V2ThreadStartedNotification__CollabAgentToolCallStatus = + - | "inProgress" + - | "completed" + -- | "failed" + -- | "interrupted"; + -+ | "failed"; + - export const V2ThreadStartedNotification__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ThreadStartedNotification__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__SessionSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadStartedNotification__ThreadExtra = {}; + --export const V2ThreadStartedNotification__ThreadExtra = Schema.Struct({}).annotate({ + -- description: "Extra app-server data for a thread.", + --}); + -- + --export type V2ThreadStartedNotification__ThreadHistoryMode = "legacy" | "paginated"; + --export const V2ThreadStartedNotification__ThreadHistoryMode = Schema.Literals([ + -- "legacy", + -- "paginated", + --]); + -- + - export type V2ThreadStartedNotification__ThreadStatus = + - | { readonly type: "notLoaded" } + - | { readonly type: "idle" } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartedNotification__ThreadStatus = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadStartedNotification__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2ThreadStartedNotification__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + - export type V2ThreadStartParams = { + - readonly approvalPolicy?: V2ThreadStartParams__AskForApproval | null; + - readonly approvalsReviewer?: V2ThreadStartParams__ApprovalsReviewer | null; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartParams = { + - readonly personality?: V2ThreadStartParams__Personality | null; + - readonly sandbox?: V2ThreadStartParams__SandboxMode | null; + - readonly serviceName?: string | null; + -- readonly serviceTier?: string | null; + -+ readonly serviceTier?: V2ThreadStartParams__ServiceTier | null | null; + - readonly sessionStartSource?: V2ThreadStartParams__ThreadStartSource | null; + -- readonly threadSource?: V2ThreadStartParams__ThreadSource | null; + - }; + - export const V2ThreadStartParams = Schema.Struct({ + - approvalPolicy: Schema.optionalKey( + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartParams = Schema.Struct({ + - personality: Schema.optionalKey(Schema.Union([V2ThreadStartParams__Personality, Schema.Null])), + - sandbox: Schema.optionalKey(Schema.Union([V2ThreadStartParams__SandboxMode, Schema.Null])), + - serviceName: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ serviceTier: Schema.optionalKey( + -+ Schema.Union([Schema.Union([V2ThreadStartParams__ServiceTier, Schema.Null]), Schema.Null]), + -+ ), + - sessionStartSource: Schema.optionalKey( + - Schema.Union([V2ThreadStartParams__ThreadStartSource, Schema.Null]), + - ), + -- threadSource: Schema.optionalKey( + -- Schema.Union([V2ThreadStartParams__ThreadSource, Schema.Null]).annotate({ + -- description: "Optional client-supplied analytics source classification for this thread.", + -- }), + -- ), + - }).annotate({ title: "ThreadStartParams" }); + - + --export type V2ThreadStartParams__AbsolutePathBuf = string; + --export const V2ThreadStartParams__AbsolutePathBuf = Schema.String.annotate({ + -- description: + -- "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.", + --}); + -- + --export type V2ThreadStartParams__CapabilityRootLocation = { + -- readonly environmentId: string; + -- readonly path: string; + -- readonly type: "environment"; + --}; + --export const V2ThreadStartParams__CapabilityRootLocation = Schema.Union( + -- [ + -- Schema.Struct({ + -- environmentId: Schema.String, + -- path: Schema.String.annotate({ + -- description: "Absolute path for the root in the selected environment.", + -- }), + -- type: Schema.Literal("environment").annotate({ + -- title: "EnvironmentCapabilityRootLocationType", + -- }), + -- }).annotate({ + -- title: "EnvironmentCapabilityRootLocation", + -- description: "A path owned by an execution environment.", + -- }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ description: "Location used to resolve a selected capability root." }); + -- + --export type V2ThreadStartParams__DynamicToolSpec = + -- | { + -- readonly deferLoading?: boolean; + -- readonly description: string; + -- readonly inputSchema: unknown; + -- readonly name: string; + -- readonly type: "function"; + -- } + -- | { + -- readonly description: string; + -- readonly name: string; + -- readonly tools: ReadonlyArray; + -- readonly type: "namespace"; + -- }; + --export const V2ThreadStartParams__DynamicToolSpec = Schema.Union( + -- [ + -- Schema.Struct({ + -- deferLoading: Schema.optionalKey(Schema.Boolean), + -- description: Schema.String, + -- inputSchema: Schema.Unknown, + -- name: Schema.String, + -- type: Schema.Literal("function").annotate({ title: "FunctionDynamicToolSpecType" }), + -- }).annotate({ title: "FunctionDynamicToolSpec" }), + -- Schema.Struct({ + -- description: Schema.String, + -- name: Schema.String, + -- tools: Schema.Array(V2ThreadStartParams__DynamicToolNamespaceTool), + -- type: Schema.Literal("namespace").annotate({ title: "NamespaceDynamicToolSpecType" }), + -- }).annotate({ title: "NamespaceDynamicToolSpec" }), + -- ], + -- { mode: "oneOf" }, + --); + -- + --export type V2ThreadStartParams__MultiAgentMode = + -- | "explicitRequestOnly" + -- | "proactive" + -- | { readonly custom: string }; + --export const V2ThreadStartParams__MultiAgentMode = Schema.Union( + -- [ + -- Schema.Literals(["explicitRequestOnly", "proactive"]), + -- Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomMultiAgentMode" }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ + -- description: + -- "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.", + --}); + -- + --export type V2ThreadStartParams__SelectedCapabilityRoot = { + -- readonly id: string; + -- readonly location: { + -- readonly environmentId: string; + -- readonly path: string; + -- readonly type: "environment"; + -- }; + --}; + --export const V2ThreadStartParams__SelectedCapabilityRoot = Schema.Struct({ + -- id: Schema.String.annotate({ + -- description: "Stable identifier supplied by the capability selection platform.", + -- }), + -- location: Schema.Union( + -- [ + -- Schema.Struct({ + -- environmentId: Schema.String, + -- path: Schema.String.annotate({ + -- description: "Absolute path for the root in the selected environment.", + -- }), + -- type: Schema.Literal("environment").annotate({ + -- title: "EnvironmentCapabilityRootLocationType", + -- }), + -- }).annotate({ + -- title: "EnvironmentCapabilityRootLocation", + -- description: "A path owned by an execution environment.", + -- }), + -- ], + -- { mode: "oneOf" }, + -- ).annotate({ description: "Location used to resolve a selected capability root." }), + --}).annotate({ + -- description: "A user-selected root that can expose one or more runtime capabilities.", + --}); + -- + --export type V2ThreadStartParams__ThreadHistoryMode = "legacy" | "paginated"; + --export const V2ThreadStartParams__ThreadHistoryMode = Schema.Literals(["legacy", "paginated"]); + -- + --export type V2ThreadStartParams__TurnEnvironmentParams = { + -- readonly cwd: V2ThreadStartParams__LegacyAppPathString; + -- readonly environmentId: string; + -- readonly runtimeWorkspaceRoots?: ReadonlyArray | null; + -+export type V2ThreadStartParams__DynamicToolSpec = { + -+ readonly deferLoading?: boolean; + -+ readonly description: string; + -+ readonly inputSchema: unknown; + -+ readonly name: string; + - }; + --export const V2ThreadStartParams__TurnEnvironmentParams = Schema.Struct({ + -- cwd: V2ThreadStartParams__LegacyAppPathString, + -- environmentId: Schema.String, + -- runtimeWorkspaceRoots: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(V2ThreadStartParams__LegacyAppPathString).annotate({ + -- description: "Environment-native runtime workspace roots. Omitted defaults to `cwd`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -+export const V2ThreadStartParams__DynamicToolSpec = Schema.Struct({ + -+ deferLoading: Schema.optionalKey(Schema.Boolean), + -+ description: Schema.String, + -+ inputSchema: Schema.Unknown, + -+ name: Schema.String, + - }); + - + - export type V2ThreadStartResponse = { + - readonly approvalPolicy: V2ThreadStartResponse__AskForApproval; + -- readonly approvalsReviewer: "user" | "auto_review" | "guardian_subagent"; + -- readonly cwd: V2ThreadStartResponse__AbsolutePathBuf; + -- readonly instructionSources?: ReadonlyArray; + -+ readonly approvalsReviewer: "user" | "guardian_subagent"; + -+ readonly cwd: string; + - readonly model: string; + - readonly modelProvider: string; + - readonly reasoningEffort?: V2ThreadStartResponse__ReasoningEffort | null; + -- readonly sandbox: + -- | { readonly type: "dangerFullAccess" } + -- | { readonly networkAccess?: boolean; readonly type: "readOnly" } + -- | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + -- | { + -- readonly excludeSlashTmp?: boolean; + -- readonly excludeTmpdirEnvVar?: boolean; + -- readonly networkAccess?: boolean; + -- readonly type: "workspaceWrite"; + -- readonly writableRoots?: ReadonlyArray; + -- }; + -- readonly serviceTier?: string | null; + -+ readonly sandbox: V2ThreadStartResponse__SandboxPolicy; + -+ readonly serviceTier?: V2ThreadStartResponse__ServiceTier | null; + - readonly thread: V2ThreadStartResponse__Thread; + - }; + - export const V2ThreadStartResponse = Schema.Struct({ + - approvalPolicy: V2ThreadStartResponse__AskForApproval, + -- approvalsReviewer: Schema.Literals(["user", "auto_review", "guardian_subagent"]).annotate({ + -+ approvalsReviewer: Schema.Literals(["user", "guardian_subagent"]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }), + -- cwd: V2ThreadStartResponse__AbsolutePathBuf, + -- instructionSources: Schema.optionalKey( + -- Schema.Array(V2ThreadStartResponse__LegacyAppPathString).annotate({ + -- description: + -- "Environment-native paths to instruction source files currently loaded for this thread.", + -- default: [], + -- }), + -- ), + -+ cwd: Schema.String, + - model: Schema.String, + - modelProvider: Schema.String, + - reasoningEffort: Schema.optionalKey( + - Schema.Union([V2ThreadStartResponse__ReasoningEffort, Schema.Null]), + - ), + -- sandbox: Schema.Union( + -- [ + -- Schema.Struct({ + -- type: Schema.Literal("dangerFullAccess").annotate({ + -- title: "DangerFullAccessSandboxPolicyType", + -- }), + -- }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + -- }).annotate({ title: "ReadOnlySandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey( + -- Schema.Literals(["restricted", "enabled"]).annotate({ default: "restricted" }), + -- ), + -- type: Schema.Literal("externalSandbox").annotate({ + -- title: "ExternalSandboxSandboxPolicyType", + -- }), + -- }).annotate({ title: "ExternalSandboxSandboxPolicy" }), + -- Schema.Struct({ + -- excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("workspaceWrite").annotate({ + -- title: "WorkspaceWriteSandboxPolicyType", + -- }), + -- writableRoots: Schema.optionalKey( + -- Schema.Array(V2ThreadStartResponse__AbsolutePathBuf).annotate({ default: [] }), + -- ), + -- }).annotate({ title: "WorkspaceWriteSandboxPolicy" }), + -- ], + -- { mode: "oneOf" }, + -- ).annotate({ + -- description: + -- "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance.", + -- }), + -- serviceTier: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + -+ sandbox: V2ThreadStartResponse__SandboxPolicy, + -+ serviceTier: Schema.optionalKey(Schema.Union([V2ThreadStartResponse__ServiceTier, Schema.Null])), + - thread: V2ThreadStartResponse__Thread, + - }).annotate({ title: "ThreadStartResponse" }); + - + --export type V2ThreadStartResponse__ActivePermissionProfile = { + -- readonly extends?: string | null; + -- readonly id: string; + --}; + --export const V2ThreadStartResponse__ActivePermissionProfile = Schema.Struct({ + -- extends: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: + -- "Parent profile identifier from the selected permissions profile's `extends` setting, when present.", + -- }), + -- Schema.Null, + -- ]), + -- ), + -- id: Schema.String.annotate({ + -- description: + -- "Identifier from `default_permissions` or the implicit built-in default, such as `:workspace` or a user-defined `[permissions.]` profile.", + -- }), + --}); + -- + --export type V2ThreadStartResponse__ApprovalsReviewer = "user" | "auto_review" | "guardian_subagent"; + -+export type V2ThreadStartResponse__ApprovalsReviewer = "user" | "guardian_subagent"; + - export const V2ThreadStartResponse__ApprovalsReviewer = Schema.Literals([ + - "user", + -- "auto_review", + - "guardian_subagent", + - ]).annotate({ + - description: + -- "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + -+ "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + - }); + - + - export type V2ThreadStartResponse__ByteRange = { readonly end: number; readonly start: number }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadStartResponse__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ThreadStartResponse__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + - export type V2ThreadStartResponse__CollabAgentToolCallStatus = + - | "inProgress" + - | "completed" + -- | "failed" + -- | "interrupted"; + -+ | "failed"; + - export const V2ThreadStartResponse__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ThreadStartResponse__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__CommandExecutionSource = Schema.Literals([ + - "unifiedExecInteraction", + - ]); + - + --export type V2ThreadStartResponse__MultiAgentMode = + -- | "explicitRequestOnly" + -- | "proactive" + -- | { readonly custom: string }; + --export const V2ThreadStartResponse__MultiAgentMode = Schema.Union( + -- [ + -- Schema.Literals(["explicitRequestOnly", "proactive"]), + -- Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomMultiAgentMode" }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ + -- description: + -- "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.", + --}); + -- + - export type V2ThreadStartResponse__NetworkAccess = "restricted" | "enabled"; + - export const V2ThreadStartResponse__NetworkAccess = Schema.Literals(["restricted", "enabled"]); + - + --export type V2ThreadStartResponse__SandboxPolicy = + -- | { readonly type: "dangerFullAccess" } + -- | { readonly networkAccess?: boolean; readonly type: "readOnly" } + -- | { readonly networkAccess?: "restricted" | "enabled"; readonly type: "externalSandbox" } + -+export type V2ThreadStartResponse__ReadOnlyAccess = + - | { + -- readonly excludeSlashTmp?: boolean; + -- readonly excludeTmpdirEnvVar?: boolean; + -- readonly networkAccess?: boolean; + -- readonly type: "workspaceWrite"; + -- readonly writableRoots?: ReadonlyArray; + -- }; + --export const V2ThreadStartResponse__SandboxPolicy = Schema.Union( + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+export const V2ThreadStartResponse__ReadOnlyAccess = Schema.Union( + - [ + - Schema.Struct({ + -- type: Schema.Literal("dangerFullAccess").annotate({ + -- title: "DangerFullAccessSandboxPolicyType", + -- }), + -- }).annotate({ title: "DangerFullAccessSandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("readOnly").annotate({ title: "ReadOnlySandboxPolicyType" }), + -- }).annotate({ title: "ReadOnlySandboxPolicy" }), + -- Schema.Struct({ + -- networkAccess: Schema.optionalKey( + -- Schema.Literals(["restricted", "enabled"]).annotate({ default: "restricted" }), + -- ), + -- type: Schema.Literal("externalSandbox").annotate({ + -- title: "ExternalSandboxSandboxPolicyType", + -- }), + -- }).annotate({ title: "ExternalSandboxSandboxPolicy" }), + -- Schema.Struct({ + -- excludeSlashTmp: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- excludeTmpdirEnvVar: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- networkAccess: Schema.optionalKey(Schema.Boolean.annotate({ default: false })), + -- type: Schema.Literal("workspaceWrite").annotate({ title: "WorkspaceWriteSandboxPolicyType" }), + -- writableRoots: Schema.optionalKey( + -+ includePlatformDefaults: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + -+ readableRoots: Schema.optionalKey( + - Schema.Array(V2ThreadStartResponse__AbsolutePathBuf).annotate({ default: [] }), + - ), + -- }).annotate({ title: "WorkspaceWriteSandboxPolicy" }), + -+ type: Schema.Literal("restricted").annotate({ title: "RestrictedReadOnlyAccessType" }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ title: "FullAccessReadOnlyAccessType" }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + - ], + - { mode: "oneOf" }, + - ); + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__SessionSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadStartResponse__ThreadExtra = {}; + --export const V2ThreadStartResponse__ThreadExtra = Schema.Struct({}).annotate({ + -- description: "Extra app-server data for a thread.", + --}); + -- + --export type V2ThreadStartResponse__ThreadHistoryMode = "legacy" | "paginated"; + --export const V2ThreadStartResponse__ThreadHistoryMode = Schema.Literals(["legacy", "paginated"]); + -- + - export type V2ThreadStartResponse__ThreadStatus = + - | { readonly type: "notLoaded" } + - | { readonly type: "idle" } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadStartResponse__ThreadStatus = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadStartResponse__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2ThreadStartResponse__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + - export type V2ThreadStatusChangedNotification = { + - readonly status: V2ThreadStatusChangedNotification__ThreadStatus; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2ThreadUnarchiveResponse__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2ThreadUnarchiveResponse__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + - export type V2ThreadUnarchiveResponse__CollabAgentToolCallStatus = + - | "inProgress" + - | "completed" + -- | "failed" + -- | "interrupted"; + -+ | "failed"; + - export const V2ThreadUnarchiveResponse__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2ThreadUnarchiveResponse__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__SessionSource = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadUnarchiveResponse__ThreadExtra = {}; + --export const V2ThreadUnarchiveResponse__ThreadExtra = Schema.Struct({}).annotate({ + -- description: "Extra app-server data for a thread.", + --}); + -- + --export type V2ThreadUnarchiveResponse__ThreadHistoryMode = "legacy" | "paginated"; + --export const V2ThreadUnarchiveResponse__ThreadHistoryMode = Schema.Literals([ + -- "legacy", + -- "paginated", + --]); + -- + - export type V2ThreadUnarchiveResponse__ThreadStatus = + - | { readonly type: "notLoaded" } + - | { readonly type: "idle" } + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2ThreadUnarchiveResponse__ThreadStatus = Schema.Union( + - { mode: "oneOf" }, + - ); + - + --export type V2ThreadUnarchiveResponse__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2ThreadUnarchiveResponse__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + - export type V2ThreadUnsubscribeParams = { readonly threadId: string }; + - export const V2ThreadUnsubscribeParams = Schema.Struct({ threadId: Schema.String }).annotate({ + - title: "ThreadUnsubscribeParams", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnCompletedNotification__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2TurnCompletedNotification__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + - export type V2TurnCompletedNotification__CollabAgentToolCallStatus = + - | "inProgress" + - | "completed" + -- | "failed" + -- | "interrupted"; + -+ | "failed"; + - export const V2TurnCompletedNotification__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2TurnCompletedNotification__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnCompletedNotification__CommandExecutionSource = Schema.Litera + - "unifiedExecInteraction", + - ]); + - + --export type V2TurnCompletedNotification__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2TurnCompletedNotification__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + - export type V2TurnDiffUpdatedNotification = { + - readonly diff: string; + - readonly threadId: string; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnInterruptResponse = Schema.Struct({}).annotate({ + - title: "TurnInterruptResponse", + - }); + - + --export type V2TurnModerationMetadataNotification = { + -- readonly metadata: unknown; + -- readonly threadId: string; + -- readonly turnId: string; + --}; + --export const V2TurnModerationMetadataNotification = Schema.Struct({ + -- metadata: Schema.Unknown, + -- threadId: Schema.String, + -- turnId: Schema.String, + --}).annotate({ title: "TurnModerationMetadataNotification" }); + -- + - export type V2TurnPlanUpdatedNotification = { + - readonly explanation?: string | null; + - readonly plan: ReadonlyArray; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartedNotification__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2TurnStartedNotification__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + - export type V2TurnStartedNotification__CollabAgentToolCallStatus = + - | "inProgress" + - | "completed" + -- | "failed" + -- | "interrupted"; + -+ | "failed"; + - export const V2TurnStartedNotification__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2TurnStartedNotification__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartedNotification__CommandExecutionSource = Schema.Literals + - "unifiedExecInteraction", + - ]); + - + --export type V2TurnStartedNotification__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2TurnStartedNotification__TurnItemsView = Schema.Literals([ + -- "notLoaded", + -- "summary", + -- "full", + --]); + -- + - export type V2TurnStartParams = { + - readonly approvalPolicy?: V2TurnStartParams__AskForApproval | null; + - readonly approvalsReviewer?: V2TurnStartParams__ApprovalsReviewer | null; + -- readonly clientUserMessageId?: string | null; + - readonly cwd?: string | null; + - readonly effort?: V2TurnStartParams__ReasoningEffort | null; + - readonly input: ReadonlyArray; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartParams = { + - readonly outputSchema?: unknown; + - readonly personality?: V2TurnStartParams__Personality | null; + - readonly sandboxPolicy?: V2TurnStartParams__SandboxPolicy | null; + -- readonly serviceTier?: string | null; + -+ readonly serviceTier?: V2TurnStartParams__ServiceTier | null | null; + - readonly summary?: V2TurnStartParams__ReasoningSummary | null; + - readonly threadId: string; + - }; + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams = Schema.Struct({ + - "Override where approval requests are routed for review on this turn and subsequent turns.", + - }), + - ), + -- clientUserMessageId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - cwd: Schema.optionalKey( + - Schema.Union([ + - Schema.String.annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams = Schema.Struct({ + - ), + - serviceTier: Schema.optionalKey( + - Schema.Union([ + -- Schema.String.annotate({ + -- description: "Override the service tier for this turn and subsequent turns.", + -- }), + -+ Schema.Union([V2TurnStartParams__ServiceTier, Schema.Null]), + - Schema.Null, + -- ]), + -+ ]).annotate({ description: "Override the service tier for this turn and subsequent turns." }), + - ), + - summary: Schema.optionalKey( + - Schema.Union([V2TurnStartParams__ReasoningSummary, Schema.Null]).annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams = Schema.Struct({ + - threadId: Schema.String, + - }).annotate({ title: "TurnStartParams" }); + - + --export type V2TurnStartParams__AdditionalContextEntry = { + -- readonly kind: V2TurnStartParams__AdditionalContextKind; + -- readonly value: string; + --}; + --export const V2TurnStartParams__AdditionalContextEntry = Schema.Struct({ + -- kind: V2TurnStartParams__AdditionalContextKind, + -- value: Schema.String, + --}); + -- + - export type V2TurnStartParams__ByteRange = { readonly end: number; readonly start: number }; + - export const V2TurnStartParams__ByteRange = Schema.Struct({ + - end: Schema.Number.annotate({ format: "uint" }) + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartParams__CollaborationMode = Schema.Struct({ + - settings: V2TurnStartParams__Settings, + - }).annotate({ description: "Collaboration mode for a Codex session." }); + - + --export type V2TurnStartParams__MultiAgentMode = + -- | "explicitRequestOnly" + -- | "proactive" + -- | { readonly custom: string }; + --export const V2TurnStartParams__MultiAgentMode = Schema.Union( + -- [ + -- Schema.Literals(["explicitRequestOnly", "proactive"]), + -- Schema.Struct({ custom: Schema.String }).annotate({ title: "CustomMultiAgentMode" }), + -- ], + -- { mode: "oneOf" }, + --).annotate({ + -- description: + -- "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.", + --}); + -- + - export type V2TurnStartParams__NetworkAccess = "restricted" | "enabled"; + - export const V2TurnStartParams__NetworkAccess = Schema.Literals(["restricted", "enabled"]); + - + --export type V2TurnStartParams__TurnEnvironmentParams = { + -- readonly cwd: V2TurnStartParams__LegacyAppPathString; + -- readonly environmentId: string; + -- readonly runtimeWorkspaceRoots?: ReadonlyArray | null; + --}; + --export const V2TurnStartParams__TurnEnvironmentParams = Schema.Struct({ + -- cwd: V2TurnStartParams__LegacyAppPathString, + -- environmentId: Schema.String, + -- runtimeWorkspaceRoots: Schema.optionalKey( + -- Schema.Union([ + -- Schema.Array(V2TurnStartParams__LegacyAppPathString).annotate({ + -- description: "Environment-native runtime workspace roots. Omitted defaults to `cwd`.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}); + -+export type V2TurnStartParams__ReadOnlyAccess = + -+ | { + -+ readonly includePlatformDefaults?: boolean; + -+ readonly readableRoots?: ReadonlyArray; + -+ readonly type: "restricted"; + -+ } + -+ | { readonly type: "fullAccess" }; + -+export const V2TurnStartParams__ReadOnlyAccess = Schema.Union( + -+ [ + -+ Schema.Struct({ + -+ includePlatformDefaults: Schema.optionalKey(Schema.Boolean.annotate({ default: true })), + -+ readableRoots: Schema.optionalKey( + -+ Schema.Array(V2TurnStartParams__AbsolutePathBuf).annotate({ default: [] }), + -+ ), + -+ type: Schema.Literal("restricted").annotate({ title: "RestrictedReadOnlyAccessType" }), + -+ }).annotate({ title: "RestrictedReadOnlyAccess" }), + -+ Schema.Struct({ + -+ type: Schema.Literal("fullAccess").annotate({ title: "FullAccessReadOnlyAccessType" }), + -+ }).annotate({ title: "FullAccessReadOnlyAccess" }), + -+ ], + -+ { mode: "oneOf" }, + -+); + - + - export type V2TurnStartResponse = { readonly turn: V2TurnStartResponse__Turn }; + - export const V2TurnStartResponse = Schema.Struct({ turn: V2TurnStartResponse__Turn }).annotate({ + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export type V2TurnStartResponse__CollabAgentTool = + - | "sendInput" + - | "resumeAgent" + - | "wait" + -- | "closeAgent" + -- | "sendMessage" + -- | "followupTask" + -- | "interruptAgent" + -- | "listAgents"; + -+ | "closeAgent"; + - export const V2TurnStartResponse__CollabAgentTool = Schema.Literals([ + - "spawnAgent", + - "sendInput", + - "resumeAgent", + - "wait", + - "closeAgent", + -- "sendMessage", + -- "followupTask", + -- "interruptAgent", + -- "listAgents", + - ]); + - + --export type V2TurnStartResponse__CollabAgentToolCallStatus = + -- | "inProgress" + -- | "completed" + -- | "failed" + -- | "interrupted"; + -+export type V2TurnStartResponse__CollabAgentToolCallStatus = "inProgress" | "completed" | "failed"; + - export const V2TurnStartResponse__CollabAgentToolCallStatus = Schema.Literals([ + - "inProgress", + - "completed", + - "failed", + -- "interrupted", + - ]); + - + - export type V2TurnStartResponse__CommandExecutionSource = + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnStartResponse__CommandExecutionSource = Schema.Literals([ + - "unifiedExecInteraction", + - ]); + - + --export type V2TurnStartResponse__TurnItemsView = "notLoaded" | "summary" | "full"; + --export const V2TurnStartResponse__TurnItemsView = Schema.Literals(["notLoaded", "summary", "full"]); + -- + - export type V2TurnSteerParams = { + -- readonly clientUserMessageId?: string | null; + - readonly expectedTurnId: string; + - readonly input: ReadonlyArray; + - readonly threadId: string; + - }; + - export const V2TurnSteerParams = Schema.Struct({ + -- clientUserMessageId: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + - expectedTurnId: Schema.String.annotate({ + - description: + - "Required active turn id precondition. The request fails when it does not match the currently active turn.", + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnSteerParams = Schema.Struct({ + - threadId: Schema.String, + - }).annotate({ title: "TurnSteerParams" }); + - + --export type V2TurnSteerParams__AdditionalContextEntry = { + -- readonly kind: V2TurnSteerParams__AdditionalContextKind; + -- readonly value: string; + --}; + --export const V2TurnSteerParams__AdditionalContextEntry = Schema.Struct({ + -- kind: V2TurnSteerParams__AdditionalContextKind, + -- value: Schema.String, + --}); + -- + - export type V2TurnSteerParams__ByteRange = { readonly end: number; readonly start: number }; + - export const V2TurnSteerParams__ByteRange = Schema.Struct({ + - end: Schema.Number.annotate({ format: "uint" }) + -@@ packages/effect-codex-app-server/src/_generated/schema.gen.ts: export const V2TurnSteerResponse = Schema.Struct({ turnId: Schema.String }).anno + - title: "TurnSteerResponse", + - }); + - + --export type V2WarningNotification = { readonly message: string; readonly threadId?: string | null }; + --export const V2WarningNotification = Schema.Struct({ + -- message: Schema.String.annotate({ description: "Concise warning message for the user." }), + -- threadId: Schema.optionalKey( + -- Schema.Union([ + -- Schema.String.annotate({ + -- description: "Optional thread target when the warning applies to a specific thread.", + -- }), + -- Schema.Null, + -- ]), + -- ), + --}).annotate({ title: "WarningNotification" }); + -- + --export type V2WindowsSandboxReadinessResponse = { + -- readonly status: V2WindowsSandboxReadinessResponse__WindowsSandboxReadiness; + --}; + --export const V2WindowsSandboxReadinessResponse = Schema.Struct({ + -- status: V2WindowsSandboxReadinessResponse__WindowsSandboxReadiness, + --}).annotate({ title: "WindowsSandboxReadinessResponse" }); + -- + - export type V2WindowsSandboxSetupCompletedNotification = { + - readonly error?: string | null; + - readonly mode: V2WindowsSandboxSetupCompletedNotification__WindowsSandboxSetupMode; + - + ## packages/effect-codex-app-server/src/_internal/shared.ts ## + @@ + import * as Effect from "effect/Effect"; + 3: 77a63c13b82 ! 3: 8852b949785 nit + @@ Metadata + ## Commit message ## + nit + + - ## apps/server/src/git/GitManager.test.ts ## + -@@ apps/server/src/git/GitManager.test.ts: const GitManagerTestLayer = GitVcsDriver.layer.pipe( + - ); + - + - it.layer(GitManagerTestLayer)("GitManager", (it) => { + -- const LONG_EFFECT_TEST_TIMEOUT_MS = 30_000; + -- const effect = ( + -- name: string, + -- test: Parameters[1], + -- timeout = LONG_EFFECT_TEST_TIMEOUT_MS, + -- ) => it.effect(name, test, timeout); + -- + -- effect("status includes PR metadata when branch already has an open PR", () => + -+ it.effect("status includes PR metadata when branch already has an open PR", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("status trims PR metadata returned by gh before publishing it", () => + -+ it.effect("status trims PR metadata returned by gh before publishing it", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("status ignores invalid gh pr list entries and keeps valid ones", () => + -+ it.effect("status ignores invalid gh pr list entries and keeps valid ones", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("status preserves lowercase merged and closed PR states from gh json", () => + -+ it.effect("status preserves lowercase merged and closed PR states from gh json", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("status returns an explicit non-repo result for non-git directories", () => + -+ it.effect("status returns an explicit non-repo result for non-git directories", () => + - Effect.gen(function* () { + - const cwd = yield* makeTempDir("t3code-git-manager-non-repo-"); + - const { manager } = yield* makeManager(); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("status returns an explicit non-repo result for deleted directories", () => + -+ it.effect("status returns an explicit non-repo result for deleted directories", () => + - Effect.gen(function* () { + - const rootDir = yield* makeTempDir("t3code-git-manager-missing-dir-"); + - const cwd = NodePath.join(rootDir, "deleted-repo"); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("status briefly caches repeated lookups for the same cwd", () => + -+ it.effect("status briefly caches repeated lookups for the same cwd", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - + - it.effect( + - effect( + -+ it.effect( + - "status ignores unrelated fork PRs when the current branch tracks the same repository", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect( + -+ it.effect( + - "status detects cross-repo PRs from the upstream remote URL owner", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - "pr list --head jasonLaster:statemachine --state all --limit 20 --json number,title,url,baseRefName,headRefName,state,mergedAt,updatedAt,isCrossRepository,headRepository,headRepositoryOwner", + - ); + - }), + -- LONG_EFFECT_TEST_TIMEOUT_MS, + -+ 20_000, + - ); + - + -- effect( + -+ it.effect( + - "status ignores synthetic local branch aliases when the upstream remote name contains slashes", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - ), + - ).toBe(false); + - }), + -- LONG_EFFECT_TEST_TIMEOUT_MS, + -+ 20_000, + - ); + - + -- effect("status returns merged PR state when latest PR was merged", () => + -+ it.effect("status returns merged PR state when latest PR was merged", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("status prefers open PR when merged PR has newer updatedAt", () => + -+ it.effect("status prefers open PR when merged PR has newer updatedAt", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("status is resilient to gh lookup failures and returns pr null", () => + -+ it.effect("status is resilient to gh lookup failures and returns pr null", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }); + - }), + - ); + -- + - it.effect("uses custom commit message when provided", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("commits only selected files when filePaths is provided", () => + -+ it.effect("commits only selected files when filePaths is provided", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("creates feature branch, commits, and pushes with featureBranch option", () => + -+ it.effect("creates feature branch, commits, and pushes with featureBranch option", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("featureBranch uses custom commit message and derives branch name", () => + -+ it.effect("featureBranch uses custom commit message and derives branch name", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("skips commit when there are no uncommitted changes", () => + -+ it.effect("skips commit when there are no uncommitted changes", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("featureBranch returns error when worktree is clean", () => + -+ it.effect("featureBranch returns error when worktree is clean", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("commits and pushes with upstream auto-setup when needed", () => + -+ it.effect("commits and pushes with upstream auto-setup when needed", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect( + -+ it.effect( + - "pushes and creates PR from a no-upstream branch when local commits are ahead of base", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("skips push when branch is already up to date", () => + -+ it.effect("skips push when branch is already up to date", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("pushes existing clean commits without rerunning commit logic", () => + -+ it.effect("pushes existing clean commits without rerunning commit logic", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("create_pr pushes a clean branch before creating the PR when needed", () => + -+ it.effect("create_pr pushes a clean branch before creating the PR when needed", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("returns existing PR metadata for commit/push/pr action", () => + -+ it.effect("returns existing PR metadata for commit/push/pr action", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect( + -+ it.effect( + - "returns existing cross-repo PR metadata using the fork owner selector", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - ).toBe(true); + - expect(ghCalls.some((call) => call.startsWith("pr create "))).toBe(false); + - }), + -- LONG_EFFECT_TEST_TIMEOUT_MS, + -+ 12_000, + - ); + - + -- effect( + -+ it.effect( + - "returns the correct existing PR when a slash remote checks out to a synthetic local alias", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - false, + - ); + - }), + -- LONG_EFFECT_TEST_TIMEOUT_MS, + -+ 20_000, + - ); + - + -- effect( + -+ it.effect( + - "prefers owner-qualified selectors before bare branch names for cross-repo PRs", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - expect(ownerSelectorCallIndex).toBeGreaterThanOrEqual(0); + - expect(ghCalls.some((call) => call.startsWith("pr create "))).toBe(false); + - }), + -- LONG_EFFECT_TEST_TIMEOUT_MS, + -+ 12_000, + - ); + - + -- effect( + -+ it.effect( + - "stops probing head selectors after finding an existing PR", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - "pr list --head octocat:statemachine --state open --limit 1", + - ); + - }), + -- LONG_EFFECT_TEST_TIMEOUT_MS, + -+ 12_000, + - ); + - + -- effect("creates PR when one does not already exist", () => + -+ it.effect("creates PR when one does not already exist", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("creates a new PR instead of reusing an unrelated fork PR with the same head branch", () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- yield* runGit(repoDir, ["checkout", "-b", "feature/no-fork-match"]); + -- const remoteDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); + -- fs.writeFileSync(path.join(repoDir, "changes.txt"), "change\n"); + -- yield* runGit(repoDir, ["add", "changes.txt"]); + -- yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "feature/no-fork-match"]); + -+ it.effect( + -+ "creates a new PR instead of reusing an unrelated fork PR with the same head branch", + -+ () => + -+ Effect.gen(function* () { + -+ const repoDir = yield* makeTempDir("t3code-git-manager-"); + -+ yield* initRepo(repoDir); + -+ yield* runGit(repoDir, ["checkout", "-b", "feature/no-fork-match"]); + -+ const remoteDir = yield* createBareRemote(); + -+ yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); + -+ fs.writeFileSync(path.join(repoDir, "changes.txt"), "change\n"); + -+ yield* runGit(repoDir, ["add", "changes.txt"]); + -+ yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); + -+ yield* runGit(repoDir, ["push", "-u", "origin", "feature/no-fork-match"]); + - + -- const { manager, ghCalls } = yield* makeManager({ + -- ghScenario: { + -- prListSequence: [ + -- JSON.stringify([ + -- { + -- number: 1661, + -- title: "Fork PR with same branch name", + -- url: "https://github.com/pingdotgg/t3code/pull/1661", + -- baseRefName: "main", + -- headRefName: "feature/no-fork-match", + -- state: "OPEN", + -- isCrossRepository: true, + -- headRepository: { + -- nameWithOwner: "lnieuwenhuis/t3code", + -+ const { manager, ghCalls } = yield* makeManager({ + -+ ghScenario: { + -+ prListSequence: [ + -+ JSON.stringify([ + -+ { + -+ number: 1661, + -+ title: "Fork PR with same branch name", + -+ url: "https://github.com/pingdotgg/t3code/pull/1661", + -+ baseRefName: "main", + -+ headRefName: "feature/no-fork-match", + -+ state: "OPEN", + -+ isCrossRepository: true, + -+ headRepository: { + -+ nameWithOwner: "lnieuwenhuis/t3code", + -+ }, + -+ headRepositoryOwner: { + -+ login: "lnieuwenhuis", + -+ }, + - }, + -- headRepositoryOwner: { + -- login: "lnieuwenhuis", + -+ ]), + -+ JSON.stringify([ + -+ { + -+ number: 188, + -+ title: "Add stacked git actions", + -+ url: "https://github.com/pingdotgg/codething-mvp/pull/188", + -+ baseRefName: "main", + -+ headRefName: "feature/no-fork-match", + -+ state: "OPEN", + -+ isCrossRepository: false, + - }, + -- }, + -- ]), + -- JSON.stringify([ + -- { + -- number: 188, + -- title: "Add stacked git actions", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/188", + -- baseRefName: "main", + -- headRefName: "feature/no-fork-match", + -- state: "OPEN", + -- isCrossRepository: false, + -- }, + -- ]), + -- ], + -- }, + -- }); + -- const result = yield* runStackedAction(manager, { + -- cwd: repoDir, + -- action: "commit_push_pr", + -- }); + -+ ]), + -+ ], + -+ }, + -+ }); + -+ const result = yield* runStackedAction(manager, { + -+ cwd: repoDir, + -+ action: "commit_push_pr", + -+ }); + - + -- expect(result.pr.status).toBe("created"); + -- expect(result.pr.number).toBe(188); + -- expect(result.toast).toEqual({ + -- title: "Created PR #188", + -- description: "Add stacked git actions", + -- cta: { + -- kind: "open_pr", + -- label: "View PR", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/188", + -- }, + -- }); + -- expect( + -- ghCalls.some((call) => call.includes("pr create --base main --head feature/no-fork-match")), + -- ).toBe(true); + -- }), + -+ expect(result.pr.status).toBe("created"); + -+ expect(result.pr.number).toBe(188); + -+ expect(result.toast).toEqual({ + -+ title: "Created PR #188", + -+ description: "Add stacked git actions", + -+ cta: { + -+ kind: "open_pr", + -+ label: "View PR", + -+ url: "https://github.com/pingdotgg/codething-mvp/pull/188", + -+ }, + -+ }); + -+ expect( + -+ ghCalls.some((call) => + -+ call.includes("pr create --base main --head feature/no-fork-match"), + -+ ), + -+ ).toBe(true); + -+ }), + - ); + - + -- effect("creates cross-repo PRs with the fork owner selector and default base branch", () => + -+ it.effect("creates cross-repo PRs with the fork owner selector and default base branch", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("rejects push/pr actions from detached HEAD", () => + -+ it.effect("rejects push/pr actions from detached HEAD", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("surfaces missing gh binary errors", () => + -+ it.effect("surfaces missing gh binary errors", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("surfaces gh auth errors with guidance", () => + -+ it.effect("surfaces gh auth errors with guidance", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("resolves pull requests from #number references", () => + -+ it.effect("resolves pull requests from #number references", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("prepares pull request threads in local mode by checking out the PR branch", () => + -+ it.effect("prepares pull request threads in local mode by checking out the PR branch", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("prepares pull request threads in worktree mode on the PR head branch", () => + -+ it.effect("prepares pull request threads in worktree mode on the PR head branch", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("preserves fork upstream tracking when preparing a local PR thread", () => + -+ it.effect("preserves fork upstream tracking when preparing a local PR thread", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("derives fork repository identity from PR URL when GitHub omits nameWithOwner", () => + -+ it.effect("derives fork repository identity from PR URL when GitHub omits nameWithOwner", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("reuses an existing dedicated worktree for the PR head branch", () => + -+ it.effect("reuses an existing dedicated worktree for the PR head branch", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect( + -+ it.effect( + - "does not block fork PR worktree prep when the fork head branch collides with root main", + - () => + - Effect.gen(function* () { + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("does not overwrite an existing local main branch when preparing a fork PR worktree", () => + -- Effect.gen(function* () { + -- const repoDir = yield* makeTempDir("t3code-git-manager-"); + -- yield* initRepo(repoDir); + -- const originDir = yield* createBareRemote(); + -- const forkDir = yield* createBareRemote(); + -- yield* runGit(repoDir, ["remote", "add", "origin", originDir]); + -- yield* runGit(repoDir, ["push", "-u", "origin", "main"]); + -- yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); + -- yield* runGit(repoDir, ["checkout", "-b", "fork-main-source"]); + -- fs.writeFileSync(path.join(repoDir, "fork-main-second.txt"), "fork main second\n"); + -- yield* runGit(repoDir, ["add", "fork-main-second.txt"]); + -- yield* runGit(repoDir, ["commit", "-m", "Fork main second branch"]); + -- yield* runGit(repoDir, ["push", "-u", "fork-seed", "fork-main-source:main"]); + -- yield* runGit(repoDir, ["checkout", "main"]); + -- const localMainBefore = (yield* runGit(repoDir, ["rev-parse", "main"])).stdout.trim(); + -- yield* runGit(repoDir, ["checkout", "-b", "feature/root-branch"]); + -+ it.effect( + -+ "does not overwrite an existing local main branch when preparing a fork PR worktree", + -+ () => + -+ Effect.gen(function* () { + -+ const repoDir = yield* makeTempDir("t3code-git-manager-"); + -+ yield* initRepo(repoDir); + -+ const originDir = yield* createBareRemote(); + -+ const forkDir = yield* createBareRemote(); + -+ yield* runGit(repoDir, ["remote", "add", "origin", originDir]); + -+ yield* runGit(repoDir, ["push", "-u", "origin", "main"]); + -+ yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); + -+ yield* runGit(repoDir, ["checkout", "-b", "fork-main-source"]); + -+ fs.writeFileSync(path.join(repoDir, "fork-main-second.txt"), "fork main second\n"); + -+ yield* runGit(repoDir, ["add", "fork-main-second.txt"]); + -+ yield* runGit(repoDir, ["commit", "-m", "Fork main second branch"]); + -+ yield* runGit(repoDir, ["push", "-u", "fork-seed", "fork-main-source:main"]); + -+ yield* runGit(repoDir, ["checkout", "main"]); + -+ const localMainBefore = (yield* runGit(repoDir, ["rev-parse", "main"])).stdout.trim(); + -+ yield* runGit(repoDir, ["checkout", "-b", "feature/root-branch"]); + - + -- const { manager } = yield* makeManager({ + -- ghScenario: { + -- pullRequest: { + -- number: 92, + -- title: "Fork main overwrite PR", + -- url: "https://github.com/pingdotgg/codething-mvp/pull/92", + -- baseRefName: "main", + -- headRefName: "main", + -- state: "open", + -- isCrossRepository: true, + -- headRepositoryNameWithOwner: "octocat/codething-mvp", + -- headRepositoryOwnerLogin: "octocat", + -- }, + -- repositoryCloneUrls: { + -- "octocat/codething-mvp": { + -- url: forkDir, + -- sshUrl: forkDir, + -+ const { manager } = yield* makeManager({ + -+ ghScenario: { + -+ pullRequest: { + -+ number: 92, + -+ title: "Fork main overwrite PR", + -+ url: "https://github.com/pingdotgg/codething-mvp/pull/92", + -+ baseRefName: "main", + -+ headRefName: "main", + -+ state: "open", + -+ isCrossRepository: true, + -+ headRepositoryNameWithOwner: "octocat/codething-mvp", + -+ headRepositoryOwnerLogin: "octocat", + -+ }, + -+ repositoryCloneUrls: { + -+ "octocat/codething-mvp": { + -+ url: forkDir, + -+ sshUrl: forkDir, + -+ }, + - }, + - }, + -- }, + -- }); + -+ }); + - + -- const result = yield* preparePullRequestThread(manager, { + -- cwd: repoDir, + -- reference: "92", + -- mode: "worktree", + -- }); + -+ const result = yield* preparePullRequestThread(manager, { + -+ cwd: repoDir, + -+ reference: "92", + -+ mode: "worktree", + -+ }); + - + -- expect(result.branch).toBe("t3code/pr-92/main"); + -- expect((yield* runGit(repoDir, ["rev-parse", "main"])).stdout.trim()).toBe(localMainBefore); + -- expect( + -- (yield* runGit(result.worktreePath as string, [ + -- "rev-parse", + -- "--abbrev-ref", + -- "@{upstream}", + -- ])).stdout.trim(), + -- ).toBe("fork-seed/main"); + -- }), + -+ expect(result.branch).toBe("t3code/pr-92/main"); + -+ expect((yield* runGit(repoDir, ["rev-parse", "main"])).stdout.trim()).toBe(localMainBefore); + -+ expect( + -+ (yield* runGit(result.worktreePath as string, [ + -+ "rev-parse", + -+ "--abbrev-ref", + -+ "@{upstream}", + -+ ])).stdout.trim(), + -+ ).toBe("fork-seed/main"); + -+ }), + - ); + - + -- effect("reuses an existing PR worktree and restores fork upstream tracking", () => + -+ it.effect("reuses an existing PR worktree and restores fork upstream tracking", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("emits ordered progress events for commit hooks", () => + -+ it.effect("emits ordered progress events for commit hooks", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + -@@ apps/server/src/git/GitManager.test.ts: it.layer(GitManagerTestLayer)("GitManager", (it) => { + - }), + - ); + - + -- effect("emits action_failed when a commit hook rejects", () => + -+ it.effect("emits action_failed when a commit hook rejects", () => + - Effect.gen(function* () { + - const repoDir = yield* makeTempDir("t3code-git-manager-"); + - yield* initRepo(repoDir); + - + ## apps/server/src/git/Layers/CursorTextGeneration.test.ts ## + @@ apps/server/src/git/Layers/CursorTextGeneration.test.ts: function withFakeAcpAgent( + }); + 4: 4da42ca393a ! 4: 3fe3534dbef revert more + @@ apps/server/src/provider/acp/AcpRuntimeModel.test.ts: describe("AcpRuntimeModel" + + ## apps/server/src/provider/acp/AcpRuntimeModel.ts ## + @@ apps/server/src/provider/acp/AcpRuntimeModel.ts: export function parseSessionUpdateEvent(params: EffectAcpSchema.SessionNotificat + - + - switch (upd.sessionUpdate) { + + break; + + } + case "current_mode_update": { + - modeId = upd.currentModeId; + - events.push({ + @@ apps/server/src/provider/codexAppServer.test.ts (deleted) + - }); + -}); + + - ## apps/server/src/provider/makeManagedServerProvider.ts ## + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - readonly getSettings: Effect.Effect; + - readonly streamSettings: Stream.Stream; + - readonly haveSettingsChanged: (previous: Settings, next: Settings) => boolean; + -- readonly buildInitialSnapshot?: ((settings: Settings) => ServerProvider) | undefined; + -- readonly initialSnapshot?: ((settings: Settings) => ServerProvider) | undefined; + -+ readonly initialSnapshot: (settings: Settings) => Effect.Effect; + - readonly checkProvider: Effect.Effect; + - readonly enrichSnapshot?: (input: { + - readonly settings: Settings; + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - > { + - const backgroundPolicy = yield* BackgroundPolicy.BackgroundPolicy; + - const serverSettings = yield* ServerSettingsService; + -- type InitialRefreshState = "idle" | "running" | "done"; + - const refreshSemaphore = yield* Semaphore.make(1); + - const changesPubSub = yield* Effect.acquireRelease( + - PubSub.unbounded(), + - PubSub.shutdown, + - ); + - const initialSettings = yield* input.getSettings; + -- const initialSnapshotFactory = input.buildInitialSnapshot ?? input.initialSnapshot; + -- if (!initialSnapshotFactory) { + -- return yield* Effect.die( + -- new Error("makeManagedServerProvider requires an initial snapshot factory."), + -- ); + -- } + -- const initialSnapshot = initialSnapshotFactory(initialSettings); + -+ const initialSnapshot = yield* input.initialSnapshot(initialSettings); + - const snapshotStateRef = yield* Ref.make({ + - snapshot: initialSnapshot, + - enrichmentGeneration: 0, + - }); + - const settingsRef = yield* Ref.make(initialSettings); + -- const initialRefreshStateRef = yield* Ref.make("idle"); + - const enrichmentFiberRef = yield* Ref.make | null>(null); + - const scope = yield* Effect.scope; + - + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - if (state.enrichmentGeneration !== generation || Equal.equals(state.snapshot, nextSnapshot)) { + - return [null, state] as const; + - } + -- + - return [ + - nextSnapshot, + - { + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - ] as const; + - }); + - yield* Ref.set(settingsRef, nextSettings); + -- yield* Ref.set(initialRefreshStateRef, "done"); + - yield* PubSub.publish(changesPubSub, nextSnapshot); + - yield* restartSnapshotEnrichment(nextSettings, nextSnapshot, nextGeneration); + - return nextSnapshot; + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - return yield* applySnapshot(nextSettings, { forceRefresh: true }); + - }); + - + -- const startInitialRefreshIfNeeded = Effect.fn("startInitialRefreshIfNeeded")(function* () { + -- const shouldStart = yield* Ref.modify( + -- initialRefreshStateRef, + -- (state): readonly [boolean, InitialRefreshState] => + -- state === "idle" ? [true, "running"] : [false, state], + -- ); + -- + -- if (!shouldStart) { + -- return; + -- } + -+ const hasProviderStatusDemand = Effect.gen(function* () { + -+ const state = yield* Ref.get(snapshotStateRef); + -+ const instanceId = state.snapshot.instanceId; + -+ const [genericDemand, instanceDemand] = yield* Effect.all([ + -+ backgroundPolicy.shouldRunScopeWork({ type: "provider-status" }), + -+ backgroundPolicy.shouldRunScopeWork({ type: "provider-status", instanceId }), + -+ ]); + -+ return genericDemand || instanceDemand; + -+ }); + - + -- yield* refreshSnapshot().pipe( + -- Effect.onExit((exit) => + -- exit._tag === "Failure" + -- ? Ref.update(initialRefreshStateRef, (state) => (state === "running" ? "idle" : state)) + -- : Effect.void, + -+ const getRefreshInterval = + -+ input.refreshInterval !== undefined + -+ ? Effect.succeed(input.refreshInterval) + -+ : serverSettings.getSettings.pipe( + -+ Effect.map( + -+ (settings) => + -+ resolveServerBackgroundActivitySettings(settings).providerHealthRefreshInterval, + -+ ), + -+ Effect.orElseSucceed(() => DEFAULT_PROVIDER_HEALTH_REFRESH_INTERVAL), + -+ ); + -+ + -+ const refreshIntervalChanges = yield* Queue.sliding(1); + -+ if (input.refreshInterval === undefined) { + -+ const serverSettingsChanges = yield* serverSettings.subscribeChanges; + -+ yield* serverSettingsChanges.pipe( + -+ Stream.map((settings) => + -+ Duration.toMillis( + -+ resolveServerBackgroundActivitySettings(settings).providerHealthRefreshInterval, + -+ ), + - ), + -- Effect.ignoreCause({ log: true }), + -- Effect.forkIn(scope), + -+ Stream.changes, + -+ Stream.runForEach(() => Queue.offer(refreshIntervalChanges, undefined).pipe(Effect.asVoid)), + -+ Effect.forkScoped, + - ); + -- }); + -+ } + - + - yield* Stream.runForEach(input.streamSettings, (nextSettings) => + - Effect.asVoid(applySnapshot(nextSettings)), + -@@ apps/server/src/provider/makeManagedServerProvider.ts: export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( + - Effect.ignoreCause({ log: true }), + - ), + - ).pipe(Effect.forkScoped); + -- yield* startInitialRefreshIfNeeded(); + -+ + -+ yield* applySnapshot(initialSettings, { forceRefresh: true }).pipe( + -+ Effect.ignoreCause({ log: true }), + -+ Effect.forkScoped, + -+ ); + - + - return { + -- getSnapshot: startInitialRefreshIfNeeded().pipe( + -- Effect.flatMap(() => + -- input.getSettings.pipe( + -- Effect.flatMap(applySnapshot), + -- Effect.tapError(Effect.logError), + -- Effect.orDie, + -- ), + -- ), + -- ), + -+ maintenanceCapabilities: input.maintenanceCapabilities, + -+ getSnapshot: Ref.get(snapshotStateRef).pipe(Effect.map((state) => state.snapshot)), + - refresh: refreshSnapshot().pipe(Effect.tapError(Effect.logError), Effect.orDie), + - get streamChanges() { + - return Stream.fromPubSub(changesPubSub); + - + ## apps/server/src/serverSettings.ts ## + @@ apps/server/src/serverSettings.ts: function restoreUsedProviders( + }; + @@ apps/web/src/components/chat/CompactComposerControlsMenu.browser.tsx: async func + ["variant"]; + - triggerClassName?: string; + -- disabledReason?: string; + -- onProviderModelChange: (provider: ProviderKind, model: string) => void; + -+ triggerAriaLabel?: string; + -+ onOpenChange?: (open: boolean) => void; + -+ getModelDisabledReason?: (instanceId: ProviderInstanceId, model: string) => string | null; + -+ onInstanceModelChange: (instanceId: ProviderInstanceId, model: string) => void; + - }) { + - const [uncontrolledIsMenuOpen, setUncontrolledIsMenuOpen] = useState(false); + - const isMenuOpen = props.open ?? uncontrolledIsMenuOpen; + -@@ apps/web/src/components/chat/ProviderModelPicker.tsx: export const ProviderModelPicker = memo(function ProviderModelPicker(props: { + - + - const handleInstanceModelChange = (instanceId: ProviderInstanceId, model: string) => { + - if (props.disabled) return; + -- if (!value) return; + -- const resolvedModel = + -- resolveSelectableModel(provider, value, props.modelOptionsByProvider[provider]) ?? + -- resolveModelSlugForProvider(provider, value); + -- if (!resolvedModel) return; + -- props.onProviderModelChange(provider, resolvedModel); + -+ props.onInstanceModelChange(instanceId, model); + - setIsMenuOpen(false); + - }; + - + -@@ apps/web/src/components/chat/ProviderModelPicker.tsx: export const ProviderModelPicker = memo(function ProviderModelPicker(props: { + - props.triggerClassName, + - )} + - disabled={props.disabled} + -- title={props.disabled ? props.disabledReason : undefined} + - /> + - } + - > + -@@ apps/web/src/components/chat/ProviderModelPicker.tsx: export const ProviderModelPicker = memo(function ProviderModelPicker(props: { + - showBadge={showInstanceBadge} + - className="size-4" + - iconClassName={cn("size-4", props.activeProviderIconClassName)} + -- indicatorBackground="var(--input)" + -+ indicatorBackground="var(--contrast-input)" + - badgeClassName={cn( + - "right-[-0.125rem] bottom-[-0.125rem] h-3 min-w-3", + - "px-0.5 text-[7px]", + -@@ apps/web/src/components/chat/ProviderModelPicker.tsx: export const ProviderModelPicker = memo(function ProviderModelPicker(props: { + - + - ) : null} + - + -- + -- + -- {props.lockedProvider !== null ? ( + -- + -- handleModelChange(props.lockedProvider!, value)} + -- > + -- {props.modelOptionsByProvider[props.lockedProvider].map((modelOption) => ( + -- setIsMenuOpen(false)} + -- > + -- {modelOption.name} + -- + -- ))} + -- + -- + -- ) : ( + -- <> + -- {AVAILABLE_PROVIDER_OPTIONS.map((option) => { + -- const OptionIcon = PROVIDER_ICON_BY_PROVIDER[option.value]; + -- const liveProvider = props.providers + -- ? getProviderSnapshot(props.providers, option.value) + -- : undefined; + -- if (liveProvider && liveProvider.status !== "ready") { + -- const unavailableLabel = !liveProvider.enabled + -- ? "Disabled" + -- : !liveProvider.installed + -- ? "Not installed" + -- : "Unavailable"; + -- return ( + -- + -- + -- ); + -- } + -- return ( + -- + -- + -- + -- + -- + -- handleModelChange(option.value, value)} + -- > + -- {props.modelOptionsByProvider[option.value].map((modelOption) => ( + -- setIsMenuOpen(false)} + -- > + -- {modelOption.name} + -- + -- ))} + -- + -- + -- + -- + -- ); + -- })} + -- {UNAVAILABLE_PROVIDER_OPTIONS.length > 0 && } + -- {UNAVAILABLE_PROVIDER_OPTIONS.map((option) => { + -- const OptionIcon = PROVIDER_ICON_BY_PROVIDER[option.value]; + -- return ( + -- + -- + -- ); + -- })} + -- {UNAVAILABLE_PROVIDER_OPTIONS.length === 0 && } + -- {COMING_SOON_PROVIDER_OPTIONS.map((option) => { + -- const OptionIcon = option.icon; + -- return ( + -- + -- + -- ); + -- })} + -- + -- )} + -- + -- + -+ + -+ + -+ + -+ setIsMenuOpen(false)} + -+ {...(props.getModelDisabledReason + -+ ? { getModelDisabledReason: props.getModelDisabledReason } + -+ : {})} + -+ onInstanceModelChange={handleInstanceModelChange} + -+ /> + -+ + -+ + - ); + - }); + - + ## apps/web/src/components/chat/TraitsPicker.browser.tsx ## + @@ apps/web/src/components/chat/TraitsPicker.browser.tsx: describe("TraitsPicker (Codex)", () => { + }); + 5: d914dc03290 = 5: fdf63358fa2 resynclock + 6: ba5d340a047 < -: ----------- Delay Codex provider availability until checked + 7: 4c8648f791f = 6: 773f789c828 Return Cursor ACP runtime with explicit scope + 8: a5270231419 = 7: f355bd32b10 Normalize Codex IDs and preserve streamed stdout decoding + 9: 99e5494242a ! 8: c41b812f43f Scope Codex session runtime lifetimes + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export interface CodexAdapterLi + + readonly scope: Scope.Closeable; + readonly runtime: CodexSessionRuntimeShape; + readonly eventFiber: Fiber.Fiber; + - stopped: boolean; + + readonly turnTokenUsage: CodexTurnTokenUsageState; + @@ apps/server/src/provider/Layers/CodexAdapter.ts: export const makeCodexAdapter = Effect.fn("makeCodexAdapter")(function* ( + const runtimeEventQueue = yield* Queue.unbounded(); + const sessions = new Map(); + 10: 3bded8ba565 = 9: faf4d6c04e2 decoders + 11: 3182df2608d = 10: a1d85aa3331 Flush native logs on adapter shutdown + 12: 74942087a35 ! 11: ce08dee1407 Switch Codex provider checks to app-server probe + @@ apps/server/src/git/Layers/CodexTextGeneration.ts: const makeCodexTextGeneration + schemaPath, + "--output-last-message", + + - ## apps/server/src/provider/Layers/CodexProvider.ts ## + -@@ + --import * as DateTime from "effect/DateTime"; + --import * as Duration from "effect/Duration"; + --import * as Effect from "effect/Effect"; + --import * as Layer from "effect/Layer"; + --import * as Option from "effect/Option"; + --import * as Result from "effect/Result"; + --import * as Schema from "effect/Schema"; + --import * as Scope from "effect/Scope"; + --import * as Types from "effect/Types"; + --import * as ChildProcess from "effect/unstable/process/ChildProcess"; + --import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; + --import * as CodexClient from "effect-codex-app-server/client"; + --import * as CodexSchema from "effect-codex-app-server/schema"; + -+import type { CodexSettings, ServerProvider, ServerProviderState } from "@t3tools/contracts"; + -+import { ServerSettingsError } from "@t3tools/contracts"; + -+import { Duration, Effect, Equal, Layer, Option, Result, Schema, Stream } from "effect"; + - import * as CodexErrors from "effect-codex-app-server/errors"; + -+import { ChildProcessSpawner } from "effect/unstable/process"; + - + --import type { + -- CodexSettings, + -- ServerProvider, + -- ServerProviderAuth, + -- ServerProviderSkill, + -- ServerProviderState, + -- ModelCapabilities, + -- ProviderOptionDescriptor, + -- ServerProviderModel, + -- ServerProviderSkill, + --} from "@t3tools/contracts"; + --import { + -- Cache, + -- Data, + -- Duration, + -- Effect, + -- Equal, + -- FileSystem, + -- Layer, + -- Option, + -- Path, + -- Result, + -- Stream, + --} from "effect"; + --import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; + -- + --import { createModelCapabilities } from "@t3tools/shared/model"; + --import { resolveSpawnCommand } from "@t3tools/shared/shell"; + --import { codexAppServerArgs, resolveCodexLaunchArgs } from "./codexLaunchArgs.ts"; + --import { + -- AUTH_PROBE_TIMEOUT_MS, + -- buildServerProvider, + -- type ServerProviderDraft, + --} from "../providerSnapshot.ts"; + - import { makeManagedServerProvider } from "../makeManagedServerProvider.ts"; + -+import { buildServerProvider } from "../providerSnapshot.ts"; + - import { + -- formatCodexCliUpgradeMessage, + -- isCodexCliVersionSupported, + -- parseCodexCliVersion, + --} from "../codexCliVersion.ts"; + --import { + -- adjustCodexModelsForAccount, + -- codexAuthSubLabel, + -- codexAuthSubType, + -- type CodexAccountSnapshot, + --} from "../codexAccount.ts"; + --import { type CodexDiscoverySnapshot, probeCodexDiscovery } from "../codexAppServer.ts"; + --import { BUILT_IN_CODEX_MODELS, DEFAULT_CODEX_MODEL_CAPABILITIES } from "../codexModels.ts"; + -+ codexAccountAuthLabel, + -+ probeCodexAppServerProvider, + -+ type CodexAppServerProviderSnapshot, + -+} from "../codexAppServer.ts"; + - import { CodexProvider } from "../Services/CodexProvider.ts"; + - import { ServerSettingsService } from "../../serverSettings.ts"; + --import { ServerSettingsError } from "@t3tools/contracts"; + - + - const PROVIDER = "codex" as const; + --const OPENAI_AUTH_PROVIDERS = new Set(["openai"]); + -- + --class CodexDiscoveryCacheKey extends Data.Class<{ + -- readonly binaryPath: string; + -- readonly homePath?: string; + -- readonly cwd: string; + --}> {} + -+const PROVIDER_PROBE_TIMEOUT_MS = 8_000; + -+ + -+const emptyCodexModelsFromSettings = (codexSettings: CodexSettings): ServerProvider["models"] => + -+ codexSettings.customModels + -+ .map((model) => model.trim()) + -+ .filter((model, index, models) => model.length > 0 && models.indexOf(model) === index) + -+ .map((model) => ({ + -+ slug: model, + -+ name: model, + -+ isCustom: true, + -+ capabilities: null, + -+ })); + - + - const makePendingCodexProvider = (codexSettings: CodexSettings): ServerProvider => { + - const checkedAt = new Date().toISOString(); + -- const models = providerModelsFromSettings( + -- BUILT_IN_CODEX_MODELS, + -- PROVIDER, + -- codexSettings.customModels, + -- DEFAULT_CODEX_MODEL_CAPABILITIES, + -- ); + -+ const models = emptyCodexModelsFromSettings(codexSettings); + - + - if (!codexSettings.enabled) { + - return buildServerProvider({ + -@@ apps/server/src/provider/Layers/CodexProvider.ts: const makePendingCodexProvider = (codexSettings: CodexSettings): ServerProvider + - }); + - }; + - + --const REASONING_EFFORT_LABELS: Readonly> = { + -- none: "None", + -- minimal: "Minimal", + -- low: "Low", + -- medium: "Medium", + -- high: "High", + -- xhigh: "Extra High", + -- max: "Max", + -- ultra: "Ultra", + --}; + -- + --const DEFAULT_SERVICE_TIER_ID = "default"; + -- + --function reasoningEffortLabel(reasoningEffort: string): string { + -- return REASONING_EFFORT_LABELS[reasoningEffort] ?? reasoningEffort; + --} + -- + --function codexAccountAuthLabel(account: CodexSchema.V2GetAccountResponse["account"]) { + -- if (!account) return undefined; + -- if (account.type === "apiKey") return "OpenAI API Key"; + -- if (account.type === "amazonBedrock") return "Amazon Bedrock"; + -- if (account.type !== "chatgpt") return undefined; + -- + -- switch (account.planType) { + -- case "free": + -- return "ChatGPT Free Subscription"; + -- case "go": + -- return "ChatGPT Go Subscription"; + -- case "plus": + -- return "ChatGPT Plus Subscription"; + -- case "pro": + -- return "ChatGPT Pro 20x Subscription"; + -- case "prolite": + -- return "ChatGPT Pro 5x Subscription"; + -- case "team": + -- return "ChatGPT Team Subscription"; + -- case "self_serve_business_prolite": + -- case "self_serve_business_usage_based": + -- case "business": + -- return "ChatGPT Business Subscription"; + -- case "ent26": + -- case "enterprise_cbp_automation": + -- case "enterprise_cbp_usage_based": + -- case "enterprise": + -- return "ChatGPT Enterprise Subscription"; + -- case "edu": + -- case "edu_plus": + -- case "edu_pro": + -- return "ChatGPT Edu Subscription"; + -- case "unknown": + -- return "ChatGPT Subscription"; + -- default: + -- account.planType satisfies never; + -- return undefined; + -- } + --} + -- + --function codexAccountEmail(account: CodexSchema.V2GetAccountResponse["account"]) { + -- if (!account || account.type !== "chatgpt") return undefined; + -- return account.email; + --} + -- + --export function mapCodexModelCapabilities( + -- model: CodexSchema.V2ModelListResponse__Model, + --): ModelCapabilities { + -- const reasoningOptions = model.supportedReasoningEfforts.map(({ reasoningEffort }) => + -- reasoningEffort === model.defaultReasoningEffort + -- ? { + -- id: reasoningEffort, + -- label: reasoningEffortLabel(reasoningEffort), + -- isDefault: true, + -- } + -- : { + -- id: reasoningEffort, + -- label: reasoningEffortLabel(reasoningEffort), + -- }, + -- ); + -- const defaultReasoning = reasoningOptions.find((option) => option.isDefault)?.id; + -- const serviceTiers = + -- model.serviceTiers && model.serviceTiers.length > 0 + -- ? model.serviceTiers + -- : (model.additionalSpeedTiers ?? []).map((id) => ({ + -- id, + -- name: id === "fast" ? "Fast" : id, + -- description: "", + -- })); + -- const catalogDefaultServiceTier = serviceTiers.some( + -- (tier) => tier.id === model.defaultServiceTier, + -- ) + -- ? model.defaultServiceTier + -- : null; + -- const defaultServiceTier = catalogDefaultServiceTier ?? DEFAULT_SERVICE_TIER_ID; + -- const optionDescriptors: ProviderOptionDescriptor[] = []; + -- + -- if (reasoningOptions.length > 0) { + -- optionDescriptors.push({ + -- id: "reasoningEffort", + -- label: "Reasoning", + -- type: "select", + -- options: reasoningOptions, + -- ...(defaultReasoning ? { currentValue: defaultReasoning } : {}), + -- }); + -- } + -- if (serviceTiers.length > 0) { + -- optionDescriptors.push({ + -- id: "serviceTier", + -- label: "Service Tier", + -- type: "select", + -- options: [ + -- { + -- id: DEFAULT_SERVICE_TIER_ID, + -- label: "Standard", + -- ...(defaultServiceTier === DEFAULT_SERVICE_TIER_ID ? { isDefault: true } : {}), + -- }, + -- ...serviceTiers.map((tier) => ({ + -- id: tier.id, + -- label: tier.name, + -- ...(tier.description ? { description: tier.description } : {}), + -- ...(defaultServiceTier === tier.id ? { isDefault: true } : {}), + -- })), + -- ], + -- currentValue: defaultServiceTier, + -- }); + -- } + -- + -- return createModelCapabilities({ + -- optionDescriptors, + -- }); + --} + -- + --const toDisplayName = (model: CodexSchema.V2ModelListResponse__Model): string => { + -- // Capitalize 'gpt' to 'GPT-' and capitalize any letter following a dash + -- return model.displayName + -- .replace(/^gpt/i, "GPT") // Handle start with 'gpt' or 'GPT' + -- .replace(/-([a-z])/g, (_, c) => "-" + c.toUpperCase()); + --}; + -- + --function parseCodexModelListResponse( + -- response: CodexSchema.V2ModelListResponse, + --): ReadonlyArray { + -- return response.data.map((model) => ({ + -- slug: model.model, + -- name: toDisplayName(model), + -- isCustom: false, + -- ...(model.isDefault ? { isDefault: true } : {}), + -- capabilities: mapCodexModelCapabilities(model), + -- })); + --} + -- + --/** + -- * Prefer our own default-model ranking when one of the preferred slugs is in + -- * the live catalog; otherwise keep whatever Codex itself flagged as default. + -- */ + --export function applyPreferredCodexDefaultModel( + -- models: ReadonlyArray, + --): ReadonlyArray { + -- const preferredSlug = PREFERRED_DEFAULT_CODEX_MODELS.find((slug) => + -- models.some((model) => model.slug === slug && !model.isCustom), + -- ); + -- if (!preferredSlug) { + -- return models; + -- } + -- return models.map((model) => { + -- if (model.slug === preferredSlug) { + -- return model.isDefault ? model : { ...model, isDefault: true }; + -- } + -- if (!model.isDefault) { + -- return model; + -- } + -- const { isDefault: _isDefault, ...rest } = model; + -- return rest; + -- }); + --} + -- + --function appendCustomCodexModels( + -- models: ReadonlyArray, + -- customModels: ReadonlyArray, + --): ReadonlyArray { + -- if (customModels.length === 0) { + -- return models; + -- } + -- + -- const seen = new Set(models.map((model) => model.slug)); + -- const fallbackCapabilities = models.find((model) => model.capabilities)?.capabilities ?? null; + -- const customEntries: ServerProviderModel[] = []; + -- for (const rawModel of customModels) { + -- const slug = rawModel.trim(); + -- if (!slug || seen.has(slug)) { + -- continue; + -- } + -- seen.add(slug); + -- customEntries.push({ + -- slug, + -- name: slug, + -- isCustom: true, + -- capabilities: fallbackCapabilities, + -- }); + -+function accountProbeStatus(account: CodexAppServerProviderSnapshot["account"]): { + -+ readonly status: Exclude; + -+ readonly auth: ServerProvider["auth"]; + -+ readonly message?: string; + -+} { + -+ const authLabel = codexAccountAuthLabel(account.account); + -+ const auth = { + -+ status: account.account ? ("authenticated" as const) : ("unknown" as const), + -+ ...(account.account?.type ? { type: account.account?.type } : {}), + -+ ...(authLabel ? { label: authLabel } : {}), + -+ } satisfies ServerProvider["auth"]; + -+ + -+ if (account.account) { + -+ return { status: "ready", auth }; + - } + -- return customEntries.length === 0 ? models : [...models, ...customEntries]; + --} + - + --function parseCodexSkillsListResponse( + -- response: CodexSchema.V2SkillsListResponse, + -- cwd: string, + --): ReadonlyArray { + -- const matchingEntry = response.data.find((entry) => entry.cwd === cwd); + -- const skills = matchingEntry + -- ? matchingEntry.skills + -- : response.data.flatMap((entry) => entry.skills); + -- + -- return skills.map((skill) => { + -- const shortDescription = + -- skill.shortDescription ?? skill.interface?.shortDescription ?? undefined; + -- + -- const parsedSkill: Types.Mutable = { + -- name: skill.name, + -- path: skill.path, + -- enabled: skill.enabled, + -- }; + -- + -- if (skill.description) { + -- parsedSkill.description = skill.description; + -- } + -- if (skill.scope) { + -- parsedSkill.scope = skill.scope; + -- } + -- if (skill.interface?.displayName) { + -- parsedSkill.displayName = skill.interface.displayName; + -- } + -- if (shortDescription) { + -- parsedSkill.shortDescription = shortDescription; + -- } + -- + -- return parsedSkill; + -- }); + --} + -- + --const requestAllCodexModels = Effect.fn("requestAllCodexModels")(function* ( + -- client: CodexClient.CodexAppServerClient["Service"], + --) { + -- const models: ServerProviderModel[] = []; + -- let cursor: string | null | undefined = undefined; + -- + -- do { + -- const response: CodexSchema.V2ModelListResponse = yield* client.request( + -- "model/list", + -- cursor ? { cursor } : {}, + -- ); + -- models.push(...parseCodexModelListResponse(response)); + -- cursor = response.nextCursor; + -- } while (cursor); + -- + -- return models; + --}); + -- + --export function buildCodexInitializeParams(): CodexSchema.V1InitializeParams { + -- return { + -- clientInfo: { + -- name: "t3code_desktop", + -- title: "T3 Code Desktop", + -- version: packageJson.version, + -- }, + -- capabilities: { + -- experimentalApi: true, + -- }, + -- }; + --} + -- + --const probeCodexAppServerProvider = Effect.fn("probeCodexAppServerProvider")(function* (input: { + -- readonly binaryPath: string; + -- readonly homePath?: string; + -- readonly launchArgs?: string; + -- readonly cwd: string; + --}) => + -- probeCodexDiscovery(input).pipe( + -- Effect.timeoutOption(CAPABILITIES_PROBE_TIMEOUT_MS), + -- Effect.result, + -- Effect.map((result) => { + -- if (Result.isFailure(result)) return undefined; + -- return Option.isSome(result.success) ? result.success.value : undefined; + -- }), + -- ); + -- + -- const initialize = yield* client.request("initialize", { + -- clientInfo: { + -- name: "t3code_desktop", + -- title: "T3 Code Desktop", + -- version: "0.1.0", + -- }, + -- capabilities: { + -- experimentalApi: true, + -- }, + -- }); + -- yield* client.notify("initialized", undefined); + -- + -- // Extract the version string after the first '/' in userAgent, up to the next space or the end + -- const versionMatch = initialize.userAgent.match(/\/([^\s]+)/); + -- const version = versionMatch ? versionMatch[1] : undefined; + -- + -- const accountResponse = yield* client.request("account/read", {}); + -- if (!accountResponse.account && accountResponse.requiresOpenaiAuth) { + -+ if (account.requiresOpenaiAuth) { + - return { + -- account: accountResponse, + -- version, + -- models: appendCustomCodexModels([], input.customModels ?? []), + -- skills: [], + -- } satisfies CodexAppServerProviderSnapshot; + -+ status: "error", + -+ auth: { status: "unauthenticated" }, + -+ message: "Codex CLI is not authenticated. Run `codex login` and try again.", + -+ }; + - } + - + -- const [skillsResponse, models] = yield* Effect.all( + -- [ + -- client.request("skills/list", { + -- cwds: [input.cwd], + -- }), + -- requestAllCodexModels(client), + -- ], + -- { concurrency: "unbounded" }, + -- ); + -- + -- return { + -- account: accountResponse, + -- version, + -- models: applyPreferredCodexDefaultModel( + -- appendCustomCodexModels(models, input.customModels ?? []), + -- ), + -- skills: parseCodexSkillsListResponse(skillsResponse, input.cwd), + -- } satisfies CodexAppServerProviderSnapshot; + --}); + -+ return { status: "ready", auth }; + -+} + - + - export const checkCodexProviderStatus = Effect.fn("checkCodexProviderStatus")(function* ( + -- resolveAccount?: (input: { + -- readonly binaryPath: string; + -- readonly homePath?: string; + -- }) => Effect.Effect, + -- resolveSkills?: (input: { + -+ probe: (input: { + - readonly binaryPath: string; + - readonly homePath?: string; + - readonly cwd: string; + -- }) => Effect.Effect | undefined>, + -+ readonly customModels: ReadonlyArray; + -+ }) => Effect.Effect< + -+ CodexAppServerProviderSnapshot, + -+ CodexErrors.CodexAppServerError, + -+ ChildProcessSpawner.ChildProcessSpawner + -+ > = probeCodexAppServerProvider, + - ): Effect.fn.Return< + - ServerProvider, + - ServerSettingsError, + -- | ChildProcessSpawner.ChildProcessSpawner + -- | FileSystem.FileSystem + -- | Path.Path + -- | ServerSettingsService + -+ ServerSettingsService | ChildProcessSpawner.ChildProcessSpawner + - > { + - const codexSettings = yield* Effect.service(ServerSettingsService).pipe( + - Effect.flatMap((service) => service.getSettings), + - Effect.map((settings) => settings.providers.codex), + - ); + - const checkedAt = new Date().toISOString(); + -- const models = providerModelsFromSettings( + -- BUILT_IN_CODEX_MODELS, + -- PROVIDER, + -- codexSettings.customModels, + -- DEFAULT_CODEX_MODEL_CAPABILITIES, + -- ); + -+ const emptyModels = emptyCodexModelsFromSettings(codexSettings); + - + - if (!codexSettings.enabled) { + - return buildServerProvider({ + - provider: PROVIDER, + - enabled: false, + - checkedAt, + -- models, + -+ models: emptyModels, + -+ skills: [], + - probe: { + - installed: false, + - version: null, + -@@ apps/server/src/provider/Layers/CodexProvider.ts: export const checkCodexProviderStatus = Effect.fn("checkCodexProviderStatus")(fu + - }); + - } + - + -- const versionProbe = yield* runCodexCommand(["--version"]).pipe( + -- Effect.timeoutOption(DEFAULT_TIMEOUT_MS), + -- Effect.result, + -- ); + -+ const probeResult = yield* probe({ + -+ binaryPath: codexSettings.binaryPath, + -+ homePath: codexSettings.homePath, + -+ cwd: process.cwd(), + -+ customModels: codexSettings.customModels, + -+ }).pipe(Effect.timeoutOption(Duration.millis(PROVIDER_PROBE_TIMEOUT_MS)), Effect.result); + - + -- if (Result.isFailure(versionProbe)) { + -- const error = versionProbe.failure; + -+ if (Result.isFailure(probeResult)) { + -+ const error = probeResult.failure; + -+ const installed = !Schema.is(CodexErrors.CodexAppServerSpawnError)(error); + - return buildServerProvider({ + - provider: PROVIDER, + - enabled: codexSettings.enabled, + - checkedAt, + -- models, + -+ models: emptyModels, + -+ skills: [], + - probe: { + -- installed: !isCommandMissingCause(error), + -+ installed, + - version: null, + - status: "error", + - auth: { status: "unknown" }, + -- message: isCommandMissingCause(error) + -- ? "Codex CLI (`codex`) is not installed or not on PATH." + -- : `Failed to execute Codex CLI health check: ${error.message}.`, + -+ message: installed + -+ ? `Codex app-server provider probe failed: ${error.message}.` + -+ : "Codex CLI (`codex`) is not installed or not on PATH.", + - }, + - }); + - } + - + -- if (Option.isNone(versionProbe.success)) { + -+ if (Option.isNone(probeResult.success)) { + - return buildServerProvider({ + - provider: PROVIDER, + - enabled: codexSettings.enabled, + - checkedAt, + -- models, + -+ models: emptyModels, + -+ skills: [], + - probe: { + - installed: true, + - version: null, + - status: "error", + - auth: { status: "unknown" }, + -- message: "Codex CLI is installed but failed to run. Timed out while running command.", + -- }, + -- }); + -- } + -- + -- const version = versionProbe.success.value; + -- const parsedVersion = + -- parseCodexCliVersion(`${version.stdout}\n${version.stderr}`) ?? + -- parseGenericCliVersion(`${version.stdout}\n${version.stderr}`); + -- if (version.code !== 0) { + -- const detail = detailFromResult(version); + -- return buildServerProvider({ + -- provider: PROVIDER, + -- enabled: codexSettings.enabled, + -- checkedAt, + -- models, + -- probe: { + -- installed: true, + -- version: parsedVersion, + -- status: "error", + -- auth: { status: "unknown" }, + -- message: detail + -- ? `Codex CLI is installed but failed to run. ${detail}` + -- : "Codex CLI is installed but failed to run.", + -- }, + -- }); + -- } + -- + -- if (parsedVersion && !isCodexCliVersionSupported(parsedVersion)) { + -- return buildServerProvider({ + -- provider: PROVIDER, + -- enabled: codexSettings.enabled, + -- checkedAt, + -- models, + -- probe: { + -- installed: true, + -- version: parsedVersion, + -- status: "error", + -- auth: { status: "unknown" }, + -- message: formatCodexCliUpgradeMessage(parsedVersion), + -- }, + -- }); + -- } + -- + -- const skills = + -- (resolveSkills + -- ? yield* resolveSkills({ + -- binaryPath: codexSettings.binaryPath, + -- homePath: codexSettings.homePath, + -- cwd: process.cwd(), + -- }).pipe(Effect.orElseSucceed(() => undefined)) + -- : undefined) ?? []; + -- + -- if (yield* hasCustomModelProvider) { + -- return buildServerProvider({ + -- provider: PROVIDER, + -- enabled: codexSettings.enabled, + -- checkedAt, + -- models, + -- skills, + -- probe: { + -- installed: true, + -- version: parsedVersion, + -- status: "ready", + -- auth: { status: "unknown" }, + -- message: "Using a custom Codex model provider; OpenAI login check skipped.", + -- }, + -- }); + -- } + -- + -- const authProbe = yield* runCodexCommand(["login", "status"]).pipe( + -- Effect.timeoutOption(DEFAULT_TIMEOUT_MS), + -- Effect.result, + -- ); + -- const account = resolveAccount + -- ? yield* resolveAccount({ + -- binaryPath: codexSettings.binaryPath, + -- homePath: codexSettings.homePath, + -- }) + -- : undefined; + -- const resolvedModels = adjustCodexModelsForAccount(models, account); + -- + -- if (Result.isFailure(authProbe)) { + -- const error = authProbe.failure; + -- return buildServerProvider({ + -- provider: PROVIDER, + -- enabled: codexSettings.enabled, + -- checkedAt, + -- models: resolvedModels, + -- skills, + -- probe: { + -- installed: true, + -- version: parsedVersion, + -- status: "warning", + -- auth: { status: "unknown" }, + -- message: `Could not verify Codex authentication status: ${error.message}.`, + -+ message: "Timed out while checking Codex app-server provider status.", + - }, + - }); + - } + - + -- if (Option.isNone(authProbe.success)) { + -- return buildServerProvider({ + -- provider: PROVIDER, + -- enabled: codexSettings.enabled, + -- checkedAt, + -- models: resolvedModels, + -- skills, + -- probe: { + -- installed: true, + -- version: parsedVersion, + -- status: "warning", + -- auth: { status: "unknown" }, + -- message: "Could not verify Codex authentication status. Timed out while running command.", + -- }, + -- }); + -- } + -+ const snapshot = probeResult.success.value; + -+ const accountStatus = accountProbeStatus(snapshot.account); + - + -- const parsed = parseAuthStatusFromOutput(authProbe.success.value); + -- const authType = codexAuthSubType(account); + -- const authLabel = codexAuthSubLabel(account); + - return buildServerProvider({ + - provider: PROVIDER, + - enabled: codexSettings.enabled, + - checkedAt, + -- models: resolvedModels, + -- skills, + -+ models: snapshot.models, + -+ skills: snapshot.skills, + - probe: { + - installed: true, + -- version: parsedVersion, + -- status: parsed.status, + -- auth: { + -- ...parsed.auth, + -- ...(authType ? { type: authType } : {}), + -- ...(authLabel ? { label: authLabel } : {}), + -- }, + -- ...(parsed.message ? { message: parsed.message } : {}), + -+ version: snapshot.version ?? null, + -+ status: accountStatus.status, + -+ auth: accountStatus.auth, + -+ ...(accountStatus.message ? { message: accountStatus.message } : {}), + - }, + - }); + - }); + - + --const applyCodexDiscoverySnapshot = ( + -- snapshot: ServerProvider, + -- discovery: CodexDiscoverySnapshot, + --): ServerProvider => { + -- const authType = codexAuthSubType(discovery.account); + -- const authLabel = codexAuthSubLabel(discovery.account); + -- + -- return { + -- ...snapshot, + -- auth: { + -- ...snapshot.auth, + -- ...(authType ? { type: authType } : {}), + -- ...(authLabel ? { label: authLabel } : {}), + -- }, + -- models: adjustCodexModelsForAccount(snapshot.models, discovery.account), + -- skills: discovery.skills, + -- }; + --}; + -- + --const enrichCodexSnapshotViaDiscovery = (input: { + -- readonly settings: CodexSettings; + -- readonly snapshot: ServerProvider; + -- readonly publishSnapshot: (snapshot: ServerProvider) => Effect.Effect; + -- readonly getDiscovery: (input: { + -- readonly binaryPath: string; + -- readonly homePath?: string; + -- readonly cwd: string; + -- }) => Effect.Effect; + --}) => + -- (input.settings.enabled && input.snapshot.installed + -- ? input + -- .getDiscovery({ + -- binaryPath: input.settings.binaryPath, + -- homePath: input.settings.homePath, + -- cwd: process.cwd(), + -- }) + -- .pipe( + -- Effect.flatMap((discovery) => + -- discovery + -- ? input.publishSnapshot(applyCodexDiscoverySnapshot(input.snapshot, discovery)) + -- : Effect.void, + -- ), + -- ) + -- : Effect.void + -- ).pipe(Effect.catchCause((cause) => Effect.logError(cause))); + -- + - export const CodexProviderLive = Layer.effect( + - CodexProvider, + - Effect.gen(function* () { + - const serverSettings = yield* ServerSettingsService; + -- const fileSystem = yield* FileSystem.FileSystem; + -- const path = yield* Path.Path; + - const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; + -- const accountProbeCache = yield* Cache.make({ + -- capacity: 4, + -- timeToLive: Duration.minutes(5), + -- lookup: (key: CodexDiscoveryCacheKey) => { + -- const { binaryPath, homePath, cwd } = key; + -- return probeCodexCapabilities({ + -- binaryPath, + -- cwd, + -- ...(homePath ? { homePath } : {}), + -- }); + -- }, + -- }); + -- }); + -- + -- const getDiscovery = (input: { + -- readonly binaryPath: string; + -- readonly homePath?: string; + -- readonly cwd: string; + -- }) => Cache.get(accountProbeCache, new CodexDiscoveryCacheKey(input)); + -- + - const checkProvider = checkCodexProviderStatus().pipe( + - Effect.provideService(ServerSettingsService, serverSettings), + -- Effect.provideService(FileSystem.FileSystem, fileSystem), + -- Effect.provideService(Path.Path, path), + - Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), + - ); + - + -@@ apps/server/src/provider/Layers/CodexProvider.ts: export const CodexProviderLive = Layer.effect( + - haveSettingsChanged: (previous, next) => !Equal.equals(previous, next), + - initialSnapshot: makePendingCodexProvider, + - checkProvider, + -- enrichSnapshot: ({ settings, snapshot, publishSnapshot }) => + -- enrichCodexSnapshotViaDiscovery({ + -- settings, + -- snapshot, + -- publishSnapshot, + -- getDiscovery, + -- }), + -+ refreshInterval: Duration.minutes(5), + - }); + - } + - + -@@ apps/server/src/provider/Layers/CodexProvider.ts: export const CodexProviderLive = Layer.effect( + - auth: { status: "unknown" }, + - message: installed + - ? `Codex app-server provider probe failed: ${error.message}.` + -- : "Codex CLI (`codex`) was not found on PATH.", + -+ : "Codex CLI (`codex`) is not installed or not on PATH.", + - }, + - }); + - } + -@@ apps/server/src/provider/Layers/CodexProvider.ts: export const CodexProviderLive = Layer.effect( + - checkedAt, + - models: snapshot.models, + - skills: snapshot.skills, + -- slashCommands: [ + -- { + -- name: "feedback", + -- description: "Send this thread and Codex logs to OpenAI", + -- input: { hint: "Describe the issue (optional)" }, + -- }, + -- ], + - probe: { + - installed: true, + - version: snapshot.version ?? null, + - + ## apps/server/src/provider/Layers/ProviderRegistry.test.ts ## + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te + ); + 13: fa13e794bbe ! 12: d2a22ec1652 Address Codex review feedback + @@ Commit message + Co-authored-by: codex + + ## apps/server/src/provider/Layers/CodexAdapter.ts ## + -@@ apps/server/src/provider/Layers/CodexAdapter.ts: function normalizeCodexTokenUsage( + +@@ apps/server/src/provider/Layers/CodexAdapter.ts: function completeCodexTurnTokenUsage( + } + + function toTurnStatus( + 14: 783f4f6e8d2 = 13: 99de1c8833e Add orchestration v2 docs and probe fixtures + 15: eb8af12dca3 = 14: 28999d55151 Add orchestration v2 replay and service contracts + 16: 75120285ae7 = 15: 67d40b8e8ee Map Codex turns into orchestration v2 + 17: 5e551ef7227 ! 16: 41937c522ee Implement orchestration v2 runtime + @@ apps/server/src/persistence/Migrations.ts: import Migration0034 from "./Migratio + -import Migration0042 from "./Migrations/042_ProjectionThreadLinkedPullRequest.ts"; + -import Migration0043 from "./Migrations/043_ProjectionThreadsUnsettledAt.ts"; + -import Migration0044 from "./Migrations/044_ClearAutomaticProjectModelDefaults.ts"; + +-import Migration0045 from "./Migrations/045_ProjectionProjectsAutoPull.ts"; + +-import Migration0046 from "./Migrations/046_RepairAutomaticSettlementTimestamps.ts"; + +-import Migration0047 from "./Migrations/047_ProjectionProjectIcon.ts"; + +======= + +import Migration026V2 from "./Migrations/026_OrchestrationV2.ts"; + +>>>>>>> d788fb20eb (Implement orchestration v2 runtime) + @@ apps/server/src/persistence/Migrations.ts: export const migrationEntries = [ + - [42, "ProjectionThreadLinkedPullRequest", Migration0042], + - [43, "ProjectionThreadsUnsettledAt", Migration0043], + - [44, "ClearAutomaticProjectModelDefaults", Migration0044], + +- [45, "ProjectionProjectsAutoPull", Migration0045], + +- [46, "RepairAutomaticSettlementTimestamps", Migration0046], + +- [47, "ProjectionProjectIcon", Migration0047], + +======= + + [38, "OrchestrationV2", Migration026V2], + +>>>>>>> d788fb20eb (Implement orchestration v2 runtime) + @@ apps/server/src/server.test.ts: import * as NodeHttpServer from "@effect/platfor + + import { + AuthAccessTokenType, + +- AuthStandardClientScopes, + + AuthEnvironmentBootstrapTokenType, + + AuthTokenExchangeGrantType, + + CommandId, + @@ apps/server/src/server.test.ts: import { + GitCommandError, + KeybindingRule, + @@ apps/server/src/server.test.ts: import { + - type PreviewEvent, + + type ProviderKind, + ProjectId, + +- type ProviderAuthState, + ProviderDriverKind, + ProviderInstanceId, + +- type ProviderInstallState, + +- ProviderSetupError, + + ResolvedKeybindingRule, + + ThreadId, + + TurnId, + @@ apps/server/src/server.test.ts: import { RELAY_HEALTH_REQUEST_TYP, RELAY_MINT_REQUEST_TYP } from "@t3tools/share + import * as RelayClient from "@t3tools/shared/relayClient"; + import { assert, it } from "@effect/vitest"; + @@ apps/server/src/server.test.ts: import { RELAY_HEALTH_REQUEST_TYP, RELAY_MINT_RE + -import * as FileSystem from "effect/FileSystem"; + -import * as Fiber from "effect/Fiber"; + -import * as Layer from "effect/Layer"; + --import * as ManagedRuntime from "effect/ManagedRuntime"; + -import * as Option from "effect/Option"; + -import * as Path from "effect/Path"; + -import * as PubSub from "effect/PubSub"; + -import * as Ref from "effect/Ref"; + +-import * as Queue from "effect/Queue"; + -import * as Schema from "effect/Schema"; + -import * as Stream from "effect/Stream"; + -import * as TestClock from "effect/testing/TestClock"; + @@ apps/server/src/server.test.ts: import { + -import * as CheckpointDiffQuery from "./checkpointing/CheckpointDiffQuery.ts"; + -import * as GitManager from "./git/GitManager.ts"; + -import * as EnvironmentTheme from "./environmentTheme.ts"; + +-import * as UsageLimitSources from "./usage/UsageLimitSources.ts"; + -import * as Keybindings from "./keybindings.ts"; + -import * as ExternalLauncher from "./process/externalLauncher.ts"; + -import * as RemoteOpenTargets from "./environment/RemoteOpenTargets.ts"; + @@ apps/server/src/server.test.ts: import { + import * as ProjectionSnapshotQuery from "./orchestration/Services/ProjectionSnapshotQuery.ts"; + import { ThreadDeletionReactor } from "./orchestration/Services/ThreadDeletionReactor.ts"; + import { SqlitePersistenceMemory } from "./persistence/Layers/Sqlite.ts"; + +@@ apps/server/src/server.test.ts: import { OrchestrationEventStoreLive } from "./persistence/Layers/OrchestrationE + + import { OrchestrationEventStore } from "./persistence/Services/OrchestrationEventStore.ts"; + import { PersistenceSqlError } from "./persistence/Errors.ts"; + import * as ProviderRegistry from "./provider/Services/ProviderRegistry.ts"; + -import * as ProviderService from "./provider/Services/ProviderService.ts"; + +-import { ProviderAuthService } from "./provider/Services/ProviderAuthService.ts"; + +-import { ProviderInstanceRegistry } from "./provider/Services/ProviderInstanceRegistry.ts"; + +-import { + +- AntigravityInstallation, + +- AntigravityInstallationError, + +-} from "./provider/AntigravityInstallation.ts"; + +-import type { ProviderInstance } from "./provider/ProviderDriver.ts"; + -import { ProviderAdapterRequestError } from "./provider/Errors.ts"; + import { makeManualOnlyProviderMaintenanceCapabilities } from "./provider/providerMaintenance.ts"; + import * as ServerLifecycleEvents from "./serverLifecycleEvents.ts"; + import * as ServerRuntimeStartup from "./serverRuntimeStartup.ts"; + +@@ apps/server/src/server.test.ts: import * as TerminalManager from "./terminal/Manager.ts"; + + import * as PreviewManager from "./preview/Manager.ts"; + + import * as PortScanner from "./preview/PortScanner.ts"; + + import * as BrowserTraceCollector from "./observability/BrowserTraceCollector.ts"; + +-import * as NativeAppIconResolver from "./assets/NativeAppIconResolver.ts"; + + import * as ProjectFaviconResolver from "./project/ProjectFaviconResolver.ts"; + + import * as T3ProjectFileLoader from "./project/T3ProjectFileLoader.ts"; + + import * as ProjectSetupScriptRunner from "./project/ProjectSetupScriptRunner.ts"; + @@ apps/server/src/server.test.ts: import * as VcsDriver from "./vcs/VcsDriver.ts"; + import * as VcsStatusBroadcaster from "./vcs/VcsStatusBroadcaster.ts"; + import * as VcsDriverRegistry from "./vcs/VcsDriverRegistry.ts"; + @@ apps/server/src/server.test.ts: import * as VcsDriver from "./vcs/VcsDriver.ts"; + import * as GitWorkflowService from "./git/GitWorkflowService.ts"; + import * as ReviewService from "./review/ReviewService.ts"; + import * as SourceControlRepositoryService from "./sourceControl/SourceControlRepositoryService.ts"; + + import * as ServerSecretStore from "./auth/ServerSecretStore.ts"; + + import * as EnvironmentAuth from "./auth/EnvironmentAuth.ts"; + +-import * as PairingGrantStore from "./auth/PairingGrantStore.ts"; + + import * as CloudManagedEndpointRuntime from "./cloud/ManagedEndpointRuntime.ts"; + + import * as CloudCliTokenManager from "./cloud/CliTokenManager.ts"; + + import * as ProcessDiagnostics from "./diagnostics/ProcessDiagnostics.ts"; + @@ apps/server/src/server.test.ts: import * as NativeTelemetryClient from "./resourceTelemetry/NativeTelemetryClien + import * as ResourceAttribution from "./resourceTelemetry/ResourceAttribution.ts"; + import * as ResourceTelemetry from "./resourceTelemetry/ResourceTelemetry.ts"; + @@ apps/server/src/server.test.ts: import * as NativeTelemetryClient from "./resour + const defaultProjectId = ProjectId.make("project-default"); + const defaultThreadId = ThreadId.make("thread-default"); + const defaultDesktopBootstrapToken = "test-desktop-bootstrap-token"; + +@@ apps/server/src/server.test.ts: const defaultModelSelection = { + + model: "gpt-5-codex", + + } as const; + + + +-const providerSetupInstanceId = ProviderInstanceId.make("antigravity-custom-profile"); + +-const providerSetupDriver = ProviderDriverKind.make("antigravity"); + +-const providerSetupInstallState: ProviderInstallState = { + +- driver: providerSetupDriver, + +- operationId: "install-operation", + +- phase: "downloading", + +- downloadedBytes: 128, + +- totalBytes: 256, + +- version: "test-release", + +- installedVersion: null, + +- canRemove: false, + +- message: null, + +-}; + +-const providerSetupAuthState: ProviderAuthState = { + +- instanceId: providerSetupInstanceId, + +- phase: "idle", + +- flowId: null, + +- authorizationUrl: null, + +- expiresAt: null, + +- message: null, + +-}; + +-const providerSetupInstance: ProviderInstance = { + +- instanceId: providerSetupInstanceId, + +- driverKind: providerSetupDriver, + +- enabled: false, + +- displayName: "Google account", + +- continuationIdentity: { + +- driverKind: providerSetupDriver, + +- continuationKey: providerSetupInstanceId, + +- }, + +- get adapter(): never { + +- throw new Error("Provider setup must not start a chat session."); + +- }, + +- get snapshot(): never { + +- throw new Error("Installation routing must not probe the provider."); + +- }, + +- get textGeneration(): never { + +- throw new Error("Provider setup must not generate text."); + +- }, + +-}; + +- + + const makeLiveToolActivityEvent = ( + + sequence: number, + + kind: "tool.updated" | "tool.completed" = "tool.updated", + @@ apps/server/src/server.test.ts: const makeBrowserOtlpPayload = (spanName: string) => + + ({ close }) => Effect.promise(close), + + ); + + + +- // The exporter's batch fiber is forked while the layer builds and ticks on + +- // a wall-clock interval, so the whole tracer runs on the live clock. + +- yield* Layer.build( + ++ const runtime = ManagedRuntime.make( + + OtlpTracer.layer({ + + url: collector.url, + + exportInterval: "10 millis", + +@@ apps/server/src/server.test.ts: const makeBrowserOtlpPayload = (spanName: string) => + + }, + + }, + + }).pipe(Layer.provide(browserOtlpTracingLayer)), + +- ).pipe( + +- Effect.flatMap((tracing) => + +- Effect.void.pipe(Effect.withSpan(spanName), Effect.provideContext(tracing)), + +- ), + +- TestClock.withLive, + + ); + + + ++ try { + ++ yield* Effect.promise(() => runtime.runPromise(Effect.void.pipe(Effect.withSpan(spanName)))); + ++ } finally { + ++ yield* Effect.promise(() => runtime.dispose()); + ++ } + ++ + + const request = yield* Effect.raceFirst( + + Effect.promise(() => collector.firstRequest).pipe(Effect.orDie), + + Effect.sleep(Duration.seconds(1)).pipe( + +@@ apps/server/src/server.test.ts: const makeBrowserOtlpPayload = (spanName: string) => + + }); + + + const buildAppUnderTest = (options?: { + +- onPairingChangesSubscribed?: Effect.Effect; + config?: Partial; + layers?: { + - keybindings?: Partial; + - environmentTheme?: Partial; + - providerRegistry?: Partial; + - providerService?: Partial; + +- providerAuth?: Partial; + +- providerInstanceRegistry?: Partial; + +- antigravityInstallation?: Partial; + - serverSettings?: Partial; + - externalLauncher?: Partial; + - vcsDriver?: Partial; + @@ apps/server/src/server.test.ts: const makeBrowserOtlpPayload = (spanName: string + }; + }) => + Effect.gen(function* () { + +@@ apps/server/src/server.test.ts: const buildAppUnderTest = (options?: { + + Layer.provide(WorkspacePaths.layer), + + Layer.provide(T3ProjectFileLoader.layer), + + ), + +- NativeAppIconResolver.layer, + + ); + + const gitWorkflowLayer = GitWorkflowService.layer.pipe( + + Layer.provideMerge(vcsDriverRegistryLayer), + @@ apps/server/src/server.test.ts: const buildAppUnderTest = (options?: { + ), + ), + @@ apps/server/src/server.test.ts: const buildAppUnderTest = (options?: { + disableListenLog: true, + disableLogger: true, + @@ apps/server/src/server.test.ts: const buildAppUnderTest = (options?: { + + streamChanges: Stream.empty, + + ...options?.layers?.environmentTheme, + + }), + +- Layer.mock(UsageLimitSources.UsageLimitSources)({ + +- current: Effect.succeed([]), + +- streamChanges: Stream.empty, + +- refresh: Effect.void, + +- }), + ), + ), + Layer.provide( + @@ apps/server/src/server.test.ts: const buildAppUnderTest = (options?: { + - uploadFeedback: () => Effect.die("Provider feedback is not stubbed in this test"), + - ...options?.layers?.providerService, + - }), + +- Layer.mock(ProviderAuthService)({ + +- ...options?.layers?.providerAuth, + +- }), + +- Layer.mock(ProviderInstanceRegistry)({ + +- getInstance: () => Effect.succeed(undefined), + +- listInstances: Effect.succeed([]), + +- ...options?.layers?.providerInstanceRegistry, + +- }), + +- Layer.mock(AntigravityInstallation)({ + +- managedDirectory: "unused-test-antigravity-runtime", + +- ...options?.layers?.antigravityInstallation, + +- }), + - ), + + Layer.mock(ProviderRegistry.ProviderRegistry)({ + + getProviders: Effect.succeed([]), + @@ apps/server/src/server.test.ts: const buildAppUnderTest = (options?: { + ), + Layer.provide( + Layer.mock(ProcessDiagnostics.ProcessDiagnostics)({ + +@@ apps/server/src/server.test.ts: const buildAppUnderTest = (options?: { + + ), + + Layer.provide( + + Layer.mock(ProjectionSnapshotQuery.ProjectionSnapshotQuery)({ + +- getUserInputActivity: () => Effect.die("unused"), + + getCommandReadModel: () => Effect.succeed(makeDefaultOrchestrationReadModel()), + + getSnapshot: () => Effect.succeed(makeDefaultOrchestrationReadModel()), + + getShellSnapshot: () => + @@ apps/server/src/server.test.ts: const buildAppUnderTest = (options?: { + ...options?.layers?.projectionSnapshotQuery, + }), + @@ apps/server/src/server.test.ts: const buildAppUnderTest = (options?: { + ...options?.layers?.serverRuntimeStartup, + }), + @@ apps/server/src/server.test.ts: const buildAppUnderTest = (options?: { + + ...options?.layers?.cloudCliTokenManager, + + }), + + ), + +- Layer.updateService(PairingGrantStore.PairingGrantStore, (grants) => { + +- const subscribed = options?.onPairingChangesSubscribed; + +- if (!subscribed) return grants; + +- return { + +- ...grants, + +- streamChanges: Stream.unwrap( + +- Effect.gen(function* () { + +- const changes = yield* Queue.unbounded(); + +- yield* grants.streamChanges.pipe( + +- Stream.runForEach((change) => Queue.offer(changes, change)), + +- Effect.forkScoped({ startImmediately: true }), + +- ); + +- yield* subscribed; + +- return Stream.fromQueue(changes); + +- }), + +- ), + +- }; + +- }), + + Layer.provideMerge(makeAuthTestLayer()), + Layer.provideMerge(ServerSecretStore.layer), + Layer.provide(workspaceAndProjectServicesLayer), + Layer.provideMerge(FetchHttpClient.layer), + @@ apps/server/src/server.test.ts: const buildAppUnderTest = (options?: { + Layer.provide(layerConfig), + ); + + +@@ apps/server/src/server.test.ts: const parseSessionCookieFromWsUrl = ( + + }; + + }; + + + +-const wsRpcProtocolLayer = (wsUrl: string, onMessage?: (message: string) => void) => { + ++const wsRpcProtocolLayer = (wsUrl: string) => { + + const { cookie, url } = parseSessionCookieFromWsUrl(wsUrl); + + const webSocketConstructorLayer = Layer.succeed( + + Socket.WebSocketConstructor, + +- (socketUrl, protocols) => { + +- const socket = new NodeSocket.NodeWS.WebSocket( + ++ (socketUrl, protocols) => + ++ new NodeSocket.NodeWS.WebSocket( + + socketUrl, + + protocols, + + cookie ? { headers: { cookie } } : undefined, + +- ); + +- if (onMessage) socket.on("message", (data) => onMessage(data.toString())); + +- return socket as unknown as globalThis.WebSocket; + +- }, + ++ ) as unknown as globalThis.WebSocket, + + ); + + + + return RpcClient.layerProtocolSocket().pipe( + @@ apps/server/src/server.test.ts: const makeWsRpcClient = RpcClient.make(WsRpcGroup); + type WsRpcClient = + typeof makeWsRpcClient extends Effect.Effect ? Client : never; + @@ apps/server/src/server.test.ts: const makeWsRpcClient = RpcClient.make(WsRpcGrou + const withWsRpcClient = ( + wsUrl: string, + f: (client: WsRpcClient) => Effect.Effect, + - ) => makeWsRpcClient.pipe(Effect.flatMap(f), Effect.provide(wsRpcProtocolLayer(wsUrl))); + - + +- onMessage?: (message: string) => void, + +-) => makeWsRpcClient.pipe(Effect.flatMap(f), Effect.provide(wsRpcProtocolLayer(wsUrl, onMessage))); + ++) => makeWsRpcClient.pipe(Effect.flatMap(f), Effect.provide(wsRpcProtocolLayer(wsUrl))); + ++ + +const ORCHESTRATION_V2_REPLAY_HARNESSES = [CodexOrchestratorReplayHarness] as const; + + + +function orchestrationV2ReplayHarnessFor(provider: ProviderKind) { + @@ apps/server/src/server.test.ts: const makeWsRpcClient = RpcClient.make(WsRpcGrou + + }), + + ), + + ); + -+ + - const appendSessionCookieToWsUrl = (url: string, sessionCookieHeader: string) => { + - const isAbsoluteUrl = /^[a-zA-Z][a-zA-Z\d+.-]*:/.test(url); + - const next = new URL(url, "http://localhost"); + + + + const withFirstWsAckHeld = ( + + wsUrl: string, + @@ apps/server/src/server.test.ts: const getWsServerUrl = ( + ); + }); + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam + it.effect("negotiates permessage-deflate with clients that offer it", () => + Effect.gen(function* () { + yield* buildAppUnderTest(); + +@@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam", (it) => { + + }).pipe(Effect.provide(NodeHttpServer.layerTest)), + + ); + + + +- it.effect("returns only pairing metadata to access-read HTTP sessions", () => + +- Effect.gen(function* () { + +- yield* buildAppUnderTest(); + +- const reader = yield* exchangeAccessToken(defaultDesktopBootstrapToken, { + +- scope: "access:read", + +- }); + +- assert.equal(reader.response.status, 200); + +- assert.equal(reader.body.scope, "access:read"); + +- const createdResponse = yield* HttpClient.post("/api/auth/pairing-token", { + +- headers: { cookie: yield* getAuthenticatedSessionCookieHeader() }, + +- body: yield* HttpBody.json({ label: "Synthetic phone" }), + +- }); + +- const created = (yield* createdResponse.json) as { id: string; credential: string }; + +- assert.equal(createdResponse.status, 200); + +- const response = yield* HttpClient.get("/api/auth/pairing-links", { + +- headers: { authorization: `Bearer ${reader.body.access_token ?? ""}` }, + +- }); + +- assert.equal(response.status, 200); + +- const responseText = yield* response.text; + +- assert.notInclude(responseText, '"credential"'); + +- assert.notInclude(responseText, created.credential); + +- const links = yield* responseJsonEffect< + +- ReadonlyArray<{ + +- readonly id: string; + +- readonly label?: string; + +- readonly scopes: ReadonlyArray; + +- }> + +- >(response); + +- const listed = links.find((link) => link.id === created.id); + +- assert.isDefined(listed); + +- assert.deepInclude(listed, { + +- label: "Synthetic phone", + +- scopes: [...AuthStandardClientScopes], + +- }); + +- + +- const unauthorizedCreate = yield* HttpClient.post("/api/auth/pairing-token", { + +- headers: { authorization: `Bearer ${reader.body.access_token ?? ""}` }, + +- body: yield* HttpBody.json({}), + +- }); + +- assert.equal(unauthorizedCreate.status, 403); + +- const idExchange = yield* exchangeAccessToken(created.id, { scope: "terminal:operate" }); + +- assert.equal(idExchange.response.status, 401); + +- const authorized = yield* exchangeAccessToken(created.credential, { + +- scope: AuthStandardClientScopes.join(" "), + +- }); + +- assert.equal(authorized.response.status, 200); + +- assert.equal(authorized.body.scope, AuthStandardClientScopes.join(" ")); + +- const reused = yield* exchangeAccessToken(created.credential, { scope: "terminal:operate" }); + +- assert.equal(reused.response.status, 401); + +- }).pipe(Effect.provide(NodeHttpServer.layerTest)), + +- ); + +- + +- it.effect("returns only pairing metadata in access-read WebSocket snapshots and updates", () => + +- Effect.gen(function* () { + +- const changesSubscribed = yield* Deferred.make(); + +- yield* buildAppUnderTest({ + +- onPairingChangesSubscribed: Deferred.succeed(changesSubscribed, undefined).pipe( + +- Effect.asVoid, + +- ), + +- }); + +- const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); + +- const createLink = Effect.gen(function* () { + +- const response = yield* HttpClient.post("/api/auth/pairing-token", { + +- headers: { cookie: ownerCookie }, + +- body: yield* HttpBody.json({}), + +- }); + +- assert.equal(response.status, 200); + +- return (yield* response.json) as { id: string; credential: string }; + +- }); + +- const initialLink = yield* createLink; + +- const reader = yield* exchangeAccessToken(defaultDesktopBootstrapToken, { + +- scope: "access:read", + +- }); + +- assert.equal(reader.body.scope, "access:read"); + +- const ticketResponse = yield* HttpClient.post("/api/auth/websocket-ticket", { + +- headers: { authorization: `Bearer ${reader.body.access_token ?? ""}` }, + +- }); + +- assert.equal(ticketResponse.status, 200); + +- const { ticket } = (yield* ticketResponse.json) as { ticket: string }; + +- const wsUrl = `${yield* getWsServerUrl("/ws", { authenticated: false })}?wsTicket=${encodeURIComponent(ticket)}`; + +- const frames: string[] = []; + +- yield* withWsRpcClient( + +- wsUrl, + +- (client) => + +- Effect.gen(function* () { + +- const snapshotReceived = yield* Deferred.make(); + +- const eventsFiber = yield* client.subscribeAuthAccess({}).pipe( + +- Stream.tap((event) => + +- event.type === "snapshot" + +- ? Deferred.succeed(snapshotReceived, undefined) + +- : Effect.void, + +- ), + +- Stream.takeUntil((event) => event.type === "pairingLinkUpserted"), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- yield* Deferred.await(snapshotReceived); + +- yield* Deferred.await(changesSubscribed); + +- const liveLink = yield* createLink; + +- const events = yield* Fiber.join(eventsFiber); + +- const snapshot = events.find((event) => event.type === "snapshot"); + +- const update = events.find((event) => event.type === "pairingLinkUpserted"); + +- assert.isDefined(snapshot); + +- assert.isDefined(update); + +- assert.isTrue( + +- snapshot?.payload.pairingLinks.some((link) => link.id === initialLink.id), + +- ); + +- assert.equal(update?.payload.id, liveLink.id); + +- // Inspect the wire frames so client schema decoding cannot hide a leak. + +- assert.notInclude(frames.join(""), '"credential"'); + +- assert.notInclude(frames.join(""), initialLink.credential); + +- assert.notInclude(frames.join(""), liveLink.credential); + +- const paired = yield* exchangeAccessToken(liveLink.credential, { + +- scope: AuthStandardClientScopes.join(" "), + +- }); + +- assert.equal(paired.response.status, 200); + +- }), + +- (frame) => frames.push(frame), + +- ); + +- }).pipe(Effect.scoped, Effect.provide(NodeHttpServer.layerTest)), + +- ); + +- + + it.effect("lists and revokes pairing links for access management sessions", () => + + Effect.gen(function* () { + + yield* buildAppUnderTest({ + +@@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam", (it) => { + + }); + + const listedLinks = (yield* listResponse.json) as ReadonlyArray<{ + + readonly id: string; + ++ readonly credential: string; + + }>; + + + + const revokeResponse = yield* HttpClient.post("/api/auth/pairing-links/revoke", { + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam", (it) => { + assert.equal(response.environment.environmentId, testEnvironmentDescriptor.environmentId); + assert.equal(response.auth.policy, "desktop-managed-local"); + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam + Effect.scoped( + Effect.gen(function* () { + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam", (it) => { + + }).pipe(Effect.provide(NodeHttpServer.layerTest)), + + ); + + - it.effect("routes websocket rpc subscribeServerConfig streams snapshot then update", () => + +- it.effect("provider setup lets read-only clients observe installation but not change setup", () => + ++ it.effect("routes websocket rpc subscribeServerConfig streams snapshot then update", () => + Effect.gen(function* () { + +- let installStarts = 0; + +- let authCalls = 0; + +- yield* buildAppUnderTest({ + +- layers: { + +- providerInstanceRegistry: { + +- getInstance: (instanceId) => + +- Effect.succeed( + +- instanceId === providerSetupInstanceId ? providerSetupInstance : undefined, + +- ), + +- }, + +- antigravityInstallation: { + +- start: Effect.sync(() => { + +- installStarts += 1; + +- return providerSetupInstallState; + +- }), + +- changes: Stream.succeed(providerSetupInstallState), + +- }, + +- providerAuth: { + +- start: () => + +- Effect.sync(() => { + +- authCalls += 1; + +- return providerSetupAuthState; + +- }), + +- subscribe: () => + +- Stream.fromEffect( + +- Effect.sync(() => { + +- authCalls += 1; + +- return providerSetupAuthState; + +- }), + +- ), + +- }, + +- }, + +- }); + +- const token = yield* exchangeAccessToken(defaultDesktopBootstrapToken, { + +- scope: "orchestration:read", + +- }); + +- assert.equal(token.response.status, 200); + +- const ticketResponse = yield* HttpClient.post("/api/auth/websocket-ticket", { + +- headers: { authorization: `Bearer ${token.body.access_token ?? ""}` }, + +- }); + +- const { ticket } = yield* responseJsonEffect<{ readonly ticket: string }>(ticketResponse); + +- const wsUrl = `${yield* getWsServerUrl("/ws", { authenticated: false })}?wsTicket=${encodeURIComponent(ticket)}`; + +- yield* Effect.scoped( + +- withWsRpcClient(wsUrl, (client) => + +- Effect.gen(function* () { + +- const observed = yield* client[WS_METHODS.providerInstallSubscribe]({ + +- instanceId: providerSetupInstanceId, + +- }).pipe(Stream.runHead, Effect.map(Option.getOrThrow)); + +- assert.deepEqual(observed, providerSetupInstallState); + +- const errors = [ + +- yield* client[WS_METHODS.providerInstallStart]({ + +- instanceId: providerSetupInstanceId, + +- }).pipe(Effect.flip), + +- yield* client[WS_METHODS.providerAuthStart]({ + +- instanceId: providerSetupInstanceId, + +- }).pipe(Effect.flip), + +- yield* client[WS_METHODS.providerAuthSubscribe]({ + +- instanceId: providerSetupInstanceId, + +- }).pipe(Stream.runHead, Effect.flip), + +- ]; + +- for (const error of errors) { + +- assert.equal(error._tag, "EnvironmentAuthorizationError"); + +- if (error._tag === "EnvironmentAuthorizationError") { + +- assert.equal(error.requiredScope, "orchestration:operate"); + +- } + +- } + +- }), + +- ), + +- ); + +- assert.equal(installStarts, 0); + +- assert.equal(authCalls, 0); + +- }).pipe(Effect.provide(NodeHttpServer.layerTest)), + +- ); + +- + +- it.effect("provider setup binds private sign-in to the authenticated websocket session", () => + +- Effect.gen(function* () { + +- const flowId = "private-sign-in-flow"; + +- const callbackUrl = "http://127.0.0.1:51234/?state=test-state&code=test-code"; + +- const waiting: ProviderAuthState = { + +- ...providerSetupAuthState, + +- phase: "waiting", + +- flowId, + +- authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth?state=test-state", + +- expiresAt: "2026-09-02T00:05:00.000Z", + +- }; + +- const calls: Array<{ + +- readonly operation: string; + +- readonly instanceId: ProviderInstanceId; + +- readonly ownerSessionId: string; + +- }> = []; + +- const forwardedCallbacks: string[] = []; + +- const logoutInstances: ProviderInstanceId[] = []; + +- let flowOwner = ""; + +- yield* buildAppUnderTest({ + +- layers: { + +- providerAuth: { + +- start: (input, ownerSessionId) => + +- Effect.sync(() => { + +- flowOwner = ownerSessionId; + +- calls.push({ operation: "start", instanceId: input.instanceId, ownerSessionId }); + +- return waiting; + +- }), + +- subscribe: (input, ownerSessionId) => + +- Stream.fromEffect( + +- Effect.sync(() => { + +- calls.push({ + +- operation: "subscribe", + +- instanceId: input.instanceId, + +- ownerSessionId, + +- }); + +- return ownerSessionId === flowOwner + +- ? waiting + +- : { ...waiting, flowId: null, authorizationUrl: null, expiresAt: null }; + +- }), + +- ), + +- complete: (input, ownerSessionId) => + +- Effect.gen(function* () { + +- calls.push({ operation: "complete", instanceId: input.instanceId, ownerSessionId }); + +- if (ownerSessionId !== flowOwner) { + +- return yield* new ProviderSetupError({ + +- instanceId: input.instanceId, + +- operation: "complete", + +- detail: "This sign-in belongs to another client.", + +- }); + +- } + +- assert.equal(input.flowId, flowId); + +- forwardedCallbacks.push(input.callbackUrl); + +- return { ...waiting, phase: "verifying" as const, authorizationUrl: null }; + +- }), + +- cancel: (input, ownerSessionId) => + +- Effect.sync(() => { + +- assert.equal(input.flowId, flowId); + +- calls.push({ operation: "cancel", instanceId: input.instanceId, ownerSessionId }); + +- return { ...providerSetupAuthState, phase: "cancelled" as const, flowId }; + +- }), + +- logout: (input) => + +- Effect.sync(() => { + +- logoutInstances.push(input.instanceId); + +- return providerSetupAuthState; + +- }), + +- }, + +- }, + +- }); + +- const firstCookie = yield* getAuthenticatedSessionCookieHeader(); + +- const secondCookie = yield* getAuthenticatedSessionCookieHeader(); + +- const firstClients = yield* HttpClient.get("/api/auth/clients", { + +- headers: { cookie: firstCookie }, + +- }).pipe( + +- Effect.flatMap( + +- responseJsonEffect< + +- ReadonlyArray<{ readonly sessionId: string; readonly current: boolean }> + +- >, + +- ), + +- ); + +- const secondClients = yield* HttpClient.get("/api/auth/clients", { + +- headers: { cookie: secondCookie }, + +- }).pipe( + +- Effect.flatMap( + +- responseJsonEffect< + +- ReadonlyArray<{ readonly sessionId: string; readonly current: boolean }> + +- >, + +- ), + +- ); + +- const firstOwner = firstClients.find((session) => session.current)?.sessionId; + +- const secondOwner = secondClients.find((session) => session.current)?.sessionId; + +- assert.isString(firstOwner); + +- assert.isString(secondOwner); + +- assert.notEqual(firstOwner, secondOwner); + +- const baseWsUrl = yield* getWsServerUrl("/ws", { authenticated: false }); + +- const target = { + +- instanceId: providerSetupInstanceId, + +- ownerSessionId: "client-supplied-owner", + +- }; + +- yield* Effect.scoped( + +- withWsRpcClient(appendSessionCookieToWsUrl(baseWsUrl, firstCookie), (client) => + +- Effect.gen(function* () { + +- const started = yield* client[WS_METHODS.providerAuthStart](target); + +- assert.equal(started.flowId, flowId); + +- const ownState = yield* client[WS_METHODS.providerAuthSubscribe](target).pipe( + +- Stream.runHead, + +- Effect.map(Option.getOrThrow), + +- ); + +- assert.equal(ownState.authorizationUrl, waiting.authorizationUrl); + +- yield* Effect.scoped( + +- withWsRpcClient(appendSessionCookieToWsUrl(baseWsUrl, secondCookie), (otherClient) => + +- Effect.gen(function* () { + +- const otherState = yield* otherClient[WS_METHODS.providerAuthSubscribe]( + +- target, + +- ).pipe(Stream.runHead, Effect.map(Option.getOrThrow)); + +- assert.isNull(otherState.authorizationUrl); + +- assert.isNull(otherState.flowId); + +- const forged = { ...target, ownerSessionId: firstOwner, flowId, callbackUrl }; + +- const denied = yield* otherClient[WS_METHODS.providerAuthComplete](forged).pipe( + +- Effect.flip, + +- ); + +- assert.equal(denied._tag, "ProviderSetupError"); + +- assert.deepEqual(forwardedCallbacks, []); + +- }), + +- ), + +- ); + +- const completed = yield* client[WS_METHODS.providerAuthComplete]({ + +- ...target, + +- flowId, + +- callbackUrl, + +- }); + +- assert.equal(completed.phase, "verifying"); + +- const cancelled = yield* client[WS_METHODS.providerAuthCancel]({ ...target, flowId }); + +- assert.equal(cancelled.phase, "cancelled"); + +- const signedOut = yield* client[WS_METHODS.providerAuthLogout](target); + +- assert.equal(signedOut.phase, "idle"); + +- }), + +- ), + +- ); + +- assert.deepEqual(forwardedCallbacks, [callbackUrl]); + +- assert.deepEqual(logoutInstances, [providerSetupInstanceId]); + +- assert.isTrue(calls.every((call) => call.instanceId === providerSetupInstanceId)); + +- assert.deepEqual( + +- calls.map((call) => call.ownerSessionId), + +- [firstOwner, firstOwner, secondOwner, secondOwner, firstOwner, firstOwner], + +- ); + +- }).pipe(Effect.provide(NodeHttpServer.layerTest)), + +- ); + +- + +- it.effect( + +- "provider setup routes installation operations and returns only safe typed errors", + +- () => + +- Effect.gen(function* () { + +- const calls: string[] = []; + +- let state = providerSetupInstallState; + +- yield* buildAppUnderTest({ + +- layers: { + +- providerInstanceRegistry: { + +- getInstance: (instanceId) => + +- Effect.succeed( + +- instanceId === providerSetupInstanceId ? providerSetupInstance : undefined, + +- ), + +- }, + +- antigravityInstallation: { + +- start: Effect.sync(() => { + +- calls.push("start"); + +- return state; + +- }), + +- cancel: (operationId) => + +- Effect.gen(function* () { + +- calls.push(`cancel:${operationId}`); + +- if (operationId !== state.operationId) { + +- return yield* new AntigravityInstallationError({ + +- operation: "cancel", + +- detail: "This installation is no longer running.", + +- cause: new Error("Private download diagnostics."), + +- }); + +- } + +- state = { ...state, phase: "cancelled" }; + +- return state; + +- }), + +- changes: Stream.fromEffect(Effect.sync(() => state)), + +- }, + +- }, + +- }); + +- const wsUrl = yield* getWsServerUrl("/ws"); + +- yield* Effect.scoped( + +- withWsRpcClient(wsUrl, (client) => + +- Effect.gen(function* () { + +- const unknownInstance = yield* client[WS_METHODS.providerInstallStart]({ + +- instanceId: ProviderInstanceId.make("unknown-instance"), + +- }).pipe(Effect.flip); + +- assert.equal(unknownInstance._tag, "ProviderSetupError"); + +- assert.deepEqual(calls, []); + +- const started = yield* client[WS_METHODS.providerInstallStart]({ + +- instanceId: providerSetupInstanceId, + +- }); + +- assert.deepEqual(started, providerSetupInstallState); + +- const stale = yield* client[WS_METHODS.providerInstallCancel]({ + +- instanceId: providerSetupInstanceId, + +- operationId: "old-operation", + +- }).pipe(Effect.flip); + +- assert.equal(stale._tag, "ProviderSetupError"); + +- if (stale._tag === "ProviderSetupError") { + +- assert.equal(stale.instanceId, providerSetupInstanceId); + +- assert.equal(stale.operation, "cancel"); + +- assert.equal(stale.detail, "This installation is no longer running."); + +- assert.notProperty(stale, "cause"); + +- } + +- const cancelled = yield* client[WS_METHODS.providerInstallCancel]({ + +- instanceId: providerSetupInstanceId, + +- operationId: "install-operation", + +- }); + +- assert.equal(cancelled.phase, "cancelled"); + +- const observed = yield* client[WS_METHODS.providerInstallSubscribe]({ + +- instanceId: providerSetupInstanceId, + +- }).pipe(Stream.runHead, Effect.map(Option.getOrThrow)); + +- assert.deepEqual(observed, cancelled); + +- }), + +- ), + +- ); + +- assert.deepEqual(calls, ["start", "cancel:old-operation", "cancel:install-operation"]); + +- }).pipe(Effect.provide(NodeHttpServer.layerTest)), + +- ); + +- + +- it.effect("routes websocket rpc subscribeServerConfig streams snapshot then update", () => + +- Effect.gen(function* () { + - const path = yield* Path.Path; + const providers = [ + { + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam + ); + + - it.effect("records thread analytics only after a client command succeeds", () => + -+ it.effect("routes websocket rpc projects.writeFile errors", () => + - Effect.gen(function* () { + +- Effect.gen(function* () { + - const effects: string[] = []; + - const analyticsProperties: Array> | undefined> = []; + - const failedCommandId = CommandId.make("cmd-thread-create-failed"); + -+ const fs = yield* FileSystem.FileSystem; + -+ const workspaceDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-ws-project-write-" }); + -+ + -+ yield* buildAppUnderTest(); + -+ + -+ const wsUrl = yield* getWsServerUrl("/ws"); + -+ const result = yield* Effect.scoped( + -+ withWsRpcClient(wsUrl, (client) => + -+ client[WS_METHODS.projectsWriteFile]({ + -+ cwd: workspaceDir, + -+ relativePath: "../escape.txt", + -+ contents: "nope", + -+ }), + -+ ).pipe(Effect.result), + -+ ); + -+ + -+ if (result._tag !== "Failure" || result.failure._tag !== "ProjectWriteFileError") { + -+ assert.fail("Expected a ProjectWriteFileError"); + -+ } + -+ const writeError = result.failure; + -+ assert.equal( + -+ writeError.message, + -+ `Failed to write workspace file '../escape.txt' in '${workspaceDir}'.`, + -+ ); + -+ assert.equal(writeError.cwd, workspaceDir); + -+ assert.equal(writeError.relativePath, "../escape.txt"); + -+ assert.equal(writeError.failure, "workspace_path_outside_root"); + -+ assert.isDefined(writeError.cause); + -+ assert.notProperty(writeError, "contents"); + -+ }).pipe(Effect.provide(NodeHttpServer.layerTest)), + -+ ); + - + -+ it.effect("routes websocket rpc shell.openInEditor", () => + -+ Effect.gen(function* () { + -+ let openedInput: { cwd: string; editor: EditorId } | null = null; + - yield* buildAppUnderTest({ + - layers: { + +- + +- yield* buildAppUnderTest({ + +- layers: { + - analyticsService: { + - record: (event, properties) => + -+ externalLauncher: { + -+ launchEditor: (input) => + - Effect.sync(() => { + +- Effect.sync(() => { + - effects.push(`analytics:${event}`); + - analyticsProperties.push(properties); + -+ openedInput = input; + - }), + - }, + +- }), + +- }, + - orchestrationEngine: { + - dispatch: (command) => + - Effect.sync(() => effects.push(`dispatch:${command.commandId}`)).pipe( + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam + - ), + - ), + - }, + - }, + - }); + - + +- }, + +- }); + +- + - const createThreadCommand = (commandId: CommandId, threadId: ThreadId) => + - ({ + - type: "thread.create", + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam + - const wsUrl = yield* getWsServerUrl( + - "/ws?clientSurface=mobile&clientAppVersion=1.2.3&clientDeviceType=phone&clientOs=iOS&clientOsMajorVersion=18&clientDeviceModel=iPhone+15+Pro&connectionMethod=relay", + - ); + -+ const wsUrl = yield* getWsServerUrl("/ws"); + - yield* Effect.scoped( + - withWsRpcClient(wsUrl, (client) => + +- yield* Effect.scoped( + +- withWsRpcClient(wsUrl, (client) => + - Effect.gen(function* () { + - const failed = yield* client[ORCHESTRATION_WS_METHODS.dispatchCommand]( + - createThreadCommand(failedCommandId, ThreadId.make("thread-create-failed")), + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam + - ); + - + - assert.equal(succeeded.sequence, 1); + -+ client[WS_METHODS.shellOpenInEditor]({ + -+ cwd: "/tmp/project", + -+ editor: "cursor", + - }), + - ), + - ); + - + +- }), + +- ), + +- ); + +- + - assert.deepEqual(effects, [ + - "analytics:client.connected", + - "dispatch:cmd-thread-create-failed", + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam + - connectionMethod: "relay", + - }, + - ]); + -+ assert.deepEqual(openedInput, { cwd: "/tmp/project", editor: "cursor" }); + - }).pipe(Effect.provide(NodeHttpServer.layerTest)), + - ); + - + +- }).pipe(Effect.provide(NodeHttpServer.layerTest)), + +- ); + +- + - it.effect("keeps telemetry separate for simultaneous clients", () => + -+ it.effect("routes websocket rpc shell.openInEditor errors", () => + - Effect.gen(function* () { + +- Effect.gen(function* () { + - const analyticsEvents: Array<{ + - event: string; + - properties: Readonly> | undefined; + - }> = []; + - + -+ const externalLauncherError = new ExternalLauncherCommandNotFoundError({ + -+ editor: "cursor", + -+ command: "cursor", + -+ }); + - yield* buildAppUnderTest({ + - layers: { + +- yield* buildAppUnderTest({ + +- layers: { + - analyticsService: { + - record: (event, properties) => + - Effect.sync(() => analyticsEvents.push({ event, properties })), + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam + - }).pipe(Effect.provide(NodeHttpServer.layerTest)), + - ); + - + -- it.effect("routes websocket rpc projects.writeFile errors", () => + -- Effect.gen(function* () { + -- const fs = yield* FileSystem.FileSystem; + -- const workspaceDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-ws-project-write-" }); + -- + -- yield* buildAppUnderTest(); + -- + -- const wsUrl = yield* getWsServerUrl("/ws"); + -- const result = yield* Effect.scoped( + -- withWsRpcClient(wsUrl, (client) => + -- client[WS_METHODS.projectsWriteFile]({ + -- cwd: workspaceDir, + -- relativePath: "../escape.txt", + -- contents: "nope", + -- }), + -- ).pipe(Effect.result), + -- ); + -- + -- if (result._tag !== "Failure" || result.failure._tag !== "ProjectWriteFileError") { + -- assert.fail("Expected a ProjectWriteFileError"); + -- } + -- const writeError = result.failure; + -- assert.equal( + -- writeError.message, + -- `Failed to write workspace file '../escape.txt' in '${workspaceDir}'.`, + -- ); + -- assert.equal(writeError.cwd, workspaceDir); + -- assert.equal(writeError.relativePath, "../escape.txt"); + -- assert.equal(writeError.failure, "workspace_path_outside_root"); + -- assert.isDefined(writeError.cause); + -- assert.notProperty(writeError, "contents"); + -- }).pipe(Effect.provide(NodeHttpServer.layerTest)), + -- ); + -- + -- it.effect("routes websocket rpc shell.openInEditor", () => + -- Effect.gen(function* () { + -- let openedInput: { cwd: string; editor: EditorId } | null = null; + -- yield* buildAppUnderTest({ + -- layers: { + -- externalLauncher: { + -- launchEditor: (input) => + -- Effect.sync(() => { + -- openedInput = input; + -- }), + -- }, + -- }, + -- }); + -- + -- const wsUrl = yield* getWsServerUrl("/ws"); + -- yield* Effect.scoped( + -- withWsRpcClient(wsUrl, (client) => + -- client[WS_METHODS.shellOpenInEditor]({ + -- cwd: "/tmp/project", + -- editor: "cursor", + -- }), + -- ), + -- ); + -- + -- assert.deepEqual(openedInput, { cwd: "/tmp/project", editor: "cursor" }); + -- }).pipe(Effect.provide(NodeHttpServer.layerTest)), + -- ); + -- + -- it.effect("routes websocket rpc shell.openInEditor errors", () => + -- Effect.gen(function* () { + -- const externalLauncherError = new ExternalLauncherCommandNotFoundError({ + -- editor: "cursor", + -- command: "cursor", + -- }); + -- yield* buildAppUnderTest({ + -- layers: { + -- externalLauncher: { + -- launchEditor: () => Effect.fail(externalLauncherError), + -+ externalLauncher: { + -+ launchEditor: () => Effect.fail(externalLauncherError), + - }, + - }, + - }); + + it.effect("routes websocket rpc projects.writeFile errors", () => + + Effect.gen(function* () { + + const fs = yield* FileSystem.FileSystem; + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam", (it) => { + }).pipe(Effect.provide(NodeHttpServer.layerTest)), + ); + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam + Effect.gen(function* () { + const projectionError = new PersistenceSqlError({ + operation: "ProjectionSnapshotQuery.getShellSnapshot:test", + +@@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam", (it) => { + + projectionSnapshotQuery: { + + getThreadDetailSnapshot: () => + + Effect.gen(function* () { + ++ yield* Effect.sleep("25 millis"); + + yield* PubSub.publish(liveEvents, messageEvent); + + return Option.some({ snapshotSequence: 1, thread }); + + }), + +@@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam", (it) => { + + withWsRpcClient(wsUrl, (client) => + + client[ORCHESTRATION_WS_METHODS.subscribeThread]({ + + threadId: defaultThreadId, + +- requestCompletionMarker: true, + +- }).pipe( + +- Stream.takeUntil((item) => item.kind === "synchronized"), + +- Stream.runCollect, + +- ), + ++ }).pipe(Stream.take(2), Stream.runCollect), + + ), + +- ); + ++ ).pipe(Effect.timeout("2 seconds")); + + + + assert.equal(items[0]?.kind, "snapshot"); + + assert.equal(items[1]?.kind, "event"); + + assert.equal(items[1]?.kind === "event" ? items[1].event.sequence : null, 2); + +- assert.equal(items[2]?.kind, "synchronized"); + +- }).pipe(Effect.provide(NodeHttpServer.layerTest)), + ++ }).pipe(Effect.provide(NodeHttpServer.layerTest), TestClock.withLive), + + ); + + + + it.effect("coalesces buffered live tool updates to the latest state", () => + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam", (it) => { + pr: null, + }), + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam + - }).pipe(Effect.provide(NodeHttpServer.layerTest)), + - ); + - + - it.effect("records setup-script failures without aborting bootstrap turn start", () => + +- it.effect("records setup-script failures without aborting bootstrap turn start", () => + ++ it.effect("records setup-script failures without aborting bootstrap turn start", () => + Effect.gen(function* () { + const dispatchedCommands: Array = []; + + const createWorktree = vi.fn( + @@ apps/server/src/server.test.ts: it.layer(NodeServices.layer)("server router seam", (it) => { + it.effect("cleans up created bootstrap threads when worktree creation defects", () => + Effect.gen(function* () { + @@ apps/server/src/ws.ts: import { + ProjectSearchEntriesError, + ProjectWriteFileError, + - ProviderUploadFeedbackError, + +- ProviderSetupError, + RelayClientInstallFailedError, + type RelayClientInstallProgressEvent, + - ServerSelfUpdateError, + @@ apps/server/src/ws.ts: import { + projectThreadDetailSnapshot, + } from "./orchestration/ActivityPayloadProjection.ts"; + -import { makeThreadLiveEventCoalescer } from "./orchestration/ThreadLiveEventCoalescer.ts"; + +-import { makeLiveStreamBudget, type RetainedLiveItem } from "./orchestration/LiveStreamBudget.ts"; + -import { + - cleanupFailedUploadedAttachments, + - normalizeDispatchCommand, + @@ apps/server/src/ws.ts: import { + import * as ProviderRegistry from "./provider/Services/ProviderRegistry.ts"; + -import * as ProviderService from "./provider/Services/ProviderService.ts"; + import * as ProviderMaintenanceRunner from "./provider/providerMaintenanceRunner.ts"; + +-import { ProviderAuthService } from "./provider/Services/ProviderAuthService.ts"; + +-import { ProviderInstanceRegistry } from "./provider/Services/ProviderInstanceRegistry.ts"; + +-import { makeProviderInstallation } from "./provider/providerInstallation.ts"; + import * as ServerSelfUpdate from "./cloud/selfUpdate.ts"; + import * as ServerLifecycleEvents from "./serverLifecycleEvents.ts"; + + import * as ServerRuntimeStartup from "./serverRuntimeStartup.ts"; + @@ apps/server/src/ws.ts: import * as TerminalManager from "./terminal/Manager.ts"; + import * as PreviewAutomationBroker from "./mcp/PreviewAutomationBroker.ts"; + import * as PreviewManager from "./preview/Manager.ts"; + @@ apps/server/src/ws.ts: import * as GitWorkflowService from "./git/GitWorkflowSer + import * as ProcessResourceMonitor from "./diagnostics/ProcessResourceMonitor.ts"; + import * as ResourceTelemetry from "./resourceTelemetry/ResourceTelemetry.ts"; + -import * as AnalyticsService from "./telemetry/AnalyticsService.ts"; + +-import * as UsageLimitSources from "./usage/UsageLimitSources.ts"; + import * as UsageService from "./usage/UsageService.ts"; + import * as TraceDiagnostics from "./diagnostics/TraceDiagnostics.ts"; + import * as PullRequestService from "./pullRequest/PullRequestService.ts"; + @@ apps/server/src/ws.ts: function toAuthAccessStreamEvent( + - const checkpointDiffQuery = yield* CheckpointDiffQuery.CheckpointDiffQuery; + - const keybindings = yield* Keybindings.Keybindings; + - const environmentTheme = yield* EnvironmentTheme.EnvironmentThemeService; + +- const usageLimitSources = yield* UsageLimitSources.UsageLimitSources; + - const externalLauncher = yield* ExternalLauncher.ExternalLauncher; + - const remoteOpenTargets = yield* RemoteOpenTargets.RemoteOpenTargets; + - const gitWorkflow = yield* GitWorkflowService.GitWorkflowService; + @@ apps/server/src/ws.ts: function toAuthAccessStreamEvent( + - const providerRegistry = yield* ProviderRegistry.ProviderRegistry; + - const providerService = yield* ProviderService.ProviderService; + - const providerMaintenanceRunner = yield* ProviderMaintenanceRunner.ProviderMaintenanceRunner; + +- const providerAuth = yield* ProviderAuthService; + +- const providerInstances = yield* ProviderInstanceRegistry; + +- const providerInstallation = yield* makeProviderInstallation(); + - const serverUpdate = yield* ServerSelfUpdate.ServerSelfUpdate; + - const config = yield* ServerConfig.ServerConfig; + - const lifecycleEvents = yield* ServerLifecycleEvents.ServerLifecycleEvents; + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + if (shouldStopSessionAfterCommand) { + yield* Effect.gen(function* () { + const stopCommand = yield* normalizeDispatchCommand({ + +@@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + + // Attach live delivery before reading either replay or snapshot state. + + // Otherwise an event published while the snapshot is loading is lost. + + const liveBuffer = yield* makeThreadLiveEventCoalescer(); + +- yield* Effect.forkScoped( + +- liveStream.pipe( + +- Stream.runForEachArray(liveBuffer.offerAll), + +- Effect.raceFirst(liveBuffer.failed), + +- Effect.catchTags({ OrchestrationGetSnapshotError: () => Effect.void }), + +- ), + +- { startImmediately: true }, + +- ); + ++ yield* Effect.forkScoped(liveStream.pipe(Stream.runForEach(liveBuffer.offer))); + + const bufferedLiveStream = liveBuffer.stream; + + let replayOnMissingSnapshot: typeof bufferedLiveStream | undefined; + + + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + }), + { "rpc.aggregate": "orchestration" }, + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + - observeRpcEffect(WS_METHODS.serverProbe, Effect.succeed({}), { + - "rpc.aggregate": "server", + - }), + +- [WS_METHODS.serverGetConfig]: (_input) => + +- observeRpcEffect(WS_METHODS.serverGetConfig, loadServerConfig, { + +- "rpc.aggregate": "server", + +- }), + +- [WS_METHODS.serverRefreshProviders]: (input) => + + [ORCHESTRATION_V2_WS_METHODS.dispatchCommand]: (command) => + -+ observeRpcEffect( + + observeRpcEffect( + +- WS_METHODS.serverRefreshProviders, + +- Effect.gen(function* () { + +- // An untargeted refresh is "re-read everything's status", which + +- // includes quota from configured usage-limit sources. Awaited, + +- // not forked: the RPC scope closes on return and would + +- // interrupt a fork before the hub answered. + +- if (input.instanceId === undefined) { + +- yield* usageLimitSources.refresh; + +- } + +- let providers = yield* input.cwd !== undefined && input.instanceId !== undefined + +- ? providerRegistry.refreshWorkspaceSnapshot({ + +- instanceId: input.instanceId, + +- cwd: input.cwd, + +- }) + +- : input.instanceId !== undefined + +- ? providerRegistry.refreshInstance(input.instanceId) + +- : providerRegistry.refresh(); + +- if (input.refreshModels) { + +- const instances = yield* providerInstances.listInstances; + +- for (const instance of instances) { + +- if ( + +- !instance.refreshModels || + +- (input.instanceId !== undefined && input.instanceId !== instance.instanceId) || + +- !providers.some( + +- (provider) => + +- provider.instanceId === instance.instanceId && + +- provider.enabled && + +- provider.installed, + +- ) + +- ) + +- continue; + +- yield* instance.refreshModels().pipe( + +- Effect.mapError( + +- (error) => + +- new ProviderSetupError({ + +- instanceId: instance.instanceId, + +- operation: "refresh-models", + +- detail: error.detail, + +- }), + +- ), + +- ); + +- providers = yield* providerRegistry.refreshInstance(instance.instanceId); + +- } + +- } + +- return { providers }; + +- }), + +- { "rpc.aggregate": "server" }, + + ORCHESTRATION_V2_WS_METHODS.dispatchCommand, + + orchestrationV2.dispatch(command).pipe( + + Effect.map((result) => ({ sequence: result.sequence })), + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + + ), + + ), + + { "rpc.aggregate": "orchestrationV2" }, + -+ ), + + ), + +- [WS_METHODS.providerUploadFeedback]: (input) => + + [ORCHESTRATION_V2_WS_METHODS.getThreadProjection]: (input) => + -+ observeRpcEffect( + + observeRpcEffect( + +- WS_METHODS.providerUploadFeedback, + +- providerService.uploadFeedback(input).pipe( + + ORCHESTRATION_V2_WS_METHODS.getThreadProjection, + + orchestrationV2.getThreadProjection(input.threadId).pipe( + -+ Effect.mapError( + -+ (cause) => + + Effect.mapError( + + (cause) => + +- new ProviderUploadFeedbackError({ + + new OrchestrationV2GetThreadProjectionError({ + -+ threadId: input.threadId, + + threadId: input.threadId, + + message: `Failed to load orchestration V2 thread ${input.threadId}`, + -+ cause, + -+ }), + -+ ), + -+ ), + + cause, + + }), + + ), + + ), + +- { "rpc.aggregate": "provider" }, + + { "rpc.aggregate": "orchestrationV2" }, + -+ ), + + ), + +- [WS_METHODS.serverUpdateProvider]: (input) => + +- observeRpcEffect( + +- WS_METHODS.serverUpdateProvider, + +- providerMaintenanceRunner.updateProvider(input), + +- { + +- "rpc.aggregate": "server", + +- }, + +- ), + +- [WS_METHODS.providerConsumeResetCredit]: (input) => + +- observeRpcEffect( + +- WS_METHODS.providerConsumeResetCredit, + + [ORCHESTRATION_V2_WS_METHODS.subscribeThread]: (input) => + + observeRpcStreamEffect( + + ORCHESTRATION_V2_WS_METHODS.subscribeThread, + -+ Effect.gen(function* () { + + Effect.gen(function* () { + +- const instance = yield* providerInstances.getInstance(input.instanceId); + +- // A disabled instance must not spend anything on its account. + +- if (instance === undefined || !instance.enabled) { + +- return yield* new ProviderSetupError({ + +- instanceId: input.instanceId, + +- operation: "consume-reset-credit", + +- detail: instance ? "This provider is disabled." : "Provider instance not found.", + +- }); + +- } + +- if (instance.consumeResetCredit === undefined) { + +- return yield* new ProviderSetupError({ + +- instanceId: input.instanceId, + +- operation: "consume-reset-credit", + +- detail: "This provider does not bank reset credits.", + +- }); + +- } + +- const outcome = yield* instance.consumeResetCredit().pipe( + + const projection = yield* orchestrationV2.getThreadProjection(input.threadId).pipe( + -+ Effect.mapError( + + Effect.mapError( + +- (error) => + +- new ProviderSetupError({ + +- instanceId: input.instanceId, + +- operation: "consume-reset-credit", + +- detail: error.detail, + +- cause: error, + + (cause) => + + new OrchestrationV2GetThreadProjectionError({ + + threadId: input.threadId, + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + + threadId: input.threadId, + + message: `Failed while streaming orchestration V2 thread ${input.threadId}`, + + cause, + -+ }), + -+ ), + -+ ); + + }), + + ), + + ); + +- return { outcome }; + + + + return Stream.concat( + + Stream.make({ + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + + }), + + liveStream, + + ); + -+ }), + + }), + +- { "rpc.aggregate": "provider" }, + +- ), + +- [WS_METHODS.providerAuthStart]: (input) => + +- observeRpcEffect( + +- WS_METHODS.providerAuthStart, + +- providerAuth.start(input, currentSessionId), + +- { "rpc.aggregate": "provider" }, + + { "rpc.aggregate": "orchestrationV2" }, + -+ ), + - [WS_METHODS.serverGetConfig]: (_input) => + - observeRpcEffect(WS_METHODS.serverGetConfig, loadServerConfig, { + - "rpc.aggregate": "server", + -@@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + - ).pipe(Effect.map((providers) => ({ providers }))), + - { "rpc.aggregate": "server" }, + ), + -- [WS_METHODS.providerUploadFeedback]: (input) => + -- observeRpcEffect( + -- WS_METHODS.providerUploadFeedback, + -- providerService.uploadFeedback(input).pipe( + -- Effect.mapError( + -- (cause) => + -- new ProviderUploadFeedbackError({ + -- threadId: input.threadId, + -- cause, + -- }), + -- ), + -- ), + +- [WS_METHODS.providerAuthComplete]: (input) => + ++ [WS_METHODS.serverGetConfig]: (_input) => + ++ observeRpcEffect(WS_METHODS.serverGetConfig, loadServerConfig, { + ++ "rpc.aggregate": "server", + ++ }), + ++ [WS_METHODS.serverRefreshProviders]: (input) => + + observeRpcEffect( + +- WS_METHODS.providerAuthComplete, + +- providerAuth.complete(input, currentSessionId), + - { "rpc.aggregate": "provider" }, + -- ), + - [WS_METHODS.serverUpdateProvider]: (input) => + ++ WS_METHODS.serverRefreshProviders, + ++ (input.cwd !== undefined && input.instanceId !== undefined + ++ ? providerRegistry.refreshWorkspaceSnapshot({ + ++ instanceId: input.instanceId, + ++ cwd: input.cwd, + ++ }) + ++ : input.instanceId !== undefined + ++ ? providerRegistry.refreshInstance(input.instanceId) + ++ : providerRegistry.refresh() + ++ ).pipe(Effect.map((providers) => ({ providers }))), + ++ { "rpc.aggregate": "server" }, + + ), + +- [WS_METHODS.providerAuthCancel]: (input) => + ++ [WS_METHODS.serverUpdateProvider]: (input) => + observeRpcEffect( + - WS_METHODS.serverUpdateProvider, + -@@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + - }, + +- WS_METHODS.providerAuthCancel, + +- providerAuth.cancel(input, currentSessionId), + +- { "rpc.aggregate": "provider" }, + +- ), + +- [WS_METHODS.providerAuthLogout]: (input) => + +- observeRpcEffect(WS_METHODS.providerAuthLogout, providerAuth.logout(input), { + +- "rpc.aggregate": "provider", + +- }), + +- [WS_METHODS.providerAuthSubscribe]: (input) => + +- observeRpcStream( + +- WS_METHODS.providerAuthSubscribe, + +- providerAuth.subscribe(input, currentSessionId), + +- { "rpc.aggregate": "provider" }, + +- ), + +- [WS_METHODS.providerInstallStart]: (input) => + +- observeRpcEffect(WS_METHODS.providerInstallStart, providerInstallation.start(input), { + +- "rpc.aggregate": "provider", + +- }), + +- [WS_METHODS.providerInstallCancel]: (input) => + +- observeRpcEffect(WS_METHODS.providerInstallCancel, providerInstallation.cancel(input), { + +- "rpc.aggregate": "provider", + +- }), + +- [WS_METHODS.providerInstallSubscribe]: (input) => + +- observeRpcStream( + +- WS_METHODS.providerInstallSubscribe, + +- providerInstallation.subscribe(input), + +- { "rpc.aggregate": "provider" }, + ++ WS_METHODS.serverUpdateProvider, + ++ providerMaintenanceRunner.updateProvider(input), + ++ { + ++ "rpc.aggregate": "server", + ++ }, + ), + +- [WS_METHODS.providerInstallRemove]: (input) => + +- observeRpcEffect(WS_METHODS.providerInstallRemove, providerInstallation.remove(input), { + +- "rpc.aggregate": "provider", + +- }), + [WS_METHODS.serverUpdateServer]: (input) => + - observeRpcEffect(WS_METHODS.serverUpdateServer, serverUpdate.update(input), { + + observeRpcEffect(WS_METHODS.serverUpdateServer, serverSelfUpdate.update(input), { + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + { "rpc.aggregate": "server" }, + ), + [WS_METHODS.serverUpsertKeybinding]: (rule) => + +@@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + + observeRpcEffect(WS_METHODS.serverGetUsageSummary, usage.readSummary(input), { + + "rpc.aggregate": "server", + + }), + +- [WS_METHODS.serverRefreshUsageRates]: (_input) => + +- observeRpcEffect(WS_METHODS.serverRefreshUsageRates, usage.refreshRates, { + +- "rpc.aggregate": "server", + +- }), + + [WS_METHODS.serverRetryResourceTelemetry]: (_input) => + + observeRpcEffect(WS_METHODS.serverRetryResourceTelemetry, resourceTelemetry.retry, { + + "rpc.aggregate": "server", + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + observeRpcEffect(WS_METHODS.pullRequestsListStats, pullRequests.listStats(input), { + "rpc.aggregate": "pull-requests", + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + [WS_METHODS.pullRequestsDetail]: (input) => + observeRpcEffect(WS_METHODS.pullRequestsDetail, pullRequests.detail(input), { + "rpc.aggregate": "pull-requests", + +@@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + + pullRequests.requestReviewers(input), + + { "rpc.aggregate": "pull-requests" }, + + ), + +- [WS_METHODS.pullRequestsLabelCandidates]: (input) => + +- observeRpcEffect( + +- WS_METHODS.pullRequestsLabelCandidates, + +- pullRequests.labelCandidates(input), + +- { "rpc.aggregate": "pull-requests" }, + +- ), + +- [WS_METHODS.pullRequestsSetLabels]: (input) => + +- observeRpcEffect(WS_METHODS.pullRequestsSetLabels, pullRequests.setLabels(input), { + +- "rpc.aggregate": "pull-requests", + +- }), + + [WS_METHODS.sourceControlLookupRepository]: (input) => + + observeRpcEffect( + + WS_METHODS.sourceControlLookupRepository, + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + ), + { "rpc.aggregate": "workspace" }, + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + [WS_METHODS.assetsCreateUrl]: (input) => + observeRpcEffect( + WS_METHODS.assetsCreateUrl, + + Effect.gen(function* () { + +- if ( + +- input.resource._tag === "attachment" || + +- input.resource._tag === "native-app-icon" + +- ) { + ++ if (input.resource._tag === "attachment") { + + return yield* issueAssetUrl({ resource: input.resource }); + + } + + if (input.resource._tag === "project-favicon") { + +@@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + + })), + + ) + + : Stream.empty; + +- // Same gate as themes: an older client dies on an unknown event. + +- const usageLimitSourceUpdates = + +- input.usageLimitSources === true + +- ? usageLimitSources.streamChanges.pipe( + +- Stream.map((sources) => ({ + +- version: 1 as const, + +- type: "usageLimitSourcesUpdated" as const, + +- payload: { sources }, + +- })), + +- ) + +- : Stream.empty; + + const settingsUpdates = serverSettings.streamChanges.pipe( + + Stream.map((settings) => ServerSettings.redactServerSettingsForClient(settings)), + + Stream.map((settings) => ({ + +@@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + + keybindingsUpdates, + + Stream.merge( + + providerStatuses, + +- Stream.merge( + +- settingsUpdates, + +- Stream.merge(environmentThemeUpdates, usageLimitSourceUpdates), + +- ), + ++ Stream.merge(settingsUpdates, environmentThemeUpdates), + + ), + + ); + + + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + export const websocketRpcRouteLayer = Layer.unwrap( + Effect.gen(function* () { + @@ packages/contracts/src/ipc.ts: import type { + OrchestrationThreadStreamItem, + } from "./orchestration.ts"; + -import { EnvironmentId } from "./baseSchemas.ts"; + +-import { BrowserProfileId } from "./browserProfile.ts"; + + import type { + +- BrowserImportResult, + +- BrowserImportSource, + +- BrowserImportSourceId, + +-} from "./browserImport.ts"; + -import { AuthAccessTokenResult, AuthSessionState, AuthWebSocketTicketResult } from "./auth.ts"; + -import { AdvertisedEndpoint } from "./remoteAccess.ts"; + -import { ExecutionEnvironmentDescriptor } from "./environment.ts"; + -import type { ClientSettings, QuitConfirmationMode } from "./settings.ts"; + -import type { EditorId } from "./editor.ts"; + - import type { + +-import type { + - SourceControlCloneRepositoryInput, + - SourceControlCloneRepositoryResult, + - SourceControlPublishRepositoryInput, + @@ packages/contracts/src/ipc.ts: import type { + + export interface ContextMenuItem { + id: T; + +@@ packages/contracts/src/ipc.ts: export const PreviewAnnotationSubmissionSchema: Schema.Codec = + + Schema.Struct({ + + annotation: PreviewAnnotationPayloadSchema, + + submission: PreviewAnnotationSubmissionSchema, + +- screenshotFailed: Schema.optionalKey(Schema.Boolean), + + }); + + + + export const DesktopPreviewTabInputSchema = Schema.Struct({ + +@@ packages/contracts/src/ipc.ts: export const DesktopPreviewNavigateInputSchema = Schema.Struct({ + + + + export const DesktopPreviewConfigInputSchema = Schema.Struct({ + + environmentId: EnvironmentId, + +- /** + +- * Browser profile the partition is derived from. Derivation stays in main: + +- * `will-attach-webview` only prefix-checks the partition string, so a + +- * renderer-supplied partition could attach to a session that never had the + +- * UA rewrite or permission handlers installed. + +- */ + +- profileId: Schema.optional(BrowserProfileId), + +-}); + +- + +-export const DesktopPreviewClearDataInputSchema = Schema.Struct({ + +- environmentId: EnvironmentId, + +- /** Omit to clear every profile; otherwise only this profile's partition. */ + +- profileId: Schema.optional(BrowserProfileId), + + }); + + + + export const DesktopPreviewSetColorSchemeInputSchema = Schema.Struct({ + +@@ packages/contracts/src/ipc.ts: export interface DesktopBridge { + + setConnectionCatalog?: (catalog: string) => Promise; + + clearConnectionCatalog?: () => Promise; + + discoverSshHosts: () => Promise; + +- /** Resolves a suggested SSH alias before populating the connection form. */ + +- resolveSshHost: (alias: string) => Promise; + + ensureSshEnvironment: ( + + target: DesktopSshEnvironmentTarget, + + options?: { issuePairingToken?: boolean }, + @@ packages/contracts/src/ipc.ts: export interface DesktopBridge { + position?: { x: number; y: number }, + ) => Promise; + @@ packages/contracts/src/ipc.ts: export interface DesktopBridge { + getWindowFullscreenState: () => boolean; + onWindowFullscreenStateChange: (listener: (fullscreen: boolean) => void) => () => void; + getUpdateState: () => Promise; + +@@ packages/contracts/src/ipc.ts: export interface DesktopPreviewBridge { + + /** Open the guest webview's DevTools (detached). */ + + openDevTools: (tabId: string) => Promise; + + /** Drop cookies + storage data for the preview partition (all tabs). */ + +- clearCookies: (environmentId: EnvironmentId, profileId?: string) => Promise; + ++ clearCookies: () => Promise; + + /** Drop the HTTP cache for the preview partition (all tabs). */ + +- clearCache: (environmentId: EnvironmentId, profileId?: string) => Promise; + ++ clearCache: () => Promise; + + /** + + * One-shot config for mounting a preview ``. Replaces three + + * earlier round-trip calls (`getBrowserPartition`, `getWebviewPreferences`, + + * `getPickPreloadPath`) so adding a new field here only requires touching + + * the contract + main, not the renderer's mount logic. + + */ + +- getPreviewConfig: ( + +- environmentId: EnvironmentId, + +- profileId?: string, + +- ) => Promise; + +- /** Browsers on this machine whose cookies can be imported. */ + +- listBrowserImportSources: () => Promise>; + +- importBrowserCookies: (input: { + +- readonly environmentId: EnvironmentId; + +- readonly sourceId: BrowserImportSourceId; + +- readonly sourceProfileDirectory: string; + +- readonly targetProfileId: string; + +- }) => Promise; + ++ getPreviewConfig: (environmentId: EnvironmentId) => Promise; + + setAnnotationTheme: (theme: DesktopPreviewAnnotationTheme) => Promise; + + /** + + * Activate the in-page element picker for the given tab. Resolves with + @@ packages/contracts/src/ipc.ts: export interface LocalApi { + items: readonly ContextMenuItem[], + position?: { x: number; y: number }, + 18: ca9ba20375c = 17: 959c0e22e73 Add thread fork lineage and lazy context transfer + 19: 76dc095de6a = 18: 5169fe6083b Add orchestration V2 backend checklist + 20: be1d5acc702 = 19: 88b265dab63 Add merge-back context handoff support + 21: 052c24ec16d = 20: 3a75dbb5a18 Add V2 command capability policy + 22: b460c064415 = 21: 5c6af6923c2 Add Claude replay fixture recorder + 23: 166fd1c53cf = 22: 05d619192a4 Extract Claude SDK query runner from provider adapter + 24: d4cd5427996 = 23: f806017a3c6 Add model selection to orchestration runs + 25: 41c5f212a75 = 24: c71caf0f964 Map Claude replay fixtures to multi-turn turns + 26: c1e8a125374 = 25: d9f4e700c07 Map Claude turns to runtime query policies + 27: 617f3279952 = 26: 1be35b30fa1 Support active Claude steering and turn replay mapping + 28: 2182b71bfab = 27: ebf98e42177 Add turn-interrupt replay coverage and protocol logging + 29: b76bbc23de9 = 28: ec935be6a56 Document Cursor SDK MCP projection for V2 + 30: 631219bca58 = 29: bf94a66361a feat(orchestration-v2): wire claude adapter primitives + 31: e2ba0751f78 = 30: 1ed757ba0c5 feat(orchestration-v2): support cross-provider handoff + 32: 2e38197d2b2 = 31: 69cba683fa0 fix(orchestration-v2): resolve cross-provider forks + 33: 08430b8115f = 32: 86f785623b1 feat(orchestration-v2): add merge-back replay coverage + 34: 98e98085afd = 33: 28cc526e1f8 fix(orchestration-v2): compose provider switch merge context + 35: 73fe5fd8780 = 34: 3c06f0c2c9c fix(orchestration-v2): preserve source history on merged switch + 36: a4a63953eda ! 35: 43910683671 Map orchestration v2 WS methods to auth scopes + @@ apps/server/src/ws.ts: export function isThreadDetailEvent(event: OrchestrationE + -// Matches the event store's default page size (DEFAULT_READ_FROM_SEQUENCE_LIMIT). + -const SHELL_RESUME_MAX_GAP = 1_000; + - + --// Same bound for thread resume. The replay reads the *global* event range and + --// filters per-thread afterwards, so a stale cursor far behind the head would + --// otherwise decode every intervening event's payload — reconnects with cursors + --// hundreds of thousands of events behind have OOM-killed servers on large + --// databases. Past this gap the client is reset with a fresh thread snapshot. + --const THREAD_RESUME_MAX_GAP = 1_000; + +-// Thread replay counts only this thread's rows. Busy or pruned unrelated + +-// streams must not force a full thread snapshot. + +-const THREAD_RESUME_MAX_EVENTS = 1_000; + -// Row count alone does not bound replay memory: a few events with large tool + -// payloads can decode to gigabytes. Before replaying, sum the serialized + -// payload bytes of the range in SQL and reset with a snapshot past this budget. + 37: 7078dac915d = 36: d175a63a1bc feat(orchestration-v2): model native subagents + 38: d855d91f0a3 ! 37: 5dec17fc19c wip + @@ apps/server/src/persistence/Migrations/026_OrchestrationV2.ts => apps/server/src + + + ## apps/server/src/server.ts ## + +@@ + +-import { EnvironmentHttpApi, ProviderDriverKind } from "@t3tools/contracts"; + +-import * as Cause from "effect/Cause"; + ++import { EnvironmentHttpApi } from "@t3tools/contracts"; + + import * as Duration from "effect/Duration"; + + import * as Deferred from "effect/Deferred"; + + import * as Effect from "effect/Effect"; + + import * as Layer from "effect/Layer"; + + import * as Schedule from "effect/Schedule"; + +-import * as Stream from "effect/Stream"; + + import { FetchHttpClient, HttpRouter, HttpServer } from "effect/unstable/http"; + + import * as HttpApiBuilder from "effect/unstable/httpapi/HttpApiBuilder"; + + + @@ apps/server/src/server.ts: import * as ServerConfig from "./config.ts"; + import { + otlpTracesProxyRouteLayer, + @@ apps/server/src/server.ts: import * as AnalyticsService from "./telemetry/Analyt + import * as ProviderSessionRuntime from "./persistence/ProviderSessionRuntime.ts"; + import { ProviderAdapterRegistryLive } from "./provider/Layers/ProviderAdapterRegistry.ts"; + -import * as ModelManifest from "./provider/ModelManifest.ts"; + +-import * as CodexResetCredit from "./provider/Layers/codexResetCredit.ts"; + import * as ProviderEventLoggers from "./provider/Layers/ProviderEventLoggers.ts"; + import { ProviderServiceLive } from "./provider/Layers/ProviderService.ts"; + +-import { ProviderAuthServiceLive } from "./provider/Layers/ProviderAuthService.ts"; + +-import { AntigravityInstallation } from "./provider/AntigravityInstallation.ts"; + +-import { ProviderInstanceRegistry } from "./provider/Services/ProviderInstanceRegistry.ts"; + +-import { ProviderRegistry } from "./provider/Services/ProviderRegistry.ts"; + import { ProviderSessionReaperLive } from "./provider/Layers/ProviderSessionReaper.ts"; + +-import { ProviderUsageLimitsIngestionLive } from "./provider/Layers/ProviderUsageLimitsIngestion.ts"; + + import * as OpenCodeRuntime from "./provider/opencodeRuntime.ts"; + + import * as CheckpointDiffQuery from "./checkpointing/CheckpointDiffQuery.ts"; + + import * as CheckpointStore from "./checkpointing/CheckpointStore.ts"; + +@@ apps/server/src/server.ts: import * as AgentAwarenessRelay from "./relay/AgentAwarenessRelay.ts"; + + import { hasCloudPublicConfig } from "./cloud/publicConfig.ts"; + + import { ProviderRegistryLive } from "./provider/Layers/ProviderRegistry.ts"; + + import * as ServerSettings from "./serverSettings.ts"; + +-import * as NativeAppIconResolver from "./assets/NativeAppIconResolver.ts"; + + import * as ProjectFaviconResolver from "./project/ProjectFaviconResolver.ts"; + + import * as T3ProjectFileLoader from "./project/T3ProjectFileLoader.ts"; + + import * as RepositoryIdentityResolver from "./project/RepositoryIdentityResolver.ts"; + +@@ apps/server/src/server.ts: import * as NativeTelemetryClient from "./resourceTelemetry/NativeTelemetryClien + + import * as ResourceAttribution from "./resourceTelemetry/ResourceAttribution.ts"; + + import * as ResourceMonitorBinary from "./resourceTelemetry/ResourceMonitorBinary.ts"; + + import * as ResourceTelemetry from "./resourceTelemetry/ResourceTelemetry.ts"; + +-import * as UsageLimitSources from "./usage/UsageLimitSources.ts"; + + import * as UsageService from "./usage/UsageService.ts"; + + import { OrchestrationLayerLive } from "./orchestration/runtimeLayer.ts"; + + import { + @@ apps/server/src/server.ts: const PtyAdapterLive = Layer.unwrap( + }), + ); + @@ apps/server/src/server.ts: const PtyAdapterLive = Layer.unwrap( + + const NativeTelemetryLayerLive = NativeTelemetryClient.layer.pipe( + Layer.provide(ResourceMonitorBinary.layer), + -@@ apps/server/src/server.ts: const ProviderRuntimeLayerLive = ProviderSessionReaperLive.pipe( + +@@ apps/server/src/server.ts: const VcsLayerLive = Layer.empty.pipe( + + Layer.provideMerge(GitWorkflowLayerLive), + + Layer.provideMerge(ReviewLayerLive), + + Layer.provideMerge(SourceControlRepositoryServiceLayerLive), + +- Layer.provideMerge( + +- VcsStatusBroadcaster.layer.pipe( + +- Layer.provide(GitWorkflowLayerLive), + +- Layer.provide(VcsStatusBroadcaster.autoPullPolicyLayer), + +- ), + +- ), + ++ Layer.provideMerge(VcsStatusBroadcaster.layer.pipe(Layer.provide(GitWorkflowLayerLive))), + + ); + + + + const CheckpointingLayerLive = Layer.empty.pipe( + +@@ apps/server/src/server.ts: const CloudManagedEndpointRuntimeLive = Layer.mergeAll( + + ); + + + + const ProviderRuntimeLayerLive = ProviderSessionReaperLive.pipe( + +- // Subscribes to `account.rate-limits.updated` so usage bars track live + +- // telemetry instead of waiting for the next status probe. + +- Layer.provideMerge(ProviderUsageLimitsIngestionLive), + + Layer.provideMerge(ProviderLayerLive), + Layer.provideMerge(OrchestrationLayerLive), + ); + + +-const AntigravityInstallationRefreshLive = Layer.effectDiscard( + +- Effect.gen(function* () { + +- const installation = yield* AntigravityInstallation; + +- const instances = yield* ProviderInstanceRegistry; + +- const providers = yield* ProviderRegistry; + +- yield* installation.changes.pipe( + +- Stream.map((state) => state.installedVersion), + +- Stream.changes, + +- Stream.drop(1), + +- Stream.runForEach(() => + +- instances.listInstances.pipe( + +- Effect.flatMap((entries) => + +- Effect.forEach( + +- entries.filter( + +- (instance) => instance.driverKind === ProviderDriverKind.make("antigravity"), + +- ), + +- (instance) => providers.refreshInstance(instance.instanceId), + +- { discard: true }, + +- ), + +- ), + +- ), + +- ), + +- Effect.forkScoped, + +- ); + +- }), + +-); + +- + -const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe( + +- Layer.provideMerge(AntigravityInstallationRefreshLive), + +- Layer.provideMerge(ProviderAuthServiceLive), + +const RuntimeCoreDependenciesBaseLive = ReactorLayerLive.pipe( + // Core Services + Layer.provideMerge(ServerSettingsLayerLive), + Layer.provideMerge(CheckpointingLayerLive), + @@ apps/server/src/server.ts: const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe( + + Layer.provideMerge(PersistenceLayerLive), + + // Both read a user-owned file out of the state directory and stream changes + + // to clients; neither depends on the other. + +- Layer.provideMerge( + +- Layer.mergeAll(Keybindings.layer, EnvironmentTheme.layer, UsageLimitSources.layer), + +- ), + ++ Layer.provideMerge(Layer.mergeAll(Keybindings.layer, EnvironmentTheme.layer)), + + Layer.provideMerge(ProviderRegistryLive), + + // The instance registry is the new routing keystone — text generation, + + // adapter lookup, and runtime ingestion all resolve `ProviderInstanceId` + +@@ apps/server/src/server.ts: const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe( + + // `providerInstances` hydration merges `settings.providers.` + + // with explicit `providerInstances` entries on boot. + + Layer.provideMerge(ProviderInstanceRegistryHydrationLive), + +-).pipe( + +- Layer.provideMerge(AntigravityInstallation.layer), + + // Shared native/canonical NDJSON writers used by both the per-instance + + // drivers (native stream, written from inside each `Adapter`) and + // `ProviderService` (canonical stream, written after event normalization). + // Provided once at the runtime level so every consumer sees the same + // logger instances. + - // `ModelManifest.layer` is the legacy-model classification data, refreshed + - // from the repo's `model-manifest.json` on `main` and applied by the + - // Codex/Claude drivers. + -- Layer.provideMerge(Layer.mergeAll(ProviderEventLoggers.layer, ModelManifest.layer)), + +- Layer.provideMerge( + +- Layer.mergeAll(ProviderEventLoggers.layer, ModelManifest.layer, CodexResetCredit.layer), + +- ), + + Layer.provideMerge(ProviderEventLoggersLive), + +); + + + @@ apps/server/src/server.ts: const RuntimeCoreDependenciesLive = ReactorLayerLive. + // `OpenCodeDriver.create()` yields `OpenCodeRuntime`; previously the old + // `ProviderRegistryLive` pulled `OpenCodeRuntimeLive` in for itself, but + // the rewritten registry reads snapshots off the instance registry and + +@@ apps/server/src/server.ts: const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe( + + // keeps a single Live for all opencode consumers. + + Layer.provideMerge(OpenCodeRuntime.OpenCodeRuntimeLive), + + Layer.provideMerge(WorkspaceLayerLive), + +- Layer.provideMerge(Layer.mergeAll(NativeAppIconResolver.layer, ProjectFaviconResolverLayerLive)), + ++ Layer.provideMerge(ProjectFaviconResolverLayerLive), + + Layer.provideMerge(RepositoryIdentityResolver.layer), + + Layer.provideMerge(ServerEnvironmentLayerLive), + + Layer.provideMerge(AuthLayerLive), + @@ apps/server/src/server.ts: export const makeRoutesLayer = Layer.mergeAll( + ), + otlpTracesProxyRouteLayer, + 39: 6b81144d2cd = 38: a244d5c8951 refactor(orchestration-v2): adopt host process spawn policy + 40: 3056bfd7c01 = 39: 8cc9df27fa7 Add orchestration MCP toolkit + 41: 8dcf191a942 ! 40: 26e930ea408 Add Cursor SDK orchestration replay support + @@ apps/server/package.json + "test": "vp test run" + }, + "dependencies": { + - "@anthropic-ai/claude-agent-sdk": "^0.3.170", + +- "@anthropic-ai/claude-agent-sdk": "^0.3.260", + ++ "@anthropic-ai/claude-agent-sdk": "^0.3.170", + + "@connectrpc/connect": "1.7.0", + + "@connectrpc/connect-node": "1.7.0", + + "@cursor/sdk": "1.0.19", + @@ docs/user/cursor.md (new) + + ## pnpm-lock.yaml ## + @@ pnpm-lock.yaml: importers: + + apps/server: + + dependencies: + '@anthropic-ai/claude-agent-sdk': + - specifier: ^0.3.170 + - version: 0.3.170(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3) + +- specifier: ^0.3.260 + +- version: 0.3.260(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3) + ++ specifier: ^0.3.170 + ++ version: 0.3.170(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3) + + '@connectrpc/connect': + + specifier: 1.7.0 + + version: 1.7.0(@bufbuild/protobuf@1.10.0) + 42: 4ff48c09838 = 41: 37045a02fe9 Handle segmented Cursor turns and stable visible timelines + 43: ad109c26f5a ! 42: b43bc2b62c4 Add ACP replay harness and session lifecycle support + @@ apps/server/src/orchestration-v2/testkit/fixtures/turn_interrupt/opencode_transc + +{"type":"runtime_exit","status":"success"} + + ## apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts ## + -@@ apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts: import * as TestClock from "effect/testing/TestClock"; + +@@ apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts: import * as NodeFS from "node:fs"; + + + + import * as NodeServices from "@effect/platform-node/NodeServices"; + + import { it } from "@effect/vitest"; + +-import * as Deferred from "effect/Deferred"; + + import * as Effect from "effect/Effect"; + +-import * as Exit from "effect/Exit"; + + import * as Fiber from "effect/Fiber"; + + import * as Option from "effect/Option"; + +-import * as Scope from "effect/Scope"; + + import * as TestClock from "effect/testing/TestClock"; + import * as Stream from "effect/Stream"; + import { describe, expect } from "vite-plus/test"; + + @@ apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts: import * as TestClock + + type AcpSessionRequestLogEvent, + +} from "./AcpSessionRuntime.ts"; + import type * as EffectAcpProtocol from "effect-acp/protocol"; + +-import * as EffectAcpErrors from "effect-acp/errors"; + + const __dirname = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); + -@@ apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts: const mockAgentCommand = "node"; + + const mockAgentPath = NodePath.join(__dirname, "../../../scripts/acp-mock-agent.ts"); + + const mockAgentCommand = "node"; + const mockAgentArgs = [mockAgentPath]; + +-const mockRuntimeOptions = { + +- spawn: { command: mockAgentCommand, args: mockAgentArgs }, + +- cwd: process.cwd(), + +- clientInfo: { name: "t3-test", version: "0.0.0" }, + +- authMethodId: "test", + +-} satisfies AcpSessionRuntime.AcpSessionRuntimeOptions; + + describe("AcpSessionRuntime", () => { + +- for (const setupMethod of ["session/new", "session/resume"] as const) { + +- it.effect(`buffers root metadata while ${setupMethod} startup is still pending`, () => + +- Effect.gen(function* () { + +- const setupReplied = yield* Deferred.make(); + +- const allowStartup = yield* Deferred.make(); + +- const events: Array = []; + +- const runtime = yield* AcpSessionRuntime.make({ + +- ...mockRuntimeOptions, + +- ...(setupMethod === "session/resume" + +- ? { resumeSessionId: "mock-session-1", resumeMethod: "resume" as const } + +- : {}), + +- requestLogger: (event) => + +- event.method === setupMethod && event.status === "succeeded" + +- ? Deferred.succeed(setupReplied, undefined).pipe( + +- Effect.andThen(Deferred.await(allowStartup)), + +- ) + +- : Effect.void, + +- }); + +- yield* runtime.getEvents().pipe( + +- Stream.runForEach((event) => { + +- if (event._tag === "EventStreamBarrier") { + +- return Deferred.succeed(event.acknowledge, undefined); + +- } + +- events.push(event); + +- return Effect.void; + +- }), + +- Effect.forkChild, + +- ); + +- const startup = yield* runtime.start().pipe(Effect.forkChild); + +- yield* Deferred.await(setupReplied); + +- yield* runtime.request("_test/startup-metadata", {}); + +- yield* Deferred.succeed(allowStartup, undefined); + +- yield* Fiber.join(startup); + +- yield* runtime.drainEvents; + +- + +- expect(events.map((event) => event._tag)).toEqual([ + +- "AvailableCommandsUpdated", + +- "ModeChanged", + +- "ConfigOptionsUpdated", + +- ]); + +- expect(events[0]).toMatchObject({ + +- availableCommands: [{ name: "plan", description: "Native command" }], + +- }); + +- expect(yield* runtime.getModeState).toMatchObject({ currentModeId: "code" }); + +- expect(events[2]).toMatchObject({ + +- configOptions: yield* runtime.getConfigOptions, + +- }); + +- expect( + +- (yield* runtime.getConfigOptions).find((option) => option.category === "model"), + +- ).toMatchObject({ currentValue: "gpt-5.4" }); + +- }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + +- ); + +- } + +- + +- it.effect("publishes model changes returned by a config request and live notifications", () => + +- Effect.gen(function* () { + +- const runtime = yield* AcpSessionRuntime.make(mockRuntimeOptions); + +- yield* runtime.start(); + +- const updates = yield* Stream.toPull( + +- runtime.getEvents().pipe(Stream.filter((event) => event._tag === "ConfigOptionsUpdated")), + +- ); + +- const selected = yield* runtime.setConfigOption("model", "composer-2"); + +- expect((yield* updates)[0]?.configOptions).toEqual(selected.configOptions); + +- yield* runtime.request("_test/startup-metadata", {}); + +- expect((yield* updates)[0]?.configOptions).toEqual(yield* runtime.getConfigOptions); + +- }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + +- ); + +- + +- it.effect("awaits native resume instead of using the load replay idle fallback", () => + +- Effect.gen(function* () { + +- const resumeStarted = yield* Deferred.make(); + +- const requestMethods: Array = []; + +- const runtime = yield* AcpSessionRuntime.make({ + +- ...mockRuntimeOptions, + +- spawn: { + +- ...mockRuntimeOptions.spawn, + +- env: { T3_ACP_WAIT_FOR_RESUME_RELEASE: "1" }, + +- }, + +- resumeSessionId: "mock-session-1", + +- resumeMethod: "resume", + +- sessionLoadReplayIdleGap: "1 second", + +- requestLogger: (event) => + +- Effect.sync(() => { + +- if (event.status === "started") requestMethods.push(event.method); + +- }), + +- }); + +- yield* runtime.handleSessionUpdate((notification) => + +- notification.update.sessionUpdate === "user_message_chunk" + +- ? Deferred.succeed(resumeStarted, undefined).pipe(Effect.asVoid) + +- : Effect.void, + +- ); + +- const startup = yield* runtime.start().pipe(Effect.forkChild); + +- yield* Deferred.await(resumeStarted); + +- yield* TestClock.adjust("3 seconds"); + +- expect(startup.pollUnsafe()).toBeUndefined(); + +- yield* runtime.request("_test/release-resume", {}); + +- const started = yield* Fiber.join(startup); + +- + +- expect(started.sessionSetupResult._meta).toEqual({ nativeResume: true }); + +- expect(requestMethods).toContain("session/resume"); + +- expect(requestMethods).not.toContain("session/load"); + +- }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + +- ); + +- + +- it.effect("waits for native cancellation and drains final updates before another prompt", () => + +- Effect.gen(function* () { + +- const toolStarted = yield* Deferred.make(); + +- const cancelReceived = yield* Deferred.make(); + +- const events: Array = []; + +- let promptRequests = 0; + +- const runtime = yield* AcpSessionRuntime.make({ + +- ...mockRuntimeOptions, + +- spawn: { + +- ...mockRuntimeOptions.spawn, + +- env: { T3_ACP_COMPLETE_FIRST_PROMPT_ON_CANCEL: "1" }, + +- }, + +- cancelBehavior: "wait-for-prompt", + +- requestLogger: (event) => + +- Effect.sync(() => { + +- if (event.method === "session/prompt" && event.status === "started") + +- promptRequests += 1; + +- }), + +- }); + +- yield* runtime.getEvents().pipe( + +- Stream.runForEach((event) => { + +- if (event._tag === "EventStreamBarrier") { + +- return Deferred.succeed(event.acknowledge, undefined); + +- } + +- events.push(event); + +- if (event._tag === "ToolCallUpdated" && event.toolCall.status === "inProgress") { + +- return Deferred.succeed(toolStarted, undefined); + +- } + +- if (event._tag === "ThoughtDelta" && event.text === "native-cancel-received") { + +- return Deferred.succeed(cancelReceived, undefined); + +- } + +- return Effect.void; + +- }), + +- Effect.forkChild, + +- ); + +- yield* runtime.start(); + +- const prompt = yield* runtime + +- .prompt({ + +- prompt: [{ type: "text", text: "first" }], + +- }) + +- .pipe(Effect.forkChild); + +- yield* Deferred.await(toolStarted); + +- const cancellation = yield* runtime.cancel.pipe(Effect.forkChild); + +- yield* Deferred.await(cancelReceived); + +- const replacement = yield* runtime + +- .prompt({ + +- prompt: [{ type: "text", text: "second" }], + +- }) + +- .pipe(Effect.forkChild({ startImmediately: true })); + +- + +- expect(prompt.pollUnsafe()).toBeUndefined(); + +- expect(cancellation.pollUnsafe()).toBeUndefined(); + +- expect(promptRequests).toBe(1); + +- yield* runtime.request("_test/finish-cancel", {}); + +- yield* Fiber.join(cancellation); + +- + +- expect(yield* Fiber.join(prompt)).toEqual({ + +- stopReason: "cancelled", + +- _meta: { nativeCancel: true }, + +- }); + +- expect( + +- events.some( + +- (event) => + +- event._tag === "ToolCallUpdated" && + +- event.toolCall.status === "failed" && + +- event.toolCall.detail === "Cancelled.", + +- ), + +- ).toBe(true); + +- const cancelledDelta = events.find( + +- (event) => event._tag === "ContentDelta" && event.text === "Request cancelled.", + +- ); + +- expect(cancelledDelta?._tag).toBe("ContentDelta"); + +- if (cancelledDelta?._tag === "ContentDelta") { + +- expect( + +- events.filter( + +- (event) => + +- event._tag === "AssistantItemCompleted" && event.itemId === cancelledDelta.itemId, + +- ), + +- ).toHaveLength(1); + +- } + +- expect(yield* Fiber.join(replacement)).toMatchObject({ stopReason: "end_turn" }); + +- expect(promptRequests).toBe(2); + +- }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + +- ); + +- + +- it.effect("retires a process when native cancellation times out", () => + +- Effect.gen(function* () { + +- const toolStarted = yield* Deferred.make(); + +- const cancelReceived = yield* Deferred.make(); + +- const runtime = yield* AcpSessionRuntime.make({ + +- ...mockRuntimeOptions, + +- spawn: { + +- ...mockRuntimeOptions.spawn, + +- env: { T3_ACP_COMPLETE_FIRST_PROMPT_ON_CANCEL: "1" }, + +- }, + +- cancelBehavior: "wait-for-prompt", + +- cancelTimeout: "1 second", + +- }); + +- yield* runtime.getEvents().pipe( + +- Stream.runForEach((event) => { + +- if (event._tag === "EventStreamBarrier") { + +- return Deferred.succeed(event.acknowledge, undefined); + +- } + +- if (event._tag === "ToolCallUpdated") { + +- return Deferred.succeed(toolStarted, undefined); + +- } + +- if (event._tag === "ThoughtDelta") { + +- return Deferred.succeed(cancelReceived, undefined); + +- } + +- return Effect.void; + +- }), + +- Effect.forkChild, + +- ); + +- yield* runtime.start(); + +- const prompt = yield* runtime + +- .prompt({ + +- prompt: [{ type: "text", text: "first" }], + +- }) + +- .pipe(Effect.forkChild); + +- yield* Deferred.await(toolStarted); + +- const cancellation = yield* runtime.cancel.pipe(Effect.forkChild); + +- yield* Deferred.await(cancelReceived); + +- yield* TestClock.adjust("2 seconds"); + +- + +- const error = yield* Fiber.join(cancellation).pipe(Effect.flip); + +- expect(error).toMatchObject({ + +- _tag: "AcpTransportError", + +- method: "session/cancel", + +- }); + +- expect(Exit.isFailure(yield* Fiber.await(prompt))).toBe(true); + +- expect( + +- yield* runtime + +- .prompt({ + +- prompt: [{ type: "text", text: "must not run" }], + +- }) + +- .pipe(Effect.flip), + +- ).toBe(error); + +- }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + +- ); + +- + +- it.effect("reports an idle child exit and rejects later prompts", () => + +- Effect.gen(function* () { + +- const runtime = yield* AcpSessionRuntime.make(mockRuntimeOptions); + +- yield* runtime.start(); + +- yield* runtime.notify("_test/exit", {}); + +- const events = yield* runtime.getEvents().pipe(Stream.take(1), Stream.runCollect); + +- const event = events[0]; + +- expect(event).toMatchObject({ _tag: "ConnectionTerminated", error: { code: 19 } }); + +- if (event?._tag !== "ConnectionTerminated") return; + +- expect( + +- yield* runtime + +- .prompt({ + +- prompt: [{ type: "text", text: "must not run" }], + +- }) + +- .pipe(Effect.flip), + +- ).toBe(event.error); + +- expect(yield* runtime.start().pipe(Effect.flip)).toBe(event.error); + +- expect(yield* runtime.initialize().pipe(Effect.flip)).toBe(event.error); + +- expect( + +- yield* runtime.request("_test/environment", {}).pipe( + +- Effect.match({ + +- onFailure: (error) => error, + +- onSuccess: () => undefined, + +- }), + +- ), + +- ).toBe(event.error); + +- expect(yield* runtime.notify("_test/exit", {}).pipe(Effect.flip)).toBe(event.error); + +- }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + +- ); + +- + +- it.effect("retires a native runtime when its prompt caller is interrupted", () => + +- Effect.gen(function* () { + +- const dispatched = yield* Deferred.make(); + +- const runtime = yield* AcpSessionRuntime.make({ + +- ...mockRuntimeOptions, + +- spawn: { + +- ...mockRuntimeOptions.spawn, + +- env: { T3_ACP_COMPLETE_FIRST_PROMPT_ON_CANCEL: "1" }, + +- }, + +- cancelBehavior: "wait-for-prompt", + +- }); + +- yield* runtime.start(); + +- const prompt = yield* runtime + +- .prompt( + +- { + +- prompt: [{ type: "text", text: "first" }], + +- }, + +- { dispatched }, + +- ) + +- .pipe(Effect.forkChild); + +- yield* Deferred.await(dispatched); + +- yield* Fiber.interrupt(prompt); + +- const events = yield* runtime.getEvents().pipe( + +- Stream.filter((event) => event._tag === "ConnectionTerminated"), + +- Stream.take(1), + +- Stream.runCollect, + +- ); + +- expect(events[0]).toMatchObject({ + +- error: { _tag: "AcpTransportError", method: "session/prompt" }, + +- }); + +- expect( + +- yield* runtime + +- .prompt({ + +- prompt: [{ type: "text", text: "must not run" }], + +- }) + +- .pipe(Effect.flip), + +- ).toBe(events[0]?.error); + +- }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + +- ); + +- + +- it.effect("fails a pending request when the stderr handler rejects the runtime", () => + +- Effect.gen(function* () { + +- const failure = new EffectAcpErrors.AcpTransportError({ + +- detail: "Sign in before continuing.", + +- cause: undefined, + +- }); + +- const runtime = yield* AcpSessionRuntime.make({ + +- ...mockRuntimeOptions, + +- spawn: { ...mockRuntimeOptions.spawn, env: { T3_ACP_FLOOD_STDERR: "1" } }, + +- onStderr: () => Effect.fail(failure), + +- }); + +- expect(yield* runtime.start().pipe(Effect.flip)).toBe(failure); + +- const events = yield* runtime.getEvents().pipe( + +- Stream.filter((event) => event._tag === "ConnectionTerminated"), + +- Stream.take(1), + +- Stream.runCollect, + +- ); + +- expect(events[0]?.error).toBe(failure); + +- expect(yield* runtime.initialize().pipe(Effect.flip)).toBe(failure); + +- }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + +- ); + +- + +- it.effect("drains large stderr output and keeps auth-sized logging chunks", () => + +- Effect.gen(function* () { + +- const lengths: Array = []; + +- for (const logStderr of [false, true]) { + +- yield* Effect.gen(function* () { + +- const runtime = yield* AcpSessionRuntime.make({ + +- ...mockRuntimeOptions, + +- spawn: { ...mockRuntimeOptions.spawn, env: { T3_ACP_FLOOD_STDERR: "1" } }, + +- ...(logStderr + +- ? { + +- onStderr: (text: string) => + +- Effect.sync(() => { + +- lengths.push(text.length); + +- }), + +- } + +- : {}), + +- }); + +- expect(yield* runtime.initialize()).toMatchObject({ protocolVersion: 1 }); + +- }).pipe(Effect.scoped); + +- } + +- expect(lengths.length).toBeGreaterThan(0); + +- expect(Math.max(...lengths)).toBeGreaterThanOrEqual(16_384); + +- expect(Math.max(...lengths)).toBeLessThanOrEqual(32_768); + +- }).pipe(Effect.provide(NodeServices.layer)), + +- ); + +- + +- it.effect("releases a queued event drain when its runtime scope closes", () => + +- Effect.gen(function* () { + +- const scope = yield* Effect.acquireRelease(Scope.make(), (scope) => + +- Scope.close(scope, Exit.void), + +- ); + +- const barrierReceived = yield* Deferred.make(); + +- const runtime = yield* AcpSessionRuntime.make(mockRuntimeOptions).pipe( + +- Effect.provideService(Scope.Scope, scope), + +- ); + +- yield* runtime.start(); + +- yield* runtime.getEvents().pipe( + +- Stream.runForEach((event) => + +- event._tag === "EventStreamBarrier" + +- ? Deferred.succeed(barrierReceived, undefined).pipe(Effect.andThen(Effect.never)) + +- : Effect.void, + +- ), + +- Effect.forkIn(scope), + +- ); + +- const drain = yield* runtime.drainEvents.pipe(Effect.forkChild); + +- yield* Deferred.await(barrierReceived); + +- yield* Scope.close(scope, Exit.void); + +- yield* Fiber.join(drain); + +- yield* runtime.drainEvents; + +- expect(yield* runtime.initialize().pipe(Effect.flip)).toMatchObject({ + +- _tag: "AcpTransportError", + +- detail: "The ACP session runtime is closed.", + +- }); + +- }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + +- ); + +- + +- it.effect("bounds native cancellation when its event consumer is absent", () => + +- Effect.gen(function* () { + +- const toolStarted = yield* Deferred.make(); + +- const cancelReceived = yield* Deferred.make(); + +- const runtime = yield* AcpSessionRuntime.make({ + +- ...mockRuntimeOptions, + +- spawn: { + +- ...mockRuntimeOptions.spawn, + +- env: { T3_ACP_COMPLETE_FIRST_PROMPT_ON_CANCEL: "1" }, + +- }, + +- cancelBehavior: "wait-for-prompt", + +- cancelTimeout: "1 second", + +- }); + +- yield* runtime.handleSessionUpdate((notification) => { + +- if (notification.update.sessionUpdate === "tool_call") { + +- return Deferred.succeed(toolStarted, undefined).pipe(Effect.asVoid); + +- } + +- if (notification.update.sessionUpdate === "agent_thought_chunk") { + +- return Deferred.succeed(cancelReceived, undefined).pipe(Effect.asVoid); + +- } + +- return Effect.void; + +- }); + +- yield* runtime.start(); + +- const prompt = yield* runtime + +- .prompt({ + +- prompt: [{ type: "text", text: "first" }], + +- }) + +- .pipe(Effect.forkChild); + +- yield* Deferred.await(toolStarted); + +- const cancellation = yield* runtime.cancel.pipe(Effect.forkChild); + +- yield* Deferred.await(cancelReceived); + +- yield* runtime.request("_test/finish-cancel", {}); + +- expect(yield* Fiber.join(prompt)).toMatchObject({ stopReason: "cancelled" }); + +- yield* TestClock.adjust("2 seconds"); + +- expect(yield* Fiber.join(cancellation).pipe(Effect.flip)).toMatchObject({ + +- _tag: "AcpTransportError", + +- method: "session/cancel", + +- }); + +- }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + +- ); + +- + +- it.effect("does not restore ambient variables to a sanitized child environment", () => + +- Effect.gen(function* () { + +- yield* Effect.acquireRelease( + +- Effect.sync(() => { + +- const previous = process.env.T3_ACP_RUNTIME_AMBIENT; + +- process.env.T3_ACP_RUNTIME_AMBIENT = "sentinel"; + +- return previous; + +- }), + +- (previous) => + +- Effect.sync(() => { + +- if (previous === undefined) delete process.env.T3_ACP_RUNTIME_AMBIENT; + +- else process.env.T3_ACP_RUNTIME_AMBIENT = previous; + +- }), + +- ); + +- const runtime = yield* AcpSessionRuntime.make({ + +- ...mockRuntimeOptions, + +- spawn: { + +- command: process.execPath, + +- args: mockAgentArgs, + +- extendEnv: false, + +- env: { T3_ACP_RUNTIME_EXPLICIT: "kept" }, + +- }, + +- }); + +- yield* runtime.initialize(); + +- expect(yield* runtime.request("_test/environment", {})).toEqual({ + +- inherited: false, + +- explicit: true, + +- }); + +- }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + +- ); + + it("selects explicit or agent-managed authentication without choosing terminal auth", () => { + + const methods = [ + + { id: "browser", name: "Browser", type: "terminal" as const }, + @@ apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts: const mockAgentComman + + expect(selectAcpAgentAuthMethod(methods, "browser")?.id).toBe("browser"); + + expect(selectAcpAgentAuthMethod(methods, "missing")).toBeUndefined(); + + }); + -+ + + + it.effect("merges custom initialize client capabilities into the ACP handshake", () => { + const requestEvents: Array = []; + - return Effect.gen(function* () { + @@ apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts: describe("AcpSessionRuntime", () => { + ); + }); + @@ apps/web/src/components/settings/ProviderSettingsForm.test.ts: describe("Provide + }); + }); + + +- it("derives a select control with its choices for the Antigravity sign-in method", () => { + +- const antigravity = DRIVER_OPTION_BY_VALUE[ProviderDriverKind.make("antigravity")]; + +- expect(antigravity).toBeDefined(); + +- + +- const fields = deriveProviderSettingsFields(antigravity!); + +- expect(fields.map((field) => field.key)).toEqual([ + +- "authMethod", + +- "apiKey", + +- "gcpProject", + +- "gcpLocation", + +- "binaryPath", + +- ]); + +- const authMethod = fields.find((field) => field.key === "authMethod"); + +- expect(authMethod).toMatchObject({ control: "select", clearWhenEmpty: "omit" }); + +- expect(authMethod?.options?.map((option) => option.value)).toEqual([ + +- "oauth-personal", + +- "oauth-business", + +- "gemini-api-key", + +- "agent-platform", + +- ]); + +- expect(fields.find((field) => field.key === "apiKey")?.control).toBe("password"); + +- }); + +- + - it("shows the auto-compaction threshold for Claude providers", () => { + - const claude = DRIVER_OPTION_BY_VALUE[ProviderDriverKind.make("claudeAgent")]; + - expect(claude).toBeDefined(); + @@ apps/web/src/components/settings/SettingsPanels.tsx: export function GeneralSett + ## apps/web/src/components/settings/providerDriverMeta.ts ## + @@ + import { + +- AntigravitySettings, + + AcpRegistrySettings, + ClaudeSettings, + CodexSettings, + CursorSettings, + @@ apps/web/src/components/settings/providerDriverMeta.ts: import { + - ProviderDriverKind, + } from "@t3tools/contracts"; + import type * as Schema from "effect/Schema"; + --import { ClaudeAI, CursorIcon, GrokIcon, type Icon, OpenAI, OpenCodeIcon } from "../Icons"; + -+import { + + import { + +- AntigravityIcon, + + ACPRegistryIcon, + -+ ClaudeAI, + -+ CursorIcon, + -+ GrokIcon, + -+ type Icon, + -+ OpenAI, + -+ OpenCodeIcon, + -+} from "../Icons"; + - + - type ProviderSettingsSchema = { + - readonly fields: Readonly>; + + ClaudeAI, + + CursorIcon, + + GrokIcon, + @@ apps/web/src/components/settings/providerDriverMeta.ts: export interface ProviderClientDefinition { + readonly label: string; + readonly icon: Icon; + @@ apps/web/src/components/settings/providerDriverMeta.ts: export const PROVIDER_CL + { + value: ProviderDriverKind.make("opencode"), + label: "OpenCode", + + icon: OpenCodeIcon, + + settingsSchema: OpenCodeSettings, + + }, + +- { + +- value: ProviderDriverKind.make("antigravity"), + +- label: "Antigravity", + +- icon: AntigravityIcon, + +- settingsSchema: AntigravitySettings, + +- }, + + ]; + + + + export const PROVIDER_CLIENT_DEFINITION_BY_VALUE: Partial< + + ## apps/web/src/orchestrationV2DebugProviders.test.ts (new) ## + @@ + 44: e35661a8497 = 43: 7cfebe0be47 Add MCP thread management and Codex turn mapping + 45: a115e55b347 = 44: 915e6b385a2 Add Orchestration V2 application integration plan + 46: fb1ebd0f2f7 ! 45: dab646dc400 Map orchestration turns to provider instances + @@ apps/server/src/provider/Drivers/ClaudeDriver.ts: import { ChildProcessSpawner } + +} from "../../orchestration-v2/Adapters/ClaudeAdapterV2.ts"; + import { ProviderDriverError } from "../Errors.ts"; + import { makeClaudeAdapter } from "../Layers/ClaudeAdapter.ts"; + - import { + + import { makeClaudeScopedLimitNames } from "../Layers/claudeUsageLimits.ts"; + @@ apps/server/src/provider/Drivers/ClaudeDriver.ts: const UPDATE = makePackageManagedProviderMaintenanceResolver({ + }); + + @@ apps/server/src/provider/Drivers/CodexDriver.ts: const UPDATE = makePackageManag + - | BackgroundPolicy.BackgroundPolicy + + | CodexAdapterV2DriverEnv + | ChildProcessSpawner.ChildProcessSpawner + + | CodexResetCreditCoordinator + | Crypto.Crypto + - | FileSystem.FileSystem + @@ apps/server/src/provider/Drivers/CodexDriver.ts: export const CodexDriver: ProviderDriver = { + environment: processEnv, + ...(eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {}), + @@ apps/server/src/provider/Drivers/CodexDriver.ts: export const CodexDriver: Provi + + // Build a managed snapshot whose settings never change — mutations come + @@ apps/server/src/provider/Drivers/CodexDriver.ts: export const CodexDriver: ProviderDriver = { + - snapshot, + snapshotForCwd, + + consumeResetCredit, + adapter, + + orchestrationAdapter, + textGeneration, + @@ apps/server/src/provider/Drivers/CursorDriver.ts: export const CursorDriver: Pro + + const checkProvider = checkCursorProviderStatus(effectiveConfig, processEnv).pipe( + @@ apps/server/src/provider/Drivers/CursorDriver.ts: export const CursorDriver: ProviderDriver = { + - enabled, + - snapshot, + + ), + + ]).pipe(Effect.map(([machineSnapshot, skills]) => ({ ...machineSnapshot, skills }))), + adapter, + + orchestrationAdapter, + textGeneration, + @@ apps/server/src/provider/Drivers/GrokDriver.ts: export const GrokDriver: Provide + + const checkProvider = checkGrokProviderStatus(effectiveConfig, processEnv, cwd).pipe( + @@ apps/server/src/provider/Drivers/GrokDriver.ts: export const GrokDriver: ProviderDriver = { + - enabled, + snapshot, + + snapshotForCwd, + adapter, + + orchestrationAdapter, + textGeneration, + @@ apps/server/src/provider/Layers/ProviderInstanceRegistryHydration.ts: export con + +) as Layer.Layer; + + ## apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts ## + -@@ apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts: import * as BackgroundPolicy from "../../background/BackgroundPolicy.ts"; + +@@ apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts: import { HttpClient, HttpClientResponse } from "effect/unstable/http"; + + + + import * as BackgroundPolicy from "../../background/BackgroundPolicy.ts"; + import type { BuiltInDriversEnv } from "../builtInDrivers.ts"; + +-import { AntigravityInstallation } from "../AntigravityInstallation.ts"; + import { ServerConfig } from "../../config.ts"; + import { ServerSettingsService } from "../../serverSettings.ts"; + +import type { BuiltInDriversEnv } from "../builtInDrivers.ts"; + @@ apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts: import * a + import { CursorDriver } from "../Drivers/CursorDriver.ts"; + import { GrokDriver } from "../Drivers/GrokDriver.ts"; + import { OpenCodeDriver } from "../Drivers/OpenCodeDriver.ts"; + -@@ apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts: import * as ModelManifest from "../ModelManifest.ts"; + + import * as ModelManifest from "../ModelManifest.ts"; + import { OpenCodeRuntimeLive } from "../opencodeRuntime.ts"; + +-import * as CodexResetCredit from "./codexResetCredit.ts"; + import { NoOpProviderEventLoggers, ProviderEventLoggers } from "./ProviderEventLoggers.ts"; + import { makeProviderInstanceRegistry } from "./ProviderInstanceRegistryLive.ts"; + +import { ProviderOrchestrationAdapterInfrastructureLive } from "./ProviderOrchestrationAdapterInfrastructure.ts"; + @@ apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts: describe(" + + Layer.provideMerge(ServerSettingsService.layerTest()), + Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), + Layer.provideMerge(ModelManifest.layerTest), + - ); + +- Layer.provideMerge(CodexResetCredit.layerTest), + ++ ); + + const testLayer = ProviderOrchestrationAdapterInfrastructureLive.pipe( + + Layer.provideMerge(baseLayer), + -+ ); + + ); + + it.live("boots two independent codex instances from a ProviderInstanceConfigMap", () => + - Effect.gen(function* () { + @@ apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts: describe("ProviderInstanceRegistryLive — multi-instance codex slice", () => { + }, + }; + @@ apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts: describe(" + // surfaced; that merged layer then provides `ServerConfig.layerTest`'s + // `FileSystem` dep while keeping everything else surfaced to the test. + const infraLayer = OpenCodeRuntimeLive.pipe(Layer.provideMerge(NodeServices.layer)); + -- const testLayer = ServerConfig.layerTest(process.cwd(), { + +- const testLayer = AntigravityInstallation.layer.pipe( + +- Layer.provideMerge( + +- ServerConfig.layerTest(process.cwd(), { + +- prefix: "provider-instance-registry-all-drivers-test", + +- }), + +- ), + + const baseLayer = ServerConfig.layerTest(process.cwd(), { + - prefix: "provider-instance-registry-all-drivers-test", + - }).pipe( + ++ prefix: "provider-instance-registry-all-drivers-test", + ++ }).pipe( + Layer.provideMerge(infraLayer), + Layer.provideMerge(BackgroundPolicyAlwaysRunLayer), + Layer.provideMerge(ServerSettingsService.layerTest()), + @@ apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts: describe(" + + Layer.provideMerge(ServerSettingsService.layerTest()), + Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), + Layer.provideMerge(ModelManifest.layerTest), + - ); + +- Layer.provideMerge(CodexResetCredit.layerTest), + ++ ); + + const testLayer = ProviderOrchestrationAdapterInfrastructureLive.pipe( + + Layer.provideMerge(baseLayer), + -+ ); + + ); + + it.live("boots one instance of every shipped driver from a single config map", () => + - Effect.gen(function* () { + + ## apps/server/src/provider/Layers/ProviderOrchestrationAdapterInfrastructure.ts (new) ## + @@ + @@ apps/server/src/provider/Layers/ProviderOrchestrationAdapterInfrastructure.ts (n + + ## apps/server/src/provider/Layers/ProviderRegistry.test.ts ## + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te + - streamChanges: Stream.empty, + + applyUsageLimits: () => Effect.void, + }, + adapter: {} as ProviderInstance["adapter"], + + orchestrationAdapter: {} as ProviderInstance["orchestrationAdapter"], + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAl + } satisfies ProviderInstance; + const instanceRegistryLayer = Layer.succeed( + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te + - streamChanges: Stream.fromPubSub(changes), + + applyUsageLimits: () => Effect.void, + }, + adapter: {} as ProviderInstance["adapter"], + + orchestrationAdapter: {} as ProviderInstance["orchestrationAdapter"], + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAl + const instanceRegistryLayer = Layer.succeed( + + ## apps/server/src/provider/ProviderDriver.ts ## + +@@ + + * @module provider/ProviderDriver + + */ + + import type { + +- ProviderConsumeResetCreditOutcome, + + ProviderDriverKind, + + ProviderInstanceEnvironment, + + ProviderInstanceId, + @@ apps/server/src/provider/ProviderDriver.ts: import type * as Effect from "effect/Effect"; + import type * as Schema from "effect/Schema"; + import type * as Scope from "effect/Scope"; + @@ apps/server/src/provider/ProviderDriver.ts: import type * as Effect from "effect + import type { ProviderAdapterError, ProviderDriverError } from "./Errors.ts"; + import type { ProviderAdapterShape } from "./Services/ProviderAdapter.ts"; + import type { ServerProviderShape } from "./Services/ServerProvider.ts"; + +-import type { ProviderAuthController } from "./Services/ProviderAuthService.ts"; + + + + /** + + * Static metadata advertised by a driver. Used for default presentation + @@ apps/server/src/provider/ProviderDriver.ts: export interface ProviderInstance { + + readonly enabled: boolean; + readonly snapshot: ServerProviderShape; + readonly snapshotForCwd?: (cwd: string) => Effect.Effect; + +- readonly refreshModels?: () => Effect.Effect; + +- /** + +- * Redeem one banked rate-limit reset credit on the signed-in account, then + +- * re-probe so the snapshot reflects the cleared windows. Account-level, + +- * not thread-level, which is why it lives here rather than on the adapter. + +- */ + +- readonly consumeResetCredit?: () => Effect.Effect< + +- ProviderConsumeResetCreditOutcome, + +- ProviderDriverError + +- >; + readonly adapter: ProviderAdapterShape; + - readonly textGeneration: TextGeneration.TextGeneration["Service"]; + +- readonly auth?: ProviderAuthController; + + readonly orchestrationAdapter: ProviderAdapterV2Shape; + + readonly textGeneration: TextGenerationShape; + } + @@ apps/server/src/provider/builtInDrivers.ts + import { ClaudeDriver, type ClaudeDriverEnv } from "./Drivers/ClaudeDriver.ts"; + import { CodexDriver, type CodexDriverEnv } from "./Drivers/CodexDriver.ts"; + import { CursorDriver, type CursorDriverEnv } from "./Drivers/CursorDriver.ts"; + + import { GrokDriver, type GrokDriverEnv } from "./Drivers/GrokDriver.ts"; + + import { OpenCodeDriver, type OpenCodeDriverEnv } from "./Drivers/OpenCodeDriver.ts"; + +-import { AntigravityDriver, type AntigravityDriverEnv } from "./Drivers/AntigravityDriver.ts"; + + import type { AnyProviderDriver } from "./ProviderDriver.ts"; + + + + /** + @@ apps/server/src/provider/builtInDrivers.ts: import type { AnyProviderDriver } from "./ProviderDriver.ts"; + * layer must provide every service in this union. + */ + @@ apps/server/src/provider/builtInDrivers.ts: import type { AnyProviderDriver } fr + | ClaudeDriverEnv + | CodexDriverEnv + | CursorDriverEnv + + | GrokDriverEnv + +- | OpenCodeDriverEnv + +- | AntigravityDriverEnv; + ++ | OpenCodeDriverEnv; + + + + /** + + * Ordered list of built-in drivers. Order matters only for tie-breaking in + @@ apps/server/src/provider/builtInDrivers.ts: export const BUILT_IN_DRIVERS: ReadonlyArray Effect.die("unused"), + - getCommandReadModel: () => + - Effect.die("CheckpointDiffQuery should not request the command read model"), + - getSnapshot: () => + @@ apps/server/src/checkpointing/CheckpointDiffQuery.test.ts + - toCheckpointRef, + - }); + - }), + +- getThreadRuntimeContext: () => Effect.die("unused"), + - getThreadShellById: () => Effect.succeed(Option.none()), + - getThreadDetailById: () => Effect.succeed(Option.none()), + - getThreadDetailSnapshot: () => Effect.succeed(Option.none()), + @@ apps/server/src/checkpointing/CheckpointDiffQuery.test.ts + - Layer.provideMerge(Layer.succeed(CheckpointStore.CheckpointStore, checkpointStore)), + - Layer.provideMerge( + - Layer.succeed(ProjectionSnapshotQuery.ProjectionSnapshotQuery, { + +- getUserInputActivity: () => Effect.die("unused"), + - getCommandReadModel: () => + - Effect.die("CheckpointDiffQuery should not request the command read model"), + - getSnapshot: () => + @@ apps/server/src/checkpointing/CheckpointDiffQuery.test.ts + - getFirstActiveThreadIdByProjectId: () => Effect.succeed(Option.none()), + - getThreadCheckpointContext: () => Effect.succeed(Option.some(threadCheckpointContext)), + - getFullThreadDiffContext: () => Effect.die("unused"), + +- getThreadRuntimeContext: () => Effect.die("unused"), + - getThreadShellById: () => Effect.succeed(Option.none()), + - getThreadDetailById: () => Effect.succeed(Option.none()), + - getThreadDetailSnapshot: () => Effect.succeed(Option.none()), + @@ apps/server/src/checkpointing/CheckpointDiffQuery.test.ts + - Layer.provideMerge(Layer.succeed(CheckpointStore.CheckpointStore, checkpointStore)), + - Layer.provideMerge( + - Layer.succeed(ProjectionSnapshotQuery.ProjectionSnapshotQuery, { + +- getUserInputActivity: () => Effect.die("unused"), + - getCommandReadModel: () => + - Effect.die("CheckpointDiffQuery should not request the command read model"), + - getSnapshot: () => + @@ apps/server/src/checkpointing/CheckpointDiffQuery.test.ts + - getFirstActiveThreadIdByProjectId: () => Effect.succeed(Option.none()), + - getThreadCheckpointContext: () => Effect.succeed(Option.some(threadCheckpointContext)), + - getFullThreadDiffContext: () => Effect.die("unused"), + +- getThreadRuntimeContext: () => Effect.die("unused"), + - getThreadShellById: () => Effect.succeed(Option.none()), + - getThreadDetailById: () => Effect.succeed(Option.none()), + - getThreadDetailSnapshot: () => Effect.succeed(Option.none()), + @@ apps/server/src/checkpointing/CheckpointDiffQuery.test.ts + - Layer.provideMerge(Layer.succeed(CheckpointStore.CheckpointStore, checkpointStore)), + - Layer.provideMerge( + - Layer.succeed(ProjectionSnapshotQuery.ProjectionSnapshotQuery, { + +- getUserInputActivity: () => Effect.die("unused"), + - getCommandReadModel: () => + - Effect.die("CheckpointDiffQuery should not request the command read model"), + - getSnapshot: () => + @@ apps/server/src/checkpointing/CheckpointDiffQuery.test.ts + - getFirstActiveThreadIdByProjectId: () => Effect.succeed(Option.none()), + - getThreadCheckpointContext: () => Effect.succeed(Option.some(threadCheckpointContext)), + - getFullThreadDiffContext: () => Effect.die("unused"), + +- getThreadRuntimeContext: () => Effect.die("unused"), + - getThreadShellById: () => Effect.succeed(Option.none()), + - getThreadDetailById: () => Effect.succeed(Option.none()), + - getThreadDetailSnapshot: () => Effect.succeed(Option.none()), + @@ apps/server/src/checkpointing/CheckpointDiffQuery.test.ts + - Layer.provideMerge(Layer.succeed(CheckpointStore.CheckpointStore, checkpointStore)), + - Layer.provideMerge( + - Layer.succeed(ProjectionSnapshotQuery.ProjectionSnapshotQuery, { + +- getUserInputActivity: () => Effect.die("unused"), + - getCommandReadModel: () => + - Effect.die("CheckpointDiffQuery should not request the command read model"), + - getSnapshot: () => + @@ apps/server/src/checkpointing/CheckpointDiffQuery.test.ts + - getFirstActiveThreadIdByProjectId: () => Effect.succeed(Option.none()), + - getThreadCheckpointContext: () => Effect.succeed(Option.none()), + - getFullThreadDiffContext: () => Effect.succeed(Option.none()), + +- getThreadRuntimeContext: () => Effect.die("unused"), + - getThreadShellById: () => Effect.succeed(Option.none()), + - getThreadDetailById: () => Effect.succeed(Option.none()), + - getThreadDetailSnapshot: () => Effect.succeed(Option.none()), + @@ apps/server/src/orchestration/Layers/CheckpointReactor.ts (deleted) + -import { makeDrainableWorker } from "@t3tools/shared/DrainableWorker"; + -import { isTemporaryWorktreeBranch } from "@t3tools/shared/git"; + - + --import { parseTurnDiffFilesFromUnifiedDiff } from "../../checkpointing/Diffs.ts"; + +-import { parseTurnDiffFilesFromNumstat } from "../../checkpointing/Diffs.ts"; + -import { + - checkpointRefForThreadTurn, + - resolveThreadWorkspaceCwd, + @@ apps/server/src/orchestration/Layers/CheckpointReactor.ts (deleted) + -import { isGitRepository } from "../../git/Utils.ts"; + -import { VcsStatusBroadcaster } from "../../vcs/VcsStatusBroadcaster.ts"; + -import * as WorkspaceEntries from "../../workspace/WorkspaceEntries.ts"; + +-import * as PullRequestService from "../../pullRequest/PullRequestService.ts"; + - + -const nowIso = Effect.map(DateTime.now, DateTime.formatIso); + - + @@ apps/server/src/orchestration/Layers/CheckpointReactor.ts (deleted) + - const receiptBus = yield* RuntimeReceiptBus; + - const workspaceEntries = yield* WorkspaceEntries.WorkspaceEntries; + - const vcsStatusBroadcaster = yield* VcsStatusBroadcaster; + +- const pullRequests = yield* PullRequestService.PullRequestService; + +- const startedTurns = new Map(); + +- const pending = new Set(); + - + - const appendRevertFailureActivity = (input: { + - readonly threadId: ThreadId; + @@ apps/server/src/orchestration/Layers/CheckpointReactor.ts (deleted) + - toCheckpointRef: targetCheckpointRef, + - fallbackFromToHead: false, + - ignoreWhitespace: false, + +- format: "numstat", + - }) + - .pipe( + - Effect.map((diff) => + -- parseTurnDiffFilesFromUnifiedDiff(diff).map((file) => ({ + +- parseTurnDiffFilesFromNumstat(diff).map((file) => ({ + - path: file.path, + - kind: "modified" as const, + - additions: file.additions, + @@ apps/server/src/orchestration/Layers/CheckpointReactor.ts (deleted) + - cwd: sessionRuntime.value.cwd, + - local, + - }); + +- yield* refreshPullRequestAfterTurn({ + +- threadId: event.threadId, + +- turnId: toTurnId(event.turnId), + +- cwd: sessionRuntime.value.cwd, + +- local, + +- }); + - } + - }); + - + +- // Retry a missing PR after the agent finishes its push and PR creation. + +- // Re-read the projected branch after drift adoption. A rejected metadata + +- // update must not let this thread refresh another thread's checkout. + +- const refreshPullRequestAfterTurn = Effect.fn("refreshPullRequestAfterTurn")(function* (input: { + +- readonly threadId: ThreadId; + +- readonly turnId: TurnId | null; + +- readonly cwd: string; + +- readonly local: VcsStatusLocalResult; + +- }) { + +- const checkedOutBranch = input.local.refName; + +- if (checkedOutBranch === null || input.local.isDefaultRef) return; + +- const thread = yield* projectionSnapshotQuery + +- .getThreadShellById(input.threadId) + +- .pipe(Effect.map(Option.getOrUndefined)); + +- if (!thread || thread.branch !== checkedOutBranch) return; + +- if (thread.session?.activeTurnId && !sameId(thread.session.activeTurnId, input.turnId)) return; + +- yield* vcsStatusBroadcaster.refreshPullRequestStatus(input.cwd).pipe( + +- Effect.catch((error) => + +- Effect.logWarning("failed to refresh pull request status after turn completion", { + +- threadId: input.threadId, + +- cwd: input.cwd, + +- detail: error.message, + +- }), + +- ), + +- ); + +- }); + +- + - // A `git checkout` run inside a thread's dedicated worktree (by an agent or + - // the user) bypasses T3's commands, so the thread's recorded branch goes + - // stale. Since #4460 the client only attributes PR state to a thread when + @@ apps/server/src/orchestration/Layers/CheckpointReactor.ts (deleted) + - return; + - } + - + +- yield* providerService.assertConversationRollbackSupported(event.payload.threadId); + +- + - const restored = yield* checkpointStore.restoreCheckpoint({ + - cwd: sessionRuntime.value.cwd, + - checkpointRef: targetCheckpointRef, + @@ apps/server/src/orchestration/Layers/CheckpointReactor.ts (deleted) + - + - const processDomainEvent = Effect.fn("processDomainEvent")(function* (event: OrchestrationEvent) { + - if (event.type === "thread.turn-start-requested" || event.type === "thread.message-sent") { + +- if (event.type === "thread.turn-start-requested") pending.add(event.payload.threadId); + - yield* ensurePreTurnBaselineFromDomainTurnStart(event); + - return; + - } + @@ apps/server/src/orchestration/Layers/CheckpointReactor.ts (deleted) + - + - // When ProviderRuntimeIngestion creates a placeholder checkpoint (status "missing") + - // from a turn.diff.updated runtime event, capture the real git checkpoint to + -- // replace it. The providerService.streamEvents PubSub does not reliably deliver + -- // turn.completed runtime events to this reactor (shared subscription), so + -- // reacting to the domain event is the reliable path. + +- // replace it. ProviderService broadcasts runtime events to each subscriber. + +- // This domain-event path also captures checkpoints from turn diff updates. + - if (event.type === "thread.turn-diff-completed") { + - yield* captureCheckpointFromPlaceholder(event).pipe( + - Effect.catch((error) => + @@ apps/server/src/orchestration/Layers/CheckpointReactor.ts (deleted) + - const processRuntimeEvent = Effect.fn("processRuntimeEvent")(function* ( + - event: ProviderRuntimeEvent, + - ) { + +- if (event.type === "session.exited") { + +- startedTurns.delete(event.threadId); + +- pending.delete(event.threadId); + +- return; + +- } + +- + - if (event.type === "turn.started") { + +- const turnId = toTurnId(event.turnId); + +- const activeTurnId = (yield* providerService.listSessions()).find((session) => + +- sameId(session.threadId, event.threadId), + +- )?.activeTurnId; + +- const mayReplace = pending.has(event.threadId) && sameId(activeTurnId, turnId); + +- if (turnId !== null && (!startedTurns.has(event.threadId) || mayReplace)) { + +- startedTurns.set(event.threadId, turnId); + +- pending.delete(event.threadId); + +- } + - yield* ensurePreTurnBaselineFromTurnStart(event); + - return; + - } + - + -- if (event.type === "turn.completed") { + +- if (event.type === "turn.completed" || event.type === "turn.aborted") { + - const turnId = toTurnId(event.turnId); + -- yield* refreshLocalGitStatusFromTurnCompletion(event); + +- const thread = yield* resolveThreadDetail(event.threadId); + +- const startedTurnId = startedTurns.get(event.threadId); + +- const isTrackedTurn = sameId(startedTurnId, turnId); + +- if (isTrackedTurn) startedTurns.delete(event.threadId); + +- if (event.type === "turn.completed") { + +- yield* refreshLocalGitStatusFromTurnCompletion(event); + +- } + +- if ( + +- turnId !== null && + +- thread !== undefined && + +- (isTrackedTurn || + +- sameId(thread.session?.activeTurnId, turnId) || + +- (startedTurnId === undefined && !thread.session?.activeTurnId)) + +- ) { + +- pending.delete(event.threadId); + +- yield* pullRequests.refreshAfterTurn; + +- } + +- if (event.type === "turn.aborted") return; + - yield* captureCheckpointFromTurnCompletion(event).pipe( + - Effect.catch((error) => + - Effect.flatMap(nowIso, (createdAt) => + @@ apps/server/src/orchestration/Layers/CheckpointReactor.ts (deleted) + - + - yield* forkParked( + - Stream.runForEach(providerService.streamEvents, (event) => { + -- if (event.type !== "turn.started" && event.type !== "turn.completed") { + +- if ( + +- event.type !== "turn.started" && + +- event.type !== "turn.completed" && + +- event.type !== "turn.aborted" && + +- event.type !== "session.exited" + +- ) { + - return Effect.void; + - } + - return worker.enqueue({ source: "runtime", event }); + @@ apps/server/src/orchestration/Layers/OrchestrationEngine.ts: const makeOrchestra + const readEvents: OrchestrationEngineShape["readEvents"] = (fromSequenceExclusive, limit) => + eventStore.readFromSequence(fromSequenceExclusive, limit); + + +- const readThreadEvents: OrchestrationEngineShape["readThreadEvents"] = ({ threadId, ...range }) => + +- eventStore.readAggregateRange({ ...range, aggregateKind: "thread", aggregateId: threadId }); + +- + +- const getThreadReplayStats: OrchestrationEngineShape["getThreadReplayStats"] = ({ + +- threadId, + +- ...range + +- }) => + +- eventStore.getAggregateReplayStats({ + +- ...range, + +- aggregateKind: "thread", + +- aggregateId: threadId, + +- }); + +- + - const dispatch: OrchestrationEngineShape["dispatch"] = (command, options) => + + const dispatch: OrchestrationEngineShape["dispatch"] = (command) => + Effect.gen(function* () { + @@ apps/server/src/orchestration/Services/OrchestrationEngine.ts + - OrchestrationClientOrigin, + - OrchestrationCommand, + - OrchestrationEvent, + +- ThreadId, + -} from "@t3tools/contracts"; + +import type { OrchestrationEvent, ProjectOrchestrationCommand } from "@t3tools/contracts"; + import * as Context from "effect/Context"; + @@ apps/server/src/orchestration/decider.ts: export const decideOrchestrationComman + + defaultModelSelection: command.defaultModelSelection ?? null, + +<<<<<<< HEAD + faviconPath: null, + + projectIcon: null, + scripts: [], + +======= + + scripts: command.scripts ?? [], + @@ apps/server/src/persistence/Layers/OrchestrationCommandReceipts.ts: const makeOr + + ## apps/server/src/persistence/Layers/OrchestrationEventStore.test.ts ## + @@ + --import { CommandId, EventId, ProjectId } from "@t3tools/contracts"; + +-import { + +- CommandId, + +- EventId, + +- MessageId, + +- ProjectId, + +- ThreadId, + +- type OrchestrationEvent, + +-} from "@t3tools/contracts"; + +import { CommandId, EventId, ProjectId, ProviderInstanceId, ThreadId } from "@t3tools/contracts"; + import { assert, it } from "@effect/vitest"; + +import * as DateTime from "effect/DateTime"; + @@ apps/server/src/persistence/Layers/OrchestrationEventStore.test.ts + import * as Layer from "effect/Layer"; + import * as Schema from "effect/Schema"; + @@ apps/server/src/persistence/Layers/OrchestrationEventStore.test.ts: layer("OrchestrationEventStore", (it) => { + - } + + ); + }), + ); + + + @@ apps/server/src/persistence/Layers/OrchestrationEventStore.ts: const AppendEvent + }); + + const OrchestrationEventPersistedRowSchema = Schema.Struct({ + -@@ apps/server/src/persistence/Layers/OrchestrationEventStore.ts: const ReadFromSequenceRequestSchema = Schema.Struct({ + +@@ apps/server/src/persistence/Layers/OrchestrationEventStore.ts: const AggregateReplayStatsRowSchema = Schema.Struct({ + const DEFAULT_READ_FROM_SEQUENCE_LIMIT = 1_000; + const READ_PAGE_SIZE = 500; + + @@ apps/server/src/persistence/Layers/OrchestrationEventStore.ts: const makeEventSt + ), + ); + + +- const readAggregateRange: OrchestrationEventStoreShape["readAggregateRange"] = (input) => { + +- const limit = Math.max(0, Math.floor(input.limit ?? DEFAULT_READ_FROM_SEQUENCE_LIMIT)); + +- if (limit === 0 || input.fromSequenceExclusive >= input.toSequenceInclusive) { + +- return Stream.empty; + +- } + +- const readPage = ( + +- cursor: number, + +- remaining: number, + +- ): Stream.Stream => + +- Stream.fromEffect( + +- readAggregateEventRows({ + +- ...input, + +- fromSequenceExclusive: cursor, + +- limit: Math.min(remaining, READ_PAGE_SIZE), + +- }).pipe( + + const readAgentEvents: OrchestrationEventStoreShape["readAgentEvents"] = (input) => + + Stream.fromEffect( + + readApplicationRows({ + @@ apps/server/src/persistence/Layers/OrchestrationEventStore.ts: const makeEventSt + + Stream.flatMap(Stream.fromIterable), + + Stream.mapEffect((row) => + + rowToV2StoredEvent(row).pipe( + -+ Effect.mapError( + + Effect.mapError( + +- toPersistenceSqlOrDecodeError( + +- "OrchestrationEventStore.readAggregateRange:query", + +- "OrchestrationEventStore.readAggregateRange:decodeRows", + +- ), + + toPersistenceDecodeError("OrchestrationEventStore.readAgentEvents:decode"), + -+ ), + + ), + +- Effect.flatMap((rows) => + +- Effect.forEach(rows, (row) => + +- decodeEvent(row).pipe( + +- Effect.mapError( + +- toPersistenceDecodeError("OrchestrationEventStore.readAggregateRange:rowToEvent"), + +- ), + +- ), + +- ), + + ), + + ), + + ); + @@ apps/server/src/persistence/Layers/OrchestrationEventStore.ts: const makeEventSt + + rowToApplicationStoredEvent(row).pipe( + + Effect.mapError( + + toPersistenceDecodeError("OrchestrationEventStore.readApplicationEvents:decode"), + -+ ), + -+ ), + + ), + + ), + +- ).pipe( + +- Stream.flatMap((events) => { + +- const last = events.at(-1); + +- if (last === undefined) { + +- return Stream.empty; + +- } + +- const nextRemaining = remaining - events.length; + +- if ( + +- events.length < READ_PAGE_SIZE || + +- nextRemaining === 0 || + +- last.sequence >= input.toSequenceInclusive + +- ) { + +- return Stream.fromIterable(events); + +- } + +- return Stream.concat(Stream.fromIterable(events), readPage(last.sequence, nextRemaining)); + +- }), + + ), + + ); + + + @@ apps/server/src/persistence/Layers/OrchestrationEventStore.ts: const makeEventSt + + : Stream.concat(current, loop(last)); + + }), + + ), + -+ ); + + ); + +- return readPage(input.fromSequenceExclusive, limit); + + return loop(input.afterSequence); + -+ }; + -+ + + }; + + + +- const getAggregateReplayStats: OrchestrationEventStoreShape["getAggregateReplayStats"] = ( + + const streamApplicationEvents: OrchestrationEventStoreShape["streamApplicationEvents"] = ( + -+ input, + -+ ) => + + input, + + ) => + +- readAggregateReplayStats({ + +- ...input, + +- limit: Math.max(0, Math.floor(input.maxEvents)) + 1, + +- }).pipe( + +- Effect.mapError( + +- toPersistenceSqlOrDecodeError( + +- "OrchestrationEventStore.getAggregateReplayStats:query", + +- "OrchestrationEventStore.getAggregateReplayStats:decodeRow", + +- ), + +- ), + +- Effect.map((row) => ({ ...row, hasCreateEvent: row.hasCreateEvent !== 0 })), + + Stream.unwrap( + + Effect.gen(function* () { + + const subscription = yield* PubSub.subscribe(committedEvents); + @@ apps/server/src/persistence/Layers/OrchestrationEventStore.ts: const makeEventSt + + ); + + return Stream.concat(replay, live); + + }), + -+ ); + -+ + + ); + + + return { + - append, + - readFromSequence, + +@@ apps/server/src/persistence/Layers/OrchestrationEventStore.ts: const makeEventStore = Effect.gen(function* () { + + getAggregateReplayStats, + readAll: () => readFromSequence(0, Number.MAX_SAFE_INTEGER), + hasEventAfter, + + appendAgentEvents, + @@ apps/server/src/project/ProjectSetupScriptRunner.test.ts + - + -const makeProjectionSnapshotQueryLayer = (project: OrchestrationProject) => + - Layer.succeed(ProjectionSnapshotQuery.ProjectionSnapshotQuery, { + +- getUserInputActivity: () => Effect.die("unused"), + - getCommandReadModel: () => Effect.die("unused"), + - getSnapshot: () => Effect.die("unused"), + - getShellSnapshot: () => Effect.die("unused"), + @@ apps/server/src/project/ProjectSetupScriptRunner.test.ts + - getFirstActiveThreadIdByProjectId: () => Effect.die("unused"), + - getThreadCheckpointContext: () => Effect.die("unused"), + - getFullThreadDiffContext: () => Effect.die("unused"), + +- getThreadRuntimeContext: () => Effect.die("unused"), + - getThreadShellById: () => Effect.die("unused"), + - getThreadDetailById: () => Effect.die("unused"), + - getThreadDetailSnapshot: () => Effect.die("unused"), + @@ apps/server/src/provider/Drivers/ClaudeDriver.ts: import { + } from "../../orchestration-v2/Adapters/ClaudeAdapterV2.ts"; + import { ProviderDriverError } from "../Errors.ts"; + -import { makeClaudeAdapter } from "../Layers/ClaudeAdapter.ts"; + +-import { makeClaudeScopedLimitNames } from "../Layers/claudeUsageLimits.ts"; + import { + checkClaudeProviderStatus, + makePendingClaudeProvider, + @@ apps/server/src/provider/Drivers/ClaudeDriver.ts: export const ClaudeDriver: Pro + continuationGroupKey, + }); + + +- // One per instance: the status probe writes the model-scoped bucket + +- // names it saw, the adapter reads them to place turn-driven events. + +- const scopedLimitNames = yield* makeClaudeScopedLimitNames; + - const adapterOptions = { + - instanceId, + - environment: processEnv, + - modelCatalog, + +- scopedLimitNames, + - ...(eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {}), + - }; + - const adapter = yield* makeClaudeAdapter(effectiveConfig, adapterOptions); + @@ apps/server/src/provider/Drivers/ClaudeDriver.ts: export const ClaudeDriver: Pro + - processEnv, + - cwd, + - resolveClaudeModelCatalog(manifest), + +- scopedLimitNames, + - ), + - ), + - Effect.map(stampIdentity), + @@ apps/server/src/provider/Drivers/CodexDriver.ts: import { + import { ProviderDriverError } from "../Errors.ts"; + -import { makeCodexAdapter } from "../Layers/CodexAdapter.ts"; + -import { + +- CODEX_RESET_CREDIT_TIMEOUT, + +- CodexResetCreditCoordinator, + +-} from "../Layers/codexResetCredit.ts"; + +-import { + - checkCodexProviderStatus, + - makePendingCodexProvider, + - probeCodexSkillsForCwd, + +- withCodexAppServerClient, + -} from "../Layers/CodexProvider.ts"; + -import { resolveCodexLaunchArgs } from "../Layers/codexLaunchArgs.ts"; + -import { ProviderEventLoggers } from "../Layers/ProviderEventLoggers.ts"; + @@ apps/server/src/provider/Drivers/CodexDriver.ts: import { + import type { ProviderDriver, ProviderInstance } from "../ProviderDriver.ts"; + import { withInstanceIdentity } from "./instanceIdentity.ts"; + import { mergeProviderInstanceEnvironment } from "../ProviderInstanceEnvironment.ts"; + -@@ apps/server/src/provider/Drivers/CodexDriver.ts: export type CodexDriverEnv = + +@@ apps/server/src/provider/Drivers/CodexDriver.ts: const UPDATE = makePackageManagedProviderMaintenanceResolver({ + + export type CodexDriverEnv = + + | CodexAdapterV2DriverEnv + + | ChildProcessSpawner.ChildProcessSpawner + +- | CodexResetCreditCoordinator + | Crypto.Crypto + | FileSystem.FileSystem + | HttpClient.HttpClient + @@ apps/server/src/provider/Drivers/CodexDriver.ts: export type CodexDriverEnv = + | ServerSettingsService; + + @@ apps/server/src/provider/Drivers/CodexDriver.ts: export const CodexDriver: ProviderDriver = { + + create: ({ instanceId, displayName, accentColor, environment, enabled, config }) => + + Effect.gen(function* () { + const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; + +- const resetCreditCoordinator = yield* CodexResetCreditCoordinator; + const httpClient = yield* HttpClient.HttpClient; + const serverSettings = yield* ServerSettingsService; + - const eventLoggers = yield* ProviderEventLoggers; + @@ apps/server/src/provider/Drivers/CodexDriver.ts: export const CodexDriver: Provi + - }), + - ), + - ); + +- + +- // Redemption spends something on the user's account. It serialises on + +- // the account (instances sharing a Codex home share the credit), keeps + +- // one idempotency key until Codex reports an outcome, and is bounded so + +- // a hung app-server cannot hold the account lock. + +- // Keyed on the directory holding auth.json: an auth-overlay instance has + +- // its own account under `effectiveHomePath`, while plain instances share + +- // the common home. The continuation key would conflate the two. + +- const accountKey = homeLayout.effectiveHomePath ?? homeLayout.sharedHomePath; + +- const consumeResetCredit: NonNullable = () => + +- resetCreditCoordinator + +- .redeem(accountKey, (idempotencyKey) => + +- Effect.gen(function* () { + +- const { client } = yield* withCodexAppServerClient({ + +- binaryPath: effectiveConfig.binaryPath, + +- homePath: effectiveConfig.homePath, + +- launchArgs: resolveCodexLaunchArgs(effectiveConfig.launchArgs, processEnv), + +- // Account-level request; any directory serves, same as the status probe. + +- cwd: process.cwd(), + +- environment: processEnv, + +- }); + +- const response = yield* client.request("account/rateLimitResetCredit/consume", { + +- idempotencyKey, + +- }); + +- return response.outcome; + +- }).pipe(Effect.scoped, Effect.timeout(CODEX_RESET_CREDIT_TIMEOUT)), + +- ) + +- .pipe( + +- Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), + +- Effect.mapError( + +- (cause) => + +- new ProviderDriverError({ + +- driver: DRIVER_KIND, + +- instanceId, + +- detail: "Codex could not redeem the reset credit.", + +- cause, + +- }), + +- ), + +- // The windows just changed; re-probe so the snapshot says so. A + +- // failed probe republishes the pre-redemption limits rather than + +- // marking them failed, so "confirmed" means `checkedAt` moved + +- // past what was published before the redemption started. + +- Effect.tap(() => + +- Effect.gen(function* () { + +- const before = (yield* snapshot.getSnapshot).usageLimits?.checkedAt; + +- const refreshed = yield* snapshot.refresh; + +- const after = refreshed.usageLimits?.checkedAt; + +- if ( + +- after === undefined || + +- after === before || + +- refreshed.usageLimits?.unavailable?.reason === "probeFailed" + +- ) { + +- return yield* new ProviderDriverError({ + +- driver: DRIVER_KIND, + +- instanceId, + +- detail: + +- "The reset was applied, but Codex could not confirm the new limits. Refresh to check.", + +- }); + +- } + +- }), + +- ), + +- ); + + return { + instanceId, + @@ apps/server/src/provider/Drivers/CodexDriver.ts: export const CodexDriver: Provi + enabled, + snapshot, + - snapshotForCwd, + +- consumeResetCredit, + - adapter, + orchestrationAdapter, + textGeneration, + @@ apps/server/src/provider/Drivers/CursorDriver.ts: import { + import { makeManagedServerProvider } from "../makeManagedServerProvider.ts"; + import { + defaultProviderContinuationIdentity, + +@@ apps/server/src/provider/Drivers/CursorDriver.ts: import { + + makeProviderSnapshotSettingsSource, + + type ProviderSnapshotSettings, + + } from "../providerUpdateSettings.ts"; + +-import { probeCursorSkills } from "./CursorSkills.ts"; + + const decodeCursorSettings = Schema.decodeSync(CursorSettings); + + + + const DRIVER_KIND = ProviderDriverKind.make("cursor"); + @@ apps/server/src/provider/Drivers/CursorDriver.ts: export type CursorDriverEnv = + | FileSystem.FileSystem + | HttpClient.HttpClient + @@ apps/server/src/provider/Drivers/CursorDriver.ts: export const CursorDriver: Pro + accentColor, + enabled, + snapshot, + +- snapshotForCwd: (cwd) => + +- !effectiveConfig.enabled + +- ? snapshot.getSnapshot + +- : Effect.all([ + +- snapshot.getSnapshot, + +- probeCursorSkills(cwd, processEnv).pipe( + +- Effect.provideService(FileSystem.FileSystem, fileSystem), + +- Effect.provideService(Path.Path, path), + +- Effect.mapError( + +- (cause) => + +- new ProviderDriverError({ + +- driver: DRIVER_KIND, + +- instanceId, + +- detail: `Failed to discover Cursor skills for '${cwd}'`, + +- cause, + +- }), + +- ), + +- ), + +- ]).pipe(Effect.map(([machineSnapshot, skills]) => ({ ...machineSnapshot, skills }))), + - adapter, + orchestrationAdapter, + textGeneration, + @@ apps/server/src/provider/Drivers/GrokDriver.ts: import { + import { makeManagedServerProvider } from "../makeManagedServerProvider.ts"; + import { + defaultProviderContinuationIdentity, + +@@ apps/server/src/provider/Drivers/GrokDriver.ts: import { + + } from "../ProviderDriver.ts"; + + import { withInstanceIdentity } from "./instanceIdentity.ts"; + + import { mergeProviderInstanceEnvironment } from "../ProviderInstanceEnvironment.ts"; + +-import { discoverGrokSkills } from "./GrokSkills.ts"; + + import { + + makeManualOnlyProviderMaintenanceCapabilities, + + makeStaticProviderMaintenanceResolver, + @@ apps/server/src/provider/Drivers/GrokDriver.ts: export type GrokDriverEnv = + | FileSystem.FileSystem + | HttpClient.HttpClient + @@ apps/server/src/provider/Drivers/GrokDriver.ts: export const GrokDriver: Provide + Effect.map(stampIdentity), + Effect.provideService(Crypto.Crypto, crypto), + Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), + +@@ apps/server/src/provider/Drivers/GrokDriver.ts: export const GrokDriver: ProviderDriver = { + + }), + + ), + + ); + +- const snapshotForCwd = (workspaceCwd: string) => + +- !effectiveConfig.enabled + +- ? snapshot.getSnapshot + +- : Effect.all([ + +- snapshot.getSnapshot, + +- discoverGrokSkills(effectiveConfig, processEnv, workspaceCwd).pipe( + +- Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), + +- Effect.mapError( + +- (cause) => + +- new ProviderDriverError({ + +- driver: DRIVER_KIND, + +- instanceId, + +- detail: `Failed to discover Grok skills for '${workspaceCwd}'`, + +- cause, + +- }), + +- ), + +- ), + +- ]).pipe(Effect.map(([machineSnapshot, skills]) => ({ ...machineSnapshot, skills }))); + + + + return { + + instanceId, + @@ apps/server/src/provider/Drivers/GrokDriver.ts: export const GrokDriver: ProviderDriver = { + accentColor, + enabled, + snapshot, + +- snapshotForCwd, + - adapter, + orchestrationAdapter, + textGeneration, + @@ apps/server/src/provider/Drivers/OpenCodeDriver.ts: export const OpenCodeDriver: + Effect.provideService(OpenCodeServerOwner.OpenCodeServerOwner, serverOwner), + Effect.provideService(OpenCodeRuntime, openCodeRuntime), + ); + +- // NOTE: the local branch intentionally uses the shared SDK server + +- // instead of `opencode debug skill` (loadSkillsFromCli). The CLI writes + +- // its full JSON inventory to stdout, but the Bun-compiled binary does + +- // not flush more than one 64KB pipe buffer to a non-TTY stdout, so the + +- // piped output arrives truncated and unparseable — which degrades to an + +- // empty skill list and poisons the workspace snapshot the `$` picker + +- // reads. The SDK `app.skills` endpoint honors the per-request directory + +- // and returns complete results regardless of size. + - const loadSkillsForCwd = (cwd: string) => + - effectiveConfig.serverUrl.trim().length > 0 + - ? Effect.scoped( + @@ apps/server/src/provider/Drivers/OpenCodeDriver.ts: export const OpenCodeDriver: + - return yield* openCodeRuntime.loadOpenCodeSkills(client); + - }), + - ) + -- : openCodeRuntime.loadSkillsFromCli({ + -- binaryPath: effectiveConfig.binaryPath, + -- cwd, + -- environment: processEnv, + -- }); + +- : serverOwner.withServer((server) => + +- openCodeRuntime.loadOpenCodeSkills( + +- openCodeRuntime.createOpenCodeSdkClient({ + +- baseUrl: server.url, + +- directory: cwd, + +- ...(server.serverPassword !== undefined + +- ? { serverPassword: server.serverPassword } + +- : {}), + +- }), + +- ), + +- ); + + const snapshotSettings = makeProviderSnapshotSettingsSource(effectiveConfig, serverSettings); + const snapshot = yield* makeManagedServerProvider>( + @@ apps/server/src/provider/Layers/CodexAdapter.test.ts (deleted) + - }), + - ); + - + -- public readonly interruptTurnImpl = vi.fn( + -- (_turnId?: TurnId): Promise => Promise.resolve(undefined), + +- public readonly compactThread = Effect.void; + +- + +- public readonly interruptTurnImpl = vi.fn((_turnId?: TurnId): Promise => + +- Promise.resolve(undefined), + - ); + - + -- public readonly readThreadImpl = vi.fn( + -- (): Promise => + -- Promise.resolve({ + -- threadId: "provider-thread-1", + -- turns: [], + -- }), + +- public readonly readThreadImpl = vi.fn((): Promise => + +- Promise.resolve({ + +- threadId: "provider-thread-1", + +- turns: [], + +- }), + - ); + - + -- public readonly rollbackThreadImpl = vi.fn( + -- (_numTurns: number): Promise => + -- Promise.resolve({ + -- threadId: "provider-thread-1", + -- turns: [], + -- }), + +- public readonly rollbackThreadImpl = vi.fn((_numTurns: number): Promise => + +- Promise.resolve({ + +- threadId: "provider-thread-1", + +- turns: [], + +- }), + - ); + - + - public readonly uploadFeedbackImpl = vi.fn((_reason?: string) => + @@ apps/server/src/provider/Layers/CodexAdapter.test.ts (deleted) + - }), + - ); + - + +- it.effect("compacts the active Codex thread and emits compacted state", () => + +- Effect.gen(function* () { + +- const adapter = yield* CodexAdapter; + +- const threadId = asThreadId("thread-compact"); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("codex"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- const runtime = sessionRuntimeFactory.lastRuntime; + +- NodeAssert.ok(runtime); + +- const compactedEventFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.type === "thread.state.changed"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- yield* adapter.compactThread!(threadId); + +- yield* runtime.emit({ + +- id: asEventId("evt-compaction-item-completed"), + +- kind: "notification", + +- provider: ProviderDriverKind.make("codex"), + +- createdAt: "2026-01-01T00:00:00.000Z", + +- method: "item/completed", + +- threadId, + +- payload: { + +- completedAtMs: 1_778_000_000_000, + +- threadId: "provider-thread-1", + +- turnId: "provider-compact-turn", + +- item: { + +- id: "provider-compact-item", + +- type: "contextCompaction", + +- }, + +- }, + +- }); + +- const event = Option.getOrThrow(yield* Fiber.join(compactedEventFiber)); + +- NodeAssert.ok(event.type === "thread.state.changed"); + +- NodeAssert.equal(event.payload.state, "compacted"); + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + - it.effect("uploads feedback for the active Codex thread", () => + - Effect.gen(function* () { + - const adapter = yield* CodexAdapter; + @@ apps/server/src/provider/Layers/CodexAdapter.test.ts (deleted) + - }); + -} + - + +-function codexTokenUsageEvent(input: { + +- readonly id: string; + +- readonly turnId: string; + +- readonly inputTokens: number; + +- readonly cachedInputTokens: number; + +- readonly cacheCreationTokens: number; + +- readonly outputTokens: number; + +- readonly reasoningTokens: number; + +- readonly last?: { + +- readonly inputTokens: number; + +- readonly cachedInputTokens: number; + +- readonly cacheCreationTokens: number; + +- readonly outputTokens: number; + +- readonly reasoningTokens: number; + +- }; + +-}): ProviderEvent { + +- const totalTokens = input.inputTokens + input.outputTokens; + +- const last = input.last ?? input; + +- return { + +- id: asEventId(input.id), + +- kind: "notification", + +- provider: ProviderDriverKind.make("codex"), + +- threadId: asThreadId("thread-1"), + +- turnId: asTurnId(input.turnId), + +- createdAt: "2026-01-01T00:00:00.000Z", + +- method: "thread/tokenUsage/updated", + +- payload: { + +- threadId: "thread-1", + +- turnId: input.turnId, + +- tokenUsage: { + +- total: { + +- inputTokens: input.inputTokens, + +- cachedInputTokens: input.cachedInputTokens, + +- cacheWriteInputTokens: input.cacheCreationTokens, + +- outputTokens: input.outputTokens, + +- reasoningOutputTokens: input.reasoningTokens, + +- totalTokens, + +- }, + +- last: { + +- inputTokens: last.inputTokens, + +- cachedInputTokens: last.cachedInputTokens, + +- cacheWriteInputTokens: last.cacheCreationTokens, + +- outputTokens: last.outputTokens, + +- reasoningOutputTokens: last.reasoningTokens, + +- totalTokens: last.inputTokens + last.outputTokens, + +- }, + +- }, + +- }, + +- }; + +-} + +- + +-function codexTurnEvent(method: "turn/started" | "turn/completed", turnId: string): ProviderEvent { + +- return { + +- id: asEventId(`evt-${method}-${turnId}`), + +- kind: "notification", + +- provider: ProviderDriverKind.make("codex"), + +- threadId: asThreadId("thread-1"), + +- turnId: asTurnId(turnId), + +- createdAt: "2026-01-01T00:00:00.000Z", + +- method, + +- payload: + +- method === "turn/started" + +- ? {} + +- : { + +- threadId: "thread-1", + +- turn: { id: turnId, items: [], status: "completed" }, + +- }, + +- }; + +-} + +- + -lifecycleLayer("CodexAdapterLive lifecycle", (it) => { + +- it.effect("calculates one Codex turn total from cumulative counters", () => + +- Effect.gen(function* () { + +- const { adapter, runtime } = yield* startLifecycleRuntime(); + +- const completedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.type === "turn.completed"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- + +- yield* runtime.emit(codexTurnEvent("turn/started", "turn-usage")); + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-usage-1", + +- turnId: "turn-usage", + +- inputTokens: 100, + +- cachedInputTokens: 40, + +- cacheCreationTokens: 10, + +- outputTokens: 20, + +- reasoningTokens: 8, + +- }), + +- ); + +- // Codex can repeat both notifications without new work. + +- yield* runtime.emit(codexTurnEvent("turn/started", "turn-usage")); + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-usage-duplicate", + +- turnId: "turn-usage", + +- inputTokens: 100, + +- cachedInputTokens: 40, + +- cacheCreationTokens: 10, + +- outputTokens: 20, + +- reasoningTokens: 8, + +- }), + +- ); + +- yield* runtime.emit({ + +- id: asEventId("evt-collab-activity"), + +- kind: "notification", + +- provider: ProviderDriverKind.make("codex"), + +- threadId: asThreadId("thread-1"), + +- turnId: asTurnId("turn-usage"), + +- createdAt: "2026-01-01T00:00:00.000Z", + +- method: "collabAgent/activity", + +- payload: { + +- agentThreadId: "child-1", + +- agentPath: "/root/child-1", + +- activityKind: "started", + +- }, + +- }); + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-usage-2", + +- turnId: "turn-usage", + +- inputTokens: 150, + +- cachedInputTokens: 60, + +- cacheCreationTokens: 15, + +- outputTokens: 30, + +- reasoningTokens: 12, + +- }), + +- ); + +- yield* runtime.emit(codexTurnEvent("turn/completed", "turn-usage")); + +- + +- const completed = yield* Fiber.join(completedFiber); + +- NodeAssert.equal(completed._tag, "Some"); + +- if (completed._tag === "Some" && completed.value.type === "turn.completed") { + +- NodeAssert.deepStrictEqual(completed.value.payload.tokenUsage, { + +- usageStatus: "complete", + +- usageScope: "main_agent", + +- inputTokens: 150, + +- cachedInputTokens: 60, + +- cacheCreationTokens: 15, + +- outputTokens: 30, + +- reasoningTokens: 12, + +- hasSubagents: true, + +- }); + +- } + +- }), + +- ); + +- + +- it.effect("does not charge a late prior-turn update to the next Codex turn", () => + +- Effect.gen(function* () { + +- const { adapter, runtime } = yield* startLifecycleRuntime(); + +- const completedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.type === "turn.completed"), + +- Stream.take(2), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- + +- yield* runtime.emit(codexTurnEvent("turn/started", "turn-first")); + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-late-1", + +- turnId: "turn-first", + +- inputTokens: 100, + +- cachedInputTokens: 40, + +- cacheCreationTokens: 10, + +- outputTokens: 20, + +- reasoningTokens: 8, + +- }), + +- ); + +- yield* runtime.emit(codexTurnEvent("turn/completed", "turn-first")); + +- yield* runtime.emit(codexTurnEvent("turn/started", "turn-second")); + +- // A late update for the finished turn lands after the next turn starts. + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-late-2", + +- turnId: "turn-first", + +- inputTokens: 150, + +- cachedInputTokens: 60, + +- cacheCreationTokens: 15, + +- outputTokens: 30, + +- reasoningTokens: 12, + +- }), + +- ); + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-late-3", + +- turnId: "turn-second", + +- inputTokens: 170, + +- cachedInputTokens: 65, + +- cacheCreationTokens: 16, + +- outputTokens: 35, + +- reasoningTokens: 14, + +- }), + +- ); + +- yield* runtime.emit(codexTurnEvent("turn/completed", "turn-second")); + +- + +- const completed = Array.from(yield* Fiber.join(completedFiber)); + +- const second = completed[1]; + +- NodeAssert.equal(second?.type, "turn.completed"); + +- if (second?.type === "turn.completed") { + +- NodeAssert.deepStrictEqual(second.payload.tokenUsage, { + +- usageStatus: "complete", + +- usageScope: "main_agent", + +- inputTokens: 20, + +- cachedInputTokens: 5, + +- cacheCreationTokens: 1, + +- outputTokens: 5, + +- reasoningTokens: 2, + +- hasSubagents: false, + +- }); + +- } + +- }), + +- ); + +- + +- it.effect("clamps Codex cache and reasoning subsets to their totals", () => + +- Effect.gen(function* () { + +- const { adapter, runtime } = yield* startLifecycleRuntime(); + +- const completedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.type === "turn.completed"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- + +- yield* runtime.emit(codexTurnEvent("turn/started", "turn-clamp")); + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-clamp-1", + +- turnId: "turn-clamp", + +- inputTokens: 100, + +- cachedInputTokens: 140, + +- cacheCreationTokens: 120, + +- outputTokens: 20, + +- reasoningTokens: 30, + +- }), + +- ); + +- yield* runtime.emit(codexTurnEvent("turn/completed", "turn-clamp")); + +- + +- const completed = yield* Fiber.join(completedFiber); + +- NodeAssert.equal(completed._tag, "Some"); + +- if (completed._tag === "Some" && completed.value.type === "turn.completed") { + +- NodeAssert.deepStrictEqual(completed.value.payload.tokenUsage, { + +- usageStatus: "complete", + +- usageScope: "main_agent", + +- inputTokens: 100, + +- cachedInputTokens: 100, + +- cacheCreationTokens: 100, + +- outputTokens: 20, + +- reasoningTokens: 20, + +- hasSubagents: false, + +- }); + +- } + +- }), + +- ); + +- + +- it.effect("counts the last response when Codex resets its running total mid-turn", () => + +- Effect.gen(function* () { + +- const { adapter, runtime } = yield* startLifecycleRuntime(); + +- const completedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.type === "turn.completed"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- + +- yield* runtime.emit(codexTurnEvent("turn/started", "turn-reset")); + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-reset-1", + +- turnId: "turn-reset", + +- inputTokens: 5_000, + +- cachedInputTokens: 4_000, + +- cacheCreationTokens: 100, + +- outputTokens: 500, + +- reasoningTokens: 200, + +- last: { + +- inputTokens: 100, + +- cachedInputTokens: 80, + +- cacheCreationTokens: 10, + +- outputTokens: 20, + +- reasoningTokens: 8, + +- }, + +- }), + +- ); + +- // Codex restarted its cumulative total. The new total is smaller than + +- // the previous one, so only `last` is counted for this update. + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-reset-2", + +- turnId: "turn-reset", + +- inputTokens: 150, + +- cachedInputTokens: 90, + +- cacheCreationTokens: 5, + +- outputTokens: 30, + +- reasoningTokens: 12, + +- }), + +- ); + +- yield* runtime.emit(codexTurnEvent("turn/completed", "turn-reset")); + +- + +- const completed = yield* Fiber.join(completedFiber); + +- NodeAssert.equal(completed._tag, "Some"); + +- if (completed._tag === "Some" && completed.value.type === "turn.completed") { + +- NodeAssert.deepStrictEqual(completed.value.payload.tokenUsage, { + +- usageStatus: "complete", + +- usageScope: "main_agent", + +- inputTokens: 250, + +- cachedInputTokens: 170, + +- cacheCreationTokens: 15, + +- outputTokens: 50, + +- reasoningTokens: 20, + +- hasSubagents: false, + +- }); + +- } + +- }), + +- ); + +- + +- it.effect("uses the last response usage when no prior Codex total exists", () => + +- Effect.gen(function* () { + +- const adapter = yield* CodexAdapter; + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("codex"), + +- threadId: asThreadId("thread-1"), + +- resumeCursor: { threadId: "provider-thread-1" }, + +- runtimeMode: "full-access", + +- }); + +- const runtime = lifecycleRuntimeFactory.lastRuntime; + +- NodeAssert.ok(runtime); + +- const firstCompletionsFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.type === "turn.completed"), + +- Stream.take(2), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- + +- // Resumed thread: the cumulative total already holds old history, so the + +- // first update must count only `last`. + +- yield* runtime.emit(codexTurnEvent("turn/started", "turn-resumed")); + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-resume-baseline", + +- turnId: "turn-resumed", + +- inputTokens: 1_000, + +- cachedInputTokens: 400, + +- cacheCreationTokens: 100, + +- outputTokens: 200, + +- reasoningTokens: 80, + +- last: { + +- inputTokens: 300, + +- cachedInputTokens: 120, + +- cacheCreationTokens: 30, + +- outputTokens: 60, + +- reasoningTokens: 24, + +- }, + +- }), + +- ); + +- yield* runtime.emit(codexTurnEvent("turn/completed", "turn-resumed")); + +- + +- yield* runtime.emit(codexTurnEvent("turn/started", "turn-after-resume")); + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-after-resume", + +- turnId: "turn-after-resume", + +- inputTokens: 1_100, + +- cachedInputTokens: 440, + +- cacheCreationTokens: 110, + +- outputTokens: 220, + +- reasoningTokens: 88, + +- }), + +- ); + +- yield* runtime.emit(codexTurnEvent("turn/completed", "turn-after-resume")); + +- + +- const firstCompletions = Array.from(yield* Fiber.join(firstCompletionsFiber)); + +- + +- yield* adapter.rollbackThread(asThreadId("thread-1"), 1); + +- const rollbackCompletionFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.type === "turn.completed"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- // Rollback drops the baseline and Codex shrinks its total, so the first + +- // update after it counts only `last` again. + +- yield* runtime.emit(codexTurnEvent("turn/started", "turn-after-rollback")); + +- yield* runtime.emit( + +- codexTokenUsageEvent({ + +- id: "evt-after-rollback", + +- turnId: "turn-after-rollback", + +- inputTokens: 1_050, + +- cachedInputTokens: 420, + +- cacheCreationTokens: 105, + +- outputTokens: 210, + +- reasoningTokens: 84, + +- last: { + +- inputTokens: 50, + +- cachedInputTokens: 20, + +- cacheCreationTokens: 5, + +- outputTokens: 10, + +- reasoningTokens: 4, + +- }, + +- }), + +- ); + +- yield* runtime.emit(codexTurnEvent("turn/completed", "turn-after-rollback")); + +- + +- const rollbackCompletion = yield* Fiber.join(rollbackCompletionFiber); + +- const completions = [ + +- ...firstCompletions, + +- ...(rollbackCompletion._tag === "Some" ? [rollbackCompletion.value] : []), + +- ]; + +- NodeAssert.deepStrictEqual( + +- completions.map((event) => + +- event.type === "turn.completed" ? event.payload.tokenUsage : undefined, + +- ), + +- [ + +- { + +- usageStatus: "complete", + +- usageScope: "main_agent", + +- inputTokens: 300, + +- cachedInputTokens: 120, + +- cacheCreationTokens: 30, + +- outputTokens: 60, + +- reasoningTokens: 24, + +- hasSubagents: false, + +- }, + +- { + +- usageStatus: "complete", + +- usageScope: "main_agent", + +- inputTokens: 100, + +- cachedInputTokens: 40, + +- cacheCreationTokens: 10, + +- outputTokens: 20, + +- reasoningTokens: 8, + +- hasSubagents: false, + +- }, + +- { + +- usageStatus: "complete", + +- usageScope: "main_agent", + +- inputTokens: 50, + +- cachedInputTokens: 20, + +- cacheCreationTokens: 5, + +- outputTokens: 10, + +- reasoningTokens: 4, + +- hasSubagents: false, + +- }, + +- ], + +- ); + +- }), + +- ); + +- + - it.effect("carries child model metadata through every task event", () => + - Effect.gen(function* () { + - const { adapter, runtime } = yield* startLifecycleRuntime(); + @@ apps/server/src/provider/Layers/CodexAdapter.test.ts (deleted) + - }), + - ); + - + +- it.effect("presents browser and computer-use calls with Codex-style titles and sources", () => + +- Effect.gen(function* () { + +- const { adapter, runtime } = yield* startLifecycleRuntime(); + +- const eventsFiber = yield* Stream.runCollect(Stream.take(adapter.streamEvents, 3)).pipe( + +- Effect.forkChild, + +- ); + +- const longIntentTitle = ` ${"a".repeat(39)} ${"a".repeat(38)}😀bc `; + +- const serializedOverContractUrl = `https://example.com/?query=${"😀".repeat(400)}`; + +- + +- yield* runtime.emit({ + +- id: asEventId("evt-computer-start"), + +- kind: "notification", + +- provider: ProviderDriverKind.make("codex"), + +- createdAt: "2026-01-01T00:00:00.000Z", + +- method: "item/started", + +- threadId: asThreadId("thread-1"), + +- turnId: asTurnId("turn-1"), + +- itemId: asItemId("computer_1"), + +- payload: { + +- startedAtMs: 1_778_000_000_000, + +- threadId: "thread-1", + +- turnId: "turn-1", + +- item: { + +- type: "mcpToolCall", + +- id: "computer_1", + +- server: "node_repl", + +- tool: "js", + +- arguments: { + +- code: 'await sky.click({ app: "Finder", x: 10, y: 20 })', + +- title: longIntentTitle, + +- }, + +- durationMs: null, + +- error: null, + +- result: { + +- _meta: { + +- "codex/toolSurface": { + +- kind: "computerUse", + +- app: { kind: "appId", appId: "com.apple.finder" }, + +- }, + +- }, + +- content: [], + +- }, + +- status: "inProgress", + +- }, + +- }, + +- }); + +- yield* runtime.emit({ + +- id: asEventId("evt-browser-complete"), + +- kind: "notification", + +- provider: ProviderDriverKind.make("codex"), + +- createdAt: "2026-01-01T00:00:01.000Z", + +- method: "item/completed", + +- threadId: asThreadId("thread-1"), + +- turnId: asTurnId("turn-1"), + +- itemId: asItemId("browser_1"), + +- payload: { + +- completedAtMs: 1_778_000_001_000, + +- threadId: "thread-1", + +- turnId: "turn-1", + +- item: { + +- type: "mcpToolCall", + +- id: "browser_1", + +- server: "node_repl", + +- tool: "js", + +- arguments: { code: "await tab.playwright.domSnapshot()", title: "Inspect checkout" }, + +- durationMs: 12, + +- error: null, + +- result: { + +- _meta: { + +- "codex/toolSurface": { + +- kind: "browserUse", + +- backend: "chrome", + +- openTabs: [ + +- { + +- pageUrl: "https://www.mathworks.com/help/matlab/", + +- faviconUrl: "https://www.mathworks.com/favicon.ico", + +- faviconUrlDark: "https://www.mathworks.com/favicon-dark.ico", + +- url: "https://www.mathworks.com/help/matlab/", + +- }, + +- ], + +- }, + +- browser_use: { url: serializedOverContractUrl }, + +- }, + +- content: [], + +- }, + +- status: "completed", + +- }, + +- }, + +- }); + +- yield* runtime.emit({ + +- id: asEventId("evt-computer-use-complete"), + +- kind: "notification", + +- provider: ProviderDriverKind.make("codex"), + +- createdAt: "2026-01-01T00:00:02.000Z", + +- method: "item/completed", + +- threadId: asThreadId("thread-1"), + +- turnId: asTurnId("turn-1"), + +- itemId: asItemId("computer_2"), + +- payload: { + +- completedAtMs: 1_778_000_002_000, + +- threadId: "thread-1", + +- turnId: "turn-1", + +- item: { + +- type: "mcpToolCall", + +- id: "computer_2", + +- server: "computer-use", + +- tool: "type_text", + +- arguments: { text: "Hello world", app: "TextEdit" }, + +- durationMs: 12, + +- error: null, + +- result: { + +- _meta: { + +- "codex/toolSurface": { + +- kind: "computerUse", + +- app: { kind: "displayName", displayName: "TextEdit" }, + +- }, + +- }, + +- content: [], + +- }, + +- status: "completed", + +- }, + +- }, + +- }); + +- + +- const events = Array.from(yield* Fiber.join(eventsFiber)); + +- NodeAssert.deepStrictEqual( + +- events.map((event) => ({ + +- type: event.type, + +- title: "title" in event.payload ? event.payload.title : undefined, + +- toolSurface: "toolSurface" in event.payload ? event.payload.toolSurface : undefined, + +- toolIcon: "toolIcon" in event.payload ? event.payload.toolIcon : undefined, + +- toolSource: "toolSource" in event.payload ? event.payload.toolSource : undefined, + +- })), + +- [ + +- { + +- type: "item.started", + +- title: `${"a".repeat(39)} ${"a".repeat(38)}😀…`, + +- toolSurface: "computer", + +- toolIcon: { + +- _tag: "native-app", + +- app: { _tag: "app-id", appId: "com.apple.finder" }, + +- }, + +- toolSource: { + +- key: "native-app:com.apple.finder", + +- name: "Finder", + +- kind: "computer", + +- icon: { + +- _tag: "native-app", + +- app: { _tag: "app-id", appId: "com.apple.finder" }, + +- }, + +- }, + +- }, + +- { + +- type: "item.completed", + +- title: "Inspect checkout", + +- toolSurface: "browser", + +- toolIcon: { + +- _tag: "website", + +- pageUrl: "https://www.mathworks.com/help/matlab/", + +- faviconUrl: "https://www.mathworks.com/favicon.ico", + +- faviconUrlDark: "https://www.mathworks.com/favicon-dark.ico", + +- }, + +- toolSource: { + +- key: "browser-use:chrome", + +- name: "Chrome", + +- kind: "integration", + +- icon: { + +- _tag: "native-app", + +- app: { _tag: "display-name", displayName: "Google Chrome" }, + +- }, + +- }, + +- }, + +- { + +- type: "item.completed", + +- title: "Typed text in TextEdit", + +- toolSurface: "computer", + +- toolIcon: { + +- _tag: "native-app", + +- app: { _tag: "display-name", displayName: "TextEdit" }, + +- }, + +- toolSource: { + +- key: "native-app-name:textedit", + +- name: "TextEdit", + +- kind: "computer", + +- icon: { + +- _tag: "native-app", + +- app: { _tag: "display-name", displayName: "TextEdit" }, + +- }, + +- }, + +- }, + +- ], + +- ); + +- }), + +- ); + +- + - it.effect("preserves failed and declined outcomes on completed tool items", () => + - Effect.gen(function* () { + - const { adapter, runtime } = yield* startLifecycleRuntime(); + +- const maxLengthAppId = `com.${"a".repeat(508)}`; + +- const collidingMaxLengthAppId = `com.${"a".repeat(507)}b`; + +- const longAppSourceKeys: string[] = []; + - const items = [ + - { + - type: "commandExecution", + @@ apps/server/src/provider/Layers/CodexAdapter.test.ts (deleted) + - status: "failed", + - }, + - { + +- type: "mcpToolCall", + +- id: "failed-computer", + +- server: "computer-use", + +- tool: "click", + +- arguments: { app: "Finder" }, + +- error: { message: "Click failed" }, + +- result: { + +- _meta: { + +- "codex/toolSurface": { + +- kind: "computerUse", + +- app: { kind: "appId", appId: maxLengthAppId }, + +- }, + +- }, + +- content: [], + +- }, + +- status: "failed", + +- }, + +- { + +- type: "mcpToolCall", + +- id: "failed-computer-collision", + +- server: "computer-use", + +- tool: "click", + +- arguments: { app: "Other" }, + +- error: { message: "Click failed" }, + +- result: { + +- _meta: { + +- "codex/toolSurface": { + +- kind: "computerUse", + +- app: { kind: "appId", appId: collidingMaxLengthAppId }, + +- }, + +- }, + +- content: [], + +- }, + +- status: "failed", + +- }, + +- { + - type: "fileChange", + - id: "declined-change", + - changes: [], + @@ apps/server/src/provider/Layers/CodexAdapter.test.ts (deleted) + - return; + - } + - NodeAssert.equal(firstEvent.value.payload.status, item.status); + +- if (item.id.startsWith("failed-computer")) { + +- NodeAssert.equal(firstEvent.value.payload.title, "computer-use · click"); + +- const sourceKey = firstEvent.value.payload.toolSource?.key; + +- NodeAssert.equal(sourceKey?.length, 512); + +- if (sourceKey) longAppSourceKeys.push(sourceKey); + +- } + - } + +- NodeAssert.equal(new Set(longAppSourceKeys).size, 2); + - }), + - ); + - + @@ apps/server/src/provider/Layers/CodexAdapter.test.ts (deleted) + - }), + - ); + - + +- it.effect("maps async agent questions without ending the turn", () => + +- Effect.gen(function* () { + +- const { adapter, runtime } = yield* startLifecycleRuntime(); + +- const eventsFiber = yield* Stream.runCollect(Stream.take(adapter.streamEvents, 2)).pipe( + +- Effect.forkChild, + +- ); + +- yield* runtime.emit({ + +- id: asEventId("evt-async-question"), + +- kind: "notification", + +- provider: ProviderDriverKind.make("codex"), + +- threadId: asThreadId("thread-1"), + +- createdAt: "2026-01-01T00:00:00.000Z", + +- method: "item/completed", + +- payload: { + +- completedAtMs: 0, + +- threadId: "thread-1", + +- turnId: "turn-1", + +- item: { + +- type: "agentMessage", + +- id: "async-question-1", + +- text: "Which package manager?\n- pnpm\n- npm\n\nWhat should it be named?", + +- phase: "final_answer", + +- delivery: "async", + +- questions: [ + +- { title: "Which package manager?", options: ["pnpm", "npm"] }, + +- { title: "What should it be named?" }, + +- ], + +- }, + +- }, + +- }); + +- yield* runtime.emit({ + +- id: asEventId("evt-async-continued"), + +- kind: "notification", + +- provider: ProviderDriverKind.make("codex"), + +- threadId: asThreadId("thread-1"), + +- createdAt: "2026-01-01T00:00:01.000Z", + +- method: "item/agentMessage/delta", + +- payload: { + +- threadId: "thread-1", + +- turnId: "turn-1", + +- itemId: "message-2", + +- delta: "I will keep working.", + +- }, + +- }); + +- const events = Array.from(yield* Fiber.join(eventsFiber)); + +- NodeAssert.equal(events[0]?.type, "user-input.requested"); + +- NodeAssert.equal(events[0]?.requestId, "codex-async:thread-1:async-question-1"); + +- NodeAssert.deepEqual(events[0]?.payload, { + +- responseMode: "message", + +- questions: [ + +- { + +- id: "0", + +- header: "Question", + +- question: "Which package manager?", + +- options: [ + +- { label: "pnpm", description: "" }, + +- { label: "npm", description: "" }, + +- ], + +- allowCustomAnswer: true, + +- multiSelect: false, + +- }, + +- { + +- id: "1", + +- header: "Question", + +- question: "What should it be named?", + +- options: [], + +- allowCustomAnswer: true, + +- multiSelect: false, + +- }, + +- ], + +- }); + +- NodeAssert.equal(events[1]?.type, "content.delta"); + +- }), + +- ); + +- + - it.effect("unwraps Codex token usage payloads for context window events", () => + - Effect.gen(function* () { + - const { adapter, runtime } = yield* startLifecycleRuntime(); + @@ apps/server/src/provider/Layers/CursorAdapter.test.ts (deleted) + -} from "@t3tools/contracts"; + - + -import { ServerConfig } from "../../config.ts"; + +-import { buildRuntimeInstructions } from "../RuntimeInstructions.ts"; + -import { ServerSettingsService } from "../../serverSettings.ts"; + -import type { CursorAdapterShape } from "../Services/CursorAdapter.ts"; + -import { makeCursorAdapter } from "./CursorAdapter.ts"; + @@ apps/server/src/provider/Layers/CursorAdapter.ts (deleted) + - + -import { resolveAttachmentPath } from "../../attachmentStore.ts"; + -import { ServerConfig } from "../../config.ts"; + +-import { buildRuntimeInstructions } from "../RuntimeInstructions.ts"; + -import * as McpProviderSession from "../../mcp/McpProviderSession.ts"; + -import { + - ProviderAdapterProcessError, + @@ apps/server/src/provider/Layers/CursorAdapter.ts (deleted) + - }); + - } + - + +- // ACP has no system-message field; keep runtime context separate from the user's text. + - const result = yield* ctx.acp + - .prompt({ + -- prompt: promptParts, + +- prompt: [ + +- ...promptParts, + +- { + +- type: "text", + +- text: buildRuntimeInstructions({ harness: "Cursor", model: resolvedModel }), + +- }, + +- ], + - }) + - .pipe( + - Effect.mapError((error) => + @@ apps/server/src/provider/Layers/GrokAdapter.test.ts (deleted) + -}); + - + -it.layer(grokAdapterTestLayer)("GrokAdapterLive", (it) => { + +- it.effect("sends runtime context with the current model without changing saved prompts", () => + +- Effect.gen(function* () { + +- const threadId = ThreadId.make("grok-runtime-context"); + +- const tempDir = yield* Effect.promise(() => + +- NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "grok-runtime-context-")), + +- ); + +- const requestLogPath = NodePath.join(tempDir, "requests.ndjson"); + +- const wrapperPath = yield* Effect.promise(() => + +- makeMockGrokWrapper({ T3_ACP_REQUEST_LOG_PATH: requestLogPath }), + +- ); + +- const adapter = yield* makeTestAdapter(wrapperPath); + +- yield* adapter.startSession({ + +- threadId, + +- cwd: process.cwd(), + +- runtimeMode: "full-access", + +- modelSelection: { instanceId: ProviderInstanceId.make("grok"), model: "grok-mock-alt" }, + +- }); + +- yield* adapter.sendTurn({ threadId, input: "First prompt" }); + +- yield* adapter.sendTurn({ + +- threadId, + +- input: "Second prompt", + +- modelSelection: { + +- instanceId: ProviderInstanceId.make("grok"), + +- model: "grok-4.6", + +- options: [{ id: "reasoningEffort", value: "low" }], + +- }, + +- }); + +- const snapshot = yield* adapter.readThread(threadId); + +- assert.deepEqual( + +- snapshot.turns.map((turn) => turn.items), + +- [ + +- [ + +- { + +- prompt: [{ type: "text", text: "First prompt" }], + +- result: { stopReason: "end_turn" }, + +- }, + +- ], + +- [ + +- { + +- prompt: [{ type: "text", text: "Second prompt" }], + +- result: { stopReason: "end_turn" }, + +- }, + +- ], + +- ], + +- ); + +- yield* adapter.stopSession(threadId); + +- const requests = yield* Effect.promise(() => readJsonLines(requestLogPath)); + +- const prompts = requests + +- .filter((request) => request.method === "session/prompt") + +- .map( + +- (request) => (request.params as { prompt: Array<{ type: string; text: string }> }).prompt, + +- ); + +- assert.equal(prompts.length, 2); + +- assert.deepEqual(prompts[0]?.[0], { type: "text", text: "First prompt" }); + +- assert.include(prompts[0]?.[1]?.text, "Grok harness, as grok-mock-alt"); + +- assert.deepEqual(prompts[1]?.[0], { type: "text", text: "Second prompt" }); + +- assert.include(prompts[1]?.[1]?.text, "Grok harness, as grok-4.6"); + +- assert.include(prompts[1]?.[1]?.text, "with low reasoning effort"); + +- assert.include(prompts[1]?.[1]?.text, "embed images and videos"); + +- }), + +- ); + +- + - it.effect("starts a session and maps mock ACP prompt flow to runtime events", () => + - Effect.gen(function* () { + - const threadId = ThreadId.make("grok-mock-thread"); + @@ apps/server/src/provider/Layers/GrokAdapter.ts (deleted) + - + -import { resolveAttachmentPath } from "../../attachmentStore.ts"; + -import { ServerConfig } from "../../config.ts"; + +-import { buildRuntimeInstructions } from "../RuntimeInstructions.ts"; + -import * as McpProviderSession from "../../mcp/McpProviderSession.ts"; + -import { + - ProviderAdapterProcessError, + @@ apps/server/src/provider/Layers/GrokAdapter.ts (deleted) + - const displayModel = currentModelId + - ? resolveGrokAcpBaseModelId(currentModelId) + - : undefined; + +- const runtimeInstructions = buildRuntimeInstructions({ + +- harness: "Grok", + +- model: displayModel, + +- reasoningEffort: normalizeGrokReasoningEffort(requestedTurnReasoningEffort), + +- }); + - for (let yieldAttempt = 0; yieldAttempt < 8; yieldAttempt += 1) { + - yield* Effect.yieldNow; + - } + @@ apps/server/src/provider/Layers/GrokAdapter.ts (deleted) + - acpSessionId: ctx.acpSessionId, + - displayModel, + - promptParts, + +- runtimeInstructions, + - turnId, + - promptEpoch, + - promptLifecycle: ctx.promptLifecycle, + @@ apps/server/src/provider/Layers/GrokAdapter.ts (deleted) + - } + - const dispatched = yield* Deferred.make(); + - const fiber = yield* liveCtx.acp + -- .prompt({ prompt: prepared.promptParts }, { dispatched }) + +- .prompt( + +- { + +- prompt: [ + +- ...prepared.promptParts, + +- { type: "text", text: prepared.runtimeInstructions }, + +- ], + +- }, + +- { dispatched }, + +- ) + - .pipe(Effect.forkChild({ startImmediately: true })); + - // Hold the lifecycle permit until the runtime has registered this + - // prompt's RPC fiber, so a later steer's session/cancel targets + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + -import { it } from "@effect/vitest"; + -import * as Cause from "effect/Cause"; + -import * as Context from "effect/Context"; + +-import * as Crypto from "effect/Crypto"; + +-import * as Deferred from "effect/Deferred"; + -import * as Effect from "effect/Effect"; + -import * as Exit from "effect/Exit"; + -import * as Fiber from "effect/Fiber"; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + -import * as Stream from "effect/Stream"; + -import * as TestClock from "effect/testing/TestClock"; + -import { beforeEach } from "vite-plus/test"; + --import type { PermissionRequest, QuestionRequest } from "@opencode-ai/sdk/v2"; + +-import type { + +- Event as OpenCodeEvent, + +- PermissionRequest, + +- QuestionRequest, + +- ToolPart, + +-} from "@opencode-ai/sdk/v2"; + - + -import { + - ApprovalRequestId, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + -import { createModelSelection } from "@t3tools/shared/model"; + -import { ServerConfig } from "../../config.ts"; + -import { ServerSettingsService } from "../../serverSettings.ts"; + +-import { buildRuntimeInstructions } from "../RuntimeInstructions.ts"; + -import { ProviderSessionDirectory } from "../Services/ProviderSessionDirectory.ts"; + -import type { OpenCodeAdapterShape } from "../Services/OpenCodeAdapter.ts"; + -import { + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - messageCalls: [] as Array<{ sessionID: string; messageID: string }>, + - messageFailures: 0, + - promptCalls: [] as Array, + +- summarizeCalls: [] as Array, + - promptAsyncError: null as Error | null, + - promptAsyncImplementation: null as (() => Promise) | null, + - autoPromptEcho: true, + - autoConnect: true, + +- endEventStream: false, + - promptEchoEvents: [] as Array, + - closeError: null as Error | null, + - messages: [] as MessageEntry[], + - subscribedEvents: [] as Array>, + - eventSubscribeObserved: null as (() => void) | null, + +- eventStreamError: null as ((cause: unknown) => void) | null, + - permissionReplyCalls: [] as Array<{ requestID: string; reply: string }>, + +- permissionReplyImplementation: null as ((signal?: AbortSignal) => Promise) | null, + +- permissionReplySignals: [] as AbortSignal[], + - questionReplyCalls: [] as Array<{ + - requestID: string; + - answers: ReadonlyArray>; + - }>, + +- questionReplyImplementation: null as ((signal?: AbortSignal) => Promise) | null, + - sessionStatus: "idle" as "idle" | "busy", + - sessionStatusFailures: 0, + - sessionStatusCalls: 0, + - sessionStatusImplementation: null as (() => Promise) | null, + - sessionGetIds: [] as string[], + - sessionGetObserved: null as ((sessionID: string) => void) | null, + +- sessionGetImplementation: null as + +- | ((sessionID: string, signal?: AbortSignal) => Promise) + +- | null, + - missingSessionIds: new Set(), + - transientErrorSessionIds: new Set(), + - sessionDirectoryById: new Map(), + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - this.state.messageCalls.length = 0; + - this.state.messageFailures = 0; + - this.state.promptCalls.length = 0; + +- this.state.summarizeCalls.length = 0; + - this.state.promptAsyncError = null; + - this.state.promptAsyncImplementation = null; + - this.state.autoPromptEcho = true; + - this.state.autoConnect = true; + +- this.state.endEventStream = false; + - this.state.promptEchoEvents.length = 0; + - this.state.closeError = null; + - this.state.messages = []; + - this.state.subscribedEvents = []; + - this.state.eventSubscribeObserved = null; + +- this.state.eventStreamError = null; + - this.state.permissionReplyCalls.length = 0; + +- this.state.permissionReplyImplementation = null; + +- this.state.permissionReplySignals.length = 0; + - this.state.questionReplyCalls.length = 0; + +- this.state.questionReplyImplementation = null; + - this.state.sessionStatus = "idle"; + - this.state.sessionStatusFailures = 0; + - this.state.sessionStatusCalls = 0; + - this.state.sessionStatusImplementation = null; + - this.state.sessionGetIds.length = 0; + - this.state.sessionGetObserved = null; + +- this.state.sessionGetImplementation = null; + - this.state.missingSessionIds.clear(); + - this.state.transientErrorSessionIds.clear(); + - this.state.sessionDirectoryById.clear(); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - data: { id: runtimeMock.state.createdSessionIds.shift() ?? `${baseUrl}/session` }, + - }; + - }, + -- get: async ({ sessionID }: { sessionID: string }) => { + +- get: async ({ sessionID }: { sessionID: string }, options?: { signal?: AbortSignal }) => { + - runtimeMock.state.sessionGetIds.push(sessionID); + - runtimeMock.state.sessionGetObserved?.(sessionID); + +- if (runtimeMock.state.sessionGetImplementation) { + +- await runtimeMock.state.sessionGetImplementation(sessionID, options?.signal); + +- } + - // The real client is `throwOnError: true`: non-2xx rejects rather + - // than resolving, so missing → 404 throw, transient → 500 throw. + - if (runtimeMock.state.transientErrorSessionIds.has(sessionID)) { + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - runtimeMock.state.abortSignals.push(options.signal); + - } + - await runtimeMock.state.abortImplementation?.(sessionID, options?.signal); + +- runtimeMock.state.pendingPermissions = runtimeMock.state.pendingPermissions.filter( + +- (request) => request.sessionID !== sessionID, + +- ); + +- runtimeMock.state.pendingQuestions = runtimeMock.state.pendingQuestions.filter( + +- (request) => request.sessionID !== sessionID, + +- ); + - }, + - children: async ({ sessionID }: { sessionID: string }) => { + - runtimeMock.state.sessionChildrenCalls.push(sessionID); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - }); + - } + - }, + +- summarize: async (input: unknown) => { + +- runtimeMock.state.summarizeCalls.push(input); + +- return { data: true }; + +- }, + - messages: async () => ({ data: runtimeMock.state.messages }), + - message: async ({ sessionID, messageID }: { sessionID: string; messageID: string }) => { + - runtimeMock.state.messageCalls.push({ sessionID, messageID }); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - }, + - }, + - event: { + -- subscribe: async () => { + +- subscribe: async ( + +- _input: unknown, + +- options?: { signal?: AbortSignal; onSseError?: (cause: unknown) => void }, + +- ) => { + - runtimeMock.state.eventSubscribeObserved?.(); + +- runtimeMock.state.eventStreamError = options?.onSseError ?? null; + - return { + - stream: (async function* () { + -- if (runtimeMock.state.autoConnect) { + -- yield { id: "evt-auto-connected", type: "server.connected", properties: {} }; + -- } + -- for (const event of runtimeMock.state.subscribedEvents) { + -- const resolved = await event; + -- while (runtimeMock.state.promptEchoEvents.length > 0) { + -- yield runtimeMock.state.promptEchoEvents.shift(); + +- const aborted = promiseWithResolvers(); + +- const onAbort = () => aborted.resolve(undefined); + +- options?.signal?.addEventListener("abort", onAbort, { once: true }); + +- try { + +- if (runtimeMock.state.autoConnect) { + +- yield { id: "evt-auto-connected", type: "server.connected", properties: {} }; + - } + -- yield resolved; + +- for (const event of runtimeMock.state.subscribedEvents) { + +- if (options?.signal?.aborted) return; + +- const resolved = await Promise.race([event, aborted.promise]); + +- if (options?.signal?.aborted) return; + +- while (runtimeMock.state.promptEchoEvents.length > 0) { + +- yield runtimeMock.state.promptEchoEvents.shift(); + +- } + +- const nativeEvent = resolved as OpenCodeEvent; + +- if (nativeEvent.type === "permission.asked") { + +- runtimeMock.state.pendingPermissions = + +- runtimeMock.state.pendingPermissions.filter( + +- (request) => request.id !== nativeEvent.properties.id, + +- ); + +- runtimeMock.state.pendingPermissions.push(nativeEvent.properties); + +- } else if (nativeEvent.type === "permission.replied") { + +- runtimeMock.state.pendingPermissions = + +- runtimeMock.state.pendingPermissions.filter( + +- (request) => request.id !== nativeEvent.properties.requestID, + +- ); + +- } else if (nativeEvent.type === "question.asked") { + +- runtimeMock.state.pendingQuestions = runtimeMock.state.pendingQuestions.filter( + +- (request) => request.id !== nativeEvent.properties.id, + +- ); + +- runtimeMock.state.pendingQuestions.push(nativeEvent.properties); + +- } else if ( + +- nativeEvent.type === "question.replied" || + +- nativeEvent.type === "question.rejected" + +- ) { + +- runtimeMock.state.pendingQuestions = runtimeMock.state.pendingQuestions.filter( + +- (request) => request.id !== nativeEvent.properties.requestID, + +- ); + +- } + +- yield resolved; + +- } + +- if (!runtimeMock.state.endEventStream && !options?.signal?.aborted) { + +- await aborted.promise; + +- } + +- } finally { + +- options?.signal?.removeEventListener("abort", onAbort); + - } + - })(), + - }; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - : runtimeMock.state.pendingPermissions, + - }; + - }, + -- reply: async ({ requestID, reply }: { requestID: string; reply: string }) => { + +- reply: async ( + +- { requestID, reply }: { requestID: string; reply: string }, + +- options?: { signal?: AbortSignal }, + +- ) => { + - runtimeMock.state.permissionReplyCalls.push({ requestID, reply }); + +- if (options?.signal) runtimeMock.state.permissionReplySignals.push(options.signal); + +- if (runtimeMock.state.permissionReplyImplementation) { + +- await runtimeMock.state.permissionReplyImplementation(options?.signal); + +- } + +- runtimeMock.state.pendingPermissions = runtimeMock.state.pendingPermissions.filter( + +- (request) => request.id !== requestID, + +- ); + - }, + - }, + - question: { + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - : runtimeMock.state.pendingQuestions, + - }; + - }, + -- reply: async ({ + -- requestID, + -- answers, + -- }: { + -- requestID: string; + -- answers: ReadonlyArray>; + -- }) => { + +- reply: async ( + +- { + +- requestID, + +- answers, + +- }: { + +- requestID: string; + +- answers: ReadonlyArray>; + +- }, + +- options?: { signal?: AbortSignal }, + +- ) => { + - runtimeMock.state.questionReplyCalls.push({ requestID, answers }); + +- await runtimeMock.state.questionReplyImplementation?.(options?.signal); + +- runtimeMock.state.pendingQuestions = runtimeMock.state.pendingQuestions.filter( + +- (request) => request.id !== requestID, + +- ); + - }, + - }, + - }) as unknown as ReturnType, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - }), + - ); + - + +- it.effect("compacts through the native OpenCode session API", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-opencode-compact"); + +- runtimeMock.state.subscribedEvents.push({ + +- type: "session.compacted", + +- properties: { sessionID: "http://127.0.0.1:9999/session" }, + +- }); + +- const eventsFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId), + +- Stream.take(3), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- yield* adapter.compactThread!( + +- threadId, + +- createModelSelection(ProviderInstanceId.make("opencode"), "openai/gpt-5"), + +- ); + +- const summarizeCall = runtimeMock.state.summarizeCalls[0] as Record; + +- NodeAssert.equal(summarizeCall.modelID, "gpt-5"); + +- const events = Array.from(yield* Fiber.join(eventsFiber)); + +- yield* adapter.stopSession(threadId); + +- const compacted = events.some( + +- (event) => event.type === "thread.state.changed" && event.payload.state === "compacted", + +- ); + +- NodeAssert.equal(compacted, true); + +- }), + +- ); + - it.effect("falls back to a fresh session when the persisted session is gone", () => + - Effect.gen(function* () { + - const adapter = yield* OpenCodeAdapter; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - }), + - ); + - + +- it.effect("marks subagents when a child is proven related by ancestry lookup", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-child-ancestry-usage"); + +- // The child's `session.created` event was missed. Only the ancestry + +- // lookup can prove that `ses_child` belongs to this thread. + +- runtimeMock.state.sessionParentById.set("ses_child", "http://127.0.0.1:9999/session"); + +- runtimeMock.state.sessionStatus = "busy"; + +- const busy = promiseWithResolvers(); + +- const childPermission = promiseWithResolvers(); + +- const idle = promiseWithResolvers(); + +- runtimeMock.state.subscribedEvents = [busy.promise, childPermission.promise, idle.promise]; + +- + +- const eventsFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter( + +- (event) => + +- event.threadId === threadId && + +- (event.type === "request.opened" || event.type === "turn.completed"), + +- ), + +- Stream.take(2), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "approval-required", + +- }); + +- const sendFiber = yield* adapter + +- .sendTurn({ + +- threadId, + +- input: "Delegate to a child", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }) + +- .pipe(Effect.forkChild); + +- busy.resolve({ + +- id: "evt-child-ancestry-busy", + +- type: "session.status", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- status: { type: "busy" }, + +- }, + +- }); + +- yield* Fiber.join(sendFiber); + +- + +- const requestOpened = promiseWithResolvers(); + +- runtimeMock.state.sessionGetObserved = (sessionID) => { + +- if (sessionID === "ses_child") requestOpened.resolve(undefined); + +- }; + +- childPermission.resolve({ + +- id: "evt-child-ancestry-permission", + +- type: "permission.asked", + +- properties: permissionRequest("per_child_ancestry", "ses_child"), + +- }); + +- yield* Effect.promise(() => requestOpened.promise); + +- yield* Effect.yieldNow; + +- runtimeMock.state.sessionStatus = "idle"; + +- idle.resolve({ + +- id: "evt-child-ancestry-idle", + +- type: "session.status", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- status: { type: "idle" }, + +- }, + +- }); + +- + +- const events = Array.from(yield* Fiber.join(eventsFiber).pipe(Effect.timeout("1 second"))); + +- NodeAssert.deepEqual( + +- events.map((event) => event.type), + +- ["request.opened", "turn.completed"], + +- ); + +- const completed = events[1]; + +- if (completed?.type === "turn.completed") { + +- NodeAssert.deepEqual(completed.payload.tokenUsage, { + +- usageStatus: "unavailable", + +- usageScope: "main_agent", + +- hasSubagents: true, + +- }); + +- } + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + +- it.effect("sums owned OpenCode step usage and marks unresolved usage partial", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-step-usage"); + +- const busy = promiseWithResolvers(); + +- const firstStep = promiseWithResolvers(); + +- const assistantMessage = promiseWithResolvers(); + +- const duplicateStep = promiseWithResolvers(); + +- const secondStep = promiseWithResolvers(); + +- const unresolvedHeader = promiseWithResolvers(); + +- const unresolvedStep = promiseWithResolvers(); + +- const recoveredStep = promiseWithResolvers(); + +- const recoveredIncompleteHeader = promiseWithResolvers(); + +- const recoveredCompleteHeader = promiseWithResolvers(); + +- const childSession = promiseWithResolvers(); + +- const idle = promiseWithResolvers(); + +- runtimeMock.state.subscribedEvents = [ + +- busy.promise, + +- firstStep.promise, + +- assistantMessage.promise, + +- duplicateStep.promise, + +- secondStep.promise, + +- unresolvedHeader.promise, + +- unresolvedStep.promise, + +- recoveredStep.promise, + +- recoveredIncompleteHeader.promise, + +- recoveredCompleteHeader.promise, + +- childSession.promise, + +- idle.promise, + +- ]; + +- + +- const completedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "turn.completed"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- const sendFiber = yield* adapter + +- .sendTurn({ + +- threadId, + +- input: "Use two model steps", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }) + +- .pipe(Effect.forkChild); + +- busy.resolve({ + +- id: "evt-step-usage-busy", + +- type: "session.status", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- status: { type: "busy" }, + +- }, + +- }); + +- yield* Fiber.join(sendFiber); + +- const promptMessageId = (runtimeMock.state.promptCalls[0] as { messageID: string }).messageID; + +- + +- const stepPart = { + +- id: "step-usage-1", + +- sessionID: "http://127.0.0.1:9999/session", + +- messageID: "assistant-step-usage-1", + +- type: "step-finish", + +- reason: "tool-calls", + +- cost: 0, + +- tokens: { + +- input: 100, + +- output: 20, + +- reasoning: 5, + +- cache: { read: 40, write: 10 }, + +- }, + +- } as const; + +- firstStep.resolve({ + +- id: "evt-step-usage-1", + +- type: "message.part.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- part: stepPart, + +- }, + +- }); + +- assistantMessage.resolve({ + +- id: "evt-step-usage-assistant", + +- type: "message.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- info: { + +- id: "assistant-step-usage-1", + +- role: "assistant", + +- parentID: promptMessageId, + +- }, + +- }, + +- }); + +- duplicateStep.resolve({ + +- id: "evt-step-usage-1-duplicate", + +- type: "message.part.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- part: stepPart, + +- }, + +- }); + +- secondStep.resolve({ + +- id: "evt-step-usage-2", + +- type: "message.part.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- part: { + +- ...stepPart, + +- id: "step-usage-2", + +- tokens: { + +- input: 50, + +- output: 10, + +- reasoning: 2, + +- cache: { read: 10, write: 0 }, + +- }, + +- }, + +- }, + +- }); + +- unresolvedHeader.resolve({ + +- id: "evt-step-usage-unresolved-header", + +- type: "message.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- info: { + +- id: "assistant-step-usage-without-parent", + +- role: "assistant", + +- }, + +- }, + +- }); + +- unresolvedStep.resolve({ + +- id: "evt-step-usage-unresolved", + +- type: "message.part.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- part: { + +- ...stepPart, + +- id: "step-usage-unresolved", + +- messageID: "assistant-step-usage-without-parent", + +- tokens: { + +- input: 1_000, + +- output: 1_000, + +- reasoning: 0, + +- cache: { read: 0, write: 0 }, + +- }, + +- }, + +- }, + +- }); + +- recoveredStep.resolve({ + +- id: "evt-step-usage-recovered", + +- type: "message.part.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- part: { + +- ...stepPart, + +- id: "step-usage-recovered", + +- messageID: "assistant-step-usage-recovered", + +- tokens: { + +- input: 30, + +- output: 10, + +- reasoning: 2, + +- cache: { read: 5, write: 1 }, + +- }, + +- }, + +- }, + +- }); + +- recoveredIncompleteHeader.resolve({ + +- id: "evt-step-usage-recovered-incomplete-header", + +- type: "message.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- info: { + +- id: "assistant-step-usage-recovered", + +- role: "assistant", + +- parentID: "", + +- }, + +- }, + +- }); + +- recoveredCompleteHeader.resolve({ + +- id: "evt-step-usage-recovered-complete-header", + +- type: "message.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- info: { + +- id: "assistant-step-usage-recovered", + +- role: "assistant", + +- parentID: promptMessageId, + +- }, + +- }, + +- }); + +- childSession.resolve({ + +- id: "evt-step-usage-child", + +- type: "session.created", + +- properties: { + +- info: { + +- id: "child-step-usage", + +- parentID: "http://127.0.0.1:9999/session", + +- }, + +- }, + +- }); + +- idle.resolve({ + +- id: "evt-step-usage-idle", + +- type: "session.status", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- status: { type: "idle" }, + +- }, + +- }); + +- + +- const completed = yield* Fiber.join(completedFiber).pipe(Effect.timeout("1 second")); + +- NodeAssert.equal(completed._tag, "Some"); + +- if (completed._tag === "Some" && completed.value.type === "turn.completed") { + +- NodeAssert.deepStrictEqual(completed.value.payload.tokenUsage, { + +- usageStatus: "partial", + +- usageScope: "main_agent", + +- inputTokens: 246, + +- cachedInputTokens: 55, + +- cacheCreationTokens: 11, + +- outputTokens: 49, + +- reasoningTokens: 9, + +- hasSubagents: true, + +- }); + +- } + +- + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + +- it.effect("keeps the next turn usage while the prior completion is delayed", () => + +- Effect.gen(function* () { + +- const threadId = asThreadId("thread-token-usage-terminal-handoff"); + +- const firstBusy = promiseWithResolvers(); + +- const firstAssistantMessage = promiseWithResolvers(); + +- const firstStep = promiseWithResolvers(); + +- const firstIdle = promiseWithResolvers(); + +- const secondBusy = promiseWithResolvers(); + +- const secondAssistantMessage = promiseWithResolvers(); + +- const secondStep = promiseWithResolvers(); + +- const secondIdle = promiseWithResolvers(); + +- runtimeMock.state.subscribedEvents = [ + +- firstBusy.promise, + +- firstAssistantMessage.promise, + +- firstStep.promise, + +- firstIdle.promise, + +- secondBusy.promise, + +- secondAssistantMessage.promise, + +- secondStep.promise, + +- secondIdle.promise, + +- ]; + +- + +- const firstStepWriteStarted = yield* Deferred.make(); + +- const firstStepWriteRelease = yield* Deferred.make(); + +- const terminalUuidStarted = yield* Deferred.make(); + +- const terminalUuidRelease = yield* Deferred.make(); + +- let blockFirstStepWrite = true; + +- let blockNextUuid = false; + +- const nodeCrypto = yield* Crypto.Crypto; + +- const gatedCrypto = { + +- ...nodeCrypto, + +- randomUUIDv4: Effect.suspend(() => { + +- if (!blockNextUuid) return nodeCrypto.randomUUIDv4; + +- blockNextUuid = false; + +- return Deferred.succeed(terminalUuidStarted, undefined).pipe( + +- Effect.andThen(Deferred.await(terminalUuidRelease)), + +- Effect.andThen(nodeCrypto.randomUUIDv4), + +- ); + +- }), + +- } satisfies Crypto.Crypto; + +- const adapter = yield* makeOpenCodeAdapter(openCodeAdapterTestSettings, { + +- nativeEventLogger: { + +- filePath: "memory://opencode-token-usage-terminal-handoff", + +- write: (record) => { + +- const eventType = (record as { event?: { type?: unknown } }).event?.type; + +- if (blockFirstStepWrite && eventType === "message.part.updated") { + +- blockFirstStepWrite = false; + +- return Deferred.succeed(firstStepWriteStarted, undefined).pipe( + +- Effect.andThen(Deferred.await(firstStepWriteRelease)), + +- ); + +- } + +- return Effect.void; + +- }, + +- close: () => Effect.void, + +- }, + +- }).pipe(Effect.provideService(Crypto.Crypto, gatedCrypto)); + +- + +- const completedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "turn.completed"), + +- Stream.take(2), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- + +- const firstSend = yield* adapter + +- .sendTurn({ + +- threadId, + +- input: "Run the first token handoff turn", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }) + +- .pipe(Effect.forkChild); + +- firstBusy.resolve({ + +- id: "evt-token-handoff-first-busy", + +- type: "session.status", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- status: { type: "busy" }, + +- }, + +- }); + +- const firstTurn = yield* Fiber.join(firstSend); + +- const firstPromptMessageId = (runtimeMock.state.promptCalls[0] as { messageID: string }) + +- .messageID; + +- firstAssistantMessage.resolve({ + +- id: "evt-token-handoff-first-assistant", + +- type: "message.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- info: { + +- id: "assistant-token-handoff-first", + +- role: "assistant", + +- parentID: firstPromptMessageId, + +- }, + +- }, + +- }); + +- firstStep.resolve({ + +- id: "evt-token-handoff-first-step", + +- type: "message.part.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- part: { + +- id: "step-token-handoff-first", + +- sessionID: "http://127.0.0.1:9999/session", + +- messageID: "assistant-token-handoff-first", + +- type: "step-finish", + +- reason: "stop", + +- cost: 0, + +- tokens: { + +- input: 100, + +- output: 20, + +- reasoning: 5, + +- cache: { read: 40, write: 10 }, + +- }, + +- }, + +- }, + +- }); + +- yield* Deferred.await(firstStepWriteStarted); + +- blockNextUuid = true; + +- firstIdle.resolve({ + +- id: "evt-token-handoff-first-idle", + +- type: "session.status", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- status: { type: "idle" }, + +- }, + +- }); + +- yield* Deferred.succeed(firstStepWriteRelease, undefined); + +- yield* Deferred.await(terminalUuidStarted); + +- + +- runtimeMock.state.sessionStatus = "busy"; + +- const secondTurn = yield* adapter.sendTurn({ + +- threadId, + +- input: "Run the second token handoff turn", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }); + +- NodeAssert.notEqual(secondTurn.turnId, firstTurn.turnId); + +- const secondPromptMessageId = (runtimeMock.state.promptCalls[1] as { messageID: string }) + +- .messageID; + +- yield* Deferred.succeed(terminalUuidRelease, undefined); + +- + +- secondBusy.resolve({ + +- id: "evt-token-handoff-second-busy", + +- type: "session.status", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- status: { type: "busy" }, + +- }, + +- }); + +- secondAssistantMessage.resolve({ + +- id: "evt-token-handoff-second-assistant", + +- type: "message.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- info: { + +- id: "assistant-token-handoff-second", + +- role: "assistant", + +- parentID: secondPromptMessageId, + +- }, + +- }, + +- }); + +- secondStep.resolve({ + +- id: "evt-token-handoff-second-step", + +- type: "message.part.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- part: { + +- id: "step-token-handoff-second", + +- sessionID: "http://127.0.0.1:9999/session", + +- messageID: "assistant-token-handoff-second", + +- type: "step-finish", + +- reason: "stop", + +- cost: 0, + +- tokens: { + +- input: 90, + +- output: 13, + +- reasoning: 3, + +- cache: { read: 20, write: 5 }, + +- }, + +- }, + +- }, + +- }); + +- secondIdle.resolve({ + +- id: "evt-token-handoff-second-idle", + +- type: "session.status", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- status: { type: "idle" }, + +- }, + +- }); + +- + +- const completed = Array.from( + +- yield* Fiber.join(completedFiber).pipe(Effect.timeout("1 second")), + +- ); + +- NodeAssert.deepStrictEqual( + +- completed.map((event) => + +- event.type === "turn.completed" ? event.payload.tokenUsage : undefined, + +- ), + +- [ + +- { + +- usageStatus: "complete", + +- usageScope: "main_agent", + +- inputTokens: 150, + +- cachedInputTokens: 40, + +- cacheCreationTokens: 10, + +- outputTokens: 25, + +- reasoningTokens: 5, + +- hasSubagents: false, + +- }, + +- { + +- usageStatus: "complete", + +- usageScope: "main_agent", + +- inputTokens: 115, + +- cachedInputTokens: 20, + +- cacheCreationTokens: 5, + +- outputTokens: 16, + +- reasoningTokens: 3, + +- hasSubagents: false, + +- }, + +- ], + +- ); + +- + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + - it.effect("ignores a stale admission status response after the next turn starts", () => + - Effect.gen(function* () { + - const adapter = yield* OpenCodeAdapter; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - }), + - ); + - + +- it.effect("ignores a late prior-turn step after the next prompt is admitted", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-token-usage-late-prior-step"); + +- const firstBusy = promiseWithResolvers(); + +- const firstAssistant = promiseWithResolvers(); + +- const secondBusy = promiseWithResolvers(); + +- const secondAssistant = promiseWithResolvers(); + +- const lateFirstStep = promiseWithResolvers(); + +- const secondStep = promiseWithResolvers(); + +- const secondIdle = promiseWithResolvers(); + +- runtimeMock.state.subscribedEvents = [ + +- firstBusy.promise, + +- firstAssistant.promise, + +- secondBusy.promise, + +- secondAssistant.promise, + +- lateFirstStep.promise, + +- secondStep.promise, + +- secondIdle.promise, + +- ]; + +- + +- const terminalsFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter( + +- (event) => + +- event.threadId === threadId && + +- (event.type === "turn.aborted" || event.type === "turn.completed"), + +- ), + +- Stream.take(2), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- + +- const firstSend = yield* adapter + +- .sendTurn({ + +- threadId, + +- input: "Start the interrupted turn", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }) + +- .pipe(Effect.forkChild); + +- firstBusy.resolve({ + +- id: "evt-token-late-first-busy", + +- type: "session.status", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- status: { type: "busy" }, + +- }, + +- }); + +- yield* Fiber.join(firstSend); + +- const firstPromptMessageId = (runtimeMock.state.promptCalls[0] as { messageID: string }) + +- .messageID; + +- firstAssistant.resolve({ + +- id: "evt-token-late-first-assistant", + +- type: "message.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- info: { + +- id: "assistant-token-late-first", + +- role: "assistant", + +- parentID: firstPromptMessageId, + +- }, + +- }, + +- }); + +- yield* Effect.yieldNow; + +- yield* adapter.interruptTurn(threadId); + +- + +- const secondSend = yield* adapter + +- .sendTurn({ + +- threadId, + +- input: "Start the next turn", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }) + +- .pipe(Effect.forkChild); + +- while (runtimeMock.state.promptCalls.length < 2) { + +- yield* Effect.yieldNow; + +- } + +- secondBusy.resolve({ + +- id: "evt-token-late-second-busy", + +- type: "session.status", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- status: { type: "busy" }, + +- }, + +- }); + +- yield* Fiber.join(secondSend); + +- const secondPromptMessageId = (runtimeMock.state.promptCalls[1] as { messageID: string }) + +- .messageID; + +- secondAssistant.resolve({ + +- id: "evt-token-late-second-assistant", + +- type: "message.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- info: { + +- id: "assistant-token-late-second", + +- role: "assistant", + +- parentID: secondPromptMessageId, + +- }, + +- }, + +- }); + +- lateFirstStep.resolve({ + +- id: "evt-token-late-first-step", + +- type: "message.part.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- part: { + +- id: "step-token-late-first", + +- sessionID: "http://127.0.0.1:9999/session", + +- messageID: "assistant-token-late-first", + +- type: "step-finish", + +- reason: "stop", + +- cost: 0, + +- tokens: { + +- input: 1_000, + +- output: 1_000, + +- reasoning: 0, + +- cache: { read: 0, write: 0 }, + +- }, + +- }, + +- }, + +- }); + +- secondStep.resolve({ + +- id: "evt-token-late-second-step", + +- type: "message.part.updated", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- part: { + +- id: "step-token-late-second", + +- sessionID: "http://127.0.0.1:9999/session", + +- messageID: "assistant-token-late-second", + +- type: "step-finish", + +- reason: "stop", + +- cost: 0, + +- tokens: { + +- input: 40, + +- output: 10, + +- reasoning: 2, + +- cache: { read: 5, write: 1 }, + +- }, + +- }, + +- }, + +- }); + +- secondIdle.resolve({ + +- id: "evt-token-late-second-idle", + +- type: "session.status", + +- properties: { + +- sessionID: "http://127.0.0.1:9999/session", + +- status: { type: "idle" }, + +- }, + +- }); + +- + +- const terminals = Array.from( + +- yield* Fiber.join(terminalsFiber).pipe(Effect.timeout("1 second")), + +- ); + +- const secondCompleted = terminals.find((event) => event.type === "turn.completed"); + +- NodeAssert.equal(secondCompleted?.type, "turn.completed"); + +- if (secondCompleted?.type === "turn.completed") { + +- NodeAssert.deepStrictEqual(secondCompleted.payload.tokenUsage, { + +- usageStatus: "complete", + +- usageScope: "main_agent", + +- inputTokens: 46, + +- cachedInputTokens: 5, + +- cacheCreationTokens: 1, + +- outputTokens: 12, + +- reasoningTokens: 2, + +- hasSubagents: false, + +- }); + +- } + +- + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + - it.effect("reconciles a sole idle when the matching prompt echo arrives later", () => + - Effect.gen(function* () { + - const adapter = yield* OpenCodeAdapter; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - }), + - ); + - + +- it.effect.each([ + +- { permission: "external_directory", decision: "accept", reply: "once" }, + +- { permission: "doom_loop", decision: "acceptForSession", reply: "always" }, + +- { permission: "todowrite", decision: "decline", reply: "reject" }, + +- { permission: "webfetch", decision: "cancel", reply: "reject" }, + +- { permission: "custom_tool", decision: "accept", reply: "once" }, + +- ] as const)( + +- "shows $permission approval and resolves its $decision reply without SSE", + +- ({ permission, decision, reply }) => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId(`thread-permission-${permission}`); + +- const request = { + +- ...permissionRequest(`per_${permission}`, "http://127.0.0.1:9999/session"), + +- permission, + +- patterns: ["*"], + +- }; + +- runtimeMock.state.subscribedEvents = [ + +- { + +- id: "evt-permission", + +- type: "permission.asked", + +- properties: request, + +- } satisfies OpenCodeEvent, + +- ]; + +- const openedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "request.opened"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "approval-required", + +- }); + +- const opened = Option.getOrThrow(yield* Fiber.join(openedFiber)); + +- NodeAssert.ok(opened.type === "request.opened"); + +- NodeAssert.equal(opened.payload.requestType, "command_execution_approval"); + +- NodeAssert.equal(opened.payload.detail, permission.replaceAll("_", " ")); + +- NodeAssert.deepEqual( + +- opened.payload.options?.map((option) => option.label), + +- ["Allow once", "Allow for workspace", "Deny"], + +- ); + +- const resolvedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter( + +- (event) => event.threadId === threadId && event.type === "request.resolved", + +- ), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- yield* adapter.respondToRequest(threadId, ApprovalRequestId.make(request.id), decision); + +- const resolved = Option.getOrThrow(yield* Fiber.join(resolvedFiber)); + +- NodeAssert.equal(resolved.requestId, request.id); + +- yield* adapter.respondToRequest(threadId, ApprovalRequestId.make(request.id), decision); + +- NodeAssert.deepEqual(runtimeMock.state.permissionReplyCalls, [ + +- { requestID: request.id, reply }, + +- ]); + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + +- it.effect("keeps a permission reply retryable after its HTTP request times out", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-permission-timeout"); + +- const request = permissionRequest("per_timeout", "http://127.0.0.1:9999/session"); + +- const replyStarted = promiseWithResolvers(); + +- runtimeMock.state.permissionReplyImplementation = async () => { + +- replyStarted.resolve(undefined); + +- await new Promise(() => {}); + +- }; + +- runtimeMock.state.subscribedEvents = [ + +- { id: "evt-ask", type: "permission.asked", properties: request }, + +- ]; + +- const openedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "request.opened"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "approval-required", + +- }); + +- yield* Fiber.join(openedFiber); + +- const replyFiber = yield* adapter + +- .respondToRequest(threadId, ApprovalRequestId.make(request.id), "accept") + +- .pipe(Effect.exit, Effect.forkChild); + +- yield* Effect.promise(() => replyStarted.promise); + +- yield* Effect.yieldNow; + +- yield* advanceTestClock(10_000); + +- NodeAssert.equal(Exit.isFailure(yield* Fiber.join(replyFiber)), true); + +- NodeAssert.equal(runtimeMock.state.permissionReplySignals[0]?.aborted, true); + +- runtimeMock.state.permissionReplyImplementation = null; + +- const resolvedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "request.resolved"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- yield* adapter.respondToRequest(threadId, ApprovalRequestId.make(request.id), "accept"); + +- NodeAssert.equal(Option.getOrThrow(yield* Fiber.join(resolvedFiber)).requestId, request.id); + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + +- it.effect("keeps a recovering permission retryable until its native request is loaded", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-permission-recovering"); + +- const request = permissionRequest("per_recovering", "ses_resumed"); + +- const listStarted = promiseWithResolvers(); + +- const releaseList = promiseWithResolvers(); + +- runtimeMock.state.permissionListImplementation = async () => { + +- listStarted.resolve(undefined); + +- return await releaseList.promise; + +- }; + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "approval-required", + +- resumeCursor: { schemaVersion: 1, sessionId: request.sessionID }, + +- }); + +- yield* Effect.promise(() => listStarted.promise); + +- const reply = yield* adapter + +- .respondToRequest(threadId, ApprovalRequestId.make(request.id), "accept") + +- .pipe(Effect.result); + +- NodeAssert.equal(reply._tag, "Failure"); + +- if (reply._tag === "Failure" && reply.failure._tag === "ProviderAdapterRequestError") { + +- NodeAssert.match(reply.failure.detail, /still loading/); + +- } + +- const openedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "request.opened"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- releaseList.resolve([request]); + +- yield* Fiber.join(openedFiber); + +- yield* adapter.respondToRequest(threadId, ApprovalRequestId.make(request.id), "accept"); + +- NodeAssert.deepEqual(runtimeMock.state.permissionReplyCalls, [ + +- { requestID: request.id, reply: "once" }, + +- ]); + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + +- it.effect("closes missing permissions and questions after reconnect", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-missing-requests"); + +- const sessionID = "http://127.0.0.1:9999/session"; + +- const reconnect = promiseWithResolvers(); + +- runtimeMock.state.subscribedEvents = [ + +- { + +- id: "evt-permission", + +- type: "permission.asked", + +- properties: permissionRequest("per_missing", sessionID), + +- }, + +- { + +- id: "evt-question", + +- type: "question.asked", + +- properties: questionRequest("que_missing", sessionID), + +- }, + +- reconnect.promise, + +- ]; + +- const openedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter( + +- (event) => + +- event.threadId === threadId && + +- (event.type === "request.opened" || event.type === "user-input.requested"), + +- ), + +- Stream.take(2), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "approval-required", + +- }); + +- yield* Fiber.join(openedFiber); + +- const resolvedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter( + +- (event) => + +- event.threadId === threadId && + +- (event.type === "request.resolved" || event.type === "user-input.resolved"), + +- ), + +- Stream.take(2), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- runtimeMock.state.pendingPermissions = []; + +- runtimeMock.state.pendingQuestions = []; + +- reconnect.resolve({ id: "evt-reconnected", type: "server.connected", properties: {} }); + +- const resolved = yield* Fiber.join(resolvedFiber); + +- NodeAssert.deepEqual( + +- resolved.map((event) => event.requestId), + +- ["per_missing", "que_missing"], + +- ); + +- NodeAssert.deepEqual(runtimeMock.state.permissionReplyCalls, []); + +- NodeAssert.deepEqual(runtimeMock.state.questionReplyCalls, []); + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + +- it.effect("closes pending requests after Stop and ignores late requests from that turn", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-stop-requests"); + +- const sessionID = "http://127.0.0.1:9999/session"; + +- const startRequests = promiseWithResolvers(); + +- const lateRequests = promiseWithResolvers(); + +- runtimeMock.state.subscribedEvents = [ + +- startRequests.promise, + +- { + +- id: "evt-question", + +- type: "question.asked", + +- properties: questionRequest("que_stop", sessionID), + +- }, + +- lateRequests.promise, + +- { + +- id: "evt-late-question", + +- type: "question.asked", + +- properties: questionRequest("que_late", sessionID), + +- }, + +- { id: "evt-drained", type: "session.compacted", properties: { sessionID } }, + +- ]; + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "approval-required", + +- }); + +- const turn = yield* adapter.sendTurn({ + +- threadId, + +- input: "Work", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }); + +- const openedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter( + +- (event) => + +- event.threadId === threadId && + +- (event.type === "request.opened" || event.type === "user-input.requested"), + +- ), + +- Stream.take(2), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- startRequests.resolve({ + +- id: "evt-permission", + +- type: "permission.asked", + +- properties: permissionRequest("per_stop", sessionID), + +- }); + +- yield* Fiber.join(openedFiber); + +- const stoppedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId), + +- Stream.takeUntil((event) => event.type === "turn.aborted"), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- yield* adapter.interruptTurn(threadId, turn.turnId); + +- const stopped = yield* Fiber.join(stoppedFiber); + +- NodeAssert.deepEqual( + +- stopped.map((event) => event.type), + +- ["request.resolved", "user-input.resolved", "turn.aborted"], + +- ); + +- const lateFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId), + +- Stream.takeUntil((event) => event.type === "thread.state.changed"), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- lateRequests.resolve({ + +- id: "evt-late-permission", + +- type: "permission.asked", + +- properties: permissionRequest("per_late", sessionID), + +- }); + +- const late = yield* Fiber.join(lateFiber); + +- NodeAssert.deepEqual( + +- late.map((event) => event.type), + +- ["thread.state.changed"], + +- ); + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + +- it.effect("keeps progress live during automatic approval and never reopens a finished turn", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-auto-approval-progress"); + +- const sessionID = "http://127.0.0.1:9999/session"; + +- const ask = promiseWithResolvers(); + +- const idle = promiseWithResolvers(); + +- const replyStarted = promiseWithResolvers(); + +- const releaseReply = promiseWithResolvers(); + +- runtimeMock.state.permissionReplyImplementation = async () => { + +- replyStarted.resolve(undefined); + +- await releaseReply.promise; + +- throw new Error("reply response lost"); + +- }; + +- runtimeMock.state.subscribedEvents = [ask.promise, idle.promise]; + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- yield* adapter.sendTurn({ + +- threadId, + +- input: "Work", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }); + +- const completedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId), + +- Stream.takeUntil((event) => event.type === "turn.completed"), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- ask.resolve({ + +- id: "evt-ask", + +- type: "permission.asked", + +- properties: permissionRequest("per_slow_auto", sessionID), + +- }); + +- yield* Effect.promise(() => replyStarted.promise); + +- idle.resolve({ + +- id: "evt-idle", + +- type: "session.status", + +- properties: { sessionID, status: { type: "idle" } }, + +- }); + +- const completed = yield* Fiber.join(completedFiber); + +- NodeAssert.equal( + +- completed.some((event) => event.type === "request.opened"), + +- false, + +- ); + +- const remainingFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId), + +- Stream.takeUntil((event) => event.type === "session.exited"), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- releaseReply.resolve(undefined); + +- yield* advanceTestClock(10_000); + +- yield* adapter.stopSession(threadId); + +- const remaining = yield* Fiber.join(remainingFiber); + +- NodeAssert.equal( + +- remaining.some((event) => event.type === "request.opened"), + +- false, + +- ); + +- }), + +- ); + +- + +- it.effect("keeps automatic approval fallback available after a steer", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-auto-approval-steer"); + +- const ask = promiseWithResolvers(); + +- const replyStarted = promiseWithResolvers(); + +- const releaseReply = promiseWithResolvers(); + +- runtimeMock.state.sessionStatus = "busy"; + +- runtimeMock.state.permissionReplyImplementation = async () => { + +- replyStarted.resolve(undefined); + +- await releaseReply.promise; + +- throw new Error("reply failed"); + +- }; + +- runtimeMock.state.subscribedEvents = [ask.promise]; + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- const modelSelection = createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ); + +- const turn = yield* adapter.sendTurn({ threadId, input: "Work", modelSelection }); + +- ask.resolve({ + +- id: "evt-ask", + +- type: "permission.asked", + +- properties: permissionRequest("per_steer_auto", "http://127.0.0.1:9999/session"), + +- }); + +- yield* Effect.promise(() => replyStarted.promise); + +- const steered = yield* adapter.sendTurn({ + +- threadId, + +- input: "Keep the change small", + +- modelSelection, + +- }); + +- NodeAssert.equal(steered.turnId, turn.turnId); + +- const openedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "request.opened"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- releaseReply.resolve(undefined); + +- NodeAssert.equal( + +- Option.getOrThrow(yield* Fiber.join(openedFiber)).requestId, + +- "per_steer_auto", + +- ); + +- runtimeMock.state.permissionReplyImplementation = null; + +- yield* adapter.respondToRequest(threadId, ApprovalRequestId.make("per_steer_auto"), "accept"); + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + - it.effect("routes child-session approval requests and replies through the parent thread", () => + - Effect.gen(function* () { + - const adapter = yield* OpenCodeAdapter; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - }), + - ); + - + +- it.effect.each([ + +- { + +- name: "a doom-loop ask on the parent session", + +- requestId: "per_doom_loop", + +- sessionID: "http://127.0.0.1:9999/session", + +- permission: "doom_loop", + +- patterns: ["bash"], + +- always: [] as string[], + +- }, + +- { + +- name: "a child-session ask", + +- requestId: "per_child_full", + +- sessionID: "ses_child_full", + +- permission: "read", + +- patterns: ["/repo/settings.env"], + +- always: ["/repo/settings.env"], + +- }, + +- ])( + +- "auto-approves $name in full access", + +- ({ requestId, sessionID, permission, patterns, always }) => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId(`thread-full-access-${requestId}`); + +- const replyStarted = promiseWithResolvers(); + +- runtimeMock.state.permissionReplyImplementation = async () => + +- replyStarted.resolve(undefined); + +- runtimeMock.state.subscribedEvents = [ + +- { + +- id: "evt-child-created", + +- type: "session.created", + +- properties: { + +- sessionID: "ses_child_full", + +- info: { + +- id: "ses_child_full", + +- parentID: "http://127.0.0.1:9999/session", + +- title: "Child session", + +- }, + +- }, + +- }, + +- { + +- id: "evt-permission", + +- type: "permission.asked", + +- properties: { id: requestId, sessionID, permission, patterns, metadata: {}, always }, + +- }, + +- replyStarted.promise.then(() => ({ + +- id: "evt-permission-replied", + +- type: "permission.replied", + +- properties: { sessionID, requestID: requestId, reply: "once" }, + +- })), + +- // The suppressed ask emits nothing, so an empty question serves as a + +- // sentinel that closes the collected stream once the pump is past it. + +- { + +- id: "evt-sentinel-question", + +- type: "question.asked", + +- properties: { + +- id: "que_sentinel", + +- sessionID: "http://127.0.0.1:9999/session", + +- questions: [], + +- }, + +- }, + +- ]; + +- + +- const eventsFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId), + +- Stream.takeUntil((event) => event.type === "user-input.requested"), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- const events = Array.from(yield* Fiber.join(eventsFiber).pipe(Effect.timeout("1 second"))); + +- + +- NodeAssert.deepEqual(runtimeMock.state.permissionReplyCalls, [ + +- { requestID: requestId, reply: "once" }, + +- ]); + +- NodeAssert.equal( + +- events.some((event) => event.type === "request.opened"), + +- false, + +- ); + +- NodeAssert.equal( + +- events.some((event) => event.type === "request.resolved"), + +- false, + +- ); + +- + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + +- it.effect("surfaces the approval when the full-access auto-reply fails", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-full-access-reply-failed"); + +- runtimeMock.state.permissionReplyImplementation = async () => { + +- throw new Error("reply failed"); + +- }; + +- runtimeMock.state.subscribedEvents = [ + +- { + +- id: "evt-doom-loop", + +- type: "permission.asked", + +- properties: { + +- id: "per_doom_loop_failed", + +- sessionID: "http://127.0.0.1:9999/session", + +- permission: "doom_loop", + +- patterns: ["bash"], + +- metadata: {}, + +- always: [], + +- }, + +- }, + +- ]; + +- + +- const openedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "request.opened"), + +- Stream.take(1), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- const opened = Option.getOrUndefined( + +- yield* Fiber.join(openedFiber).pipe(Effect.timeout("1 second")), + +- ); + +- NodeAssert.equal(opened?.requestId, "per_doom_loop_failed"); + +- // Exactly one auto-reply attempt: the fallback surfaces the dialog + +- // instead of retrying the reply. + +- NodeAssert.deepEqual(runtimeMock.state.permissionReplyCalls, [ + +- { requestID: "per_doom_loop_failed", reply: "once" }, + +- ]); + +- + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + +- it.effect("does not reopen a failed full-access auto-reply after its terminal reply", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-full-access-reply-failed-after-terminal"); + +- const childId = "ses_full_access_terminal_child"; + +- const request = permissionRequest("per_failed_after_terminal", childId); + +- const ancestryAttempted = promiseWithResolvers(); + +- const releaseReply = promiseWithResolvers(); + +- // The ask arrives from a child whose ancestry lookup is failing, so it + +- // is handled on a retry fiber. The terminal reply lands while that + +- // fiber's auto-reply is still in flight; the reply then fails. The + +- // request must neither reopen nor emit a stray resolution. + +- runtimeMock.state.sessionParentById.set(childId, "http://127.0.0.1:9999/session"); + +- runtimeMock.state.transientErrorSessionIds.add(childId); + +- runtimeMock.state.sessionGetObserved = (sessionID) => { + +- if (sessionID === childId) { + +- ancestryAttempted.resolve(undefined); + +- } + +- }; + +- runtimeMock.state.permissionReplyImplementation = async () => { + +- await releaseReply.promise; + +- throw new Error("reply failed"); + +- }; + +- const terminalEvent = promiseWithResolvers(); + +- runtimeMock.state.subscribedEvents = [ + +- { id: "evt-ask", type: "permission.asked", properties: request }, + +- terminalEvent.promise, + +- ]; + +- + +- const requestEventsFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter( + +- (event) => + +- event.threadId === threadId && + +- (event.type === "request.opened" || event.type === "request.resolved"), + +- ), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- yield* Effect.promise(() => ancestryAttempted.promise); + +- runtimeMock.state.transientErrorSessionIds.delete(childId); + +- yield* advanceTestClock(250); + +- NodeAssert.deepEqual(runtimeMock.state.permissionReplyCalls, [ + +- { requestID: request.id, reply: "once" }, + +- ]); + +- + +- // Drain the microtask queue so the pump has consumed the terminal reply + +- // before the in-flight auto-reply is allowed to fail. + +- terminalEvent.resolve({ + +- id: "evt-reply", + +- type: "permission.replied", + +- properties: { sessionID: childId, requestID: request.id, reply: "once" }, + +- }); + +- yield* Effect.promise(() => new Promise((resolve) => setImmediate(resolve))); + +- releaseReply.resolve(undefined); + +- yield* advanceTestClock(250); + +- + +- NodeAssert.equal(requestEventsFiber.pollUnsafe(), undefined); + +- yield* Fiber.interrupt(requestEventsFiber); + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + - it.effect("routes child-session questions and replies through the parent thread", () => + - Effect.gen(function* () { + - const adapter = yield* OpenCodeAdapter; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - }), + - ); + - + -- it.effect("retries ancestry for one live child request after a transient failure", () => + -- Effect.gen(function* () { + -- const adapter = yield* OpenCodeAdapter; + -- const threadId = asThreadId("thread-child-request-ancestry-retry"); + -- const parentId = "http://127.0.0.1:9999/session"; + -- const ancestryAttempted = promiseWithResolvers(); + -- runtimeMock.state.sessionParentById.set("ses_existing_child", parentId); + -- runtimeMock.state.transientErrorSessionIds.add("ses_existing_child"); + -- runtimeMock.state.sessionGetObserved = (sessionID) => { + -- if (sessionID === "ses_existing_child") { + -- ancestryAttempted.resolve(undefined); + +- it.effect.each(["failure", "timeout"] as const)( + +- "retries ancestry for a child request after a transient %s", + +- (lookupFailure) => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId(`thread-child-request-ancestry-retry-${lookupFailure}`); + +- const parentId = "http://127.0.0.1:9999/session"; + +- const ancestryAttempted = promiseWithResolvers(); + +- runtimeMock.state.sessionParentById.set("ses_existing_child", parentId); + +- runtimeMock.state.transientErrorSessionIds.add("ses_existing_child"); + +- let lookupSignal: AbortSignal | undefined; + +- if (lookupFailure === "timeout") { + +- runtimeMock.state.sessionGetImplementation = async (_sessionID, signal) => { + +- lookupSignal = signal; + +- await new Promise(() => {}); + +- }; + - } + -- }; + -- runtimeMock.state.subscribedEvents = [ + -- { + -- id: "evt-existing-child-permission", + -- type: "permission.asked", + -- properties: permissionRequest("per_retry", "ses_existing_child"), + -- }, + -- ]; + +- runtimeMock.state.sessionGetObserved = (sessionID) => { + +- if (sessionID === "ses_existing_child") { + +- ancestryAttempted.resolve(undefined); + +- } + +- }; + +- runtimeMock.state.subscribedEvents = [ + +- { + +- id: "evt-existing-child-permission", + +- type: "permission.asked", + +- properties: permissionRequest("per_retry", "ses_existing_child"), + +- }, + +- ]; + - + -- const eventsFiber = yield* adapter.streamEvents.pipe( + -- Stream.filter( + -- (event) => + -- event.threadId === threadId && + -- (event.type === "runtime.warning" || event.type === "request.opened"), + -- ), + -- Stream.take(2), + -- Stream.runCollect, + -- Effect.forkChild, + -- ); + -- yield* adapter.startSession({ + -- provider: ProviderDriverKind.make("opencode"), + -- threadId, + -- runtimeMode: "approval-required", + -- }); + -- yield* Effect.promise(() => ancestryAttempted.promise); + -- runtimeMock.state.transientErrorSessionIds.delete("ses_existing_child"); + -- yield* advanceTestClock(250); + +- const eventsFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter( + +- (event) => + +- event.threadId === threadId && + +- (event.type === "runtime.warning" || event.type === "request.opened"), + +- ), + +- Stream.take(2), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "approval-required", + +- }); + +- yield* Effect.promise(() => ancestryAttempted.promise); + +- if (lookupFailure === "timeout") { + +- yield* Effect.yieldNow; + +- yield* advanceTestClock(10_000); + +- NodeAssert.equal(lookupSignal?.aborted, true); + +- runtimeMock.state.sessionGetImplementation = null; + +- } + +- runtimeMock.state.transientErrorSessionIds.delete("ses_existing_child"); + +- yield* advanceTestClock(250); + - + -- const events = Array.from(yield* Fiber.join(eventsFiber).pipe(Effect.timeout("1 second"))); + -- NodeAssert.deepEqual( + -- events.map((event) => event.type), + -- ["runtime.warning", "request.opened"], + -- ); + -- yield* adapter.respondToRequest(threadId, ApprovalRequestId.make("per_retry"), "accept"); + -- }), + +- const events = Array.from(yield* Fiber.join(eventsFiber).pipe(Effect.timeout("1 second"))); + +- NodeAssert.deepEqual( + +- events.map((event) => event.type), + +- ["runtime.warning", "request.opened"], + +- ); + +- yield* adapter.respondToRequest(threadId, ApprovalRequestId.make("per_retry"), "accept"); + +- }), + - ); + - + - it.effect("does not resurrect a recovered child request after its live reply", () => + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - const response = yield* Effect.exit( + - adapter.respondToRequest(threadId, ApprovalRequestId.make(stale.id), "accept"), + - ); + -- NodeAssert.equal(Exit.isFailure(response), true); + +- NodeAssert.equal(Exit.isSuccess(response), true); + +- NodeAssert.deepEqual(runtimeMock.state.permissionReplyCalls, []); + - }), + - ); + - + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - const response = yield* Effect.exit( + - adapter.respondToRequest(threadId, ApprovalRequestId.make(request.id), "accept"), + - ); + -- NodeAssert.equal(Exit.isFailure(response), true); + +- NodeAssert.equal(Exit.isSuccess(response), true); + +- NodeAssert.deepEqual(runtimeMock.state.permissionReplyCalls, []); + - }), + - ); + - + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - + - return Effect.gen(function* () { + - const adapter = yield* OpenCodeAdapter; + +- const startedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.type === "turn.started"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + - yield* adapter.startSession({ + - provider: ProviderDriverKind.make("opencode"), + - threadId: asThreadId("thread-custom-instance"), + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - }, + - agent: "github-copilot", + - variant: "high", + +- system: buildRuntimeInstructions({ + +- harness: "OpenCode", + +- model: "anthropic/claude-sonnet-4-5", + +- }), + - parts: [{ type: "text", text: "Fix it" }], + - }); + +- const started = yield* Fiber.join(startedFiber); + +- NodeAssert.equal(started._tag, "Some"); + +- if (started._tag === "Some" && started.value.type === "turn.started") { + +- NodeAssert.equal(started.value.payload.effort, undefined); + +- } + - }).pipe(Effect.provide(adapterLayer)); + - }); + - + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - providerID: "anthropic", + - modelID: "claude-sonnet-4-5", + - }, + +- system: buildRuntimeInstructions({ + +- harness: "OpenCode", + +- model: "anthropic/claude-sonnet-4-5", + +- }), + - parts: [{ type: "text", text: "Fix it" }], + - }); + - }).pipe(Effect.provide(adapterLayer)); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.test.ts (deleted) + - }), + - ); + - + +- it.effect("emits tool lifecycle events before late assistant metadata", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-tool-lifecycle"); + +- const sessionID = "http://127.0.0.1:9999/session"; + +- const messageID = "msg-tools-before-role"; + +- const start = promiseWithResolvers(); + +- const input = { command: "pwd" }; + +- const states = [ + +- { status: "pending", input, raw: "" }, + +- { status: "running", input, title: "Working directory", time: { start: 1 } }, + +- { + +- status: "completed", + +- input, + +- output: "/repo\n", + +- title: "Working directory", + +- metadata: {}, + +- time: { start: 1, end: 2 }, + +- }, + +- { status: "error", input, error: "Command failed", time: { start: 3, end: 4 } }, + +- ] satisfies ReadonlyArray; + +- runtimeMock.state.subscribedEvents = [ + +- start.promise, + +- ...states.map( + +- (state) => + +- ({ + +- id: `evt-tool-${state.status}`, + +- type: "message.part.updated", + +- properties: { + +- sessionID, + +- time: 4, + +- part: { + +- id: state.status === "error" ? "part-failed" : "part-working", + +- sessionID, + +- messageID, + +- type: "tool", + +- callID: state.status === "error" ? "call-failed" : "call-working", + +- tool: "bash", + +- state, + +- }, + +- }, + +- }) satisfies OpenCodeEvent, + +- ), + +- { + +- id: "evt-text-before-role", + +- type: "message.part.updated", + +- properties: { + +- sessionID, + +- time: 4, + +- part: { + +- id: "part-late-text", + +- sessionID, + +- messageID, + +- type: "text", + +- text: "Tool results received", + +- time: { start: 4 }, + +- }, + +- }, + +- }, + +- { + +- id: "evt-late-assistant-role", + +- type: "message.updated", + +- properties: { sessionID, info: { id: messageID, role: "assistant" } }, + +- }, + +- { + +- id: "evt-tool-lifecycle-drained", + +- type: "session.compacted", + +- properties: { sessionID }, + +- }, + +- ]; + +- const eventsFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId), + +- Stream.takeUntil((event) => event.type === "thread.state.changed"), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- yield* adapter.sendTurn({ + +- threadId, + +- input: "Read the working directory", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }); + +- start.resolve({ + +- id: "evt-tool-lifecycle-started", + +- type: "session.status", + +- properties: { sessionID, status: { type: "busy" } }, + +- }); + +- const events = yield* Fiber.join(eventsFiber); + +- const tools = events.filter( + +- (event) => + +- event.type === "item.started" || + +- event.type === "item.updated" || + +- event.type === "item.completed", + +- ); + +- NodeAssert.deepEqual( + +- tools.map((event) => [event.type, event.itemId, event.payload.status]), + +- [ + +- ["item.started", "call-working", "inProgress"], + +- ["item.updated", "call-working", "inProgress"], + +- ["item.completed", "call-working", "completed"], + +- ["item.completed", "call-failed", "failed"], + +- ], + +- ); + +- NodeAssert.partialDeepStrictEqual(tools[2]?.payload.data, { + +- command: "pwd", + +- result: "/repo\n", + +- }); + +- NodeAssert.partialDeepStrictEqual(tools[3]?.payload.data, { + +- command: "pwd", + +- state: { error: "Command failed" }, + +- }); + +- NodeAssert.deepEqual( + +- events + +- .filter((event) => event.type === "content.delta") + +- .map((event) => event.payload.delta), + +- ["Tool results received"], + +- ); + +- }), + +- ); + +- + +- it.effect("maps native task progress only while a turn is active", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-native-progress"); + +- const sessionID = "http://127.0.0.1:9999/session"; + +- const startProgress = promiseWithResolvers(); + +- const finishTurn = promiseWithResolvers(); + +- const lateProgress = promiseWithResolvers(); + +- const todos = [ + +- { content: "Read files", status: "completed", priority: "high" }, + +- { content: "Fix OpenCode", status: "in_progress", priority: "high" }, + +- { content: "Run tests", status: "pending", priority: "medium" }, + +- { content: "Old task", status: "cancelled", priority: "low" }, + +- ]; + +- const todoEvent = { + +- id: "evt-todos", + +- type: "todo.updated", + +- properties: { sessionID, todos }, + +- } satisfies OpenCodeEvent; + +- runtimeMock.state.subscribedEvents = [ + +- startProgress.promise, + +- ...["todowrite", "bash"].map( + +- (tool) => + +- ({ + +- id: `evt-${tool}`, + +- type: "message.part.updated", + +- properties: { + +- sessionID, + +- time: 2, + +- part: { + +- id: `part-${tool}`, + +- sessionID, + +- messageID: "msg-tools", + +- type: "tool", + +- callID: `call-${tool}`, + +- tool, + +- state: { + +- status: "completed", + +- input: tool === "bash" ? { command: "pwd" } : { todos }, + +- output: tool === "bash" ? "/repo\n" : "Tasks updated", + +- title: tool === "bash" ? "Working directory" : "Tasks updated", + +- metadata: {}, + +- time: { start: 1, end: 2 }, + +- }, + +- }, + +- }, + +- }) satisfies OpenCodeEvent, + +- ), + +- finishTurn.promise, + +- lateProgress.promise, + +- { id: "evt-progress-drained", type: "session.compacted", properties: { sessionID } }, + +- ]; + +- const eventsFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter( + +- (event) => + +- event.threadId === threadId && + +- (event.type === "turn.plan.updated" || event.type === "item.completed"), + +- ), + +- Stream.take(3), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- const turn = yield* adapter.sendTurn({ + +- threadId, + +- input: "Work through the task list", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }); + +- startProgress.resolve(todoEvent); + +- const events = yield* Fiber.join(eventsFiber); + +- const plan = events.find((event) => event.type === "turn.plan.updated"); + +- NodeAssert.equal(plan?.turnId, turn.turnId); + +- NodeAssert.deepEqual(plan?.payload.plan, [ + +- { step: "Read files", status: "completed" }, + +- { step: "Fix OpenCode", status: "inProgress" }, + +- { step: "Run tests", status: "pending" }, + +- ]); + +- const tools = events.filter((event) => event.type === "item.completed"); + +- NodeAssert.equal(tools[0]?.payload.itemType, "dynamic_tool_call"); + +- NodeAssert.equal(tools[1]?.payload.title, "Working directory"); + +- NodeAssert.partialDeepStrictEqual(tools[1]?.payload.data, { + +- command: "pwd", + +- result: "/repo\n", + +- }); + +- const completedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "turn.completed"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- finishTurn.resolve({ + +- id: "evt-progress-completed", + +- type: "session.status", + +- properties: { sessionID, status: { type: "idle" } }, + +- }); + +- yield* Fiber.join(completedFiber); + +- const lateEventsFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId), + +- Stream.takeUntil((event) => event.type === "thread.state.changed"), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- lateProgress.resolve({ ...todoEvent, id: "evt-late-todos" }); + +- NodeAssert.deepEqual( + +- (yield* Fiber.join(lateEventsFiber)).map((event) => event.type), + +- ["thread.state.changed"], + +- ); + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + +- it.effect("warns on disconnection and recovers a completion missed during reconnect", () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-reconnect-completion"); + +- const reconnect = promiseWithResolvers(); + +- runtimeMock.state.subscribedEvents = [reconnect.promise]; + +- runtimeMock.state.sessionStatus = "busy"; + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "full-access", + +- }); + +- const turn = yield* adapter.sendTurn({ + +- threadId, + +- input: "Work", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }); + +- const warningFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "runtime.warning"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- runtimeMock.state.eventStreamError?.(new Error("socket closed")); + +- const warning = Option.getOrThrow(yield* Fiber.join(warningFiber)); + +- NodeAssert.ok(warning.type === "runtime.warning"); + +- NodeAssert.equal(warning.payload.message, "OpenCode connection lost. Reconnecting."); + +- const completedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "turn.completed"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- runtimeMock.state.sessionStatus = "idle"; + +- reconnect.resolve({ + +- id: "evt-reconnected", + +- type: "server.connected", + +- properties: {}, + +- } satisfies OpenCodeEvent); + +- NodeAssert.equal(Option.getOrThrow(yield* Fiber.join(completedFiber)).turnId, turn.turnId); + +- NodeAssert.equal( + +- (yield* adapter.listSessions()).find((session) => session.threadId === threadId)?.status, + +- "ready", + +- ); + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + +- it.effect( + +- "ends a running session on clean stream closure without discarding unresolved permissions", + +- () => + +- Effect.gen(function* () { + +- const adapter = yield* OpenCodeAdapter; + +- const threadId = asThreadId("thread-stream-closed"); + +- const endStream = promiseWithResolvers(); + +- const request = permissionRequest("per_disconnect", "http://127.0.0.1:9999/session"); + +- runtimeMock.state.pendingPermissions = [request]; + +- runtimeMock.state.subscribedEvents = [endStream.promise]; + +- const openedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "request.opened"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- const session = yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "approval-required", + +- }); + +- yield* Fiber.join(openedFiber); + +- yield* adapter.sendTurn({ + +- threadId, + +- input: "Work", + +- modelSelection: createModelSelection( + +- ProviderInstanceId.make("opencode"), + +- "opencode/kimi-k3", + +- ), + +- }); + +- const exitedFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId), + +- Stream.takeUntil((event) => event.type === "session.exited"), + +- Stream.runCollect, + +- Effect.forkChild, + +- ); + +- runtimeMock.state.endEventStream = true; + +- runtimeMock.state.abortImplementation = async () => { + +- throw new Error("server unreachable"); + +- }; + +- endStream.resolve({ + +- id: "evt-busy", + +- type: "session.status", + +- properties: { sessionID: request.sessionID, status: { type: "busy" } }, + +- }); + +- const exited = yield* Fiber.join(exitedFiber); + +- NodeAssert.equal( + +- exited.some((event) => event.type === "request.resolved"), + +- false, + +- ); + +- NodeAssert.match( + +- exited.find((event) => event.type === "runtime.error")?.payload.message ?? "", + +- /event stream ended/, + +- ); + +- NodeAssert.equal(yield* adapter.hasSession(threadId), false); + +- runtimeMock.state.endEventStream = false; + +- runtimeMock.state.subscribedEvents = []; + +- runtimeMock.state.abortImplementation = null; + +- const recoveredFiber = yield* adapter.streamEvents.pipe( + +- Stream.filter((event) => event.threadId === threadId && event.type === "request.opened"), + +- Stream.runHead, + +- Effect.forkChild, + +- ); + +- yield* adapter.startSession({ + +- provider: ProviderDriverKind.make("opencode"), + +- threadId, + +- runtimeMode: "approval-required", + +- resumeCursor: session.resumeCursor, + +- }); + +- NodeAssert.equal( + +- Option.getOrThrow(yield* Fiber.join(recoveredFiber)).requestId, + +- request.id, + +- ); + +- yield* adapter.respondToRequest(threadId, ApprovalRequestId.make(request.id), "accept"); + +- yield* adapter.stopSession(threadId); + +- }), + +- ); + +- + - it.effect("lets OpenCode own session title generation and emits title metadata updates", () => + - Effect.gen(function* () { + - const adapter = yield* OpenCodeAdapter; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - RuntimeRequestId, + - ThreadId, + - type ToolLifecycleItemType, + +- type TurnTokenUsage, + - TurnId, + - type UserInputQuestion, + -} from "@t3tools/contracts"; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - ProviderAdapterSessionNotFoundError, + - ProviderAdapterValidationError, + -} from "../Errors.ts"; + +-import { buildRuntimeInstructions } from "../RuntimeInstructions.ts"; + -import { type OpenCodeAdapterShape } from "../Services/OpenCodeAdapter.ts"; + -import { + - buildOpenCodePermissionRules, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - readonly openCodeSessionId: string; + - readonly relatedSessionIds: Set; + - readonly resolvedRequestIds: Set; + +- readonly autoRepliedRequestIds: Set; + - readonly emittedTerminalRequestIds: Set; + - readonly requestRelationRetries: Map; + - readonly pendingPermissions: Map; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - readonly partById: Map; + - readonly emittedTextByPartId: Map; + - readonly completedAssistantPartIds: Set; + -- readonly turns: Array; + +- turnTokenUsage: OpenCodeTurnTokenUsageAccumulator | undefined; + - activeTurnId: TurnId | undefined; + - activeAgent: string | undefined; + - activeVariant: string | undefined; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - readonly sessionScope: Scope.Closeable; + -} + - + +-interface OpenCodeTurnTokenUsageAccumulator { + +- readonly partIds: Set; + +- readonly promptMessageIds: Set; + +- readonly assistantOwnershipByMessageId: Map; + +- readonly unresolvedStepPartIds: Set; + +- inputTokens: number; + +- cachedInputTokens: number; + +- cacheCreationTokens: number; + +- outputTokens: number; + +- reasoningTokens: number; + +- complete: boolean; + +- hasSubagents: boolean; + +-} + +- + +-function makeOpenCodeTurnTokenUsageAccumulator(): OpenCodeTurnTokenUsageAccumulator { + +- return { + +- partIds: new Set(), + +- promptMessageIds: new Set(), + +- assistantOwnershipByMessageId: new Map(), + +- unresolvedStepPartIds: new Set(), + +- inputTokens: 0, + +- cachedInputTokens: 0, + +- cacheCreationTokens: 0, + +- outputTokens: 0, + +- reasoningTokens: 0, + +- complete: true, + +- hasSubagents: false, + +- }; + +-} + +- + +-function accumulateOpenCodeStepUsage( + +- accumulator: OpenCodeTurnTokenUsageAccumulator, + +- part: Extract, + +-): void { + +- if (accumulator.partIds.has(part.id)) return; + +- accumulator.partIds.add(part.id); + +- accumulator.inputTokens += part.tokens.input + part.tokens.cache.read + part.tokens.cache.write; + +- accumulator.cachedInputTokens += part.tokens.cache.read; + +- accumulator.cacheCreationTokens += part.tokens.cache.write; + +- accumulator.outputTokens += part.tokens.output + part.tokens.reasoning; + +- accumulator.reasoningTokens += part.tokens.reasoning; + +-} + +- + +-function takeOpenCodeTurnTokenUsage( + +- context: OpenCodeSessionContext, + +- complete: boolean, + +-): TurnTokenUsage { + +- const usage = context.turnTokenUsage; + +- context.turnTokenUsage = undefined; + +- if (!usage || usage.partIds.size === 0) { + +- return { + +- usageStatus: "unavailable", + +- usageScope: "main_agent", + +- hasSubagents: usage?.hasSubagents ?? false, + +- }; + +- } + +- return { + +- usageStatus: + +- complete && usage.complete && usage.unresolvedStepPartIds.size === 0 ? "complete" : "partial", + +- usageScope: "main_agent", + +- inputTokens: usage.inputTokens, + +- cachedInputTokens: usage.cachedInputTokens, + +- cacheCreationTokens: usage.cacheCreationTokens, + +- outputTokens: usage.outputTokens, + +- reasoningTokens: Math.min(usage.outputTokens, usage.reasoningTokens), + +- hasSubagents: usage.hasSubagents, + +- }; + +-} + +- + -export interface OpenCodeAdapterLiveOptions { + - readonly instanceId?: ProviderInstanceId; + - readonly environment?: NodeJS.ProcessEnv; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - + -function toToolLifecycleItemType(toolName: string): ToolLifecycleItemType { + - const normalized = toolName.toLowerCase(); + +- if (normalized === "todowrite" || normalized === "todoread") { + +- return "dynamic_tool_call"; + +- } + - if (normalized.includes("bash") || normalized.includes("command")) { + - return "command_execution"; + - } + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - + -function mapPermissionToRequestType( + - permission: string, + --): "command_execution_approval" | "file_read_approval" | "file_change_approval" | "unknown" { + +-): "command_execution_approval" | "file_read_approval" | "file_change_approval" { + - switch (permission) { + -- case "bash": + -- return "command_execution_approval"; + - case "read": + - return "file_read_approval"; + - case "edit": + - return "file_change_approval"; + - default: + -- return "unknown"; + +- // Every OpenCode permission needs an actionable approval in each client. + +- return "command_execution_approval"; + - } + -} + - + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - } + -} + - + --function resolveTurnSnapshot( + -- context: OpenCodeSessionContext, + -- turnId: TurnId, + --): OpenCodeTurnSnapshot { + -- const existing = context.turns.find((turn) => turn.id === turnId); + -- if (existing) { + -- return existing; + -- } + -- + -- const created: OpenCodeTurnSnapshot = { id: turnId, items: [] }; + -- context.turns.push(created); + -- return created; + --} + -- + --function appendTurnItem( + -- context: OpenCodeSessionContext, + -- turnId: TurnId | undefined, + -- item: unknown, + --): void { + -- if (!turnId) { + -- return; + -- } + -- resolveTurnSnapshot(context, turnId).items.push(item); + --} + -- + -const ensureSessionContext = Effect.fn("ensureSessionContext")(function* ( + - sessions: ReadonlyMap, + - threadId: ThreadId, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - + - const emit = (event: ProviderRuntimeEvent) => + - Queue.offer(runtimeEvents, event).pipe(Effect.asVoid); + +- // Synchronous publish for callers that must not yield between a state + +- // check and the enqueue, e.g. reopening an approval only if its terminal + +- // event has not landed yet. + +- const emitUnsafe = (event: ProviderRuntimeEvent) => { + +- Queue.offerUnsafe(runtimeEvents, event); + +- }; + - const writeNativeEvent = ( + - threadId: ThreadId, + - event: { + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - ) { + - context.pendingIdleReconciliation = undefined; + - } + +- const tokenUsage = takeOpenCodeTurnTokenUsage(context, true); + - context.activeTurnId = undefined; + - context.activeAgent = undefined; + - context.activeVariant = undefined; + - context.interruptedTurnId = undefined; + - context.awaitingBusyAfterInterruption = false; + - context.reconcileIdleStatus = false; + +- for (const requestId of context.autoRepliedRequestIds) { + +- context.emittedTerminalRequestIds.add(requestId); + +- } + +- context.autoRepliedRequestIds.clear(); + - applyProviderSessionUpdate( + - context, + - { status: "ready" }, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - if (pendingIdleReconciliation?.fiber) { + - yield* Fiber.interrupt(pendingIdleReconciliation.fiber); + - } + +- yield* schedulePendingRequestRecovery(context); + - yield* emit({ + - ...(yield* buildEventBase({ + - threadId: context.session.threadId, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - type: "turn.completed", + - payload: { + - state: "completed", + +- tokenUsage, + - }, + - }); + - }); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - deleteContextIfCurrent(context); + - return; + - } + +- const tokenUsage = takeOpenCodeTurnTokenUsage(context, false); + - context.promptAdmission = undefined; + - context.activeTurnId = undefined; + - context.activeAgent = undefined; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - payload: { + - state: "failed", + - errorMessage: detail, + +- tokenUsage, + - }, + - }); + - yield* emit({ + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - if (cancellation) { + - context.cancellation = undefined; + - } + +- let tokenUsage: TurnTokenUsage = { + +- usageStatus: "unavailable", + +- usageScope: "main_agent", + +- hasSubagents: false, + +- }; + - if (context.activeTurnId === turnId) { + +- tokenUsage = takeOpenCodeTurnTokenUsage(context, false); + - context.activeTurnId = undefined; + - context.activeAgent = undefined; + - context.activeVariant = undefined; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - { clearActiveTurnId: true, clearLastError: true }, + - ); + - } + +- yield* clearPendingOpenCodeRequests(context, { type: "session.abort" }); + - yield* emit({ + - ...(yield* buildEventBase({ + - threadId: context.session.threadId, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - type: "turn.aborted", + - payload: { + - reason: "Interrupted by user.", + +- tokenUsage, + - }, + - }); + - if (cancellation) { + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - } + - }); + - + +- // Records a child session of this thread. A child seen during a live turn + +- // means that turn used subagents, whether the relation came from a + +- // `session.created` event or a later ancestry lookup after reconnect. + +- const addRelatedOpenCodeSession = (context: OpenCodeSessionContext, sessionId: string) => { + +- context.relatedSessionIds.add(sessionId); + +- if (context.activeTurnId && context.turnTokenUsage) { + +- context.turnTokenUsage.hasSubagents = true; + +- } + +- }; + +- + - const isRelatedOpenCodeSession = Effect.fn("isRelatedOpenCodeSession")(function* ( + - context: OpenCodeSessionContext, + - candidateSessionId: string, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - + - const seen = new Set(); + - const getSession = (sessionID: string) => + -- runOpenCodeSdk("session.get", () => context.client.session.get({ sessionID })).pipe( + +- runOpenCodeSdk("session.get", (signal) => + +- context.client.session.get({ sessionID }, { signal }), + +- ).pipe( + +- Effect.timeoutOrElse({ + +- duration: "10 seconds", + +- orElse: () => + +- Effect.fail( + +- new OpenCodeRuntimeError({ + +- operation: "session.get", + +- detail: "OpenCode session ancestry lookup did not complete within 10 seconds.", + +- }), + +- ), + +- }), + - Effect.catchIf( + - (cause) => isOpenCodeNotFound(cause), + - () => Effect.succeed(undefined), + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - let sessionId: string | undefined = candidateSessionId; + - for (let depth = 0; sessionId !== undefined && depth < 32; depth += 1) { + - if (context.relatedSessionIds.has(sessionId)) { + -- context.relatedSessionIds.add(candidateSessionId); + +- addRelatedOpenCodeSession(context, candidateSessionId); + - return true; + - } + - if (seen.has(sessionId)) { + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - return false; + - }); + - + +- const openPermissionRequest = Effect.fn("openPermissionRequest")(function* ( + +- context: OpenCodeSessionContext, + +- request: PermissionRequest, + +- raw: unknown, + +- ) { + +- const base = yield* buildEventBase({ + +- threadId: context.session.threadId, + +- turnId: context.activeTurnId, + +- requestId: request.id, + +- raw, + +- }); + +- const stopped = yield* Ref.get(context.stopped); + +- if ( + +- stopped || + +- context.emittedTerminalRequestIds.has(request.id) || + +- context.pendingPermissions.has(request.id) + +- ) { + +- return; + +- } + +- const patterns = request.patterns.filter((pattern) => pattern !== "*"); + +- const detail = + +- request.permission === "bash" && patterns.length > 0 + +- ? patterns.join("\n") + +- : [request.permission.replaceAll("_", " "), ...patterns].join("\n"); + +- context.autoRepliedRequestIds.delete(request.id); + +- context.pendingPermissions.set(request.id, request); + +- emitUnsafe({ + +- ...base, + +- type: "request.opened", + +- payload: { + +- requestType: mapPermissionToRequestType(request.permission), + +- detail, + +- args: request.metadata, + +- options: [ + +- { decision: "accept", label: "Allow once" }, + +- { + +- decision: "acceptForSession", + +- label: "Allow for workspace", + +- warning: "Applies to matching requests in other OpenCode sessions in this workspace.", + +- }, + +- { decision: "decline", label: "Deny" }, + +- ], + +- }, + +- }); + +- }); + +- + +- // Full access means the user already granted everything, but two upstream + +- // paths never consult the session ruleset we send: doom-loop detection + +- // (evaluated against the agent ruleset only) and subagent sessions (which + +- // keep only deny and external-directory rules). Answer those asks here. + +- // + +- // Reply "once", not "always": OpenCode stores "always" grants per + +- // directory, so on a shared external server an "always" from a full-access + +- // thread would silently widen what a supervised thread on the same + +- // directory is allowed to do. + +- const autoReplyFullAccess = Effect.fn("autoReplyFullAccess")(function* ( + +- context: OpenCodeSessionContext, + +- request: PermissionRequest, + +- raw: unknown, + +- ) { + +- const replied = yield* runOpenCodeSdk("permission.reply", (signal) => + +- context.client.permission.reply({ requestID: request.id, reply: "once" }, { signal }), + +- ).pipe( + +- Effect.timeout("10 seconds"), + +- Effect.as(true), + +- Effect.orElseSucceed(() => false), + +- ); + +- if (!replied) { + +- // Fall back to the dialog. The id stays resolved so a recovered copy + +- // of this ask cannot reopen after the user answers; + +- // `pendingPermissions` gates re-asks while the dialog is open. + +- yield* openPermissionRequest(context, request, raw); + +- } + +- }); + +- + - const emitPendingOpenCodeRequest = Effect.fn("emitPendingOpenCodeRequest")(function* ( + - context: OpenCodeSessionContext, + - event: OpenCodeAskedRequestEvent, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - if (context.resolvedRequestIds.has(event.properties.id)) { + - return; + - } + +- if (context.activeTurnId === undefined && context.reconcileIdleStatus) { + +- context.resolvedRequestIds.add(event.properties.id); + +- return; + +- } + - if (event.type === "permission.asked") { + - const request = event.properties; + - if (context.pendingPermissions.has(request.id)) { + - return; + - } + -- context.pendingPermissions.set(request.id, request); + -- yield* emit({ + -- ...(yield* buildEventBase({ + -- threadId: context.session.threadId, + -- turnId: context.activeTurnId, + -- requestId: request.id, + -- raw, + -- })), + -- type: "request.opened", + -- payload: { + -- requestType: mapPermissionToRequestType(request.permission), + -- detail: request.patterns.length > 0 ? request.patterns.join("\n") : request.permission, + -- args: request.metadata, + -- }, + -- }); + +- if (context.session.runtimeMode === "full-access") { + +- // Reply outside the event pump so a slow HTTP response cannot hide + +- // progress, terminal replies, or the acknowledgment for Stop. + +- context.resolvedRequestIds.add(request.id); + +- context.autoRepliedRequestIds.add(request.id); + +- yield* autoReplyFullAccess(context, request, raw).pipe( + +- Effect.forkIn(context.sessionScope), + +- ); + +- return; + +- } + +- yield* openPermissionRequest(context, request, raw); + - return; + - } + - + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - if (context.pendingQuestions.has(request.id)) { + - return; + - } + +- const base = yield* buildEventBase({ + +- threadId: context.session.threadId, + +- turnId: context.activeTurnId, + +- requestId: request.id, + +- raw, + +- }); + +- const stopped = yield* Ref.get(context.stopped); + +- if (stopped || context.resolvedRequestIds.has(request.id)) { + +- return; + +- } + - context.pendingQuestions.set(request.id, request); + -- yield* emit({ + -- ...(yield* buildEventBase({ + -- threadId: context.session.threadId, + -- turnId: context.activeTurnId, + -- requestId: request.id, + -- raw, + -- })), + +- emitUnsafe({ + +- ...base, + - type: "user-input.requested", + - payload: { questions: normalizeQuestionRequest(request) }, + - }); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - const emitTerminalOpenCodeRequest = Effect.fn("emitTerminalOpenCodeRequest")(function* ( + - context: OpenCodeSessionContext, + - event: OpenCodeTerminalRequestEvent, + +- raw: unknown = event, + - ) { + - const requestId = event.properties.requestID; + - if (context.emittedTerminalRequestIds.has(requestId)) { + - return; + - } + +- if (context.autoRepliedRequestIds.delete(requestId)) { + +- context.emittedTerminalRequestIds.add(requestId); + +- return; + +- } + +- const base = yield* buildEventBase({ + +- threadId: context.session.threadId, + +- turnId: context.activeTurnId, + +- requestId, + +- raw, + +- }); + +- if (context.emittedTerminalRequestIds.has(requestId)) return; + - context.emittedTerminalRequestIds.add(requestId); + - if (event.type === "permission.replied") { + -- yield* emit({ + -- ...(yield* buildEventBase({ + -- threadId: context.session.threadId, + -- turnId: context.activeTurnId, + -- requestId, + -- raw: event, + -- })), + +- const request = context.pendingPermissions.get(requestId); + +- context.pendingPermissions.delete(requestId); + +- emitUnsafe({ + +- ...base, + - type: "request.resolved", + - payload: { + -- requestType: "unknown", + +- requestType: request ? mapPermissionToRequestType(request.permission) : "unknown", + - decision: mapPermissionDecision(event.properties.reply), + - }, + - }); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - } + - + - const request = context.pendingQuestions.get(requestId); + +- context.pendingQuestions.delete(requestId); + - const answers = + - event.type === "question.replied" && request + - ? Object.fromEntries( + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - ]), + - ) + - : {}; + -- yield* emit({ + -- ...(yield* buildEventBase({ + -- threadId: context.session.threadId, + -- turnId: context.activeTurnId, + -- requestId, + -- raw: event, + -- })), + +- emitUnsafe({ + +- ...base, + - type: "user-input.resolved", + - payload: { answers }, + - }); + - }); + - + +- const closePendingOpenCodeRequests = Effect.fn("closePendingOpenCodeRequests")(function* ( + +- context: OpenCodeSessionContext, + +- permissions: ReadonlyArray, + +- questions: ReadonlyArray, + +- raw: unknown, + +- ) { + +- for (const request of permissions) { + +- if (!context.pendingPermissions.has(request.id)) continue; + +- yield* resolvePendingOpenCodeRequest(context, request.id); + +- const base = yield* buildEventBase({ + +- threadId: context.session.threadId, + +- turnId: context.activeTurnId, + +- requestId: request.id, + +- raw, + +- }); + +- if (context.emittedTerminalRequestIds.has(request.id)) continue; + +- context.pendingPermissions.delete(request.id); + +- context.emittedTerminalRequestIds.add(request.id); + +- emitUnsafe({ + +- ...base, + +- type: "request.resolved", + +- payload: { requestType: mapPermissionToRequestType(request.permission) }, + +- }); + +- } + +- for (const request of questions) { + +- if (!context.pendingQuestions.has(request.id)) continue; + +- yield* resolvePendingOpenCodeRequest(context, request.id); + +- const base = yield* buildEventBase({ + +- threadId: context.session.threadId, + +- turnId: context.activeTurnId, + +- requestId: request.id, + +- raw, + +- }); + +- if (context.emittedTerminalRequestIds.has(request.id)) continue; + +- context.pendingQuestions.delete(request.id); + +- context.emittedTerminalRequestIds.add(request.id); + +- emitUnsafe({ ...base, type: "user-input.resolved", payload: { answers: {} } }); + +- } + +- }); + +- + +- const clearPendingOpenCodeRequests = Effect.fn("clearPendingOpenCodeRequests")(function* ( + +- context: OpenCodeSessionContext, + +- raw: unknown, + +- ) { + +- context.pendingRequestRecovery = undefined; + +- for (const requestId of context.requestRelationRetries.keys()) { + +- yield* resolvePendingOpenCodeRequest(context, requestId); + +- } + +- for (const requestId of context.autoRepliedRequestIds) { + +- context.emittedTerminalRequestIds.add(requestId); + +- } + +- context.autoRepliedRequestIds.clear(); + +- yield* closePendingOpenCodeRequests( + +- context, + +- [...context.pendingPermissions.values()], + +- [...context.pendingQuestions.values()], + +- raw, + +- ); + +- }); + +- + - const scheduleRequestRelationRetry = Effect.fn("scheduleRequestRelationRetry")(function* ( + - context: OpenCodeSessionContext, + - event: OpenCodeRoutedRequestEvent, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - const run = Effect.gen(function* () { + - let retryCount = 0; + - while (context.pendingRequestRecovery === recovery) { + -- const responses = yield* Effect.all({ + -- permissions: runOpenCodeSdk("permission.list", () => context.client.permission.list()), + -- questions: runOpenCodeSdk("question.list", () => context.client.question.list()), + -- }).pipe( + +- // Only requests pending before the snapshot can be closed by it. + +- const priorPermissions = [...context.pendingPermissions.values()]; + +- const priorQuestions = [...context.pendingQuestions.values()]; + +- const responses = yield* Effect.all( + +- { + +- permissions: runOpenCodeSdk("permission.list", (signal) => + +- context.client.permission.list(undefined, { signal }), + +- ), + +- questions: runOpenCodeSdk("question.list", (signal) => + +- context.client.question.list(undefined, { signal }), + +- ), + +- }, + +- { concurrency: 2 }, + +- ).pipe( + +- Effect.timeout("10 seconds"), + - Effect.match({ + - onFailure: (cause) => ({ type: "failure" as const, cause }), + - onSuccess: (value) => ({ type: "success" as const, value }), + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - yield* Effect.sleep(`${delayMs} millis`); + - continue; + - } + +- const permissionIds = new Set(permissions.map((request) => request.id)); + +- const questionIds = new Set(questions.map((request) => request.id)); + +- yield* closePendingOpenCodeRequests( + +- context, + +- priorPermissions.filter((request) => !permissionIds.has(request.id)), + +- priorQuestions.filter((request) => !questionIds.has(request.id)), + +- { type: "pending-requests.recovered" }, + +- ); + - yield* Effect.forEach( + - permissions, + - (request) => + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - } + - yield* schedulePendingRequestRecovery(context); + - if (!isFirstConnection) { + +- if (context.turnTokenUsage) { + +- context.turnTokenUsage.complete = false; + +- } + - yield* schedulePromptAdmissionRecovery(context, event); + +- if (context.activeTurnId !== undefined && context.promptAdmission === undefined) { + +- yield* scheduleIdleReconciliation(context, context.activeTurnId, event); + +- } + - } + - return; + - } + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - if (event.type === "session.created" || event.type === "session.updated") { + - const session = event.properties.info; + - if (session.parentID && context.relatedSessionIds.has(session.parentID)) { + -- context.relatedSessionIds.add(session.id); + +- addRelatedOpenCodeSession(context, session.id); + - } + - } else if (event.type === "session.deleted") { + - context.relatedSessionIds.delete(event.properties.info.id); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - context.awaitingBusyAfterInterruption) && + - (event.type === "message.part.delta" || + - event.type === "message.part.updated" || + +- event.type === "todo.updated" || + - (event.type === "message.updated" && event.properties.info.role === "assistant")); + - if (suppressInterruptedParentOutput) { + - return; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - } + - break; + - } + +- case "session.compacted": { + +- yield* emit({ + +- ...(yield* buildEventBase({ + +- threadId: context.session.threadId, + +- turnId, + +- raw: event, + +- })), + +- type: "thread.state.changed", + +- payload: { + +- state: "compacted", + +- detail: event, + +- }, + +- }); + +- break; + +- } + - + - case "message.updated": { + - const promptAdmission = context.promptAdmission; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - } + - context.messageRoleById.set(event.properties.info.id, event.properties.info.role); + - if (event.properties.info.role === "assistant") { + +- const usage = context.turnTokenUsage; + +- const parentMessageId = + +- typeof event.properties.info.parentID === "string" && + +- event.properties.info.parentID.trim().length > 0 + +- ? event.properties.info.parentID + +- : undefined; + +- const observedOwnership = + +- parentMessageId === undefined + +- ? "unknown" + +- : usage?.promptMessageIds.has(parentMessageId) + +- ? "owned" + +- : "other"; + +- const priorOwnership = usage?.assistantOwnershipByMessageId.get( + +- event.properties.info.id, + +- ); + +- const ownership = + +- priorOwnership === undefined || priorOwnership === "unknown" + +- ? observedOwnership + +- : priorOwnership; + +- if (usage) { + +- usage.assistantOwnershipByMessageId.set(event.properties.info.id, ownership); + +- } + - for (const part of context.partById.values()) { + - if (part.messageID !== event.properties.info.id) { + - continue; + - } + +- if (usage && part.type === "step-finish") { + +- if (ownership !== "unknown") usage.unresolvedStepPartIds.delete(part.id); + +- if (ownership === "owned") accumulateOpenCodeStepUsage(usage, part); + +- } + - yield* emitAssistantTextDelta(context, part, turnId, event); + - } + - } + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - + - case "message.part.delta": { + - const existingPart = context.partById.get(event.properties.partID); + -- if (!existingPart) { + +- if ( + +- !existingPart || + +- (existingPart.type !== "text" && existingPart.type !== "reasoning") || + +- event.properties.field !== "text" + +- ) { + - break; + - } + - const role = messageRoleForPart(context, existingPart); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - + - case "message.part.updated": { + - const part = event.properties.part; + -- context.partById.set(part.id, part); + +- // Tool events use the incoming part and do not need a cached copy. + +- if (part.type !== "tool") { + +- context.partById.set(part.id, part); + +- } + - const messageRole = messageRoleForPart(context, part); + - + +- if (turnId && part.type === "step-finish" && context.turnTokenUsage) { + +- const ownership = context.turnTokenUsage.assistantOwnershipByMessageId.get( + +- part.messageID, + +- ); + +- if (ownership === "owned") { + +- accumulateOpenCodeStepUsage(context.turnTokenUsage, part); + +- } else if ( + +- ownership === "unknown" || + +- (ownership === undefined && + +- context.messageRoleById.get(part.messageID) !== "assistant") + +- ) { + +- context.turnTokenUsage.unresolvedStepPartIds.add(part.id); + +- } + +- } + +- + - if (messageRole === "assistant") { + - yield* emitAssistantTextDelta(context, part, turnId, event); + - } + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - if (part.type === "tool") { + - const itemType = toToolLifecycleItemType(part.tool); + - const title = + -- part.state.status === "running" ? (part.state.title ?? part.tool) : part.tool; + +- part.state.status === "running" || part.state.status === "completed" + +- ? (part.state.title ?? part.tool) + +- : part.tool; + - const detail = detailFromToolPart(part); + - const payload = { + - itemType, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - data: { + - tool: part.tool, + - state: part.state, + +- ...(typeof part.state.input.command === "string" + +- ? { command: part.state.input.command } + +- : {}), + +- ...(itemType === "file_change" ? { input: part.state.input } : {}), + +- ...(part.state.status === "completed" && + +- (itemType === "command_execution" || itemType === "mcp_tool_call") + +- ? { result: part.state.output } + +- : {}), + - }, + - }; + - const runtimeEvent: ProviderRuntimeEvent = { + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - : "item.updated", + - payload, + - }; + -- appendTurnItem(context, turnId, part); + - yield* emit(runtimeEvent); + - } + - break; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - } + - + - case "permission.replied": { + -- context.pendingPermissions.delete(event.properties.requestID); + - yield* emitTerminalOpenCodeRequest(context, event); + - break; + - } + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - + - case "question.replied": { + - yield* emitTerminalOpenCodeRequest(context, event); + -- context.pendingQuestions.delete(event.properties.requestID); + - break; + - } + - + - case "question.rejected": { + -- context.pendingQuestions.delete(event.properties.requestID); + - yield* emitTerminalOpenCodeRequest(context, event); + - break; + - } + - + +- case "todo.updated": { + +- if (turnId === undefined) break; + +- const base = yield* buildEventBase({ + +- threadId: context.session.threadId, + +- turnId, + +- raw: event, + +- }); + +- // Session-wide task updates must not reopen progress after a turn ends. + +- if (context.activeTurnId !== turnId) break; + +- emitUnsafe({ + +- ...base, + +- type: "turn.plan.updated", + +- payload: { + +- plan: event.properties.todos + +- .filter((todo) => todo.status !== "cancelled") + +- .map((todo) => ({ + +- step: trimText(todo.content) ?? "Task", + +- status: + +- todo.status === "completed" + +- ? "completed" + +- : todo.status === "in_progress" + +- ? "inProgress" + +- : "pending", + +- })), + +- }, + +- }); + +- break; + +- } + +- + - case "session.status": { + -- if (event.properties.status.type === "busy") { + +- if (event.properties.status.type === "busy" || event.properties.status.type === "retry") { + - if (turnId === undefined) { + - break; + - } + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - })), + - type: "runtime.warning", + - payload: { + -- message: event.properties.status.message, + +- message: `OpenCode retry ${event.properties.status.attempt}: ${event.properties.status.message}`, + - detail: event.properties.status, + - }, + - }); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - terminalCancellation.turnSettled = true; + - terminalCancellation.acknowledged = true; + - } + +- const tokenUsage = activeTurnId ? takeOpenCodeTurnTokenUsage(context, false) : undefined; + - context.activeTurnId = undefined; + - context.activeAgent = undefined; + - context.activeVariant = undefined; + - context.reconcileIdleStatus = false; + +- yield* schedulePendingRequestRecovery(context); + - yield* updateProviderSession( + - context, + - { + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - payload: { + - state: "failed", + - errorMessage: message, + +- tokenUsage, + - }, + - }); + - } + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - // shutdown) and cancels the in-flight `event.subscribe` fetch so + - // the async iterable unwinds cleanly. + - const eventsAbortController = new AbortController(); + -- yield* Scope.addFinalizer( + -- context.sessionScope, + -- Effect.sync(() => eventsAbortController.abort()), + +- let lastStreamError: unknown; + +- let warnedAboutDisconnect = false; + +- const streamErrors = yield* Queue.unbounded(); + +- yield* Scope.addFinalizer(context.sessionScope, Queue.shutdown(streamErrors)); + +- yield* Stream.fromQueue(streamErrors).pipe( + +- Stream.runForEach((cause) => + +- Effect.gen(function* () { + +- if (warnedAboutDisconnect) return; + +- warnedAboutDisconnect = true; + +- yield* emit({ + +- ...(yield* buildEventBase({ + +- threadId: context.session.threadId, + +- turnId: context.activeTurnId, + +- })), + +- type: "runtime.warning", + +- payload: { + +- message: "OpenCode connection lost. Reconnecting.", + +- detail: openCodeRuntimeErrorDetail(cause), + +- }, + +- }); + +- }), + +- ), + +- Effect.forkIn(context.sessionScope), + - ); + - + - // Fibers forked into `context.sessionScope` are interrupted + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - runOpenCodeSdk("event.subscribe", () => + - context.client.event.subscribe(undefined, { + - signal: eventsAbortController.signal, + +- onSseError: (cause) => { + +- lastStreamError = cause; + +- Queue.offerUnsafe(streamErrors, cause); + +- }, + - }), + - ), + - (subscription) => + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - detail: openCodeRuntimeErrorDetail(cause), + - cause, + - }), + -- ).pipe(Stream.runForEach((event) => handleSubscribedEvent(context, event))), + +- ).pipe( + +- Stream.runForEach((event) => { + +- if (event.type === "server.connected") lastStreamError = undefined; + +- if (event.type === "server.connected") warnedAboutDisconnect = false; + +- return handleSubscribedEvent(context, event); + +- }), + +- ), + - ).pipe( + - Effect.exit, + - Effect.flatMap((exit) => + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - if (eventsAbortController.signal.aborted || (yield* Ref.get(context.stopped))) { + - return; + - } + -- if (Exit.isFailure(exit)) { + -- yield* emitUnexpectedExit( + -- context, + -- openCodeRuntimeErrorDetail(Cause.squash(exit.cause)), + -- ); + -- } + +- yield* emitUnexpectedExit( + +- context, + +- Exit.isFailure(exit) + +- ? openCodeRuntimeErrorDetail(Cause.squash(exit.cause)) + +- : lastStreamError !== undefined + +- ? `OpenCode event stream disconnected: ${openCodeRuntimeErrorDetail(lastStreamError)}` + +- : "OpenCode event stream ended unexpectedly. Send another message to reconnect.", + +- ); + - }), + - ), + - Effect.forkIn(context.sessionScope), + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - Effect.forkIn(context.sessionScope), + - ); + - } + +- // Scope finalizers run in reverse order. Abort the pending read before + +- // interrupting the pump, whose iterator.return() waits for that read. + +- yield* Scope.addFinalizer( + +- context.sessionScope, + +- Effect.sync(() => eventsAbortController.abort()), + +- ); + - }); + - + - const startSession: OpenCodeAdapterShape["startSession"] = Effect.fn("startSession")( + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - openCodeSessionId: started.openCodeSession.id, + - relatedSessionIds: new Set([started.openCodeSession.id]), + - resolvedRequestIds: new Set(), + +- autoRepliedRequestIds: new Set(), + - emittedTerminalRequestIds: new Set(), + - requestRelationRetries: new Map(), + - pendingPermissions: new Map(), + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - emittedTextByPartId: new Map(), + - messageRoleById: new Map(), + - completedAssistantPartIds: new Set(), + -- turns: [], + +- turnTokenUsage: undefined, + - activeTurnId: undefined, + - activeAgent: undefined, + - activeVariant: undefined, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - context.promptAdmission = promptAdmission; + - + - context.activeTurnId = turnId; + +- if (steeringTurnId === undefined) { + +- context.turnTokenUsage = makeOpenCodeTurnTokenUsageAccumulator(); + +- } + +- context.turnTokenUsage?.promptMessageIds.add(messageId); + - context.activeAgent = agent ?? (input.interactionMode === "plan" ? "plan" : undefined); + - context.activeVariant = variant; + - if (steeringTurnId === undefined) { + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - type: "turn.started", + - payload: { + - model: modelSelection?.model ?? context.session.model, + -- ...(variant ? { effort: variant } : {}), + - }, + - }); + - } + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - model: parsedModel, + - ...(context.activeAgent ? { agent: context.activeAgent } : {}), + - ...(context.activeVariant ? { variant: context.activeVariant } : {}), + +- // OpenCode appends this after its own agent/provider prompts. + +- system: buildRuntimeInstructions({ + +- harness: "OpenCode", + +- model: `${parsedModel.providerID}/${parsedModel.modelID}`, + +- }), + - parts: [...(text ? [{ type: "text" as const, text }] : []), ...fileParts], + - }, + - { signal }, + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - } + - return; + - } + +- const tokenUsage = takeOpenCodeTurnTokenUsage(context, false); + - context.promptAdmission = undefined; + - context.activeTurnId = undefined; + - context.activeAgent = undefined; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - yield* emit({ + - ...(yield* buildEventBase({ threadId: input.threadId, turnId })), + - type: "turn.aborted", + -- payload: { reason: requestError.detail }, + +- payload: { + +- reason: requestError.detail, + +- tokenUsage, + +- }, + - }); + - return; + - } + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - }); + - return; + - } + +- const tokenUsage = takeOpenCodeTurnTokenUsage(context, false); + - context.promptAdmission = undefined; + - context.activeTurnId = undefined; + - context.activeAgent = undefined; + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - type: "turn.aborted", + - payload: { + - reason: requestError.detail, + +- tokenUsage, + - }, + - }); + - }), + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - ); + - }); + - + +- const compactThread: NonNullable = Effect.fn( + +- "compactThread", + +- )(function* (threadId, requestedModelSelection) { + +- const context = yield* ensureSessionContext(sessions, threadId); + +- yield* awaitOpenCodeContextReady(context); + +- const modelSelection = + +- requestedModelSelection ?? + +- (context.session.model + +- ? { instanceId: boundInstanceId, model: context.session.model } + +- : undefined); + +- if (modelSelection !== undefined && modelSelection.instanceId !== boundInstanceId) { + +- return yield* new ProviderAdapterValidationError({ + +- provider: PROVIDER, + +- operation: "compactThread", + +- issue: `OpenCode model selection is bound to instance '${modelSelection.instanceId}', expected '${boundInstanceId}'.`, + +- }); + +- } + +- const parsedModel = parseOpenCodeModelSlug(modelSelection?.model); + +- if (!parsedModel) { + +- return yield* new ProviderAdapterValidationError({ + +- provider: PROVIDER, + +- operation: "compactThread", + +- issue: "OpenCode compaction requires an active 'provider/model' selection.", + +- }); + +- } + +- yield* context.promptSemaphore.withPermit( + +- Effect.gen(function* () { + +- if (sessions.get(threadId) !== context || (yield* Ref.get(context.stopped))) { + +- return yield* Effect.interrupt; + +- } + +- if (context.activeTurnId !== undefined) { + +- return yield* new ProviderAdapterValidationError({ + +- provider: PROVIDER, + +- operation: "compactThread", + +- issue: "OpenCode cannot compact while a turn is running.", + +- }); + +- } + +- yield* runOpenCodeSdk("session.summarize", (signal) => + +- context.client.session.summarize( + +- { + +- sessionID: context.openCodeSessionId, + +- ...parsedModel, + +- auto: false, + +- }, + +- { signal }, + +- ), + +- ).pipe( + +- Effect.timeout("10 minutes"), + +- Effect.catchTags({ + +- OpenCodeRuntimeError: (cause) => Effect.fail(toRequestError(cause)), + +- TimeoutError: (cause) => + +- Effect.fail( + +- new ProviderAdapterRequestError({ + +- provider: PROVIDER, + +- method: "session.summarize", + +- detail: "OpenCode session compaction did not complete within 10 minutes.", + +- cause, + +- }), + +- ), + +- }), + +- Effect.asVoid, + +- ); + +- }), + +- ); + +- }); + - const interruptTurn: OpenCodeAdapterShape["interruptTurn"] = Effect.fn("interruptTurn")( + - function* (threadId, turnId) { + - const context = yield* ensureSessionContext(sessions, threadId); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - } else { + - context.cancellation = undefined; + - context.reconcileIdleStatus = true; + +- yield* clearPendingOpenCodeRequests(context, { type: "session.abort" }); + - } + - } + - yield* Deferred.succeed(cancellation.completion, undefined).pipe(Effect.ignore); + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - "respondToRequest", + - )(function* (threadId, requestId, decision) { + - const context = yield* ensureSessionContext(sessions, threadId); + -- if (!context.pendingPermissions.has(requestId)) { + +- const request = context.pendingPermissions.get(requestId); + +- if (!request) { + +- if (context.emittedTerminalRequestIds.has(requestId)) return; + - return yield* new ProviderAdapterRequestError({ + - provider: PROVIDER, + - method: "permission.reply", + -- detail: `Unknown pending permission request: ${requestId}`, + +- detail: + +- context.pendingRequestRecovery || context.requestRelationRetries.has(requestId) + +- ? "OpenCode is still loading this permission request. Try again." + +- : `Unknown pending permission request: ${requestId}`, + - }); + - } + - + -- yield* runOpenCodeSdk("permission.reply", () => + -- context.client.permission.reply({ + -- requestID: requestId, + -- reply: toOpenCodePermissionReply(decision), + +- const reply = toOpenCodePermissionReply(decision); + +- yield* runOpenCodeSdk("permission.reply", (signal) => + +- context.client.permission.reply( + +- { + +- requestID: requestId, + +- reply, + +- }, + +- { signal }, + +- ), + +- ).pipe( + +- Effect.mapError(toRequestError), + +- Effect.timeoutOrElse({ + +- duration: "10 seconds", + +- orElse: () => + +- Effect.fail( + +- new ProviderAdapterRequestError({ + +- provider: PROVIDER, + +- method: "permission.reply", + +- detail: "OpenCode permission reply did not complete within 10 seconds.", + +- }), + +- ), + - }), + -- ).pipe(Effect.mapError(toRequestError)); + +- ); + +- yield* resolvePendingOpenCodeRequest(context, requestId); + +- yield* emitTerminalOpenCodeRequest( + +- context, + +- { + +- id: `reply:${requestId}`, + +- type: "permission.replied", + +- properties: { sessionID: request.sessionID, requestID: requestId, reply }, + +- }, + +- { type: "permission.reply", requestID: requestId, reply }, + +- ); + - }); + - + - const respondToUserInput: OpenCodeAdapterShape["respondToUserInput"] = Effect.fn( + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - const context = yield* ensureSessionContext(sessions, threadId); + - const request = context.pendingQuestions.get(requestId); + - if (!request) { + +- if (context.emittedTerminalRequestIds.has(requestId)) return; + - return yield* new ProviderAdapterRequestError({ + - provider: PROVIDER, + - method: "question.reply", + -- detail: `Unknown pending user-input request: ${requestId}`, + +- detail: + +- context.pendingRequestRecovery || context.requestRelationRetries.has(requestId) + +- ? "OpenCode is still loading this question. Try again." + +- : `Unknown pending user-input request: ${requestId}`, + - }); + - } + - + -- yield* runOpenCodeSdk("question.reply", () => + -- context.client.question.reply({ + -- requestID: requestId, + -- answers: toOpenCodeQuestionAnswers(request, answers), + +- const questionAnswers = toOpenCodeQuestionAnswers(request, answers); + +- yield* runOpenCodeSdk("question.reply", (signal) => + +- context.client.question.reply( + +- { + +- requestID: requestId, + +- answers: questionAnswers, + +- }, + +- { signal }, + +- ), + +- ).pipe( + +- Effect.mapError(toRequestError), + +- Effect.timeoutOrElse({ + +- duration: "10 seconds", + +- orElse: () => + +- Effect.fail( + +- new ProviderAdapterRequestError({ + +- provider: PROVIDER, + +- method: "question.reply", + +- detail: "OpenCode question reply did not complete within 10 seconds.", + +- }), + +- ), + - }), + -- ).pipe(Effect.mapError(toRequestError)); + +- ); + +- yield* resolvePendingOpenCodeRequest(context, requestId); + +- yield* emitTerminalOpenCodeRequest( + +- context, + +- { + +- id: `reply:${requestId}`, + +- type: "question.replied", + +- properties: { + +- sessionID: request.sessionID, + +- requestID: requestId, + +- answers: questionAnswers, + +- }, + +- }, + +- { type: "question.reply", requestID: requestId }, + +- ); + - }); + - + - const stopSession: OpenCodeAdapterShape["stopSession"] = Effect.fn("stopSession")( + @@ apps/server/src/provider/Layers/OpenCodeAdapter.ts (deleted) + - }, + - startSession, + - sendTurn, + +- compactThread, + - interruptTurn, + - respondToRequest, + - respondToUserInput, + @@ apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts: describe(" + + ## apps/server/src/provider/Layers/ProviderRegistry.test.ts ## + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te + - ), + streamChanges: Stream.empty, + + applyUsageLimits: () => Effect.void, + }, + - adapter: {} as ProviderInstance["adapter"], + orchestrationAdapter: {} as ProviderInstance["orchestrationAdapter"], + textGeneration: {} as ProviderInstance["textGeneration"], + } satisfies ProviderInstance; + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te + - ), + streamChanges: Stream.empty, + + applyUsageLimits: () => Effect.void, + }, + - adapter: {} as ProviderInstance["adapter"], + + orchestrationAdapter: {} as ProviderInstance["orchestrationAdapter"], + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAl + }, + { + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te + - ), + streamChanges: Stream.empty, + + applyUsageLimits: () => Effect.void, + }, + - adapter: {} as ProviderInstance["adapter"], + + orchestrationAdapter: {} as ProviderInstance["orchestrationAdapter"], + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAl + }, + ] satisfies ReadonlyArray; + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te + - refresh: Effect.succeed(refreshedProvider), + streamChanges: Stream.fromPubSub(changes), + + applyUsageLimits: () => Effect.void, + }, + - adapter: {} as ProviderInstance["adapter"], + orchestrationAdapter: {} as ProviderInstance["orchestrationAdapter"], + textGeneration: {} as ProviderInstance["textGeneration"], + } satisfies ProviderInstance; + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te + - refresh: Effect.succeed(authoritativeProvider), + streamChanges: Stream.fromPubSub(changes), + + applyUsageLimits: () => Effect.void, + }, + - adapter: {} as ProviderInstance["adapter"], + + orchestrationAdapter: {} as ProviderInstance["orchestrationAdapter"], + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAl + } satisfies ProviderInstance; + const instanceRegistryLayer = Layer.succeed( + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te + - refresh: Effect.die(new Error("simulated refresh failure")), + streamChanges: Stream.empty, + + applyUsageLimits: () => Effect.void, + }, + - adapter: {} as ProviderInstance["adapter"], + + orchestrationAdapter: {} as ProviderInstance["orchestrationAdapter"], + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAl + } satisfies ProviderInstance; + const instanceRegistryLayer = Layer.succeed( + @@ apps/server/src/provider/Layers/ProviderRegistry.test.ts: it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te + - refresh: Effect.succeed(provider), + streamChanges: Stream.empty, + + applyUsageLimits: () => Effect.void, + }, + - adapter: {} as ProviderInstance["adapter"], + + orchestrationAdapter: {} as ProviderInstance["orchestrationAdapter"], + @@ apps/server/src/provider/Services/ProviderAdapter.ts (deleted) + - /** Starts a resumed turn with no synthetic user prompt. Omitted means the + - adapter needs an explicit continuation instruction. */ + - readonly promptlessTurnContinuation?: boolean; + +- /** False when native conversation history cannot be rewound. */ + +- readonly supportsConversationRollback?: boolean; + -} + - + -export interface ProviderThreadTurnSnapshot { + @@ apps/server/src/provider/Services/ProviderAdapter.ts (deleted) + - input: ProviderSendTurnInput, + - ) => Effect.Effect; + - + +- readonly compactThread?: ( + +- threadId: ThreadId, + +- modelSelection?: ProviderSendTurnInput["modelSelection"], + +- ) => Effect.Effect; + +- + - /** + - * Interrupt an active turn. + - */ + @@ apps/server/src/provider/Services/ProviderService.ts (deleted) + - ProviderStopSessionInput, + - ProviderUploadFeedbackInput, + - ProviderUploadFeedbackResult, + +- MessageId, + - ThreadId, + - ProviderTurnStartResult, + -} from "@t3tools/contracts"; + @@ apps/server/src/provider/Services/ProviderService.ts (deleted) + - input: ProviderSendTurnInput, + - ) => Effect.Effect; + - + +- readonly compactThread: ( + +- threadId: ThreadId, + +- modelSelection?: ProviderSendTurnInput["modelSelection"], + +- requestId?: MessageId, + +- ) => Effect.Effect; + +- + - /** + - * Interrupt a running provider turn. + - */ + @@ apps/server/src/provider/Services/ProviderService.ts (deleted) + - ) => Effect.Effect; + - + - /** + +- * Reject unsupported rewind before files change, without resuming the session. + +- */ + +- readonly assertConversationRollbackSupported: ( + +- threadId: ThreadId, + +- ) => Effect.Effect; + +- + +- /** + - * Roll back provider conversation state by a number of turns. + - */ + - readonly rollbackConversation: (input: { + @@ apps/server/src/relay/AgentAwarenessRelay.test.ts (deleted) + - ).toEqual([activeThreadId]); + - }); + - + -- it("signs the activity publish JWT and rejects tampering", async () => { + -- const keyPair = NodeCrypto.generateKeyPairSync("ed25519", { + -- privateKeyEncoding: { format: "pem", type: "pkcs8" }, + -- publicKeyEncoding: { format: "pem", type: "spki" }, + -- }); + -- const payload = { + -- iss: "t3-env:env", + -- aud: "https://relay.example.test", + -- sub: "env", + -- jti: "nonce-1", + -- iat: 100, + -- exp: 200, + -- environmentId: state.environmentId, + -- threadId: state.threadId, + -- state, + -- } satisfies RelayAgentActivityPublishProofPayload; + -- const proof = await Effect.runPromise( + -- AgentAwarenessRelay.signRelayAgentActivityPublishProof({ + +- it.effect("signs the activity publish JWT and rejects tampering", () => + +- Effect.gen(function* () { + +- const keyPair = NodeCrypto.generateKeyPairSync("ed25519", { + +- privateKeyEncoding: { format: "pem", type: "pkcs8" }, + +- publicKeyEncoding: { format: "pem", type: "spki" }, + +- }); + +- const payload = { + +- iss: "t3-env:env", + +- aud: "https://relay.example.test", + +- sub: "env", + +- jti: "nonce-1", + +- iat: 100, + +- exp: 200, + +- environmentId: state.environmentId, + +- threadId: state.threadId, + +- state, + +- } satisfies RelayAgentActivityPublishProofPayload; + +- const proof = yield* AgentAwarenessRelay.signRelayAgentActivityPublishProof({ + - privateKey: keyPair.privateKey, + - payload, + -- }), + -- ); + -- + -- await expect( + -- Effect.runPromise( + -- verifyRelayJwt({ + -- publicKey: keyPair.publicKey, + -- token: proof, + -- typ: RELAY_ACTIVITY_PUBLISH_TYP, + -- issuer: "t3-env:env", + -- audience: "https://relay.example.test", + -- nowEpochSeconds: 150, + -- }), + -- ), + -- ).resolves.toMatchObject({ jti: "nonce-1", state }); + -- await expect( + -- Effect.runPromise( + +- }); + +- const verify = (token: string) => + - verifyRelayJwt({ + - publicKey: keyPair.publicKey, + -- token: (() => { + -- const [header, body, signature = ""] = proof.split("."); + -- const corruptedSignature = `${signature.startsWith("a") ? "b" : "a"}${signature.slice(1)}`; + -- return `${header}.${body}.${corruptedSignature}`; + -- })(), + +- token, + - typ: RELAY_ACTIVITY_PUBLISH_TYP, + - issuer: "t3-env:env", + - audience: "https://relay.example.test", + - nowEpochSeconds: 150, + -- }), + -- ), + -- ).rejects.toBeDefined(); + -- }); + +- }); + +- + +- expect(yield* verify(proof)).toMatchObject({ jti: "nonce-1", state }); + +- + +- const [header, body, signature = ""] = proof.split("."); + +- const corruptedSignature = `${signature.startsWith("a") ? "b" : "a"}${signature.slice(1)}`; + +- const rejection = yield* Effect.flip(verify(`${header}.${body}.${corruptedSignature}`)); + +- expect(rejection).toBeDefined(); + +- }), + +- ); + - + - it.effect("keeps the orchestration listener armed until relay config is installed", () => + - Effect.scoped( + @@ apps/server/src/relay/AgentAwarenessRelay.test.ts (deleted) + - + - const orchestrationEngine = { + - readEvents: () => Stream.empty, + +- readThreadEvents: () => Stream.empty, + +- getThreadReplayStats: () => Effect.die("unused thread replay stats"), + - dispatch: () => Effect.succeed({ sequence: 1 }), + - streamDomainEvents: Stream.fromQueue(events), + - subscribeDomainEvents: Effect.succeed(Stream.fromQueue(events)), + @@ apps/server/src/relay/AgentAwarenessRelay.test.ts (deleted) + - Effect.scoped( + - Effect.gen(function* () { + - const originalFetch = globalThis.fetch; + -- const context = yield* Effect.context(); + -- const runFork = Effect.runForkWith(context); + - const events = yield* Queue.unbounded(); + -- const fetchSeen = yield* Deferred.make(); + +- let resolveFetchSeen: (url: URL) => void = () => {}; + +- const fetchSeen = new Promise((resolve) => { + +- resolveFetchSeen = resolve; + +- }); + - const userSpans: Array = []; + - const productSpans: Array = []; + - const collectingTracer = (spans: Array) => + @@ apps/server/src/relay/AgentAwarenessRelay.test.ts (deleted) + - ? input + - : (input as unknown as { readonly url: string }).url, + - ); + -- runFork(Deferred.succeed(fetchSeen, url)); + +- resolveFetchSeen(url); + - return Promise.resolve(Response.json({ ok: true, deliveries: [] })); + - }) as unknown as typeof fetch; + - yield* Effect.addFinalizer(() => + @@ apps/server/src/relay/AgentAwarenessRelay.test.ts (deleted) + - }), + - Layer.succeed(OrchestrationEngineService, { + - readEvents: () => Stream.empty, + +- readThreadEvents: () => Stream.empty, + +- getThreadReplayStats: () => Effect.die("unused thread replay stats"), + - dispatch: () => Effect.succeed({ sequence: 1 }), + - streamDomainEvents: Stream.fromQueue(events), + - subscribeDomainEvents: Effect.succeed(Stream.fromQueue(events)), + @@ apps/server/src/relay/AgentAwarenessRelay.test.ts (deleted) + - occurredAt: now, + - } as unknown as OrchestrationEvent); + - + -- const url = yield* Deferred.await(fetchSeen).pipe(Effect.timeout("2 seconds")); + +- const url = yield* Effect.promise(() => fetchSeen).pipe(Effect.timeout("2 seconds")); + - expect(url.origin).toBe("https://transport.example.test"); + - expect(productSpans).toContain("makePublishProof"); + - expect(userSpans).not.toContain("makePublishProof"); + @@ apps/server/src/serverRuntimeStartup.test.ts + -import * as ProjectionSnapshotQuery from "./orchestration/Services/ProjectionSnapshotQuery.ts"; + -import * as AnalyticsService from "./telemetry/AnalyticsService.ts"; + import * as ServerRuntimeStartup from "./serverRuntimeStartup.ts"; + +-import * as GitVcsDriver from "./vcs/GitVcsDriver.ts"; + + -it("uses the canonical Codex default for the auto-bootstrapped welcome thread", () => { + - assert.deepStrictEqual(ServerRuntimeStartup.getAutoBootstrapThreadModelSelection(), { + @@ apps/server/src/serverRuntimeStartup.test.ts + }); + }); + + +-it.effect("automatic pull only updates enabled, behind, clean default-branch checkouts", () => + ++it.effect("runs projection repair, recovery, worker startup, and bootstrap in order", () => + + Effect.gen(function* () { + +- const pulled: string[] = []; + +- const git = { + +- statusDetails: (cwd: string) => + +- Effect.succeed({ + +- isRepo: true, + +- isDefaultBranch: cwd !== "/feature", + +- hasUpstream: true, + +- hasWorkingTreeChanges: cwd === "/dirty", + +- aheadCount: cwd === "/ahead" ? 1 : 0, + +- behindCount: cwd === "/current" ? 0 : 1, + +- } as never), + +- pullCurrentBranch: (cwd: string) => + +- Effect.sync(() => { + +- pulled.push(cwd); + +- return { + +- status: "pulled" as const, + +- refName: "main", + +- upstreamRef: "origin/main", + +- }; + +- }), + +- } as unknown as GitVcsDriver.GitVcsDriver["Service"]; + +- const project = (workspaceRoot: string, autoPull = true) => + +- ({ workspaceRoot, autoPull }) as never; + +- + +- yield* ServerRuntimeStartup.autoPullProjects([ + +- project("/clean"), + +- project("/current"), + +- project("/dirty"), + +- project("/ahead"), + +- project("/feature"), + +- project("/disabled", false), + +- ]).pipe(Effect.provideService(GitVcsDriver.GitVcsDriver, git)); + ++ const calls = yield* Ref.make>([]); + ++ const record = (label: string) => Ref.update(calls, (current) => [...current, label]); + ++ + ++ const result = yield* ServerRuntimeStartup.runOrderedV2StartupPhases({ + ++ verify: record("verify").pipe(Effect.as({ valid: false })), + ++ rebuild: record("rebuild").pipe(Effect.as({ valid: true })), + ++ recover: record("recover").pipe(Effect.as({ resumedSessions: 2 })), + ++ startEffectWorker: record("worker"), + ++ autoBootstrap: record("bootstrap").pipe(Effect.as({ projectId: "project-1" })), + ++ }); + + + +- assert.deepStrictEqual(pulled, ["/clean"]); + ++ assert.deepEqual(yield* Ref.get(calls), [ + ++ "verify", + ++ "rebuild", + ++ "recover", + ++ "worker", + ++ "bootstrap", + ++ ]); + ++ assert.deepEqual(result, { + ++ recovery: { resumedSessions: 2 }, + ++ bootstrap: { projectId: "project-1" }, + ++ }); + + }), + + ); + + + -it.effect("enqueueCommand waits for readiness and then drains queued work", () => + - Effect.scoped( + - Effect.gen(function* () { + @@ apps/server/src/serverRuntimeStartup.test.ts + - assert.equal(yield* Ref.get(executionCount), 1); + - }), + - ), + --); + -- + ++it.effect("does not rebuild valid projections", () => + ++ Effect.gen(function* () { + ++ const rebuilt = yield* Ref.make(false); + ++ yield* ServerRuntimeStartup.runOrderedV2StartupPhases({ + ++ verify: Effect.succeed({ valid: true }), + ++ rebuild: Ref.set(rebuilt, true).pipe(Effect.as({ valid: true })), + ++ recover: Effect.void, + ++ startEffectWorker: Effect.void, + ++ autoBootstrap: Effect.void, + ++ }); + ++ assert.isFalse(yield* Ref.get(rebuilt)); + ++ }), + + ); + + + -it.effect("enqueueCommand fails queued work when readiness fails", () => + -- Effect.scoped( + -- Effect.gen(function* () { + ++it.effect("queues commands until startup signals readiness", () => + + Effect.scoped( + + Effect.gen(function* () { + - const commandGate = yield* ServerRuntimeStartup.makeCommandGate; + - const failure = yield* Deferred.make(); + - + - const queuedCommandFiber = yield* commandGate + - .enqueueCommand(Deferred.await(failure).pipe(Effect.as("should-not-run"))) + -- .pipe(Effect.forkScoped); + -- + ++ const gate = yield* ServerRuntimeStartup.makeCommandGate; + ++ const count = yield* Ref.make(0); + ++ const queued = yield* gate + ++ .enqueueCommand(Ref.updateAndGet(count, (value) => value + 1)) + + .pipe(Effect.forkScoped); + + + - yield* commandGate.failCommandReady( + - new ServerRuntimeStartup.ServerRuntimeStartupError({ + - mode: "web", + @@ apps/server/src/serverRuntimeStartup.test.ts + - + - yield* ServerRuntimeStartup.launchStartupHeartbeat.pipe( + - Effect.provideService(ProjectionSnapshotQuery.ProjectionSnapshotQuery, { + +- getUserInputActivity: () => Effect.die("unused"), + - getCommandReadModel: () => Effect.die("unused"), + - getSnapshot: () => Effect.die("unused"), + - getShellSnapshot: () => Effect.die("unused"), + @@ apps/server/src/serverRuntimeStartup.test.ts + - getFirstActiveThreadIdByProjectId: () => Effect.succeed(Option.none()), + - getThreadCheckpointContext: () => Effect.succeed(Option.none()), + - getFullThreadDiffContext: () => Effect.succeed(Option.none()), + +- getThreadRuntimeContext: () => Effect.die("unused"), + - getThreadShellById: () => Effect.succeed(Option.none()), + - getThreadDetailById: () => Effect.succeed(Option.none()), + - getThreadDetailSnapshot: () => Effect.succeed(Option.none()), + @@ apps/server/src/serverRuntimeStartup.test.ts + - // never waited for it. + - yield* Deferred.await(countsStarted); + - assert.equal(yield* Deferred.isDone(releaseCounts), false); + -- }), + -- ), + --); + ++ yield* Effect.yieldNow; + ++ assert.equal(yield* Ref.get(count), 0); + ++ yield* gate.signalCommandReady; + ++ assert.equal(yield* Fiber.join(queued), 1); + + }), + + ), + + ); + - + -it.effect("resolveWelcomeBase derives cwd and project name from server config", () => + -+it.effect("runs projection repair, recovery, worker startup, and bootstrap in order", () => + - Effect.gen(function* () { + +- Effect.gen(function* () { + - const welcome = yield* ServerRuntimeStartup.resolveWelcomeBase.pipe( + - Effect.provideService(ServerConfig.ServerConfig, { + - cwd: "/tmp/startup-project", + @@ apps/server/src/serverRuntimeStartup.test.ts + - assert.deepStrictEqual(welcome, { + - cwd: "/tmp/startup-project", + - projectName: "startup-project", + -+ const calls = yield* Ref.make>([]); + -+ const record = (label: string) => Ref.update(calls, (current) => [...current, label]); + -+ + -+ const result = yield* ServerRuntimeStartup.runOrderedV2StartupPhases({ + -+ verify: record("verify").pipe(Effect.as({ valid: false })), + -+ rebuild: record("rebuild").pipe(Effect.as({ valid: true })), + -+ recover: record("recover").pipe(Effect.as({ resumedSessions: 2 })), + -+ startEffectWorker: record("worker"), + -+ autoBootstrap: record("bootstrap").pipe(Effect.as({ projectId: "project-1" })), + - }); + +- }); + - }), + -); + - + +- + -it.effect("resolveAutoBootstrapWelcomeTargets returns existing project and thread ids", () => { + - const bootstrapProjectId = ProjectId.make("project-startup-bootstrap"); + - const bootstrapThreadId = ThreadId.make("thread-startup-bootstrap"); + @@ apps/server/src/serverRuntimeStartup.test.ts + - autoBootstrapProjectFromCwd: true, + - } as never), + - Effect.provideService(ProjectionSnapshotQuery.ProjectionSnapshotQuery, { + +- getUserInputActivity: () => Effect.die("unused"), + - getCommandReadModel: () => Effect.die("unused"), + - getSnapshot: () => Effect.die("unused"), + - getShellSnapshot: () => Effect.die("unused"), + @@ apps/server/src/serverRuntimeStartup.test.ts + - getFirstActiveThreadIdByProjectId: () => Effect.succeed(Option.some(bootstrapThreadId)), + - getThreadCheckpointContext: () => Effect.succeed(Option.none()), + - getFullThreadDiffContext: () => Effect.succeed(Option.none()), + +- getThreadRuntimeContext: () => Effect.die("unused"), + - getThreadShellById: () => Effect.die("unused"), + - getThreadDetailById: () => Effect.die("unused"), + - getThreadDetailSnapshot: () => Effect.die("unused"), + @@ apps/server/src/serverRuntimeStartup.test.ts + - }), + - Effect.provideService(OrchestrationEngine.OrchestrationEngineService, { + - readEvents: () => Stream.empty, + +- readThreadEvents: () => Stream.empty, + +- getThreadReplayStats: () => Effect.die("unused thread replay stats"), + - dispatch: (command) => + - Ref.update(dispatchCalls, (calls) => [...calls, command.type]).pipe( + - Effect.as({ sequence: 1 }), + @@ apps/server/src/serverRuntimeStartup.test.ts + - assert.deepStrictEqual(targets, { + - bootstrapProjectId, + - bootstrapThreadId, + -+ assert.deepEqual(yield* Ref.get(calls), [ + -+ "verify", + -+ "rebuild", + -+ "recover", + -+ "worker", + -+ "bootstrap", + -+ ]); + -+ assert.deepEqual(result, { + -+ recovery: { resumedSessions: 2 }, + -+ bootstrap: { projectId: "project-1" }, + - }); + +- }); + - assert.deepStrictEqual(yield* Ref.get(dispatchCalls), []); + - }); + -}); + @@ apps/server/src/serverRuntimeStartup.test.ts + - autoBootstrapProjectFromCwd: true, + - } as never), + - Effect.provideService(ProjectionSnapshotQuery.ProjectionSnapshotQuery, { + +- getUserInputActivity: () => Effect.die("unused"), + - getCommandReadModel: () => Effect.die("unused"), + - getSnapshot: () => Effect.die("unused"), + - getShellSnapshot: () => Effect.die("unused"), + @@ apps/server/src/serverRuntimeStartup.test.ts + - getFirstActiveThreadIdByProjectId: () => Effect.succeed(Option.none()), + - getThreadCheckpointContext: () => Effect.succeed(Option.none()), + - getFullThreadDiffContext: () => Effect.succeed(Option.none()), + +- getThreadRuntimeContext: () => Effect.die("unused"), + - getThreadShellById: () => Effect.die("unused"), + - getThreadDetailById: () => Effect.die("unused"), + - getThreadDetailSnapshot: () => Effect.die("unused"), + @@ apps/server/src/serverRuntimeStartup.test.ts + - }), + - Effect.provideService(OrchestrationEngine.OrchestrationEngineService, { + - readEvents: () => Stream.empty, + +- readThreadEvents: () => Stream.empty, + +- getThreadReplayStats: () => Effect.die("unused thread replay stats"), + - dispatch: (command) => + - Ref.update(dispatchCalls, (calls) => [...calls, command]).pipe( + - Effect.as({ sequence: 1 }), + @@ apps/server/src/serverRuntimeStartup.test.ts + - commands[1]?.modelSelection, + - ServerRuntimeStartup.getAutoBootstrapThreadModelSelection(), + - ); + - }), + - ); + - + +- }), + +-); + +- + -it.effect("resolveAutoBootstrapWelcomeTargets preserves typed UUID generation failures", () => + -+it.effect("does not rebuild valid projections", () => + - Effect.gen(function* () { + +- Effect.gen(function* () { + - const crypto = yield* Crypto.Crypto; + - const uuidError = PlatformError.systemError({ + - _tag: "Unknown", + - module: "Crypto", + - method: "randomUUIDv4", + - description: "UUID generation unavailable", + -+ const rebuilt = yield* Ref.make(false); + -+ yield* ServerRuntimeStartup.runOrderedV2StartupPhases({ + -+ verify: Effect.succeed({ valid: true }), + -+ rebuild: Ref.set(rebuilt, true).pipe(Effect.as({ valid: true })), + -+ recover: Effect.void, + -+ startEffectWorker: Effect.void, + -+ autoBootstrap: Effect.void, + - }); + +- }); + - const dispatchCalls = yield* Ref.make>([]); + -+ assert.isFalse(yield* Ref.get(rebuilt)); + -+ }), + -+); + - + +- + - const error = yield* ServerRuntimeStartup.resolveAutoBootstrapWelcomeTargets.pipe( + - Effect.provideService(ServerConfig.ServerConfig, { + - cwd: "/tmp/startup-project", + - autoBootstrapProjectFromCwd: true, + - } as never), + - Effect.provideService(ProjectionSnapshotQuery.ProjectionSnapshotQuery, { + +- getUserInputActivity: () => Effect.die("unused"), + - getCommandReadModel: () => Effect.die("unused"), + - getSnapshot: () => Effect.die("unused"), + - getShellSnapshot: () => Effect.die("unused"), + @@ apps/server/src/serverRuntimeStartup.test.ts + - getFirstActiveThreadIdByProjectId: () => Effect.succeed(Option.none()), + - getThreadCheckpointContext: () => Effect.succeed(Option.none()), + - getFullThreadDiffContext: () => Effect.succeed(Option.none()), + +- getThreadRuntimeContext: () => Effect.die("unused"), + - getThreadShellById: () => Effect.die("unused"), + - getThreadDetailById: () => Effect.die("unused"), + - getThreadDetailSnapshot: () => Effect.die("unused"), + @@ apps/server/src/serverRuntimeStartup.test.ts + - }), + - Effect.provideService(OrchestrationEngine.OrchestrationEngineService, { + - readEvents: () => Stream.empty, + +- readThreadEvents: () => Stream.empty, + +- getThreadReplayStats: () => Effect.die("unused thread replay stats"), + - dispatch: (command) => + - Ref.update(dispatchCalls, (calls) => [...calls, command.type]).pipe( + - Effect.as({ sequence: 1 }), + @@ apps/server/src/serverRuntimeStartup.test.ts + - }), + - Effect.flip, + - ); + -+it.effect("queues commands until startup signals readiness", () => + -+ Effect.scoped( + -+ Effect.gen(function* () { + -+ const gate = yield* ServerRuntimeStartup.makeCommandGate; + -+ const count = yield* Ref.make(0); + -+ const queued = yield* gate + -+ .enqueueCommand(Ref.updateAndGet(count, (value) => value + 1)) + -+ .pipe(Effect.forkScoped); + - + +- + - assert.strictEqual(error, uuidError); + - assert.deepStrictEqual(yield* Ref.get(dispatchCalls), []); + - }).pipe(Effect.provide(NodeServices.layer)), + -+ yield* Effect.yieldNow; + -+ assert.equal(yield* Ref.get(count), 0); + -+ yield* gate.signalCommandReady; + -+ assert.equal(yield* Fiber.join(queued), 1); + -+ }), + -+ ), + - ); + +-); + + ## apps/server/src/serverRuntimeStartup.ts ## + @@ apps/server/src/serverRuntimeStartup.ts: import { + + DEFAULT_MODEL, + + DEFAULT_PROVIDER_INTERACTION_MODE, + + type ModelSelection, + +- type OrchestrationProjectShell, + ProjectId, + ProviderInstanceId, + ThreadId, + @@ apps/server/src/serverRuntimeStartup.ts: import * as Deferred from "effect/Defer + -import * as ProviderSessionReaper from "./provider/Services/ProviderSessionReaper.ts"; + -import { forkParked } from "./serverActivation.ts"; + -import * as ServiceLauncherClient from "./cloud/serviceLauncherClient.ts"; + +-import * as GitVcsDriver from "./vcs/GitVcsDriver.ts"; + import { + formatHeadlessServeOutput, + formatHostForUrl, + @@ apps/server/src/serverRuntimeStartup.ts: const runStartupPhase = (phase + - } + - + - yield* forkParked( + -+ ), + -+ ), + -+ rebuild: runStartupPhase( + -+ "orchestration-v2.projections.rebuild", + -+ projectionMaintenance.rebuild, + -+ ), + -+ recover: runStartupPhase("orchestration-v2.recovery", providerRuntimeRecovery.recover), + -+ startEffectWorker: runStartupPhase( + -+ "orchestration-v2.effect-worker.start", + - Effect.gen(function* () { + +- Effect.gen(function* () { + - const continuation = Effect.gen(function* () { + - const providerInstanceId = binding.value.providerInstanceId; + - if (providerInstanceId === undefined) { + @@ apps/server/src/serverRuntimeStartup.ts: const runStartupPhase = (phase + - yield* settleAsError( + - "Could not continue this thread after the server update. Send a new message to continue.", + - ).pipe(Effect.ignoreCause); + -+ yield* EffectWorker.runDaemon.pipe(Effect.forkScoped); + -+ yield* agentAwarenessRelay.start(); + - }), + +- }), + - ); + - continue; + - } + @@ apps/server/src/serverRuntimeStartup.ts: const runStartupPhase = (phase + - readonly abort?: (error: ServerRuntimeStartupError) => Effect.Effect; + -} + - + +-export const autoPullProjects = Effect.fn("autoPullProjects")(function* ( + +- projects: ReadonlyArray, + +-) { + +- const git = yield* GitVcsDriver.GitVcsDriver; + +- const workspaceRoots = [ + +- ...new Set( + +- projects + +- .filter((project) => project.autoPull === true) + +- .map((project) => project.workspaceRoot), + +- ), + +- ]; + +- + +- yield* Effect.forEach( + +- workspaceRoots, + +- (cwd) => + +- Effect.gen(function* () { + +- const status = yield* git.statusDetails(cwd); + +- if ( + +- !status.isRepo || + +- !status.isDefaultBranch || + +- !status.hasUpstream || + +- status.hasWorkingTreeChanges || + +- status.aheadCount > 0 + +- ) { + +- yield* Effect.logDebug("Skipped automatic project pull", { + +- cwd, + +- reason: !status.isRepo + +- ? "not-a-repository" + +- : !status.isDefaultBranch + +- ? "not-on-default-branch" + +- : !status.hasUpstream + +- ? "no-upstream" + +- : status.hasWorkingTreeChanges + +- ? "working-tree-changes" + +- : "local-commits", + +- }); + +- return; + +- } + +- + +- if (status.behindCount <= 0) return; + +- + +- const result = yield* git.pullCurrentBranch(cwd); + +- yield* Effect.logDebug("Automatic project pull completed", { + +- cwd, + +- status: result.status, + +- refName: result.refName, + +- }); + +- }).pipe( + +- Effect.catch((cause) => + +- Effect.logWarning("Automatic project pull failed", { + +- cwd, + +- cause, + +- }), + + ), + + ), + +- { concurrency: 4, discard: true }, + +- ); + +-}); + +- + -export const make = (options?: StartupOptions) => + - Effect.gen(function* () { + - const serverConfig = yield* ServerConfig.ServerConfig; + @@ apps/server/src/serverRuntimeStartup.ts: const runStartupPhase = (phase + - const commandGate = yield* makeCommandGate; + - const httpListening = yield* Deferred.make(); + - const reactorScope = yield* Scope.make("sequential"); + +- + +- const syncAutoPullProjects = projectionSnapshotQuery.getShellSnapshot().pipe( + +- Effect.flatMap((snapshot) => autoPullProjects(snapshot.projects)), + +- Effect.catch((cause) => + +- Effect.logWarning("Failed to load projects for automatic pull", { cause }), + ++ rebuild: runStartupPhase( + ++ "orchestration-v2.projections.rebuild", + ++ projectionMaintenance.rebuild, + + ), + +- ); + ++ recover: runStartupPhase("orchestration-v2.recovery", providerRuntimeRecovery.recover), + ++ startEffectWorker: runStartupPhase( + ++ "orchestration-v2.effect-worker.start", + ++ Effect.gen(function* () { + ++ yield* EffectWorker.runDaemon.pipe(Effect.forkScoped); + ++ yield* agentAwarenessRelay.start(); + ++ }), + + ), + + autoBootstrap: (serverConfig.autoBootstrapProjectFromCwd + + ? runStartupPhase( + @@ apps/server/src/serverRuntimeStartup.ts: export const make = (options?: StartupO + ); + + - yield* runStartupPhase("provider-sessions.reconcile", reconcileProviderSessions); + +- + +- yield* Effect.logDebug("startup phase: syncing clean projects"); + +- yield* runStartupPhase("projects.auto-pull", syncAutoPullProjects); + - + const welcomeBase = yield* resolveWelcomeBase; + const environment = yield* serverEnvironment.getDescriptor; + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + - return output; + - }); + - + -- const coalesceShellLiveStream = ( + -- stream: Stream.Stream, + -- ): Stream.Stream => + -- stream.pipe( + -- Stream.groupedWithin(SHELL_COALESCE_MAX_CHUNK, SHELL_COALESCE_WINDOW), + -- Stream.mapEffect(coalesceShellLiveInputs), + -- Stream.flatMap((items) => Stream.fromIterable(items)), + -- ); + -- + - const dispatchBootstrapTurnStart = ( + - command: Extract, + - ): Effect.Effect<{ readonly sequence: number }, OrchestrationDispatchCommandError> => + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + - // sequence but the live subscription is not attached yet). Every + - // path below emits from this same buffered live tail. Overlapping + - // events are deduped by sequence on the client. + -- const liveBuffer = yield* Queue.unbounded(); + +- const liveBudget = yield* makeLiveStreamBudget(); + +- const liveBuffer = yield* Queue.unbounded< + +- RetainedLiveItem, + +- OrchestrationGetSnapshotError + +- >(); + +- let liveBufferClosed = false; + +- const closeLiveBuffer = (error?: OrchestrationGetSnapshotError) => + +- Effect.gen(function* () { + +- if (liveBufferClosed) { + +- return; + +- } + +- liveBufferClosed = true; + +- liveBudget.release(yield* Queue.clear(liveBuffer).pipe(Effect.orDie)); + +- if (error) { + +- yield* Queue.fail(liveBuffer, error); + +- } + +- yield* Queue.shutdown(liveBuffer); + +- }); + +- yield* Effect.addFinalizer(() => closeLiveBuffer()); + +- yield* liveBudget.failed.pipe( + +- Effect.catchTags({ OrchestrationGetSnapshotError: closeLiveBuffer }), + +- Effect.forkScoped, + +- ); + - yield* Effect.forkScoped( + - orchestrationEngine.streamDomainEvents.pipe( + - Stream.runForEach((event) => + -- Queue.offer(liveBuffer, { kind: "event" as const, event }), + +- liveBudget.retain({ kind: "event" as const, event }, event).pipe( + +- Effect.flatMap((item) => Queue.offer(liveBuffer, item)), + +- Effect.uninterruptible, + +- ), + - ), + +- // Stop the PubSub consumer even if RPC delivery is waiting + +- // for an ACK and never pulls the failed buffer again. + +- Effect.raceFirst(liveBudget.failed), + +- Effect.catchTags({ OrchestrationGetSnapshotError: () => Effect.void }), + - ), + - { startImmediately: true }, + - ); + -- const bufferedLiveStream = coalesceShellLiveStream(Stream.fromQueue(liveBuffer)); + +- const coalesceRetainedInputs = ( + +- items: ReadonlyArray>, + +- ) => + +- coalesceShellLiveInputs(items.map((item) => item.value)).pipe( + +- Effect.flatMap((output) => liveBudget.replace(items, output)), + +- ); + +- const bufferedLiveStream = Stream.fromQueue(liveBuffer).pipe( + +- Stream.groupedWithin(SHELL_COALESCE_MAX_CHUNK, SHELL_COALESCE_WINDOW), + +- Stream.mapEffect(coalesceRetainedInputs), + +- Stream.flatMap((items) => Stream.fromIterable(items)), + +- ); + + const getOrchestrationV2ArchivedShellSnapshot = threadManagement.getShellSnapshot().pipe( + + Effect.map((snapshot) => ({ + + schemaVersion: snapshot.schemaVersion, + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + - // Offer the completion marker into the same queue as live events. + - // Anything buffered while snapshot/replay work was in flight is + - // therefore delivered before the client is told it is synchronized. + -- const synchronizedThenLive = + +- const synchronizedThenLive = liveBudget.deliver( + - input.requestCompletionMarker === true + - ? Stream.concat( + - Stream.fromEffect( + -- Queue.offer(liveBuffer, { kind: "synchronized" as const }).pipe( + +- liveBudget.retain({ kind: "synchronized" as const }).pipe( + +- Effect.flatMap((item) => Queue.offer(liveBuffer, item)), + +- Effect.uninterruptible, + - Effect.andThen(Queue.takeAll(liveBuffer)), + -- Effect.flatMap(coalesceShellLiveInputs), + +- Effect.flatMap(coalesceRetainedInputs), + - ), + - ).pipe(Stream.flatMap((items) => Stream.fromIterable(items))), + - bufferedLiveStream, + - ) + -- : bufferedLiveStream; + +- : bufferedLiveStream, + +- ); + - + - // When the client already holds a shell snapshot (cached, or loaded + - // over HTTP) it passes that snapshot's sequence, and we resume by + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + - const liveBuffer = yield* makeThreadLiveEventCoalescer(); + - yield* Effect.forkScoped(liveStream.pipe(Stream.runForEach(liveBuffer.offer))); + - const bufferedLiveStream = liveBuffer.stream; + +- let replayOnMissingSnapshot: typeof bufferedLiveStream | undefined; + - + - // When the client already loaded the snapshot over HTTP it passes + - // that snapshot's sequence, and we resume the live subscription by + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + - // catch-up followed by the buffered/ongoing live events. Overlapping + - // events are deduped by sequence on the client. + - // + -- // The replay is bounded to the projection head captured below. The + -- // catch-up range is normally tiny (a fresh HTTP snapshot sequence), + -- // but a stale cached cursor can sit hundreds of thousands of global + -- // events behind — replaying that decodes every intervening event + -- // (including every other thread's tool payloads) only to discard + -- // almost all of them, which has OOM-killed servers on large + -- // databases. A truncated replay would silently drop this thread's + -- // events, so past the gap cap we reset the client with a fresh + -- // thread snapshot instead, exactly like subscribeShell above. + +- // Measure only this thread's rows. Global sequence gaps can + +- // contain unrelated or pruned streams. Keep an explicit upper + +- // bound so events after the captured head stay in the live tail. + - if (input.afterSequence !== undefined) { + - const afterSequence = input.afterSequence; + - const headSequence = yield* orchestrationEngine.latestSequence; + -- const replayGap = headSequence - afterSequence; + +- const range = { + +- threadId: input.threadId, + +- fromSequenceExclusive: afterSequence, + +- toSequenceInclusive: headSequence, + +- }; + +- const replayStats = + +- afterSequence > headSequence + +- ? null + +- : yield* orchestrationEngine + +- .getThreadReplayStats({ + +- ...range, + +- maxEvents: THREAD_RESUME_MAX_EVENTS, + +- }) + +- .pipe( + +- Effect.mapError( + +- (cause) => + +- new OrchestrationGetSnapshotError({ + +- message: `Failed to measure thread ${input.threadId} replay range`, + +- cause, + +- }), + +- ), + +- ); + - if ( + -- yield* canReplayPersistedRange(afterSequence, headSequence, THREAD_RESUME_MAX_GAP) + +- replayStats !== null && + +- replayStats.eventCount <= THREAD_RESUME_MAX_EVENTS && + +- replayStats.payloadBytes <= ORCHESTRATION_REPLAY_PAYLOAD_BUDGET_BYTES + - ) { + - const catchUpStream = orchestrationEngine + -- .readEvents(afterSequence, replayGap) + +- .readThreadEvents({ ...range, limit: THREAD_RESUME_MAX_EVENTS }) + - .pipe( + - Stream.filter(isThisThreadDetailEvent), + - Stream.map((event) => ({ + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + - ); + - const afterCatchUp = + - input.requestCompletionMarker === true + -- ? Stream.concat( + -- Stream.fromEffect( + -- liveBuffer + -- .offerAndWait({ kind: "synchronized" as const }) + -- .pipe(Effect.andThen(liveBuffer.takeAll)), + -- ).pipe(Stream.flatMap((items) => Stream.fromIterable(items))), + -- bufferedLiveStream, + +- ? Stream.unwrap( + +- liveBuffer + +- .offer({ kind: "synchronized" as const }) + +- .pipe(Effect.as(bufferedLiveStream)), + - ) + - : bufferedLiveStream; + -- return Stream.concat(catchUpStream, afterCatchUp); + +- const replay = Stream.concat(catchUpStream, afterCatchUp); + +- if (!replayStats.hasCreateEvent) { + +- return replay; + +- } + +- replayOnMissingSnapshot = replay; + - } + -- // Gap too large (or cursor ahead of authoritative state): fall + -- // through to the snapshot path so the client converges from a + -- // fresh thread detail instead of an unbounded replay. + +- // A recreated thread needs a fresh snapshot if it still exists. + +- // Oversized replays and invalid cursors also use the snapshot path. + - } + - + - const snapshot = yield* projectionSnapshotQuery + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + - ); + - + - if (Option.isNone(snapshot)) { + +- // The recreated thread can already be deleted. Preserve the + +- // bounded replay and shell removal instead of retrying a + +- // snapshot that cannot exist. Oversized ranges still fail. + +- if (replayOnMissingSnapshot !== undefined) { + +- return replayOnMissingSnapshot; + +- } + - return yield* new OrchestrationGetSnapshotError({ + - message: `Thread ${input.threadId} was not found`, + - cause: input.threadId, + @@ apps/server/src/ws.ts: const makeWsRpcLayer = ( + - + - const afterSnapshot = + - input.requestCompletionMarker === true + -- ? Stream.concat( + -- Stream.fromEffect( + -- liveBuffer + -- .offerAndWait({ kind: "synchronized" as const }) + -- .pipe(Effect.andThen(liveBuffer.takeAll)), + -- ).pipe(Stream.flatMap((items) => Stream.fromIterable(items))), + -- bufferedLiveStream, + +- ? Stream.unwrap( + +- liveBuffer + +- .offer({ kind: "synchronized" as const }) + +- .pipe(Effect.as(bufferedLiveStream)), + - ) + - : bufferedLiveStream; + - return Stream.concat( + 55: c9dec101819 = 54: 78b451958a7 Split the V2 frontend plan into parity and enrichment phases + 56: b1c074b2ec3 ! 55: 65e85e1e2d4 Complete orchestration V2 frontend cutover + @@ apps/mobile/src/features/threads/PendingApprovalCard.tsx: import type { PendingA + ) => Promise; + } + + --const DEFAULT_APPROVAL_OPTIONS = [ + +-const DEFAULT_APPROVAL_OPTIONS: ReadonlyArray = [ + - { decision: "accept", label: "Allow once" }, + - { decision: "acceptForSession", label: "Allow session" }, + - { decision: "decline", label: "Decline" }, + --] satisfies ReadonlyArray; + +-]; + - + export function PendingApprovalCard(props: PendingApprovalCardProps) { + -- const options = props.approval.options ?? DEFAULT_APPROVAL_OPTIONS; + +- const options: ReadonlyArray = + +- props.approval.options ?? DEFAULT_APPROVAL_OPTIONS; + +- const warning = options.find((option) => option.warning)?.warning; + - // Opaque for the same reason as PendingUserInputCard: nothing blurs the feed + - // behind this card, so a translucent surface bleeds messages through it. + + const canRespond = props.approval.responseCapability === "live"; + @@ apps/mobile/src/features/threads/PendingApprovalCard.tsx: import type { PendingA + {props.approval.detail} + + ) : null} + +- {warning ? ( + +- + +- {warning} + + {!canRespond ? ( + + + + The provider process for this request is no longer available. Interrupt or restart the run + + to continue. + -+ + -+ ) : null} + + + + ) : null} + + - {options.map((option) => ( + - void; + + readonly answers: Record | null; + + readonly respondingUserInputId: RuntimeRequestId | null; + @@ apps/mobile/src/features/threads/PendingUserInputCard.tsx + + const cardCoverage = props.cardCoverage; + @@ apps/mobile/src/features/threads/PendingUserInputCard.tsx: export function PendingUserInputCard(props: PendingUserInputCardProps) { + + + + + + {question.options.map((option) => { + +- const optionValue = option.value ?? option.label.trim(); + +- const selected = isPendingUserInputOptionSelected(question, draft, optionValue); + ++ const selected = isPendingUserInputOptionSelected(draft, option.label); + + const description = + + option.description !== option.label ? option.description : undefined; + return ( + + @@ apps/mobile/src/features/threads/PendingUserInputCard.tsx: export function Pendi + + + ); + + })} + + + +- {question.allowCustomAnswer !== false ? ( + +- + +- props.onChangeCustomAnswer(props.pendingUserInput.requestId, question.id, value) + +- } + +- onFocus={() => props.onInputFocusChange?.(true)} + +- onBlur={() => props.onInputFocusChange?.(false)} + +- placeholder="Or type a custom answer" + +- className="min-h-[54px] rounded-2xl border border-adaptive-neutral-200-white-a8 bg-adaptive-white-neutral-950-a70 px-3.5 py-3 font-sans text-base text-adaptive-neutral-950-50" + +- /> + +- ) : null} + ++ + ++ props.onChangeCustomAnswer(props.pendingUserInput.requestId, question.id, value) + ++ } + ++ onFocus={() => props.onInputFocusChange?.(true)} + ++ onBlur={() => props.onInputFocusChange?.(false)} + ++ placeholder="Or type a custom answer" + ++ className="min-h-[54px] rounded-2xl border border-adaptive-neutral-200-white-a8 bg-adaptive-white-neutral-950-a70 px-3.5 py-3 font-sans text-base text-adaptive-neutral-950-50" + ++ /> + +======= + + {option.label} + + + @@ apps/mobile/src/features/threads/ThreadFeed.tsx + import { KeyboardAwareLegendList } from "@legendapp/list/keyboard"; + -import { useViewabilityAmount, type LegendListRef } from "@legendapp/list/react-native"; + -import type { + -- AssetResource, + - ChatAttachment, + - ChatFileAttachment, + - ChatImageAttachment, + @@ apps/mobile/src/features/threads/ThreadFeed.tsx + import { CHAT_LIST_ANCHOR_OFFSET, resolveChatListAnchoredEndSpace } from "@t3tools/shared/chatList"; + import { formatElapsed } from "@t3tools/shared/orchestrationTiming"; + import { SymbolView } from "../../components/AppSymbol"; + -@@ apps/mobile/src/features/threads/ThreadFeed.tsx: import { + - type ColorValue, + - useWindowDimensions, + - View, + -- type ViewStyle, + - } from "react-native"; + - import { FilePreviewModal, type FilePreviewSource } from "../../components/FilePreviewModal"; + - import { isPdfFile } from "../../lib/filePreview"; + @@ apps/mobile/src/features/threads/ThreadFeed.tsx: import Animated, { FadeIn, FadeInUp, type SharedValue } from "react-native-reani + import { useUniwindTheme } from "../../lib/useUniwindTheme"; + import { IOS_NAV_BAR_HEIGHT } from "../../lib/layoutMetrics"; + @@ apps/mobile/src/features/threads/ThreadFeed.tsx: function MessageAttachmentUnkno + - /> + - ); + -} + -- + --function ThreadMarkdownImageUnavailable(props: { readonly alt: string | null }) { + -- return ( + -- undefined} + -- /> + -- ); + --} + - + const MARKDOWN_MONO_FONT = Platform.select({ + ios: "ui-monospace", + @@ apps/mobile/src/lib/threadActivity.test.ts + -}); + - + -describe("pending approvals", () => { + +- it.each([{}, { requestType: "unknown" }])( + +- "exposes legacy OpenCode approvals without a known request kind: %j", + +- (legacyPayload) => { + +- const requested = makeActivity({ + +- id: EventId.make("approval-legacy"), + +- kind: "approval.requested", + +- summary: "Approval requested", + +- createdAt: "2026-08-24T00:00:00.000Z", + +- payload: { requestId: "per-legacy", detail: "*", ...legacyPayload }, + +- }); + +- + +- expect(derivePendingApprovals([requested])).toEqual([ + +- { + +- requestId: "per-legacy", + +- requestKind: "command", + +- createdAt: requested.createdAt, + +- detail: "*", + +- }, + +- ]); + +- }, + +- ); + +- + +- it.each(["tool_user_input", "auth_tokens_refresh"])( + +- "does not turn %s into an approval", + +- (requestType) => { + +- const activity = makeActivity({ + +- id: EventId.make("approval-non-approval"), + +- kind: "approval.requested", + +- summary: "Approval requested", + +- createdAt: "2026-08-24T00:00:00.000Z", + +- payload: { requestId: "not-an-approval", requestType }, + +- }); + +- + +- expect(derivePendingApprovals([activity])).toEqual([]); + +- }, + +- ); + +- + +- it.each(["approval.resolved", "provider.approval.respond.failed"])( + +- "removes legacy approvals after %s", + +- (kind) => { + +- const requested = makeActivity({ + +- id: EventId.make("approval-legacy-open"), + +- kind: "approval.requested", + +- summary: "Approval requested", + +- createdAt: "2026-08-24T00:00:00.000Z", + +- payload: { requestId: "per-legacy", requestType: "unknown" }, + +- }); + +- const resolved = makeActivity({ + +- id: EventId.make("approval-legacy-resolved"), + +- kind, + +- summary: "Approval resolved", + +- createdAt: "2026-08-24T00:00:01.000Z", + +- payload: { + +- requestId: "per-legacy", + +- detail: "Unknown pending permission request: per-legacy", + +- }, + +- }); + +- + +- expect(derivePendingApprovals([requested, resolved])).toEqual([]); + +- }, + +- ); + +- + - it("keeps app access approvals and persistence choices from remote environments", () => { + - const options = [ + - { decision: "decline", label: "Decline" }, + @@ apps/mobile/src/lib/threadActivity.test.ts + - startedAt: "2026-08-30T00:00:04.000Z", + - completedAt: null, + - assistantMessageId: null, + -+ const feed = buildThreadFeed(thread); + -+ const latestRun = { + -+ runId, + -+ status: "completed" as const, + -+ startedAt: "2026-06-20T00:00:01.000Z", + -+ completedAt: "2026-06-20T00:00:03.000Z", + - }; + - + +- }; + +- + - for (const currentTurn of [null, latestTurn]) { + -- const feed = buildThreadFeed({ ...thread, latestTurn: currentTurn }); + +- const currentThread = { ...thread, latestTurn: currentTurn }; + +- const feed = buildThreadFeed(currentThread); + - expect(feed).toMatchObject([ + - { + - type: "activity-group", + @@ apps/mobile/src/lib/threadActivity.test.ts + - ]); + - }, + - ); + -+ const collapsed = deriveThreadFeedPresentation(feed, latestRun, new Set()); + -+ expect(collapsed.map((entry) => entry.type)).toEqual(["message", "run-fold", "message"]); + - + +- + - it("keeps older local feedback before newer messages returned by the server", () => { + - const submission = { + - id: MessageId.make("feedback-command-ordering"), + @@ apps/mobile/src/lib/threadActivity.test.ts + - createdAt: "2026-08-23T00:00:02.000Z", + - updatedAt: "2026-08-23T00:00:02.000Z", + - streaming: false, + -- }; + ++ const feed = buildThreadFeed(thread); + ++ const latestRun = { + ++ runId, + ++ status: "completed" as const, + ++ startedAt: "2026-06-20T00:00:01.000Z", + ++ completedAt: "2026-06-20T00:00:03.000Z", + + }; + - const thread = makeThread({ + - id: ThreadId.make("thread-feedback-ordering"), + - projectId: ProjectId.make("project-1"), + - title: "Feedback ordering", + - messages: [laterMessage], + - }); + -- + + + - const feed = buildThreadFeed(thread, { + - localMessages: [ + - codexFeedbackMessage(submission), + @@ apps/mobile/src/lib/threadActivity.test.ts + - }), + - ], + - }); + -- + ++ const collapsed = deriveThreadFeedPresentation(feed, latestRun, new Set()); + ++ expect(collapsed.map((entry) => entry.type)).toEqual(["message", "run-fold", "message"]); + + + - const feed = buildThreadFeed(thread); + - expect(feed).toMatchObject([ + - { + @@ apps/mobile/src/lib/threadActivity.test.ts + + startedAt: "2026-06-20T00:00:01.000Z", + completedAt: null, + - assistantMessageId: null, + - }, + +- }, + - activities: [ + - makeActivity({ + - id: EventId.make("claude-mcp-completed"), + @@ apps/mobile/src/lib/threadActivity.test.ts + - summary: "Clicked in the preview browser", + - summaryToolIcon: "browser", + - live: true, + -- }, + + }, + - ]); + - }); + - + @@ apps/mobile/src/lib/threadActivity.test.ts + - label: "Worked for 17s", + - expanded: false, + - }); + -- + + + - const expanded = deriveThreadFeedPresentation(feed, thread.latestTurn, new Set([turnId])); + - expect(expanded.map((entry) => entry.id)).toEqual([ + - "assistant-first", + @@ apps/mobile/src/lib/threadActivity.test.ts + - "tool-completed", + - "assistant-final", + - ]); + +- + +- const interrupted = deriveThreadFeedPresentation( + +- feed, + +- { ...thread.latestTurn!, state: "interrupted", completedAt: "2026-04-01T00:00:20.000Z" }, + +- new Set(), + +- ); + +- expect(interrupted[1]).toMatchObject({ + +- type: "turn-fold", + +- label: "You stopped after 19s", + +- expanded: false, + +- }); + +- const retimed = deriveThreadFeedPresentation( + +- buildThreadFeed({ + +- ...thread, + +- messages: [ + +- thread.messages[0]!, + +- { ...thread.messages[1]!, updatedAt: "2026-04-01T00:00:25.000Z" }, + +- ], + +- }), + +- null, + +- new Set(), + ++ expect(presented.some((entry) => entry.type === "run-fold")).toBe(false); + ++ expect(presented.find((entry) => entry.type === "activity-group")?.activities[0]?.status).toBe( + ++ "failure", + + ); + +- expect(retimed[1]).toMatchObject({ type: "turn-fold", label: "Worked for 23s" }); + +- expect(collapsed[1]).toMatchObject({ type: "turn-fold", label: "Worked for 17s" }); + - }); + - + - it("folds assistant messages between the first and terminal messages", () => { + @@ apps/mobile/src/lib/threadActivity.test.ts + - }), + - ], + - }); + - + +- + - const feed = buildThreadFeed(thread); + - const collapsed = deriveThreadFeedPresentation(feed, thread.latestTurn, new Set()); + - expect(collapsed.find((entry) => entry.type === "turn-fold")).toMatchObject({ + @@ apps/mobile/src/lib/threadActivity.test.ts + - type: "activity-group", + - activities: [{ status: "failure" }], + - }); + -+ expect(presented.some((entry) => entry.type === "run-fold")).toBe(false); + -+ expect(presented.find((entry) => entry.type === "activity-group")?.activities[0]?.status).toBe( + -+ "failure", + -+ ); + }); + + it("appends active work as a normal timeline row", () => { + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + } + | { + - readonly type: "work-toggle"; + -- readonly id: string; + -- readonly createdAt: string; + ++ readonly type: "run-fold"; + + readonly id: string; + + readonly createdAt: string; + - readonly turnId: TurnId | null; + - readonly groupId: string; + - readonly hiddenCount: number; + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - } + - | { + - readonly type: "turn-fold"; + -+ readonly type: "run-fold"; + - readonly id: string; + - readonly createdAt: string; + +- readonly id: string; + +- readonly createdAt: string; + - readonly turnId: TurnId; + + readonly runId: RunId; + readonly label: string; + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - const taskDetailAsLabel = + - isTaskActivity && + - !taskSummary && + +- !title && + - typeof payload?.detail === "string" && + - payload.detail.length > 0 + - ? payload.detail + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - toolName: data?.toolName, + - data, + - }); + -- if (detail && !repeatsCommand) entry.detail = detail; + +- if (detail && detail !== title && !repeatsCommand) entry.detail = detail; + - } + - if (viewedImagePath) { + - entry.viewedImagePath = viewedImagePath; + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - Boolean(entry.detail?.trim()) || + - (entry.changedFiles?.some((path) => path.trim().length > 0) ?? false) + - ); + --} + -- + + } + + + -function memoizeValue(build: () => T): () => T { + - let value: T; + - let initialized = false; + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - } + - return value; + - }; + - } + - + +-} + +- + -function workEntryPreview( + - workEntry: Pick, + -): string | null { + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - return unquoted.length > 0 ? unquoted : trimmed; + - } + - return trimmed; + --} + -- + ++ : `${firstPath} +${(entry.changedFiles?.length ?? 1) - 1} more`; + + } + + + -function executableBasename(value: string): string | null { + - const trimmed = trimMatchingOuterQuotes(value); + - if (trimmed.length === 0) { + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - return null; + - } + - + +- const openingQuote = command[0]; + +- if ((openingQuote === "'" || openingQuote === '"') && !command.endsWith(openingQuote)) { + +- return null; + +- } + +- + - const unwrapped = trimMatchingOuterQuotes(command); + - return unwrapped.length > 0 ? unwrapped : null; + -} + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - return null; + - } + - return formatted === normalizedCommand ? null : formatted; + -+ : `${firstPath} +${(entry.changedFiles?.length ?? 1) - 1} more`; + - } + - + +-} + +- + -function extractToolCommand(payload: Record | null): { + - command: string | null; + - rawCommand: string | null; + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - return payload.itemType; + - } + - return undefined; + --} + -- + ++function byCreatedAt(left: A, right: A): number { + ++ return left.createdAt.localeCompare(right.createdAt); + + } + + + -function extractWorkLogRequestKind( + - payload: Record | null, + -): WorkLogEntry["requestKind"] | undefined { + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - return 2; + - } + - return 1; + -+function byCreatedAt(left: A, right: A): number { + -+ return left.createdAt.localeCompare(right.createdAt); + - } + - + +-} + +- + -const activityOrder = Order.combineAll([ + - Order.mapInput(Order.Number, (activity) => activity.sequence ?? Number.MAX_SAFE_INTEGER), + - Order.mapInput(Order.String, (activity) => activity.createdAt), + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + + function groupAdjacentActivities(entries: ReadonlyArray): ThreadFeedEntry[] { + const grouped: ThreadFeedEntry[] = []; + -- // Mutable backing array for the trailing group so appending an activity is + -- // O(1) instead of re-copying the group (which made this loop quadratic on + -- // long tool runs). The array is only mutated while it is the trailing group. + -- let openGroupActivities: ThreadFeedActivity[] | null = null; + -- let openGroupTurnId: TurnId | null = null; + +- let firstActivityEntry: Extract | null = null; + +- let openGroupActivities: ThreadFeedActivity[] = []; + +- const flushGroup = () => { + +- if (firstActivityEntry === null) return; + +- const cached = activityGroupsCache.get(firstActivityEntry.activity); + +- if ( + +- cached && + +- cached.activities.length === openGroupActivities.length && + +- cached.activities.every((activity, index) => activity === openGroupActivities[index]) + +- ) { + +- grouped.push(cached); + +- } else { + +- const group: ThreadFeedActivityGroup = { + +- type: "activity-group", + +- id: firstActivityEntry.id, + +- createdAt: firstActivityEntry.createdAt, + +- turnId: firstActivityEntry.turnId, + +- activities: openGroupActivities, + +- }; + +- activityGroupsCache.set(firstActivityEntry.activity, group); + +- grouped.push(group); + +- } + +- firstActivityEntry = null; + +- openGroupActivities = []; + +- }; + - + for (const entry of entries) { + - // Skip empty messages so they don't break activity grouping. + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - + + if (isEmptyMessage(entry)) continue; + if (entry.type !== "activity") { + + flushGroup(); + grouped.push(entry); + - openGroupActivities = null; + continue; + } + - + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + + }; + continue; + } + -- + -- openGroupActivities = [entry.activity]; + -- openGroupTurnId = entry.turnId; + - grouped.push({ + - type: "activity-group", + - id: entry.id, + - createdAt: entry.createdAt, + -- turnId: entry.turnId, + -- activities: openGroupActivities, + ++ grouped.push({ + ++ type: "activity-group", + ++ id: entry.id, + ++ createdAt: entry.createdAt, + + runId: entry.runId, + + activities: [entry.activity], + - }); + ++ }); + } + -- + +- flushGroup(); + return grouped; + } + + @@ apps/mobile/src/lib/threadActivity.ts: export type ThreadFeedEntry = + - entry.id !== firstAssistantMessageId && entry.id !== terminalAssistantMessageId, + - ) + - .map((entry) => entry.id), + +- ); + +- if (hiddenEntryIds.size === 0) { + +- continue; + +- } + +- // A lone compaction row stays visible on its own; it only folds away as + +- // part of a turn that already folds other work. + +- const hidesNonCompactionWork = entries.some( + +- (entry) => + +- hiddenEntryIds.has(entry.id) && + +- !(entry.type === "activity-group" && isContextCompactionActivityGroup(entry)), + + group.entries.filter((entry) => entry.id !== terminalAssistantId).map((entry) => entry.id), + ); + -- if (hiddenEntryIds.size === 0) { + +- if (!hidesNonCompactionWork) { + - continue; + - } + - + @@ apps/mobile/src/lib/threadActivity.ts: function deriveThreadFeedTurnFolds( + for (const entry of sourceFeed) { + const fold = foldsByAnchorId.get(entry.id); + if (fold) { + - result.push({ + -- type: "turn-fold", + -- id: `turn-fold:${fold.turnId}`, + +- const expanded = expandedTurnIds.has(fold.turnId); + +- let row = turnFoldRowsCache.get(entry); + +- if ( + +- !row || + +- row.turnId !== fold.turnId || + +- row.createdAt !== fold.createdAt || + +- row.label !== fold.label || + +- row.expanded !== expanded + +- ) { + +- row = { + +- type: "turn-fold", + +- id: `turn-fold:${fold.turnId}`, + +- createdAt: fold.createdAt, + +- turnId: fold.turnId, + +- label: fold.label, + +- expanded, + +- }; + +- turnFoldRowsCache.set(entry, row); + +- } + +- result.push(row); + +- } + +- if (!collapsedEntryIds.has(entry.id)) { + +- appendPresentedFeedEntry(result, entry, expandedWorkGroupIds); + ++ result.push({ + + type: "run-fold", + + id: `run-fold:${fold.runId}`, + - createdAt: fold.createdAt, + -- turnId: fold.turnId, + ++ createdAt: fold.createdAt, + + runId: fold.runId, + - label: fold.label, + -- expanded: expandedTurnIds.has(fold.turnId), + ++ label: fold.label, + + expanded: expandedRunIds.has(fold.runId), + - }); + ++ }); + } + -- if (!collapsedEntryIds.has(entry.id)) { + -- appendPresentedFeedEntry(result, entry, expandedWorkGroupIds); + -- } + + if (!collapsedEntryIds.has(entry.id)) result.push(entry); + } + if (activeWorkStartedAt !== null) { + @@ apps/mobile/src/lib/threadActivity.ts: export function deriveThreadFeedPresentat + - ? payload.options.filter(isProviderApprovalOption) + - : undefined; + - + -- if (activity.kind === "approval.requested" && requestId && requestKind) { + +- if ( + +- activity.kind === "approval.requested" && + +- requestId && + +- payload?.requestType !== "tool_user_input" && + +- payload?.requestType !== "auth_tokens_refresh" + +- ) { + - openByRequestId.set(requestId, { + - requestId, + -- requestKind, + +- // Older OpenCode requests can have no recognized approval kind. + +- requestKind: requestKind ?? "command", + - createdAt: activity.createdAt, + - ...(detail ? { detail } : {}), + - ...(appName ? { appName } : {}), + @@ apps/mobile/src/lib/threadActivity.ts: export function deriveThreadFeedPresentat + } + + export function buildThreadFeed( + -- thread: OrchestrationThread, + +- thread: Pick, + - options?: { + - readonly loadedMessages?: ReadonlyArray; + - readonly localMessages?: ReadonlyArray; + @@ apps/mobile/src/lib/threadActivity.ts: export function deriveThreadFeedPresentat + - : loadedMessages; + const oldestLoadedMessageCreatedAt = + - options?.loadedMessages !== undefined ? (loadedMessages[0]?.createdAt ?? null) : null; + -- const workLogEntries = deriveWorkLogEntries(thread.activities); + +- const activityEntries = getThreadFeedActivityEntries(thread.activities); + - const entries = Arr.sortWith( + - [ + - ...messages.map((message) => ({ + @@ apps/mobile/src/lib/threadActivity.ts: export function deriveThreadFeedPresentat + + ]; + + return groupAdjacentActivities(entries.toSorted(byCreatedAt)); + } + + + + function getThreadFeedActivityEntries(activities: ReadonlyArray) { + + ## apps/mobile/src/state/queries.ts ## + @@ + @@ apps/mobile/src/state/use-selected-thread-requests.ts: const userInputDraftsByRe + -function setUserInputDraftOption( + - requestKey: string, + - question: UserInputQuestion, + -- label: string, + +- value: string, + -): void { + +function setUserInputDraftOption(requestKey: string, questionId: string, label: string): void { + const current = appAtomRegistry.get(userInputDraftsByRequestKeyAtom); + @@ apps/mobile/src/state/use-selected-thread-requests.ts: const userInputDraftsByRe + - [question.id]: togglePendingUserInputOptionSelection( + - question, + - current[requestKey]?.[question.id], + -- label, + +- value, + - ), + + [questionId]: { + + selectedOptionLabel: label, + @@ apps/mobile/src/state/use-selected-thread-requests.ts: const userInputDraftsByRe + }, + }); + } + + + + function setUserInputDraftCustomAnswer( + + requestKey: string, + +- question: UserInputQuestion, + ++ questionId: string, + + customAnswer: string, + + ): void { + + const current = appAtomRegistry.get(userInputDraftsByRequestKeyAtom); + +@@ apps/mobile/src/state/use-selected-thread-requests.ts: function setUserInputDraftCustomAnswer( + + ...current, + + [requestKey]: { + + ...current[requestKey], + +- [question.id]: setPendingUserInputCustomAnswer( + +- question, + +- current[requestKey]?.[question.id], + ++ [questionId]: setPendingUserInputCustomAnswer( + ++ current[requestKey]?.[questionId], + + customAnswer, + + ), + + }, + @@ apps/mobile/src/state/use-selected-thread-requests.ts: export function useSelectedThreadRequests() { + const { selectedThread: selectedThreadShell } = useThreadSelection(); + const selectedThread = useSelectedThreadDetail(); + @@ apps/mobile/src/state/use-selected-thread-requests.ts: export function useSelect + : null; + + const onSelectUserInputOption = useCallback( + -- (requestId: ApprovalRequestId, question: UserInputQuestion, label: string) => { + +- (requestId: ApprovalRequestId, question: UserInputQuestion, value: string) => { + + (requestId: RuntimeRequestId, questionId: string, label: string) => { + if (!selectedThreadShell) { + return; + } + + const requestKey = scopedRequestKey(selectedThreadShell.environmentId, requestId); + -- setUserInputDraftOption(requestKey, question, label); + +- setUserInputDraftOption(requestKey, question, value); + + setUserInputDraftOption(requestKey, questionId, label); + }, + [selectedThreadShell], + @@ apps/mobile/src/state/use-selected-thread-requests.ts: export function useSelect + + const onChangeUserInputCustomAnswer = useCallback( + - (requestId: ApprovalRequestId, questionId: string, customAnswer: string) => { + +- const question = activePendingUserInputs + +- .find((request) => request.requestId === requestId) + +- ?.questions.find((entry) => entry.id === questionId); + +- if (!selectedThreadShell || !question) { + + (requestId: RuntimeRequestId, questionId: string, customAnswer: string) => { + - if (!selectedThreadShell) { + ++ if (!selectedThreadShell) { + return; + } + -@@ apps/mobile/src/state/use-selected-thread-requests.ts: export function useSelectedThreadRequests() { + + + + const requestKey = scopedRequestKey(selectedThreadShell.environmentId, requestId); + +- setUserInputDraftCustomAnswer(requestKey, question, customAnswer); + ++ setUserInputDraftCustomAnswer(requestKey, questionId, customAnswer); + + }, + +- [activePendingUserInputs, selectedThreadShell], + ++ [selectedThreadShell], + ); + + const onRespondToApproval = useCallback( + @@ apps/mobile/src/state/use-thread-composer-state.ts + + import { + CommandId, + +- DEFAULT_PROVIDER_INTERACTION_MODE, + + MessageId, + + PROVIDER_SEND_TURN_MAX_ATTACHMENTS, + + type EnvironmentId, + @@ apps/mobile/src/state/use-thread-composer-state.ts: import { + type ThreadId, + } from "@t3tools/contracts"; + @@ apps/mobile/src/state/use-thread-composer-state.ts: import { + import { deriveActiveWorkStartedAt } from "@t3tools/shared/orchestrationTiming"; + + import { makeQueuedMessageMetadata } from "../lib/commandMetadata"; + +-import { isModelSelectionUnavailable } from "../lib/modelOptions"; + +-import { resolveProviderInteractionMode } from "../features/threads/legacy-plan-mode"; + + import { + + convertPastedImagesToAttachments, + + pasteComposerClipboard, + @@ apps/mobile/src/state/use-thread-composer-state.ts: import { + } from "../lib/composerImages"; + import type { DraftComposerImageAttachment } from "../lib/composerImages"; + @@ apps/mobile/src/state/use-thread-composer-state.ts: import { + import { buildThreadFeed } from "../lib/threadActivity"; + import { appAtomRegistry } from "../state/atom-registry"; + import { + -@@ apps/mobile/src/state/use-thread-composer-state.ts: import { useSelectedThreadDetail } from "../state/use-thread-detail"; + +@@ apps/mobile/src/state/use-thread-composer-state.ts: import { setPendingConnectionError } from "../state/use-remote-environment-regis + + import { useSelectedThreadDetail } from "../state/use-thread-detail"; + import { useThreadSelection } from "../state/use-thread-selection"; + import { enqueueThreadOutboxMessage } from "./thread-outbox"; + - import { useThreadOutboxMessages } from "./use-thread-outbox"; + +-import { dispatchingQueuedMessageIdAtom, useThreadOutboxMessages } from "./use-thread-outbox"; + -import { threadEnvironment } from "./threads"; + -import { useAtomCommand } from "./use-atom-command"; + -import { + - composerAttachmentUploadBlockReason, + - composerAttachmentUploadsAtom, + -} from "./composer-attachment-uploads"; + ++import { useThreadOutboxMessages } from "./use-thread-outbox"; + + export function appendReviewCommentToDraft(input: { + readonly environmentId: EnvironmentId; + @@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadDra + const selectedThreadDetail = useSelectedThreadDetail(); + const composerDrafts = useAtomValue(composerDraftsAtom); + const queuedMessagesByThreadKey = useThreadOutboxMessages(); + +- const dispatchingQueuedMessageId = useAtomValue(dispatchingQueuedMessageIdAtom); + - const [feedbackSubmissionsByThreadKey, setFeedbackSubmissionsByThreadKey] = useState< + - Record> + - >({}); + @@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadCom + () => (selectedThreadKey ? (queuedMessagesByThreadKey[selectedThreadKey] ?? []) : []), + [queuedMessagesByThreadKey, selectedThreadKey], + ); + -- const selectedThreadFeed = useMemo(() => { + -- if (!selectedThreadDetail) { + -- return []; + -- } + +- const localFeedbackMessages = useMemo(() => { + - const submissions = selectedThreadKey + - ? (feedbackSubmissionsByThreadKey[selectedThreadKey] ?? []) + - : []; + -- return buildThreadFeed(selectedThreadDetail, { + -- localMessages: submissions.flatMap((submission) => + -- submission.status === "interrupted" + -- ? [] + -- : [codexFeedbackMessage(submission), codexFeedbackMessage(submission, "assistant")], + -- ), + -- }); + -- }, [feedbackSubmissionsByThreadKey, selectedThreadDetail, selectedThreadKey]); + -+ const selectedThreadFeed = useMemo( + +- return submissions.flatMap((submission) => + +- submission.status === "interrupted" + +- ? [] + +- : [codexFeedbackMessage(submission), codexFeedbackMessage(submission, "assistant")], + +- ); + +- }, [feedbackSubmissionsByThreadKey, selectedThreadKey]); + +- const selectedThreadMessages = selectedThreadDetail?.messages; + +- const selectedThreadActivities = selectedThreadDetail?.activities; + + const selectedThreadFeed = useMemo( + +- () => + +- selectedThreadMessages && selectedThreadActivities + +- ? buildThreadFeed( + +- { messages: selectedThreadMessages, activities: selectedThreadActivities }, + +- { localMessages: localFeedbackMessages }, + +- ) + +- : [], + +- [localFeedbackMessages, selectedThreadActivities, selectedThreadMessages], + + () => (selectedThreadDetail ? buildThreadFeed(selectedThreadDetail) : []), + + [selectedThreadDetail], + -+ ); + + ); + + const selectedDraft = selectedThreadKey ? composerDrafts[selectedThreadKey] : null; + - const draftMessage = selectedDraft?.text ?? ""; + @@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadComposerState() { + + const selectedThread = selectedThreadDetail ?? selectedThreadShell; + + const modelSelection = selectedDraft?.modelSelection ?? selectedThread?.modelSelection ?? null; + + const runtimeMode = selectedDraft?.runtimeMode ?? selectedThread?.runtimeMode ?? null; + +- const selectedProvider = selectedEnvironmentRuntime?.serverConfig?.providers.find( + +- (provider) => provider.instanceId === modelSelection?.instanceId, + +- ); + +- const interactionMode = selectedThread + +- ? resolveProviderInteractionMode( + +- selectedProvider, + +- selectedDraft?.interactionMode ?? selectedThread.interactionMode, + +- ) + +- : null; + ++ const interactionMode = selectedDraft?.interactionMode ?? selectedThread?.interactionMode ?? null; + + const selectedThreadSessionActivity = useMemo(() => { + const selectedThread = selectedThreadDetail ?? selectedThreadShell; + @@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadCom + }; + }, [selectedThreadDetail, selectedThreadShell]); + + +- const isCompacting = useMemo(() => { + +- const queuedMessage = selectedThreadQueuedMessages.findLast( + +- (message) => + +- message.messageId === dispatchingQueuedMessageId && + +- message.text.trim().toLowerCase() === "/compact" && + +- message.attachments.length === 0, + +- ); + +- const latestCompactMessage = selectedThreadDetail?.messages.findLast( + +- (message) => + +- message.role === "user" && + +- message.text.trim().toLowerCase() === "/compact" && + +- !message.attachments?.length, + +- ); + +- const compactRequestIsActive = + +- latestCompactMessage !== undefined && + +- (latestCompactMessage.createdAt > + +- (selectedThread?.latestTurn?.requestedAt ?? latestCompactMessage.createdAt) || + +- (selectedThread?.latestTurn?.state === "running" && + +- latestCompactMessage.createdAt === selectedThread.latestTurn.requestedAt)); + +- const compactionSettled = selectedThreadDetail?.activities.some((activity) => { + +- if (!["context-compaction", "provider.turn.start.failed"].includes(activity.kind)) + +- return false; + +- const payload = + +- typeof activity.payload === "object" && activity.payload !== null + +- ? (activity.payload as { readonly requestId?: unknown }) + +- : null; + +- return payload?.requestId === latestCompactMessage?.id; + +- }); + +- return ( + +- queuedMessage !== undefined || + +- ((selectedThread?.session?.status === "starting" || + +- selectedThread?.session?.status === "running") && + +- compactRequestIsActive && + +- !compactionSettled) + +- ); + +- }, [ + +- dispatchingQueuedMessageId, + +- selectedThread, + +- selectedThreadDetail, + +- selectedThreadQueuedMessages, + +- ]); + +- + + const activeWorkStartedAt = useMemo(() => { + + const selectedThread = selectedThreadDetail ?? selectedThreadShell; + + if (!selectedThread) { + @@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadComposerState() { + } + + @@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadCom + return null; + } + + -- const provider = selectedEnvironmentRuntime?.serverConfig?.providers.find( + -- (entry) => entry.instanceId === thread.modelSelection.instanceId, + +- const modelSelection = draft.modelSelection ?? thread.modelSelection; + +- const serverConfig = selectedEnvironmentRuntime?.serverConfig; + +- if ( + +- selectedEnvironmentRuntime?.connectionState === "connected" && + +- isModelSelectionUnavailable(serverConfig, modelSelection) + +- ) { + +- Alert.alert( + +- "Antigravity model unavailable", + +- "Set up Antigravity on web or desktop, or choose another model.", + +- ); + +- return null; + +- } + +- const provider = serverConfig?.providers.find( + +- (entry) => entry.instanceId === modelSelection.instanceId, + - ); + - const feedbackCommand = + - attachments.length === 0 && + @@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadCom + const metadata = makeQueuedMessageMetadata(); + const messageId = MessageId.make(metadata.messageId); + // Enqueue publishes the queued atom synchronously (the durable write + +@@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadComposerState() { + + commandId: CommandId.make(metadata.commandId), + + text, + + attachments, + +- modelSelection, + ++ modelSelection: draft.modelSelection ?? thread.modelSelection, + + runtimeMode: draft.runtimeMode ?? thread.runtimeMode, + +- interactionMode: resolveProviderInteractionMode( + +- provider, + +- draft.interactionMode ?? thread.interactionMode, + +- ), + ++ interactionMode: draft.interactionMode ?? thread.interactionMode, + + createdAt: metadata.createdAt, + + }); + + clearComposerDraftContent(threadKey, { deferAttachmentCleanup: true }); + @@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadComposerState() { + }, + ); + @@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadCom + const onChangeDraftMessage = useCallback( + (value: string) => { + @@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadComposerState() { + + if (!selectedThreadKey) { + + return; + + } + +- const provider = selectedEnvironmentRuntime?.serverConfig?.providers.find( + +- (candidate) => candidate.instanceId === value.instanceId, + +- ); + +- updateComposerDraftSettings(selectedThreadKey, { + +- modelSelection: value, + +- ...(provider?.showInteractionModeToggle === false + +- ? { interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE } + +- : {}), + +- }); + ++ updateComposerDraftSettings(selectedThreadKey, { modelSelection: value }); + + }, + +- [selectedEnvironmentRuntime?.serverConfig, selectedThreadKey], + ++ [selectedThreadKey], + + ); + + + + const onUpdateRuntimeMode = useCallback( + +@@ apps/mobile/src/state/use-thread-composer-state.ts: export function useThreadComposerState() { + + if (!selectedThreadKey) { + + return; + + } + +- const modelSelection = + +- getComposerDraftSnapshot(selectedThreadKey).modelSelection ?? + +- selectedThread?.modelSelection; + +- const provider = selectedEnvironmentRuntime?.serverConfig?.providers.find( + +- (candidate) => candidate.instanceId === modelSelection?.instanceId, + +- ); + +- updateComposerDraftSettings(selectedThreadKey, { + +- interactionMode: resolveProviderInteractionMode(provider, value), + +- }); + ++ updateComposerDraftSettings(selectedThreadKey, { interactionMode: value }); + + }, + +- [selectedEnvironmentRuntime?.serverConfig, selectedThread?.modelSelection, selectedThreadKey], + ++ [selectedThreadKey], + + ); + + + + return { + + selectedThreadFeed, + + selectedThreadQueueCount, + + activeWorkStartedAt, + +- isCompacting, + + draftMessage, + + draftAttachments, + modelSelection, + runtimeMode, + interactionMode, + @@ apps/mobile/src/state/use-thread-outbox-drain.ts: export function useThreadOutbo + - threadBusy: thread?.session?.status === "running" || thread?.session?.status === "starting", + + threadBusy: threadRuntimeIsActive(thread?.runtime), + }); + - // The delivery action resolves first; the file-capability gate applies + - // only to a message that will send. Gating earlier would restore a + + // The delivery action resolves first; capability checks apply only to + + // a message that will send. Checking earlier would restore a + + ## apps/mobile/src/test-fixtures.ts (new) ## + @@ + @@ apps/web/src/components/BranchToolbarBranchSelector.tsx: export function BranchT + ## apps/web/src/components/ChatView.logic.test.ts ## + @@ + -import { + +- ANTIGRAVITY_DEFAULT_MODEL, + +- CheckpointRef, + - EnvironmentId, + - MessageId, + - ProjectId, + +- ProviderDriverKind, + - ProviderInstanceId, + +- type ServerProvider, + - ThreadId, + - TurnId, + -} from "@t3tools/contracts"; + -import { afterEach, beforeEach, describe, expect, it, vi } from "vite-plus/test"; + - + --import type { Thread, ThreadShell } from "../types"; + +-import type { Thread, ThreadShell, TurnDiffSummary } from "../types"; + +-import type { TimelineEntry } from "../session-logic"; + +-import { deriveProviderInstanceEntries, NO_PROVIDER_MODEL_SELECTION } from "../providerInstances"; + -import type { CodexArtifactTemplate } from "@t3tools/client-runtime/codex-artifact-templates"; + +-import type { RightPanelSurface } from "../rightPanelStore"; + +import { EnvironmentId, ProjectId, ProviderInstanceId, ThreadId, RunId } from "@t3tools/contracts"; + +import { describe, expect, it } from "vite-plus/test"; + + + @@ apps/web/src/components/ChatView.logic.test.ts + import { + MAX_HIDDEN_MOUNTED_PREVIEW_THREADS, + MAX_HIDDEN_MOUNTED_TERMINAL_THREADS, + +- agentControlledBrowserCloseConfirmation, + + branchMismatchKey, + + buildExpiredTerminalContextToastCopy, + + buildLoadingThreadFromShell, + +- buildRevertTurnCountByUserMessageId, + + buildThreadTurnInterruptInput, + + createLocalDispatchSnapshot, + + deriveComposerSendState, + + dismissBranchMismatchForSession, + + ENVIRONMENT_RECONNECT_WARNING_GRACE_MS, + +- getAntigravitySendBlockReason, + + getStartedThreadModelChangeBlockReason, + ++ isVideoPreviewRequestCurrent, + + hasEnvironmentReconnectWarningGraceElapsed, + + hasServerAcknowledgedLocalDispatch, + + isBranchMismatchDismissedForSession, + + reconcileMountedTerminalThreadIds, + + reconcileRetainedMountedThreadIds, + + resolveBackgroundDraftWorkspaceOptions, + +- resolveComposerInteractionMode, + +- resolveComposerProviderSelection, + + resolveDraftPromotionNavigationTarget, + + resolveThreadMetadataUpdateForNextTurn, + + resolveSendEnvMode, + +@@ apps/web/src/components/ChatView.logic.test.ts: import { + + codexArtifactTemplatePromptToAppend, + + shouldDockDraftHeroForSubmission, + + shouldReleaseTimelineAnchorForToolActivity, + +- shouldOpenProactivePullRequest, + +- shouldOpenProactiveTurnDiff, + +- shouldRenderPreviewMiniPlayer, + + shouldShowBranchMismatchBanner, + + shouldShowPlanFollowUpPrompt, + + shouldWriteThreadErrorToCurrentServerThread, + + toolGroupConsumesUpwardNavigation, + + } from "./ChatView.logic"; + + + +-describe("agent browser close confirmation", () => { + +- const surfaces = [ + +- { id: "browser:one", kind: "preview", resourceId: "tab-1" }, + +- { id: "browser:two", kind: "preview", resourceId: "tab-2" }, + +- { id: "diff", kind: "diff" }, + +- ] satisfies RightPanelSurface[]; + +- + +- it("only warns for browsers under active agent control", () => { + +- expect( + +- agentControlledBrowserCloseConfirmation(surfaces, { + +- "tab-1": { controller: "none" }, + +- "tab-2": { controller: "human" }, + +- }), + +- ).toBeNull(); + +- + +- expect( + +- agentControlledBrowserCloseConfirmation([surfaces[0]!], { + +- "tab-1": { controller: "agent" }, + +- }), + +- ).toBe( + +- [ + +- "Close browser while the agent is using it?", + +- "The agent is actively controlling this browser. Closing it may interrupt the current browser action.", + +- ].join("\n"), + +- ); + +- }); + +- + +- it("counts every agent-controlled browser in a bulk close", () => { + +- expect( + +- agentControlledBrowserCloseConfirmation(surfaces, { + +- "tab-1": { controller: "agent" }, + +- "tab-2": { controller: "agent" }, + +- }), + +- ).toContain("Close 2 browsers"); + +- }); + +-}); + +- + +-describe("floating browser preview", () => { + +- it("only hides the duplicate while the same browser is rendered in the panel", () => { + +- expect(shouldRenderPreviewMiniPlayer(null, null)).toBe(false); + +- expect( + +- shouldRenderPreviewMiniPlayer("tab-1", { + +- id: "browser:one", + +- kind: "preview", + +- resourceId: "tab-1", + +- }), + +- ).toBe(false); + +- expect( + +- shouldRenderPreviewMiniPlayer("tab-1", { + +- id: "browser:two", + +- kind: "preview", + +- resourceId: "tab-2", + +- }), + +- ).toBe(true); + +- expect(shouldRenderPreviewMiniPlayer("tab-1", { id: "diff", kind: "diff" })).toBe(true); + +- }); + +-}); + +- + +-describe("proactive panels", () => { + +- it("opens a pull request only after a newly observed link appears", () => { + +- expect(shouldOpenProactivePullRequest(undefined, "project:repo:42")).toBe(false); + +- expect(shouldOpenProactivePullRequest(null, "project:repo:42")).toBe(true); + +- expect(shouldOpenProactivePullRequest("project:repo:42", "project:repo:42")).toBe(false); + +- expect(shouldOpenProactivePullRequest("project:repo:42", null)).toBe(false); + +- }); + +- + +- it("opens the diff only when the observed running turn settles", () => { + +- const turnId = TurnId.make("turn-1"); + +- expect( + +- shouldOpenProactiveTurnDiff({ + +- previousRunningTurnId: undefined, + +- runningTurnId: null, + +- settledTurnId: turnId, + +- turnCompleted: true, + +- }), + +- ).toBe(false); + +- expect( + +- shouldOpenProactiveTurnDiff({ + +- previousRunningTurnId: turnId, + +- runningTurnId: null, + +- settledTurnId: turnId, + +- turnCompleted: true, + +- }), + +- ).toBe(true); + +- expect( + +- shouldOpenProactiveTurnDiff({ + +- previousRunningTurnId: turnId, + +- runningTurnId: TurnId.make("turn-2"), + +- settledTurnId: turnId, + +- turnCompleted: true, + +- }), + +- ).toBe(false); + +- expect( + +- shouldOpenProactiveTurnDiff({ + +- previousRunningTurnId: turnId, + +- runningTurnId: null, + +- settledTurnId: turnId, + +- turnCompleted: false, + +- }), + +- ).toBe(false); + ++describe("isVideoPreviewRequestCurrent", () => { + ++ it("rejects changed threads and replaced previews", () => { + ++ expect(isVideoPreviewRequestCurrent("thread-1", "thread-2", 1, 1)).toBe(false); + ++ expect(isVideoPreviewRequestCurrent("thread-1", "thread-1", 1, 2)).toBe(false); + ++ expect(isVideoPreviewRequestCurrent("thread-1", "thread-1", 2, 2)).toBe(true); + + }); + + }); + + + @@ apps/web/src/components/ChatView.logic.test.ts: describe("environment reconnect warning grace", () => { + }); + + @@ apps/web/src/components/ChatView.logic.test.ts: const completedTurn = { + lastError: null, + updatedAt: "2026-03-29T00:00:10.000Z", + }; + +@@ apps/web/src/components/ChatView.logic.test.ts: describe("buildThreadTurnInterruptInput", () => { + + }); + + }); + + + +-describe("resolveComposerProviderSelection", () => { + +- const catalogModels: ServerProvider["models"] = [ + +- { slug: "gemini-pro", name: "Gemini Pro", isCustom: false, capabilities: null }, + +- ]; + +- + +- function entry(driver: string, instanceId = driver, overrides: Partial = {}) { + +- return deriveProviderInstanceEntries([ + +- { + +- driver: ProviderDriverKind.make(driver), + +- instanceId: ProviderInstanceId.make(instanceId), + +- enabled: true, + +- installed: true, + +- status: "ready", + +- auth: { status: "authenticated" }, + +- version: null, + +- checkedAt: now, + +- models: [], + +- slashCommands: [], + +- skills: [], + +- ...overrides, + +- }, + +- ])[0]!; + +- } + +- + +- it("uses the custom instance's capability instead of the default instance", () => { + +- const defaultEntry = entry("antigravity", "antigravity", { + +- showInteractionModeToggle: true, + +- }); + +- const customEntry = entry("antigravity", "google_work", { + +- showInteractionModeToggle: false, + +- }); + +- const selection = resolveComposerProviderSelection({ + +- entries: [defaultEntry, customEntry], + +- candidateInstanceIds: [customEntry.instanceId], + +- lockedProvider: null, + +- lockedInstanceId: null, + +- }); + +- + +- expect(selection.selectedProviderEntry?.instanceId).toBe(customEntry.instanceId); + +- expect( + +- resolveComposerInteractionMode({ + +- provider: selection.selectedProviderEntry?.snapshot, + +- planModeEnabled: true, + +- interactionMode: "plan", + +- }), + +- ).toEqual({ enabled: false, interactionMode: "default" }); + +- }); + +- + +- it("uses the fallback provider's plan capability after the draft's instance is disabled", () => { + +- const disabledEntry = entry("antigravity", "antigravity", { + +- enabled: false, + +- showInteractionModeToggle: false, + +- }); + +- const fallbackEntry = entry("codex"); + +- const selection = resolveComposerProviderSelection({ + +- entries: [disabledEntry, fallbackEntry], + +- candidateInstanceIds: [disabledEntry.instanceId], + +- lockedProvider: null, + +- lockedInstanceId: null, + +- }); + +- + +- expect(selection.selectedProviderEntry?.instanceId).toBe(fallbackEntry.instanceId); + +- expect( + +- resolveComposerInteractionMode({ + +- provider: selection.selectedProviderEntry?.snapshot, + +- planModeEnabled: true, + +- interactionMode: "plan", + +- }), + +- ).toEqual({ enabled: true, interactionMode: "plan" }); + +- }); + +- + +- it("keeps a signed-out selection instead of silently switching providers", () => { + +- const signedOutEntry = entry("antigravity", "google_work", { + +- status: "error", + +- auth: { status: "unauthenticated" }, + +- models: catalogModels, + +- }); + +- const selection = resolveComposerProviderSelection({ + +- entries: [entry("codex"), signedOutEntry], + +- candidateInstanceIds: [signedOutEntry.instanceId], + +- lockedProvider: null, + +- lockedInstanceId: null, + +- }); + +- + +- expect(selection.selectedProviderEntry?.instanceId).toBe(signedOutEntry.instanceId); + +- expect( + +- getAntigravitySendBlockReason(selection.selectedProviderEntry?.snapshot, "gemini-pro"), + +- ).toBe("Sign in to Antigravity in provider settings before sending."); + +- }); + +- + +- it("blocks sends until the selected Antigravity profile is installed", () => { + +- const provider = entry("antigravity", "google_work", { + +- installed: false, + +- models: catalogModels, + +- }).snapshot; + +- + +- expect(getAntigravitySendBlockReason(provider, "gemini-pro")).toBe( + +- "Install Antigravity in provider settings before sending.", + +- ); + +- }); + +- + +- it("lets Antigravity check saved credentials when resuming after a restart", () => { + +- const provider = entry("antigravity", "google_work", { + +- status: "warning", + +- auth: { status: "unknown" }, + +- models: [], + +- }).snapshot; + +- + +- expect(getAntigravitySendBlockReason(provider, "gemini-pro")).toBeNull(); + +- expect(getAntigravitySendBlockReason(provider, ANTIGRAVITY_DEFAULT_MODEL)).toBeNull(); + +- expect( + +- getAntigravitySendBlockReason({ ...provider, models: catalogModels }, "gemini-pro"), + +- ).toBeNull(); + +- expect(getAntigravitySendBlockReason(provider, "")).toBe( + +- "Choose an Antigravity model before sending.", + +- ); + +- }); + +- + +- it("blocks saved model sends until Antigravity loads its account catalog", () => { + +- expect(getAntigravitySendBlockReason(entry("antigravity").snapshot, "gemini-pro")).toBe( + +- "Refresh Antigravity models in provider settings before sending.", + +- ); + +- }); + +- + +- it("blocks an empty Antigravity selection after the catalog has loaded", () => { + +- const provider = entry("antigravity", "google_work", { models: catalogModels }).snapshot; + +- + +- expect(getAntigravitySendBlockReason(provider, "")).toBe( + +- "Choose an Antigravity model before sending.", + +- ); + +- }); + +- + +- it("blocks a saved model that a ready catalog no longer lists", () => { + +- const provider = entry("antigravity", "google_work", { + +- status: "ready", + +- models: catalogModels, + +- }).snapshot; + +- + +- expect(getAntigravitySendBlockReason(provider, "saved-model-not-in-current-catalog")).toBe( + +- "That Antigravity model is no longer available. Choose another model.", + +- ); + +- expect(getAntigravitySendBlockReason(provider, "gemini-pro")).toBeNull(); + +- }); + +- + +- it("allows a saved native model to retry after a provider error without changing it", () => { + +- const provider = entry("antigravity", "google_work", { + +- status: "error", + +- models: catalogModels, + +- }).snapshot; + +- + +- expect( + +- getAntigravitySendBlockReason(provider, "saved-model-not-in-current-catalog"), + +- ).toBeNull(); + +- }); + +- + +- it("keeps existing send behavior for other providers", () => { + +- const provider = entry("codex", "codex", { + +- installed: false, + +- auth: { status: "unknown" }, + +- models: [], + +- }).snapshot; + +- + +- expect(getAntigravitySendBlockReason(provider, "gpt-model")).toBeNull(); + +- }); + +- + +- it("does not continue an existing Antigravity thread in another profile after deletion", () => { + +- const missingInstanceId = ProviderInstanceId.make("google_work"); + +- const selection = resolveComposerProviderSelection({ + +- entries: [entry("antigravity")], + +- candidateInstanceIds: [missingInstanceId], + +- lockedProvider: ProviderDriverKind.make("antigravity"), + +- lockedInstanceId: missingInstanceId, + +- }); + +- + +- expect(selection.selectedProviderEntry).toBeUndefined(); + +- expect(selection.unavailableProviderInstanceId).toBe(missingInstanceId); + +- }); + +- + +- it("does not treat the empty draft placeholder as a provider setup target", () => { + +- const selection = resolveComposerProviderSelection({ + +- entries: [entry("antigravity", "antigravity", { enabled: false })], + +- candidateInstanceIds: [NO_PROVIDER_MODEL_SELECTION.instanceId], + +- lockedProvider: null, + +- lockedInstanceId: null, + +- }); + +- + +- expect(selection.selectedProviderEntry).toBeUndefined(); + +- expect(selection.unavailableProviderInstanceId).toBeUndefined(); + +- }); + +- + +- it("keeps the session's continuation group when another instance was selected", () => { + +- const sessionEntry = entry("antigravity", "google_work", { + +- enabled: false, + +- continuation: { groupKey: "work-profile" }, + +- }); + +- const anotherEntry = entry("antigravity", "google_personal", { + +- continuation: { groupKey: "personal-profile" }, + +- }); + +- const selection = resolveComposerProviderSelection({ + +- entries: [sessionEntry, anotherEntry], + +- candidateInstanceIds: [anotherEntry.instanceId, sessionEntry.instanceId], + +- lockedProvider: ProviderDriverKind.make("antigravity"), + +- lockedInstanceId: sessionEntry.instanceId, + +- }); + +- + +- expect(selection.selectedProviderEntry).toBeUndefined(); + +- }); + +-}); + +- + +-describe("resolveComposerInteractionMode", () => { + +- it("resets a restored plan draft when the selected instance does not support plan mode", () => { + +- expect( + +- resolveComposerInteractionMode({ + +- planModeEnabled: true, + +- provider: { showInteractionModeToggle: false }, + +- interactionMode: "plan", + +- }), + +- ).toEqual({ enabled: false, interactionMode: "default" }); + +- }); + +- + +- it("keeps legacy plan behavior for providers that omit the capability", () => { + +- expect( + +- resolveComposerInteractionMode({ + +- planModeEnabled: true, + +- provider: {}, + +- interactionMode: "plan", + +- }), + +- ).toEqual({ enabled: true, interactionMode: "plan" }); + +- }); + +- + +- it("resets a restored plan draft when the beta setting is off", () => { + +- expect( + +- resolveComposerInteractionMode({ + +- planModeEnabled: false, + +- provider: { showInteractionModeToggle: true }, + +- interactionMode: "plan", + +- }), + +- ).toEqual({ enabled: false, interactionMode: "default" }); + +- }); + +- + +- it("disables plan mode until the selected provider is available", () => { + +- expect( + +- resolveComposerInteractionMode({ + +- planModeEnabled: true, + +- provider: null, + +- interactionMode: "plan", + +- }), + +- ).toEqual({ enabled: false, interactionMode: "default" }); + +- }); + +-}); + +- + +-describe("buildRevertTurnCountByUserMessageId", () => { + +- const userMessageId = MessageId.make("rewind-user-message"); + +- const assistantMessageId = MessageId.make("rewind-assistant-message"); + +- const turnId = TurnId.make("rewind-turn"); + +- const timelineEntries = [ + +- { + +- id: userMessageId, + +- kind: "message", + +- createdAt: now, + +- message: { + +- id: userMessageId, + +- role: "user", + +- text: "Update the file", + +- turnId, + +- createdAt: now, + +- updatedAt: now, + +- streaming: false, + +- }, + +- }, + +- { + +- id: assistantMessageId, + +- kind: "message", + +- createdAt: now, + +- message: { + +- id: assistantMessageId, + +- role: "assistant", + +- text: "Updated the file", + +- turnId, + +- createdAt: now, + +- updatedAt: now, + +- streaming: false, + +- }, + +- }, + +- ] satisfies ReadonlyArray; + +- const turnDiffSummaryByAssistantMessageId = new Map([ + +- [ + +- assistantMessageId, + +- { + +- turnId, + +- checkpointTurnCount: 1, + +- checkpointRef: CheckpointRef.make("refs/t3/checkpoints/rewind-turn"), + +- status: "ready", + +- files: [], + +- assistantMessageId, + +- completedAt: now, + +- }, + +- ], + +- ]); + +- + +- it("offers the checkpoint before the user message when conversation rollback is supported", () => { + +- expect( + +- buildRevertTurnCountByUserMessageId({ + +- supportsConversationRollback: true, + +- timelineEntries, + +- turnDiffSummaryByAssistantMessageId, + +- inferredCheckpointTurnCountByTurnId: {}, + +- }), + +- ).toEqual(new Map([[userMessageId, 0]])); + +- }); + +- + +- it("offers no rewind action when file checkpoints exist but conversation rollback is unsupported", () => { + +- expect( + +- buildRevertTurnCountByUserMessageId({ + +- supportsConversationRollback: false, + +- timelineEntries, + +- turnDiffSummaryByAssistantMessageId, + +- inferredCheckpointTurnCountByTurnId: {}, + +- }).size, + +- ).toBe(0); + +- }); + +-}); + +- + + describe("deriveComposerSendState", () => { + + it("treats expired terminal pills as non-sendable content", () => { + + const state = deriveComposerSendState({ + @@ apps/web/src/components/ChatView.logic.test.ts: describe("startNewThreadForProject", () => { + describe("hasServerAcknowledgedLocalDispatch", () => { + it("does not acknowledge unchanged server state", () => { + @@ apps/web/src/components/ChatView.logic.test.ts: describe("hasServerAcknowledgedL + hasPendingApproval: false, + hasPendingUserInput: false, + threadError: null, + +@@ apps/web/src/components/ChatView.logic.test.ts: describe("hasServerAcknowledgedLocalDispatch", () => { + + + + expect(hasServerAcknowledgedLocalDispatch({ ...common, hasPendingApproval: true })).toBe(true); + + expect(hasServerAcknowledgedLocalDispatch({ ...common, hasPendingUserInput: true })).toBe(true); + +- expect( + +- hasServerAcknowledgedLocalDispatch({ + +- ...common, + +- latestTurnStartFailureId: "turn-start-failure-1", + +- }), + +- ).toBe(true); + + expect(hasServerAcknowledgedLocalDispatch({ ...common, threadError: "failed" })).toBe(true); + + }); + +- + +- it("acknowledges only a new turn-start failure", () => { + +- const localDispatch = { + +- ...createLocalDispatchSnapshot(makeThread()), + +- latestTurnStartFailureId: "turn-start-failure-old", + +- }; + +- const common = { + +- localDispatch, + +- phase: "ready" as const, + +- latestTurn: null, + +- latestUserMessageId: localDispatch.latestUserMessageId, + +- session: null, + +- hasPendingApproval: false, + +- hasPendingUserInput: false, + +- threadError: null, + +- }; + +- + +- expect( + +- hasServerAcknowledgedLocalDispatch({ + +- ...common, + +- latestTurnStartFailureId: "turn-start-failure-old", + +- }), + +- ).toBe(false); + +- expect( + +- hasServerAcknowledgedLocalDispatch({ + +- ...common, + +- latestTurnStartFailureId: "turn-start-failure-new", + +- }), + +- ).toBe(true); + +- }); + + }); + + ## apps/web/src/components/ChatView.logic.ts ## + @@ apps/web/src/components/ChatView.logic.ts: import { + @@ apps/web/src/components/ChatView.tsx: import { + } from "../composer-logic"; + import { + @@ apps/web/src/components/ChatView.tsx: import { + + derivePendingApprovals, + derivePendingUserInputs, + derivePhase, + - deriveTimelineEntries, + +- deriveTimelineEntriesWithState, + ++ deriveTimelineEntries, + + deriveTimelineEntriesFromVisibleTurnItems, + deriveActiveWorkStartedAt, + deriveActivePlanState, + @@ apps/web/src/components/ChatView.tsx: import { + deriveWorkLogEntries, + hasActionableProposedPlan, + - isLatestTurnSettled, + +- type TimelineEntriesProjection, + + isLatestRunSettled, + } from "../session-logic"; + import { type LegendListRef } from "@legendapp/list/react"; + @@ apps/web/src/components/ChatView.tsx: function chatActionErrorMessage(error: unk + return error instanceof Error ? error.message : "An error occurred."; + } + + +-const ENVIRONMENT_UNAVAILABLE_SEND_TOAST_TRAIL_SIZE = 3; + +- + -/** + - * Drops the send-time anchored end space. That space is what holds a sent + - * message near the top while its turn streams, and it keeps LegendList's + @@ apps/web/src/components/ChatView.tsx: function chatActionErrorMessage(error: unk + - return current.messageId === null ? current : { ...current, messageId: null }; + -} + - + - function ChatViewContent(props: ChatViewProps) { + +-export default function ChatView(props: ChatViewProps) { + ++function ChatViewContent(props: ChatViewProps) { + const { + environmentId, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + + threadId, + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const threadSyncPhase = routeKind === "server" ? (props.threadSyncPhase ?? null) : null; + const threadDetailLoading = threadSyncPhase === "loading"; + const handleNewThread = useNewThreadHandler(); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const routeThreadRef = useMemo( + () => scopeThreadRef(environmentId, threadId), + [environmentId, threadId], + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + reportFailure: false, + }); + const startThreadTurn = useAtomCommand(threadEnvironment.startTurn, { reportFailure: false }); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const interruptThreadTurn = useAtomCommand(threadEnvironment.interruptTurn, { + reportFailure: false, + }); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + ); + const composerDraftTarget: ScopedThreadRef | DraftId = + routeKind === "server" ? routeThreadRef : props.draftId; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + ); + const loadEarlierTurns = useMemo(() => { + if (routeKind !== "server" || !threadHasOlderTurns(routeThreadState)) { + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const composerActiveProvider = useComposerDraftStore( + (store) => store.getComposerDraft(composerDraftTarget)?.activeProvider ?? null, + ); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const setComposerDraftPrompt = useComposerDraftStore((store) => store.setPrompt); + const addComposerDraftImages = useComposerDraftStore((store) => store.addImages); + const addComposerDraftFiles = useComposerDraftStore((store) => store.addFiles); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const composerElementContextsRef = useRef([]); + const localComposerRef = useRef(null); + const composerRef = useComposerHandleContext() ?? localComposerRef; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const [showScrollToBottom, setShowScrollToBottom] = useState(false); + const [expandedImage, setExpandedImage] = useState(null); + useEffect(() => { + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + return () => revokeBlobPreviewUrl(item.src); + }, [expandedImage]); + const [optimisticUserMessages, setOptimisticUserMessages] = useState([]); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const optimisticUserMessagesRef = useRef(optimisticUserMessages); + optimisticUserMessagesRef.current = optimisticUserMessages; + const [localDraftErrorsByDraftId, setLocalDraftErrorsByDraftId] = useState< + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const [maximizedRightPanelThreadKey, setMaximizedRightPanelThreadKey] = useState( + null, + ); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const [pendingUserInputAnswersByRequestId, setPendingUserInputAnswersByRequestId] = useState< + Record> + >({}); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const legendListRef = useRef(null); + const [composerOverlayElement, setComposerOverlayElement] = useState(null); + const [composerOverlayHeight, setComposerOverlayHeight] = useState(0); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const attachmentPreviewHandoffByMessageIdRef = useRef>({}); + const attachmentPreviewPromotionInFlightByMessageIdRef = useRef>({}); + const sendInFlightRef = useRef(false); + +- const environmentUnavailableSendToastSlotRef = useRef(0); + - const feedbackUploadsInFlightRef = useRef(new Set()); + const terminalUiOpenByThreadRef = useRef>({}); + + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const terminalUiState = useTerminalUiStateStore((state) => + selectThreadTerminalUiState(state.terminalUiStateByThreadKey, routeThreadRef), + ); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const isServerThread = activeServerThread !== null; + const activeThread = activeServerThread ?? localDraftThread; + const threadError = isServerThread + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + : localDraftError; + // Dismissals can only mask the shown error, never clear it: a server thread + // keeps its error in session.lastError, so clearing the local shadow would + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + [activeThreadEnvironmentId, activeThreadId], + ); + const activeThreadKey = activeThreadRef ? scopedThreadKey(activeThreadRef) : null; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const [timelineAnchor, setTimelineAnchor] = useState<{ + readonly threadKey: string | null; + readonly messageId: MessageId | null; + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const activeFileSurface = + activeRightPanelSurface?.kind === "file" ? activeRightPanelSurface : null; + const activePreviewState = useThreadPreviewState(activeThreadRef); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const activePreviewMiniPlayer = usePreviewMiniPlayerStore((state) => + selectThreadPreviewMiniPlayer(state.byThreadKey, activeThreadRef), + ); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const existingThreadKeys = new Set([...serverThreadKeys, ...draftThreadKeys]); + return openTerminalThreadKeys.filter((nextThreadKey) => existingThreadKeys.has(nextThreadKey)); + }, [draftThreadKeys, openTerminalThreadKeys, serverThreadKeys]); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + useEffect(() => { + setMountedTerminalThreadKeys((currentThreadIds) => { + const nextThreadIds = reconcileMountedTerminalThreadIds({ + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + : nextThreadIds; + }); + }, [activeThreadKey, existingOpenTerminalThreadKeys, terminalUiState.terminalOpen]); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const activeProject = useProject(activeProjectRef); + const handleNewThreadInActiveProject = useCallback(() => { + startNewThreadForProject(activeProjectRef, handleNewThread); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + // drive the environment picker in BranchToolbar. + const allProjects = useProjects(); + const primaryEnvironmentId = primaryEnvironment?.environmentId ?? null; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + useEffect(() => { + if (!clientSettingsHydrated || !activeThreadRef || !activeProject) return; + // Reuse the sidebar's grouping so history follows the project rows the user + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + : (primaryEnvironment?.serverConfig ?? null); + const pullRequestsCapabilityKnown = serverConfig !== null; + const supportsPullRequests = serverConfig?.environment.capabilities.pullRequests === true; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const versionMismatch = resolveServerConfigVersionMismatch(serverConfig); + const versionMismatchDismissKey = + versionMismatch && activeThread + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const serverUpdateState = useAtomValue( + serverEnvironment.updateStateAtom(serverUpdateEnvironmentId), + ); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const systemComposerBannerItems = useMemo(() => { + const items: ComposerBannerStackItem[] = []; + const updateRunning = serverUpdateState.status === "running"; + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + items.push({ + id: `environment-unavailable:${activeEnvironmentUnavailableState.environmentId}`, + variant: "default", + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + icon: ( + + + ), + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + dismissVersionMismatch(versionMismatchDismissKey); + setDismissedVersionMismatchKey(versionMismatchDismissKey); + }, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + navigate, + setDismissedVersionMismatchKey, + showVersionMismatchBanner, + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + serverUpdateState, + versionMismatch, + versionMismatchDismissKey, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + selectedProviderByThreadId ?? threadProvider, + ); + const selectedProvider: ProviderDriverKind = lockedProvider ?? unlockedSelectedProvider; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + ); + const activePendingUserInput = pendingUserInputs[0] ?? null; + const activePendingDraftAnswers = useMemo( + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + [activePendingDraftAnswers, activePendingUserInput], + ); + const activePendingIsResponding = activePendingUserInput + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + phase, + activePendingApproval: activePendingApproval?.requestId ?? null, + activePendingUserInput: activePendingUserInput?.requestId ?? null, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + }); + const isWorking = phase === "running" || isSendBusy || isConnecting || isRevertingCheckpoint; + const activeWorkStartedAt = deriveActiveWorkStartedAt( + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + ); + useEffect(() => { + attachmentPreviewHandoffByMessageIdRef.current = attachmentPreviewHandoffByMessageId; + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + }); + }, []); + const serverMessages = activeThread?.messages; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const attachmentIds = new Set(); + for (const message of serverMessages ?? []) { + for (const attachment of message.attachments ?? []) { + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + } + return [...attachmentIds]; + }, [serverMessages]); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const serverAttachmentResources = useMemo( + () => + serverAttachmentIds.map((attachmentId) => ({ + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + - return changed ? { ...message, attachments } : message; + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + + }); + }); + + - const localMessages = [ + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + - displayServerMessages, + - feedbackSubmissions, + - optimisticUserMessages, + +- projectHandoffMessagePreviews, + +- ]); + +- const timelineProjectionRef = useRef<{ + +- threadKey: string | null; + +- projection: TimelineEntriesProjection; + +- } | null>(null); + +- const timelineEntries = useMemo(() => { + +- const previous = timelineProjectionRef.current; + +- const projection = deriveTimelineEntriesWithState( + +- timelineMessages, + +- activeThread?.proposedPlans ?? [], + +- workLogEntries, + +- previous?.threadKey === activeThreadKey ? previous.projection : null, + +- ); + +- timelineProjectionRef.current = { threadKey: activeThreadKey, projection }; + +- return projection.entries; + +- }, [ + +- timelineProjectionRef, + +- activeThreadKey, + +- activeThread?.proposedPlans, + +- timelineMessages, + +- workLogEntries, + - ]); + -- const timelineEntries = useMemo( + -+ }, [attachmentPreviewHandoffByMessageId, displayServerMessages, optimisticUserMessages]); + -+ const serverTimelineEntries = useMemo( + -+ () => + -+ deriveTimelineEntriesFromVisibleTurnItems({ + -+ visibleTurnItems: serverVisibleTurnItems, + -+ optimisticMessages: optimisticUserMessages, + -+ attachmentUrlById: serverAttachmentUrlById, + -+ }), + -+ [optimisticUserMessages, serverVisibleTurnItems, serverAttachmentUrlById], + -+ ); + -+ const draftTimelineEntries = useMemo( + - () => + - deriveTimelineEntries(timelineMessages, activeThread?.proposedPlans ?? [], workLogEntries), + - [activeThread?.proposedPlans, timelineMessages, workLogEntries], + - ); + - const [dockedDraftHeroThreadKey, setDockedDraftHeroThreadKey] = useState(null); + - const draftHeroDockRequested = + - activeThreadKey !== null && dockedDraftHeroThreadKey === activeThreadKey; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + - captureDraftHeroComposerRect, + - ] = useDraftHeroLayoutTransition(isDraftHeroState); + - const { turnDiffSummaries, inferredCheckpointTurnCountByTurnId } = + ++ }, [attachmentPreviewHandoffByMessageId, displayServerMessages, optimisticUserMessages]); + ++ const serverTimelineEntries = useMemo( + ++ () => + ++ deriveTimelineEntriesFromVisibleTurnItems({ + ++ visibleTurnItems: serverVisibleTurnItems, + ++ optimisticMessages: optimisticUserMessages, + ++ attachmentUrlById: serverAttachmentUrlById, + ++ }), + ++ [optimisticUserMessages, serverVisibleTurnItems, serverAttachmentUrlById], + ++ ); + ++ const draftTimelineEntries = useMemo( + ++ () => + ++ deriveTimelineEntries(timelineMessages, activeThread?.proposedPlans ?? [], workLogEntries), + ++ [activeThread?.proposedPlans, timelineMessages, workLogEntries], + ++ ); + + const timelineEntries = isServerThread ? serverTimelineEntries : draftTimelineEntries; + + const { turnDiffSummaries, inferredCheckpointTurnCountByRunId } = + useTurnDiffSummaries(activeThread); + const turnDiffSummaryByAssistantMessageId = useMemo(() => { + const byMessageId = new Map(); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + continue; + } + const turnCount = + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + if (typeof turnCount !== "number") { + break; + } + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + } + + return byUserMessageId; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + + const gitCwd = activeProject + ? projectScriptCwd({ + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + ?.instanceId ?? null; + const activeProviderInstanceId = + selectedProviderInstanceId ?? + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const activeProviderStatus = useMemo(() => { + if (activeProviderInstanceId) { + return ( + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const defaultInstanceId = defaultInstanceIdForDriver(selectedProvider); + return providerStatuses.find((status) => status.instanceId === defaultInstanceId) ?? null; + }, [activeProviderInstanceId, providerStatuses, selectedProvider]); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const providerStatusBannerKey = getProviderStatusBannerKey(activeProviderStatus); + const [dismissedProviderStatusBannerKey, setDismissedProviderStatusBannerKey] = useState< + string | null + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + }, [activeThreadRef, diffOpen, isServerThread, onDiffPanelOpen]); + + const envLocked = Boolean( + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + ); + + // Handle environment change for draft threads. When the user picks a + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const toggleInteractionMode = useCallback(() => { + handleInteractionModeChange(interactionMode === "plan" ? "default" : "plan"); + }, [handleInteractionModeChange, interactionMode]); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const createBrowserSurface = useCallback(() => { + if (!activeThreadRef) return; + void addBrowserSurface({ threadRef: activeThreadRef, openPreview }); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + ); + // The thread's own change request, placed against the project it belongs to. Without a + // project there is nothing to resolve it against, so the caller falls back to the browser. + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + ); + const togglePreviewPanel = useCallback(() => { + if (!activeThreadRef || !isPreviewSupportedInRuntime()) return; + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + }, + [activeRightPanelSurface, activeThreadRef, closeTerminalMutation, storeCloseTerminal], + ); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const activateRightPanelSurface = useCallback( + (surface: RightPanelSurface) => { + if (!activeThreadRef) return; + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const closeRightPanelSurface = useCallback( + (surface: RightPanelSurface) => { + if (!activeThreadRef) return; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + ); + const closeOtherRightPanelSurfaces = useCallback( + (surface: RightPanelSurface) => { + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + liveFollowUserScrollGenerationRef.current = anchorUserScrollGenerationRef.current; + setTimelineLiveFollowEnabled(true); + pendingTimelineAnchorRef.current = null; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + useEffect(() => { + let removeListeners: (() => void) | null = null; + let frame: number | null = null; + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + timelineScrollModeRef.current = "following-end"; + liveFollowUserScrollGenerationRef.current = anchorUserScrollGenerationRef.current; + setTimelineLiveFollowEnabled(true); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + showScrollDebouncer.current.cancel(); + setShowScrollToBottom(false); + } else { + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + // activeThreadRef resets transitively with the active thread. + }, [activeThread?.id]); + + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + useEffect(() => { + setIsRevertingCheckpoint(false); + }, [activeThread?.id]); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + ); + // The server-projected settled state keeps the banner and sidebar in sync. + const activeThreadShell = useThreadShell(isServerThread ? activeThreadRef : null); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + }); + const handlePullRequestTabStatusChange = useCallback( + (status: PullRequestTabStatus) => { + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + if (activeThreadRef === null || activeThreadWokeAt === null) return; + markThreadVisited(scopedThreadKey(activeThreadRef), activeThreadWokeAt); + }, [activeThreadRef, activeThreadWokeAt, markThreadVisited]); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const wokeAtMs = Date.parse(activeThreadWokeAt); + if (Number.isNaN(wokeAtMs)) return false; + // Having the thread open counts as a visit at completedAt (the effect + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + }, [ + activeLatestTurn?.completedAt, + activeThreadLastVisitedAt, + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const activeThreadSettled = + supportsSettlement && activeThreadShell?.settledOverride === "settled"; + const unsettleThreadMutation = useAtomCommand(threadEnvironment.unsettle, { + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + // Dismissal lives in a module-level set (survives remounts); this tick just + // forces a re-render so the banner leaves immediately. + const [, setBranchMismatchDismissTick] = useState(0); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const activeBranchMismatchKey = branchMismatchKey( + activeThread?.id ?? null, + localCheckoutBranchMismatch, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + const showBranchMismatchBanner = shouldShowBranchMismatchBanner({ + hasMismatch: localCheckoutBranchMismatch !== null, + isDismissed: isBranchMismatchDismissedForSession(activeBranchMismatchKey), + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + wasShownForCurrentMismatch: + revealedBranchMismatchKey !== null && revealedBranchMismatchKey === activeBranchMismatchKey, + }); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + return { + id: `background-liveness:${activeThread.id}`, + variant: "default", + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + icon: ( + 0 + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + disabled={isStoppingBackgroundWork} + onClick={() => void handleStopBackgroundWork()} + > + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + onDismiss: acknowledgeActiveThreadWoke, + }; + }, [acknowledgeActiveThreadWoke, activeThread?.id, activeThreadWokeVisible]); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const parkedThreadBannerItem = useMemo(() => { + if (!activeThreadSnoozed && !activeThreadSettled) { + return null; + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + isUnsnoozing, + isUnsettling, + ]); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const handleRestoreThreadBranch = useCallback(() => { + if (gitStatusQuery.data?.hasWorkingTreeChanges) { + setBranchRestoreConfirmOpen(true); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + void handleSwitchCheckoutToThread(); + }, [gitStatusQuery.data?.hasWorkingTreeChanges, handleSwitchCheckoutToThread]); + const composerBannerItems = useMemo(() => { + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + ...wokeThreadItems, + { + id: `branch-mismatch:${activeBranchMismatchKey}`, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + isRestoringThreadBranch, + localCheckoutBranchMismatch, + parkedThreadBannerItem, + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + useEffect(() => { + setPendingServerThreadEnvMode(null); + setPendingServerThreadBranch(undefined); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + event.stopPropagation(); + return; + } + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + if (!activeThreadId || isCommandPaletteOpen()) { + return; + } + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + }); + if (!command) return; + + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + if (command === "terminal.toggle") { + event.preventDefault(); + event.stopPropagation(); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + return; + } + + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + if (command === "terminal.split") { + event.preventDefault(); + event.stopPropagation(); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + event.preventDefault(); + event.stopPropagation(); + if (terminalFocusOwner === "right-panel" && activeRightPanelSurface?.kind === "terminal") { + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + return; + } + + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + activeProject, + activeRightPanelSurface, + addTerminalSurface, + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + toggleTerminalVisibility, + composerRef, + ]); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + + const onSend = async ( + e?: { preventDefault: () => void }, + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + directAnnotation?: { + annotation: PreviewAnnotationPayload; + image: ComposerImageAttachment | null; + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + isSendBusy || + isConnecting || + threadDetailLoading || + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + ) { + notifyDirectAnnotationAttached(); + return; + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + composerPreviewAnnotations.length + + composerReviewComments.length, + }); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + promptRef.current = ""; + clearComposerDraftContent(composerDraftTarget); + composerRef.current?.resetCursorState(); + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + return; + } + + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const composerImagesSnapshot = [...composerImages]; + const composerFilesSnapshot = [...composerFiles]; + const composerAttachmentsSnapshot = [...composerImagesSnapshot, ...composerFilesSnapshot]; + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + messageTextWithPreviewAnnotations, + composerReviewCommentsSnapshot, + ); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const outgoingMessageText = formatOutgoingPrompt({ + provider: ctxSelectedProvider, + model: ctxSelectedModel, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + effort: ctxSelectedPromptEffort, + text: messageTextForSend || ATTACHMENT_ONLY_BOOTSTRAP_PROMPT, + }); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + setOptimisticUserMessages((existing) => [ + ...existing, + { + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + role: "user", + text: outgoingMessageText, + ...(optimisticAttachments.length > 0 ? { attachments: optimisticAttachments } : {}), + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + createdAt: messageCreatedAt, + updatedAt: messageCreatedAt, + streaming: false, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + : {}), + } + : undefined; + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const startResult = await startThreadTurn({ + environmentId, + input: { + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + }, + }); + if (startResult._tag === "Failure") { + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + } + } + + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + } + if (!isAtomCommandInterrupted(failure)) { + const error = squashAtomCommandFailure(failure); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + setThreadError( + threadIdForSend, + error instanceof Error ? error.message : "Failed to send message.", + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + }; + + const onRespondToApproval = useCallback( + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + + setRespondingRequestIds((existing) => + existing.includes(requestId) ? existing : [...existing, requestId], + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + setRespondingRequestIds((existing) => existing.filter((id) => id !== requestId)); + return result; + }, + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + + setRespondingUserInputRequestIds((existing) => + existing.includes(requestId) ? existing : [...existing, requestId], + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + setRespondingUserInputRequestIds((existing) => existing.filter((id) => id !== requestId)); + return result; + }, + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + ); + + const setActivePendingUserInputQuestionIndex = useCallback( + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + ); + + const onAdvanceActivePendingUserInput = useCallback(() => { + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + return; + } + if (activePendingProgress.isLastQuestion) { + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + beginLocalDispatch({ preparingWorktree: false }); + setThreadError(threadIdForSend, null); + + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + + setOptimisticUserMessages((existing) => [ + ...existing, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + id: messageIdForSend, + role: "user", + text: outgoingMessageText, + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + createdAt: messageCreatedAt, + updatedAt: messageCreatedAt, + streaming: false, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + persistThreadSettingsForNextTurn, + resetLocalDispatch, + runtimeMode, + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + setComposerDraftInteractionMode, + setThreadError, + startThreadTurn, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + effort: ctxSelectedPromptEffort, + text: implementationPrompt, + }); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + const nextThreadTitle = truncate(buildPlanImplementationThreadTitle(planMarkdown)); + const nextThreadModelSelection: ModelSelection = ctxSelectedModelSelection; + + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + } + const reason = getStartedThreadModelChangeBlockReason({ + providers: providerStatuses, + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + nextModelSelection: { instanceId, model }, + }); + return reason ? `${reason.description} Start a new thread to use this model.` : null; + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + scheduleComposerFocus(); + return; + } + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + ); + if ( + currentEntry?.continuation?.groupKey && + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + }; + const modelChangeBlockReason = getStartedThreadModelChangeBlockReason({ + providers: providerStatuses, + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + nextModelSelection, + }); + if (modelChangeBlockReason) { + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + [cancelVideoPreviewRequest], + ); + const onOpenTurnDiff = useCallback( + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + useRightPanelStore.getState().open(activeThreadRef, "diff"); + onDiffPanelOpen?.(); + }, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + // One inset in both states: the controls move between containers when + // the right panel opens, and a different right offset made them jump + // sideways on every toggle. + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + > + {rightPanelOpen && !shouldUseRightPanelSheet ? ( + { + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + }} + /> + + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + context={ + isThreadOwnPullRequest( + { + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + repository: threadRepository, + number: activeThreadPr?.number ?? null, + }, + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + ? "thread" + : "page" + } + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + composerDraftTarget={composerDraftTarget} + onStateChange={handlePullRequestTabStatusChange} + /> + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + ) : null + ) : null; + + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + return ( +
+ {rightPanelOpen && !shouldUseRightPanelSheet ? panelLayoutControls : null} + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + data-chat-column-maximized-away={rightPanelMaximized ? "true" : "false"} + > + {/* Top bar */} + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + activeProjectName={activeProject?.title} + activeProjectCwd={activeProject?.workspaceRoot ?? null} + activeProjectFaviconPath={activeProject?.faviconPath ?? null} + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + onUpdateProjectScript={updateProjectScript} + onDeleteProjectScript={deleteProjectScript} + /> + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + + + {/* Chat column */} + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + {/* Provider status overlays the timeline without changing its content height. */} +
+ + )} +
+ -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + > +
+
+
+ -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + activeSurfaceId={activeRightPanelSurface?.id ?? null} + pendingSurfaceIds={pendingFileSurfaceIds} + previewSessions={activePreviewState.sessions} + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + terminalLabelsById={activeTerminalLabelsById} + onActivate={activateRightPanelSurface} + onCloseSurface={closeRightPanelSurface} + -@@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewProps) { + +@@ apps/web/src/components/ChatView.tsx: export default function ChatView(props: ChatViewProps) { + activeSurfaceId={activeRightPanelSurface?.id ?? null} + pendingSurfaceIds={pendingFileSurfaceIds} + previewSessions={activePreviewState.sessions} + @@ apps/web/src/components/Sidebar.logic.ts: export function resolveThreadStatusPil + return { + + ## apps/web/src/components/Sidebar.tsx ## + +@@ apps/web/src/components/Sidebar.tsx: import { + + effectiveSnoozed, + + threadWokeAt, + + } from "@t3tools/client-runtime/state/thread-settled"; + +-import { resolveSettledThreadTimestamp } from "@t3tools/client-runtime/state/thread-sort"; + + import type { EnvironmentThreadShell } from "@t3tools/client-runtime/state/models"; + + import { + + scopeProjectRef, + + scopeThreadRef, + + scopedThreadKey, + + } from "@t3tools/client-runtime/environment"; + +-import { + +- resolveEnvironmentMachineKind, + +- type EnvironmentMachineKind, + +- type ProjectIconOverride, + +- type ScopedThreadRef, + +- type ThreadId, + +-} from "@t3tools/contracts"; + ++import type { ScopedThreadRef, ThreadId } from "@t3tools/contracts"; + + import type { TimestampFormat } from "@t3tools/contracts/settings"; + + import { + + AlarmClockIcon, + +@@ apps/web/src/components/Sidebar.tsx: import { + + FolderIcon, + + FolderPlusIcon, + + GitBranchIcon, + ++ MessageSquareIcon, + + PinIcon, + + PlusIcon, + + SearchIcon, + ++ ServerIcon, + + SettingsIcon, + + SquarePenIcon, + + TerminalIcon, + @@ apps/web/src/components/Sidebar.tsx: import { + threadTraversalDirectionFromCommand, + } from "../keybindings"; + @@ apps/web/src/components/Sidebar.tsx: import { + import { readLocalApi } from "../localApi"; + import { getProjectOrderKey, selectProjectGroupingSettings } from "../logicalProject"; + import { + -@@ apps/web/src/components/Sidebar.tsx: import type { SidebarThreadSummary } from "../types"; + +@@ apps/web/src/components/Sidebar.tsx: import { + + import { formatRelativeTimeLabel, parseTimestampDate } from "../timestampFormat"; + + import type { SidebarThreadSummary } from "../types"; + import { cn } from "~/lib/utils"; + +-import { EnvironmentMachineIcon } from "./EnvironmentMachineIcon"; + import { buildThreadActionMenuItems } from "./threadActionMenu.logic"; + import { + - animatePinnedLayoutChanges, + buildBulkTitleRegenerationContextMenuItem, + + buildBulkUnpinContextMenuItem, + filterSidebarProjectScopeItems, + - formatWorkingDurationLabel, + +@@ apps/web/src/components/Sidebar.tsx: import { + + planPinnedReorder, + + reduceSidebarProjectScopeMenuState, + + resolveAdjacentThreadId, + ++ resolveSettledTimestamp, + + resolveSidebarThreadStatus, + + searchSidebarThreadsByTitle, + + shouldCreateNewThreadInCurrentProject, + @@ apps/web/src/components/Sidebar.tsx: import { + sortPinnedThreadsForSidebar, + sortSettledThreadsForSidebar, + @@ apps/web/src/components/Sidebar.tsx: import { + import { useThreadRunningTerminalIds } from "../state/terminalSessions"; + import { stackedThreadToast, toastManager } from "./ui/toast"; + import { Button } from "./ui/button"; + +@@ apps/web/src/components/Sidebar.tsx: import { + + // stays behind an explicit Show more. + + const SETTLED_TAIL_INITIAL_COUNT = 10; + + const SETTLED_TAIL_PAGE_COUNT = 25; + +-// Fresh keys deliberately reset both shelves to collapsed for existing users. + +-const SETTLED_SHELF_EXPANDED_KEY = "t3code:sidebar:settled-expanded"; + +-const SNOOZED_SHELF_EXPANDED_KEY = "t3code:sidebar:snoozed-expanded"; + ++// Keep the v2 key so existing preferences survive the v2-to-default rename. + ++const SETTLED_SHELF_EXPANDED_KEY = "t3code:sidebar-v2:settled-expanded"; + ++const SNOOZED_SHELF_EXPANDED_KEY = "t3code:sidebar-v2:snoozed-expanded"; + + + + function compactSidebarTimeLabel(label: string): string { + + if (label === "just now") return "now"; + +@@ apps/web/src/components/Sidebar.tsx: function threadTimeLabel(thread: SidebarThreadSummary): string { + + } + + + + // Settled rows read "how long ago did this wrap up", matching their sort + +-// key: both go through resolveSettledThreadTimestamp so label and order can't + ++// key: both go through resolveSettledTimestamp so label and order can't + + // disagree. + + function settledTimeLabel(thread: SidebarThreadSummary): string { + +- const timestamp = resolveSettledThreadTimestamp(thread); + ++ const timestamp = resolveSettledTimestamp(thread); + + return timestamp === null ? "" : compactSidebarTimeLabel(formatRelativeTimeLabel(timestamp)); + + } + + + @@ apps/web/src/components/Sidebar.tsx: function WorkingDuration(props: { startedAt: string | null }) { + ); + } + @@ apps/web/src/components/Sidebar.tsx: function WorkingDuration(props: { startedAt + function terminalProcessLabel(count: number): string { + return `${count} terminal ${count === 1 ? "process" : "processes"} running`; + } + -@@ apps/web/src/components/Sidebar.tsx: function SidebarThreadTooltip({ + +@@ apps/web/src/components/Sidebar.tsx: function terminalProcessLabel(count: number): string { + + function SidebarThreadTooltip({ + + thread, + + projectTitle, + +- projectDisplayName, + projectCwd, + projectFaviconPath, + +- projectIcon, + environmentLabel, + +- environmentMachine, + - providerEntry, + - showInstanceBadge, + + driverKind, + @@ apps/web/src/components/Sidebar.tsx: function SidebarThreadTooltip({ + modelLabel, + branchMismatch, + @@ apps/web/src/components/Sidebar.tsx: function SidebarThreadTooltip({ + + }: { + + thread: SidebarThreadSummary; + + projectTitle: string | null; + +- projectDisplayName: string | null; + projectCwd: string | null; + projectFaviconPath: string | null; + +- projectIcon: ProjectIconOverride | null; + environmentLabel: string | null; + +- environmentMachine: EnvironmentMachineKind; + - providerEntry: ProviderInstanceEntry | null; + - showInstanceBadge: boolean; + + driverKind: ProviderInstanceEntry["driverKind"] | null; + @@ apps/web/src/components/Sidebar.tsx: function SidebarThreadTooltip({ + return ( + + +
+ +- {projectDisplayName ? ( + ++ {projectTitle ? ( + +
+ + + +-
{projectDisplayName}
+ ++
{projectTitle}
+ +
+ + ) : null} + + {environmentLabel ? ( + +
+ +- + ++ + +
{environmentLabel}
+ +
+ + ) : null} + @@ apps/web/src/components/Sidebar.tsx: function SidebarThreadTooltip({ +
+ void; + + onDiscard: (draftId: DraftId) => void; + +@@ apps/web/src/components/Sidebar.tsx: const SidebarDraftRow = memo(function SidebarDraftRow(props: { + + + + + +- {props.projectDisplayName} + ++ {props.projectTitle} + + + + + + + +@@ apps/web/src/components/Sidebar.tsx: interface SidebarDraftRowData { + + // subscription + closing divider) so per-keystroke composer updates + + // re-render only this block, never the whole sidebar. Vanishes at count 0. + + const SidebarDraftBlock = memo(function SidebarDraftBlock(props: { + +- projectTitleByKey: ReadonlyMap; + + projectDisplayNameByKey: ReadonlyMap; + + projectCwdByKey: ReadonlyMap; + + projectFaviconPathByKey: ReadonlyMap; + +- projectIconByKey: ReadonlyMap; + + scopedProjectKeys: ReadonlySet | null; + + routeDraftId: string | null; + + onNavigateToDraft: (draftId: DraftId) => void; + @@ apps/web/src/components/Sidebar.tsx: const SidebarDraftBlock = memo(function SidebarDraftBlock(props: { + // The /draft/$draftId route redirects home on its own when the draft + // it renders disappears, so discarding the open draft needs no + @@ apps/web/src/components/Sidebar.tsx: const SidebarDraftBlock = memo(function Sid + clearDraftThread(draftId); + }, + [clearDraftThread], + +@@ apps/web/src/components/Sidebar.tsx: const SidebarDraftBlock = memo(function SidebarDraftBlock(props: { + + draftId={draftId} + + session={session} + + composer={composer} + +- projectTitle={props.projectTitleByKey.get(projectKey) ?? null} + +- projectDisplayName={props.projectDisplayNameByKey.get(projectKey) ?? null} + ++ projectTitle={props.projectDisplayNameByKey.get(projectKey) ?? null} + + projectCwd={props.projectCwdByKey.get(projectKey) ?? null} + + projectFaviconPath={props.projectFaviconPathByKey.get(projectKey) ?? null} + +- projectIcon={props.projectIconByKey.get(projectKey) ?? null} + + isActive={draftId === props.routeDraftId} + + onNavigate={props.onNavigateToDraft} + + onDiscard={handleDiscard} + @@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function SidebarThreadRow(props: { + settlementSupported: boolean; + // Same contract for thread.snooze/unsnooze. + @@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function Side + pinningSupported: boolean; + isPinned: boolean; + // Present only on pinned cards whose server supports reordering: dnd-kit + +@@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function SidebarThreadRow(props: { + + jumpLabel: string | null; + + currentEnvironmentId: string | null; + + environmentLabel: string | null; + +- environmentMachine: EnvironmentMachineKind; + + projectCwd: string | null; + + projectFaviconPath: string | null; + +- projectIcon: ProjectIconOverride | null; + + projectTitle: string | null; + +- projectDisplayName: string | null; + + providerEntryByInstanceId: ReadonlyMap; + + timestampFormat: TimestampFormat; + + onThreadClick: (event: ReactMouseEvent, threadRef: ScopedThreadRef) => void; + @@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function SidebarThreadRow(props: { + onUnsnooze: (threadRef: ScopedThreadRef) => void; + onUnpin: (threadRef: ScopedThreadRef) => void; + @@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function Side + onCommitRename, + onContextMenu, + @@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function SidebarThreadRow(props: { + - const terminalProcessCount = runningTerminalIds.length; + + ); + + const gitCwd = thread.worktreePath ?? props.projectCwd; + - const linkedPullRequestStatus = useLinkedThreadPullRequest( + @@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function Side + - linkedPullRequestStatus, + - }); + - const prStatus = prStatusIndicator(pr, prProvider); + +- const settledPrHoverClass = pr ? settledPrHoverColorClass(pr.state, pr.isDraft) : undefined; + + const prStatus = prStatusIndicator(pr, gitStatus.data?.sourceControlProvider); + - const settledPrHoverClass = pr ? settledPrHoverColorClass(pr.state) : undefined; + ++ const settledPrHoverClass = pr ? settledPrHoverColorClass(pr.state) : undefined; + + // Report the PR state so the parent can apply the configured merge rule + + // and the always-on close rule during partitioning. + useEffect(() => { + @@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function Side + (model) => model.slug === thread.modelSelection.model, + ); + @@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function SidebarThreadRow(props: { + + ? getTriggerDisplayModelLabel(selectedModel) + + : thread.modelSelection.model; + + + +- // The local environment is "this machine" and needs no marker; every other + +- // one gets its machine glyph. With no local environment (the hosted app) + +- // that is every thread, which is the point: the glyph is what tells rows on + +- // different machines apart. + +- const isRemote = thread.environmentId !== props.currentEnvironmentId; + ++ const isRemote = + ++ props.currentEnvironmentId !== null && thread.environmentId !== props.currentEnvironmentId; + + + + const detailsTooltip = ( + + + + ) : null; + +- // Same pen the new-thread draft rows lead with, so both kinds of unsent + +- // work read the same way in the list. + +- const draftIndicator = hasUnsentDraft ? ( + +- + +- + +- } + +- > + +- + +- + +- Unsent draft + +- + +- ) : null; + - const pinIndicator = props.isPinned ? ( + - props.pinningSupported ? ( + - + @@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function Side + if (variant === "slim") { + return ( + @@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function SidebarThreadRow(props: { + + + + + {draftIndicator} + {title} + - {pinIndicator} + {terminalStatusIcon} + @@ apps/web/src/components/Sidebar.tsx: const SidebarThreadRow = memo(function Side + + -- ))} + +- {options.map((option) => { + +- const button = ( + +- + +- ); + +- // A provider caution, such as a prompt injection warning on "allow + +- // always", rides along as a tooltip so the row stays one line. + +- return option.warning ? ( + +- + +- + +- + +- {option.warning} + +- + +- + +- ) : ( + +- button + +- ); + +- })} + +
+ -- + -+ + + className="flex w-80 flex-col" + +- {...composerFloatingLayerProps} + + > +
+
+ - onStartFromOriginChange(Boolean(checked))} + + /> + + ## apps/web/src/components/BranchToolbarEnvModeSelector.tsx ## + @@ + @@ apps/web/src/components/BranchToolbarEnvModeSelector.tsx + + resolveWorkspaceDisplayName, + type EnvMode, + } from "./BranchToolbar.logic"; + +-import { composerFloatingLayerProps } from "./chat/composerEventScope"; + import { + + Select, + + SelectGroup, + @@ apps/web/src/components/BranchToolbarEnvModeSelector.tsx: import { + SelectTrigger, + SelectValue, + @@ apps/web/src/components/BranchToolbarEnvModeSelector.tsx: interface BranchToolba + +======= + + const lockedRow = ( + + @@ apps/web/src/components/BranchToolbarEnvModeSelector.tsx: export const BranchToo + + - + - + +- + + {displayMode === "panel" ? ( + + + + {effectiveEnvMode === "worktree" && !activeWorktreePath ? "Create" : workspaceKind} + @@ apps/web/src/components/BranchToolbarEnvModeSelector.tsx: export const BranchToo + + + + {workspacePath ? {workspacePath} : null} + + + - + ++ + + Workspace + + + + ## apps/web/src/components/BranchToolbarEnvironmentSelector.tsx ## + -@@ apps/web/src/components/BranchToolbarEnvironmentSelector.tsx: import { CloudIcon, MonitorIcon } from "lucide-react"; + +@@ + + import type { EnvironmentId } from "@t3tools/contracts"; + ++import { CloudIcon, MonitorIcon } from "lucide-react"; + import { memo, useMemo } from "react"; + + import type { EnvironmentOption } from "./BranchToolbar.logic"; + +-import { EnvironmentMachineIcon } from "./EnvironmentMachineIcon"; + +-import { composerFloatingLayerProps } from "./chat/composerEventScope"; + +import { cn } from "../lib/utils"; + +import { + + THREAD_DETAILS_PANEL_ICON_CLASS, + @@ apps/web/src/components/BranchToolbarEnvironmentSelector.tsx: export const Branc + + + +======= + + +- + +>>>>>>> abd5cc5ff8 (Map thread panel into title bar and sidebar) + - {activeEnvironment?.isPrimary ? ( + -- + ++ {activeEnvironment?.isPrimary ? ( + + + - ) : ( + -- + ++ ) : ( + + + - )} + ++ )} + + - {activeEnvironment?.isPrimary ? ( + -- + +- + ++ {activeEnvironment?.isPrimary ? ( + + + - ) : ( + -- + ++ ) : ( + + + - )} + ++ )} + + + + - + +- + ++ + + + + Run on + + {availableEnvironments.map((env) => ( + + + + + +- + ++ {env.isPrimary ? ( + ++ + ++ ) : ( + ++ + ++ )} + + {env.label} + + + + + + ## apps/web/src/components/ChatView.logic.ts ## + @@ apps/web/src/components/ChatView.logic.ts: import { type ComposerImageAttachment, type DraftThreadState } from "../composer + @@ apps/web/src/components/ChatView.tsx: import { useTurnDiffSummaries } from "../h + type RightPanelSurface, + updatePullRequestTabStatus, + @@ apps/web/src/components/ChatView.tsx: import { + + deriveAgentPanelModel, + foldSubagentActivities, + } from "@t3tools/client-runtime/state/subagentRuntime"; + - import { DiffWorkerPoolProvider } from "./DiffWorkerPoolProvider"; + -import { BranchToolbar } from "./BranchToolbar"; + ++import { DiffWorkerPoolProvider } from "./DiffWorkerPoolProvider"; + import { resolveShortcutCommand, shortcutLabelForCommand } from "../keybindings"; + import ThreadTerminalDrawer from "./ThreadTerminalDrawer"; + -import { + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + + ## apps/web/src/components/GitActionsControl.tsx ## + @@ apps/web/src/components/GitActionsControl.tsx: import { + + ChevronDownIcon, + CloudDownloadIcon, + CloudUploadIcon, + - ExternalLinkIcon, + ++ ExternalLinkIcon, + + FileDiffIcon, + GitBranchPlusIcon, + GitCommitIcon, + InfoIcon, + -@@ apps/web/src/components/GitActionsControl.tsx: import { randomUUID } from "~/lib/utils"; + +@@ apps/web/src/components/GitActionsControl.tsx: import { vcsEnvironment } from "~/state/vcs"; + + import { randomUUID } from "~/lib/utils"; + import { resolvePathLinkTarget } from "~/terminal-links"; + import { type DraftId, useComposerDraftStore } from "~/composerDraftStore"; + - import { readLocalApi } from "~/localApi"; + ++import { readLocalApi } from "~/localApi"; + +import { + + THREAD_DETAILS_PANEL_ICON_CLASS, + + THREAD_DETAILS_PANEL_ROW_CLASS, + @@ apps/web/src/components/GitActionsControl.tsx: import { randomUUID } from "~/lib + + THREAD_DETAILS_PANEL_SPLIT_SEPARATOR_CLASS, + +} from "./chat/threadDetailsPanelStyles"; + import { getSourceControlPresentation } from "~/sourceControlPresentation"; + - import { openPullRequestLink, useOpenPrLink } from "~/lib/openPullRequestLink"; + +-import { useOpenLink } from "~/browser/useOpenLink"; + +-import { useOpenPrLink } from "~/lib/openPullRequestLink"; + ++import { openPullRequestLink, useOpenPrLink } from "~/lib/openPullRequestLink"; + + -@@ apps/web/src/components/GitActionsControl.tsx: interface GitActionsControlProps { + + interface GitActionsControlProps { + gitCwd: string | null; + activeThreadRef: ScopedThreadRef | null; + draftId?: DraftId; + @@ apps/web/src/components/GitActionsControl.tsx: function GitActionItemIcon({ + if (quickAction.kind === "open_pr") return ; + if (quickAction.kind === "open_publish") return ; + if (quickAction.kind === "run_pull") return ; + +@@ apps/web/src/components/GitActionsControl.tsx: interface PublishRepositoryDialogProps { + + readonly open: boolean; + + readonly onOpenChange: (open: boolean) => void; + + readonly environmentId: ScopedThreadRef["environmentId"] | null; + +- /** Thread the dialog was opened from, so the new repository can open beside it. */ + +- readonly threadRef: ScopedThreadRef | null; + + readonly gitCwd: string; + + } + + + + function PublishRepositoryDialog(props: PublishRepositoryDialogProps) { + +- const openLink = useOpenLink(props.threadRef); + + const navigate = useNavigate(); + + const sourceControlDiscovery = useEnvironmentQuery( + + props.environmentId === null + +@@ apps/web/src/components/GitActionsControl.tsx: function PublishRepositoryDialog(props: PublishRepositoryDialogProps) { + + size="sm" + + className="w-full" + + onClick={() => { + +- void openLink(publishResult.repository.url).catch(() => undefined); + ++ const api = readLocalApi(); + ++ if (!api) return; + ++ void api.shell.openExternal(publishResult.repository.url); + + }} + + > + ++ + + Open on {publishProviderLabel} + + + + + @@ apps/web/src/components/GitActionsControl.tsx: export default function GitActionsControl({ + gitCwd, + activeThreadRef, + @@ apps/web/src/components/GitActionsControl.tsx: export default function GitAction + const updateThreadMetadata = useAtomCommand( + threadEnvironment.updateMetadata, + "thread branch metadata update", + +@@ apps/web/src/components/GitActionsControl.tsx: export default function GitActionsControl({ + + [activeThreadRef], + + ); + + const openPrLink = useOpenPrLink(activeThreadRef ?? undefined); + +- const openLink = useOpenLink(activeThreadRef); + + const activeDraftThread = useComposerDraftStore((store) => + + draftId + + ? store.getDraftSession(draftId) + +@@ apps/web/src/components/GitActionsControl.tsx: export default function GitActionsControl({ + + onOpenPullRequest(openPr.number); + + return; + + } + ++ const api = readLocalApi(); + ++ if (!api) { + ++ toastManager.add({ + ++ type: "error", + ++ title: "Link opening is unavailable.", + ++ data: threadToastData, + ++ }); + ++ return; + ++ } + + const prUrl = openPr?.url ?? null; + + if (!prUrl) { + + toastManager.add({ + +@@ apps/web/src/components/GitActionsControl.tsx: export default function GitActionsControl({ + + }); + + return; + + } + +- void openLink(prUrl).catch((err: unknown) => { + ++ void openPullRequestLink(api.shell, prUrl).catch((err: unknown) => { + + console.error(err); + + toastManager.add( + + stackedThreadToast({ + +@@ apps/web/src/components/GitActionsControl.tsx: export default function GitActionsControl({ + + }), + + ); + + }); + +- }, [gitStatusForActions, onOpenPullRequest, openLink, threadToastData]); + ++ }, [gitStatusForActions, onOpenPullRequest, threadToastData]); + + + + runGitActionWithToast = useEffectEvent( + + async ({ + @@ apps/web/src/components/GitActionsControl.tsx: export default function GitActionsControl({ + + +- {/* + +- Same choice the tab bar's "+" menu offers: the card opens the + +- default profile, the chevron picks another. Only worth showing + +- once there is something to choose between. + +- */} + +- {action.label === "Browser" && props.browserProfiles.length > 1 ? ( + +- + +- + +- } + +- > + +- + +- + +- + +- {props.browserProfiles.map((profile) => ( + +- props.onAddBrowserInProfile(profile.id)} + +- > + +- {profile.name} + +- + +- ))} + +- + +- + +- ) : null} + +-
+ ++ {action.shortcut} + ++ + ++ {actionIcon(action)} + ++ {action.label} + ++ + ++ + ++ {action.description} + ++ + ++ + + ) : ( + +
>; + + desktopByTabId: Readonly>; + + theme: "light" | "dark"; + +- environmentId: EnvironmentId | null; + +- pullRequestStatusSeeds: Readonly> | undefined; + ++ pullRequestStatuses: Readonly> | undefined; + + }) { + + switch (surface.kind) { + + case "preview": { + +@@ apps/web/src/components/RightPanelTabs.tsx: function SurfaceIcon({ + + ); + + case "terminal": + + return ; + +- case "pull-request": + +- return ( + +- + +- ); + ++ case "pull-request": { + ++ const status = pullRequestStatuses?.[surface.id] ?? null; + ++ const toneClassName = + ++ status?.state === "merged" + ++ ? "text-violet-600 dark:text-violet-300/90" + ++ : status?.state === "closed" + ++ ? "text-red-600 dark:text-red-300/90" + ++ : status?.isDraft + ++ ? "text-zinc-500 dark:text-zinc-400/80" + ++ : status?.state === "open" + ++ ? "text-emerald-600 dark:text-emerald-300/90" + ++ : "text-muted-foreground"; + ++ return ; + ++ } + + case "agents": + + return ; + + } + + } + + + +-function PullRequestSurfaceIcon({ + +- surface, + +- environmentId, + +- seed, + +-}: { + +- surface: Extract; + +- environmentId: EnvironmentId | null; + +- seed: PullRequestTabStatusSeed | undefined; + +-}) { + +- const resolvedEnvironmentId = + +- (surface.environmentId as EnvironmentId | undefined) ?? environmentId; + +- const detail = useEnvironmentQuery( + +- resolvedEnvironmentId === null + +- ? null + +- : pullRequestEnvironment.detail({ + +- environmentId: resolvedEnvironmentId, + +- input: { + +- projectId: surface.projectId as ProjectId, + +- repository: surface.repository, + +- number: surface.number, + +- }, + +- }), + +- ).data; + +- // Only state and draft reach the tab. A list seed cannot know mergeability, so feeding the + +- // full detail would flip an open tab to the conflict glyph the moment its read lands. + +- const status = + +- detail === null ? (seed ?? null) : { state: detail.state, isDraft: detail.isDraft }; + +- if (status === null) { + +- return ; + +- } + +- const presentation = resolvePullRequestState(status); + +- return ; + +-} + +- + + export function RightPanelTabs(props: RightPanelTabsProps) { + + const ownsDesktopTitleBar = isElectron && props.mode === "inline"; + +- const browserProfiles = useBrowserDefaults().profiles; + + const { resolvedTheme } = useTheme(); + + const tabListRef = useRef(null); + + const [addSurfaceMenuOpen, setAddSurfaceMenuOpen] = useState(false); + +- const [tabScrollState, setTabScrollState] = useState({ + +- hasOverflow: false, + +- canScrollLeft: false, + +- canScrollRight: false, + +- }); + +- + +- const updateTabScrollState = useCallback(() => { + +- const viewport = tabScrollViewport(tabListRef.current); + +- if (!viewport) return; + +- + +- const hasOverflow = viewport.scrollWidth - viewport.clientWidth > TAB_SCROLL_EDGE_TOLERANCE; + +- const canScrollLeft = hasOverflow && viewport.scrollLeft > TAB_SCROLL_EDGE_TOLERANCE; + +- const canScrollRight = + +- hasOverflow && + +- viewport.scrollLeft + viewport.clientWidth < viewport.scrollWidth - TAB_SCROLL_EDGE_TOLERANCE; + +- setTabScrollState((current) => { + +- if ( + +- current.hasOverflow === hasOverflow && + +- current.canScrollLeft === canScrollLeft && + +- current.canScrollRight === canScrollRight + +- ) { + +- return current; + +- } + +- return { hasOverflow, canScrollLeft, canScrollRight }; + +- }); + +- }, []); + +- + +- const scrollTabs = useCallback((direction: -1 | 1) => { + +- const viewport = tabScrollViewport(tabListRef.current); + +- if (!viewport) return; + +- const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches; + +- viewport.scrollBy({ + +- left: direction * Math.max(120, viewport.clientWidth * 0.75), + +- behavior: reduceMotion ? "auto" : "smooth", + +- }); + +- }, []); + + + + const addSurfaceActions = [ + + { + +@@ apps/web/src/components/RightPanelTabs.tsx: export function RightPanelTabs(props: RightPanelTabsProps) { + + if (surfaceIndex < 0) return; + + + + const items: ContextMenuItem[] = []; + +- if (surface.kind === "file" && surface.attachment === undefined) { + ++ if (surface.kind === "file") { + + items.push({ id: "copy-path", label: "Copy path" }); + + } + + const menuPreviewTabId = previewTabIdOf(surface, props.previewSessions); + @@ apps/web/src/components/RightPanelTabs.tsx: export function RightPanelTabs(props: RightPanelTabsProps) { + + const action = await api.contextMenu.show(items, { x: event.clientX, y: event.clientY }); + + switch (action) { + + case "copy-path": + +- if (surface.kind === "file" && surface.attachment === undefined) { + +- props.onCopyFilePath(surface.relativePath); + +- } + ++ if (surface.kind === "file") props.onCopyFilePath(surface.relativePath); + + break; + + case "toggle-mute": { + + // menuOverlay repeats the disabled gate above: the desktop tab must + +@@ apps/web/src/components/RightPanelTabs.tsx: export function RightPanelTabs(props: RightPanelTabsProps) { + + ); + + + + useEffect(() => { + +- if (!props.activeSurfaceId || !tabScrollState.hasOverflow) return; + + const activeTab = tabListRef.current?.querySelector("[data-active-tab='true']"); + + activeTab?.scrollIntoView({ block: "nearest", inline: "nearest" }); + +- }, [props.activeSurfaceId, tabScrollState.hasOverflow]); + +- + +- useEffect(() => { + +- const viewport = tabScrollViewport(tabListRef.current); + +- if (!viewport) return; + +- + +- const content = viewport.firstElementChild; + +- const resizeObserver = new ResizeObserver(updateTabScrollState); + +- resizeObserver.observe(viewport); + +- if (content) resizeObserver.observe(content); + +- viewport.addEventListener("scroll", updateTabScrollState, { passive: true }); + +- updateTabScrollState(); + +- + +- return () => { + +- resizeObserver.disconnect(); + +- viewport.removeEventListener("scroll", updateTabScrollState); + +- }; + +- }, [updateTabScrollState]); + +- + +- useEffect(() => { + +- const viewport = tabScrollViewport(tabListRef.current); + +- if (!viewport) return; + +- + +- const handleWheel = (event: WheelEvent) => { + +- if (event.ctrlKey) return; + +- let delta = Math.abs(event.deltaX) > Math.abs(event.deltaY) ? event.deltaX : event.deltaY; + +- if (event.deltaMode === WheelEvent.DOM_DELTA_LINE) delta *= 16; + +- if (event.deltaMode === WheelEvent.DOM_DELTA_PAGE) delta *= viewport.clientWidth; + +- if (delta === 0) return; + +- + +- const previousScrollLeft = viewport.scrollLeft; + +- viewport.scrollLeft += delta; + +- if (viewport.scrollLeft === previousScrollLeft) return; + +- event.preventDefault(); + +- updateTabScrollState(); + +- }; + +- + +- viewport.addEventListener("wheel", handleWheel, { passive: false }); + +- return () => viewport.removeEventListener("wheel", handleWheel); + +- }, [updateTabScrollState]); + ++ }, [props.activeSurfaceId]); + + + + return ( + +
+ +
+ +@@ apps/web/src/components/RightPanelTabs.tsx: export function RightPanelTabs(props: RightPanelTabsProps) { + + sessions={props.previewSessions} + + desktopByTabId={props.desktopByTabId} + + theme={resolvedTheme} + +- environmentId={props.environmentId} + +- pullRequestStatusSeeds={props.pullRequestStatusSeeds} + ++ pullRequestStatuses={props.pullRequestStatuses} + + /> + + {pending ? ( + + + + {addSurfaceActions.map((action) => { + + const Icon = action.icon; + +- // Browser collapses into one row: clicking the trigger opens + +- // the default profile (the common case stays one click), + +- // while hover or arrow reveals the profiles. The choice + +- // lives at open time because a tab's profile is fixed then — + +- // Electron only honours a partition before attach. + +- if (action.label === "Browser" && action.available) { + +- return ( + +- + +- { + +- const pointerType = + +- "pointerType" in event.nativeEvent && + +- typeof event.nativeEvent.pointerType === "string" + +- ? event.nativeEvent.pointerType + +- : undefined; + +- // Touch has no hover path to the profile choices: + +- // its first tap opens the submenu, then a profile + +- // is selected there. Mouse click keeps the common + +- // default-profile action at one click. + +- if (!shouldOpenDefaultBrowserProfileFromMenuClick(pointerType)) + +- return; + +- setAddSurfaceMenuOpen(false); + +- action.onClick(); + +- }} + +- > + +- + +- {action.label} + +- {action.shortcut} + +- + +- {/* + +- Capped and truncated: profile names are user-supplied + +- and run to 48 characters, which would otherwise widen + +- the popup to fit-content and wrap. + +- */} + +- + +- {browserProfiles.map((profile) => ( + +- props.onAddBrowserInProfile(profile.id)} + +- > + +- {profile.name} + +- + +- ))} + +- + +- + +- ); + +- } + + return ( + + + + + +- {tabScrollState.hasOverflow ? ( + +-
+ +- + +- + +- + +- + +- } + +- /> + +- Scroll tabs left + +- + +- + +- + +- + +- + +- } + +- /> + +- Scroll tabs right + +- + +-
+ +- ) : null} + + {props.layoutControls} + + {ownsDesktopTitleBar ? ( + + | undefined; + - preferredScriptId: string | null; + @@ apps/web/src/components/chat/ChatHeader.tsx: export function resolveRenameCommit + -// events (the second click dismisses it and dblclick still fires), so it + -// opens immediately. + -const TITLE_MENU_OPEN_DELAY_MS = 500; + +-// Matches the @3xl/header-actions container breakpoint owned by this header. + +-const HEADER_ACTIONS_EXPANDED_BREAKPOINT_REM = 48; + - + export function shouldShowOpenInPicker(input: { + readonly activeProjectName: string | undefined; + @@ apps/web/src/components/chat/ChatHeader.tsx: export function shouldShowOpenInPic + activeProjectName, + activeProjectCwd, + activeProjectFaviconPath, + +- activeProjectIcon, + openInCwd, + - activeProjectScripts, + - preferredScriptId, + @@ apps/web/src/components/chat/ChatHeader.tsx: export function shouldShowOpenInPic + - onUpdateProjectScript, + - onDeleteProjectScript, + }: ChatHeaderProps) { + +- const { active: panelAnimationsActive, durationMs: panelAnimationDurationMs } = + +- usePanelAnimationSettings(); + +- const headerActionsRef = useRef(null); + +- useEffect(() => { + +- const actions = headerActionsRef.current; + +- const container = actions?.parentElement; + +- if (!actions || !container) return; + +- return observeResponsiveBreakpointFade({ + +- target: actions, + +- container, + +- active: panelAnimationsActive, + +- durationMs: panelAnimationDurationMs, + +- breakpoint: { value: HEADER_ACTIONS_EXPANDED_BREAKPOINT_REM, unit: "rem" }, + +- }); + +- }, [panelAnimationDurationMs, panelAnimationsActive]); + const primaryEnvironmentId = usePrimaryEnvironmentId(); + const fileScripts = useT3ProjectFileScripts( + + activeThreadEnvironmentId, + @@ apps/web/src/components/chat/ChatHeader.tsx: export const ChatHeader = memo(function ChatHeader({ + }, + [activeThreadEnvironmentId, activeThreadId, activeThreadTitle, updateThreadMetadata], + @@ apps/web/src/components/chat/ChatHeader.tsx: export const ChatHeader = memo(func + - + - {activeProjectName} + @@ apps/web/src/components/chat/ChatHeader.tsx: export const ChatHeader = memo(func + {activeThreadTitle} + + @@ apps/web/src/components/chat/ChatHeader.tsx: export const ChatHeader = memo(function ChatHeader({ + + + + + +
+ @@ apps/web/src/components/preview/PreviewPanelShell.tsx + +interface PreviewPanelShellProps { + mode: PreviewPanelMode; + maximized?: boolean; + +- open?: boolean; + - /** + - * Overrides the localStorage key used to persist the panel width. Callers + - * embedding this shell for a different surface (e.g. the pull requests + @@ apps/web/src/components/preview/PreviewPanelShell.tsx + +) { + const useDragRegion = isElectron && props.mode !== "sheet" && props.mode !== "embedded"; + const isInline = props.mode === "inline"; + +- const collapsible = isInline && props.open !== undefined; + +- const open = props.open ?? true; + +- const maximized = props.maximized ?? false; + - const hostRef = useRef(null); + - // Only inline non-maximized mode applies `width`/`maxWidth`; skip the + - // container measurement (and its re-renders) everywhere else. + -- const maxWidth = useClampedMaxWidth(hostRef, isInline && !props.maximized); + +- const maxWidth = useClampedMaxWidth(hostRef, isInline && !maximized); + - const { width, handlers } = useResizableWidth({ + - storageKey: props.widthStorageKey ?? PREVIEW_PANEL_WIDTH_STORAGE_KEY, + - defaultWidth: props.defaultWidth ?? PREVIEW_PANEL_DEFAULT_WIDTH, + @@ apps/web/src/components/preview/PreviewPanelShell.tsx + - maxWidth, + - edge: "left", + - }); + +- // Derive suppression before the layout commits so the browser never creates + +- // a width transition for resize or maximize changes. + +- const [layoutTransition, setLayoutTransition] = useState(() => ({ + +- open, + +- width, + +- maximized, + +- suppressed: false, + +- })); + +- if ( + +- layoutTransition.open !== open || + +- layoutTransition.width !== width || + +- layoutTransition.maximized !== maximized + +- ) { + +- setLayoutTransition({ + +- open, + +- width, + +- maximized, + +- suppressed: + +- collapsible && + +- layoutTransition.open === open && + +- (layoutTransition.width !== width || layoutTransition.maximized !== maximized), + +- }); + +- } + +- const suppressWidthTransition = layoutTransition.suppressed; + +- useLayoutEffect(() => { + +- if (!suppressWidthTransition) return; + +- let restoreFrame = 0; + +- const paintFrame = window.requestAnimationFrame(() => { + +- restoreFrame = window.requestAnimationFrame(() => { + +- setLayoutTransition((current) => ({ ...current, suppressed: false })); + +- }); + +- }); + +- return () => { + +- window.cancelAnimationFrame(paintFrame); + +- window.cancelAnimationFrame(restoreFrame); + +- }; + +- }, [suppressWidthTransition]); + + const { width, handlers } = props.inlineSize; + - + ++ + return ( +
+ +- {isInline && !maximized ? : null} + +-
+ +-
+ +- {useDragRegion ?
: null} + +- {props.children} + +-
+ +-
+ ++ {isInline && !props.maximized ? : null} + ++ {useDragRegion ?
: null} + ++ {props.children} +
+ ); + } + @@ apps/web/src/rightPanelLayout.test.ts (new) + ## apps/web/src/rightPanelLayout.ts ## + @@ + export const RIGHT_PANEL_INLINE_LAYOUT_MEDIA_QUERY = "(max-width: 980px)"; + +-// Applied only while a floating preview overlaps the compact sheet. + +-export const RIGHT_PANEL_SHEET_LAYER_CLASS_NAME = "z-[35]"; + +export const THREAD_PANEL_INLINE_MIN_WIDTH = 960; + export const RIGHT_PANEL_SHEET_CLASS_NAME = + "w-[min(42vw,28rem)] min-w-80 max-w-[28rem] p-0 max-[760px]:w-[min(88vw,24rem)] max-[760px]:min-w-0 wco:mt-[env(titlebar-area-height)] wco:h-[calc(100%-env(titlebar-area-height))] wco:max-h-[calc(100%-env(titlebar-area-height))]"; + @@ apps/web/src/rightPanelStore.test.ts: import { + + selectThreadPanelOpen, + + selectThreadPanelVisibility, + selectThreadRightPanelState, + - updatePullRequestTabStatus, + useRightPanelStore, + + } from "./rightPanelStore"; + @@ apps/web/src/rightPanelStore.test.ts: const refA = scopeThreadRef("env-1" as EnvironmentId, ThreadId.make("thread-A")) + const refB = scopeThreadRef("env-1" as EnvironmentId, ThreadId.make("thread-B")); + + @@ apps/web/src/rightPanelStore.test.ts: describe("rightPanelStore", () => { + expect(selectActiveRightPanel(useRightPanelStore.getState().byThreadKey, refA)).toBe("preview"); + + ## apps/web/src/rightPanelStore.ts ## + -@@ apps/web/src/rightPanelStore.ts: import { create } from "zustand"; + +@@ + + * workspace paths, and diff/files remain singleton surfaces. + + */ + + import { scopedThreadKey } from "@t3tools/client-runtime/environment"; + +-import type { ChatFileAttachment, ScopedThreadRef } from "@t3tools/contracts"; + ++import type { ScopedThreadRef } from "@t3tools/contracts"; + + import { create } from "zustand"; + import { createJSONStorage, persist } from "zustand/middleware"; + + import { resolveStorage } from "./lib/storage"; + @@ apps/web/src/rightPanelStore.ts: import { create } from "zustand"; + + export const RIGHT_PANEL_KINDS = [ + "diff", + +@@ apps/web/src/rightPanelStore.ts: export type RightPanelSurface = + + | { id: "diff"; kind: "diff" } + + | { id: "files"; kind: "files" } + + | { + +- id: `file:${string}` | `attachment:${string}`; + ++ id: `file:${string}`; + + kind: "file"; + + /** Workspace-relative, or absolute for a host file outside the workspace. */ + + relativePath: string; + + revealLine: number | null; + + revealRequestId: number; + +- /** Present when the file lives in the thread's attachment store rather + +- than at a workspace or host path. */ + +- attachment?: ChatFileAttachment; + + } + + | { + + /** + @@ apps/web/src/rightPanelStore.ts: export interface ThreadRightPanelState { + surfaces: RightPanelSurface[]; + } + @@ apps/web/src/rightPanelStore.ts: export interface ThreadRightPanelState { + open: ( + ref: ScopedThreadRef, + kind: Exclude, + + ) => void; + + openBrowser: (ref: ScopedThreadRef, tabId: string | null) => void; + + openFile: (ref: ScopedThreadRef, relativePath: string, line?: number) => void; + +- openAttachment: (ref: ScopedThreadRef, attachment: ChatFileAttachment) => void; + + openPullRequest: ( + + ref: ScopedThreadRef, + + target: { environmentId?: string; projectId: string; repository: string; number: number }, + @@ apps/web/src/rightPanelStore.ts: interface RightPanelStoreState { + ref: ScopedThreadRef, + kind: Exclude, + @@ apps/web/src/rightPanelStore.ts: const EMPTY_THREAD_STATE: ThreadRightPanelState + const singletonSurface = ( + kind: Exclude, + ): RightPanelSurface => { + +@@ apps/web/src/rightPanelStore.ts: const fileSurface = ( + + revealRequestId, + + }); + + + +-const attachmentSurface = (attachment: ChatFileAttachment): RightPanelSurface => ({ + +- id: `attachment:${attachment.id}`, + +- kind: "file", + +- relativePath: attachment.name, + +- revealLine: null, + +- revealRequestId: 0, + +- attachment, + +-}); + +- + + const terminalSurface = (terminalId: string): RightPanelSurface => ({ + + id: `terminal:${terminalId}`, + + kind: "terminal", + +@@ apps/web/src/rightPanelStore.ts: export function pullRequestSurface(target: { + + }; + + } + + + ++/** + ++ * A pull-request tab's status map with one entry set. Keyed by the surface the panel is showing + ++ * rather than by a key rebuilt from the status, so the tab is found again whether or not that + ++ * surface was opened with an environment on it. Returns the same map when the tab's own fields + ++ * have not changed, so a caller can skip a re-render. + ++ */ + ++export function updatePullRequestTabStatus( + ++ statuses: Readonly>, + ++ surfaceId: string, + ++ status: Status, + ++): Readonly> { + ++ return statuses[surfaceId]?.state === status.state && + ++ statuses[surfaceId]?.isDraft === status.isDraft + ++ ? statuses + ++ : { ...statuses, [surfaceId]: status }; + ++} + ++ + + const upsertSurface = ( + + current: ThreadRightPanelState, + + surface: RightPanelSurface, + @@ apps/web/src/rightPanelStore.ts: const upsertSurface = ( + activeSurfaceId: activate ? surface.id : current.activeSurfaceId, + }); + @@ apps/web/src/rightPanelStore.ts: export const useRightPanelStore = create + +- set((state) => ({ + +- byThreadKey: updateThread(state.byThreadKey, scopedThreadKey(ref), (current) => { + +- const withoutStandaloneExplorer = current.surfaces.filter( + +- (surface) => surface.kind !== "files", + +- ); + +- return upsertSurface( + +- { ...current, surfaces: withoutStandaloneExplorer }, + +- attachmentSurface(attachment), + +- ); + +- }), + +- })), + + ), + openTerminal: (ref, terminalId) => + - set((state) => ({ + @@ apps/web/src/rightPanelStore.ts: export const useRightPanelStore = create { + if (workspaceAvailable) return current; + const surfaces = current.surfaces.filter( + - (surface) => surface.kind !== "files" && surface.kind !== "file", + +- (surface) => + +- surface.kind !== "files" && + +- (surface.kind !== "file" || surface.attachment !== undefined), + ++ (surface) => surface.kind !== "files" && surface.kind !== "file", + + ); + + if (surfaces.length === current.surfaces.length) return current; + + const activeStillExists = surfaces.some( + @@ apps/web/src/rightPanelStore.ts: export const useRightPanelStore = create()( + : (surfaces.at(-1)?.id ?? null), + }; + @@ packages/contracts/src/keybindings.ts: export const STATIC_KEYBINDING_COMMANDS = + "terminal.close", + "rightPanel.toggle", + - "rightPanel.toggleMaximized", + +- "rightPanel.close", + + "threadPanel.toggle", + "diff.toggle", + "preview.toggle", + 61: 2aad9bc514f ! 60: 7d5eedaf9f6 Reserve space for inline thread details panel + @@ apps/web/src/index.css: html[data-mobile-composer-route-transition="true"]::view + - } + -} + - + --@keyframes live-activity-focus { + -- 0% { + -- transform: translateX(0); + -- } + -- 100% { + -- transform: translateX(100%); + -- } + --} + -- + --@keyframes live-activity-focus-counter { + -- 0% { + -- transform: translateX(0); + -- } + -- 100% { + -- transform: translateX(-100%); + -- } + --} + -- + --@utility live-activity-focus { + -- --live-activity-focus-width: 4.5rem; + -- + -- right: auto; + -- left: calc(-1 * var(--live-activity-focus-width)); + -- width: calc(100% + var(--live-activity-focus-width) + var(--live-activity-focus-width)); + -- -webkit-mask-image: linear-gradient( + -- to right, + -- transparent 0, + -- rgb(0 0 0 / 12%) 0.675rem, + -- rgb(0 0 0 / 55%) 1.575rem, + -- black 2.25rem, + -- rgb(0 0 0 / 55%) 2.925rem, + -- rgb(0 0 0 / 12%) 3.825rem, + -- transparent var(--live-activity-focus-width), + -- transparent 100% + -- ); + -- -webkit-mask-repeat: no-repeat; + -- mask-image: linear-gradient( + -- to right, + -- transparent 0, + -- rgb(0 0 0 / 12%) 0.675rem, + -- rgb(0 0 0 / 55%) 1.575rem, + -- black 2.25rem, + -- rgb(0 0 0 / 55%) 2.925rem, + -- rgb(0 0 0 / 12%) 3.825rem, + -- transparent var(--live-activity-focus-width), + -- transparent 100% + -- ); + -- mask-repeat: no-repeat; + -- animation: live-activity-focus 2.2s linear infinite; + -- will-change: transform; + -- + -- @media (prefers-reduced-motion: reduce) { + -- animation: none; + -- opacity: 0; + -- will-change: auto; + -- } + --} + -- + --@utility live-activity-focus-counter { + -- width: 100%; + -- animation: live-activity-focus-counter 2.2s linear infinite; + -- will-change: transform; + -- + -- @media (prefers-reduced-motion: reduce) { + -- animation: none; + -- will-change: auto; + -- } + --} + -- + --@utility live-activity-focus-aligned { + -- width: calc(100% - var(--live-activity-focus-width) - var(--live-activity-focus-width)); + -- margin-left: var(--live-activity-focus-width); + --} + -- + -@property --assistant-citation-highlight-opacity { + - syntax: ""; + - inherits: true; + @@ apps/web/src/index.css: html[data-mobile-composer-route-transition="true"]::view + --accent-foreground: var(--color-neutral-100); + --error: color-mix(in srgb, var(--color-red-500) 90%, var(--color-white)); + --error-foreground: var(--color-red-400); + + --tool-error-icon: #fca5a5; + --error-surface: color-mix(in srgb, var(--error) 16%, transparent); + + --destructive: var(--error); + --border: --alpha(var(--color-white) / 6%); + @@ apps/web/src/index.css: code { + -.chat-markdown .chat-markdown-file-link:hover { + - color: var(--contrast-foreground); + +.chat-markdown a.chat-markdown-file-link { + -+ color: var(--foreground); + -+ text-decoration: none; + -+} + -+ + -+.chat-markdown a.chat-markdown-file-link:hover { + + color: var(--foreground); + text-decoration: none; + } + + -.chat-markdown .chat-markdown-file-link:focus-visible { + ++.chat-markdown a.chat-markdown-file-link:hover { + ++ color: var(--foreground); + ++ text-decoration: none; + ++} + ++ + +.chat-markdown a.chat-markdown-file-link:focus-visible { + outline: none; + box-shadow: 0 0 0 2px color-mix(in srgb, var(--ring) 70%, transparent); + @@ apps/web/src/index.css: code { + + .ultrathink-frame::before { + @@ apps/web/src/index.css: code { + - animation: ultrathink-chroma-shift 10s linear infinite; + + filter: saturate(1.2); + } + + -@keyframes preview-loading-progress { + @@ apps/web/src/index.css: code { + - transition: + - transform 150ms ease-out, + - opacity 150ms ease-out 220ms; + +-} + +- + +-.preview-loading-progress[data-loading="true"] { + +- opacity: 1; + +- animation: preview-loading-progress 5.3s cubic-bezier(0.1, 0.5, 0.2, 1) forwards; + +.ultrathink-pill { + + background: + + linear-gradient(var(--card), var(--card)) padding-box, + @@ apps/web/src/index.css: code { + + 0% 50%; + + animation: ultrathink-rainbow 10s linear infinite; + + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--card) 82%, transparent); + - } + - + --.preview-loading-progress[data-loading="true"] { + -- opacity: 1; + -- animation: preview-loading-progress 5.3s cubic-bezier(0.1, 0.5, 0.2, 1) forwards; + ++} + ++ + +.ultrathink-word { + + display: inline-block; + + color: transparent; + 62: 0531d50ed58 = 61: b9ae98f9794 Split open-in editor controls into panel and toolbar variants + 63: 6c6e346d381 ! 62: c8dce47576c Hide subagent threads and simplify thread controls + @@ apps/web/src/components/Sidebar.logic.ts: type LogicalSidebarProject = SidebarPr + + : thread.lineage.parentThreadId; + } + + - export interface ThreadStatusPill { + + /** + + ## apps/web/src/components/Sidebar.tsx ## + @@ + 64: 1a2b7432e98 ! 63: 4b5fa27f95c Render mobile timelines from V2 turn items + @@ apps/mobile/src/lib/threadActivity.ts: export function buildPendingUserInputAnsw + + }); + + return groupAdjacentActivities(entries); + } + + + + function getThreadFeedActivityEntries(activities: ReadonlyArray) { + + ## apps/mobile/src/state/use-thread-composer-state.ts ## + @@ apps/mobile/src/state/use-thread-composer-state.ts: import { + 65: 327f7287bb8 ! 64: d5a4342a3da Enrich mobile V2 execution items + @@ apps/mobile/src/features/threads/ThreadFeed.tsx: export const ThreadFeed = memo( + ); + + + - ## apps/mobile/src/features/threads/thread-work-log.tsx ## + -@@ + - import * as Haptics from "expo-haptics"; + --import { type AppSymbolName, SymbolView } from "../../components/AppSymbol"; + --import { LayoutAnimation, Pressable, ScrollView, View } from "react-native"; + -+import { SymbolView, type SFSymbol } from "expo-symbols"; + -+import type { EnvironmentId } from "@t3tools/contracts"; + -+import { LayoutAnimation, Pressable, useColorScheme, View } from "react-native"; + - + - import { AppText as Text } from "../../components/AppText"; + - import { scaledTypographyLineHeight } from "../../lib/appearancePreferences"; + - import { cn } from "../../lib/cn"; + - import { THREAD_WORK_ROW_MIN_HEIGHT, type deriveThreadWorkLogSizing } from "../../lib/layout"; + - import type { ThreadFeedActivity } from "../../lib/threadActivity"; + --import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; + --import Animated, { FadeIn } from "react-native-reanimated"; + -+import { ThreadActivityInspector } from "./ThreadActivityInspector"; + - + - const WORK_LOG_LAYOUT_ANIMATION = { + - duration: 180, + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: interface ThreadWorkLogProps { + - readonly activities: ReadonlyArray; + - readonly anchorKey: string; + - readonly copiedRowId: string | null; + -+ readonly environmentId: EnvironmentId; + -+ readonly expanded: boolean; + - readonly expandedRows: Readonly>; + - readonly rowSizing: ReturnType; + - readonly scrollPositions: Map; + - readonly iconSubtleColor: ColorValue; + - readonly onCopyRow: (rowId: string, value: string) => void; + -- readonly onToggleRow: (rowId: string, anchorKey: string) => void; + -- readonly renderImage: MarkdownImageRenderer; + -+ readonly onToggleRow: (rowId: string) => void; + -+ readonly workspaceRoot?: string | null; + - }) { + -- const rows = visibleWorkLogActivities(props.activities).map((activity) => ({ + -- ...activity, + -- detail: compactActivityDetail(activity.detail), + -- })); + -+ const colorScheme = useColorScheme(); + -+ const pressedBackground = colorScheme === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.035)"; + -+ const rows = props.activities; + - + - export function ThreadWorkLog(props: ThreadWorkLogProps) { + - const renderRow = useCallback( + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: export function ThreadWorkLog(props: ThreadWorkLogProps) { + - + - {rows.map((row) => { + - const expanded = props.expandedRows[row.id] ?? false; + -- const canExpand = row.canExpand; + -- const fullDetail = expanded ? row.getFullDetail() : null; + -- const displayText = row.detail ? `${row.summary} ${row.detail}` : row.summary; + -+ const canExpand = row.fullDetail !== null; + -+ const detail = compactActivityDetail(row.detail); + -+ const displayText = detail ? `${row.summary} ${detail}` : row.summary; + - const iconIsDestructive = row.icon === "alert" || row.icon === "warning"; + - + - return ( + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: export function ThreadWorkLog(props: ThreadWorkLogProps) { + - > + - {row.summary} + - + -- {row.detail ? ( + -- {row.detail} + -+ {detail ? ( + -+ {detail} + - ) : null} + - + - + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: export function ThreadWorkLog(props: ThreadWorkLogProps) { + - + - + - + -- {fullDetail ? ( + -- + -- + -- + -- {fullDetail} + -- + -- + -+ {expanded && row.fullDetail ? ( + -+ + -+ + - + - ) : null} + - + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: export function ThreadWorkGroupToggle(props: { + - readonly onlyToolActivities: boolean; + - readonly onToggle: () => void; + - }) { + -+ const colorScheme = useColorScheme(); + -+ const pressedBackground = colorScheme === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.035)"; + - const noun = props.onlyToolActivities + - ? props.hiddenCount === 1 + - ? "tool call" + - + ## apps/mobile/src/lib/threadActivityInspector.test.ts (new) ## + @@ + +import { EMPTY_V2_ITEM_SUPPORT } from "@t3tools/client-runtime/state/item-support"; + 66: af6028c82dc ! 65: 06c57e49daa Expose V2 thread workflows on mobile + @@ apps/mobile/src/features/threads/ThreadRelationshipsBanner.tsx (new) + + ); + +} + + - ## apps/mobile/src/features/threads/thread-work-log.tsx ## + -@@ + - import * as Haptics from "expo-haptics"; + - import { SymbolView, type SFSymbol } from "expo-symbols"; + --import type { EnvironmentId } from "@t3tools/contracts"; + -+import type { EnvironmentId, ThreadId } from "@t3tools/contracts"; + -+import { useRouter } from "expo-router"; + - import { LayoutAnimation, Pressable, useColorScheme, View } from "react-native"; + - + - import { AppText as Text } from "../../components/AppText"; + - import { scaledTypographyLineHeight } from "../../lib/appearancePreferences"; + - import { cn } from "../../lib/cn"; + --import { THREAD_WORK_ROW_MIN_HEIGHT, type deriveThreadWorkLogSizing } from "../../lib/layout"; + -+import { buildThreadRoutePath } from "../../lib/routes"; + - import type { ThreadFeedActivity } from "../../lib/threadActivity"; + -+import { useV2ItemSupport } from "../../state/v2-item-support"; + - import { ThreadActivityInspector } from "./ThreadActivityInspector"; + - + - const WORK_LOG_LAYOUT_ANIMATION = { + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: function workRowSymbolName(icon: ThreadFeedActivity["icon"]): AppSymbolName { + - } + - } + - + --// Entering fades only for rows created moments ago: rows remount whenever the + --// list scrolls them back into view, and old rows must not replay an entrance. + --const FRESH_ROW_WINDOW_MS = 3_000; + --function isFreshRow(createdAt: string): boolean { + -- const timestamp = Date.parse(createdAt); + -- return Number.isFinite(timestamp) && Date.now() - timestamp < FRESH_ROW_WINDOW_MS; + --} + -+function ThreadActivityThreadLink(props: { + -+ readonly activity: ThreadFeedActivity; + -+ readonly environmentId: EnvironmentId; + -+ readonly iconColor: import("react-native").ColorValue; + -+}) { + -+ const row = props.activity.projectedItem; + -+ const support = useV2ItemSupport({ + -+ environmentId: props.environmentId, + -+ sourceThreadId: row.sourceThreadId, + -+ sourceItemId: row.sourceItemId, + -+ }); + -+ const router = useRouter(); + -+ const item = row.item; + -+ let targetThreadId: ThreadId | null = null; + -+ let label = "Open related thread"; + -+ + -+ if (item.type === "thread_created") { + -+ targetThreadId = item.targetThreadId; + -+ label = "Open created thread"; + -+ } else if (item.type === "subagent") { + -+ targetThreadId = support.subagent?.childThreadId ?? item.childThreadId; + -+ label = "Open subagent thread"; + -+ } else if (item.type === "fork") { + -+ targetThreadId = + -+ item.targetThreadId === row.sourceThreadId && item.source.type === "run" + -+ ? item.source.threadId + -+ : item.targetThreadId; + -+ label = targetThreadId === item.targetThreadId ? "Open forked thread" : "Open parent thread"; + -+ } + - + --// Tool-like activities with a neutral status carry no signal worth a row. + --export function visibleWorkLogActivities( + -- activities: ReadonlyArray, + --): ReadonlyArray { + -- return activities.filter((activity) => !(activity.toolLike && activity.status === "neutral")); + --} + -+ if (targetThreadId === null) return null; + - + --// Pre-measurement heights for the feed's getFixedItemSize. Collapsed work-log + --// rows are single-line (numberOfLines={1}) inside a min-height that stays + --// taller than the text at every supported base font size (text-xs reaches + --// 23px at the 22pt maximum, under the 32px min-h-8), so row height is + --// deterministic. The "work log" label has no such clamp — its height follows + --// the scaled text-2xs line height. Values mirror the classNames below — keep + --// them in sync; a mismatch only costs a one-time correction on measure. + --const WORK_ROW_HEIGHT = 32; // min-h-8 + --const WORK_ROW_GAP = 1; // gap-px + --const WORK_LOG_HEADER_PADDING = 2; // pb-0.5 under the "work log" label + --const WORK_LOG_BOTTOM_MARGIN = 4; // mb-1 + -- + --export const WORK_GROUP_TOGGLE_HEIGHT = THREAD_WORK_ROW_MIN_HEIGHT; + -- + --export function collapsedWorkLogHeight( + -- activities: ReadonlyArray, + -- baseFontSize: number, + --): number { + -- const rows = visibleWorkLogActivities(activities); + -- if (rows.length === 0) { + -- return 0; + -- } + -- const onlyToolRows = rows.every((row) => row.toolLike); + -- const headerHeight = + -- scaledTypographyLineHeight(MOBILE_TYPOGRAPHY.caption, baseFontSize) + WORK_LOG_HEADER_PADDING; + - return ( + -- WORK_LOG_BOTTOM_MARGIN + + -- (onlyToolRows ? 0 : headerHeight) + + -- rows.length * WORK_ROW_HEIGHT + + -- (rows.length - 1) * WORK_ROW_GAP + -+ { + -+ void Haptics.selectionAsync(); + -+ router.push( + -+ buildThreadRoutePath({ + -+ environmentId: props.environmentId, + -+ threadId: targetThreadId, + -+ }), + -+ ); + -+ }} + -+ className="mx-2 mb-2 min-h-9 flex-row items-center justify-center gap-1.5 rounded-lg border border-neutral-300/50 px-2 dark:border-white/[0.08]" + -+ > + -+ {label} + -+ + -+ + - ); + - } + - + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: export function ThreadWorkLog(props: ThreadWorkLogProps) { + - const iconIsDestructive = row.icon === "alert" || row.icon === "warning"; + - + - return ( + -- + - + - + - ) : null} + -- + -+ {row.prominent ? ( + -+ + -+ ) : null} + -+ + - ); + - })} + - + - + ## apps/mobile/src/lib/threadActivity.test.ts ## + @@ apps/mobile/src/lib/threadActivity.test.ts: describe("buildThreadFeed", () => { + "inherited", + 67: 2e05af67463 ! 66: e70b8940053 Retire V1 client orchestration parity + @@ apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts + */ + +import type { CheckpointRef, ProjectId, ThreadId } from "@t3tools/contracts"; + import type { + +- ApprovalRequestId, + - CheckpointRef, + OrchestrationCheckpointSummary, + OrchestrationProject, + OrchestrationProjectShell, + @@ apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts: import type { + + OrchestrationSearchThreadsResult, + + OrchestrationShellSnapshot, + + OrchestrationThread, + +- OrchestrationThreadActivity, + OrchestrationThreadDetailSnapshot, + OrchestrationThreadDetailWindow, + OrchestrationThreadShell, + @@ apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts: import type { + import * as Context from "effect/Context"; + import type * as Option from "effect/Option"; + import type * as Effect from "effect/Effect"; + +@@ apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts: export interface ProjectionThreadDetailQuery { + + * ProjectionSnapshotQueryShape - Service API for read-model snapshots. + + */ + + export interface ProjectionSnapshotQueryShape { + +- /** Read the latest request or resolution without loading the thread history. */ + +- readonly getUserInputActivity: (input: { + +- readonly threadId: ThreadId; + +- readonly requestId: ApprovalRequestId; + +- }) => Effect.Effect, ProjectionRepositoryError>; + +- + + /** + + * Read the lightweight command snapshot used to bootstrap the in-memory + + * orchestration engine without hydrating message/activity/checkpoint bodies. + + ## apps/server/src/orchestration/commandInvariants.ts ## + @@ + @@ apps/server/src/orchestration/decider.ts + +import { EventId } from "@t3tools/contracts"; + import { + - EventId, + +- MessageId, + +- UserInputRequestedPayload, + type OrchestrationCommand, + type OrchestrationEvent, + type OrchestrationReadModel, + - type OrchestrationThread, + +- type OrchestrationThreadActivity, + -} from "@t3tools/contracts"; + +} from "@t3tools/contracts/legacy-orchestration"; + import * as DateTime from "effect/DateTime"; + import * as Crypto from "effect/Crypto"; + import * as Effect from "effect/Effect"; + +-import * as Schema from "effect/Schema"; + +-import * as Option from "effect/Option"; + +-import * as Predicate from "effect/Predicate"; + + import type * as PlatformError from "effect/PlatformError"; + + + + import { + +@@ apps/server/src/orchestration/decider.ts: import { projectEvent } from "./projector.ts"; + + import { threadHasQueuedTurnStart } from "./ThreadSettlementPolicy.ts"; + + + + const nowIso = Effect.map(DateTime.now, DateTime.formatIso); + +-const decodeUserInputRequestedPayload = Schema.decodeUnknownOption(UserInputRequestedPayload); + + + + /** + + * Blocked-on-you work derived from the thread's retained activities: an + +@@ apps/server/src/orchestration/decider.ts: function isStaleRequestFailureDetail(payload: Record | null): b + + } + + + + // Scans the read model's activities, which the projector caps at the most + +-// recent 500 plus pending async questions. Async questions remain actionable + +-// while the agent works, so they must not expire with the activity window. + ++// recent 500. That bound is safe here: an OPEN approval/user-input request + ++// blocks its turn, so the thread cannot accumulate hundreds of later + ++// activities while one is outstanding — a request that has scrolled out of + ++// the window is one whose turn kept running, i.e. it was resolved or went + ++// stale. (The projection pipeline's pendingApprovalCount reads the same + ++// capped stream and stays consistent with this view.) + + function hasOpenBlockingRequest(thread: { + + readonly activities: ReadonlyArray<{ readonly kind: string; readonly payload: unknown }>; + + }): boolean { + +@@ apps/server/src/orchestration/decider.ts: const decideCommandSequence = Effect.fn("decideCommandSequence")(function* ({ + + export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(function* ({ + + command, + + readModel, + +- userInputActivity, + + }: { + + readonly command: OrchestrationCommand; + + readonly readModel: OrchestrationReadModel; + +- readonly userInputActivity?: OrchestrationThreadActivity; + + }): Effect.fn.Return< + + DecideOrchestrationCommandResult, + + OrchestrationCommandRejection | PlatformError.PlatformError, + @@ apps/server/src/orchestration/decider.ts: export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" + title: command.title, + workspaceRoot: command.workspaceRoot, + defaultModelSelection: command.defaultModelSelection ?? null, + -<<<<<<< HEAD + - faviconPath: null, + +- projectIcon: null, + - scripts: [], + -======= + scripts: command.scripts ?? [], + @@ apps/server/src/orchestration/decider.ts: export const decideOrchestrationComman + createdAt: command.createdAt, + updatedAt: command.createdAt, + }, + +@@ apps/server/src/orchestration/decider.ts: export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" + + ...(command.defaultThreadEnvMode !== undefined + + ? { defaultThreadEnvMode: command.defaultThreadEnvMode } + + : {}), + +- ...(command.autoPull !== undefined ? { autoPull: command.autoPull } : {}), + + ...(command.faviconPath !== undefined ? { faviconPath: command.faviconPath } : {}), + +- ...(command.projectIcon !== undefined ? { projectIcon: command.projectIcon } : {}), + + ...(command.scripts !== undefined ? { scripts: command.scripts } : {}), + + updatedAt: occurredAt, + + }, + +@@ apps/server/src/orchestration/decider.ts: export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" + + type: "thread.settled" as const, + + payload: { + + threadId: command.threadId, + +- settledAt: alreadySettled + +- ? thread.settledAt + +- : command.type === "thread.auto-settle" + +- ? command.settledAt + +- : occurredAt, + ++ settledAt: alreadySettled ? thread.settledAt : occurredAt, + + // A re-emission is a projected no-op: keep the existing updatedAt + + // so duplicate settles neither rewind nor churn ordering. A fresh + + // settle stamps the command time. + +@@ apps/server/src/orchestration/decider.ts: export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" + + } + + + + case "thread.user-input.respond": { + +- const thread = yield* requireThread({ + ++ yield* requireThread({ + + readModel, + + command, + + threadId: command.threadId, + + }); + +- const request = userInputActivity; + +- if ( + +- request && + +- Predicate.isObject(request.payload) && + +- request.payload.responseMode === "message" + +- ) { + +- const payload = decodeUserInputRequestedPayload(request.payload); + +- if (request.kind !== "user-input.requested" || Option.isNone(payload)) { + +- return yield* new OrchestrationCommandInvariantError({ + +- commandType: command.type, + +- detail: "This question has already been answered.", + +- }); + +- } + +- const replies: string[] = []; + +- for (const question of payload.value.questions) { + +- const answer = command.answers[question.id]; + +- if (typeof answer !== "string" || answer.trim().length === 0) { + +- return yield* new OrchestrationCommandInvariantError({ + +- commandType: command.type, + +- detail: "Answer each question before sending.", + +- }); + +- } + +- replies.push(`${question.question}\n${answer.trim()}`); + +- } + +- // Commit the answer and its message together. The normal turn path + +- // steers a running agent or resumes an idle session. + +- return yield* decideCommandSequence({ + +- readModel, + +- commands: [ + +- { + +- type: "thread.activity.append", + +- commandId: command.commandId, + +- threadId: command.threadId, + +- createdAt: command.createdAt, + +- activity: { + +- id: EventId.make(`async-answer:${command.requestId}`), + +- kind: "user-input.resolved", + +- summary: "User input submitted", + +- tone: "info", + +- turnId: request.turnId, + +- createdAt: command.createdAt, + +- payload: { + +- requestId: command.requestId, + +- responseMode: "message", + +- answers: command.answers, + +- }, + +- }, + +- }, + +- { + +- type: "thread.turn.start", + +- commandId: command.commandId, + +- threadId: command.threadId, + +- createdAt: command.createdAt, + +- runtimeMode: thread.runtimeMode, + +- interactionMode: thread.interactionMode, + +- message: { + +- messageId: MessageId.make(`async-answer:${command.requestId}`), + +- role: "user", + +- text: replies.join("\n\n"), + +- attachments: [], + +- }, + +- }, + +- ], + +- }); + +- } + + return { + + ...(yield* withEventBase({ + + aggregateKind: "thread", + + ## apps/server/src/orchestration/projector.ts ## + @@ + @@ apps/server/src/orchestration/projector.ts + +} from "@t3tools/contracts/legacy-orchestration"; + import * as Effect from "effect/Effect"; + import * as Schema from "effect/Schema"; + - + + import * as Predicate from "effect/Predicate"; + + ## apps/server/src/persistence/Layers/OrchestrationEventStore.ts ## + @@ + @@ apps/server/src/ws.ts: const RPC_REQUIRED_SCOPE = new Map void; + + availableEnvironments?: readonly EnvironmentOption[]; + + onEnvironmentChange?: (environmentId: EnvironmentId) => void; + +- composerControlsHostRef?: (element: HTMLDivElement | null) => void; + +- contextStripVisible?: boolean; + + } + + + + interface MobileRunContextSelectorProps { + +@@ apps/web/src/components/BranchToolbar.tsx: const MobileRunContextSelector = memo(function MobileRunContextSelector({ + + ? resolveEnvModeLabel("worktree") + + : resolveCurrentWorkspaceLabel(activeWorktreePath); + + const isLocked = envLocked || envModeLocked; + ++ const EnvironmentIcon = activeEnvironment?.isPrimary ? MonitorIcon : CloudIcon; + + const icon = showEnvironmentIndicator ? ( + + // Button's base styles apply `-mx-0.5` to descendant SVGs, which eats 4px + + // out of whatever gap we set. mx-0! cancels that so gap-0.5 reads as 2px. + + + +- + ++ + + + + + + ) : ( + +@@ apps/web/src/components/BranchToolbar.tsx: const MobileRunContextSelector = memo(function MobileRunContextSelector({ + + const triggerContent = ( + + <> + + {icon} + +- + +- + +- {showEnvironmentIndicator ? (activeEnvironment?.label ?? "Run on") : workspaceLabel} + +- + ++ + ++ {showEnvironmentIndicator ? (activeEnvironment?.label ?? "Run on") : workspaceLabel} + + + + + + ); + + + + if (isLocked) { + + return ( + +- + ++ + + {triggerContent} + + + + ); + +@@ apps/web/src/components/BranchToolbar.tsx: const MobileRunContextSelector = memo(function MobileRunContextSelector({ + + + + } + +- className="min-w-0 max-w-[48%] flex-initial justify-start font-normal text-muted-foreground/70 text-xs! hover:text-foreground/80" + +- data-composer-context-control + ++ className="min-w-0 max-w-[48%] flex-1 justify-start text-muted-foreground/70 hover:text-foreground/80 md:hidden" + + > + + {triggerContent} + + + + + +- + ++ + + {showEnvironmentPicker && availableEnvironments && onEnvironmentChange ? ( + + <> + + + +@@ apps/web/src/components/BranchToolbar.tsx: const MobileRunContextSelector = memo(function MobileRunContextSelector({ + + value={environmentId} + + onValueChange={(value) => onEnvironmentChange(value as EnvironmentId)} + + > + +- {availableEnvironments.map((env) => ( + +- + +- + +- + +- {env.label} + +- + +- + +- ))} + ++ {availableEnvironments.map((env) => { + ++ const Icon = env.isPrimary ? MonitorIcon : CloudIcon; + ++ return ( + ++ + ++ + ++ + ++ {env.label} + ++ + ++ + ++ ); + ++ })} + + + + + + + +@@ apps/web/src/components/BranchToolbar.tsx: const MobileRunContextSelector = memo(function MobileRunContextSelector({ + + * the expanded width without remembered values that could go stale or latch + + * the strip compact. A small hysteresis keeps the boundary from flapping. + + */ + ++const COMPACT_EXPAND_HYSTERESIS_PX = 16; + + const COMPOSER_CONTEXT_MOTION_DURATION_MS = 180; + + const COMPOSER_CONTEXT_MOTION_EASING = "cubic-bezier(0.32, 0.72, 0, 1)"; + + const COMPOSER_CONTEXT_CONTROL_SELECTOR = "[data-composer-context-control]"; + +@@ apps/web/src/components/BranchToolbar.tsx: function useLabelsOverflow(element: HTMLDivElement | null): boolean { + + let counted = 0; + + for (const child of parent.children) { + + if (!(child instanceof HTMLElement)) continue; + +- if (child.offsetWidth === 0) continue; + +- const style = getComputedStyle(child); + +- const position = style.position; + ++ if (child.offsetWidth <= 1) continue; + ++ const position = getComputedStyle(child).position; + + if (position === "absolute" || position === "fixed") continue; + +- width += + +- child.offsetWidth + + +- (Number.parseFloat(style.marginInlineStart) || 0) + + +- (Number.parseFloat(style.marginInlineEnd) || 0); + ++ width += child.offsetWidth; + + counted += 1; + + } + + return width + gap * Math.max(0, counted - 1); + +@@ apps/web/src/components/BranchToolbar.tsx: function useLabelsOverflow(element: HTMLDivElement | null): boolean { + + let groups = 0; + + for (const child of current.children) { + + if (!(child instanceof HTMLElement)) continue; + +- // The host itself flexes into all remaining room. Reserve the natural + +- // width of the controls inside it, blocks in overflow included, so Git + +- // labels compact before squeezing out the model picker. Reserving only + +- // the visible controls would let the labels expand into room the + +- // composer just freed, shrink the host, and hide the controls again. + +- const hostedControls = child.matches('[data-chat-resting-composer-controls-host="true"]') + +- ? child.querySelector('[data-chat-composer-resting-controls="true"]') + +- : null; + +- const hostedMeasurement = hostedControls + +- ? measureRestingComposerControls(hostedControls) + +- : null; + +- const width = hostedMeasurement + +- ? resolveRestingComposerControlsNaturalWidth(hostedMeasurement) + +- : contentWidth(hostedControls ?? child); + ++ const width = contentWidth(child); + + if (width <= 1) continue; + +- groups += 1; + + needed += width; + ++ groups += 1; + + } + + needed += stripGap * Math.max(0, groups - 1); + + for (const label of current.querySelectorAll("[data-composer-label]")) { + +@@ apps/web/src/components/BranchToolbar.tsx: function useLabelsOverflow(element: HTMLDivElement | null): boolean { + + needed += Math.max(0, textWidth - label.clientWidth); + + } + + } + +- const nextOverflows = resolveContextStripLabelsCompact({ + +- compact, + +- neededWidth: needed, + +- availableWidth: available, + +- }); + ++ const nextOverflows = compact + ++ ? needed > available - COMPACT_EXPAND_HYSTERESIS_PX + ++ : needed > available; + + if (nextOverflows !== compact) { + + pendingControlRectsRef.current = new Map( + + Array.from(current.querySelectorAll(COMPOSER_CONTEXT_CONTROL_SELECTOR)).map( + @@ apps/web/src/components/BranchToolbar.tsx: export const BranchToolbar = memo(function BranchToolbar({ + + onComposerFocusRequest, + + availableEnvironments, + + onEnvironmentChange, + +- composerControlsHostRef, + +- contextStripVisible = true, + + }: BranchToolbarProps) { + + const threadRef = useMemo( + () => scopeThreadRef(environmentId, threadId), + [environmentId, threadId], + ); + @@ apps/web/src/components/BranchToolbar.tsx: export const BranchToolbar = memo(fun + const draftThread = useComposerDraftStore((store) => + draftId ? store.getDraftSession(draftId) : store.getDraftThreadByRef(threadRef), + ); + +@@ apps/web/src/components/BranchToolbar.tsx: export const BranchToolbar = memo(function BranchToolbar({ + + activeEnvironment: activeEnvironmentOption, + + canPickEnvironment: showEnvironmentPicker, + + }); + ++ const isMobile = useIsMobile(); + + const [stripElement, setStripElement] = useState(null); + + const labelsOverflow = useLabelsOverflow(stripElement); + + + +@@ apps/web/src/components/BranchToolbar.tsx: export const BranchToolbar = memo(function BranchToolbar({ + + + +- {showGitControls ? ( + +-
+ +- + +-
+ +- ) : null} + +- {showGitControls || showEnvironmentIndicator ? ( + +-
+ ++ {isMobile && showGitControls ? ( + ++ + ++ ) : ( + ++
+ + {showEnvironmentIndicator && availableEnvironments && ( + + <> + + + + ) : null} + +
+ +- ) : null} + +- + +- {composerControlsHostRef ? ( + +- // The host takes whatever the workspace and branch controls leave + +- // over, in both strip layouts, so a collapsed composer can show its + +- // model and mode controls wherever they fit. + +-
+ +- ) : null} + ++ )} + + + + {showGitControls ? ( + + >(() => { + - if (!serverMessages) return []; + -- return serverMessages.map((message) => { + -- if (!message.attachments || message.attachments.length === 0) { + -- return message; + -- } + -- return { + -- ...message, + -- attachments: message.attachments.map((attachment) => { + -- const previewUrl = serverAttachmentUrlById.get(attachment.id); + -- return previewUrl ? { ...attachment, previewUrl } : attachment; + -- }), + -- }; + -- }); + -- }, [serverAttachmentUrlById, serverMessages]); + +- return serverMessages.map((message) => + +- projectServerMessagePreviews(message, (attachment) => + +- serverAttachmentUrlById.get(attachment.id), + +- ), + +- ); + +- }, [projectServerMessagePreviews, serverAttachmentUrlById, serverMessages]); + useEffect(() => { + - if (typeof Image === "undefined" || displayServerMessages.length === 0) { + + if (typeof Image === "undefined" || serverVisibleTurnItems.length === 0) { + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + - const serverMessagesWithPreviewHandoff = + - Object.keys(attachmentPreviewHandoffByMessageId).length === 0 + - ? messages + -- : // Spread only fires for the few messages that actually changed; + -- // unchanged ones early-return their original reference. + -- // In-place mutation would break React's immutable state contract. + -- messages.map((message) => { + +- : messages.map((message) => { + - if ( + - message.role !== "user" || + - !message.attachments || + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + - return message; + - } + - + -- let changed = false; + - let imageIndex = 0; + - const attachments = message.attachments.map((attachment) => { + - if (attachment.type !== "image") { + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + - } + - const handoffPreviewUrl = handoffPreviewUrls[imageIndex]; + - imageIndex += 1; + -- if (!handoffPreviewUrl || attachment.previewUrl === handoffPreviewUrl) { + -- return attachment; + -- } + -- changed = true; + -- return { + -- ...attachment, + -- previewUrl: handoffPreviewUrl, + -- }; + +- return handoffPreviewUrl; + - }); + -- + -- return changed ? { ...message, attachments } : message; + - }); + - + - if (optimisticUserMessages.length === 0) { + @@ apps/web/src/components/DiffPanel.tsx: import { + -import { useProject, useThread } from "../state/entities"; + +import { useProject, useThreadProjection, useThreadShell } from "../state/entities"; + import { resolveThreadRouteRef } from "../threadRoutes"; + - import { useClientSettings } from "../hooks/useSettings"; + + import { useClientSettings, useUpdateClientSettings } from "../hooks/useSettings"; + import { formatShortTimestamp } from "../timestampFormat"; + @@ apps/web/src/components/DiffPanel.tsx: export default function DiffPanel({ + select: (params) => resolveThreadRouteRef(params), + @@ apps/web/src/components/chat/ChatComposer.tsx: export const ChatComposer = memo( + composerFilesRef, + + ## apps/web/src/components/chat/MessagesTimeline.tsx ## + -@@ apps/web/src/components/chat/MessagesTimeline.tsx: import { + - import { LegendList, type LegendListRef } from "@legendapp/list/react"; + +@@ apps/web/src/components/chat/MessagesTimeline.tsx: import { LegendList, type LegendListRef } from "@legendapp/list/react"; + import { FileDiff } from "@pierre/diffs/react"; + + import { DiffWorkerPoolProvider } from "../DiffWorkerPoolProvider"; + import { + - deriveTimelineEntries, + + type TimelineEntry, + @@ apps/web/src/session-logic.ts: export function deriveTurnPlans( + - .find((thread) => thread.id === source.threadId) + - ?.proposedPlans.find((candidate) => candidate.id === source.planId); + - if (plan !== undefined) return toLatestProposedPlanState(plan); + -+ const sourceProjection = input.threads.find( + -+ (thread) => thread.id === source.threadId, + -+ )?.projection; + -+ const plan = sourceProjection?.plans.find( + -+ (candidate) => candidate.kind === "proposed_plan" && candidate.id === source.planId, + -+ ); + -+ if (sourceProjection !== undefined && plan?.kind === "proposed_plan") { + -+ return toLatestProposedPlanState(sourceProjection, plan); + -+ } + - } + +- } + - const activePlans = + - input.threads.find((thread) => thread.id === input.threadId)?.proposedPlans ?? []; + - return findLatestProposedPlan(activePlans, input.latestRun?.runId); + @@ apps/web/src/session-logic.ts: export function deriveTurnPlans( + - + -export function deriveWorkLogEntries(entries: ReadonlyArray): WorkLogEntry[] { + - return entries.map((entry) => ({ ...entry, sourceItemType: entry.itemType })); + +-} + +- + +-function timelineEntryFromMessage(message: ChatMessage): TimelineEntry { + +- return { + +- id: message.id, + +- kind: "message", + +- createdAt: message.createdAt, + +- message, + +- }; + +-} + +- + +-function timelineEntryFromProposedPlan(proposedPlan: ProposedPlan): TimelineEntry { + +- return { + +- id: proposedPlan.id, + +- kind: "proposed-plan", + +- createdAt: proposedPlan.createdAt, + +- proposedPlan, + +- }; + +-} + +- + +-function timelineEntryFromWork(workEntry: WorkLogEntry): TimelineEntry { + +- return { + +- id: workEntry.id, + +- kind: "work", + +- createdAt: workEntry.createdAt, + +- entry: workEntry, + +- }; + +-} + +- + +-function compareTimelineEntriesByCreatedAt(left: TimelineEntry, right: TimelineEntry): number { + +- return left.createdAt.localeCompare(right.createdAt); + +-} + +- + +-function timelineEntrySourceOrder(entry: TimelineEntry): number { + +- switch (entry.kind) { + +- case "message": + +- return 0; + +- case "proposed-plan": + +- return 1; + +- case "work": + +- return 2; + +- } + +-} + +- + +-function shouldTakePreviousTimelineEntry(previous: TimelineEntry, suffix: TimelineEntry): boolean { + +- const createdAtComparison = compareTimelineEntriesByCreatedAt(previous, suffix); + +- if (createdAtComparison !== 0) return createdAtComparison < 0; + +- // The original full derivation sorts a source-ordered array with a stable + +- // comparator. On a tie, messages precede plans, plans precede work, and an + +- // older item in the same source array precedes a newly appended item. + +- return timelineEntrySourceOrder(previous) <= timelineEntrySourceOrder(suffix); + +-} + +- + +-function hasExactArrayPrefix(previous: ReadonlyArray, next: ReadonlyArray): boolean { + +- if (previous === next) return true; + +- if (next.length < previous.length) return false; + +- for (let index = 0; index < previous.length; index += 1) { + +- if (previous[index] !== next[index]) return false; + +- } + +- return true; + +-} + +- + +-function mergeTimelineEntrySuffix( + +- previous: ReadonlyArray, + +- suffix: ReadonlyArray, + +-): TimelineEntry[] { + +- if (suffix.length === 0) return [...previous]; + +- const previousLast = previous.at(-1); + +- let suffixIsOrdered = true; + +- for (let index = 1; index < suffix.length; index += 1) { + +- if (compareTimelineEntriesByCreatedAt(suffix[index - 1]!, suffix[index]!) > 0) { + +- suffixIsOrdered = false; + +- break; + +- } + +- } + +- if ( + +- suffixIsOrdered && + +- (previousLast === undefined || shouldTakePreviousTimelineEntry(previousLast, suffix[0]!)) + +- ) { + +- return [...previous, ...suffix]; + +- } + +- + +- const merged: TimelineEntry[] = []; + +- let previousIndex = 0; + +- let suffixIndex = 0; + +- while (previousIndex < previous.length || suffixIndex < suffix.length) { + +- const previousEntry = previous[previousIndex]; + +- const suffixEntry = suffix[suffixIndex]; + +- if ( + +- previousEntry !== undefined && + +- (suffixEntry === undefined || shouldTakePreviousTimelineEntry(previousEntry, suffixEntry)) + +- ) { + +- merged.push(previousEntry); + +- previousIndex += 1; + +- } else if (suffixEntry !== undefined) { + +- merged.push(suffixEntry); + +- suffixIndex += 1; + +- } + +- } + +- return merged; + +-} + +- + +-/** Own one mapper per preview stage. Immutable messages retain unchanged preview objects. */ + +-export function createMessageAttachmentPreviewProjector() { + +- const attachmentsBySource = new WeakMap< + +- ReadonlyArray, + +- ReadonlyArray + +- >(); + +- const messagesBySource = new WeakMap(); + +- return ( + +- message: ChatMessage, + +- previewUrlFor: (attachment: ChatAttachment) => string | undefined, + +- ): ChatMessage => { + +- const source = message.attachments; + +- if (!source || source.length === 0) return message; + +- const previous = attachmentsBySource.get(source) ?? source; + +- let changed: ChatAttachment[] | undefined; + +- let hasOverrides = false; + +- for (const [index, attachment] of source.entries()) { + +- const previewUrl = previewUrlFor(attachment); + +- const sourceUrl = "previewUrl" in attachment ? attachment.previewUrl : undefined; + +- const previousAttachment = previous[index]!; + +- const previousUrl = + +- "previewUrl" in previousAttachment ? previousAttachment.previewUrl : undefined; + +- const next = + +- !previewUrl || previewUrl === sourceUrl + +- ? attachment + +- : previewUrl === previousUrl + +- ? previousAttachment + +- : { ...attachment, previewUrl }; + +- hasOverrides ||= next !== attachment; + +- if (next !== previousAttachment) { + +- changed ??= previous.slice(); + +- changed[index] = next; + +- } + +- } + +- const attachments = hasOverrides ? (changed ?? previous) : source; + +- attachmentsBySource.set(source, attachments); + +- if (attachments === source) { + +- messagesBySource.delete(message); + +- return message; + +- } + +- const previousMessage = messagesBySource.get(message); + +- if (previousMessage?.attachments === attachments) return previousMessage; + +- const result = { ...message, attachments }; + +- messagesBySource.set(message, result); + +- return result; + +- }; + +-} + +- + +-/** Text and update time do not change a streaming assistant message's timeline structure. */ + +-export function isStreamingMessageTextUpdate(previous: ChatMessage, next: ChatMessage): boolean { + +- if ( + +- previous.role !== "assistant" || + +- next.role !== "assistant" || + +- !previous.streaming || + +- !next.streaming + +- ) { + +- return false; + +- } + +- const { text: _previousText, updatedAt: _previousUpdatedAt, ...previousMetadata } = previous; + +- const { text: _nextText, updatedAt: _nextUpdatedAt, ...nextMetadata } = next; + +- return shallow(previousMetadata, nextMetadata); + +-} + +- + +-function replaceStreamingTimelineMessages( + +- messages: ReadonlyArray, + +- previous: TimelineEntriesProjection, + +-): TimelineEntry[] | null { + +- if (messages.length !== previous.messages.length) return null; + +- const replacements = new Map(); + +- for (const [index, message] of messages.entries()) { + +- const previousMessage = previous.messages[index]!; + +- if (message === previousMessage) continue; + +- if (!isStreamingMessageTextUpdate(previousMessage, message)) return null; + +- replacements.set(previousMessage, message); + +- } + +- if (replacements.size === 0) return previous.entries; + +- return previous.entries.map((entry) => { + +- const replacement = entry.kind === "message" ? replacements.get(entry.message) : undefined; + +- return replacement ? timelineEntryFromMessage(replacement) : entry; + +- }); + +-} + +- + +-/** Reuse ordered entries across immutable stream updates. Other changes keep the full sort. */ + +-export function deriveTimelineEntriesWithState( + +- messages: ReadonlyArray, + +- proposedPlans: ReadonlyArray, + +- workEntries: ReadonlyArray, + +- previous: TimelineEntriesProjection | null = null, + +-): TimelineEntriesProjection { + +- if ( + +- previous !== null && + +- previous.proposedPlans.length === proposedPlans.length && + +- previous.workEntries.length === workEntries.length && + +- hasExactArrayPrefix(previous.proposedPlans, proposedPlans) && + +- hasExactArrayPrefix(previous.workEntries, workEntries) + +- ) { + +- const entries = replaceStreamingTimelineMessages(messages, previous); + +- if (entries !== null) return { messages, proposedPlans, workEntries, entries }; + +- } + +- const canAppend = + +- previous !== null && + +- hasExactArrayPrefix(previous.messages, messages) && + +- hasExactArrayPrefix(previous.proposedPlans, proposedPlans) && + +- hasExactArrayPrefix(previous.workEntries, workEntries); + +- + +- if (canAppend) { + +- const messageRows = messages.slice(previous.messages.length).map(timelineEntryFromMessage); + +- const proposedPlanRows = proposedPlans + +- .slice(previous.proposedPlans.length) + +- .map(timelineEntryFromProposedPlan); + +- const workRows = workEntries.slice(previous.workEntries.length).map(timelineEntryFromWork); + +- const suffix = [...messageRows, ...proposedPlanRows, ...workRows].toSorted( + +- compareTimelineEntriesByCreatedAt, + ++ const sourceProjection = input.threads.find( + ++ (thread) => thread.id === source.threadId, + ++ )?.projection; + ++ const plan = sourceProjection?.plans.find( + ++ (candidate) => candidate.kind === "proposed_plan" && candidate.id === source.planId, + + ); + +- return { + +- messages, + +- proposedPlans, + +- workEntries, + +- entries: mergeTimelineEntrySuffix(previous.entries, suffix), + +- }; + ++ if (sourceProjection !== undefined && plan?.kind === "proposed_plan") { + ++ return toLatestProposedPlanState(sourceProjection, plan); + ++ } + + } + +- + +- const messageRows = messages.map(timelineEntryFromMessage); + +- const proposedPlanRows = proposedPlans.map(timelineEntryFromProposedPlan); + +- const workRows = workEntries.map(timelineEntryFromWork); + +- return { + +- messages, + +- proposedPlans, + +- workEntries, + +- entries: [...messageRows, ...proposedPlanRows, ...workRows].toSorted( + +- compareTimelineEntriesByCreatedAt, + +- ), + +- }; + + const activeProjection = input.threads.find((thread) => thread.id === input.threadId)?.projection; + + return findLatestProposedPlan(activeProjection ?? null, input.latestRun?.runId); + } + 68: 4d8e17808be = 67: 1ee6b0622eb Add iOS associated domains for Clerk + 69: db9310c2f62 = 68: 569c448f009 Map Grok task envelopes to subagent lineage + 70: 9f069920613 = 69: 4a7e85f0fca Adopt userdata-v2 and subagent activity mapping + 71: 4313ad89dd3 = 70: 30d6cf06ec9 Map nested Codex subagent threads correctly + 72: 0eb1fc59abf = 71: 47f269d4364 Clarify thread relationship icons and ordering + 73: 036f3f9daf4 = 72: aa9c46184f2 Keep persistent cards visible in folded turns + 74: f0bd8850aa2 ! 73: f8579194c5a Require Cursor API key for provider checks + @@ apps/server/src/provider/Layers/CursorProvider.ts: import { causeErrorTag } from + buildBooleanOptionDescriptor, + buildSelectOptionDescriptor, + buildServerProvider, + +- COMPACT_SLASH_COMMAND, + - collectStreamAsString, + - isCommandMissingCause, + providerModelsFromSettings, + @@ apps/server/src/provider/Layers/CursorProvider.ts: function joinProviderMessages + export function buildCursorProviderSnapshot(input: { + readonly checkedAt: string; + readonly cursorSettings: CursorSettings; + +@@ apps/server/src/provider/Layers/CursorProvider.ts: export function buildCursorProviderSnapshot(input: { + + input.cursorSettings.customModels, + + EMPTY_CAPABILITIES, + + ), + +- slashCommands: [COMPACT_SLASH_COMMAND], + + probe: { + + installed: true, + + version: input.parsed.version, + @@ apps/server/src/provider/Layers/CursorProvider.ts: function hasOwn(record: object, key: string): boolean { + return Object.prototype.hasOwnProperty.call(record, key); + } + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: import { useCopyToCli + +import { Collapsible, CollapsibleContent } from "../ui/collapsible"; + import { DraftInput } from "../ui/draft-input"; + import { Popover, PopoverPopup, PopoverTrigger } from "../ui/popover"; + - import { ScrollArea } from "../ui/scroll-area"; + ++import { ScrollArea } from "../ui/scroll-area"; + import { Switch } from "../ui/switch"; + +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../ui/table"; + import { stackedThreadToast, toastManager } from "../ui/toast"; + import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; + -import type { DriverOption } from "./providerDriverMeta"; + --import { providerSettingsTabClassName } from "./providerSettingsTabs"; + +import type { DriverOption, ProviderEnvironmentFieldDefinition } from "./providerDriverMeta"; + import { ProviderSettingsForm } from "./ProviderSettingsForm"; + import { ProviderModelsSection } from "./ProviderModelsSection"; + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: import { useCopyToCli + +import { ProviderInstanceIcon } from "../chat/ProviderInstanceIcon"; + import { ProviderAccentColorPicker } from "./ProviderAccentColorPicker"; + import { RedactedSensitiveText } from "./RedactedSensitiveText"; + +-import { SettingsRow, SettingsSection } from "./settingsLayout"; + import { + -@@ apps/web/src/components/settings/ProviderInstanceCard.tsx: import { + - + - const ENVIRONMENT_VARIABLE_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/; + - + --/** Label-left field grid for the Configuration tab: one row per field. */ + --const PROVIDER_FIELD_GRID_CLASS_NAME = + -- "grid gap-x-4 gap-y-2.5 sm:grid-cols-[8rem_minmax(0,1fr)] sm:items-start"; + --/** Full-width divider row that names the group of fields below it. */ + --const PROVIDER_FIELD_GROUP_LABEL_CLASS_NAME = + -- "col-span-full mt-1 border-t border-border/60 pt-2.5 text-[11px] text-muted-foreground"; + -- + - let environmentVariableDraftId = 0; + - const nextEnvironmentVariableDraftId = () => `provider-env-${environmentVariableDraftId++}`; + - + + getProviderVersionAdvisoryPresentation, + + PROVIDER_STATUS_STYLES, + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: function makeEnvironmentDraftRow( + }; + } + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: function ProviderEnvi + - ]); + - + return ( + --
+ +-
+ - {rows.map((variable, index) => ( + -
+ - updateVariable(variable.id, { name: name.trim() })} + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: function ProviderEnvi + - = + - + - updateVariable(variable.id, { value })} + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: function ProviderEnvi + + -
+ - ))} + --
+ +-
+ +- {rows.length > 0 ? ( + +- + +- Sensitive values are stored separately and never returned to the app. + +- + + ) : null} + - + -- + -- {rows.length === 0 + -- ? "API keys, base URLs, or other per-instance CLI settings." + -- : "Sensitive values are stored separately and never returned to the app."} + -- + -+ ) : null} +
+ -
+ + {props.field.description ? ( + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: interface ProviderIns + * instance slots use `undefined` — they can't be deleted without losing + * the slot, and their "reset to defaults" affordance lives on an outer + * reset button instead. Explicit `| undefined` in the type accommodates + +@@ apps/web/src/components/settings/ProviderInstanceCard.tsx: interface ProviderInstanceCardProps { + + * omit it. + + */ + + readonly headerAction?: ReactNode | undefined; + +- readonly setup?: ReactNode; + + readonly hiddenModels: ReadonlyArray; + + readonly favoriteModels: ReadonlyArray; + + readonly modelOrder: ReadonlyArray; + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: interface ProviderInstanceCardProps { + } + + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: interface ProviderIns + onUpdate, + onDelete, + headerAction, + +- setup, + + hiddenModels, + + favoriteModels, + + modelOrder, + +@@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function ProviderInstanceCard({ + + onRunUpdate, + + isUpdating = false, + + }: ProviderInstanceCardProps) { + ++ const [activeTab, setActiveTab] = useState<"configuration" | "models">("configuration"); + + const enabled = resolveProviderInstanceEnabled(instance); + + // A locally disabled provider reads "Disabled" with a muted dot even if its + + // last server status is stale. Enabled providers use the server status. + +@@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function ProviderInstanceCard({ + + ? getProviderSummary(liveProvider) + + : { headline: "Disabled", detail: null }; + + const authEmail = liveProvider?.auth.email?.trim(); + ++ // The editor header folds the account email into the status line — + ++ // "Authenticated as · " — with the email redacted until its + ++ // reveal toggle is clicked. + + const isAuthenticated = enabled && liveProvider?.auth.status === "authenticated"; + + const authLabel = + + enabled && liveProvider?.auth.status === "authenticated" + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function ProviderInstanceCard({ + const driverKind: ProviderDriverKind | null = isProviderDriverKind(instance.driver) + ? instance.driver + : null; + -- const visibleTab = driverOption === undefined ? "configuration" : activeTab; + - + - const customModels = readConfigStringArray(instance.config, "customModels"); + +- const customModels = + +- instance.driver === "antigravity" ? [] : readConfigStringArray(instance.config, "customModels"); + ++ + ++ const customModels = readConfigStringArray(instance.config, "customModels"); + + const environmentFields = driverOption?.environmentFields ?? []; + + const environmentFieldNames = new Set(environmentFields.map((field) => field.name)); + + const genericEnvironment = providerEnvironmentWithoutNames( + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function Provi + liveModels: liveProvider?.models, + customModels, + }); + -- const hiddenModelCount = modelsForDisplay.filter( + -- (model) => !model.isCustom && hiddenModels.includes(model.slug), + -- ).length; + - + ++ + const updateDisplayName = (value: string) => { + const trimmed = value.trim(); + + const { displayName: _omit, ...rest } = instance; + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function ProviderInstanceCard({ + ); + }; + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function Provi + + + ); + + - const titleHeadNode = ( + -@@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function ProviderInstanceCard({ + - + - ); + - + - const titleTailNode = headerAction ? ( + - {headerAction} + - ) : null; + ++ const titleHeadNode = ( + ++ <> + ++ {titleIconNode} + ++

+ ++ {displayName} + ++

+ ++ {String(instanceId) !== String(instance.driver) ? ( + ++ + ++ {instanceId} + ++ + ++ ) : null} + ++ {driverOption?.badgeLabel ? ( + ++ + ++ {driverOption.badgeLabel} + ++ + ++ ) : null} + ++ + ++ ); + ++ + + const titleTailNode = ( + + <> + + {headerAction ? ( + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function Provi + const versionCodeNode = versionLabel ? ( + {versionLabel} + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function ProviderInstanceCard({ + + statusKey === "warning" || statusKey === "error" ? ( + + + + ) : null; + ++ const statusHeadlineNode = {summary.headline}; + + // Trouble states carry the server's explanation (a failed probe, a shadow + + // home entry that is not a symlink, a missing binary). Show it wherever the + + // headline shows so the user can act without opening the editor. + + const needsAttention = statusKey === "warning" || statusKey === "error"; + +- const editorStatusNode = + +- isAuthenticated && authEmail ? ( + +- <> + +- {needsAttention ? statusDotNode : null} + +- Authenticated as + +- + +- {authLabel ? · {authLabel} : null} + +- {summary.detail ? ( + +- · {summary.detail} + +- ) : null} + +- + +- ) : ( + +- <> + +- {statusDotNode} + +- {summary.headline} + +- {summary.detail ? ( + +- · {summary.detail} + +- ) : null} + +- + +- ); + ++ const statusLineClassName = + ++ "flex min-w-0 flex-wrap items-center gap-x-1.5 text-[13px] leading-[1.45] text-muted-foreground/80"; + ++ + + if (mode === "list") { + + return ( + +
+ + + +- } + +- /> + +- + ++
+ ++
+ ++
+ ++ {titleHeadNode} + ++ {versionCodeNode} + ++ {/* + ++ Only the write actions go inert on read-only sessions; the + ++ status line below keeps its email reveal clickable. + ++ */} + ++ + +-
+ +-
+ +-

+ +- Update available + +-

+ +-

+ +- {versionAdvisory.detail} + +-

+ +-
+ +- {onRunUpdate ? ( + +-
+ -- {onDelete ? ( + -- + -- + -- + ++ versionAdvisory.emphasis === "strong" + ++ ? "text-warning hover:text-warning" + ++ : "text-muted-foreground hover:text-foreground", + ++ )} + ++ aria-label="Update available — view details" + ++ > + ++ + ++ + ++ } + ++ /> + ++ + +- {isUpdating ? : } + +- {isUpdating ? "Updating" : "Update now"} + +- + +- ) : null} + +- {onRunUpdate && updateCommand ? ( + +-
+ +- + +- or, update manually using + +- + +-
+ +- ) : null} + +- {updateCommand ? ( + +-
+ +- + +- {updateCommand} + +- + +- + +- + +- copyToClipboard(updateCommand, { providerName: displayName }) + +- } + +- aria-label="Copy update command" + +- > + +- + +- + +- } + +- /> + +- Copy command + +- + +-
+ +- ) : null} + +-
+ +- + +- + - ) : null} + -
+ - + -
+ -@@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function ProviderInstanceCard({ + - + ++ ) : null} + ++ {onRunUpdate && updateCommand ? ( + ++
+ ++ + ++ or, update manually using + ++ + ++
+ ++ ) : null} + ++ {updateCommand ? ( + ++
+ ++ + ++ + ++ {updateCommand} + ++ + ++ + ++ + ++ + ++ copyToClipboard(updateCommand, { + ++ providerName: displayName, + ++ }) + ++ } + ++ aria-label="Copy update command" + ++ > + ++ + ++ + ++ } + ++ /> + ++ Copy command + ++ + ++
+ ++ ) : null} + ++
+ ++ + ++ + ++ ) : null} + ++ {titleTailNode} + ++ + ++
+ ++

+ ++ {statusDotNode} + ++ {isAuthenticated && authEmail ? ( + ++ <> + ++ Authenticated as + ++ + ++ {authLabel ? · {authLabel} : null} + ++ + ++ ) : ( + ++ statusHeadlineNode + ++ )} + ++ {summary.detail && !needsAttention ? · {summary.detail} : null} + ++

+ ++ {summary.detail && needsAttention ? ( + ++

+ ++ {summary.detail} + ++

+ ++ ) : null} + ++
+ ++
+ ++ + ++
+ ++ + ++ {driverOption !== undefined ? ( + ++ + +- + +- + ++ Models + ++ + ) : null} + -
+ -@@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function ProviderInstanceCard({ + -
+ +-
+ +- ); + ++
+ + + +- return ( + +- <> + +- + +- + ++
+ ++ + - {driverOption !== undefined ? ( + ++
+ ++ + ++ {driverOption !== undefined ? ( + ++ + -- ) : null} + +-
+ +- ) : null} + +- + +
+ -
+ ++
+ + + + + + + @@ apps/web/src/components/settings/ProviderInstanceCard.tsx: export function Provi + +
+ + + + + -
+ ++
+ ); + } + + @@ packages/contracts/src/settings.ts: export const ClaudeSettings = makeProviderSe + export const GrokSettings = makeProviderSettingsSchema( + + ## pnpm-lock.yaml ## + +@@ pnpm-lock.yaml: catalogs: + + specifier: ~6.0.3 + + version: 6.0.3 + + vite-plus: + +- specifier: 0.3.0 + +- version: 0.3.0 + ++ specifier: 0.2.2 + ++ version: 0.2.2 + + + + overrides: + + '@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-darwin-arm64': '-' + +@@ pnpm-lock.yaml: overrides: + + '@expo/metro-config': 57.0.12 + + expo-constants: 57.0.16 + + '@pierre/diffs>@shikijs/transformers': ^4.2.0 + +- '@tailwindcss/node': 4.3.3 + +- '@tailwindcss/oxide': 4.3.3 + +- '@tailwindcss/vite': 4.3.3 + + '@types/node': 24.12.4 + + effect: 4.0.0-beta.103 + + expo-router: 57.0.17 + + expo-sharing>@expo/config-plugins: 57.0.9 + + expo-sharing>@expo/config-types: 57.0.2 + +- lightningcss: 1.33.0 + +- tailwindcss: 4.3.3 + +- vite: npm:@voidzero-dev/vite-plus-core@0.3.0 + ++ vite: npm:@voidzero-dev/vite-plus-core@0.2.2 + + yaml: ^2.9.0 + + + + packageExtensionsChecksum: sha256-k/dT9NFDl5hihRPaoFKeY11hzyutMFs5psfZLFiKJic= + +@@ pnpm-lock.yaml: patchedDependencies: + + '@react-navigation/native-stack@7.17.6': e667c3cef8c78bb9ff4882ee5bd23a432247b843060a9499eb5f07e9e2295552 + + effect@4.0.0-beta.103: af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6 + + expo-audio@57.0.4: fa9a3e0442ed395d4071bb406e08c3a471c9a84700bdfa0b9ad7ff144c96041a + +- expo-sharing@57.0.17: 8d2e3b10eb3f52036a9a086800180ec6cebf3b75bccc5b1775117a7244d4ac45 + ++ expo-sharing@57.0.16: 8d2e3b10eb3f52036a9a086800180ec6cebf3b75bccc5b1775117a7244d4ac45 + + react-native-gesture-handler@2.32.0: 808eb26f9e57cf4945efd3985af4d9c764da6f91f4c9764433cc868602bbf4d3 + + react-native-keyboard-controller@1.21.13: 20be72c84d74253acdcfefbc6defe36dc396944f1a44cab2bdd0e3cd572ae008 + + react-native-nitro-modules@0.35.9: 825622aae63a8fb5b904f3c77908a0e216261d727ea171709f2c0b6088422675 + +- react-native-screens@4.26.2: 8156dd0f3407822404793cfdaa95639a36b62102f4507c981b8be83600bb382d + +- uniwind@1.11.0: 17d92be2eec71bb6396b402e8d034968e54b28746876d7977cb3139655f42b90 + ++ react-native-screens@4.26.2: 149bef30a66351ea9b26b42f87b78c539cb52b880f2387bb323ec80dcac84006 + ++ uniwind@1.11.0: 329a77525509623d763b738152dbd00ab392cdcdd9fb6ed2b4a20e086e437196 + + + + importers: + + + +@@ pnpm-lock.yaml: importers: + + version: 7.0.0-dev.20260604.1 + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + apps/desktop: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + '@effect/platform-node': + + specifier: 4.0.0-beta.103 + + version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6) + +- '@napi-rs/keyring': + +- specifier: ^1.3.0 + +- version: 1.3.0 + + '@t3tools/client-runtime': + + specifier: workspace:* + + version: link:../../packages/client-runtime + +@@ pnpm-lock.yaml: importers: + + specifier: 26.15.6 + + version: 26.15.6(electron-builder-squirrel-windows@26.15.6) + + tailwindcss: + +- specifier: 4.3.3 + +- version: 4.3.3 + ++ specifier: ^4.0.0 + ++ version: 4.3.0 + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + apps/marketing: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: 7.3.4(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + + '@react-navigation/native-stack': + + specifier: 7.17.6 + +- version: 7.17.6(patch_hash=e667c3cef8c78bb9ff4882ee5bd23a432247b843060a9499eb5f07e9e2295552)(ad1eff2c3e588b799b6541240bb21d97) + ++ version: 7.17.6(patch_hash=e667c3cef8c78bb9ff4882ee5bd23a432247b843060a9499eb5f07e9e2295552)(d307537762dff86bcf277a4ec64a11d8) + + '@shikijs/core': + + specifier: 4.2.0 + + version: 4.2.0 + +@@ pnpm-lock.yaml: importers: + + specifier: ~57.0.2 + + version: 57.0.2(expo@57.0.18) + + expo-sharing: + +- specifier: 57.0.17 + +- version: 57.0.17(patch_hash=8d2e3b10eb3f52036a9a086800180ec6cebf3b75bccc5b1775117a7244d4ac45)(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)(typescript@6.0.3) + ++ specifier: ~57.0.16 + ++ version: 57.0.16(patch_hash=8d2e3b10eb3f52036a9a086800180ec6cebf3b75bccc5b1775117a7244d4ac45)(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)(typescript@6.0.3) + + expo-splash-screen: + + specifier: ~57.0.8 + + version: 57.0.8(expo@57.0.18)(typescript@6.0.3) + +@@ pnpm-lock.yaml: importers: + + version: 5.7.0(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + + react-native-screens: + + specifier: ~4.26.0 + +- version: 4.26.2(patch_hash=8156dd0f3407822404793cfdaa95639a36b62102f4507c981b8be83600bb382d)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + ++ version: 4.26.2(patch_hash=149bef30a66351ea9b26b42f87b78c539cb52b880f2387bb323ec80dcac84006)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + + react-native-shiki-engine: + + specifier: ^0.3.12 + + version: 0.3.12(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + +@@ pnpm-lock.yaml: importers: + + version: 3.6.0 + + uniwind: + + specifier: 1.11.0 + +- version: 1.11.0(patch_hash=17d92be2eec71bb6396b402e8d034968e54b28746876d7977cb3139655f42b90)(@expo/metro-config@57.0.12(patch_hash=96f1a75347e6ea02dc4b7034ace815d8ee39e18b8166ebfb573d9e58328f0dc2)(bufferutil@4.1.0)(expo@57.0.18)(typescript@6.0.3)(utf-8-validate@6.0.6))(metro-cache@0.84.5)(metro-transform-worker@0.84.5(bufferutil@4.1.0)(utf-8-validate@6.0.6))(metro@0.84.5(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)(tailwindcss@4.3.3) + ++ version: 1.11.0(patch_hash=329a77525509623d763b738152dbd00ab392cdcdd9fb6ed2b4a20e086e437196)(@expo/metro-config@57.0.12(patch_hash=96f1a75347e6ea02dc4b7034ace815d8ee39e18b8166ebfb573d9e58328f0dc2)(bufferutil@4.1.0)(expo@57.0.18)(typescript@6.0.3)(utf-8-validate@6.0.6))(metro-cache@0.84.5)(metro-transform-worker@0.84.5(bufferutil@4.1.0)(utf-8-validate@6.0.6))(metro@0.84.5(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)(tailwindcss@4.3.0) + + devDependencies: + + '@effect/vitest': + + specifier: 4.0.0-beta.103 + +@@ pnpm-lock.yaml: importers: + + specifier: ~57.0.9 + + version: 57.0.9(@babel/core@7.29.7)(@babel/runtime@7.29.7)(expo-widgets@57.0.15)(expo@57.0.18)(react-refresh@0.14.2) + + tailwindcss: + +- specifier: 4.3.3 + +- version: 4.3.3 + ++ specifier: ^4.0.0 + ++ version: 4.3.0 + + typescript: + + specifier: 'catalog:' + + version: 6.0.3 + @@ pnpm-lock.yaml: importers: + specifier: 1.7.0 + version: 1.7.0(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.7.0(@bufbuild/protobuf@1.10.0)) + @@ pnpm-lock.yaml: importers: + '@effect/platform-bun': + specifier: 4.0.0-beta.103 + version: 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6) + +@@ pnpm-lock.yaml: importers: + + yaml: + + specifier: ^2.9.0 + + version: 2.9.0 + +- yauzl: + +- specifier: ^3.4.0 + +- version: 3.4.0 + + devDependencies: + + '@effect/vitest': + + specifier: 4.0.0-beta.103 + +@@ pnpm-lock.yaml: importers: + + '@types/node': + + specifier: 24.12.4 + + version: 24.12.4 + +- '@types/yauzl': + +- specifier: ^3.4.0 + +- version: 3.4.0 + + effect-acp: + + specifier: workspace:* + + version: link:../../packages/effect-acp + +@@ pnpm-lock.yaml: importers: + + version: link:../../packages/effect-codex-app-server + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + apps/web: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + + '@rolldown/plugin-babel': + + specifier: ^0.2.0 + +- version: 0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5) + ++ version: 0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5) + + '@tailwindcss/vite': + +- specifier: 4.3.3 + +- version: 4.3.3(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)) + ++ specifier: ^4.0.0 + ++ version: 4.3.0(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)) + + '@tanstack/router-plugin': + + specifier: ^1.161.0 + +- version: 1.168.13(@tanstack/react-router@1.170.10(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)) + ++ version: 1.168.13(@tanstack/react-router@1.170.10(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)) + + '@types/babel__core': + + specifier: ^7.20.5 + + version: 7.20.5 + +@@ pnpm-lock.yaml: importers: + + version: 0.3.0 + + '@vitejs/plugin-react': + + specifier: ^6.0.0 + +- version: 6.0.2(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5))(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(babel-plugin-react-compiler@1.0.0) + ++ version: 6.0.2(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(babel-plugin-react-compiler@1.0.0) + + babel-plugin-react-compiler: + + specifier: 1.0.0 + + version: 1.0.0 + +@@ pnpm-lock.yaml: importers: + + specifier: 19.2.6 + + version: 19.2.6(react@19.2.6) + + tailwindcss: + +- specifier: 4.3.3 + +- version: 4.3.3 + ++ specifier: ^4.0.0 + ++ version: 4.3.0 + + vite: + +- specifier: npm:@voidzero-dev/vite-plus-core@0.3.0 + +- version: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ specifier: npm:@voidzero-dev/vite-plus-core@0.2.2 + ++ version: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + infra/relay: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: link:../../packages/shared + + alchemy: + + specifier: 2.0.0-beta.65 + +- version: 2.0.0-beta.65(2233d007cbd93ff91712c637e233494f) + ++ version: 2.0.0-beta.65(00c448ade6580e73d10ccfe1b32cee97) + + drizzle-orm: + + specifier: 1.0.0-rc.4 + + version: 1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(expo-sqlite@57.0.2(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3) + +@@ pnpm-lock.yaml: importers: + + specifier: 1.0.0-rc.4 + + version: 1.0.0-rc.4 + + vite: + +- specifier: npm:@voidzero-dev/vite-plus-core@0.3.0 + +- version: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ specifier: npm:@voidzero-dev/vite-plus-core@0.2.2 + ++ version: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + oxlint-plugin-t3code: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + packages/client-runtime: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: 2.0.2 + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + packages/contracts: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: 4.0.0-beta.103(patch_hash=a16b1e870d8c29e4a98b17cc4c638a4ff471753d8ca3487f78a22b759caf951b)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + packages/effect-acp: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: 24.12.4 + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + packages/effect-codex-app-server: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: 24.12.4 + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + packages/shared: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: 24.12.4 + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + packages/ssh: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: 24.12.4 + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + packages/tailscale: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: 24.12.4 + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + scripts: + + dependencies: + +@@ pnpm-lock.yaml: importers: + + version: 6.0.5 + + vite-plus: + + specifier: 'catalog:' + +- version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ version: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + packages: + + + @@ pnpm-lock.yaml: packages: + peerDependencies: + '@bufbuild/protobuf': ^1.10.0 + @@ pnpm-lock.yaml: packages: + engines: {node: '>=22.13'} + + '@develar/schema-utils@2.6.5': + -@@ pnpm-lock.yaml: snapshots: + - dependencies: + - '@bufbuild/protobuf': 1.10.0 + +@@ pnpm-lock.yaml: packages: + + resolution: {integrity: sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w==} + + engines: {node: '>=18'} + + -- '@cursor/sdk-darwin-arm64@1.0.19': + -+ '@cursor/sdk-darwin-arm64@1.0.22': + - optional: true + +- '@napi-rs/keyring-darwin-arm64@1.3.0': + +- resolution: {integrity: sha512-pl76hJvdYUBn6I24bXiOBMA9nbDapo3I5B+f3OorjDU4dUMSypXeKbOVehJe8fhgTiH24flMyTS3aAIy43xegQ==} + +- engines: {node: '>= 10'} + +- cpu: [arm64] + +- os: [darwin] + +- + +- '@napi-rs/keyring-darwin-x64@1.3.0': + +- resolution: {integrity: sha512-YcJtEV5LA3cvA4z3BurgxH5IhTsW1JfIvcAAcqcecwk06Si9F9NqkxbZVIfDwQ8oRHgaBmT3zZJnLAotCrVahw==} + +- engines: {node: '>= 10'} + +- cpu: [x64] + +- os: [darwin] + +- + +- '@napi-rs/keyring-freebsd-x64@1.3.0': + +- resolution: {integrity: sha512-vlLf31TGhfRAaxLDBhg8b89ss0HHD/lyNmL5F3UjSaz5CUXElsJmKYq9fqA/B+cZKUEUcLHHGhF0I/CqcFdaVw==} + +- engines: {node: '>= 10'} + +- cpu: [x64] + +- os: [freebsd] + +- + +- '@napi-rs/keyring-linux-arm-gnueabihf@1.3.0': + +- resolution: {integrity: sha512-KiWdMMu/Inz/bHHIAGrnF7r54FZDYXuHO6UFF/rhIrshUsxbMG1Rl9lEymNtqqsVo927G0VYcb02FzWQ3iBQRQ==} + +- engines: {node: '>= 10'} + +- cpu: [arm] + +- os: [linux] + +- + +- '@napi-rs/keyring-linux-arm64-gnu@1.3.0': + +- resolution: {integrity: sha512-eyKGpY40lm9Jvs1aD294XRH4y7+TlJM0YVAryZeXA6TX0mb4gMkxVXwSQv7MCwgah7raeUd0dKUb4BPAYIgcMg==} + +- engines: {node: '>= 10'} + +- cpu: [arm64] + +- os: [linux] + +- libc: [glibc] + +- + +- '@napi-rs/keyring-linux-arm64-musl@1.3.0': + +- resolution: {integrity: sha512-iIK6JWHXAJqDrEyLY3TmswwloVyt2vj+04TZnew+uSJ9gnDO8EwRbp3/iw3LpWaXiDO7VomGO6y8I0Id8uBZSw==} + +- engines: {node: '>= 10'} + +- cpu: [arm64] + +- os: [linux] + +- libc: [musl] + +- + +- '@napi-rs/keyring-linux-riscv64-gnu@1.3.0': + +- resolution: {integrity: sha512-/PGqrwn6EwgtK6vccASSXJRfOSP4vN1F4ASsIQ+7MdrK6hNvAJ1FZPrIuD5gGGdxezo3F++To2Wq7DbuGIeuNQ==} + +- engines: {node: '>= 10'} + +- cpu: [riscv64] + +- os: [linux] + +- libc: [glibc] + +- + +- '@napi-rs/keyring-linux-x64-gnu@1.3.0': + +- resolution: {integrity: sha512-2PDK1WKWTu9lBGq9VvNEkSlQD3O7YwVpmnyN2M3cy4v7NJ/8gDMd9GXv3G+FVXN13uhp4gnnPBS+ScefmEeD2A==} + +- engines: {node: '>= 10'} + +- cpu: [x64] + +- os: [linux] + +- libc: [glibc] + +- + +- '@napi-rs/keyring-linux-x64-musl@1.3.0': + +- resolution: {integrity: sha512-oJ2HkX8YUo46QBkn0pG+HuIKQNqr523q6vBobCn+P95s4C4K6/kLBqHY/1bg5J4ap31DzsznhnFKcfBNBsjCnw==} + +- engines: {node: '>= 10'} + +- cpu: [x64] + +- os: [linux] + +- libc: [musl] + +- + +- '@napi-rs/keyring-win32-arm64-msvc@1.3.0': + +- resolution: {integrity: sha512-tOd3c/uAaeoE4ycVlmAdSvygz0Zt3zdca6Y7gokBeIbaRDWpjDIUOpU3MvML59XAaqyuKGsVVu0F/DZb1lHPmw==} + +- engines: {node: '>= 10'} + +- cpu: [arm64] + +- os: [win32] + +- + +- '@napi-rs/keyring-win32-ia32-msvc@1.3.0': + +- resolution: {integrity: sha512-sPSqeAFZMGqP1R++M2JTza7GQJJ/TpCo6JU6Vcd4jnebvOaEDs9b7eipakU1PJdSvhpC2yXMCNRk9gXfrhuwHQ==} + +- engines: {node: '>= 10'} + +- cpu: [ia32] + +- os: [win32] + +- + +- '@napi-rs/keyring-win32-x64-msvc@1.3.0': + +- resolution: {integrity: sha512-4DnCWXwDc0HRKwyRlG5y0VhKZW2tNRQfKKfyj6IX/KWfDNyq9hn4n+GL1auyDcOO/v8PwnhmYo2+rOOqCkvvOg==} + +- engines: {node: '>= 10'} + +- cpu: [x64] + +- os: [win32] + +- + +- '@napi-rs/keyring@1.3.0': + +- resolution: {integrity: sha512-WrOw/bcXm0f9qHkumlT1QlArXSTWqaY9sunsDpOk+yCCorCKMxvWT/a3xko4EYHVdeZoh00yI2TydXn6eyICDA==} + +- engines: {node: '>= 10'} + +- + + '@napi-rs/wasm-runtime@1.1.6': + + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + + peerDependencies: + +@@ pnpm-lock.yaml: packages: + + '@oslojs/encoding@1.1.0': + + resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + + -- '@cursor/sdk-darwin-x64@1.0.19': + -+ '@cursor/sdk-darwin-x64@1.0.22': + - optional: true + +- '@oxc-project/runtime@0.146.0': + +- resolution: {integrity: sha512-lbXHIpZ1MmK6zuw5txlMdIZ2waLVUIU5Gnm3sEuwJOiqDfQfbtjeHscatmeBoxbv8+If9LFM6PGh/3DcDWYIYw==} + ++ '@oxc-project/runtime@0.138.0': + ++ resolution: {integrity: sha512-yHhoXsN8tYxgdJCdD91PbySNjEEaBX/tH2OQRDXJpsQv5b184oC4/qVbU7qlblvfil/JP15Lh2HW7+HN5DS90Q==} + + engines: {node: ^20.19.0 || >=22.12.0} + + -- '@cursor/sdk-linux-arm64@1.0.19': + -+ '@cursor/sdk-linux-arm64@1.0.22': + - optional: true + + '@oxc-project/types@0.127.0': + + resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==} + + -- '@cursor/sdk-linux-x64@1.0.19': + -+ '@cursor/sdk-linux-x64@1.0.22': + - optional: true + ++ '@oxc-project/types@0.138.0': + ++ resolution: {integrity: sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA==} + ++ + + '@oxc-project/types@0.139.0': + + resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + + -- '@cursor/sdk-win32-x64@1.0.19': + -+ '@cursor/sdk-win32-x64@1.0.22': + - optional: true + +- '@oxc-project/types@0.146.0': + +- resolution: {integrity: sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA==} + +- + +- '@oxfmt/binding-android-arm-eabi@0.64.0': + +- resolution: {integrity: sha512-o6uzh/jTOQeAY5TdkAeXdqv7MBRcPxiRA08zrcBtkKj5cSu/FMu0Hl7Q6Fi1KCKyCWZ6lJVjBzdsJvsKltUsGQ==} + ++ '@oxfmt/binding-android-arm-eabi@0.57.0': + ++ resolution: {integrity: sha512-qVBsEO+KugOsCmUHcO8iqNnqc65p7PCKpCs8M66mPZ+Ri+CWbcpoQOEJBg2OTu03+0qu++NK1jj6IzvQVs0Sig==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm] + + os: [android] + + -- '@cursor/sdk@1.0.19': + -+ '@cursor/sdk@1.0.22': + - dependencies: + - '@bufbuild/protobuf': 1.10.0 + - '@connectrpc/connect': 1.7.0(@bufbuild/protobuf@1.10.0) + -+ '@connectrpc/connect-node': 1.7.0(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.7.0(@bufbuild/protobuf@1.10.0)) + - '@connectrpc/connect-web': 1.7.0(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.7.0(@bufbuild/protobuf@1.10.0)) + - '@statsig/js-client': 3.31.0 + - zod: 3.25.76 + - optionalDependencies: + -- '@cursor/sdk-darwin-arm64': 1.0.19 + -- '@cursor/sdk-darwin-x64': 1.0.19 + -- '@cursor/sdk-linux-arm64': 1.0.19 + -- '@cursor/sdk-linux-x64': 1.0.19 + -- '@cursor/sdk-win32-x64': 1.0.19 + -+ '@cursor/sdk-darwin-arm64': 1.0.22 + -+ '@cursor/sdk-darwin-x64': 1.0.22 + -+ '@cursor/sdk-linux-arm64': 1.0.22 + -+ '@cursor/sdk-linux-x64': 1.0.22 + -+ '@cursor/sdk-win32-x64': 1.0.22 + +- '@oxfmt/binding-android-arm64@0.64.0': + +- resolution: {integrity: sha512-jRGSUeeP7p3Gynw2YaCVtjBIA6ZxY6bEB/ES5i54OhqmRTyuVg7ZgstEtzgq6GOAJd+2QZ5pvf+bFfmW5Mp9cw==} + ++ '@oxfmt/binding-android-arm64@0.57.0': + ++ resolution: {integrity: sha512-mp6PibWbao3aizijcheOeHQaYEhcUAt8pwLniYbtLfHxL/psFF0BykAwCj+s3c6qIpa8yN8keZICWrqtZ70w8g==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [android] + + - '@develar/schema-utils@2.6.5': + - dependencies: + -@@ pnpm-lock.yaml: snapshots: + - '@rolldown/plugin-babel': 0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5) + - babel-plugin-react-compiler: 1.0.0 + +- '@oxfmt/binding-darwin-arm64@0.64.0': + +- resolution: {integrity: sha512-JINwtU2lW7nOFSqi+H2qplipNUqah9Gc1jgGmB82kTD4UnZrZIVxCJ9qEmFiKfjNq27gYLFhrUb0to86aCwMjw==} + ++ '@oxfmt/binding-darwin-arm64@0.57.0': + ++ resolution: {integrity: sha512-T+0stuCBqmUVY+aMIvrgXhzGhHO3sD5tNiiEcYqgSdPsnukskQqn2u5qOVD0sv1l7RLdFS5Z/f5Wi9Ktyjr3Eg==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [darwin] + + -- '@vitest/browser-preview@4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9)': + -+ '@vitest/browser-preview@4.1.9(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9)': + - dependencies: + - '@testing-library/dom': 10.4.1 + - '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) + -- '@vitest/browser': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9) + -- vitest: 4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + -+ '@vitest/browser': 4.1.9(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9) + -+ vitest: 4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + - transitivePeerDependencies: + - - bufferutil + - - msw + - - utf-8-validate + +- '@oxfmt/binding-darwin-x64@0.64.0': + +- resolution: {integrity: sha512-gCmuswrgrOSajV4HCRFkVCGIruPq8bjYuPYgSE2WQB3mD6XrdyZ3JMSRZCkQ8zCxOyGWriBo6QoZ5nmMHQ1BfA==} + ++ '@oxfmt/binding-darwin-x64@0.57.0': + ++ resolution: {integrity: sha512-O+3JbqWs/mCI2oi4xfhRO2IVPFJNDDEBV8Odo+ZpmsUOeKJfjXoNH7nDmBEQcDgK7NfjDIyE7kRgYSZcTLDO0A==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [x64] + + os: [darwin] + + + +- '@oxfmt/binding-freebsd-x64@0.64.0': + +- resolution: {integrity: sha512-Ab8g7a38pT0MMImjh7anRSTve6buWBIlcXIFBYa5xl4s6UxEgKSc2xOOhbGtLwvXnEi2PsEDGoJh3oUU7xkehQ==} + ++ '@oxfmt/binding-freebsd-x64@0.57.0': + ++ resolution: {integrity: sha512-pxwhxVC+JkLX9twOQ/8C/vbuOQcMZyKIDmiRDZfO7yITuVcIdZCiLRqqf4QOxb2+8FWrRXzQpm+1DBKcMpHSSQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [x64] + + os: [freebsd] + + + +- '@oxfmt/binding-linux-arm-gnueabihf@0.64.0': + +- resolution: {integrity: sha512-BgvS3CoQ+Xy2deoZqEN8JVKabcCZi2RxA3yant8G9OAv9KuPJ9TCjHkqigzdHUVwErZxEP5d2bzLIEyKYyBDLg==} + ++ '@oxfmt/binding-linux-arm-gnueabihf@0.57.0': + ++ resolution: {integrity: sha512-pxBU4zH2imB/MDBfth2rOMeVxXUMjRQLCazagwLARIFH3hVlxZJBlM4nSnHXaIHJK4/qezoFCIORN6AY8Mra4A==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm] + + os: [linux] + + + +- '@oxfmt/binding-linux-arm-musleabihf@0.64.0': + +- resolution: {integrity: sha512-QXpNxwoMj0YvnceCNZadNSden3bIcnvjn/sDp/rwZhRoZoZYGpHvtPyhGsdJz9uvT9GkaMW7SsLddurU56dt8w==} + ++ '@oxfmt/binding-linux-arm-musleabihf@0.57.0': + ++ resolution: {integrity: sha512-JAprOzt8tycYou36ZgEw14DlRHTiN8qdtKANdV3VZIRIvTI/lh/cX13c9pJ/EnDk2GT3FASH7KvCgQ2AufAifQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm] + + os: [linux] + + + +- '@oxfmt/binding-linux-arm64-gnu@0.64.0': + +- resolution: {integrity: sha512-BBgH3I1ppDsI5pZ4Pdhw0ceYxwVCfbU/bZEBCeZ6caRS9x0ZabErxubP7riGUn11PXZBhe8DYdjkDKP1FlVQ5w==} + ++ '@oxfmt/binding-linux-arm64-gnu@0.57.0': + ++ resolution: {integrity: sha512-ajtjaxSaj9xl4BW7REt+Cef/ttzbAq00Bq4z7JUDZEfgFXdwSjH8K9bF+IcIJzZB9lKqMfQ4eHuSFOvvlvtqOg==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [linux] + + libc: [glibc] + + + +- '@oxfmt/binding-linux-arm64-musl@0.64.0': + +- resolution: {integrity: sha512-v19HSjC/BGXdt26qEvKZtwAHgGmQ2Agcap2kQP+KIqoRZqivVzYth3ui2dJA1i+6/fjpjga85lIOaJJjQ/bOOw==} + ++ '@oxfmt/binding-linux-arm64-musl@0.57.0': + ++ resolution: {integrity: sha512-p4Y/+RYk9Bk5WO+zHSUXAClRmZ2fbJCejMuCAsU2HhyME4jqf6Ftt/mJYEwIah1wGCBDYOB7wEGV1x5bCEZ6hA==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [linux] + + libc: [musl] + + + +- '@oxfmt/binding-linux-ppc64-gnu@0.64.0': + +- resolution: {integrity: sha512-PElLnOo4xFTBZrxPhgTIj0eHqZXwEBQoNWtb7facUV170T0B0FRET0iNbb3LUeLWTybkUW+vsdyv4ihOdyXGyw==} + ++ '@oxfmt/binding-linux-ppc64-gnu@0.57.0': + ++ resolution: {integrity: sha512-By6tRALAZsno0F4zedmtG+wdMvJiJmJoXM4d3+A9zHE4HRXLqXITwRH8mgrlcXc5yJM2g2W3riRPwTYdgemZLQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [ppc64] + + os: [linux] + + libc: [glibc] + + + +- '@oxfmt/binding-linux-riscv64-gnu@0.64.0': + +- resolution: {integrity: sha512-Qzsg15n4F5CH+MorcRW4MkAEMiLzXmeG+DiDSbP/bBTqCmWOH3K9DHryNrve+JHlV0txS+B6Z9P5Xz+cmWeL+g==} + ++ '@oxfmt/binding-linux-riscv64-gnu@0.57.0': + ++ resolution: {integrity: sha512-skYeG+RgvyzspqVEBsEprL90OYYZfoVNqB3HcCNR6QDJyXKOzfDRT3zncnHmUaFluIlBHuY23mU1b5WGgR98hA==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [riscv64] + + os: [linux] + + libc: [glibc] + + + +- '@oxfmt/binding-linux-riscv64-musl@0.64.0': + +- resolution: {integrity: sha512-/GZ358wnQ/Ez4UVnCcZIi56JkY0sOdZ+B108pqXKqZz3jLS59F4KEAB1Qv3fRlObrFEk+3L2vUQ/xoPx+3vjXw==} + ++ '@oxfmt/binding-linux-riscv64-musl@0.57.0': + ++ resolution: {integrity: sha512-FFgACrZOXAXUh5KQh2mt1CDOVOZmn+QzHP71wM9QobNwyQvoFfyAeefVUltW83g3sm7LTiH3yfFqLLVUpA5ZFQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [riscv64] + + os: [linux] + + libc: [musl] + + + +- '@oxfmt/binding-linux-s390x-gnu@0.64.0': + +- resolution: {integrity: sha512-/C9We3DXegowfLXtVCYHeNiU9azwCDr5cQkEtCVlc74vyn+lLQSPApJ1CZmxAduqeq/Oi3gQ+IVptyhCaTMtkQ==} + ++ '@oxfmt/binding-linux-s390x-gnu@0.57.0': + ++ resolution: {integrity: sha512-Nm/BAOfQeFiiKd502mZn/GAVKJwtd0RdCg17G3Wz/WSOIQmDi3+7/SZH4BHn1Ye5KvTVH3ua8WvfwLLycNIuvA==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [s390x] + + os: [linux] + + libc: [glibc] + + + +- '@oxfmt/binding-linux-x64-gnu@0.64.0': + +- resolution: {integrity: sha512-91KM2CeRWscIEHlj1NsW2WSnzGeq1Ehq+39bfDowTdkn+fcvK/x4Y1RcyqT7glyBjZio0ldkeCG6Usj3v7ASog==} + ++ '@oxfmt/binding-linux-x64-gnu@0.57.0': + ++ resolution: {integrity: sha512-BiSy5Ku3mQqyxS6YIqAJgd403wEUWvI7kerfzPxc2l/txZVmZM0pSj7oDM+4bGBExowxOi7o73jEam1W0EDTZg==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [x64] + + os: [linux] + + libc: [glibc] + + + +- '@oxfmt/binding-linux-x64-musl@0.64.0': + +- resolution: {integrity: sha512-gw7uEk9I+7zoT1EYLra1eWArIzNcz8e3jkv+Noo2+o2T7wPvsNSQbfoa4DSfZlvn1i6mJ05RiZ4/omaXPDNhQg==} + ++ '@oxfmt/binding-linux-x64-musl@0.57.0': + ++ resolution: {integrity: sha512-BCRkJiotz5s9afLYD2LuMvzAoDYx9H17E/YbDyu4xK7l4zHDPeny9ErSXL//i/nJyaOwRk08x4b8cgJC00+JDg==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [x64] + + os: [linux] + + libc: [musl] + + + +- '@oxfmt/binding-openharmony-arm64@0.64.0': + +- resolution: {integrity: sha512-HYHFf616FHSPSO07c09mjmXBfQ73wIVM3m0txOiooa5XZkGoxFd6B14PVj0LB0DXIqJ6wAO/dDR/NX/5UUaqnw==} + ++ '@oxfmt/binding-openharmony-arm64@0.57.0': + ++ resolution: {integrity: sha512-4Oaxe1qrGgXfpCJ1C/ERJ2iCtV2rN1R79ga9fsfyVHfSQRu/hVW780u2KDqZWFZ/iGTHODJji0JemxqFZ63eIQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [openharmony] + + + +- '@oxfmt/binding-win32-arm64-msvc@0.64.0': + +- resolution: {integrity: sha512-uQjFp081IZSWD6VAofX2iO2z01awAdHmfC+NrieWIPKrT2hZKQDyq/U18M7ifC0sm0Wz8aHY/p6+FDYIzs/CrQ==} + ++ '@oxfmt/binding-win32-arm64-msvc@0.57.0': + ++ resolution: {integrity: sha512-MYLAsDnhdNsSGheLYhWgbk0vfIrlS84iQYun/y21fX6u0jj8iBtYtbpZMdiqYeuf8U12eVPUjVY2xE2NrCfJ0g==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [win32] + + + +- '@oxfmt/binding-win32-ia32-msvc@0.64.0': + +- resolution: {integrity: sha512-lNM6byTAQ881jugzFu8juJTbNRgsUTlswMA6pJmwi1XDvmIqnnb49lcUAs5gz94fCJLrVN+/X3s3jOKqx23WIQ==} + ++ '@oxfmt/binding-win32-ia32-msvc@0.57.0': + ++ resolution: {integrity: sha512-PBwdzZALJY/jcCx2E6is0yu+cuVXeySTDmwuseD+9j0mHqlRNxwlKgsyRTBed/woPeqfVfuXfWjoq4Cx2Zt3Eg==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [ia32] + + os: [win32] + + + +- '@oxfmt/binding-win32-x64-msvc@0.64.0': + +- resolution: {integrity: sha512-BtmbtL/QjMtF1a6C3CqoDluH2IfB6fJt62E+B9RFfUPtFk4Iz9PFS6+y/SzzOvSxc7aUk2Kphwg7Dh8lMbwu6g==} + ++ '@oxfmt/binding-win32-x64-msvc@0.57.0': + ++ resolution: {integrity: sha512-bQJdH9i4RRfw55jm7+8/xS7GzHLLTbHx4huhrrDxQJaJtbSDbsyOnODvP1ftT7EG0KFKAYO2S+q6AcioXODx8w==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [x64] + + os: [win32] + + + +- '@oxlint-tsgolint/darwin-arm64@7.0.2001': + +- resolution: {integrity: sha512-CUJEdbSZ54+Xy9OXqOhWLTKZKV0BBiV7C2i/ygyVmXtkUNXx5YCzN8DpSSshTAKktoL7S+tnQ/ftFG/i7X896w==} + ++ '@oxlint-tsgolint/darwin-arm64@0.24.0': + ++ resolution: {integrity: sha512-C2uMmwK5Bc4ri4ysZ6sA8Rcu+A5zBQTp6ml2u0CLLbRZp4kMFPV3yWk8B5DK9Aw7y9bbjogIm75tUwGLFzlsYQ==} + + cpu: [arm64] + + os: [darwin] + + + +- '@oxlint-tsgolint/darwin-x64@7.0.2001': + +- resolution: {integrity: sha512-pXfBb5BqONCcgrXQNUZWXgiYmRSWJzd97S8i41VVOh6ut0tyo+cJ5FKFpczDHxiVNfj/3e7c9B4MtztNdpIVCw==} + ++ '@oxlint-tsgolint/darwin-x64@0.24.0': + ++ resolution: {integrity: sha512-Wgvt/1lRbDxmoNqWQKKcL+UIiqLmdJ+EWLpQa1qzoNVAfNB0PJpa82/8dH1twT/3rSs4zrP5TXPWl4juB71WuQ==} + + cpu: [x64] + + os: [darwin] + + + +- '@oxlint-tsgolint/linux-arm64@7.0.2001': + +- resolution: {integrity: sha512-roP7zujb/QDPzDwEKsFFpzNHHy91/Y7oX9vQXk78ekyZtcQj1QXDIMH33gjDdHBfRl4K9pZ36xhRgrP4Zr+R8A==} + ++ '@oxlint-tsgolint/linux-arm64@0.24.0': + ++ resolution: {integrity: sha512-PB1rxII7KV83+ASY4sSkXtqvpij6ME66+QCRL49uksi/ofs2Rf/UVboYr095n0Rkbl2wgvlsHGl6DHC361jQUQ==} + + cpu: [arm64] + + os: [linux] + + + +- '@oxlint-tsgolint/linux-x64@7.0.2001': + +- resolution: {integrity: sha512-UDezNqdECVmngu2TPnjaS1YoAmcTaBoI5lV9vk3VahBxoi+I5r9k3iJTT7qZoYWOXTD/7T7bNcwRgrocR6BscQ==} + ++ '@oxlint-tsgolint/linux-x64@0.24.0': + ++ resolution: {integrity: sha512-xcz3CxKmjTQLREtE/UShh+ruWmm9nAb7UM9zKcD65BStiuYgOakAKkPHl4YS5DztpVcDrE0+HqbOolTlRKYWmw==} + + cpu: [x64] + + os: [linux] + + + +- '@oxlint-tsgolint/win32-arm64@7.0.2001': + +- resolution: {integrity: sha512-uJZhqB6pdXLuN+AD1F5082byyQti/NPmJA77GtcFlmT2HzRelqbNls3SaIqxpjdFgvSBF9g0yOKGBkGFg7kX8Q==} + ++ '@oxlint-tsgolint/win32-arm64@0.24.0': + ++ resolution: {integrity: sha512-A2i6ZGBec3i20S7RaxkgHc6r3HYtD5Mn7j/mb22NkTz14u0JuudvTu6JggAnbGMcv8+dBKQI//EasxSPJLD8pw==} + + cpu: [arm64] + + os: [win32] + + + +- '@oxlint-tsgolint/win32-x64@7.0.2001': + +- resolution: {integrity: sha512-FkDRm8hx9OwzGQqyWG1tO5QrTLRApff9DzSgpz9QZau37BR8d1VYKOxMLGf6shPZntJFoTwIIJYT68VndYDCog==} + ++ '@oxlint-tsgolint/win32-x64@0.24.0': + ++ resolution: {integrity: sha512-0ZbGd9qRB6zs82moekaKdEvncRANq49EAwfNX62JpTS46feXUhKAuoyVDvZMj6Rywejylrmmu79Wo6faYCo4Ew==} + + cpu: [x64] + + os: [win32] + + + +- '@oxlint/binding-android-arm-eabi@1.79.0': + +- resolution: {integrity: sha512-TebFaaMklO/RXzTv7PucaCq9l3X6D1gA+C8H6K4njtjFOV+zWE9MKLpulcJZN9bzytbUbQIY0mZuz12nQ5Kv4Q==} + ++ '@oxlint/binding-android-arm-eabi@1.72.0': + ++ resolution: {integrity: sha512-zhCmvn+1Mj3UchAc/90i99S0t7jJUsHmFVSPg4UWrjO8b8eaSGwscgO6QAUtvHBstkjQwBttQNswEnAF1mIQdA==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm] + + os: [android] + + + +- '@oxlint/binding-android-arm64@1.79.0': + +- resolution: {integrity: sha512-KqqnOtAVgNsPPF0YSodkFZA1O80jcKoCZCTu3bgsszxA+MrMP9TLzfXitKjEj1FmrPprKDMdRDMmY3weESO9sg==} + ++ '@oxlint/binding-android-arm64@1.72.0': + ++ resolution: {integrity: sha512-mtH+aY/ozv1eZoCUC2owjFAtyNBKHpJHygKeEu9zXXnQGW1Q2/qOpvx+I+Lf23+TvTz66F4iiXUbl2cGvoLPCQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [android] + + + +- '@oxlint/binding-darwin-arm64@1.79.0': + +- resolution: {integrity: sha512-BVC2nsMzqQzRDPc5RhixkZ+m1p7iH4bxRRvqkbwDXX0PlQKm1BPy8J8cRjnAFafOq2QzI+BfO3vE8w2GZ3CBag==} + ++ '@oxlint/binding-darwin-arm64@1.72.0': + ++ resolution: {integrity: sha512-EvnajNPDtfknB3ZieeOOyDTwJn9QXDiwfnF4ZDQqART6RG6hjY4WigQcZdGoK2dkB3e1vrmEzN9aYbQCUkh/gQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [darwin] + + + +- '@oxlint/binding-darwin-x64@1.79.0': + +- resolution: {integrity: sha512-p6Lm+snmhGuLKL1+CpCV8L6ijkE/qJzK2H2jG9+eKJT0n31RbY4FLsdhexekgP3bLpw4Kgde+9DZuDZQ4yIInA==} + ++ '@oxlint/binding-darwin-x64@1.72.0': + ++ resolution: {integrity: sha512-ZkCdEa/G80A7vEHfeCDz/+L3m33DE73v32mDKhgOIgz8Uwf0DFcK7+uu6qC+7LEhmz5fpOe1osWKyjSNMydFIQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [x64] + + os: [darwin] + + + +- '@oxlint/binding-freebsd-x64@1.79.0': + +- resolution: {integrity: sha512-qDMm0dXZnoHyRqSL4N4xUq82T4sqK5cbKSjvd/dF/YbMUXc2R1wEPf+vmA5S0qUmi0nwXfNbjXBtZaIqzQLIMg==} + ++ '@oxlint/binding-freebsd-x64@1.72.0': + ++ resolution: {integrity: sha512-NroXv2vh+sxVY1uya/rM5pjhx1hm8BzlYpx9q67QP0Xhw5MH2bf5GJylpvLEC+781p1Xli/317EoV9AlGwViag==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [x64] + + os: [freebsd] + + + +- '@oxlint/binding-linux-arm-gnueabihf@1.79.0': + +- resolution: {integrity: sha512-2od7s0nuKPzqyUZAWk9KkCyGg7eI9dwFPZg+20lB15fKFkVZ0c9ZFxqPfiBAyDTlTkh9stPI0t+JlPCqMbItVA==} + ++ '@oxlint/binding-linux-arm-gnueabihf@1.72.0': + ++ resolution: {integrity: sha512-0NDywYgfj279Ou/BcQuCYSj7NJwBfmWn5qc5uGO/Ny7fUWmXyIpvawqX/8acQlWG6IXelJsJhj+JAy6sjsKj0A==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm] + + os: [linux] + + + +- '@oxlint/binding-linux-arm-musleabihf@1.79.0': + +- resolution: {integrity: sha512-ZOQUjkzDnvlhSE3+tWC3YXx94MMl+sYMlwH+u1+YGApGHOJP/YAc8ZBRFOXZ6eOBmxtXAWuS/fBcdZr8qqNO1A==} + ++ '@oxlint/binding-linux-arm-musleabihf@1.72.0': + ++ resolution: {integrity: sha512-4vpXB06h65Ezsy4hRyrGjGrfa1SkVPii09yaajiYhmVpgsFiLD+KNxIx/BNAY+XiO+i1yqp9HHdwqM8VTqa5XQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm] + + os: [linux] + + + +- '@oxlint/binding-linux-arm64-gnu@1.79.0': + +- resolution: {integrity: sha512-lu158FR4nGqGeRS3BQvtG85wRgU/Fy4MD5Cxp1hzJXizGiLo6u2742wJSCDKh8cFcZntvX7fcxlq4mMmfryH1g==} + ++ '@oxlint/binding-linux-arm64-gnu@1.72.0': + ++ resolution: {integrity: sha512-immaN4g2ZGFiOkKrvRX9LvzZdd2GkQM5wR+UyzYyUuyhUTXGQ4HKUJH18xp4G8OfhCVaVAJfKZxwE1r8+4hhaQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [linux] + + libc: [glibc] + + + +- '@oxlint/binding-linux-arm64-musl@1.79.0': + +- resolution: {integrity: sha512-mbpKQeE2aflTjddaHK7MP8KP/OFbUM++lt5M635ENM8IyIdK0jm2t9pb+2v9mVVIvhF6TqA4l7F79Pll1mi+uw==} + ++ '@oxlint/binding-linux-arm64-musl@1.72.0': + ++ resolution: {integrity: sha512-JGHS9Mnr7iWyyLDxgCv1MhzVpAckgptg00F2gnxt/GD7lQ2SW1BRcxHqhSTaSdDpjWRrBkBxMMh4+Hn3aVtExg==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [linux] + + libc: [musl] + + + +- '@oxlint/binding-linux-ppc64-gnu@1.79.0': + +- resolution: {integrity: sha512-WpGNua7gaxaHnpSDeog2ji8IDHn/QLPl9LPzwkR/FvVv58vT5BcXjRXnU+wbu3N75cpeha8CdC7ho/U2OIsB4g==} + ++ '@oxlint/binding-linux-ppc64-gnu@1.72.0': + ++ resolution: {integrity: sha512-AOYgBZqxNshrg83P9v0RYv+m8s10Cqkj4/PxXFDhcS3k7FqsIG5+CxErshZCIN7G8iy4Y+VGfAsuEdar8AcbBg==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [ppc64] + + os: [linux] + + libc: [glibc] + + + +- '@oxlint/binding-linux-riscv64-gnu@1.79.0': + +- resolution: {integrity: sha512-tK1E93A5LVzISg4ngpKJnfTs7EqtIUceGI7MQ4GyDjJiLi8wPCkEyKlj2xkyKWZ1yzkDJyLHTBJ5/iFWRdnJvg==} + ++ '@oxlint/binding-linux-riscv64-gnu@1.72.0': + ++ resolution: {integrity: sha512-QMybPS5ij3/vrKG67mqzHwW++91sYxK/PPUVi6SBtNCEzW4niS52fVBdXbQ6nou0wWbUPEpx8Sl/ZjtgE3clXA==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [riscv64] + + os: [linux] + + libc: [glibc] + + + +- '@oxlint/binding-linux-riscv64-musl@1.79.0': + +- resolution: {integrity: sha512-qhQvUIrngXivA2A9pQ+xPCychztn/5qUv7yS3gDwXv3w7Rag+eTeeXWmRyx+t7XsW5x6LuY/8AsTq36UgFIblg==} + ++ '@oxlint/binding-linux-riscv64-musl@1.72.0': + ++ resolution: {integrity: sha512-gOc3W7JV0PXRpIL7stUlLe3Wa9Gp0Kdlup87IT3gHDvPKck2xNgMIl/Gs2lldYY2lyXZDC4rWi3hmoLUobkgbQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [riscv64] + + os: [linux] + + libc: [musl] + + + +- '@oxlint/binding-linux-s390x-gnu@1.79.0': + +- resolution: {integrity: sha512-sv6AaVgU/eE6u+6WFiQVDcPPwTxP6IJMSB9k701W2r/r6Tx465e8vPvVyRxquNH4Vy6KwRNu90mVbxXJN8+5gg==} + ++ '@oxlint/binding-linux-s390x-gnu@1.72.0': + ++ resolution: {integrity: sha512-rpGxph+FjjHcYI5q6uxB3Az+tnfmEnDbSA8+PK9ZE/VzyUAkvBOMeuY7ZQMhu5mpZH7YQDsTdW6Cx4kV/msc6w==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [s390x] + + os: [linux] + + libc: [glibc] + + + +- '@oxlint/binding-linux-x64-gnu@1.79.0': + +- resolution: {integrity: sha512-iFZL02deziHslb3jEX9KdqlAkYoo4fGyotchKDzdfK1f5mxlIBeiQeHhvK3iFpuEJSB4ma/qeFn9oxPiwnhUPQ==} + ++ '@oxlint/binding-linux-x64-gnu@1.72.0': + ++ resolution: {integrity: sha512-WND+uhf/Ko13SLqQMWQUgsZuLvYYEvL0ZKgg0tgGYfLqxG7l8Ju123fHDMJyYSDl5E3bUbpFUuii/OvMreFQzw==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [x64] + + os: [linux] + + libc: [glibc] + + + +- '@oxlint/binding-linux-x64-musl@1.79.0': + +- resolution: {integrity: sha512-3DtZR2raqObnh7wXZoFYFd0Fw7skBvcb3f7A+/lkEiDuh8hrE6vv9b/62Qxao1a9/OeHLw/FcXlXzgsW9wTRFg==} + ++ '@oxlint/binding-linux-x64-musl@1.72.0': + ++ resolution: {integrity: sha512-SrpbrUL70nG9vh6zP4/oKHWgLuHquwsr7MW9XOn0olBVgh10Uqr8qscKhQoBGEn6olK/IUpn5GSKcdQ5AjUhGA==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [x64] + + os: [linux] + + libc: [musl] + + + +- '@oxlint/binding-openharmony-arm64@1.79.0': + +- resolution: {integrity: sha512-Oatt4GuA1WJkqzk2ozx4HrWROOi7opV3AKDw/U8qDIqeTqzsjn5K2x3REJMNjU3/KU/Bkq96Zi3CknaiDTaC/Q==} + ++ '@oxlint/binding-openharmony-arm64@1.72.0': + ++ resolution: {integrity: sha512-qkrsEn6NmgFKr7U/QnezQMb+q/vzAy0Dd9Y95gQGQTyjzDLN+HRZMuM5u70iyH4nBLCfKBzhjMsYCehKay2jyg==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [openharmony] + + + +- '@oxlint/binding-win32-arm64-msvc@1.79.0': + +- resolution: {integrity: sha512-NAgZr9Qp8nIA9rpo0JEvwiabTF/2UVqBNnupBG9X4kxXcQoScJUTi+qHhvabb9s/thgj5wQ4XcIaJvb+ZMgoKw==} + ++ '@oxlint/binding-win32-arm64-msvc@1.72.0': + ++ resolution: {integrity: sha512-LWR6ZlFZph+KPjXv8opgZsXRDCdrdQe8VL8Cg9zxCoBS73h6znzZpydVgmdnwj8mB9AuSM5jxEgDJDpQkjboeg==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [arm64] + + os: [win32] + + + +- '@oxlint/binding-win32-ia32-msvc@1.79.0': + +- resolution: {integrity: sha512-+KyXjIvcpaXmWW/j9NNY5yWjrIVxaX18VyIheQy3jwc2GSYgpCr7MGI/HxIGQ/shAL5IWEKbhsqoMpAO5Stiog==} + ++ '@oxlint/binding-win32-ia32-msvc@1.72.0': + ++ resolution: {integrity: sha512-yt6HEh7IsHvtjRWtmeZRX134eaXKHq5Gnqlf1xBJdJl1JtdoRUEJw3nAxpZoUDS860cX/foKbztO441anVBtVQ==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [ia32] + + os: [win32] + + + +- '@oxlint/binding-win32-x64-msvc@1.79.0': + +- resolution: {integrity: sha512-mEelcCMMBS57sIXh2veGMNy+pQwuGtcMxHxGIZWQ5Ba9pJ5jCCUFOZB9E2JhBaxGsURe+WGe0zJp4RVre52gpQ==} + ++ '@oxlint/binding-win32-x64-msvc@1.72.0': + ++ resolution: {integrity: sha512-b2eKFD2hX7tIwmo/cyH6TDq8vzWRZ2qNHrzoGntUTmq0h3zQh/uX3eTSHCwI8OB/ADQfJCRelLItK8BsxuucDA==} + + engines: {node: ^20.19.0 || >=22.12.0} + + cpu: [x64] + + os: [win32] + +@@ pnpm-lock.yaml: packages: + + resolution: {integrity: sha512-titLmukUt/h8ho7Svlf0xSBjoy2ccZKrXjpXpZCj+v6V4CJccC2KyP45BLSCMx8YIpifMyiDyUptM4+5sruKbQ==} + + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + + +- '@oxlint/plugins@1.79.0': + +- resolution: {integrity: sha512-S0uyoxakDINJ4DPgqxGlEEvrdSMeQb7Z2lKVjxoY2gwsbZbfg2Xr8Klfeo5ZeraHmmdBCELFUHkSe6KEmBpMvg==} + +- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + +- + + '@peculiar/asn1-schema@2.8.0': + + resolution: {integrity: sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q==} + + + +@@ pnpm-lock.yaml: packages: + + '@tabler/icons@3.44.0': + + resolution: {integrity: sha512-Wn0AOZG9sg0L+bjfMqq4eNhC6pQjIrk94LvvWYNYkY8KH8wC3YILRzQlrnVJc4FUeMxH/AK97QsYCX35H3LndA==} + + + +- '@tailwindcss/node@4.3.3': + +- resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} + ++ '@tailwindcss/node@4.3.0': + ++ resolution: {integrity: sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==} + ++ + ++ '@tailwindcss/node@4.3.2': + ++ resolution: {integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==} + ++ + ++ '@tailwindcss/oxide-android-arm64@4.3.0': + ++ resolution: {integrity: sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==} + ++ engines: {node: '>= 20'} + ++ cpu: [arm64] + ++ os: [android] + + + +- '@tailwindcss/oxide-android-arm64@4.3.3': + +- resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} + ++ '@tailwindcss/oxide-android-arm64@4.3.2': + ++ resolution: {integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==} + + engines: {node: '>= 20'} + + cpu: [arm64] + + os: [android] + + + +- '@tailwindcss/oxide-darwin-arm64@4.3.3': + +- resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} + ++ '@tailwindcss/oxide-darwin-arm64@4.3.0': + ++ resolution: {integrity: sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==} + + engines: {node: '>= 20'} + + cpu: [arm64] + + os: [darwin] + + + +- '@tailwindcss/oxide-darwin-x64@4.3.3': + +- resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} + ++ '@tailwindcss/oxide-darwin-arm64@4.3.2': + ++ resolution: {integrity: sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==} + ++ engines: {node: '>= 20'} + ++ cpu: [arm64] + ++ os: [darwin] + ++ + ++ '@tailwindcss/oxide-darwin-x64@4.3.0': + ++ resolution: {integrity: sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==} + + engines: {node: '>= 20'} + + cpu: [x64] + + os: [darwin] + + + +- '@tailwindcss/oxide-freebsd-x64@4.3.3': + +- resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} + ++ '@tailwindcss/oxide-darwin-x64@4.3.2': + ++ resolution: {integrity: sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==} + ++ engines: {node: '>= 20'} + ++ cpu: [x64] + ++ os: [darwin] + ++ + ++ '@tailwindcss/oxide-freebsd-x64@4.3.0': + ++ resolution: {integrity: sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==} + + engines: {node: '>= 20'} + + cpu: [x64] + + os: [freebsd] + + + +- '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + +- resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} + ++ '@tailwindcss/oxide-freebsd-x64@4.3.2': + ++ resolution: {integrity: sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==} + ++ engines: {node: '>= 20'} + ++ cpu: [x64] + ++ os: [freebsd] + ++ + ++ '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': + ++ resolution: {integrity: sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==} + + engines: {node: '>= 20'} + + cpu: [arm] + + os: [linux] + + + +- '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + +- resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} + ++ '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + ++ resolution: {integrity: sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==} + ++ engines: {node: '>= 20'} + ++ cpu: [arm] + ++ os: [linux] + ++ + ++ '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': + ++ resolution: {integrity: sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==} + + engines: {node: '>= 20'} + + cpu: [arm64] + + os: [linux] + + libc: [glibc] + + + +- '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + +- resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} + ++ '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + ++ resolution: {integrity: sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==} + ++ engines: {node: '>= 20'} + ++ cpu: [arm64] + ++ os: [linux] + ++ libc: [glibc] + ++ + ++ '@tailwindcss/oxide-linux-arm64-musl@4.3.0': + ++ resolution: {integrity: sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==} + ++ engines: {node: '>= 20'} + ++ cpu: [arm64] + ++ os: [linux] + ++ libc: [musl] + ++ + ++ '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + ++ resolution: {integrity: sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==} + + engines: {node: '>= 20'} + + cpu: [arm64] + + os: [linux] + + libc: [musl] + + + +- '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + +- resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} + ++ '@tailwindcss/oxide-linux-x64-gnu@4.3.0': + ++ resolution: {integrity: sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==} + ++ engines: {node: '>= 20'} + ++ cpu: [x64] + ++ os: [linux] + ++ libc: [glibc] + ++ + ++ '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + ++ resolution: {integrity: sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==} + + engines: {node: '>= 20'} + + cpu: [x64] + + os: [linux] + + libc: [glibc] + + + +- '@tailwindcss/oxide-linux-x64-musl@4.3.3': + +- resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} + ++ '@tailwindcss/oxide-linux-x64-musl@4.3.0': + ++ resolution: {integrity: sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==} + + engines: {node: '>= 20'} + + cpu: [x64] + + os: [linux] + + libc: [musl] + + + +- '@tailwindcss/oxide-wasm32-wasi@4.3.3': + +- resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} + ++ '@tailwindcss/oxide-linux-x64-musl@4.3.2': + ++ resolution: {integrity: sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==} + ++ engines: {node: '>= 20'} + ++ cpu: [x64] + ++ os: [linux] + ++ libc: [musl] + ++ + ++ '@tailwindcss/oxide-wasm32-wasi@4.3.0': + ++ resolution: {integrity: sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==} + ++ engines: {node: '>=14.0.0'} + ++ cpu: [wasm32] + ++ bundledDependencies: + ++ - '@napi-rs/wasm-runtime' + ++ - '@emnapi/core' + ++ - '@emnapi/runtime' + ++ - '@tybys/wasm-util' + ++ - '@emnapi/wasi-threads' + ++ - tslib + ++ + ++ '@tailwindcss/oxide-wasm32-wasi@4.3.2': + ++ resolution: {integrity: sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==} + + engines: {node: '>=14.0.0'} + + cpu: [wasm32] + + bundledDependencies: + +@@ pnpm-lock.yaml: packages: + + - '@emnapi/wasi-threads' + + - tslib + + + +- '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + +- resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} + ++ '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': + ++ resolution: {integrity: sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==} + + engines: {node: '>= 20'} + + cpu: [arm64] + + os: [win32] + + + +- '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + +- resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} + ++ '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + ++ resolution: {integrity: sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==} + ++ engines: {node: '>= 20'} + ++ cpu: [arm64] + ++ os: [win32] + ++ + ++ '@tailwindcss/oxide-win32-x64-msvc@4.3.0': + ++ resolution: {integrity: sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==} + + engines: {node: '>= 20'} + + cpu: [x64] + + os: [win32] + + + +- '@tailwindcss/oxide@4.3.3': + +- resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} + ++ '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + ++ resolution: {integrity: sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==} + ++ engines: {node: '>= 20'} + ++ cpu: [x64] + ++ os: [win32] + ++ + ++ '@tailwindcss/oxide@4.3.0': + ++ resolution: {integrity: sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==} + + engines: {node: '>= 20'} + + + +- '@tailwindcss/vite@4.3.3': + +- resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==} + ++ '@tailwindcss/oxide@4.3.2': + ++ resolution: {integrity: sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==} + ++ engines: {node: '>= 20'} + ++ + ++ '@tailwindcss/vite@4.3.0': + ++ resolution: {integrity: sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==} + + peerDependencies: + + vite: ^5.2.0 || ^6 || ^7 || ^8 + + + +@@ pnpm-lock.yaml: packages: + + '@types/yargs@17.0.35': + + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + + +- '@types/yauzl@3.4.0': + +- resolution: {integrity: sha512-NRPn5w6h8dhcnmx3YIRQcqMywY/+nND/uOkJessedcrowO3C0AssHp3tMJpxKAwOhFOo0OV1y9VtsC5hbKKBAw==} + +- + + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260604.1': + + resolution: {integrity: sha512-zs616um9UuaODLsNlCu5Aw95rFcTV4u3hVt090r6k0lVvTxfaJOv8HKA6BpIotcEYlZlMQowrMSYCCdedo7iyA==} + + engines: {node: '>=16.20.0'} + +@@ pnpm-lock.yaml: packages: + + babel-plugin-react-compiler: + + optional: true + + + +- '@vitest/browser-preview@4.1.11': + +- resolution: {integrity: sha512-iPKSE6Ibayey6HFgK1V1/aHgyhx7HSRk1YMi+lnBZGmlIiNV5Uc7xRkD9Su8RDylTxDECK23t7kTHdRKoqSYDQ==} + ++ '@vitest/browser-preview@4.1.9': + ++ resolution: {integrity: sha512-a4/OrkMDb/WUnE4OOB/4FJbK3rYVO7YykqtUgcTKG4p2a0R3XcjPVu7SLRHFBs2+NIYhv5yxp1Lz3dbdGBjIow==} + + peerDependencies: + +- vitest: 4.1.11 + ++ vitest: 4.1.9 + + + +- '@vitest/browser@4.1.11': + +- resolution: {integrity: sha512-bwMovvAeuTFOK5kIFevw4VEf+1gVEICv4SYK4k3knJOxl6b1zEWud8mYKD73e1B0odAn174h1MofURy2TPWf3w==} + ++ '@vitest/browser@4.1.9': + ++ resolution: {integrity: sha512-j1BKtWmPcqpMhmx/L9EPLgAJpCb0zKfwoWLmqBbxaogCXHjOwHFSEoHCBfnGtx93xKQwilZ26m+UOsHqHMkRNg==} + + peerDependencies: + +- vitest: 4.1.11 + ++ vitest: 4.1.9 + + + +- '@vitest/expect@4.1.11': + +- resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==} + ++ '@vitest/expect@4.1.9': + ++ resolution: {integrity: sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==} + + + +- '@vitest/mocker@4.1.11': + +- resolution: {integrity: sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==} + ++ '@vitest/mocker@4.1.9': + ++ resolution: {integrity: sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==} + + peerDependencies: + + msw: ^2.4.9 + + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + +@@ pnpm-lock.yaml: packages: + + vite: + + optional: true + + + +- '@vitest/pretty-format@4.1.11': + +- resolution: {integrity: sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==} + ++ '@vitest/pretty-format@4.1.9': + ++ resolution: {integrity: sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==} + + + +- '@vitest/runner@4.1.11': + +- resolution: {integrity: sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==} + ++ '@vitest/runner@4.1.9': + ++ resolution: {integrity: sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==} + + + +- '@vitest/snapshot@4.1.11': + +- resolution: {integrity: sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==} + ++ '@vitest/snapshot@4.1.9': + ++ resolution: {integrity: sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==} + + + +- '@vitest/spy@4.1.11': + +- resolution: {integrity: sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==} + ++ '@vitest/spy@4.1.9': + ++ resolution: {integrity: sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==} + + + +- '@vitest/utils@4.1.11': + +- resolution: {integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==} + ++ '@vitest/utils@4.1.9': + ++ resolution: {integrity: sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==} + + + +- '@voidzero-dev/vite-plus-core@0.3.0': + +- resolution: {integrity: sha512-aOqoqIWaF+Q/geDU48pC2rVFEVSvLV1GGj/NdvhUiBhCZntoFNbwI+hjUeG8BMaPG67sOV6ey+/sgkdmGmKqaw==} + ++ '@voidzero-dev/vite-plus-core@0.2.2': + ++ resolution: {integrity: sha512-yAbKexF3npOGjg1N5EtXxun+7vdM/0x6QE5jucO/dv0LFhCAIzSN3UvLVCeamJt/Bz3jt7DLqQHEgXXrjy8drA==} + + engines: {node: ^20.19.0 || ^22.18.0 || >=24.11.0} + + peerDependencies: + + '@arethetypeswrong/core': ^0.18.1 + + '@types/node': 24.12.4 + +- '@vitejs/devtools': ^0.4.0 || ^0.5.0 + ++ '@vitejs/devtools': ^0.3.0 + + esbuild: ^0.27.0 || ^0.28.0 + + jiti: '>=1.21.0' + + less: ^4.0.0 + +@@ pnpm-lock.yaml: packages: + + sugarss: ^5.0.0 + + terser: ^5.16.0 + + tsx: ^4.8.1 + +- typescript: ^5.0.0 || ^6.0.0 || ^7.0.0 + ++ typescript: ^5.0.0 || ^6.0.0 + + unplugin-unused: ^0.5.0 + + unrun: '*' + + yaml: ^2.9.0 + +@@ pnpm-lock.yaml: packages: + + yaml: + + optional: true + + + +- '@voidzero-dev/vite-plus-darwin-arm64@0.3.0': + +- resolution: {integrity: sha512-9ADr1egZ8T4tJOqrpQLhoDl95Y74R95+bsvjmin0gy1C0eQVhpmcNnBfb07KFNhJioJp9MMO7F7Dx4fQL5SKsw==} + ++ '@voidzero-dev/vite-plus-darwin-arm64@0.2.2': + ++ resolution: {integrity: sha512-Wy0Shx3Waa2cQZGSrPm0cpO1Y5oNyKyC1jarv12bBcgV+4uoEBKX+ep2Nh7zwjfd8Ja4QMiePE7wciOSXxu8oQ==} + + engines: {node: '>=20.0.0'} + + cpu: [arm64] + + os: [darwin] + + + +- '@voidzero-dev/vite-plus-darwin-x64@0.3.0': + +- resolution: {integrity: sha512-GegasVCwNeDOkNyvhLOuwU1+T2JkjY/Tq+SOvwphUpVcqQ6OOAUq9LlpoXviO2QL/Kq2NbMYjiAfPKVSTLUFQw==} + ++ '@voidzero-dev/vite-plus-darwin-x64@0.2.2': + ++ resolution: {integrity: sha512-09xcW67OvsQItVPzmF8UckI+glM3DzyQO3A98deNQ4QtUF7Mt+4/cYKKcLKg2ExRWWXGNDnVG/j7/hiLjZzynw==} + + engines: {node: '>=20.0.0'} + + cpu: [x64] + + os: [darwin] + + + +- '@voidzero-dev/vite-plus-linux-arm64-gnu@0.3.0': + +- resolution: {integrity: sha512-nYI3KNYXkXjRPsSdR4Lr7J2xMxfR1+TplWlG/dV37qVXWAjbyHpoAlbULjZBAVJMyXRNlcADhBrEwXe4g6s48A==} + ++ '@voidzero-dev/vite-plus-linux-arm64-gnu@0.2.2': + ++ resolution: {integrity: sha512-bR6287UFNwulMiQRhbtXF8GYs9a8EjvefXf+Glm7AzbePUXnamW9cwYIj2j4Dgoje0yC4gA52UePEFjXZnJcjA==} + + engines: {node: '>=20.0.0'} + + cpu: [arm64] + + os: [linux] + + libc: [glibc] + + + +- '@voidzero-dev/vite-plus-linux-arm64-musl@0.3.0': + +- resolution: {integrity: sha512-HRlVA3AOcuGXmOdHhQ+Zv5XAaKbYF9si5rRHoOsKl0UyBo4txA3OoJfmP0WjanfLUNmu85JyO2dO1ptL4C6wgg==} + ++ '@voidzero-dev/vite-plus-linux-arm64-musl@0.2.2': + ++ resolution: {integrity: sha512-YGtvTHT7qP4c5pZmM4kLL78/d8hj2NS150R92cR2SVOW/l9Ilq5R5WrEiMA4k5Ea3B++IJWZT5MRFI0tW9qlcg==} + + engines: {node: '>=20.0.0'} + + cpu: [arm64] + + os: [linux] + + libc: [musl] + + + +- '@voidzero-dev/vite-plus-linux-x64-gnu@0.3.0': + +- resolution: {integrity: sha512-9A+dFScPfwcrzF/rRR0zH8++2hOf6xtFmN/5LyzyfUywtw9MILXcC72IMcOeL6QRJwKUMsudi1rFeDE59azNvw==} + ++ '@voidzero-dev/vite-plus-linux-x64-gnu@0.2.2': + ++ resolution: {integrity: sha512-FvaMI/vsy4PVM+Qd73K+KM8blfCAfaoZaGaGWNrrlMryhyPThXPnHoB1AQcrKbEAWb+z2fc4zLS4sH+8uI65fw==} + + engines: {node: '>=20.0.0'} + + cpu: [x64] + + os: [linux] + + libc: [glibc] + + + +- '@voidzero-dev/vite-plus-linux-x64-musl@0.3.0': + +- resolution: {integrity: sha512-KfIV3qaPdaOOE8JQMRHRE34FtZocl9O86XLTP6JMjDUlcx8FPgf8/fz/HFqJ8g232vM+JsgLI/YTVeXP8LkTKw==} + ++ '@voidzero-dev/vite-plus-linux-x64-musl@0.2.2': + ++ resolution: {integrity: sha512-ZsMochHqXqxj2sGTJNJzz3vabppbe4BFgZAjJfsnVzkwR7jv6c5p1BM71LFWxP4qd5LL0TJT7lbeRhALlI44RQ==} + + engines: {node: '>=20.0.0'} + + cpu: [x64] + + os: [linux] + + libc: [musl] + + + +- '@voidzero-dev/vite-plus-win32-arm64-msvc@0.3.0': + +- resolution: {integrity: sha512-KRhdy5K13AYx9KBfCVHRrK7zSZU+bMW9CL6gTai+UkJgAmDJi1kjdSNboZOjO8mrzUnTCrELgMI2tnstcxSTuA==} + ++ '@voidzero-dev/vite-plus-win32-arm64-msvc@0.2.2': + ++ resolution: {integrity: sha512-noBNyJufux0cf18eDpQLOQUZ1Kybfx9zlr+yQ6gAnxMEsQXSvYqZgWymfRDesBE3G/0XB5bg+AUtWijp3TwVcw==} + + engines: {node: '>=20.0.0'} + + cpu: [arm64] + + os: [win32] + + + +- '@voidzero-dev/vite-plus-win32-x64-msvc@0.3.0': + +- resolution: {integrity: sha512-7+G+GxGmxdpQO0zjiGnkZFXKGqm0CrVduebRsJd6ccuOuxCQYPxLcoHq4WOaGrh56SrAGS7XjhnQCrXRkzKUVQ==} + ++ '@voidzero-dev/vite-plus-win32-x64-msvc@0.2.2': + ++ resolution: {integrity: sha512-+VUui1OIaFX0tqdUAXjmoKVlujEtWVdcsFDw2Jff+D6b4LUTQaOMAaaic8nNdfZL6wEjweRREQLZi/icZAXtNQ==} + + engines: {node: '>=20.0.0'} + + cpu: [x64] + + os: [win32] + +@@ pnpm-lock.yaml: packages: + + engines: {node: '>=14.6'} + + deprecated: this version has critical issues, please update to the latest version + + + +- '@yuku-codegen/binding-darwin-arm64@0.5.48': + +- resolution: {integrity: sha512-yo96Oef12WzqnphInfz/eexVse3+kWgfGS5g2S3rFS3dcGn1ENW9xLFDZUP9rh+yP76DOq38wBoFi1+I9+6qBg==} + +- cpu: [arm64] + +- os: [darwin] + +- + +- '@yuku-codegen/binding-darwin-x64@0.5.48': + +- resolution: {integrity: sha512-aRCTw0EZC4bVosmw//0OMYP5tGWFE0Cu5yUBFkUbhXx/iBzvORcJ2xPNlOp/vtCCo9Ys4vp8b0DigJV6uOVb2g==} + +- cpu: [x64] + +- os: [darwin] + +- + +- '@yuku-codegen/binding-freebsd-x64@0.5.48': + +- resolution: {integrity: sha512-CA0AQAEApDkbw51PdLWMtKPJ41/7rvXsS3SJs+phG7fHJI+MuFzWuLbkucZfZoEOiDscmcsfYIdgL8BsfuyKKQ==} + +- cpu: [x64] + +- os: [freebsd] + +- + +- '@yuku-codegen/binding-linux-arm-gnu@0.5.48': + +- resolution: {integrity: sha512-DuSQlk8bH4gpmW3/00P0NLagAcMv8jOxjT40cQmxKRkktr+SUOALCfkT89tdDq3qtY95NR2GXOZ7AjNh7KKqCw==} + +- cpu: [arm] + +- os: [linux] + +- libc: [glibc] + +- + +- '@yuku-codegen/binding-linux-arm-musl@0.5.48': + +- resolution: {integrity: sha512-bxj4Ee+wlaJcWJwft2ReJXWw5sfl1qavDz6+dlRdU1xfTEtjPSNiAWhiCHnJR0R4Ygd57DnzSQmAVGvFv6RcGw==} + +- cpu: [arm] + +- os: [linux] + +- libc: [musl] + +- + +- '@yuku-codegen/binding-linux-arm64-gnu@0.5.48': + +- resolution: {integrity: sha512-mk5JVWh+0JOe5ue8k17kbYX8uGBoKt3ZqoCyxNh4nYAAcX7+X1tFUiU7jbjctu4vHeejCBFSTdQ021+V31cUCQ==} + +- cpu: [arm64] + +- os: [linux] + +- libc: [glibc] + +- + +- '@yuku-codegen/binding-linux-arm64-musl@0.5.48': + +- resolution: {integrity: sha512-4q3vkrNghbllyxOm2KesFLxCPKHF7r3JyQ7BWZccY1j2Y05yKoIFhoWCqIuQ2W/dpte9RI0+OVfwyxnrKg6fkA==} + +- cpu: [arm64] + +- os: [linux] + +- libc: [musl] + +- + +- '@yuku-codegen/binding-linux-x64-gnu@0.5.48': + +- resolution: {integrity: sha512-csd4M1EVrGaohM8acM6gq1zpUA/Rwe2ulUMBKUcwQXm/k6n7cq1A++qdew78SOVb4do3JH1WE+WFwoGQAcWc1w==} + +- cpu: [x64] + +- os: [linux] + +- libc: [glibc] + +- + +- '@yuku-codegen/binding-linux-x64-musl@0.5.48': + +- resolution: {integrity: sha512-KcDuEOT+GFoVKdvAWOv1v9iYjwnmvMZlO+j1Rw+5PYdeFLGWGzv/DD11y4SAAdwXIFcil4T0hibeIaF82WStMg==} + +- cpu: [x64] + +- os: [linux] + +- libc: [musl] + +- + +- '@yuku-codegen/binding-win32-arm64@0.5.48': + +- resolution: {integrity: sha512-HI8qNrI8dWM5BuqIMKsqornRvTNFrE6sm5zToIJ9YIa9zt5+29P7fJ7Nr39EVf6dAWSb6q7JSpScJnRsQ+FgZA==} + +- cpu: [arm64] + +- os: [win32] + +- + +- '@yuku-codegen/binding-win32-x64@0.5.48': + +- resolution: {integrity: sha512-X5YWJLO6EfBZpeBqO0AYESnUizbpFDWArcvVD61w0PEWQ3CaFRLnbQXs+kpM4ZZfGMfIE22zfA08QSY67q7TNQ==} + +- cpu: [x64] + +- os: [win32] + +- + +- '@yuku-parser/binding-darwin-arm64@0.5.48': + +- resolution: {integrity: sha512-If8mb7HH3vqghJ2NNZ8SuHfhsnjVzOxJpB8xcNOXS5WjYrs2mUhHIh5KOIvK13hDOzh0htGeGK3A6MsiEqE7HQ==} + +- cpu: [arm64] + +- os: [darwin] + +- + +- '@yuku-parser/binding-darwin-x64@0.5.48': + +- resolution: {integrity: sha512-EimvPXfspzxf1K11eB6tCW5oiQEXB8g84T2wP1TwzQagdDKo33bkmmVF0B32vTIpXnk/Ifu5IB61izZ1MylljA==} + +- cpu: [x64] + +- os: [darwin] + +- + +- '@yuku-parser/binding-freebsd-x64@0.5.48': + +- resolution: {integrity: sha512-0GcUMrumLHheThY9r5Tp46gaZYzn0irWPS1Zba6WY+vVQfhUtzGiWgXxI6tuXX0N32kEaaEVRpkKctvo6Kx3aQ==} + +- cpu: [x64] + +- os: [freebsd] + +- + +- '@yuku-parser/binding-linux-arm-gnu@0.5.48': + +- resolution: {integrity: sha512-8S5T5wjCC73dmmpQeZ49aYsSunIUM3D4Fc6rdK96c+Ayg/p3FmeSPF3xuLZHejcTmqJIIvnbfPlUF+rB6DITjQ==} + +- cpu: [arm] + +- os: [linux] + +- libc: [glibc] + +- + +- '@yuku-parser/binding-linux-arm-musl@0.5.48': + +- resolution: {integrity: sha512-tTmbxvnUHcK2/crS9547vk2SMmsajH1yqJ8ltXhIuHJgqR1v+d9n9KT+kSayo/5CS76LegeYxhMFjEivBH2hFA==} + +- cpu: [arm] + +- os: [linux] + +- libc: [musl] + +- + +- '@yuku-parser/binding-linux-arm64-gnu@0.5.48': + +- resolution: {integrity: sha512-KGYCBMqI2zfwyhgq5tpPVNe7jpUeYTBm8DhjdS+zqWNumde/PEC170QE5RHxcOAlsirIDeIUk0jqx+r/axoFSw==} + +- cpu: [arm64] + +- os: [linux] + +- libc: [glibc] + +- + +- '@yuku-parser/binding-linux-arm64-musl@0.5.48': + +- resolution: {integrity: sha512-2wTSMsCSXLTc2lZUjMAuU5X4cje55u205WJqfV5NWNF6j9pW/tXyxr15dJeekj8ziLqBXzIsj4DbRh4sY/WcjA==} + +- cpu: [arm64] + +- os: [linux] + +- libc: [musl] + +- + +- '@yuku-parser/binding-linux-x64-gnu@0.5.48': + +- resolution: {integrity: sha512-d/6v9UnGglVu1WC2JQyv/5aWSi5fXZeGSlidCfmHp4+N65N1GDKUnFtys5MK5eAPeAjTgSHGGtOc/yCcKTlv3A==} + +- cpu: [x64] + +- os: [linux] + +- libc: [glibc] + +- + +- '@yuku-parser/binding-linux-x64-musl@0.5.48': + +- resolution: {integrity: sha512-gX19gw6u4ApPy7SYMPKfFlEkrtj6WlORvrTKK3sBQqjyV+8+mUAkQgxXNjHw4RnOiAmVYg7TOlZcg8d+Qqod9A==} + +- cpu: [x64] + +- os: [linux] + +- libc: [musl] + +- + +- '@yuku-parser/binding-win32-arm64@0.5.48': + +- resolution: {integrity: sha512-w6cQQLbqj3Jcom5Q7ifm103NUOQ9d+Cb4VU5lkrZDjMnwVJ9Hzzg1vCQR7miJuF44vhCXldbme5UryE3giEKlA==} + +- cpu: [arm64] + +- os: [win32] + +- + +- '@yuku-parser/binding-win32-x64@0.5.48': + +- resolution: {integrity: sha512-4gO0HmG7fzFxrw1rs0dUdnnaY9YgennjETqDWrTSp7x9fmTUOAoN4VsMfP7YyliQeG1WJJHc55O+rOhmsLppow==} + +- cpu: [x64] + +- os: [win32] + +- + +- '@yuku-toolchain/types@0.5.43': + +- resolution: {integrity: sha512-kSpvPntnXw5+lYjO71ffBEnQ5ycQ74KGIYknh0TS4xeyCuBkOqxyJumxZkMhLBBUCLjDAbx2+Icnr3Zh4ftjpQ==} + +- + + '@yuuang/ffi-rs-android-arm64@1.3.2': + + resolution: {integrity: sha512-eDYLT0kVBkp7e2BwdRDmt6N1rkeDPUHDefk3ZX0/nok+GLsqfy1WBoSL3Yg7HVXN1EyW8OBVc2uK8Zq8HbmaSA==} + + engines: {node: '>= 12'} + +@@ pnpm-lock.yaml: packages: + + end-of-stream@1.4.5: + + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + + +- enhanced-resolve@5.24.5: + +- resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==} + ++ enhanced-resolve@5.21.6: + ++ resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} + ++ engines: {node: '>=10.13.0'} + ++ + ++ enhanced-resolve@5.22.1: + ++ resolution: {integrity: sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==} + + engines: {node: '>=10.13.0'} + + + + entities@4.5.0: + +@@ pnpm-lock.yaml: packages: + + resolution: {integrity: sha512-aK+LdKzauHSGmsOStZtyxdzv0zWssCkxTw3m4QuOhfDSJsZaMRTd9O41d8ixU/QfELTbaJ0oRNcF7JFV/7O9YQ==} + + engines: {node: '>=20.16.0'} + + + +- expo-sharing@57.0.17: + +- resolution: {integrity: sha512-p2B4SMeNsOv6hm1NkrxRlncjwu9mmLfi0drLaEyX13Rxn4DdDFPhuaezpOK7XLogTsmWGpfR46uq6oHMvSxbfA==} + ++ expo-sharing@57.0.16: + ++ resolution: {integrity: sha512-Z4ZFYLP8+EqIdUAiERYRI4/r7rtZDCRQ8Lj6jDG0xPF19B8nsFhYMgh7uyic+WulFEr+Xn7FeWgSDAuufkOyzw==} + + peerDependencies: + + expo: '*' + + react: '*' + +@@ pnpm-lock.yaml: packages: + + lighthouse-logger@1.4.2: + + resolution: {integrity: sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==} + + + +- lightningcss-android-arm64@1.33.0: + +- resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + ++ lightningcss-android-arm64@1.32.0: + ++ resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + + engines: {node: '>= 12.0.0'} + + cpu: [arm64] + + os: [android] + + + +- lightningcss-darwin-arm64@1.33.0: + +- resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + ++ lightningcss-darwin-arm64@1.30.1: + ++ resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} + + engines: {node: '>= 12.0.0'} + + cpu: [arm64] + + os: [darwin] + + + +- lightningcss-darwin-x64@1.33.0: + +- resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + ++ lightningcss-darwin-arm64@1.32.0: + ++ resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + ++ engines: {node: '>= 12.0.0'} + ++ cpu: [arm64] + ++ os: [darwin] + ++ + ++ lightningcss-darwin-x64@1.30.1: + ++ resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==} + ++ engines: {node: '>= 12.0.0'} + ++ cpu: [x64] + ++ os: [darwin] + ++ + ++ lightningcss-darwin-x64@1.32.0: + ++ resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + + engines: {node: '>= 12.0.0'} + + cpu: [x64] + + os: [darwin] + + + +- lightningcss-freebsd-x64@1.33.0: + +- resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + ++ lightningcss-freebsd-x64@1.30.1: + ++ resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==} + + engines: {node: '>= 12.0.0'} + + cpu: [x64] + + os: [freebsd] + + + +- lightningcss-linux-arm-gnueabihf@1.33.0: + +- resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + ++ lightningcss-freebsd-x64@1.32.0: + ++ resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + ++ engines: {node: '>= 12.0.0'} + ++ cpu: [x64] + ++ os: [freebsd] + ++ + ++ lightningcss-linux-arm-gnueabihf@1.30.1: + ++ resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==} + + engines: {node: '>= 12.0.0'} + + cpu: [arm] + + os: [linux] + + + +- lightningcss-linux-arm64-gnu@1.33.0: + +- resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + ++ lightningcss-linux-arm-gnueabihf@1.32.0: + ++ resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + ++ engines: {node: '>= 12.0.0'} + ++ cpu: [arm] + ++ os: [linux] + ++ + ++ lightningcss-linux-arm64-gnu@1.30.1: + ++ resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==} + + engines: {node: '>= 12.0.0'} + + cpu: [arm64] + + os: [linux] + + libc: [glibc] + + + +- lightningcss-linux-arm64-musl@1.33.0: + +- resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + ++ lightningcss-linux-arm64-gnu@1.32.0: + ++ resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + ++ engines: {node: '>= 12.0.0'} + ++ cpu: [arm64] + ++ os: [linux] + ++ libc: [glibc] + ++ + ++ lightningcss-linux-arm64-musl@1.30.1: + ++ resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} + ++ engines: {node: '>= 12.0.0'} + ++ cpu: [arm64] + ++ os: [linux] + ++ libc: [musl] + ++ + ++ lightningcss-linux-arm64-musl@1.32.0: + ++ resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + + engines: {node: '>= 12.0.0'} + + cpu: [arm64] + + os: [linux] + + libc: [musl] + + + +- lightningcss-linux-x64-gnu@1.33.0: + +- resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + ++ lightningcss-linux-x64-gnu@1.30.1: + ++ resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} + + engines: {node: '>= 12.0.0'} + + cpu: [x64] + + os: [linux] + + libc: [glibc] + + + +- lightningcss-linux-x64-musl@1.33.0: + +- resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + ++ lightningcss-linux-x64-gnu@1.32.0: + ++ resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + ++ engines: {node: '>= 12.0.0'} + ++ cpu: [x64] + ++ os: [linux] + ++ libc: [glibc] + ++ + ++ lightningcss-linux-x64-musl@1.30.1: + ++ resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} + + engines: {node: '>= 12.0.0'} + + cpu: [x64] + + os: [linux] + + libc: [musl] + + + +- lightningcss-win32-arm64-msvc@1.33.0: + +- resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + ++ lightningcss-linux-x64-musl@1.32.0: + ++ resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + ++ engines: {node: '>= 12.0.0'} + ++ cpu: [x64] + ++ os: [linux] + ++ libc: [musl] + ++ + ++ lightningcss-win32-arm64-msvc@1.30.1: + ++ resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} + ++ engines: {node: '>= 12.0.0'} + ++ cpu: [arm64] + ++ os: [win32] + ++ + ++ lightningcss-win32-arm64-msvc@1.32.0: + ++ resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + + engines: {node: '>= 12.0.0'} + + cpu: [arm64] + + os: [win32] + + + +- lightningcss-win32-x64-msvc@1.33.0: + +- resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + ++ lightningcss-win32-x64-msvc@1.30.1: + ++ resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==} + ++ engines: {node: '>= 12.0.0'} + ++ cpu: [x64] + ++ os: [win32] + ++ + ++ lightningcss-win32-x64-msvc@1.32.0: + ++ resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + + engines: {node: '>= 12.0.0'} + + cpu: [x64] + + os: [win32] + + + +- lightningcss@1.33.0: + +- resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + ++ lightningcss@1.30.1: + ++ resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} + ++ engines: {node: '>= 12.0.0'} + ++ + ++ lightningcss@1.32.0: + ++ resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + + engines: {node: '>= 12.0.0'} + + + + locate-path@3.0.0: + +@@ pnpm-lock.yaml: packages: + + outvariant@1.4.3: + + resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} + + + +- oxfmt@0.64.0: + +- resolution: {integrity: sha512-XZ4GFBN/PLbXKq+0zrgpQfPKYuJlUuj+nzZJY7UpIbFMNyefNLCdN9EwViycNqnYcv0wrn0jXcQLlqJp8RCKBg==} + ++ oxfmt@0.57.0: + ++ resolution: {integrity: sha512-ZB7Bi+rGDSqmVIo9jwcLyFgjxXvQhDdU+jx+ZrVy6VRiVXK2+CHc4hO3J4dUQjHe7V0ymHB+MDuv5z+NhK07HA==} + + engines: {node: ^20.19.0 || >=22.12.0} + + hasBin: true + + peerDependencies: + +@@ pnpm-lock.yaml: packages: + + vite-plus: + + optional: true + + + +- oxlint-tsgolint@7.0.2001: + +- resolution: {integrity: sha512-KjK/XLcXr1DSyonKhsuFqJRiuKqcyG9j3LJ8nkOsrLzGvodBPqzHOKauy10asLMDI0sUpvb+1sxlzff3udZvfg==} + ++ oxlint-tsgolint@0.24.0: + ++ resolution: {integrity: sha512-giCk5sEvG02d5tzPmFMX3hem8ndzEEu1xvGYS5OwNfO2WGl6ZVxt5LjE0yiMDoz94INI7XkXwgFAQiydPvVHDw==} + + hasBin: true + + + +- oxlint@1.79.0: + +- resolution: {integrity: sha512-hVJ9hq9m2unPS+Of4eJJgCPdIeCC+3DHEUX3tkmrPJr3OK2hz7PhXwgC+ZP71ZcYu8cCDEtQrqLxWNvxBppBVg==} + ++ oxlint@1.72.0: + ++ resolution: {integrity: sha512-1rhdZIP/EvoI91ABIwNU5Q8+bWf8mjrS5UzIOZld4d4bXxJvtlUhlQvaoTogIGin/qdErMOrwaIJvCSIAKTLhA==} + + engines: {node: ^20.19.0 || >=22.12.0} + + hasBin: true + + peerDependencies: + +- oxlint-tsgolint: '>=7.0.2001' + ++ oxlint-tsgolint: '>=0.22.1' + + vite-plus: '*' + + peerDependenciesMeta: + + oxlint-tsgolint: + +@@ pnpm-lock.yaml: packages: + + resolution: {integrity: sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==} + + engines: {node: '>=12', npm: '>=6'} + + + +- pend@1.2.0: + +- resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + +- + + pg-cloudflare@1.4.0: + + resolution: {integrity: sha512-Vo7z/6rrQYxpNRylp4Tlob2elzbh+N/MOQbxFVWCxS7oEx6jF53GTJFxK2WWpKuBRkmiin4Mt+xofFDjx09R0A==} + + + +@@ pnpm-lock.yaml: packages: + + tailwind-merge@3.6.0: + + resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} + + + +- tailwindcss@4.3.3: + +- resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} + ++ tailwindcss@4.3.0: + ++ resolution: {integrity: sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==} + ++ + ++ tailwindcss@4.3.2: + ++ resolution: {integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==} + + + + tapable@2.3.3: + + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + +@@ pnpm-lock.yaml: packages: + + metro-transform-worker: '*' + + react: '>=19.0.0' + + react-native: '>=0.81.0' + +- tailwindcss: 4.3.3 + ++ tailwindcss: '>=4' + + peerDependenciesMeta: + + '@expo/metro-config': + + optional: true + +@@ pnpm-lock.yaml: packages: + + vfile@6.0.3: + + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + + +- vite-plus@0.3.0: + +- resolution: {integrity: sha512-GNWbWuWD37frCSFrz6MLzUo62bTv5IOJozHEgZYOkxsLkuQtTwm4TowzpfoGrSsfwhAAtfPd/sK1Y0+v1SwhZA==} + ++ vite-plus@0.2.2: + ++ resolution: {integrity: sha512-bXO3O0F2/uxtvX9Ck0o67stTErH/Zh0GEcCMd9pAh22tTHABCNTDPrRMWVo733e7Ux3h0Y7HanJ7neOV/nid4g==} + + engines: {node: ^20.19.0 || ^22.18.0 || >=24.11.0} + + hasBin: true + + peerDependencies: + +- '@vitest/browser-playwright': 4.1.11 + +- '@vitest/browser-webdriverio': 4.1.11 + ++ '@vitest/browser-playwright': 4.1.9 + ++ '@vitest/browser-webdriverio': 4.1.9 + + peerDependenciesMeta: + + '@vitest/browser-playwright': + + optional: true + +@@ pnpm-lock.yaml: packages: + + vite: + + optional: true + + + +- vitest@4.1.11: + +- resolution: {integrity: sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==} + ++ vitest@4.1.9: + ++ resolution: {integrity: sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==} + + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + + hasBin: true + + peerDependencies: + + '@edge-runtime/vm': '*' + + '@opentelemetry/api': ^1.9.0 + + '@types/node': 24.12.4 + +- '@vitest/browser-playwright': 4.1.11 + +- '@vitest/browser-preview': 4.1.11 + +- '@vitest/browser-webdriverio': 4.1.11 + +- '@vitest/coverage-istanbul': 4.1.11 + +- '@vitest/coverage-v8': 4.1.11 + +- '@vitest/ui': 4.1.11 + ++ '@vitest/browser-playwright': 4.1.9 + ++ '@vitest/browser-preview': 4.1.9 + ++ '@vitest/browser-webdriverio': 4.1.9 + ++ '@vitest/coverage-istanbul': 4.1.9 + ++ '@vitest/coverage-v8': 4.1.9 + ++ '@vitest/ui': 4.1.9 + + happy-dom: '*' + + jsdom: '*' + + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + +@@ pnpm-lock.yaml: packages: + + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + + engines: {node: '>=12'} + + + +- yauzl@3.4.0: + +- resolution: {integrity: sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==} + +- engines: {node: '>=12'} + +- + + yjs@13.6.31: + + resolution: {integrity: sha512-Eq+5BRfbeGyqGVrTJL3bEcr8gKkxPuyuoHmAwpk52fDb8kOVMrfVSTRPd6yiGgX5Fskb96qCRjzjbRjrL4YEnw==} + + engines: {node: '>=16.0.0', npm: '>=8.0.0'} + +@@ pnpm-lock.yaml: packages: + + yoga-layout@3.2.1: + + resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} + + + +- yuku-codegen@0.5.48: + +- resolution: {integrity: sha512-p7HxD5Xl4jzDzqMrGePAOeSHmRY4g58h4HuGq15weQFPxuPWd/W6e7nqp/+Lea6JfpOdBwJOAyXFqIZ/J9Zfnw==} + +- + +- yuku-parser@0.5.48: + +- resolution: {integrity: sha512-OWBfhrpgK9+/4+IXG9oT8Bao4AhViQA7vdyNNH7EUg8dQYgwa70XtIBWTpCEme1P1ECyoDNYkn0wT63f8XRcVA==} + +- + + zod-to-json-schema@3.25.2: + + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + + peerDependencies: + +@@ pnpm-lock.yaml: snapshots: + + dependencies: + + '@bufbuild/protobuf': 1.10.0 + + + +- '@cursor/sdk-darwin-arm64@1.0.19': + ++ '@cursor/sdk-darwin-arm64@1.0.22': + + optional: true + + + +- '@cursor/sdk-darwin-x64@1.0.19': + ++ '@cursor/sdk-darwin-x64@1.0.22': + + optional: true + + + +- '@cursor/sdk-linux-arm64@1.0.19': + ++ '@cursor/sdk-linux-arm64@1.0.22': + + optional: true + + + +- '@cursor/sdk-linux-x64@1.0.19': + ++ '@cursor/sdk-linux-x64@1.0.22': + + optional: true + + + +- '@cursor/sdk-win32-x64@1.0.19': + ++ '@cursor/sdk-win32-x64@1.0.22': + + optional: true + + + +- '@cursor/sdk@1.0.19': + ++ '@cursor/sdk@1.0.22': + + dependencies: + + '@bufbuild/protobuf': 1.10.0 + + '@connectrpc/connect': 1.7.0(@bufbuild/protobuf@1.10.0) + ++ '@connectrpc/connect-node': 1.7.0(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.7.0(@bufbuild/protobuf@1.10.0)) + + '@connectrpc/connect-web': 1.7.0(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.7.0(@bufbuild/protobuf@1.10.0)) + + '@statsig/js-client': 3.31.0 + + zod: 3.25.76 + + optionalDependencies: + +- '@cursor/sdk-darwin-arm64': 1.0.19 + +- '@cursor/sdk-darwin-x64': 1.0.19 + +- '@cursor/sdk-linux-arm64': 1.0.19 + +- '@cursor/sdk-linux-x64': 1.0.19 + +- '@cursor/sdk-win32-x64': 1.0.19 + ++ '@cursor/sdk-darwin-arm64': 1.0.22 + ++ '@cursor/sdk-darwin-x64': 1.0.22 + ++ '@cursor/sdk-linux-arm64': 1.0.22 + ++ '@cursor/sdk-linux-x64': 1.0.22 + ++ '@cursor/sdk-win32-x64': 1.0.22 + + + + '@develar/schema-utils@2.6.5': + + dependencies: + +@@ pnpm-lock.yaml: snapshots: + + '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + + effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6) + + + +- '@distilled.cloud/cloudflare-rolldown-plugin@0.13.10(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1)': + ++ '@distilled.cloud/cloudflare-rolldown-plugin@0.13.10(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1)': + + dependencies: + + '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260704.1) + + magic-string: 0.30.21 + + unenv: 2.0.0-rc.24 + + optionalDependencies: + + rolldown: 1.1.5 + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + transitivePeerDependencies: + + - workerd + + + +@@ pnpm-lock.yaml: snapshots: + + '@effect/platform-bun': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6) + + '@effect/platform-node': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6) + + + +- '@distilled.cloud/cloudflare-vite-plugin@0.13.10(86e3ed6000e5955518fd9c0dea8322a9)': + ++ '@distilled.cloud/cloudflare-vite-plugin@0.13.10(f97c3167f1a1990dddb83bff73e575e5)': + + dependencies: + + '@distilled.cloud/cloudflare': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + +- '@distilled.cloud/cloudflare-rolldown-plugin': 0.13.10(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1) + ++ '@distilled.cloud/cloudflare-rolldown-plugin': 0.13.10(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1) + + '@distilled.cloud/cloudflare-runtime': 0.13.10(@distilled.cloud/cloudflare@0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/platform-bun@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6))(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + + effect: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6) + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + optionalDependencies: + + '@effect/platform-bun': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6) + + '@effect/platform-node': 4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6) + +@@ pnpm-lock.yaml: snapshots: + + glob: 13.0.6 + + hermes-parser: 0.36.1 + + jsc-safe-url: 0.2.4 + +- lightningcss: 1.33.0 + ++ lightningcss: 1.32.0 + + picomatch: 4.0.4 + + postcss: 8.5.15 + + resolve-from: 5.0.0 + +@@ pnpm-lock.yaml: snapshots: + + strict-event-emitter: 0.5.1 + + optional: true + + + +- '@napi-rs/keyring-darwin-arm64@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring-darwin-x64@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring-freebsd-x64@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring-linux-arm-gnueabihf@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring-linux-arm64-gnu@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring-linux-arm64-musl@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring-linux-riscv64-gnu@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring-linux-x64-gnu@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring-linux-x64-musl@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring-win32-arm64-msvc@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring-win32-ia32-msvc@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring-win32-x64-msvc@1.3.0': + +- optional: true + +- + +- '@napi-rs/keyring@1.3.0': + +- optionalDependencies: + +- '@napi-rs/keyring-darwin-arm64': 1.3.0 + +- '@napi-rs/keyring-darwin-x64': 1.3.0 + +- '@napi-rs/keyring-freebsd-x64': 1.3.0 + +- '@napi-rs/keyring-linux-arm-gnueabihf': 1.3.0 + +- '@napi-rs/keyring-linux-arm64-gnu': 1.3.0 + +- '@napi-rs/keyring-linux-arm64-musl': 1.3.0 + +- '@napi-rs/keyring-linux-riscv64-gnu': 1.3.0 + +- '@napi-rs/keyring-linux-x64-gnu': 1.3.0 + +- '@napi-rs/keyring-linux-x64-musl': 1.3.0 + +- '@napi-rs/keyring-win32-arm64-msvc': 1.3.0 + +- '@napi-rs/keyring-win32-ia32-msvc': 1.3.0 + +- '@napi-rs/keyring-win32-x64-msvc': 1.3.0 + +- + + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + + dependencies: + + '@emnapi/core': 1.10.0 + +@@ pnpm-lock.yaml: snapshots: + + + + '@oslojs/encoding@1.1.0': {} + + + +- '@oxc-project/runtime@0.146.0': {} + ++ '@oxc-project/runtime@0.138.0': {} + + + + '@oxc-project/types@0.127.0': + + optional: true + + + +- '@oxc-project/types@0.139.0': {} + ++ '@oxc-project/types@0.138.0': {} + + + +- '@oxc-project/types@0.146.0': {} + ++ '@oxc-project/types@0.139.0': {} + + + +- '@oxfmt/binding-android-arm-eabi@0.64.0': + ++ '@oxfmt/binding-android-arm-eabi@0.57.0': + + optional: true + + + +- '@oxfmt/binding-android-arm64@0.64.0': + ++ '@oxfmt/binding-android-arm64@0.57.0': + + optional: true + + + +- '@oxfmt/binding-darwin-arm64@0.64.0': + ++ '@oxfmt/binding-darwin-arm64@0.57.0': + + optional: true + + + +- '@oxfmt/binding-darwin-x64@0.64.0': + ++ '@oxfmt/binding-darwin-x64@0.57.0': + + optional: true + + + +- '@oxfmt/binding-freebsd-x64@0.64.0': + ++ '@oxfmt/binding-freebsd-x64@0.57.0': + + optional: true + + + +- '@oxfmt/binding-linux-arm-gnueabihf@0.64.0': + ++ '@oxfmt/binding-linux-arm-gnueabihf@0.57.0': + + optional: true + + + +- '@oxfmt/binding-linux-arm-musleabihf@0.64.0': + ++ '@oxfmt/binding-linux-arm-musleabihf@0.57.0': + + optional: true + + + +- '@oxfmt/binding-linux-arm64-gnu@0.64.0': + ++ '@oxfmt/binding-linux-arm64-gnu@0.57.0': + + optional: true + + + +- '@oxfmt/binding-linux-arm64-musl@0.64.0': + ++ '@oxfmt/binding-linux-arm64-musl@0.57.0': + + optional: true + + + +- '@oxfmt/binding-linux-ppc64-gnu@0.64.0': + ++ '@oxfmt/binding-linux-ppc64-gnu@0.57.0': + + optional: true + + + +- '@oxfmt/binding-linux-riscv64-gnu@0.64.0': + ++ '@oxfmt/binding-linux-riscv64-gnu@0.57.0': + + optional: true + + + +- '@oxfmt/binding-linux-riscv64-musl@0.64.0': + ++ '@oxfmt/binding-linux-riscv64-musl@0.57.0': + + optional: true + + + +- '@oxfmt/binding-linux-s390x-gnu@0.64.0': + ++ '@oxfmt/binding-linux-s390x-gnu@0.57.0': + + optional: true + + + +- '@oxfmt/binding-linux-x64-gnu@0.64.0': + ++ '@oxfmt/binding-linux-x64-gnu@0.57.0': + + optional: true + + + +- '@oxfmt/binding-linux-x64-musl@0.64.0': + ++ '@oxfmt/binding-linux-x64-musl@0.57.0': + + optional: true + + + +- '@oxfmt/binding-openharmony-arm64@0.64.0': + ++ '@oxfmt/binding-openharmony-arm64@0.57.0': + + optional: true + + + +- '@oxfmt/binding-win32-arm64-msvc@0.64.0': + ++ '@oxfmt/binding-win32-arm64-msvc@0.57.0': + + optional: true + + + +- '@oxfmt/binding-win32-ia32-msvc@0.64.0': + ++ '@oxfmt/binding-win32-ia32-msvc@0.57.0': + + optional: true + + + +- '@oxfmt/binding-win32-x64-msvc@0.64.0': + ++ '@oxfmt/binding-win32-x64-msvc@0.57.0': + + optional: true + + + +- '@oxlint-tsgolint/darwin-arm64@7.0.2001': + ++ '@oxlint-tsgolint/darwin-arm64@0.24.0': + + optional: true + + + +- '@oxlint-tsgolint/darwin-x64@7.0.2001': + ++ '@oxlint-tsgolint/darwin-x64@0.24.0': + + optional: true + + + +- '@oxlint-tsgolint/linux-arm64@7.0.2001': + ++ '@oxlint-tsgolint/linux-arm64@0.24.0': + + optional: true + + + +- '@oxlint-tsgolint/linux-x64@7.0.2001': + ++ '@oxlint-tsgolint/linux-x64@0.24.0': + + optional: true + + + +- '@oxlint-tsgolint/win32-arm64@7.0.2001': + ++ '@oxlint-tsgolint/win32-arm64@0.24.0': + + optional: true + + + +- '@oxlint-tsgolint/win32-x64@7.0.2001': + ++ '@oxlint-tsgolint/win32-x64@0.24.0': + + optional: true + + + +- '@oxlint/binding-android-arm-eabi@1.79.0': + ++ '@oxlint/binding-android-arm-eabi@1.72.0': + + optional: true + + + +- '@oxlint/binding-android-arm64@1.79.0': + ++ '@oxlint/binding-android-arm64@1.72.0': + + optional: true + + + +- '@oxlint/binding-darwin-arm64@1.79.0': + ++ '@oxlint/binding-darwin-arm64@1.72.0': + + optional: true + + + +- '@oxlint/binding-darwin-x64@1.79.0': + ++ '@oxlint/binding-darwin-x64@1.72.0': + + optional: true + + + +- '@oxlint/binding-freebsd-x64@1.79.0': + ++ '@oxlint/binding-freebsd-x64@1.72.0': + + optional: true + + + +- '@oxlint/binding-linux-arm-gnueabihf@1.79.0': + ++ '@oxlint/binding-linux-arm-gnueabihf@1.72.0': + + optional: true + + + +- '@oxlint/binding-linux-arm-musleabihf@1.79.0': + ++ '@oxlint/binding-linux-arm-musleabihf@1.72.0': + + optional: true + + + +- '@oxlint/binding-linux-arm64-gnu@1.79.0': + ++ '@oxlint/binding-linux-arm64-gnu@1.72.0': + + optional: true + + + +- '@oxlint/binding-linux-arm64-musl@1.79.0': + ++ '@oxlint/binding-linux-arm64-musl@1.72.0': + + optional: true + + + +- '@oxlint/binding-linux-ppc64-gnu@1.79.0': + ++ '@oxlint/binding-linux-ppc64-gnu@1.72.0': + + optional: true + + + +- '@oxlint/binding-linux-riscv64-gnu@1.79.0': + ++ '@oxlint/binding-linux-riscv64-gnu@1.72.0': + + optional: true + + + +- '@oxlint/binding-linux-riscv64-musl@1.79.0': + ++ '@oxlint/binding-linux-riscv64-musl@1.72.0': + + optional: true + + + +- '@oxlint/binding-linux-s390x-gnu@1.79.0': + ++ '@oxlint/binding-linux-s390x-gnu@1.72.0': + + optional: true + + + +- '@oxlint/binding-linux-x64-gnu@1.79.0': + ++ '@oxlint/binding-linux-x64-gnu@1.72.0': + + optional: true + + + +- '@oxlint/binding-linux-x64-musl@1.79.0': + ++ '@oxlint/binding-linux-x64-musl@1.72.0': + + optional: true + + + +- '@oxlint/binding-openharmony-arm64@1.79.0': + ++ '@oxlint/binding-openharmony-arm64@1.72.0': + + optional: true + + + +- '@oxlint/binding-win32-arm64-msvc@1.79.0': + ++ '@oxlint/binding-win32-arm64-msvc@1.72.0': + + optional: true + + + +- '@oxlint/binding-win32-ia32-msvc@1.79.0': + ++ '@oxlint/binding-win32-ia32-msvc@1.72.0': + + optional: true + + + +- '@oxlint/binding-win32-x64-msvc@1.79.0': + ++ '@oxlint/binding-win32-x64-msvc@1.72.0': + + optional: true + + + + '@oxlint/plugins@1.68.0': {} + + + +- '@oxlint/plugins@1.79.0': {} + +- + + '@peculiar/asn1-schema@2.8.0': + + dependencies: + + '@peculiar/utils': 2.0.3 + +@@ pnpm-lock.yaml: snapshots: + + optionalDependencies: + + '@react-native-masked-view/masked-view': 0.3.2(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + + + +- '@react-navigation/native-stack@7.17.6(patch_hash=e667c3cef8c78bb9ff4882ee5bd23a432247b843060a9499eb5f07e9e2295552)(ad1eff2c3e588b799b6541240bb21d97)': + ++ '@react-navigation/native-stack@7.17.6(patch_hash=e667c3cef8c78bb9ff4882ee5bd23a432247b843060a9499eb5f07e9e2295552)(d307537762dff86bcf277a4ec64a11d8)': + + dependencies: + + '@react-navigation/elements': 2.9.26(c10301b6e0c42fc6434d2b643197a81e) + + '@react-navigation/native': 7.3.4(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + +@@ pnpm-lock.yaml: snapshots: + + react: 19.2.3 + + react-native: 0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6) + + react-native-safe-area-context: 5.7.0(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + +- react-native-screens: 4.26.2(patch_hash=8156dd0f3407822404793cfdaa95639a36b62102f4507c981b8be83600bb382d)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + ++ react-native-screens: 4.26.2(patch_hash=149bef30a66351ea9b26b42f87b78c539cb52b880f2387bb323ec80dcac84006)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + + sf-symbols-typescript: 2.2.0 + + warn-once: 0.1.1 + + transitivePeerDependencies: + +@@ pnpm-lock.yaml: snapshots: + + '@rolldown/binding-win32-x64-msvc@1.1.5': + + optional: true + + + +- '@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)': + ++ '@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)': + + dependencies: + + '@babel/core': 7.29.7 + + picomatch: 4.0.4 + +@@ pnpm-lock.yaml: snapshots: + + optionalDependencies: + + '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7) + + '@babel/runtime': 7.29.7 + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + + + '@rolldown/pluginutils@1.0.0-rc.17': + + optional: true + +@@ pnpm-lock.yaml: snapshots: + + + + '@tabler/icons@3.44.0': {} + + + +- '@tailwindcss/node@4.3.3': + ++ '@tailwindcss/node@4.3.0': + + dependencies: + + '@jridgewell/remapping': 2.3.5 + +- enhanced-resolve: 5.24.5 + ++ enhanced-resolve: 5.22.1 + + jiti: 2.7.0 + +- lightningcss: 1.33.0 + ++ lightningcss: 1.32.0 + + magic-string: 0.30.21 + + source-map-js: 1.2.1 + +- tailwindcss: 4.3.3 + ++ tailwindcss: 4.3.0 + ++ + ++ '@tailwindcss/node@4.3.2': + ++ dependencies: + ++ '@jridgewell/remapping': 2.3.5 + ++ enhanced-resolve: 5.21.6 + ++ jiti: 2.7.0 + ++ lightningcss: 1.32.0 + ++ magic-string: 0.30.21 + ++ source-map-js: 1.2.1 + ++ tailwindcss: 4.3.2 + ++ + ++ '@tailwindcss/oxide-android-arm64@4.3.0': + ++ optional: true + ++ + ++ '@tailwindcss/oxide-android-arm64@4.3.2': + ++ optional: true + ++ + ++ '@tailwindcss/oxide-darwin-arm64@4.3.0': + ++ optional: true + ++ + ++ '@tailwindcss/oxide-darwin-arm64@4.3.2': + ++ optional: true + ++ + ++ '@tailwindcss/oxide-darwin-x64@4.3.0': + ++ optional: true + ++ + ++ '@tailwindcss/oxide-darwin-x64@4.3.2': + ++ optional: true + ++ + ++ '@tailwindcss/oxide-freebsd-x64@4.3.0': + ++ optional: true + ++ + ++ '@tailwindcss/oxide-freebsd-x64@4.3.2': + ++ optional: true + ++ + ++ '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': + ++ optional: true + ++ + ++ '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + ++ optional: true + + + +- '@tailwindcss/oxide-android-arm64@4.3.3': + ++ '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': + + optional: true + + + +- '@tailwindcss/oxide-darwin-arm64@4.3.3': + ++ '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + + optional: true + + + +- '@tailwindcss/oxide-darwin-x64@4.3.3': + ++ '@tailwindcss/oxide-linux-arm64-musl@4.3.0': + + optional: true + + + +- '@tailwindcss/oxide-freebsd-x64@4.3.3': + ++ '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + + optional: true + + + +- '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + ++ '@tailwindcss/oxide-linux-x64-gnu@4.3.0': + + optional: true + + + +- '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + ++ '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + + optional: true + + + +- '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + ++ '@tailwindcss/oxide-linux-x64-musl@4.3.0': + + optional: true + + + +- '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + ++ '@tailwindcss/oxide-linux-x64-musl@4.3.2': + + optional: true + + + +- '@tailwindcss/oxide-linux-x64-musl@4.3.3': + ++ '@tailwindcss/oxide-wasm32-wasi@4.3.0': + + optional: true + + + +- '@tailwindcss/oxide-wasm32-wasi@4.3.3': + ++ '@tailwindcss/oxide-wasm32-wasi@4.3.2': + + optional: true + + + +- '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + ++ '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': + + optional: true + + + +- '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + ++ '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + + optional: true + + + +- '@tailwindcss/oxide@4.3.3': + ++ '@tailwindcss/oxide-win32-x64-msvc@4.3.0': + ++ optional: true + ++ + ++ '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + ++ optional: true + ++ + ++ '@tailwindcss/oxide@4.3.0': + + optionalDependencies: + +- '@tailwindcss/oxide-android-arm64': 4.3.3 + +- '@tailwindcss/oxide-darwin-arm64': 4.3.3 + +- '@tailwindcss/oxide-darwin-x64': 4.3.3 + +- '@tailwindcss/oxide-freebsd-x64': 4.3.3 + +- '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 + +- '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 + +- '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 + +- '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 + +- '@tailwindcss/oxide-linux-x64-musl': 4.3.3 + +- '@tailwindcss/oxide-wasm32-wasi': 4.3.3 + +- '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 + +- '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 + +- + +- '@tailwindcss/vite@4.3.3(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))': + +- dependencies: + +- '@tailwindcss/node': 4.3.3 + +- '@tailwindcss/oxide': 4.3.3 + +- tailwindcss: 4.3.3 + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ '@tailwindcss/oxide-android-arm64': 4.3.0 + ++ '@tailwindcss/oxide-darwin-arm64': 4.3.0 + ++ '@tailwindcss/oxide-darwin-x64': 4.3.0 + ++ '@tailwindcss/oxide-freebsd-x64': 4.3.0 + ++ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.0 + ++ '@tailwindcss/oxide-linux-arm64-gnu': 4.3.0 + ++ '@tailwindcss/oxide-linux-arm64-musl': 4.3.0 + ++ '@tailwindcss/oxide-linux-x64-gnu': 4.3.0 + ++ '@tailwindcss/oxide-linux-x64-musl': 4.3.0 + ++ '@tailwindcss/oxide-wasm32-wasi': 4.3.0 + ++ '@tailwindcss/oxide-win32-arm64-msvc': 4.3.0 + ++ '@tailwindcss/oxide-win32-x64-msvc': 4.3.0 + ++ + ++ '@tailwindcss/oxide@4.3.2': + ++ optionalDependencies: + ++ '@tailwindcss/oxide-android-arm64': 4.3.2 + ++ '@tailwindcss/oxide-darwin-arm64': 4.3.2 + ++ '@tailwindcss/oxide-darwin-x64': 4.3.2 + ++ '@tailwindcss/oxide-freebsd-x64': 4.3.2 + ++ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.2 + ++ '@tailwindcss/oxide-linux-arm64-gnu': 4.3.2 + ++ '@tailwindcss/oxide-linux-arm64-musl': 4.3.2 + ++ '@tailwindcss/oxide-linux-x64-gnu': 4.3.2 + ++ '@tailwindcss/oxide-linux-x64-musl': 4.3.2 + ++ '@tailwindcss/oxide-wasm32-wasi': 4.3.2 + ++ '@tailwindcss/oxide-win32-arm64-msvc': 4.3.2 + ++ '@tailwindcss/oxide-win32-x64-msvc': 4.3.2 + ++ + ++ '@tailwindcss/vite@4.3.0(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))': + ++ dependencies: + ++ '@tailwindcss/node': 4.3.0 + ++ '@tailwindcss/oxide': 4.3.0 + ++ tailwindcss: 4.3.0 + ++ vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + + + '@tanstack/devtools-event-client@0.4.3': {} + + + +@@ pnpm-lock.yaml: snapshots: + + transitivePeerDependencies: + + - supports-color + + + +- '@tanstack/router-plugin@1.168.13(@tanstack/react-router@1.170.10(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))': + ++ '@tanstack/router-plugin@1.168.13(@tanstack/react-router@1.170.10(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))': + + dependencies: + + '@babel/core': 7.29.7 + + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + +@@ pnpm-lock.yaml: snapshots: + + zod: 4.4.3 + + optionalDependencies: + + '@tanstack/react-router': 1.170.10(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + transitivePeerDependencies: + + - supports-color + + + +@@ pnpm-lock.yaml: snapshots: + + dependencies: + + '@types/yargs-parser': 21.0.3 + + + +- '@types/yauzl@3.4.0': + +- dependencies: + +- '@types/node': 24.12.4 + +- + + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260604.1': + + optional: true + + + +@@ pnpm-lock.yaml: snapshots: + + optionalDependencies: + + ajv: 6.15.0 + + + +- '@vitejs/plugin-react@6.0.2(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5))(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(babel-plugin-react-compiler@1.0.0)': + ++ '@vitejs/plugin-react@6.0.2(@rolldown/plugin-babel@0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5))(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(babel-plugin-react-compiler@1.0.0)': + + dependencies: + + '@rolldown/pluginutils': 1.0.1 + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + optionalDependencies: + +- '@rolldown/plugin-babel': 0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5) + ++ '@rolldown/plugin-babel': 0.2.3(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5) + + babel-plugin-react-compiler: 1.0.0 + + + +- '@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.11)': + ++ '@vitest/browser-preview@4.1.9(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9)': + + dependencies: + + '@testing-library/dom': 10.4.1 + + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) + +- '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.11) + +- vitest: 4.1.11(@types/node@24.12.4)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + ++ '@vitest/browser': 4.1.9(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9) + ++ vitest: 4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + + transitivePeerDependencies: + + - bufferutil + + - msw + + - utf-8-validate + - vite + + -- '@vitest/browser@4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9)': + +- '@vitest/browser@4.1.11(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.11)': + + '@vitest/browser@4.1.9(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9)': + dependencies: + '@blazediff/core': 1.9.1 + - '@vitest/mocker': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + -@@ pnpm-lock.yaml: snapshots: + +- '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + +- '@vitest/utils': 4.1.11 + ++ '@vitest/mocker': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + ++ '@vitest/utils': 4.1.9 + + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.0 + -- vitest: 4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + +- vitest: 4.1.11(@types/node@24.12.4)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + + vitest: 4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + transitivePeerDependencies: + - bufferutil + @@ pnpm-lock.yaml: snapshots: + + - utf-8-validate + + - vite + + + +- '@vitest/expect@4.1.11': + ++ '@vitest/expect@4.1.9': + + dependencies: + + '@standard-schema/spec': 1.1.0 + + '@types/chai': 5.2.3 + +- '@vitest/spy': 4.1.11 + +- '@vitest/utils': 4.1.11 + ++ '@vitest/spy': 4.1.9 + ++ '@vitest/utils': 4.1.9 + + chai: 6.2.2 + + tinyrainbow: 3.1.0 + + + +- '@vitest/mocker@4.1.11(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))': + ++ '@vitest/mocker@4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))': + + dependencies: + +- '@vitest/spy': 4.1.11 + ++ '@vitest/spy': 4.1.9 + + estree-walker: 3.0.3 + + magic-string: 0.30.21 + + optionalDependencies: + + msw: 2.12.11(@types/node@24.12.4)(typescript@6.0.3) + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + + +- '@vitest/pretty-format@4.1.11': + ++ '@vitest/pretty-format@4.1.9': + + dependencies: + + tinyrainbow: 3.1.0 + + + +- '@vitest/runner@4.1.11': + ++ '@vitest/runner@4.1.9': + + dependencies: + +- '@vitest/utils': 4.1.11 + ++ '@vitest/utils': 4.1.9 + + pathe: 2.0.3 + + + +- '@vitest/snapshot@4.1.11': + ++ '@vitest/snapshot@4.1.9': + + dependencies: + +- '@vitest/pretty-format': 4.1.11 + +- '@vitest/utils': 4.1.11 + ++ '@vitest/pretty-format': 4.1.9 + ++ '@vitest/utils': 4.1.9 + + magic-string: 0.30.21 + + pathe: 2.0.3 + + + +- '@vitest/spy@4.1.11': {} + ++ '@vitest/spy@4.1.9': {} + + + +- '@vitest/utils@4.1.11': + ++ '@vitest/utils@4.1.9': + + dependencies: + +- '@vitest/pretty-format': 4.1.11 + ++ '@vitest/pretty-format': 4.1.9 + + convert-source-map: 2.0.0 + + tinyrainbow: 3.1.0 + + + +- '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)': + ++ '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)': + + dependencies: + +- '@oxc-project/runtime': 0.146.0 + +- '@oxc-project/types': 0.146.0 + +- lightningcss: 1.33.0 + ++ '@oxc-project/runtime': 0.138.0 + ++ '@oxc-project/types': 0.138.0 + ++ lightningcss: 1.32.0 + + postcss: 8.5.15 + +- yuku-codegen: 0.5.48 + +- yuku-parser: 0.5.48 + + optionalDependencies: + + '@types/node': 24.12.4 + +- '@voidzero-dev/vite-plus-darwin-arm64': 0.3.0 + +- '@voidzero-dev/vite-plus-darwin-x64': 0.3.0 + +- '@voidzero-dev/vite-plus-linux-arm64-gnu': 0.3.0 + +- '@voidzero-dev/vite-plus-linux-arm64-musl': 0.3.0 + +- '@voidzero-dev/vite-plus-linux-x64-gnu': 0.3.0 + +- '@voidzero-dev/vite-plus-linux-x64-musl': 0.3.0 + +- '@voidzero-dev/vite-plus-win32-arm64-msvc': 0.3.0 + +- '@voidzero-dev/vite-plus-win32-x64-msvc': 0.3.0 + + esbuild: 0.28.1 + + fsevents: 2.3.3 + + jiti: 2.7.0 + +@@ pnpm-lock.yaml: snapshots: + + unrun: 0.2.39 + + yaml: 2.9.0 + + + +- '@voidzero-dev/vite-plus-darwin-arm64@0.3.0': + ++ '@voidzero-dev/vite-plus-darwin-arm64@0.2.2': + + optional: true + + + +- '@voidzero-dev/vite-plus-darwin-x64@0.3.0': + ++ '@voidzero-dev/vite-plus-darwin-x64@0.2.2': + + optional: true + + + +- '@voidzero-dev/vite-plus-linux-arm64-gnu@0.3.0': + ++ '@voidzero-dev/vite-plus-linux-arm64-gnu@0.2.2': + + optional: true + + + +- '@voidzero-dev/vite-plus-linux-arm64-musl@0.3.0': + ++ '@voidzero-dev/vite-plus-linux-arm64-musl@0.2.2': + + optional: true + + + +- '@voidzero-dev/vite-plus-linux-x64-gnu@0.3.0': + ++ '@voidzero-dev/vite-plus-linux-x64-gnu@0.2.2': + + optional: true + + + +- '@voidzero-dev/vite-plus-linux-x64-musl@0.3.0': + ++ '@voidzero-dev/vite-plus-linux-x64-musl@0.2.2': + + optional: true + + + +- '@voidzero-dev/vite-plus-win32-arm64-msvc@0.3.0': + ++ '@voidzero-dev/vite-plus-win32-arm64-msvc@0.2.2': + + optional: true + + + +- '@voidzero-dev/vite-plus-win32-x64-msvc@0.3.0': + ++ '@voidzero-dev/vite-plus-win32-x64-msvc@0.2.2': + + optional: true + + + + '@volar/kit@2.4.28(typescript@6.0.3)': + +@@ pnpm-lock.yaml: snapshots: + + + + '@xmldom/xmldom@0.9.10': {} + + + +- '@yuku-codegen/binding-darwin-arm64@0.5.48': + +- optional: true + +- + +- '@yuku-codegen/binding-darwin-x64@0.5.48': + +- optional: true + +- + +- '@yuku-codegen/binding-freebsd-x64@0.5.48': + +- optional: true + +- + +- '@yuku-codegen/binding-linux-arm-gnu@0.5.48': + +- optional: true + +- + +- '@yuku-codegen/binding-linux-arm-musl@0.5.48': + +- optional: true + +- + +- '@yuku-codegen/binding-linux-arm64-gnu@0.5.48': + +- optional: true + +- + +- '@yuku-codegen/binding-linux-arm64-musl@0.5.48': + +- optional: true + +- + +- '@yuku-codegen/binding-linux-x64-gnu@0.5.48': + +- optional: true + +- + +- '@yuku-codegen/binding-linux-x64-musl@0.5.48': + +- optional: true + +- + +- '@yuku-codegen/binding-win32-arm64@0.5.48': + +- optional: true + +- + +- '@yuku-codegen/binding-win32-x64@0.5.48': + +- optional: true + +- + +- '@yuku-parser/binding-darwin-arm64@0.5.48': + +- optional: true + +- + +- '@yuku-parser/binding-darwin-x64@0.5.48': + +- optional: true + +- + +- '@yuku-parser/binding-freebsd-x64@0.5.48': + +- optional: true + +- + +- '@yuku-parser/binding-linux-arm-gnu@0.5.48': + +- optional: true + +- + +- '@yuku-parser/binding-linux-arm-musl@0.5.48': + +- optional: true + +- + +- '@yuku-parser/binding-linux-arm64-gnu@0.5.48': + +- optional: true + +- + +- '@yuku-parser/binding-linux-arm64-musl@0.5.48': + +- optional: true + +- + +- '@yuku-parser/binding-linux-x64-gnu@0.5.48': + +- optional: true + +- + +- '@yuku-parser/binding-linux-x64-musl@0.5.48': + +- optional: true + +- + +- '@yuku-parser/binding-win32-arm64@0.5.48': + +- optional: true + +- + +- '@yuku-parser/binding-win32-x64@0.5.48': + +- optional: true + +- + +- '@yuku-toolchain/types@0.5.43': {} + +- + + '@yuuang/ffi-rs-android-arm64@1.3.2': + + optional: true + + + +@@ pnpm-lock.yaml: snapshots: + + json-schema-traverse: 1.0.0 + + require-from-string: 2.0.2 + + + +- alchemy@2.0.0-beta.65(2233d007cbd93ff91712c637e233494f): + ++ alchemy@2.0.0-beta.65(00c448ade6580e73d10ccfe1b32cee97): + + dependencies: + + '@alchemy.run/node-utils': 0.0.5 + + '@aws-sdk/credential-providers': 3.1062.0 + +@@ pnpm-lock.yaml: snapshots: + + '@distilled.cloud/aws': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + + '@distilled.cloud/axiom': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + + '@distilled.cloud/cloudflare': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + +- '@distilled.cloud/cloudflare-rolldown-plugin': 0.13.10(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1) + ++ '@distilled.cloud/cloudflare-rolldown-plugin': 0.13.10(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(rolldown@1.1.5)(workerd@1.20260704.1) + + '@distilled.cloud/cloudflare-runtime': 0.13.10(@distilled.cloud/cloudflare@0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/platform-bun@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(utf-8-validate@6.0.6))(@effect/platform-node@4.0.0-beta.103(bufferutil@4.1.0)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(ioredis@5.11.0)(utf-8-validate@6.0.6))(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + +- '@distilled.cloud/cloudflare-vite-plugin': 0.13.10(86e3ed6000e5955518fd9c0dea8322a9) + ++ '@distilled.cloud/cloudflare-vite-plugin': 0.13.10(f97c3167f1a1990dddb83bff73e575e5) + + '@distilled.cloud/core': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + + '@distilled.cloud/neon': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + + '@distilled.cloud/planetscale': 0.30.2(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + +@@ pnpm-lock.yaml: snapshots: + + '@effect/sql-pg': 4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)) + + drizzle-kit: 1.0.0-rc.4 + + drizzle-orm: 1.0.0-rc.4(@cloudflare/workers-types@4.20260604.1)(@effect/sql-d1@4.0.0-beta.101(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/sql-pg@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@effect/sql-sqlite-bun@4.0.0-beta.103(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)))(@libsql/client@0.17.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(bun-types@1.3.14)(effect@4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6))(expo-sqlite@57.0.2(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(mysql2@3.22.4(@types/node@24.12.4))(pg@8.21.0)(zod@4.4.3) + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + + transitivePeerDependencies: + + - '@mongodb-js/zstd' + +@@ pnpm-lock.yaml: snapshots: + + unist-util-visit: 5.1.0 + + unstorage: 1.17.5(aws4fetch@1.0.20)(idb-keyval@6.2.1)(ioredis@5.11.0) + + vfile: 6.0.3 + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + +- vitefu: 1.1.3(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)) + ++ vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ vitefu: 1.1.3(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)) + + xxhash-wasm: 1.1.0 + + yargs-parser: 22.0.0 + + zod: 4.4.3 + +@@ pnpm-lock.yaml: snapshots: + + dependencies: + + once: 1.4.0 + + + +- enhanced-resolve@5.24.5: + ++ enhanced-resolve@5.21.6: + ++ dependencies: + ++ graceful-fs: 4.2.11 + ++ tapable: 2.3.3 + ++ + ++ enhanced-resolve@5.22.1: + + dependencies: + + graceful-fs: 4.2.11 + + tapable: 2.3.3 + +@@ pnpm-lock.yaml: snapshots: + + + + expo-server@57.0.3: {} + + + +- expo-sharing@57.0.17(patch_hash=8d2e3b10eb3f52036a9a086800180ec6cebf3b75bccc5b1775117a7244d4ac45)(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)(typescript@6.0.3): + ++ expo-sharing@57.0.16(patch_hash=8d2e3b10eb3f52036a9a086800180ec6cebf3b75bccc5b1775117a7244d4ac45)(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)(typescript@6.0.3): + + dependencies: + + '@expo/config-plugins': 57.0.9(typescript@6.0.3) + + '@expo/config-types': 57.0.2 + +@@ pnpm-lock.yaml: snapshots: + + transitivePeerDependencies: + + - supports-color + + + +- lightningcss-android-arm64@1.33.0: + ++ lightningcss-android-arm64@1.32.0: + ++ optional: true + ++ + ++ lightningcss-darwin-arm64@1.30.1: + ++ optional: true + ++ + ++ lightningcss-darwin-arm64@1.32.0: + ++ optional: true + ++ + ++ lightningcss-darwin-x64@1.30.1: + + optional: true + + + +- lightningcss-darwin-arm64@1.33.0: + ++ lightningcss-darwin-x64@1.32.0: + + optional: true + + + +- lightningcss-darwin-x64@1.33.0: + ++ lightningcss-freebsd-x64@1.30.1: + + optional: true + + + +- lightningcss-freebsd-x64@1.33.0: + ++ lightningcss-freebsd-x64@1.32.0: + + optional: true + + + +- lightningcss-linux-arm-gnueabihf@1.33.0: + ++ lightningcss-linux-arm-gnueabihf@1.30.1: + + optional: true + + + +- lightningcss-linux-arm64-gnu@1.33.0: + ++ lightningcss-linux-arm-gnueabihf@1.32.0: + + optional: true + + + +- lightningcss-linux-arm64-musl@1.33.0: + ++ lightningcss-linux-arm64-gnu@1.30.1: + + optional: true + + + +- lightningcss-linux-x64-gnu@1.33.0: + ++ lightningcss-linux-arm64-gnu@1.32.0: + + optional: true + + + +- lightningcss-linux-x64-musl@1.33.0: + ++ lightningcss-linux-arm64-musl@1.30.1: + + optional: true + + + +- lightningcss-win32-arm64-msvc@1.33.0: + ++ lightningcss-linux-arm64-musl@1.32.0: + + optional: true + + + +- lightningcss-win32-x64-msvc@1.33.0: + ++ lightningcss-linux-x64-gnu@1.30.1: + + optional: true + + + +- lightningcss@1.33.0: + ++ lightningcss-linux-x64-gnu@1.32.0: + ++ optional: true + ++ + ++ lightningcss-linux-x64-musl@1.30.1: + ++ optional: true + ++ + ++ lightningcss-linux-x64-musl@1.32.0: + ++ optional: true + ++ + ++ lightningcss-win32-arm64-msvc@1.30.1: + ++ optional: true + ++ + ++ lightningcss-win32-arm64-msvc@1.32.0: + ++ optional: true + ++ + ++ lightningcss-win32-x64-msvc@1.30.1: + ++ optional: true + ++ + ++ lightningcss-win32-x64-msvc@1.32.0: + ++ optional: true + ++ + ++ lightningcss@1.30.1: + ++ dependencies: + ++ detect-libc: 2.1.2 + ++ optionalDependencies: + ++ lightningcss-darwin-arm64: 1.30.1 + ++ lightningcss-darwin-x64: 1.30.1 + ++ lightningcss-freebsd-x64: 1.30.1 + ++ lightningcss-linux-arm-gnueabihf: 1.30.1 + ++ lightningcss-linux-arm64-gnu: 1.30.1 + ++ lightningcss-linux-arm64-musl: 1.30.1 + ++ lightningcss-linux-x64-gnu: 1.30.1 + ++ lightningcss-linux-x64-musl: 1.30.1 + ++ lightningcss-win32-arm64-msvc: 1.30.1 + ++ lightningcss-win32-x64-msvc: 1.30.1 + ++ + ++ lightningcss@1.32.0: + + dependencies: + + detect-libc: 2.1.2 + + optionalDependencies: + +- lightningcss-android-arm64: 1.33.0 + +- lightningcss-darwin-arm64: 1.33.0 + +- lightningcss-darwin-x64: 1.33.0 + +- lightningcss-freebsd-x64: 1.33.0 + +- lightningcss-linux-arm-gnueabihf: 1.33.0 + +- lightningcss-linux-arm64-gnu: 1.33.0 + +- lightningcss-linux-arm64-musl: 1.33.0 + +- lightningcss-linux-x64-gnu: 1.33.0 + +- lightningcss-linux-x64-musl: 1.33.0 + +- lightningcss-win32-arm64-msvc: 1.33.0 + +- lightningcss-win32-x64-msvc: 1.33.0 + ++ lightningcss-android-arm64: 1.32.0 + ++ lightningcss-darwin-arm64: 1.32.0 + ++ lightningcss-darwin-x64: 1.32.0 + ++ lightningcss-freebsd-x64: 1.32.0 + ++ lightningcss-linux-arm-gnueabihf: 1.32.0 + ++ lightningcss-linux-arm64-gnu: 1.32.0 + ++ lightningcss-linux-arm64-musl: 1.32.0 + ++ lightningcss-linux-x64-gnu: 1.32.0 + ++ lightningcss-linux-x64-musl: 1.32.0 + ++ lightningcss-win32-arm64-msvc: 1.32.0 + ++ lightningcss-win32-x64-msvc: 1.32.0 + + + + locate-path@3.0.0: + + dependencies: + +@@ pnpm-lock.yaml: snapshots: + + outvariant@1.4.3: + + optional: true + + + +- oxfmt@0.64.0(vite-plus@0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)): + ++ oxfmt@0.57.0(vite-plus@0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)): + + dependencies: + + tinypool: 2.1.0 + + optionalDependencies: + +- '@oxfmt/binding-android-arm-eabi': 0.64.0 + +- '@oxfmt/binding-android-arm64': 0.64.0 + +- '@oxfmt/binding-darwin-arm64': 0.64.0 + +- '@oxfmt/binding-darwin-x64': 0.64.0 + +- '@oxfmt/binding-freebsd-x64': 0.64.0 + +- '@oxfmt/binding-linux-arm-gnueabihf': 0.64.0 + +- '@oxfmt/binding-linux-arm-musleabihf': 0.64.0 + +- '@oxfmt/binding-linux-arm64-gnu': 0.64.0 + +- '@oxfmt/binding-linux-arm64-musl': 0.64.0 + +- '@oxfmt/binding-linux-ppc64-gnu': 0.64.0 + +- '@oxfmt/binding-linux-riscv64-gnu': 0.64.0 + +- '@oxfmt/binding-linux-riscv64-musl': 0.64.0 + +- '@oxfmt/binding-linux-s390x-gnu': 0.64.0 + +- '@oxfmt/binding-linux-x64-gnu': 0.64.0 + +- '@oxfmt/binding-linux-x64-musl': 0.64.0 + +- '@oxfmt/binding-openharmony-arm64': 0.64.0 + +- '@oxfmt/binding-win32-arm64-msvc': 0.64.0 + +- '@oxfmt/binding-win32-ia32-msvc': 0.64.0 + +- '@oxfmt/binding-win32-x64-msvc': 0.64.0 + +- vite-plus: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + +- + +- oxlint-tsgolint@7.0.2001: + ++ '@oxfmt/binding-android-arm-eabi': 0.57.0 + ++ '@oxfmt/binding-android-arm64': 0.57.0 + ++ '@oxfmt/binding-darwin-arm64': 0.57.0 + ++ '@oxfmt/binding-darwin-x64': 0.57.0 + ++ '@oxfmt/binding-freebsd-x64': 0.57.0 + ++ '@oxfmt/binding-linux-arm-gnueabihf': 0.57.0 + ++ '@oxfmt/binding-linux-arm-musleabihf': 0.57.0 + ++ '@oxfmt/binding-linux-arm64-gnu': 0.57.0 + ++ '@oxfmt/binding-linux-arm64-musl': 0.57.0 + ++ '@oxfmt/binding-linux-ppc64-gnu': 0.57.0 + ++ '@oxfmt/binding-linux-riscv64-gnu': 0.57.0 + ++ '@oxfmt/binding-linux-riscv64-musl': 0.57.0 + ++ '@oxfmt/binding-linux-s390x-gnu': 0.57.0 + ++ '@oxfmt/binding-linux-x64-gnu': 0.57.0 + ++ '@oxfmt/binding-linux-x64-musl': 0.57.0 + ++ '@oxfmt/binding-openharmony-arm64': 0.57.0 + ++ '@oxfmt/binding-win32-arm64-msvc': 0.57.0 + ++ '@oxfmt/binding-win32-ia32-msvc': 0.57.0 + ++ '@oxfmt/binding-win32-x64-msvc': 0.57.0 + ++ vite-plus: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ + ++ oxlint-tsgolint@0.24.0: + + optionalDependencies: + +- '@oxlint-tsgolint/darwin-arm64': 7.0.2001 + +- '@oxlint-tsgolint/darwin-x64': 7.0.2001 + +- '@oxlint-tsgolint/linux-arm64': 7.0.2001 + +- '@oxlint-tsgolint/linux-x64': 7.0.2001 + +- '@oxlint-tsgolint/win32-arm64': 7.0.2001 + +- '@oxlint-tsgolint/win32-x64': 7.0.2001 + +- + +- oxlint@1.79.0(oxlint-tsgolint@7.0.2001)(vite-plus@0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)): + ++ '@oxlint-tsgolint/darwin-arm64': 0.24.0 + ++ '@oxlint-tsgolint/darwin-x64': 0.24.0 + ++ '@oxlint-tsgolint/linux-arm64': 0.24.0 + ++ '@oxlint-tsgolint/linux-x64': 0.24.0 + ++ '@oxlint-tsgolint/win32-arm64': 0.24.0 + ++ '@oxlint-tsgolint/win32-x64': 0.24.0 + ++ + ++ oxlint@1.72.0(oxlint-tsgolint@0.24.0)(vite-plus@0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)): + + optionalDependencies: + +- '@oxlint/binding-android-arm-eabi': 1.79.0 + +- '@oxlint/binding-android-arm64': 1.79.0 + +- '@oxlint/binding-darwin-arm64': 1.79.0 + +- '@oxlint/binding-darwin-x64': 1.79.0 + +- '@oxlint/binding-freebsd-x64': 1.79.0 + +- '@oxlint/binding-linux-arm-gnueabihf': 1.79.0 + +- '@oxlint/binding-linux-arm-musleabihf': 1.79.0 + +- '@oxlint/binding-linux-arm64-gnu': 1.79.0 + +- '@oxlint/binding-linux-arm64-musl': 1.79.0 + +- '@oxlint/binding-linux-ppc64-gnu': 1.79.0 + +- '@oxlint/binding-linux-riscv64-gnu': 1.79.0 + +- '@oxlint/binding-linux-riscv64-musl': 1.79.0 + +- '@oxlint/binding-linux-s390x-gnu': 1.79.0 + +- '@oxlint/binding-linux-x64-gnu': 1.79.0 + +- '@oxlint/binding-linux-x64-musl': 1.79.0 + +- '@oxlint/binding-openharmony-arm64': 1.79.0 + +- '@oxlint/binding-win32-arm64-msvc': 1.79.0 + +- '@oxlint/binding-win32-ia32-msvc': 1.79.0 + +- '@oxlint/binding-win32-x64-msvc': 1.79.0 + +- oxlint-tsgolint: 7.0.2001 + +- vite-plus: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + ++ '@oxlint/binding-android-arm-eabi': 1.72.0 + ++ '@oxlint/binding-android-arm64': 1.72.0 + ++ '@oxlint/binding-darwin-arm64': 1.72.0 + ++ '@oxlint/binding-darwin-x64': 1.72.0 + ++ '@oxlint/binding-freebsd-x64': 1.72.0 + ++ '@oxlint/binding-linux-arm-gnueabihf': 1.72.0 + ++ '@oxlint/binding-linux-arm-musleabihf': 1.72.0 + ++ '@oxlint/binding-linux-arm64-gnu': 1.72.0 + ++ '@oxlint/binding-linux-arm64-musl': 1.72.0 + ++ '@oxlint/binding-linux-ppc64-gnu': 1.72.0 + ++ '@oxlint/binding-linux-riscv64-gnu': 1.72.0 + ++ '@oxlint/binding-linux-riscv64-musl': 1.72.0 + ++ '@oxlint/binding-linux-s390x-gnu': 1.72.0 + ++ '@oxlint/binding-linux-x64-gnu': 1.72.0 + ++ '@oxlint/binding-linux-x64-musl': 1.72.0 + ++ '@oxlint/binding-openharmony-arm64': 1.72.0 + ++ '@oxlint/binding-win32-arm64-msvc': 1.72.0 + ++ '@oxlint/binding-win32-ia32-msvc': 1.72.0 + ++ '@oxlint/binding-win32-x64-msvc': 1.72.0 + ++ oxlint-tsgolint: 0.24.0 + ++ vite-plus: 0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + + + + p-cancelable@2.1.1: {} + + + +@@ pnpm-lock.yaml: snapshots: + + + + pe-library@0.4.1: {} + + + +- pend@1.2.0: {} + +- + + pg-cloudflare@1.4.0: + + optional: true + + + +@@ pnpm-lock.yaml: snapshots: + + react: 19.2.3 + + react-native: 0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6) + + + +- react-native-screens@4.26.2(patch_hash=8156dd0f3407822404793cfdaa95639a36b62102f4507c981b8be83600bb382d)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3): + ++ react-native-screens@4.26.2(patch_hash=149bef30a66351ea9b26b42f87b78c539cb52b880f2387bb323ec80dcac84006)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3): + + dependencies: + + react: 19.2.3 + + react-freeze: 1.0.4(react@19.2.3) + +@@ pnpm-lock.yaml: snapshots: + + + + tailwind-merge@3.6.0: {} + + + +- tailwindcss@4.3.3: {} + ++ tailwindcss@4.3.0: {} + ++ + ++ tailwindcss@4.3.2: {} + + + + tapable@2.3.3: {} + + + +@@ pnpm-lock.yaml: snapshots: + + + + universalify@2.0.1: {} + + + +- uniwind@1.11.0(patch_hash=17d92be2eec71bb6396b402e8d034968e54b28746876d7977cb3139655f42b90)(@expo/metro-config@57.0.12(patch_hash=96f1a75347e6ea02dc4b7034ace815d8ee39e18b8166ebfb573d9e58328f0dc2)(bufferutil@4.1.0)(expo@57.0.18)(typescript@6.0.3)(utf-8-validate@6.0.6))(metro-cache@0.84.5)(metro-transform-worker@0.84.5(bufferutil@4.1.0)(utf-8-validate@6.0.6))(metro@0.84.5(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)(tailwindcss@4.3.3): + ++ uniwind@1.11.0(patch_hash=329a77525509623d763b738152dbd00ab392cdcdd9fb6ed2b4a20e086e437196)(@expo/metro-config@57.0.12(patch_hash=96f1a75347e6ea02dc4b7034ace815d8ee39e18b8166ebfb573d9e58328f0dc2)(bufferutil@4.1.0)(expo@57.0.18)(typescript@6.0.3)(utf-8-validate@6.0.6))(metro-cache@0.84.5)(metro-transform-worker@0.84.5(bufferutil@4.1.0)(utf-8-validate@6.0.6))(metro@0.84.5(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)(tailwindcss@4.3.0): + dependencies: + - '@oxc-project/types': 0.138.0 + - '@oxlint/plugins': 1.68.0 + -- '@vitest/browser': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9) + -- '@vitest/browser-preview': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9) + +- '@tailwindcss/node': 4.3.3 + +- '@tailwindcss/oxide': 4.3.3 + ++ '@tailwindcss/node': 4.3.2 + ++ '@tailwindcss/oxide': 4.3.2 + + culori: 4.0.2 + +- lightningcss: 1.33.0 + ++ lightningcss: 1.30.1 + + metro: 0.84.5(bufferutil@4.1.0)(utf-8-validate@6.0.6) + + metro-cache: 0.84.5 + + react: 19.2.3 + + react-native: 0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6) + +- tailwindcss: 4.3.3 + ++ tailwindcss: 4.3.0 + + optionalDependencies: + + '@expo/metro-config': 57.0.12(patch_hash=96f1a75347e6ea02dc4b7034ace815d8ee39e18b8166ebfb573d9e58328f0dc2)(bufferutil@4.1.0)(expo@57.0.18)(typescript@6.0.3)(utf-8-validate@6.0.6) + + metro-transform-worker: 0.84.5(bufferutil@4.1.0)(utf-8-validate@6.0.6) + +@@ pnpm-lock.yaml: snapshots: + + '@types/unist': 3.0.3 + + vfile-message: 4.0.3 + + + +- vite-plus@0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0): + +- dependencies: + +- '@oxc-project/types': 0.146.0 + +- '@oxlint/plugins': 1.79.0 + +- '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.11) + +- '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.11) + +- '@vitest/expect': 4.1.11 + +- '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + +- '@vitest/pretty-format': 4.1.11 + +- '@vitest/runner': 4.1.11 + +- '@vitest/snapshot': 4.1.11 + +- '@vitest/spy': 4.1.11 + +- '@vitest/utils': 4.1.11 + +- '@voidzero-dev/vite-plus-core': 0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0) + +- oxfmt: 0.64.0(vite-plus@0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)) + +- oxlint: 1.79.0(oxlint-tsgolint@7.0.2001)(vite-plus@0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)) + +- oxlint-tsgolint: 7.0.2001 + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + +- vitest: 4.1.11(@types/node@24.12.4)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + ++ vite-plus@0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0): + ++ dependencies: + ++ '@oxc-project/types': 0.138.0 + ++ '@oxlint/plugins': 1.68.0 + + '@vitest/browser': 4.1.9(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9) + + '@vitest/browser-preview': 4.1.9(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9) + - '@vitest/expect': 4.1.9 + - '@vitest/mocker': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + - '@vitest/pretty-format': 4.1.9 + -@@ pnpm-lock.yaml: snapshots: + - '@vitest/snapshot': 4.1.9 + - '@vitest/spy': 4.1.9 + - '@vitest/utils': 4.1.9 + -- '@voidzero-dev/vite-plus-core': 0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0) + -- oxfmt: 0.57.0(vite-plus@0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)) + -- oxlint: 1.72.0(oxlint-tsgolint@0.24.0)(vite-plus@0.2.2(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)) + -- oxlint-tsgolint: 0.24.0 + -- vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + -- vitest: 4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + ++ '@vitest/expect': 4.1.9 + ++ '@vitest/mocker': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + ++ '@vitest/pretty-format': 4.1.9 + ++ '@vitest/runner': 4.1.9 + ++ '@vitest/snapshot': 4.1.9 + ++ '@vitest/spy': 4.1.9 + ++ '@vitest/utils': 4.1.9 + + '@voidzero-dev/vite-plus-core': 0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0) + + oxfmt: 0.55.0(vite-plus@0.2.1(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)) + + oxlint: 1.70.0(oxlint-tsgolint@0.23.0)(vite-plus@0.2.1(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0)) + @@ pnpm-lock.yaml: snapshots: + + vite: '@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + vitest: 4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + optionalDependencies: + - '@voidzero-dev/vite-plus-darwin-arm64': 0.2.2 + - '@voidzero-dev/vite-plus-darwin-x64': 0.2.2 + +- '@voidzero-dev/vite-plus-darwin-arm64': 0.3.0 + +- '@voidzero-dev/vite-plus-darwin-x64': 0.3.0 + +- '@voidzero-dev/vite-plus-linux-arm64-gnu': 0.3.0 + +- '@voidzero-dev/vite-plus-linux-arm64-musl': 0.3.0 + +- '@voidzero-dev/vite-plus-linux-x64-gnu': 0.3.0 + +- '@voidzero-dev/vite-plus-linux-x64-musl': 0.3.0 + +- '@voidzero-dev/vite-plus-win32-arm64-msvc': 0.3.0 + +- '@voidzero-dev/vite-plus-win32-x64-msvc': 0.3.0 + ++ '@voidzero-dev/vite-plus-darwin-arm64': 0.2.2 + ++ '@voidzero-dev/vite-plus-darwin-x64': 0.2.2 + ++ '@voidzero-dev/vite-plus-linux-arm64-gnu': 0.2.2 + ++ '@voidzero-dev/vite-plus-linux-arm64-musl': 0.2.2 + ++ '@voidzero-dev/vite-plus-linux-x64-gnu': 0.2.2 + ++ '@voidzero-dev/vite-plus-linux-x64-musl': 0.2.2 + ++ '@voidzero-dev/vite-plus-win32-arm64-msvc': 0.2.2 + ++ '@voidzero-dev/vite-plus-win32-x64-msvc': 0.2.2 + + transitivePeerDependencies: + + - '@arethetypeswrong/core' + + - '@edge-runtime/vm' + @@ pnpm-lock.yaml: snapshots: + + - utf-8-validate + + - yaml + + + +- vitefu@1.1.3(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)): + ++ vitefu@1.1.3(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)): + optionalDependencies: + - vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + + -- vitest@4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)): + +- vitest@4.1.11(@types/node@24.12.4)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)): + + vitest@4.1.9(@types/node@24.12.4)(@vitest/browser-preview@4.1.9)(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)): + dependencies: + - '@vitest/expect': 4.1.9 + - '@vitest/mocker': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + +- '@vitest/expect': 4.1.11 + +- '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + +- '@vitest/pretty-format': 4.1.11 + +- '@vitest/runner': 4.1.11 + +- '@vitest/snapshot': 4.1.11 + +- '@vitest/spy': 4.1.11 + +- '@vitest/utils': 4.1.11 + ++ '@vitest/expect': 4.1.9 + ++ '@vitest/mocker': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3)) + ++ '@vitest/pretty-format': 4.1.9 + ++ '@vitest/runner': 4.1.9 + ++ '@vitest/snapshot': 4.1.9 + ++ '@vitest/spy': 4.1.9 + ++ '@vitest/utils': 4.1.9 + + es-module-lexer: 2.1.0 + + expect-type: 1.4.0 + + magic-string: 0.30.21 + @@ pnpm-lock.yaml: snapshots: + + tinyexec: 1.2.4 + + tinyglobby: 0.2.17 + + tinyrainbow: 3.1.0 + +- vite: '@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + ++ vite: '@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0)' + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.12.4 + -- '@vitest/browser-preview': 4.1.9(@voidzero-dev/vite-plus-core@0.2.2(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9) + +- '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.0(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.11) + + '@vitest/browser-preview': 4.1.9(@voidzero-dev/vite-plus-core@0.2.1(@types/node@24.12.4)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(yaml@2.9.0))(bufferutil@4.1.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(utf-8-validate@6.0.6)(vitest@4.1.9) + transitivePeerDependencies: + - msw + + +@@ pnpm-lock.yaml: snapshots: + + y18n: 5.0.8 + + yargs-parser: 21.1.1 + + + +- yauzl@3.4.0: + +- dependencies: + +- pend: 1.2.0 + +- + + yjs@13.6.31: + + dependencies: + + lib0: 0.2.117 + +@@ pnpm-lock.yaml: snapshots: + + + + yoga-layout@3.2.1: {} + + + +- yuku-codegen@0.5.48: + +- dependencies: + +- '@yuku-toolchain/types': 0.5.43 + +- optionalDependencies: + +- '@yuku-codegen/binding-darwin-arm64': 0.5.48 + +- '@yuku-codegen/binding-darwin-x64': 0.5.48 + +- '@yuku-codegen/binding-freebsd-x64': 0.5.48 + +- '@yuku-codegen/binding-linux-arm-gnu': 0.5.48 + +- '@yuku-codegen/binding-linux-arm-musl': 0.5.48 + +- '@yuku-codegen/binding-linux-arm64-gnu': 0.5.48 + +- '@yuku-codegen/binding-linux-arm64-musl': 0.5.48 + +- '@yuku-codegen/binding-linux-x64-gnu': 0.5.48 + +- '@yuku-codegen/binding-linux-x64-musl': 0.5.48 + +- '@yuku-codegen/binding-win32-arm64': 0.5.48 + +- '@yuku-codegen/binding-win32-x64': 0.5.48 + +- + +- yuku-parser@0.5.48: + +- dependencies: + +- '@yuku-toolchain/types': 0.5.43 + +- optionalDependencies: + +- '@yuku-parser/binding-darwin-arm64': 0.5.48 + +- '@yuku-parser/binding-darwin-x64': 0.5.48 + +- '@yuku-parser/binding-freebsd-x64': 0.5.48 + +- '@yuku-parser/binding-linux-arm-gnu': 0.5.48 + +- '@yuku-parser/binding-linux-arm-musl': 0.5.48 + +- '@yuku-parser/binding-linux-arm64-gnu': 0.5.48 + +- '@yuku-parser/binding-linux-arm64-musl': 0.5.48 + +- '@yuku-parser/binding-linux-x64-gnu': 0.5.48 + +- '@yuku-parser/binding-linux-x64-musl': 0.5.48 + +- '@yuku-parser/binding-win32-arm64': 0.5.48 + +- '@yuku-parser/binding-win32-x64': 0.5.48 + +- + + zod-to-json-schema@3.25.2(zod@4.4.3): + + dependencies: + + zod: 4.4.3 + 75: 5f2045fcc32 = 74: 0d4886de7c9 fix(web): align thread details panel controls and menus (#3606) + 76: 6c78a01831d ! 75: 8e2e8edd364 Switch Cursor provider to the official SDK + @@ Commit message + - refresh marketing copy to match the SDK runtime + + ## apps/marketing/src/pages/index.astro ## + -@@ apps/marketing/src/pages/index.astro: const mobileEndorsementRows = [ + +@@ apps/marketing/src/pages/index.astro: const screenshot = await getImage({ +
+
+
Cursor
+ @@ apps/server/src/provider/acp/CursorAcpSupport.test.ts (deleted) + - cwd: "/tmp/project", + - }); + - }); + +- + +- it("forces approval in full-access mode", () => { + +- expect(buildCursorAcpSpawnInput(undefined, "/tmp/project", undefined, "full-access")).toEqual({ + +- command: "cursor-agent", + +- args: ["--force", "acp"], + +- cwd: "/tmp/project", + +- }); + +- }); + +- + +- it("uses Cursor auto-review in auto mode", () => { + +- expect(buildCursorAcpSpawnInput(undefined, "/tmp/project", undefined, "auto")).toEqual({ + +- command: "cursor-agent", + +- args: ["--auto-review", "acp"], + +- cwd: "/tmp/project", + +- }); + +- }); + +- + +- it.each(["approval-required", "auto-accept-edits"] as const)( + +- "does not relax approval in %s mode", + +- (runtimeMode) => { + +- expect(buildCursorAcpSpawnInput(undefined, "/tmp/project", undefined, runtimeMode)).toEqual({ + +- command: "cursor-agent", + +- args: ["acp"], + +- cwd: "/tmp/project", + +- }); + +- }, + +- ); + -}); + - + -describe("applyCursorAcpModelSelection", () => { + 77: 695c57b4227 = 76: 61dec910677 Remove early access badges from Cursor and Grok + 78: f2711e089d1 = 77: 89eb3f0bb82 Allow provider switching via handoff in chat threads + 79: 5dc316e8ebe = 78: cb435247582 Fix Claude task turn mapping + 80: 25df2c7c873 ! 79: 2871cf85de7 feat: scheduled tasks (automations) (#3638) + @@ apps/web/src/components/settings/SettingsSidebarNav.tsx: import { + GitBranchIcon, + KeyboardIcon, + Link2Icon, + +@@ apps/web/src/components/settings/SettingsSidebarNav.tsx: import { + + SidebarMenu, + + SidebarMenuButton, + + SidebarMenuItem, + +- SidebarMenuSub, + +- SidebarMenuSubButton, + +- SidebarMenuSubItem, + + useSidebar, + + } from "../ui/sidebar"; + + import { SidebarUtilityMenu } from "../sidebar/SidebarChrome"; + @@ apps/web/src/components/settings/SettingsSidebarNav.tsx: const SETTINGS_SECTION_ICONS: Readonly< + "/settings/integrations": BlocksIcon, + "/settings/source-control": GitBranchIcon, + @@ apps/web/src/components/settings/SettingsSidebarNav.tsx: export const SETTINGS_N + - icon: SETTINGS_SECTION_ICONS[to], + -})); + - + +-const SETTINGS_PAGE_SECTIONS: Partial< + +- Readonly>> + +-> = { + +- "/settings/general": [ + +- { label: "Organization", targetId: "organization" }, + +- { label: "Behavior", targetId: "behavior" }, + +- { label: "Projects & threads", targetId: "projects-and-threads" }, + +- { label: "Confirmations", targetId: "confirmations" }, + +- { label: "Text generation", targetId: "text-generation" }, + +- { label: "About", targetId: "about" }, + +- { label: "Legacy features", targetId: "legacy-features" }, + +- ], + +- "/settings/appearance": [ + +- { label: "Colors & themes", targetId: "appearance" }, + +- { label: "Interface", targetId: "appearance-interface" }, + +- { label: "Typography", targetId: "typography" }, + +- ], + +- "/settings/source-control": [ + +- { label: "Version control", targetId: "source-control" }, + +- { label: "Text generation", targetId: "source-control-text-generation" }, + +- ], + +- "/settings/connections": [ + +- { label: "This environment", targetId: "connections-environment" }, + +- { label: "Remote environments", targetId: "remote-environments" }, + +- ], + +-}; + +- + -function SettingsSectionIcon({ to }: { to: SettingsPath }) { + - const Icon = SETTINGS_SECTION_ICONS[to]; + - return ; + @@ apps/web/src/components/settings/SettingsSidebarNav.tsx: export const SETTINGS_N + + export function SettingsSidebarNav({ pathname }: { pathname: string }) { + const navigate = useNavigate(); + +@@ apps/web/src/components/settings/SettingsSidebarNav.tsx: export function SettingsSidebarNav({ pathname }: { pathname: string }) { + + if (isMobile) { + + setOpenMobile(false); + + } + +- void navigate({ + +- to, + +- hash: "", + +- replace: true, + +- hashScrollIntoView: false, + +- }); + ++ void navigate({ to, hash: "", replace: true, hashScrollIntoView: false }); + + }, + + [isMobile, navigate, setOpenMobile], + + ); + +- const handlePageSectionClick = useCallback( + +- (to: SettingsPath, targetId: string) => { + +- if (isMobile) { + +- setOpenMobile(false); + +- } + +- if (pathname === to && scrollToSettingsTarget(targetId, { highlight: false })) { + +- return; + +- } + +- void navigate({ + +- to, + +- hash: targetId, + +- replace: true, + +- hashScrollIntoView: false, + +- state: { settingsTargetHighlight: false }, + +- }); + +- }, + +- [isMobile, navigate, pathname, setOpenMobile], + +- ); + + const clearSearch = useCallback(() => { + + setQuery(""); + + setActiveResultIndex(0); + +@@ apps/web/src/components/settings/SettingsSidebarNav.tsx: export function SettingsSidebarNav({ pathname }: { pathname: string }) { + + scrollToSettingsTarget(targetId); + + return; + + } + +- void navigate({ + +- to: item.to, + +- hash: targetId, + +- replace: true, + +- hashScrollIntoView: false, + +- state: { settingsTargetHighlight: true }, + +- }); + ++ void navigate({ to: item.to, hash: targetId, replace: true, hashScrollIntoView: false }); + + }, + + [clearSearch, currentHash, isMobile, navigate, pathname, setOpenMobile], + + ); + +@@ apps/web/src/components/settings/SettingsSidebarNav.tsx: export function SettingsSidebarNav({ pathname }: { pathname: string }) { + + No settings found + +

+ + ) : null} + +- {isSearching ? ( + +- + +- {results.map((item, index) => ( + +- + +- setActiveResultIndex(index)} + +- onClick={() => handleSearchResultClick(item)} + +- > + +- + +- + +- + +- {item.title} + +- + +- + +- {SETTINGS_SECTION_LABELS[item.to]} + +- + +- + +- + +- + +- ))} + +- + +- ) : ( + +- + +- {SETTINGS_NAV_ITEMS.map((item) => { + +- const Icon = item.icon; + +- const isActive = pathname === item.to || pathname.startsWith(`${item.to}/`); + +- const pageSections = SETTINGS_PAGE_SECTIONS[item.to]; + +- return ( + +- + ++ + ++ {isSearching + ++ ? results.map((item, index) => ( + ++ + + handleSectionClick(item.to)} + ++ id={`settings-search-result-${item.id}`} + ++ role="option" + ++ aria-selected={index === activeResultIndex} + ++ tabIndex={-1} + ++ size="sm" + ++ isActive={index === activeResultIndex} + ++ className="h-auto min-h-10 items-start gap-2 rounded-md px-2 py-2 text-left hover:bg-sidebar-row-hover hover:text-sidebar-foreground" + ++ onMouseMove={() => setActiveResultIndex(index)} + ++ onClick={() => handleSearchResultClick(item)} + + > + +- + +- {item.label} + ++ + ++ + ++ + ++ {item.title} + ++ + ++ + ++ {SETTINGS_SECTION_LABELS[item.to]} + ++ + ++ + + + +- {isActive && pageSections ? ( + +- + +- {pageSections.map((section) => ( + +- + +- } + +- size="sm" + +- className="w-full text-sidebar-muted-foreground/65" + +- onClick={() => handlePageSectionClick(item.to, section.targetId)} + +- > + +- {section.label} + +- + +- + +- ))} + +- + +- ) : null} + + + +- ); + +- })} + +- + +- )} + ++ )) + ++ : SETTINGS_NAV_ITEMS.map((item) => { + ++ const Icon = item.icon; + ++ const isActive = pathname === item.to || pathname.startsWith(`${item.to}/`); + ++ return ( + ++ + ++ handleSectionClick(item.to)} + ++ > + ++ + ++ {item.label} + ++ + ++ + ++ ); + ++ })} + ++ + + + + + + + + ## apps/web/src/components/settings/settingsSearch.ts ## + @@ apps/web/src/components/settings/settingsSearch.ts: export type SettingsPath = + @@ packages/client-runtime/src/rpc/client.ts: export type EnvironmentSubscriptionRp + | typeof WS_METHODS.subscribePreviewEvents + + ## packages/client-runtime/src/state/server.ts ## + +@@ packages/client-runtime/src/state/server.ts: const cachedConfigSnapshotEvent = (config: ServerConfig): ServerConfigStreamEven + + config, + + }); + + + +-export interface ServerConfigSubscriptionOptions { + +- readonly environmentThemes?: boolean; + +- readonly usageLimitSources?: boolean; + +-} + +- + + export const makeEnvironmentServerConfigState = Effect.fn("EnvironmentServerConfigState.make")( + +- function* (subscription: ServerConfigSubscriptionOptions) { + ++ function* (environmentThemes?: boolean) { + + const supervisor = yield* EnvironmentSupervisor; + + const cache = yield* EnvironmentCacheStore; + + const environmentId = supervisor.target.environmentId; + +@@ packages/client-runtime/src/state/server.ts: export const makeEnvironmentServerConfigState = Effect.fn("EnvironmentServerConf + + Effect.forkScoped, + + ); + + + +- yield* subscribe(WS_METHODS.subscribeServerConfig, { + +- ...(subscription.environmentThemes === true ? { environmentThemes: true } : {}), + +- ...(subscription.usageLimitSources === true ? { usageLimitSources: true } : {}), + +- }).pipe( + ++ yield* subscribe( + ++ WS_METHODS.subscribeServerConfig, + ++ environmentThemes === true ? { environmentThemes: true } : {}, + ++ ).pipe( + + Stream.runForEach((event) => + + Effect.gen(function* () { + + const next = applyServerConfigProjection(yield* SubscriptionRef.get(state), event); + +@@ packages/client-runtime/src/state/server.ts: export const makeEnvironmentServerConfigState = Effect.fn("EnvironmentServerConf + + + + export function serverConfigStateChanges( + + environmentId: EnvironmentId, + +- subscription: ServerConfigSubscriptionOptions, + ++ environmentThemes?: boolean, + + ) { + + return followStreamInEnvironment( + + environmentId, + + Stream.unwrap( + +- makeEnvironmentServerConfigState(subscription).pipe( + ++ makeEnvironmentServerConfigState(environmentThemes).pipe( + + Effect.map((state) => + + SubscriptionRef.changes(state).pipe( + + Stream.filterMap((projection) => + +@@ packages/client-runtime/src/state/server.ts: export function createServerEnvironmentAtoms( + + * receives the payload. + + */ + + readonly environmentThemes?: boolean; + +- /** Whether this surface renders quota from configured usage-limit sources. */ + +- readonly usageLimitSources?: boolean; + + }, + + ) { + + const configScheduler = createAtomCommandScheduler(); + +@@ packages/client-runtime/src/state/server.ts: export function createServerEnvironmentAtoms( + + }; + + const configProjectionFamily = Atom.family((environmentId: EnvironmentId) => + + runtime + +- .atom( + +- serverConfigStateChanges(environmentId, { + +- ...(options.environmentThemes === true ? { environmentThemes: true } : {}), + +- ...(options.usageLimitSources === true ? { usageLimitSources: true } : {}), + +- }), + +- ) + ++ .atom(serverConfigStateChanges(environmentId, options.environmentThemes)) + + .pipe( + + Atom.setIdleTTL(5 * 60_000), + + Atom.withLabel(`environment-data:server:config-projection:${environmentId}`), + +@@ packages/client-runtime/src/state/server.ts: export function createServerEnvironmentAtoms( + + updateStateAtom, + + settingsValueAtom, + + providersValueAtom, + +- providerAuthState: createEnvironmentRpcSubscriptionAtomFamily(runtime, { + +- label: "environment-data:provider:auth-state", + +- tag: WS_METHODS.providerAuthSubscribe, + +- idleTtlMs: 0, + +- }), + +- startProviderAuth: createEnvironmentRpcCommand(runtime, { + +- label: "environment-data:provider:auth-start", + +- tag: WS_METHODS.providerAuthStart, + +- concurrency: { + +- mode: "singleFlight", + +- key: ({ environmentId, input }) => JSON.stringify([environmentId, input.instanceId]), + +- }, + +- }), + +- completeProviderAuth: createEnvironmentRpcCommand(runtime, { + +- label: "environment-data:provider:auth-complete", + +- tag: WS_METHODS.providerAuthComplete, + +- }), + +- cancelProviderAuth: createEnvironmentRpcCommand(runtime, { + +- label: "environment-data:provider:auth-cancel", + +- tag: WS_METHODS.providerAuthCancel, + +- }), + +- logoutProviderAuth: createEnvironmentRpcCommand(runtime, { + +- label: "environment-data:provider:auth-logout", + +- tag: WS_METHODS.providerAuthLogout, + +- }), + +- providerInstallState: createEnvironmentRpcSubscriptionAtomFamily(runtime, { + +- label: "environment-data:provider:install-state", + +- tag: WS_METHODS.providerInstallSubscribe, + +- idleTtlMs: 0, + +- }), + +- startProviderInstall: createEnvironmentRpcCommand(runtime, { + +- label: "environment-data:provider:install-start", + +- tag: WS_METHODS.providerInstallStart, + +- concurrency: { + +- mode: "singleFlight", + +- key: ({ environmentId }) => environmentId, + +- }, + +- }), + +- cancelProviderInstall: createEnvironmentRpcCommand(runtime, { + +- label: "environment-data:provider:install-cancel", + +- tag: WS_METHODS.providerInstallCancel, + +- }), + +- removeProviderInstallation: createEnvironmentRpcCommand(runtime, { + +- label: "environment-data:provider:install-remove", + +- tag: WS_METHODS.providerInstallRemove, + +- }), + + traceDiagnostics: createEnvironmentRpcQueryAtomFamily(runtime, { + + label: "environment-data:server:trace-diagnostics", + + tag: WS_METHODS.serverGetTraceDiagnostics, + @@ packages/client-runtime/src/state/server.ts: export function createServerEnvironmentAtoms( + label: "environment-data:server:process-resource-history", + tag: WS_METHODS.serverGetProcessResourceHistory, + @@ packages/client-runtime/src/state/server.ts: export function createServerEnviron + }), + // A cold transcript scan is measured in seconds, so keep the result around + // long enough that switching windows or re-rendering does not rescan. + +@@ packages/client-runtime/src/state/server.ts: export function createServerEnvironmentAtoms( + + Stream.mapAccum(Option.none, projectServerWelcome), + + ), + + }), + +- consumeResetCredit: createEnvironmentRpcCommand(runtime, { + +- label: "environment-data:server:consume-reset-credit", + +- tag: WS_METHODS.providerConsumeResetCredit, + +- concurrency: { + +- mode: "singleFlight", + +- // Both ids are free-form strings; a delimiter could collide. + +- key: ({ environmentId, input }) => JSON.stringify([environmentId, input.instanceId]), + +- }, + +- }), + + refreshProviders: createEnvironmentRpcCommand(runtime, { + + label: "environment-data:server:refresh-providers", + + tag: WS_METHODS.serverRefreshProviders, + + concurrency: { + + mode: "singleFlight", + + key: ({ environmentId, input }) => + +- JSON.stringify([ + +- environmentId, + +- input.instanceId ?? null, + +- input.cwd ?? null, + +- input.refreshModels ?? false, + +- ]), + ++ JSON.stringify([environmentId, input.instanceId ?? null, input.cwd ?? null]), + + }, + + }), + + updateProvider: createEnvironmentRpcCommand(runtime, { + @@ packages/client-runtime/src/state/server.ts: export function createServerEnvironmentAtoms( + label: "environment-data:server:signal-process", + tag: WS_METHODS.serverSignalProcess, + }), + -- retryResourceTelemetry: createEnvironmentRpcCommand(runtime, { + -- label: "environment-data:server:retry-resource-telemetry", + -- tag: WS_METHODS.serverRetryResourceTelemetry, + +- refreshUsageRates: createEnvironmentRpcCommand(runtime, { + +- label: "environment-data:server:refresh-usage-rates", + +- tag: WS_METHODS.serverRefreshUsageRates, + - concurrency: { + - mode: "singleFlight", + - key: ({ environmentId }) => environmentId, + @@ packages/client-runtime/src/state/server.ts: export function createServerEnviron + + tag: WS_METHODS.scheduledTasksUpsert, + + scheduler: configScheduler, + + concurrency: configConcurrency, + -+ }), + + }), + +- retryResourceTelemetry: createEnvironmentRpcCommand(runtime, { + +- label: "environment-data:server:retry-resource-telemetry", + +- tag: WS_METHODS.serverRetryResourceTelemetry, + +- concurrency: { + +- mode: "singleFlight", + +- key: ({ environmentId }) => environmentId, + +- }, + + setScheduledTaskEnabled: createEnvironmentRpcCommand(runtime, { + + label: "environment-data:server:scheduled-task:set-enabled", + + tag: WS_METHODS.scheduledTasksSetEnabled, + 81: 698f41eb600 = 80: c1bae1c69fc feat(orchestrator): Add shared provider continuation and background item plumbing + 82: 55fd431a069 ! 81: 47ec735048d [orchestrator-v2] fix(orchestrator): Restore Claude session continuity for resume, wake, and idle release (#3860) + @@ pnpm-lock.yaml: packages: + '@alchemy.run/node-utils@0.0.5': + resolution: {integrity: sha512-5agdhQxWBodxa5hDRyjnpx91RTU3g+qd5fxYB7uNDCaOzB0XC47UU/KHR6zf6jhz/NXf61gJS+vhYwn8NHeRoQ==} + + -- '@anthropic-ai/claude-agent-sdk@0.3.170': + -- resolution: {integrity: sha512-pAvhfk+iTodXZ6RF18Kz7BEUWFjL7EcR3tKuhUNdPpE1NAYCR3mSHGbafi72JsrNwKEDIs7FU31z3fqhwy8QzA==} + +- '@anthropic-ai/claude-agent-sdk@0.3.260': + +- resolution: {integrity: sha512-PmABtP4Rwd6l95itQrqzguv6rS9uACqikPB9g8BPeWRKZOpy3xpEOjJLYauof3BFk2wNZnfhr0Ttx8ttcZzq0w==} + + '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.205': + + resolution: {integrity: sha512-lrfJ4eVtzfPkCpbSkBOGSMQCBbvmW6nbPzgHE4IwMN3scZlpuFMUFqh2aaJa/X2SAcWD9H2S0t2WWvSRgM7BjA==} + + cpu: [arm64] + @@ pnpm-lock.yaml: snapshots: + + '@alchemy.run/node-utils@0.0.5': {} + + -- '@anthropic-ai/claude-agent-sdk@0.3.170(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3)': + +- '@anthropic-ai/claude-agent-sdk@0.3.260(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3)': + + '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.205': + + optional: true + + + 83: 935aa5deb7a = 82: f11c744887c [orchestrator-v2] fix(orchestrator): Codex background command completion and subagent resume (#3908) + 84: 822242fc77b = 83: e15cb8b34f6 fix(orchestrator): scope Claude MCP tool pre-approval (#3862) + 85: ec90f1ec95e = 84: a9f67f41d33 feat(orchestrator): pass model options through MCP thread targets (#3872) + 86: 4060032ea1d = 85: 8a79bdd091c fix(orchestrator): align Claude permission replay with SDK + 87: 6e01338ad37 = 86: 5d7d125331d fix(ci): restore Claude permission request identity + 88: 17d2f5d2d42 = 87: b9668c94839 test(desktop): expect orchestrator v2 state directory + 89: 6f0e825e483 = 88: 5ce823a928c fix(claude): redact launch arguments from protocol logs + 90: cec49e2ca05 = 89: bfb55f793b3 fix(claude): preserve approvals with full-access sandbox + 91: 66f3b79c8e1 = 90: bad24edaf5c fix(claude): allow questions during plan mode + 92: bf9a8775d7c = 91: 3c091989c6f fix(claude): honor never-approval runtime policies + 93: cbcfea8b7d0 = 92: f218e04f09a fix(claude): enforce read-only tool availability + 94: f17413cc120 = 93: 1e4a96b5610 fix(claude): reopen queries after MCP credential rotation + 95: 14f5595b686 = 94: 1124866e9f6 fix(acp): release turns after interrupt timeout + 96: 9a065758da1 = 95: be7bb48c0aa fix(acp): bind MCP credentials to activated threads + 97: 555b0469e9d ! 96: 333ecf1ff79 fix(orchestrator): harden Grok v2 lifecycle (#3578) + @@ apps/mobile/src/features/threads/ThreadFeed.tsx: export const ThreadFeed = memo( + props.skills, + props.workspaceRoot, + + - ## apps/mobile/src/features/threads/thread-work-log.tsx ## + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: interface ThreadWorkLogProps { + - readonly activities: ReadonlyArray; + - readonly anchorKey: string; + - readonly copiedRowId: string | null; + -+ readonly currentThreadId: ThreadId; + - readonly environmentId: EnvironmentId; + - readonly expanded: boolean; + - readonly expandedRows: Readonly>; + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: export function ThreadWorkLog(props: ThreadWorkLogProps) { + - + - { + } as never, + @@ packages/client-runtime/src/state/orchestrationV2Projection.ts: function shouldS + + + ## packages/effect-acp/src/client.ts ## + +@@ + + import * as Context from "effect/Context"; + + import * as Effect from "effect/Effect"; + ++import * as Stdio from "effect/Stdio"; + + import * as Layer from "effect/Layer"; + + import * as Schema from "effect/Schema"; + + import * as Scope from "effect/Scope"; + @@ packages/effect-acp/src/client.ts: export interface AcpClientOptions { + readonly logIncoming?: boolean; + readonly logOutgoing?: boolean; + readonly logger?: (event: AcpProtocol.AcpProtocolLogEvent) => Effect.Effect; + +- /** Transforms child output before protocol logging and parsing. */ + +- readonly transformStdout?: ( + +- stdout: ChildProcessSpawner.ChildProcessHandle["stdout"], + +- ) => AcpProtocol.AcpStdio["stdin"]; + +- /** Transforms decoded session updates before buffering or delivery. */ + +- readonly transformSessionUpdate?: ( + +- notification: AcpSchema.SessionNotification, + +- ) => AcpSchema.SessionNotification; + +- /** Reports input failures and process exits, even between requests. */ + +- readonly onTermination?: (error: AcpError.AcpError) => Effect.Effect; + + readonly onIncomingRequest?: AcpProtocol.AcpPatchedProtocolOptions["onIncomingRequest"]; + + readonly onTermination?: AcpProtocol.AcpPatchedProtocolOptions["onTermination"]; + + readonly onOutgoingResponseFailure?: AcpProtocol.AcpPatchedProtocolOptions["onOutgoingResponseFailure"]; + @@ packages/effect-acp/src/client.ts: export interface AcpClientOptions { + } + + type AcpClientRaw = { + +@@ packages/effect-acp/src/client.ts: interface BufferedNotificationHandler
{ + + } + + + + export const make = Effect.fn("effect-acp/AcpClient.make")(function* ( + +- stdio: AcpProtocol.AcpStdio, + ++ stdio: Stdio.Stdio, + + options: AcpClientOptions = {}, + + terminationError?: Effect.Effect, + + ): Effect.fn.Return { + @@ packages/effect-acp/src/client.ts: export const make = Effect.fn("effect-acp/AcpClient.make")(function* ( + ...(options.logIncoming !== undefined ? { logIncoming: options.logIncoming } : {}), + ...(options.logOutgoing !== undefined ? { logOutgoing: options.logOutgoing } : {}), + ...(options.logger ? { logger: options.logger } : {}), + +- ...(options.transformSessionUpdate + +- ? { transformSessionUpdate: options.transformSessionUpdate } + +- : {}), + + ...(options.onIncomingRequest ? { onIncomingRequest: options.onIncomingRequest } : {}), + -+ ...(options.onTermination ? { onTermination: options.onTermination } : {}), + + ...(options.onTermination ? { onTermination: options.onTermination } : {}), + + ...(options.onOutgoingResponseFailure + + ? { onOutgoingResponseFailure: options.onOutgoingResponseFailure } + + : {}), + @@ packages/effect-acp/src/client.ts: export const make = Effect.fn("effect-acp/Acp + onNotification: dispatchNotification, + onExtRequest: dispatchExtRequest, + }); + +@@ packages/effect-acp/src/client.ts: export const make = Effect.fn("effect-acp/AcpClient.make")(function* ( + + }); + + }); + + + +-export const layer = ( + +- stdio: AcpProtocol.AcpStdio, + +- options: AcpClientOptions = {}, + +-): Layer.Layer => Layer.effect(AcpClient, make(stdio, options)); + ++export const layer = (stdio: Stdio.Stdio, options: AcpClientOptions = {}): Layer.Layer => + ++ Layer.effect(AcpClient, make(stdio, options)); + + + + export const layerChildProcess = ( + + handle: ChildProcessSpawner.ChildProcessHandle, + + options: AcpClientOptions = {}, + + ): Layer.Layer => { + +- const stdio = { + +- ...makeChildStdio(handle), + +- stdin: options.transformStdout?.(handle.stdout) ?? handle.stdout, + +- }; + ++ const stdio = makeChildStdio(handle); + + const terminationError = makeTerminationError(handle); + + return Layer.effect(AcpClient, make(stdio, options, terminationError)); + + }; + + ## packages/effect-acp/src/protocol.test.ts ## + @@ packages/effect-acp/src/protocol.test.ts: import * as AcpError from "./errors.ts"; + @@ packages/effect-acp/src/protocol.test.ts: it.layer(NodeServices.layer)("effect-a + const handle = yield* makeHandle({ + + ## packages/effect-acp/src/protocol.ts ## + -@@ packages/effect-acp/src/protocol.ts: export interface AcpPatchedProtocolOptions { + +@@ packages/effect-acp/src/protocol.ts: import * as Deferred from "effect/Deferred"; + + import * as Exit from "effect/Exit"; + + import * as Queue from "effect/Queue"; + + import * as Ref from "effect/Ref"; + +-import type * as PlatformError from "effect/PlatformError"; + + import * as Schema from "effect/Schema"; + + import * as Scope from "effect/Scope"; + + import * as Stream from "effect/Stream"; + +@@ packages/effect-acp/src/protocol.ts: export type AcpIncomingNotification = + + readonly params: unknown; + + }; + + + +-/** Standard I/O whose input can report provider-specific ACP failures. */ + +-export interface AcpStdio extends Omit { + +- readonly stdin: Stream.Stream; + +-} + +- + + export interface AcpPatchedProtocolOptions { + +- readonly stdio: AcpStdio; + ++ readonly stdio: Stdio.Stdio; + + readonly terminationError?: Effect.Effect; + + readonly serverRequestMethods: ReadonlySet; + readonly logIncoming?: boolean; + readonly logOutgoing?: boolean; + readonly logger?: (event: AcpProtocolLogEvent) => Effect.Effect; + +- readonly transformSessionUpdate?: ( + +- notification: AcpSchema.SessionNotification, + +- ) => AcpSchema.SessionNotification; + + readonly onIncomingRequest?: ( + + requestId: string, + + method: string, + @@ packages/effect-acp/src/protocol.ts: export const makeAcpPatchedProtocol = Effec + + }); + + const nextRequestId = yield* Ref.make(1n); + const terminationHandled = yield* Ref.make(false); + +- const terminationFailure = yield* Deferred.make(); + const extPending = yield* Ref.make(new Map()); + + +- const ensureActive = Ref.get(terminationHandled).pipe( + +- Effect.flatMap((terminated) => (terminated ? Deferred.await(terminationFailure) : Effect.void)), + +- ); + +- + + const logProtocol = (event: AcpProtocolLogEvent) => { + + if (event.direction === "incoming" && !options.logIncoming) { + + return Effect.void; + +@@ packages/effect-acp/src/protocol.ts: export const makeAcpPatchedProtocol = Effect.fn("makeAcpPatchedProtocol")(functi + + if (message._tag === "Interrupt") { + + return; + + } + +- yield* ensureActive; + + yield* logProtocol({ + + direction: "outgoing", + + stage: "decoded", + @@ packages/effect-acp/src/protocol.ts: export const makeAcpPatchedProtocol = Effect.fn("makeAcpPatchedProtocol")(functi + payload: typeof encoded === "string" ? encoded : new TextDecoder().decode(encoded), + }); + + +- yield* ensureActive; + - yield* Queue.offer(outgoing, encoded).pipe(Effect.asVoid); + + const acknowledgement = + + message._tag === "Exit" ? yield* Deferred.make() : undefined; + @@ packages/effect-acp/src/protocol.ts: export const makeAcpPatchedProtocol = Effec + } + }); + + +@@ packages/effect-acp/src/protocol.ts: export const makeAcpPatchedProtocol = Effect.fn("makeAcpPatchedProtocol")(functi + + }), + + }).pipe(Effect.asVoid); + + + +- const handleTermination = (classify: () => Effect.Effect) => + ++ const handleTermination = (classify: () => Effect.Effect) => + + Ref.modify(terminationHandled, (handled) => { + + if (handled) { + + return [Effect.void, true] as const; + +@@ packages/effect-acp/src/protocol.ts: export const makeAcpPatchedProtocol = Effect.fn("makeAcpPatchedProtocol")(functi + + Effect.gen(function* () { + + yield* Queue.offer(disconnects, 0); + + const error = yield* classify(); + +- yield* Deferred.fail(terminationFailure, error); + ++ if (!error) { + ++ return; + ++ } + + yield* failAllExtPending(error); + + yield* emitClientProtocolError(error); + + if (options.onTermination) { + +@@ packages/effect-acp/src/protocol.ts: export const makeAcpPatchedProtocol = Effect.fn("makeAcpPatchedProtocol")(functi + + ({ + + _tag: "SessionUpdate", + + method: CLIENT_METHODS.session_update, + +- params: options.transformSessionUpdate?.(params) ?? params, + ++ params, + + }) satisfies AcpIncomingNotification, + + ), + + Effect.mapError((cause) => + @@ packages/effect-acp/src/protocol.ts: export const makeAcpPatchedProtocol = Effect.fn("makeAcpPatchedProtocol")(functi + }); + } + @@ packages/effect-acp/src/protocol.ts: export const makeAcpPatchedProtocol = Effec + clientIds: Effect.succeed(new Set([0])), + initialMessage: Effect.succeedNone, + supportsAck: true, + +@@ packages/effect-acp/src/protocol.ts: export const makeAcpPatchedProtocol = Effect.fn("makeAcpPatchedProtocol")(functi + + method: string, + + payload: unknown, + + ) { + +- yield* ensureActive; + + yield* logProtocol({ + + direction: "outgoing", + + stage: "decoded", + +@@ packages/effect-acp/src/protocol.ts: export const makeAcpPatchedProtocol = Effect.fn("makeAcpPatchedProtocol")(functi + + } + + const encoded = `${exit.value}\n`; + + yield* logProtocol({ direction: "outgoing", stage: "raw", payload: encoded }); + +- yield* ensureActive; + + yield* Queue.offer(outgoing, encoded); + + }); + + + + const sendRequest = Effect.fn("sendRequest")(function* (method: string, payload: unknown) { + +- yield* ensureActive; + + const requestId = yield* Ref.modify( + + nextRequestId, + + (current) => [current, current + 1] as const, + + ## packages/shared/src/agentAwareness.test.ts ## + @@ packages/shared/src/agentAwareness.test.ts: describe("projectThreadAwarenessV2", () => { + 98: a307962b2ba = 97: f006bffe139 fix(orchestrator): dedupe Grok continuation dispatch + 99: 8e879081c3f = 98: 007b51b0ce5 fix(orchestrator): Harden Grok v2 runtime lifecycle +100: a210dc8c288 = 99: b116daa728b test(orchestrator): align integration fixtures +101: 1695b69e128 = 100: fa905ec6362 fix(mobile): support Hermes collection sorting +102: 643047ad47f = 101: 2fd782d05bc fix(grok): align ACP extensions with open source runtime +103: c026716d343 ! 102: 1093a70b448 Render T3 MCP tools with branded timeline labels + @@ apps/web/src/components/chat/MessagesTimeline.logic.test.ts: import { + - workEntryDisplayLabel, + + resolveTimelineToolPresentation, + } from "./MessagesTimeline.logic"; + + import { + + createMessageAttachmentPreviewProjector, + +@@ apps/web/src/components/chat/MessagesTimeline.logic.test.ts: describe("streaming row projection", () => { + + }); + + }); + + -describe("expanded tool group scrolling", () => { + - const entries = [{ id: "first" }, { id: "second" }]; +104: d8b06653dff ! 103: 917fad6c322 Unify T3 MCP tool presentation across clients + @@ apps/mobile/src/components/brandAssets.ts (new) + + ? require("../../../../assets/nightly/nightly-ios-1024.png") + + : require("../../../../assets/prod/black-ios-1024.png"); + + - ## apps/mobile/src/features/threads/thread-work-log.tsx ## + -@@ + - import * as Haptics from "expo-haptics"; + --import { SymbolView, type SFSymbol } from "expo-symbols"; + -+import { Image } from "expo-image"; + -+import { type AppSymbolName, SymbolView } from "../../components/AppSymbol"; + - import type { EnvironmentId, ThreadId } from "@t3tools/contracts"; + - import { useRouter } from "expo-router"; + - import { LayoutAnimation, Pressable, useColorScheme, View } from "react-native"; + - + - import { AppText as Text } from "../../components/AppText"; + --import { scaledTypographyLineHeight } from "../../lib/appearancePreferences"; + -+import { T3_CODE_BRAND_MARK_SOURCE } from "../../components/brandAssets"; + - import { cn } from "../../lib/cn"; + - import { buildThreadRoutePath } from "../../lib/routes"; + - import type { ThreadFeedActivity } from "../../lib/threadActivity"; + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: function workRowSymbolName(icon: ThreadFeedActivity["icon"]): AppSymbolName { + - } + - } + - + -+function WorkRowIcon(props: { + -+ readonly row: ThreadFeedActivity; + -+ readonly iconSubtleColor: import("react-native").ColorValue; + -+}) { + -+ const iconIsDestructive = props.row.icon === "alert" || props.row.icon === "warning"; + -+ if (props.row.logo === "t3-code") { + -+ return ( + -+ + -+ ); + -+ } + -+ + -+ return ( + -+ + -+ ); + -+} + -+ + - function ThreadActivityThreadLink(props: { + - readonly activity: ThreadFeedActivity; + - readonly environmentId: EnvironmentId; + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: export function ThreadWorkLog(props: ThreadWorkLogProps) { + - const canExpand = row.fullDetail !== null; + - const detail = compactActivityDetail(row.detail); + - const displayText = detail ? `${row.summary} ${detail}` : row.summary; + -- const iconIsDestructive = row.icon === "alert" || row.icon === "warning"; + -+ const textIsDestructive = row.icon === "alert" || row.icon === "warning"; + - + - return ( + - props.onCopyRow(row.id, row.getCopyText())} + - className="rounded-md px-0.5 py-0 active:bg-subtle" + - > + -- + -- + -- + -+ + -+ + -+ + - + - + - + - + - {row.summary} + - + ## apps/mobile/src/lib/threadActivity.test.ts ## + @@ apps/mobile/src/lib/threadActivity.test.ts: describe("buildThreadFeed", () => { + getFullDetail: () => null, + @@ apps/mobile/src/lib/threadActivity.test.ts: describe("buildThreadFeed", () => { + status, + }); + @@ apps/mobile/src/lib/threadActivity.test.ts: describe("buildThreadFeed", () => { + - ], + - }); + + expect(unchanged[1]).toBe(expanded[1]); + + expect(deriveThreadFeedPresentation(feed, null, new Set())).toEqual(collapsed); + }); + + + + it("pretty prints T3 MCP dynamic tool activities and attaches the product logo", () => { + @@ packages/shared/package.json + "types": "./src/toolActivity.ts", + "import": "./src/toolActivity.ts" + }, + +- "./favicon": { + +- "types": "./src/favicon.ts", + +- "import": "./src/favicon.ts" + + "./t3McpToolPresentation": { + + "types": "./src/t3McpToolPresentation.ts", + + "import": "./src/t3McpToolPresentation.ts" + -+ }, + + }, + "./Struct": { + "types": "./src/Struct.ts", + - "import": "./src/Struct.ts" + +@@ + + "types": "./src/usageFormat.ts", + + "import": "./src/usageFormat.ts" + + }, + +- "./usageLimits": { + +- "types": "./src/usageLimits.ts", + +- "import": "./src/usageLimits.ts" + +- }, + + "./desktopAppControl": { + + "types": "./src/desktopAppControl.ts", + + "import": "./src/desktopAppControl.ts" + +@@ + + "./claudeCompaction": { + + "types": "./src/claudeCompaction.ts", + + "import": "./src/claudeCompaction.ts" + +- }, + +- "./nodeSqliteClient": { + +- "types": "./src/nodeSqliteClient.ts", + +- "import": "./src/nodeSqliteClient.ts" + + } + + }, + + "scripts": { + + ## packages/shared/src/t3McpToolPresentation.test.ts (new) ## + @@ +105: 8e173085a7c ! 104: bcf43a8f018 fix(orchestration): clarify agent delegation and scheduling + @@ apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.ts: export function + ## apps/server/src/provider/CodexDeveloperInstructions.ts ## + @@ + import type { ProviderInteractionMode } from "@t3tools/contracts"; + + import { buildRuntimeInstructions } from "./RuntimeInstructions.ts"; + + +import { T3_CODE_ORCHESTRATION_INSTRUCTIONS } from "./T3OrchestrationInstructions.ts"; + + +106: 092daf3c497 = 105: cd095953df7 fix(server): preserve released migration ordering +107: 39505241c82 = 106: f18cbfb6841 fix(web): restore v2 composer chrome +108: 92bfc55bc39 = 107: 80a9b6628b8 fix(web): remove stacked composer shadows +109: 7e3d2119880 = 108: 3fa4661dd66 refactor(web): use shared glass surfaces +110: b07b35f8fcc = 109: b51d858ac04 fix(web): contain thread details panel effects +111: 2f50f6b93f0 = 110: df523273344 test(orchestrator): Align post-merge CTM fixtures (#4193) +112: c93936748b4 = 111: 3e6d9c12dd6 fix(orchestrator): Preserve claude/codex post-interrupt recovery state (#4229) +113: b2e4223af67 = 112: c75cec919c3 test(orchestrator): align Codex approval reviewer replays (#4457) +114: 2a25e1d2deb = 113: dff34c177aa fix(orchestrator): hydrate shell cache and group multi-environment projects (#3640) +115: 83ea5f70c16 = 114: 780302519d3 feat(subagents): disclose projected results consistently (#3866) +116: 7ae175a5f35 = 115: d52c1e6e6d5 Add worktree handoff and status tools to the t3-code MCP server (#3754) +117: 0bc459bd0fa = 116: 64a9daf87cd fix(mobile): wait for fork shell before navigation +118: bafa7a432ba = 117: 55cb6938055 fix(server): keep derived threads awake +119: 45d60f9a51b = 118: 961a655902e fix(server): enforce ACP auth and preserve fork provenance +120: 16b8599b267 = 119: 8fb46345695 fix(server): clean up Claude replay failures +121: 4a3797b4825 = 120: 0bcafedc7ca test(orchestrator): align merged V2 compatibility checks +122: da04feea481 = 121: e05564e15a5 fix(grok): Prevent spurious wake run after in-turn monitors +123: 9649b226006 = 122: af0f7759971 fix(acp): Preserve wake evidence across an app-owned wake +124: ba3c8210040 = 123: f4553701dbb fix(orchestrator): Wake settled parents when delegated children finish +125: 0e018044d74 = 124: f0b7a4ed427 fix(claude): Settle positive task-notification results +126: 1e42d8e9098 ! 125: dda77e7bb49 fix: hide subagent threads from v2 lists + @@ apps/mobile/src/features/threads/threadListV2.ts: export function buildThreadLis + + ## apps/web/src/components/Sidebar.logic.test.ts ## + @@ apps/web/src/components/Sidebar.logic.test.ts: import { + - buildBulkTitleRegenerationContextMenuItem, + + buildBulkUnpinContextMenuItem, + buildMultiSelectThreadContextMenuItems, + createThreadJumpHintVisibilityController, + - filterSidebarProjectScopeItems, +127: 4d9180dc781 = 126: bc1a9c7d76b fix: ignore subagents when sorting sidebar projects +128: ef8219c2e3d = 127: 933d9c04217 fix(web): restore checked-in project scripts +129: d59b7c2ba35 = 128: 4569c531d59 chore(orchestrator): refresh checks after main sync +130: 3ba155db4fa = 129: e684489f7d8 feat: migrate v1 state into orchestrator v2 (#4400) +131: 6c82f71da51 = 130: 81619adf57b fix(orchestrator): schedule effects from durable deadlines (#4656) +132: 32d563e07ce = 131: 73fb62aeed3 fix(orchestration): harden scheduled task startup +133: 8006f38f2e6 ! 132: 384873780e8 fix(mobile): preserve active thread state + @@ apps/mobile/src/features/threads/ThreadRouteScreen.tsx: function ThreadRouteCont + selectedThreadFeed={composer.selectedThreadFeed} + + activityRun={composer.selectedThreadActivityRun} + activeWorkStartedAt={composer.activeWorkStartedAt} + + isCompacting={composer.isCompacting} + activePendingApproval={requests.activePendingApproval} + - respondingApprovalId={requests.respondingApprovalId} + @@ apps/mobile/src/features/threads/ThreadRouteScreen.tsx: function ThreadRouteContent( + connectionStateLabel={routeConnectionState} + threadSyncStatus={selectedThreadDetailState.status} +134: 51e044f7ad1 = 133: 657ee69e5ff fix(orchestration): preserve legacy schedule compatibility +135: 8d27ca499e3 = 134: 385f1537b78 fix(contracts): reject invalid legacy intervals +136: 3edb72687d6 = 135: cedc11513d4 fix(acp): make xai cancellation reliable +137: 7252e405740 = 136: 49654af76e5 fix(orchestration): handle checkpoint-wait runs +138: 0900ea01d94 = 137: 9761382b9df fix(orchestration): cancel queued work on archive +139: 1fdab432e8f = 138: 3087d27841d fix(mobile): allow archiving post-provider work +140: 0db5a1d2e6d = 139: 14d68b3c2ad fix(mobile): distinguish queued and waiting archive states +141: 120242d9fb5 = 140: 4fd8f62bc94 fix(cursor): log close attempts before execution +142: 345a9a4a3a6 = 141: ff5e6f1b32d fix(acp): discover final teardown descendants +143: 09963b2172d = 142: d0fca84e651 fix(checkpoints): preserve valid run history +144: 6c30ce289bd = 143: c2b51fc0902 fix(orchestration): preserve imported conversation state +145: 0d5dbddd166 = 144: 6ab76be2243 fix(acp): enforce task and permission invariants +146: c6adb55a0a7 = 145: bd653b476bf fix(testkit): harden provider replay recording +147: 9f71aa9ca6b = 146: 4cf4ed7202f fix(server): isolate deterministic attachment ids +148: afeb2089d20 = 147: 2ca3166d409 fix(claude): preserve explicit model options +149: 153a1f8548e = 148: 0954b3bb597 fix(web): enforce secure provider field defaults +150: c2145dde126 = 149: b605ddde083 fix(client): preserve live thread relationships +151: 6179f46681c = 150: 67f85a5c781 fix(checkpoints): retain thread-start baseline after failed runs +152: 80e5ef9865d = 151: 91e3a339592 fix(mobile): gate thread controls on live runs +153: 5a2a714d781 ! 152: 088c56b41f3 fix(orchestrator): address late review findings + @@ apps/mobile/src/features/threads/thread-work-log-labels.ts (new) + + return count === 1 ? "log entry" : "log entries"; + +} + + - ## apps/mobile/src/features/threads/thread-work-log.tsx ## + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: import { buildThreadRoutePath } from "../../lib/routes"; + - import type { ThreadFeedActivity } from "../../lib/threadActivity"; + - import { useV2ItemSupport } from "../../state/v2-item-support"; + - import { ThreadActivityInspector } from "./ThreadActivityInspector"; + -+import { threadWorkLogOverflowNoun } from "./thread-work-log-labels"; + - + - const WORK_LOG_LAYOUT_ANIMATION = { + - duration: 180, + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: export function ThreadWorkLog(props: ThreadWorkLogProps) { + - } + - + - const onlyToolRows = rows.every((row) => row.toolLike); + -+ const overflowNoun = threadWorkLogOverflowNoun(onlyToolRows, hiddenCount); + - + - return ( + - + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: export function ThreadWorkLog(props: ThreadWorkLogProps) { + - ); + - })} + - + -+ + -+ {hasOverflow ? ( + -+ { + -+ triggerDisclosureFeedback(); + -+ props.onToggleGroup(); + -+ }} + -+ style={({ pressed }) => ({ + -+ backgroundColor: pressed ? pressedBackground : "transparent", + -+ })} + -+ className="min-h-9 flex-row items-center gap-1.5 rounded-md px-0.5 py-0.5" + -+ > + -+ + -+ + -+ + -+ + -+ {props.expanded + -+ ? `Show fewer ${overflowNoun}` + -+ : `+${hiddenCount} previous ${overflowNoun}`} + -+ + -+ + -+ ) : null} + - + - ); + - } + -@@ apps/mobile/src/features/threads/thread-work-log.tsx: export function ThreadWorkGroupToggle(props: { + - }) { + - const colorScheme = useColorScheme(); + - const pressedBackground = colorScheme === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.035)"; + -- const noun = props.onlyToolActivities + -- ? props.hiddenCount === 1 + -- ? "tool call" + -- : "tool calls" + -- : props.hiddenCount === 1 + -- ? "log entry" + -- : "log entries"; + -- const collapsedLabel = `Show ${props.hiddenCount} previous ${noun}`; + -- const expandedLabel = props.onlyToolActivities + -- ? "Show fewer tool calls" + -- : "Show fewer log entries"; + -+ const noun = threadWorkLogOverflowNoun(props.onlyToolActivities, props.hiddenCount); + - + - return ( + - + - + ## apps/mobile/src/state/use-thread-composer-state.ts ## + @@ apps/mobile/src/state/use-thread-composer-state.ts: import { useAtomValue } from "@effect/atom-react"; + import { threadRuntimeIsActive } from "@t3tools/client-runtime/state/shell"; +154: ff10b65fe6e = 153: 739c3ff962d fix(orchestrator): handle fresh review edge cases +155: 785e1388d01 = 154: b65d8ca4cf6 fix(orchestrator): harden provider edge cases +156: 0a9a06ba642 = 155: d6eb526629a fix(orchestrator): execute resolved runtime responses +157: 49ad52e66d3 = 156: dd2b8814975 fix(orchestrator): release stranded effect claims +158: c17955171a4 = 157: c2a48e3c8e9 fix(worktrees): make handoff rollback atomic +159: c7a62d3c36d = 158: f081c2c84c4 fix(orchestrator): avoid replaying settled effects +160: 7b1e9dad867 = 159: 83cf7d6dfa6 fix(orchestrator): preserve retryable effect failures +161: 69299bf47b7 = 160: ddb3c272115 fix(orchestrator): preserve terminal effect outcomes +162: 9c3a6b75e98 = 161: 9a404d4672f fix(orchestrator): validate replay edge cases +163: af590d13aea = 162: 697fff8d50d fix(orchestrator): decode direct Claude result blocks +164: 614c744be91 = 163: 2e813f8c4bd fix(orchestrator): close cancellation edge cases +165: e59043aebb2 = 164: 6fcbf009d42 fix(orchestrator): validate rollback and search links +166: 327189894e0 = 165: 014e9a2621e fix(server): preserve project mutation client errors +167: 8af2b58d152 = 166: 10c462fbd20 fix(orchestrator): preserve migrated and nested history +168: 9aeb65f738d = 167: 01c127f54ed fix: address orchestration review findings +169: fa408d129f1 = 168: 3e72c6a17b2 fix(mobile): label queued message intent +170: 5de19555913 = 169: 88a1900091b fix: address orchestration review findings +171: a2b1e1ef93f = 170: 1e65d374c19 fix: preserve orchestration task identity +172: 981b2ddc749 = 171: dbc5127f330 fix: address latest orchestration review findings +173: 6832caec1f1 = 172: d4990c75c3a fix: preserve thread management failure semantics +174: dd9b6b0d4bd = 173: 5c24e3506ae fix: close failed provider adapter scopes +175: 0ee02d54900 = 174: a12849d5916 feat(server): surface legacy thread migration progress +176: 7b28551f4bb ! 175: 27806ef4d85 feat(orchestration): track provider retries and thread visits + @@ apps/mobile/src/features/threads/ThreadDetailScreen.tsx: export const ThreadDeta + lastScrolledAnchorMessageIdRef.current = null; + + ## apps/mobile/src/features/threads/thread-list-v2-items.tsx ## + +@@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: import type { + + EnvironmentThreadShell, + + } from "@t3tools/client-runtime/state/shell"; + + import type { EnvironmentThreadSearchMatch } from "@t3tools/client-runtime/state/thread-search"; + +-import type { EnvironmentMachineKind } from "@t3tools/contracts"; + + import { canSnooze, resolveSnoozePresets } from "@t3tools/client-runtime/state/thread-settled"; + +-import { resolveSettledThreadTimestamp } from "@t3tools/client-runtime/state/thread-sort"; + + import type { MenuAction } from "@react-native-menu/menu"; + + import { memo, useCallback, useEffect, useMemo, useState, type ComponentProps } from "react"; + + import { Alert, Platform, Pressable, useWindowDimensions, View } from "react-native"; + +@@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: import type { SwipeableMethods } from "react-native-gesture-handler/ReanimatedSw + + import { SymbolView } from "../../components/AppSymbol"; + + import { AppText as Text } from "../../components/AppText"; + + import { ControlPillMenu } from "../../components/ControlPill"; + +-import { EnvironmentMachineSymbol } from "../../components/EnvironmentMachineSymbol"; + + import { ProjectFavicon } from "../../components/ProjectFavicon"; + + import { ProviderIcon } from "../../components/ProviderIcon"; + + import { cn } from "../../lib/cn"; + @@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: import { + resolveThreadListV2SwipeActions, + type ThreadListV2Status, + @@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadLi + /> + + ); + +@@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadListV2PendingRow = memo(function ThreadListV2PendingRow(props + + readonly project: EnvironmentProject | null; + + readonly projectTitle?: string; + + readonly environmentLabel: string | null; + +- /** Drawn beside the label; ignored while the label is null. */ + +- readonly environmentMachine?: EnvironmentMachineKind; + + readonly pane?: "screen" | "sidebar"; + + /** Draws the "Pending" divider above the first queued row. */ + + readonly showPendingDivider: boolean; + +@@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadListV2PendingRow = memo(function ThreadListV2PendingRow(props + + readonly onDeletePendingTask: (pendingTask: PendingNewTask) => void; + + }) { + + const { pendingTask, onSelectPendingTask, onDeletePendingTask } = props; + ++ const theme = useUniwindTheme(); + ++ const drawerColor = theme["--color-drawer"]; + ++ const pressedBackgroundColor = theme["--color-subtle"]; + + const sidebarPane = props.pane === "sidebar"; + + const projectTitle = + + props.projectTitle ?? props.project?.title ?? pendingTask.creation.projectTitle ?? ""; + +@@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadListV2PendingRow = memo(function ThreadListV2PendingRow(props + + {pendingTask.title} + + + + {branch || props.environmentLabel ? ( + +- + +- + +- {branch ? ( + +- + +- {branch} + +- + +- ) : null} + +- {branch && props.environmentLabel ? " · " : null} + +- {props.environmentLabel ? ( + +- {props.environmentLabel} + +- ) : null} + +- + +- {props.environmentLabel && props.environmentMachine ? ( + +- + ++ + ++ {branch ? ( + ++ + ++ {branch} + ++ + + ) : null} + +- + ++ {branch && props.environmentLabel ? " · " : null} + ++ {props.environmentLabel ? ( + ++ {props.environmentLabel} + ++ ) : null} + ++ + + ) : null} + + + + ); + +@@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadListV2PendingRow = memo(function ThreadListV2PendingRow(props + + accessibilityHint="Opens the queued task for editing" + + accessibilityLabel={pendingTask.title} + + accessibilityRole="button" + +- className={sidebarPane ? "bg-drawer active:bg-subtle" : undefined} + + onPress={() => onSelectPendingTask(pendingTask)} + + style={ + + sidebarPane + +- ? { + ++ ? ({ pressed }) => ({ + ++ backgroundColor: pressed ? pressedBackgroundColor : drawerColor, + + borderRadius: SIDEBAR_V2_ROW_RADIUS, + + paddingHorizontal: 12, + + paddingVertical: 10, + +- } + ++ }) + + : ({ pressed }) => ({ opacity: pressed ? 0.7 : 1 }) + + } + + > + +@@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadListV2Row = memo(function ThreadListV2Row(props: { + + the web sidebar's remote-environment cloud icon, but as text since + + phones have no hover tooltips. */ + + readonly environmentLabel: string | null; + +- /** Drawn after the label so the machine reads at a glance; ignored while + +- the label is null. */ + +- readonly environmentMachine?: EnvironmentMachineKind; + + /** Hosting surface. "screen" (default) renders the compact Home idiom: + + flat edge-to-edge rows on the screen background with inset hairlines. + + "sidebar" renders the iPad split-view idiom: rounded rows blending + @@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadListV2Row = memo(function ThreadListV2Row(props: { + const selected = props.selected === true; + + const status = resolveThreadListV2Status(thread); + - const statusLabel = STATUS_LABEL_BY_STATUS[status]; + +- // Settled rows label by the same stamp they sort by, so order and label + +- // can't disagree. updatedAt is always present, so the resolver never + +- // returns null here. + +- const settledTimestamp = + +- variant === "slim" && !snoozedRow ? resolveSettledThreadTimestamp(thread) : null; + +- const timeLabel = + +- settledTimestamp !== null ? relativeTime(settledTimestamp) : threadTimeLabel(thread); + + // "Done" marks a completion the user has not opened yet — same emerald + + // label as the web sidebar, sourced from the server-side visited watermark + + // so checking a thread on any device clears it everywhere. + @@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadLi + + const statusLabel = + + STATUS_LABEL_BY_STATUS[status] ?? + + (isUnread ? { label: "Done", className: "text-emerald-700 dark:text-emerald-300" } : undefined); + - const timeLabel = threadTimeLabel(thread); + ++ const timeLabel = threadTimeLabel(thread); + + const handleDelete = useCallback(() => onDeleteThread(thread), [onDeleteThread, thread]); + + const handleRegenerateTitle = useCallback( + @@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadListV2Row = memo(function ThreadListV2Row(props: { + } satisfies MenuAction, + ] + @@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadLi + ); + const snoozedMenuActions = useMemo( + () => [SNOOZED_MENU_ACTIONS[0]!, ...titleRegenerationMenuItems, SNOOZED_MENU_ACTIONS[1]!], + +@@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadListV2Row = memo(function ThreadListV2Row(props: { + + ) : thread.branch || props.environmentLabel ? ( + + /* "branch · machine" share one truncating line. The machine sits + + last so a tight fit cuts the repetitive label, not the branch — + +- and machine-only fills the row for non-git projects. The glyph + +- hugs the label (it cannot live inside the Text without breaking + +- truncation), and the wrapper takes the slack so the trailers + +- stay pinned right. */ + +- + +- + +- {thread.branch ? ( + +- + +- {thread.branch} + +- + +- ) : null} + +- {thread.branch && props.environmentLabel ? " · " : null} + +- {props.environmentLabel ? ( + +- + +- {props.environmentLabel} + +- + +- ) : null} + +- + +- {props.environmentLabel && props.environmentMachine ? ( + +- + ++ and machine-only fills the row for non-git projects. */ + ++ + ++ {thread.branch ? ( + ++ + ++ {thread.branch} + ++ + + ) : null} + +- + ++ {thread.branch && props.environmentLabel ? " · " : null} + ++ {props.environmentLabel ? ( + ++ + ++ {props.environmentLabel} + ++ + ++ ) : null} + ++ + + ) : ( + + + + )} + +@@ apps/mobile/src/features/threads/thread-list-v2-items.tsx: export const ThreadListV2Row = memo(function ThreadListV2Row(props: { + + > + + {snoozedRow && props.snoozeWakeLabelText !== undefined + + ? props.snoozeWakeLabelText + +- : timeLabel} + ++ : relativeTime(thread.latestUserMessageAt ?? thread.updatedAt ?? thread.createdAt)} + + + + + + + + ## apps/mobile/src/features/threads/threadListV2.ts ## + @@ apps/mobile/src/features/threads/threadListV2.ts: export function resolveThreadListV2Enabled(input: { + @@ apps/mobile/src/lib/threadActivity.ts: export function buildThreadFeed( + + } + return groupAdjacentActivities(entries); + } + + + + ## apps/server/src/environment/ServerEnvironment.ts ## + +@@ apps/server/src/environment/ServerEnvironment.ts: import { resolveServiceLauncherMode } from "../cloud/serviceLauncherClient.ts"; + + import * as ServerConfig from "../config.ts"; + + import * as ProcessRunner from "../processRunner.ts"; + + import { resolveServerEnvironmentLabel } from "./ServerEnvironmentLabel.ts"; + +-import { detectServerEnvironmentMachineKind } from "./ServerEnvironmentMachine.ts"; + + + + export class ServerEnvironmentIdPersistenceError extends Schema.TaggedErrorClass()( + + "ServerEnvironmentIdPersistenceError", + +@@ apps/server/src/environment/ServerEnvironment.ts: export const make = Effect.gen(function* () { + + const environmentId = yield* identity.getEnvironmentId; + + const cwdBaseName = path.basename(serverConfig.cwd).trim(); + + const label = yield* resolveServerEnvironmentLabel({ cwdBaseName }); + +- const machine = yield* detectServerEnvironmentMachineKind(); + + const launcher = yield* resolveServiceLauncherMode(); + + const serverSelfUpdate = resolveServerSelfUpdateCapability({ + + desktopManaged: serverConfig.mode === "desktop", + +@@ apps/server/src/environment/ServerEnvironment.ts: export const make = Effect.gen(function* () { + + platform: { + + os: platformOs(hostPlatform), + + arch: platformArch(hostArchitecture), + +- ...(machine === null ? {} : { machine }), + + }, + + serverVersion: packageJson.version, + + capabilities: { + @@ apps/server/src/environment/ServerEnvironment.ts: export const make = Effect.gen(function* () { + + threadAutoSettlement: true, + + threadSnooze: true, + + environmentThemes: true, + +- usageLimitSources: true, + threadPinning: true, + threadPinReorder: true, + threadTitleRegeneration: true, + - threadPullRequestLinking: true, + +- environmentIcon: true, + + threadVisitedTracking: true, + ...(serverSelfUpdate === null ? {} : { serverSelfUpdate }), + ...(serverSelfUpdate === "boot-service" || desktopAppUpdate + @@ apps/web/src/components/AppSidebarLayout.tsx: import { getLocalStorageItem, remo + import { primaryServerKeybindingsAtom } from "../state/server"; + +<<<<<<< HEAD + import { useEnvironmentIdentificationMode, useLegacySidebarEnabled } from "../hooks/useSettings"; + + import { usePanelAnimationSettings } from "../panelAnimations"; + import LegacyThreadSidebar from "./LegacySidebar"; + +======= + +import { useEnvironmentIdentificationMode, useSidebarV2Enabled } from "../hooks/useSettings"; + +import { useThreadVisitedMigration } from "../hooks/useThreadVisitedMigration"; + +>>>>>>> 844dad005a (feat(orchestration): track provider retries and thread visits) + import ThreadSidebar from "./Sidebar"; + + import { SettingsSidebarNav } from "./settings/SettingsSidebarNav"; + import { SidebarChromeHeader } from "./sidebar/SidebarChrome"; + - import { + @@ apps/web/src/components/AppSidebarLayout.tsx: function ProjectProjectionRetention() { + + export function AppSidebarLayout({ children }: { children: ReactNode }) { + const navigate = useNavigate(); + +<<<<<<< HEAD + const legacySidebarEnabled = useLegacySidebarEnabled(); + + const { active: panelAnimationsActive, durationMs: panelAnimationDurationMs } = + + usePanelAnimationSettings(); + // Settings routes show the settings nav in place of whichever thread + // sidebar is active. + +======= + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + + + + const nextOffset = list.getState().scroll + metrics.scrollDeltaToRevealEnd; + + void list.scrollToOffset({ offset: nextOffset, animated: false }); + -+ return; + -+ } + -+ + -+ if (timelineScrollModeRef.current !== "following-end") { + -+ return; + -+ } + -+ if (!timelineRealContentOverflowsViewport(list)) { + return; + } + + - const nextOffset = list.getState().scroll + metrics.scrollDeltaToRevealEnd; + - void list.scrollToOffset({ offset: nextOffset, animated: false }); + ++ if (timelineScrollModeRef.current !== "following-end") { + ++ return; + ++ } + ++ if (!timelineRealContentOverflowsViewport(list)) { + ++ return; + ++ } + ++ + + void list.scrollToEnd?.({ animated: false }); + }); + }); + @@ apps/web/src/components/ChatView.tsx: function ChatViewContent(props: ChatViewPr + return; + } + - if (activeEnvironmentUnavailable) { + -- toastManager.add( + -- stackedThreadToast({ + +- const toastSlot = environmentUnavailableSendToastSlotRef.current; + +- environmentUnavailableSendToastSlotRef.current = + +- (toastSlot + 1) % ENVIRONMENT_UNAVAILABLE_SEND_TOAST_TRAIL_SIZE; + +- toastManager.add({ + +- ...stackedThreadToast({ + - type: "warning", + - title: "Not connected: message not sent", + - description: "Reconnecting to the environment. Try again once it is connected.", + - }), + -- ); + +- id: `chat-send-environment-unavailable:${toastSlot}`, + +- }); + - return; + - } + if (activePendingProgress) { + @@ apps/web/src/components/ThreadStatusIndicators.tsx: import { useThreadRunningTer + import { useUiStateStore } from "../uiStateStore"; + import { resolveChangeRequestPresentation } from "../sourceControlPresentation"; + -import { resolveThreadStatusPill, type ThreadStatusPill } from "./Sidebar.logic"; + +-import { resolvePullRequestState } from "./pullRequest/pullRequestPresentation"; + +import { + + resolveThreadLastVisitedAt, + + resolveThreadStatusPill, + @@ apps/web/src/components/chat/MessagesTimeline.tsx: import { + +import { flushSync } from "react-dom"; + import { LegendList, type LegendListRef } from "@legendapp/list/react"; + import { FileDiff } from "@pierre/diffs/react"; + + import { DiffWorkerPoolProvider } from "../DiffWorkerPoolProvider"; + import { + type TimelineEntry, + + providerErrorPresentation, + @@ apps/web/src/components/chat/MessagesTimeline.tsx: function toolWorkEntryHeading + - Math.max(memberIds.size - (spawn.workflowId ? 1 : 0), 0), + - ); + - + -- const running = agents.filter( + -- (agent) => agent.status === "running" || agent.status === "pending", + -- ).length; + -- const waiting = agents.filter((agent) => agent.status === "waiting").length; + -- const failed = agents.filter((agent) => agent.status === "failed").length; + -- // The coordinator's own status is authoritative for workflows: dynamic + -- // spawns mean the member list can be momentarily all-settled while the + -- // run is still mid-flight (the "completed" lie from live testing). A + -- // workflow is live until the coordinator itself reaches a terminal state. + -- const coordinatorStatus = workflowGroup?.workflow.status; + -- const coordinatorSettled = + -- coordinatorStatus === "completed" || + -- coordinatorStatus === "failed" || + -- coordinatorStatus === "cancelled" || + -- coordinatorStatus === "interrupted"; + -- const live = workflowGroup !== undefined ? !coordinatorSettled : running + waiting > 0; + +- const summary = deriveAgentSpawnSummary({ + +- agents, + +- agentCount, + +- coordinatorStatus: workflowGroup?.workflow.status, + +- }); + +- const { live, lead } = summary; + - // Same rule as the panel footer: providers may aggregate member usage into + - // the coordinator, so count the coordinator only when no members exist. + - const totalTokens = agents.reduce( + @@ apps/web/src/components/chat/MessagesTimeline.tsx: function toolWorkEntryHeading + - const workflowName = + - workflowGroup?.workflow.workflowName ?? workflowGroup?.workflow.title ?? null; + - + -- // One steady in-flight presentation (monitoring-pill rule): waiting and + -- // stalled agents read as working; only settled states differentiate. + -- const working = running + waiting; + -- const dotClass = live ? "bg-info" : failed > 0 ? "bg-destructive" : "bg-success"; + -- const lead = live + -- ? `Kicked off ${agentCount} subagent${agentCount === 1 ? "" : "s"}` + -- : `Ran ${agentCount} subagent${agentCount === 1 ? "" : "s"}`; + -- const status = live + -- ? livePhase + -- ? `${livePhase.title} · ${livePhase.activeCount} working` + -- : working > 0 + -- ? `${working} working` + -- : "working" + -- : failed > 0 + -- ? `${failed} failed` + -- : "✓ completed"; + +- const dotClass = { + +- working: "bg-info", + +- failed: "bg-destructive", + +- completed: "bg-success", + +- inactive: "bg-muted-foreground/50", + +- }[summary.tone]; + +- const status = + +- live && livePhase ? `${livePhase.title} · ${livePhase.activeCount} working` : summary.status; + - + - return ( + -