@getpaseo/server 0.1.63 → 0.1.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/client/daemon-client-transport-types.d.ts +2 -0
- package/dist/server/client/daemon-client-transport-types.d.ts.map +1 -1
- package/dist/server/client/daemon-client-websocket-transport.d.ts +2 -1
- package/dist/server/client/daemon-client-websocket-transport.d.ts.map +1 -1
- package/dist/server/client/daemon-client-websocket-transport.js +4 -4
- package/dist/server/client/daemon-client-websocket-transport.js.map +1 -1
- package/dist/server/client/daemon-client.d.ts +30 -20
- package/dist/server/client/daemon-client.d.ts.map +1 -1
- package/dist/server/client/daemon-client.js +206 -98
- package/dist/server/client/daemon-client.js.map +1 -1
- package/dist/server/client/terminal-stream-router.d.ts +24 -0
- package/dist/server/client/terminal-stream-router.d.ts.map +1 -0
- package/dist/server/client/terminal-stream-router.js +100 -0
- package/dist/server/client/terminal-stream-router.js.map +1 -0
- package/dist/server/server/agent/activity-curator.d.ts +6 -3
- package/dist/server/server/agent/activity-curator.d.ts.map +1 -1
- package/dist/server/server/agent/activity-curator.js +45 -138
- package/dist/server/server/agent/activity-curator.js.map +1 -1
- package/dist/server/server/agent/agent-manager.d.ts +3 -14
- package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
- package/dist/server/server/agent/agent-manager.js +75 -140
- package/dist/server/server/agent/agent-manager.js.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.d.ts +0 -5
- package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.js +3 -93
- package/dist/server/server/agent/agent-metadata-generator.js.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.d.ts +15 -1
- package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
- package/dist/server/server/agent/agent-stream-coalescer.d.ts +1 -1
- package/dist/server/server/agent/agent-stream-coalescer.d.ts.map +1 -1
- package/dist/server/server/agent/agent-stream-coalescer.js +1 -1
- package/dist/server/server/agent/agent-stream-coalescer.js.map +1 -1
- package/dist/server/server/agent/agent-timeline-store.d.ts.map +1 -1
- package/dist/server/server/agent/agent-timeline-store.js +29 -32
- package/dist/server/server/agent/agent-timeline-store.js.map +1 -1
- package/dist/server/server/agent/foreground-run-state.d.ts +50 -0
- package/dist/server/server/agent/foreground-run-state.d.ts.map +1 -0
- package/dist/server/server/agent/foreground-run-state.js +162 -0
- package/dist/server/server/agent/foreground-run-state.js.map +1 -0
- package/dist/server/server/agent/mcp-server.d.ts +5 -3
- package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
- package/dist/server/server/agent/mcp-server.js +110 -99
- package/dist/server/server/agent/mcp-server.js.map +1 -1
- package/dist/server/server/agent/mcp-shared.d.ts.map +1 -1
- package/dist/server/server/agent/mcp-shared.js +7 -1
- package/dist/server/server/agent/mcp-shared.js.map +1 -1
- package/dist/server/server/agent/prompt-attachments.d.ts +4 -3
- package/dist/server/server/agent/prompt-attachments.d.ts.map +1 -1
- package/dist/server/server/agent/prompt-attachments.js +43 -4
- package/dist/server/server/agent/prompt-attachments.js.map +1 -1
- package/dist/server/server/agent/provider-manifest.d.ts.map +1 -1
- package/dist/server/server/agent/provider-manifest.js +7 -0
- package/dist/server/server/agent/provider-manifest.js.map +1 -1
- package/dist/server/server/agent/providers/acp-agent.d.ts +38 -1
- package/dist/server/server/agent/providers/acp-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/acp-agent.js +257 -140
- package/dist/server/server/agent/providers/acp-agent.js.map +1 -1
- package/dist/server/server/agent/providers/claude/sidechain-tracker.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude/sidechain-tracker.js +1 -1
- package/dist/server/server/agent/providers/claude/sidechain-tracker.js.map +1 -1
- package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude/tool-call-mapper.js +68 -198
- package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -1
- package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude-agent.js +52 -102
- package/dist/server/server/agent/providers/claude-agent.js.map +1 -1
- package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex/tool-call-mapper.js +125 -141
- package/dist/server/server/agent/providers/codex/tool-call-mapper.js.map +1 -1
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +36 -6
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex-app-server-agent.js +374 -219
- package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
- package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +6 -2
- package/dist/server/server/agent/providers/mock-load-test-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/mock-load-test-agent.js +294 -113
- package/dist/server/server/agent/providers/mock-load-test-agent.js.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +94 -2
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +24 -115
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.js.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.d.ts +102 -1
- package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.js +416 -158
- package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
- package/dist/server/server/agent/providers/provider-runner.d.ts +27 -0
- package/dist/server/server/agent/providers/provider-runner.d.ts.map +1 -0
- package/dist/server/server/agent/providers/provider-runner.js +80 -0
- package/dist/server/server/agent/providers/provider-runner.js.map +1 -0
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +6 -3
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -1
- package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +2 -0
- package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -1
- package/dist/server/server/agent/providers/tool-call-mapper-utils.js +31 -0
- package/dist/server/server/agent/providers/tool-call-mapper-utils.js.map +1 -1
- package/dist/server/server/agent/timeline-projection.d.ts +21 -5
- package/dist/server/server/agent/timeline-projection.d.ts.map +1 -1
- package/dist/server/server/agent/timeline-projection.js +59 -9
- package/dist/server/server/agent/timeline-projection.js.map +1 -1
- package/dist/server/server/auth.d.ts +25 -0
- package/dist/server/server/auth.d.ts.map +1 -0
- package/dist/server/server/auth.js +93 -0
- package/dist/server/server/auth.js.map +1 -0
- package/dist/server/server/bootstrap.d.ts +3 -1
- package/dist/server/server/bootstrap.d.ts.map +1 -1
- package/dist/server/server/bootstrap.js +87 -30
- package/dist/server/server/bootstrap.js.map +1 -1
- package/dist/server/server/config.d.ts.map +1 -1
- package/dist/server/server/config.js +11 -0
- package/dist/server/server/config.js.map +1 -1
- package/dist/server/server/exports.d.ts +7 -1
- package/dist/server/server/exports.d.ts.map +1 -1
- package/dist/server/server/exports.js +6 -1
- package/dist/server/server/exports.js.map +1 -1
- package/dist/server/server/file-explorer/service.d.ts +10 -0
- package/dist/server/server/file-explorer/service.d.ts.map +1 -1
- package/dist/server/server/file-explorer/service.js +38 -4
- package/dist/server/server/file-explorer/service.js.map +1 -1
- package/dist/server/server/index.js +9 -6
- package/dist/server/server/index.js.map +1 -1
- package/dist/server/server/logger.d.ts.map +1 -1
- package/dist/server/server/logger.js +15 -1
- package/dist/server/server/logger.js.map +1 -1
- package/dist/server/server/pagination/cursor.d.ts +16 -0
- package/dist/server/server/pagination/cursor.d.ts.map +1 -0
- package/dist/server/server/pagination/cursor.js +62 -0
- package/dist/server/server/pagination/cursor.js.map +1 -0
- package/dist/server/server/pagination/sortable-pager.d.ts +24 -0
- package/dist/server/server/pagination/sortable-pager.d.ts.map +1 -0
- package/dist/server/server/pagination/sortable-pager.js +68 -0
- package/dist/server/server/pagination/sortable-pager.js.map +1 -0
- package/dist/server/server/paseo-worktree-archive-service.d.ts +3 -1
- package/dist/server/server/paseo-worktree-archive-service.d.ts.map +1 -1
- package/dist/server/server/paseo-worktree-archive-service.js +61 -53
- package/dist/server/server/paseo-worktree-archive-service.js.map +1 -1
- package/dist/server/server/paseo-worktree-service.d.ts +13 -0
- package/dist/server/server/paseo-worktree-service.d.ts.map +1 -1
- package/dist/server/server/paseo-worktree-service.js +72 -3
- package/dist/server/server/paseo-worktree-service.js.map +1 -1
- package/dist/server/server/persisted-config.d.ts +25 -0
- package/dist/server/server/persisted-config.d.ts.map +1 -1
- package/dist/server/server/persisted-config.js +9 -0
- package/dist/server/server/persisted-config.js.map +1 -1
- package/dist/server/server/relay-transport.d.ts.map +1 -1
- package/dist/server/server/relay-transport.js +16 -4
- package/dist/server/server/relay-transport.js.map +1 -1
- package/dist/server/server/resolve-worktree-creation-intent.d.ts +0 -10
- package/dist/server/server/resolve-worktree-creation-intent.d.ts.map +1 -1
- package/dist/server/server/resolve-worktree-creation-intent.js +1 -45
- package/dist/server/server/resolve-worktree-creation-intent.js.map +1 -1
- package/dist/server/server/script-status-projection.d.ts +6 -1
- package/dist/server/server/script-status-projection.d.ts.map +1 -1
- package/dist/server/server/script-status-projection.js +12 -3
- package/dist/server/server/script-status-projection.js.map +1 -1
- package/dist/server/server/session.d.ts +19 -51
- package/dist/server/server/session.d.ts.map +1 -1
- package/dist/server/server/session.js +354 -1069
- package/dist/server/server/session.js.map +1 -1
- package/dist/server/server/websocket-server.d.ts +4 -2
- package/dist/server/server/websocket-server.d.ts.map +1 -1
- package/dist/server/server/websocket-server.js +65 -12
- package/dist/server/server/websocket-server.js.map +1 -1
- package/dist/server/server/workspace-directory.d.ts +69 -0
- package/dist/server/server/workspace-directory.d.ts.map +1 -0
- package/dist/server/server/workspace-directory.js +229 -0
- package/dist/server/server/workspace-directory.js.map +1 -0
- package/dist/server/server/worktree-bootstrap.d.ts.map +1 -1
- package/dist/server/server/worktree-bootstrap.js +6 -2
- package/dist/server/server/worktree-bootstrap.js.map +1 -1
- package/dist/server/server/worktree-core.d.ts +2 -0
- package/dist/server/server/worktree-core.d.ts.map +1 -1
- package/dist/server/server/worktree-core.js.map +1 -1
- package/dist/server/server/worktree-errors.d.ts +1 -1
- package/dist/server/server/worktree-errors.d.ts.map +1 -1
- package/dist/server/server/worktree-errors.js +1 -4
- package/dist/server/server/worktree-errors.js.map +1 -1
- package/dist/server/server/worktree-session.d.ts +47 -20
- package/dist/server/server/worktree-session.d.ts.map +1 -1
- package/dist/server/server/worktree-session.js +68 -25
- package/dist/server/server/worktree-session.js.map +1 -1
- package/dist/server/shared/binary-frames/file-transfer.d.ts +56 -0
- package/dist/server/shared/binary-frames/file-transfer.d.ts.map +1 -0
- package/dist/server/shared/binary-frames/file-transfer.js +108 -0
- package/dist/server/shared/binary-frames/file-transfer.js.map +1 -0
- package/dist/server/shared/binary-frames/index.d.ts +3 -0
- package/dist/server/shared/binary-frames/index.d.ts.map +1 -0
- package/dist/server/shared/binary-frames/index.js +3 -0
- package/dist/server/shared/binary-frames/index.js.map +1 -0
- package/dist/server/shared/{terminal-stream-protocol.d.ts → binary-frames/terminal.d.ts} +2 -2
- package/dist/server/shared/binary-frames/terminal.d.ts.map +1 -0
- package/dist/server/shared/{terminal-stream-protocol.js → binary-frames/terminal.js} +2 -2
- package/dist/server/shared/binary-frames/terminal.js.map +1 -0
- package/dist/server/shared/client-capabilities.d.ts +5 -0
- package/dist/server/shared/client-capabilities.d.ts.map +1 -0
- package/dist/server/shared/client-capabilities.js +4 -0
- package/dist/server/shared/client-capabilities.js.map +1 -0
- package/dist/server/shared/connection-offer.d.ts +8 -0
- package/dist/server/shared/connection-offer.d.ts.map +1 -1
- package/dist/server/shared/connection-offer.js +35 -0
- package/dist/server/shared/connection-offer.js.map +1 -1
- package/dist/server/shared/daemon-endpoints.d.ts +16 -1
- package/dist/server/shared/daemon-endpoints.d.ts.map +1 -1
- package/dist/server/shared/daemon-endpoints.js +65 -6
- package/dist/server/shared/daemon-endpoints.js.map +1 -1
- package/dist/server/shared/host-connection-schema.d.ts +23 -0
- package/dist/server/shared/host-connection-schema.d.ts.map +1 -0
- package/dist/server/shared/host-connection-schema.js +9 -0
- package/dist/server/shared/host-connection-schema.js.map +1 -0
- package/dist/server/shared/messages.d.ts +3242 -535
- package/dist/server/shared/messages.d.ts.map +1 -1
- package/dist/server/shared/messages.js +73 -34
- package/dist/server/shared/messages.js.map +1 -1
- package/dist/server/terminal/terminal-manager-factory.d.ts +7 -0
- package/dist/server/terminal/terminal-manager-factory.d.ts.map +1 -0
- package/dist/server/terminal/terminal-manager-factory.js +13 -0
- package/dist/server/terminal/terminal-manager-factory.js.map +1 -0
- package/dist/server/terminal/terminal-manager.d.ts +7 -1
- package/dist/server/terminal/terminal-manager.d.ts.map +1 -1
- package/dist/server/terminal/terminal-manager.js +14 -1
- package/dist/server/terminal/terminal-manager.js.map +1 -1
- package/dist/server/terminal/terminal-session-controller.d.ts +63 -0
- package/dist/server/terminal/terminal-session-controller.d.ts.map +1 -0
- package/dist/server/terminal/terminal-session-controller.js +615 -0
- package/dist/server/terminal/terminal-session-controller.js.map +1 -0
- package/dist/server/terminal/terminal-ts-loader.mjs +20 -0
- package/dist/server/terminal/terminal-worker-process.d.ts +2 -0
- package/dist/server/terminal/terminal-worker-process.d.ts.map +1 -0
- package/dist/server/terminal/terminal-worker-process.js +221 -0
- package/dist/server/terminal/terminal-worker-process.js.map +1 -0
- package/dist/server/terminal/terminal-worker-protocol.d.ts +113 -0
- package/dist/server/terminal/terminal-worker-protocol.d.ts.map +1 -0
- package/dist/server/terminal/terminal-worker-protocol.js +2 -0
- package/dist/server/terminal/terminal-worker-protocol.js.map +1 -0
- package/dist/server/terminal/terminal.d.ts +7 -0
- package/dist/server/terminal/terminal.d.ts.map +1 -1
- package/dist/server/terminal/terminal.js +22 -9
- package/dist/server/terminal/terminal.js.map +1 -1
- package/dist/server/terminal/worker-terminal-manager.d.ts +19 -0
- package/dist/server/terminal/worker-terminal-manager.d.ts.map +1 -0
- package/dist/server/terminal/worker-terminal-manager.js +466 -0
- package/dist/server/terminal/worker-terminal-manager.js.map +1 -0
- package/dist/server/utils/directory-suggestions.d.ts.map +1 -1
- package/dist/server/utils/directory-suggestions.js +10 -1
- package/dist/server/utils/directory-suggestions.js.map +1 -1
- package/dist/server/utils/process-tree.d.ts +25 -0
- package/dist/server/utils/process-tree.d.ts.map +1 -0
- package/dist/server/utils/process-tree.js +96 -0
- package/dist/server/utils/process-tree.js.map +1 -0
- package/dist/server/utils/windows-command.d.ts.map +1 -1
- package/dist/server/utils/windows-command.js +5 -1
- package/dist/server/utils/windows-command.js.map +1 -1
- package/dist/server/utils/worktree-metadata.d.ts +44 -0
- package/dist/server/utils/worktree-metadata.d.ts.map +1 -1
- package/dist/server/utils/worktree-metadata.js +58 -0
- package/dist/server/utils/worktree-metadata.js.map +1 -1
- package/dist/server/utils/worktree.d.ts +14 -2
- package/dist/server/utils/worktree.d.ts.map +1 -1
- package/dist/server/utils/worktree.js +22 -13
- package/dist/server/utils/worktree.js.map +1 -1
- package/package.json +5 -4
- package/dist/server/shared/terminal-stream-protocol.d.ts.map +0 -1
- package/dist/server/shared/terminal-stream-protocol.js.map +0 -1
|
@@ -5,15 +5,17 @@ import os from "node:os";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import readline from "node:readline";
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
import { loadCodexPersistedTimeline } from "./codex-rollout-timeline.js";
|
|
9
8
|
import { renderPromptAttachmentAsText } from "../prompt-attachments.js";
|
|
9
|
+
import { curateAgentActivity } from "../activity-curator.js";
|
|
10
10
|
import { mapCodexRolloutToolCall, mapCodexToolCallFromThreadItem, } from "./codex/tool-call-mapper.js";
|
|
11
11
|
import { createProviderEnv, createProviderEnvSpec, resolveProviderCommandPrefix, } from "../provider-launch-config.js";
|
|
12
12
|
import { findExecutable, isCommandAvailable } from "../../../utils/executable.js";
|
|
13
|
+
import { terminateProcessTree } from "../../../utils/process-tree.js";
|
|
13
14
|
import { spawnProcess } from "../../../utils/spawn.js";
|
|
14
15
|
import { extractCodexTerminalSessionId, nonEmptyString } from "./tool-call-mapper-utils.js";
|
|
15
16
|
import { buildCodexFeatures, codexModelSupportsFastMode } from "./codex-feature-definitions.js";
|
|
16
17
|
import { formatDiagnosticStatus, formatProviderDiagnostic, formatProviderDiagnosticError, resolveBinaryVersion, toDiagnosticErrorMessage, } from "./diagnostic-utils.js";
|
|
18
|
+
import { runProviderTurn } from "./provider-runner.js";
|
|
17
19
|
const DEFAULT_TIMEOUT_MS = 14 * 24 * 60 * 60 * 1000;
|
|
18
20
|
const TURN_START_TIMEOUT_MS = 90 * 1000;
|
|
19
21
|
const INTERRUPT_TIMEOUT_MS = 2000;
|
|
@@ -21,6 +23,7 @@ const APP_SERVER_GRACEFUL_SHUTDOWN_TIMEOUT_MS = 2000;
|
|
|
21
23
|
const APP_SERVER_FORCE_SHUTDOWN_TIMEOUT_MS = 1000;
|
|
22
24
|
const CODEX_PROVIDER = "codex";
|
|
23
25
|
const CODEX_IMAGE_ATTACHMENT_DIR = "paseo-attachments";
|
|
26
|
+
const ASSISTANT_MESSAGE_BOUNDARY_MARKDOWN = "\n\n---\n\n";
|
|
24
27
|
const CODEX_PLAN_IMPLEMENTATION_PROMPT_PREFIX = "The user approved the plan. Implement it now. Do not restate or revise the plan unless blocked.";
|
|
25
28
|
const CODEX_APP_SERVER_CAPABILITIES = {
|
|
26
29
|
supportsStreaming: true,
|
|
@@ -406,11 +409,7 @@ class CodexAppServerClient {
|
|
|
406
409
|
this.nextId = 1;
|
|
407
410
|
this.disposed = false;
|
|
408
411
|
this.stderrBuffer = "";
|
|
409
|
-
this.resolveExitPromise = null;
|
|
410
412
|
this.rl = readline.createInterface({ input: child.stdout });
|
|
411
|
-
this.exitPromise = new Promise((resolve) => {
|
|
412
|
-
this.resolveExitPromise = resolve;
|
|
413
|
-
});
|
|
414
413
|
this.rl.on("line", (line) => this.handleLine(line));
|
|
415
414
|
child.stderr.on("data", (chunk) => {
|
|
416
415
|
this.stderrBuffer += chunk.toString();
|
|
@@ -426,8 +425,6 @@ class CodexAppServerClient {
|
|
|
426
425
|
}
|
|
427
426
|
this.pending.clear();
|
|
428
427
|
this.disposed = true;
|
|
429
|
-
this.resolveExitPromise?.();
|
|
430
|
-
this.resolveExitPromise = null;
|
|
431
428
|
});
|
|
432
429
|
child.on("exit", (code, signal) => {
|
|
433
430
|
const message = code === 0 && !signal
|
|
@@ -440,8 +437,6 @@ class CodexAppServerClient {
|
|
|
440
437
|
}
|
|
441
438
|
this.pending.clear();
|
|
442
439
|
this.disposed = true;
|
|
443
|
-
this.resolveExitPromise?.();
|
|
444
|
-
this.resolveExitPromise = null;
|
|
445
440
|
});
|
|
446
441
|
}
|
|
447
442
|
setNotificationHandler(handler) {
|
|
@@ -495,31 +490,15 @@ class CodexAppServerClient {
|
|
|
495
490
|
catch {
|
|
496
491
|
// ignore
|
|
497
492
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
this.logger.warn({ timeoutMs: APP_SERVER_FORCE_SHUTDOWN_TIMEOUT_MS }, "Codex app-server did not report exit after SIGKILL");
|
|
508
|
-
}
|
|
509
|
-
async waitForExit(timeoutMs) {
|
|
510
|
-
let timer = null;
|
|
511
|
-
try {
|
|
512
|
-
return await Promise.race([
|
|
513
|
-
this.exitPromise.then(() => true),
|
|
514
|
-
new Promise((resolve) => {
|
|
515
|
-
timer = setTimeout(() => resolve(false), timeoutMs);
|
|
516
|
-
}),
|
|
517
|
-
]);
|
|
518
|
-
}
|
|
519
|
-
finally {
|
|
520
|
-
if (timer) {
|
|
521
|
-
clearTimeout(timer);
|
|
522
|
-
}
|
|
493
|
+
const result = await terminateProcessTree(this.child, {
|
|
494
|
+
gracefulTimeoutMs: APP_SERVER_GRACEFUL_SHUTDOWN_TIMEOUT_MS,
|
|
495
|
+
forceTimeoutMs: APP_SERVER_FORCE_SHUTDOWN_TIMEOUT_MS,
|
|
496
|
+
onForceSignal: () => {
|
|
497
|
+
this.logger.warn({ timeoutMs: APP_SERVER_GRACEFUL_SHUTDOWN_TIMEOUT_MS }, "Codex app-server did not exit after SIGTERM; sending SIGKILL");
|
|
498
|
+
},
|
|
499
|
+
});
|
|
500
|
+
if (result === "kill-timeout") {
|
|
501
|
+
this.logger.warn({ timeoutMs: APP_SERVER_FORCE_SHUTDOWN_TIMEOUT_MS }, "Codex app-server did not report exit after SIGKILL");
|
|
523
502
|
}
|
|
524
503
|
}
|
|
525
504
|
async handleLine(line) {
|
|
@@ -572,26 +551,6 @@ class CodexAppServerClient {
|
|
|
572
551
|
}
|
|
573
552
|
}
|
|
574
553
|
}
|
|
575
|
-
function signalChildProcessTree(child, signal) {
|
|
576
|
-
if (child.exitCode !== null || child.signalCode !== null) {
|
|
577
|
-
return;
|
|
578
|
-
}
|
|
579
|
-
if (process.platform !== "win32" && typeof child.pid === "number" && child.pid > 0) {
|
|
580
|
-
try {
|
|
581
|
-
process.kill(-child.pid, signal);
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
catch {
|
|
585
|
-
// Fall back to the direct child when no separate process group exists.
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
try {
|
|
589
|
-
child.kill(signal);
|
|
590
|
-
}
|
|
591
|
-
catch {
|
|
592
|
-
// ignore
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
554
|
function toAgentUsage(tokenUsage) {
|
|
596
555
|
if (!tokenUsage || typeof tokenUsage !== "object")
|
|
597
556
|
return undefined;
|
|
@@ -881,6 +840,8 @@ function normalizeCodexThreadItemType(rawType) {
|
|
|
881
840
|
return "mcpToolCall";
|
|
882
841
|
case "WebSearch":
|
|
883
842
|
return "webSearch";
|
|
843
|
+
case "CollabAgentToolCall":
|
|
844
|
+
return "collabAgentToolCall";
|
|
884
845
|
default:
|
|
885
846
|
return rawType;
|
|
886
847
|
}
|
|
@@ -1183,11 +1144,51 @@ function threadItemToTimeline(item, options) {
|
|
|
1183
1144
|
case "fileChange":
|
|
1184
1145
|
case "mcpToolCall":
|
|
1185
1146
|
case "webSearch":
|
|
1147
|
+
case "collabAgentToolCall":
|
|
1186
1148
|
return mapCodexToolCallFromThreadItem(normalizedItem, { cwd });
|
|
1187
1149
|
default:
|
|
1188
1150
|
return null;
|
|
1189
1151
|
}
|
|
1190
1152
|
}
|
|
1153
|
+
const CodexThreadReadResponseSchema = z
|
|
1154
|
+
.object({
|
|
1155
|
+
thread: z
|
|
1156
|
+
.object({
|
|
1157
|
+
turns: z
|
|
1158
|
+
.array(z
|
|
1159
|
+
.object({
|
|
1160
|
+
items: z.array(z.unknown()).default([]),
|
|
1161
|
+
})
|
|
1162
|
+
.passthrough())
|
|
1163
|
+
.default([]),
|
|
1164
|
+
})
|
|
1165
|
+
.passthrough()
|
|
1166
|
+
.default({ turns: [] }),
|
|
1167
|
+
})
|
|
1168
|
+
.passthrough();
|
|
1169
|
+
async function requestCodexThreadHistory(requestThread, threadId) {
|
|
1170
|
+
const response = await requestThread(threadId);
|
|
1171
|
+
return CodexThreadReadResponseSchema.parse(response);
|
|
1172
|
+
}
|
|
1173
|
+
async function loadCodexThreadHistoryTimeline(params) {
|
|
1174
|
+
const response = await requestCodexThreadHistory(params.requestThread, params.threadId);
|
|
1175
|
+
const timeline = [];
|
|
1176
|
+
for (const turn of response.thread.turns) {
|
|
1177
|
+
for (const item of turn.items) {
|
|
1178
|
+
const timelineItem = threadItemToTimeline(item, { cwd: params.cwd });
|
|
1179
|
+
if (timelineItem) {
|
|
1180
|
+
timeline.push(timelineItem);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
return timeline;
|
|
1185
|
+
}
|
|
1186
|
+
function readCodexThread(client, threadId) {
|
|
1187
|
+
return client.request("thread/read", {
|
|
1188
|
+
threadId,
|
|
1189
|
+
includeTurns: true,
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1191
1192
|
function toSandboxPolicy(type, networkAccess) {
|
|
1192
1193
|
switch (type) {
|
|
1193
1194
|
case "read-only":
|
|
@@ -1234,11 +1235,13 @@ const ThreadStartedNotificationSchema = z
|
|
|
1234
1235
|
.passthrough();
|
|
1235
1236
|
const TurnStartedNotificationSchema = z
|
|
1236
1237
|
.object({
|
|
1238
|
+
threadId: z.string().optional(),
|
|
1237
1239
|
turn: z.object({ id: z.string() }).passthrough(),
|
|
1238
1240
|
})
|
|
1239
1241
|
.passthrough();
|
|
1240
1242
|
const TurnCompletedNotificationSchema = z
|
|
1241
1243
|
.object({
|
|
1244
|
+
threadId: z.string().optional(),
|
|
1242
1245
|
turn: z
|
|
1243
1246
|
.object({
|
|
1244
1247
|
status: z.string(),
|
|
@@ -1275,12 +1278,14 @@ const ThreadTokenUsageUpdatedNotificationSchema = z
|
|
|
1275
1278
|
.passthrough();
|
|
1276
1279
|
const ItemTextDeltaNotificationSchema = z
|
|
1277
1280
|
.object({
|
|
1281
|
+
threadId: z.string().optional(),
|
|
1278
1282
|
itemId: z.string(),
|
|
1279
1283
|
delta: z.string(),
|
|
1280
1284
|
})
|
|
1281
1285
|
.passthrough();
|
|
1282
1286
|
const ItemLifecycleNotificationSchema = z
|
|
1283
1287
|
.object({
|
|
1288
|
+
threadId: z.string().optional(),
|
|
1284
1289
|
item: z
|
|
1285
1290
|
.object({
|
|
1286
1291
|
id: z.string().optional(),
|
|
@@ -1310,9 +1315,12 @@ const CodexEventTaskCompleteNotificationSchema = z
|
|
|
1310
1315
|
.passthrough();
|
|
1311
1316
|
const CodexEventItemLifecycleNotificationSchema = z
|
|
1312
1317
|
.object({
|
|
1318
|
+
threadId: z.string().optional(),
|
|
1313
1319
|
msg: z
|
|
1314
1320
|
.object({
|
|
1315
1321
|
type: z.enum(["item_started", "item_completed"]),
|
|
1322
|
+
threadId: z.string().optional(),
|
|
1323
|
+
thread_id: z.string().optional(),
|
|
1316
1324
|
item: z
|
|
1317
1325
|
.object({
|
|
1318
1326
|
id: z.string().optional(),
|
|
@@ -1442,9 +1450,11 @@ const CodexNotificationSchema = z.union([
|
|
|
1442
1450
|
method,
|
|
1443
1451
|
params,
|
|
1444
1452
|
})),
|
|
1445
|
-
z
|
|
1446
|
-
|
|
1447
|
-
|
|
1453
|
+
z.object({ method: z.literal("turn/started"), params: TurnStartedNotificationSchema }).transform(({ params }) => ({
|
|
1454
|
+
kind: "turn_started",
|
|
1455
|
+
turnId: params.turn.id,
|
|
1456
|
+
threadId: params.threadId ?? null,
|
|
1457
|
+
})),
|
|
1448
1458
|
z.object({ method: z.literal("turn/started"), params: z.unknown() }).transform(({ method, params }) => ({
|
|
1449
1459
|
kind: "invalid_payload",
|
|
1450
1460
|
method,
|
|
@@ -1456,6 +1466,7 @@ const CodexNotificationSchema = z.union([
|
|
|
1456
1466
|
kind: "turn_completed",
|
|
1457
1467
|
status: params.turn.status,
|
|
1458
1468
|
errorMessage: params.turn.error?.message ?? null,
|
|
1469
|
+
threadId: params.threadId ?? null,
|
|
1459
1470
|
})),
|
|
1460
1471
|
z.object({ method: z.literal("turn/completed"), params: z.unknown() }).transform(({ method, params }) => ({
|
|
1461
1472
|
kind: "invalid_payload",
|
|
@@ -1507,6 +1518,7 @@ const CodexNotificationSchema = z.union([
|
|
|
1507
1518
|
kind: "agent_message_delta",
|
|
1508
1519
|
itemId: params.itemId,
|
|
1509
1520
|
delta: params.delta,
|
|
1521
|
+
threadId: params.threadId ?? null,
|
|
1510
1522
|
})),
|
|
1511
1523
|
z.object({ method: z.literal("item/agentMessage/delta"), params: z.unknown() }).transform(({ method, params }) => ({
|
|
1512
1524
|
kind: "invalid_payload",
|
|
@@ -1522,6 +1534,7 @@ const CodexNotificationSchema = z.union([
|
|
|
1522
1534
|
kind: "reasoning_delta",
|
|
1523
1535
|
itemId: params.itemId,
|
|
1524
1536
|
delta: params.delta,
|
|
1537
|
+
threadId: params.threadId ?? null,
|
|
1525
1538
|
})),
|
|
1526
1539
|
z.object({ method: z.literal("item/reasoning/summaryTextDelta"), params: z.unknown() }).transform(({ method, params }) => ({
|
|
1527
1540
|
kind: "invalid_payload",
|
|
@@ -1533,6 +1546,7 @@ const CodexNotificationSchema = z.union([
|
|
|
1533
1546
|
.transform(({ params }) => ({
|
|
1534
1547
|
kind: "item_completed",
|
|
1535
1548
|
source: "item",
|
|
1549
|
+
threadId: params.threadId ?? null,
|
|
1536
1550
|
item: params.item,
|
|
1537
1551
|
})),
|
|
1538
1552
|
z.object({ method: z.literal("item/completed"), params: z.unknown() }).transform(({ method, params }) => ({
|
|
@@ -1545,6 +1559,7 @@ const CodexNotificationSchema = z.union([
|
|
|
1545
1559
|
.transform(({ params }) => ({
|
|
1546
1560
|
kind: "item_started",
|
|
1547
1561
|
source: "item",
|
|
1562
|
+
threadId: params.threadId ?? null,
|
|
1548
1563
|
item: params.item,
|
|
1549
1564
|
})),
|
|
1550
1565
|
z.object({ method: z.literal("item/started"), params: z.unknown() }).transform(({ method, params }) => ({
|
|
@@ -1560,6 +1575,7 @@ const CodexNotificationSchema = z.union([
|
|
|
1560
1575
|
.transform(({ params }) => ({
|
|
1561
1576
|
kind: "item_started",
|
|
1562
1577
|
source: "codex_event",
|
|
1578
|
+
threadId: params.threadId ?? params.msg.threadId ?? params.msg.thread_id ?? null,
|
|
1563
1579
|
item: params.msg.item,
|
|
1564
1580
|
})),
|
|
1565
1581
|
z.object({ method: z.literal("codex/event/item_started"), params: z.unknown() }).transform(({ method, params }) => ({
|
|
@@ -1575,6 +1591,7 @@ const CodexNotificationSchema = z.union([
|
|
|
1575
1591
|
.transform(({ params }) => ({
|
|
1576
1592
|
kind: "item_completed",
|
|
1577
1593
|
source: "codex_event",
|
|
1594
|
+
threadId: params.threadId ?? params.msg.threadId ?? params.msg.thread_id ?? null,
|
|
1578
1595
|
item: params.msg.item,
|
|
1579
1596
|
})),
|
|
1580
1597
|
z.object({ method: z.literal("codex/event/item_completed"), params: z.unknown() }).transform(({ method, params }) => ({
|
|
@@ -1759,6 +1776,7 @@ const CodexNotificationSchema = z.union([
|
|
|
1759
1776
|
kind: "turn_completed",
|
|
1760
1777
|
status: "interrupted",
|
|
1761
1778
|
errorMessage: null,
|
|
1779
|
+
threadId: null,
|
|
1762
1780
|
})),
|
|
1763
1781
|
z.object({ method: z.literal("codex/event/turn_aborted"), params: z.unknown() }).transform(({ method, params }) => ({
|
|
1764
1782
|
kind: "invalid_payload",
|
|
@@ -1774,6 +1792,7 @@ const CodexNotificationSchema = z.union([
|
|
|
1774
1792
|
kind: "turn_completed",
|
|
1775
1793
|
status: "completed",
|
|
1776
1794
|
errorMessage: null,
|
|
1795
|
+
threadId: null,
|
|
1777
1796
|
})),
|
|
1778
1797
|
z.object({ method: z.literal("codex/event/task_complete"), params: z.unknown() }).transform(({ method, params }) => ({
|
|
1779
1798
|
kind: "invalid_payload",
|
|
@@ -1824,40 +1843,49 @@ async function readCodexConfiguredDefaults(client, logger) {
|
|
|
1824
1843
|
}
|
|
1825
1844
|
export async function codexAppServerTurnInputFromPrompt(prompt, logger) {
|
|
1826
1845
|
if (typeof prompt === "string") {
|
|
1827
|
-
return [
|
|
1828
|
-
}
|
|
1829
|
-
const
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1846
|
+
return [toCodexTextInput(prompt)];
|
|
1847
|
+
}
|
|
1848
|
+
const output = [];
|
|
1849
|
+
let previousTextBlock = false;
|
|
1850
|
+
for (const block of prompt) {
|
|
1851
|
+
if (block.type === "text") {
|
|
1852
|
+
output.push(toCodexTextInput(block.text));
|
|
1853
|
+
previousTextBlock = block.text.length > 0;
|
|
1854
|
+
continue;
|
|
1833
1855
|
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1856
|
+
if (block.type === "skill") {
|
|
1857
|
+
output.push(block);
|
|
1858
|
+
previousTextBlock = false;
|
|
1859
|
+
continue;
|
|
1860
|
+
}
|
|
1861
|
+
if (block.type === "image") {
|
|
1838
1862
|
try {
|
|
1839
|
-
const filePath = await writeImageAttachment(
|
|
1840
|
-
|
|
1863
|
+
const filePath = await writeImageAttachment(block.mimeType, block.data);
|
|
1864
|
+
output.push({ type: "localImage", path: filePath });
|
|
1841
1865
|
}
|
|
1842
1866
|
catch (error) {
|
|
1843
1867
|
const message = error instanceof Error ? error.message : String(error);
|
|
1844
1868
|
logger.warn({ message }, "Failed to write Codex image attachment");
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
};
|
|
1869
|
+
output.push({
|
|
1870
|
+
...toCodexTextInput(`User attached image (failed to write temp file): ${message}`),
|
|
1871
|
+
});
|
|
1849
1872
|
}
|
|
1873
|
+
previousTextBlock = false;
|
|
1874
|
+
continue;
|
|
1850
1875
|
}
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
};
|
|
1856
|
-
}
|
|
1857
|
-
return block;
|
|
1858
|
-
}));
|
|
1876
|
+
const attachmentText = renderPromptAttachmentAsText(block);
|
|
1877
|
+
output.push(toCodexTextInput(previousTextBlock ? `\n\n${attachmentText}` : attachmentText));
|
|
1878
|
+
previousTextBlock = true;
|
|
1879
|
+
}
|
|
1859
1880
|
return output;
|
|
1860
1881
|
}
|
|
1882
|
+
function toCodexTextInput(text) {
|
|
1883
|
+
return {
|
|
1884
|
+
type: "text",
|
|
1885
|
+
text,
|
|
1886
|
+
text_elements: [],
|
|
1887
|
+
};
|
|
1888
|
+
}
|
|
1861
1889
|
function buildCodexAppServerEnv(runtimeSettings, launchEnv) {
|
|
1862
1890
|
return createProviderEnv({
|
|
1863
1891
|
runtimeSettings,
|
|
@@ -1901,6 +1929,7 @@ class CodexAppServerAgentSession {
|
|
|
1901
1929
|
this.pendingReasoning = new Map();
|
|
1902
1930
|
this.pendingCommandOutputDeltas = new Map();
|
|
1903
1931
|
this.pendingFileChangeOutputDeltas = new Map();
|
|
1932
|
+
this.pendingAssistantMessageBoundary = false;
|
|
1904
1933
|
this.terminalCommandByProcessId = new Map();
|
|
1905
1934
|
this.pendingUnlabeledTerminalInteractions = new Set();
|
|
1906
1935
|
this.emittedTerminalInteractionKeys = new Set();
|
|
@@ -1908,6 +1937,8 @@ class CodexAppServerAgentSession {
|
|
|
1908
1937
|
this.emittedExecCommandCompletedCallIds = new Set();
|
|
1909
1938
|
this.emittedItemStartedIds = new Set();
|
|
1910
1939
|
this.emittedItemCompletedIds = new Set();
|
|
1940
|
+
this.subAgentCallsByCallId = new Map();
|
|
1941
|
+
this.subAgentCallIdByChildThreadId = new Map();
|
|
1911
1942
|
this.warnedUnknownNotificationMethods = new Set();
|
|
1912
1943
|
this.warnedInvalidNotificationPayloads = new Set();
|
|
1913
1944
|
this.warnedIncompleteEditToolCallIds = new Set();
|
|
@@ -1958,8 +1989,8 @@ class CodexAppServerAgentSession {
|
|
|
1958
1989
|
await this.loadCollaborationModes();
|
|
1959
1990
|
await this.loadSkills();
|
|
1960
1991
|
if (this.currentThreadId) {
|
|
1961
|
-
await this.loadPersistedHistory();
|
|
1962
1992
|
await this.ensureThreadLoaded();
|
|
1993
|
+
await this.loadPersistedHistory();
|
|
1963
1994
|
}
|
|
1964
1995
|
this.connected = true;
|
|
1965
1996
|
}
|
|
@@ -2128,27 +2159,16 @@ class CodexAppServerAgentSession {
|
|
|
2128
2159
|
async loadPersistedHistory() {
|
|
2129
2160
|
if (!this.client || !this.currentThreadId)
|
|
2130
2161
|
return;
|
|
2162
|
+
const client = this.client;
|
|
2163
|
+
const threadId = this.currentThreadId;
|
|
2131
2164
|
try {
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
}
|
|
2139
|
-
const response = (await this.client.request("thread/read", {
|
|
2140
|
-
threadId: this.currentThreadId,
|
|
2141
|
-
includeTurns: true,
|
|
2142
|
-
}));
|
|
2143
|
-
const thread = response?.thread;
|
|
2144
|
-
const threadTimeline = [];
|
|
2145
|
-
if (thread && Array.isArray(thread.turns)) {
|
|
2146
|
-
for (const turn of thread.turns) {
|
|
2147
|
-
const items = Array.isArray(turn.items) ? turn.items : [];
|
|
2148
|
-
this.collectThreadTurnTimelineItems(items, threadTimeline);
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
const timeline = rolloutTimeline.length > 0 ? rolloutTimeline : threadTimeline;
|
|
2165
|
+
const timeline = await loadCodexThreadHistoryTimeline({
|
|
2166
|
+
threadId,
|
|
2167
|
+
cwd: this.config.cwd ?? null,
|
|
2168
|
+
requestThread: (threadIdToRead) => {
|
|
2169
|
+
return readCodexThread(client, threadIdToRead);
|
|
2170
|
+
},
|
|
2171
|
+
});
|
|
2152
2172
|
if (timeline.length > 0) {
|
|
2153
2173
|
this.persistedHistory = timeline;
|
|
2154
2174
|
this.historyPending = true;
|
|
@@ -2245,79 +2265,22 @@ class CodexAppServerAgentSession {
|
|
|
2245
2265
|
return args ? `$${commandName} ${args}` : `$${commandName}`;
|
|
2246
2266
|
}
|
|
2247
2267
|
async run(prompt, options) {
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
if (settled) {
|
|
2258
|
-
return;
|
|
2259
|
-
}
|
|
2260
|
-
const eventTurnId = event.turnId;
|
|
2261
|
-
if (turnId && eventTurnId && eventTurnId !== turnId) {
|
|
2262
|
-
return;
|
|
2263
|
-
}
|
|
2264
|
-
if (event.type === "timeline") {
|
|
2265
|
-
timeline.push(event.item);
|
|
2266
|
-
if (event.item.type === "assistant_message") {
|
|
2267
|
-
finalText = event.item.text;
|
|
2268
|
+
return runProviderTurn({
|
|
2269
|
+
prompt,
|
|
2270
|
+
runOptions: options,
|
|
2271
|
+
startTurn: (p, o) => this.startTurn(p, o),
|
|
2272
|
+
subscribe: (callback) => this.subscribe(callback),
|
|
2273
|
+
getSessionId: async () => (await this.getRuntimeInfo()).sessionId ?? "",
|
|
2274
|
+
reduceFinalText: ({ current, item }) => {
|
|
2275
|
+
if (item.type === "assistant_message") {
|
|
2276
|
+
return item.text;
|
|
2268
2277
|
}
|
|
2269
|
-
|
|
2270
|
-
|
|
2278
|
+
if (item.type === "tool_call" && item.detail.type === "plan") {
|
|
2279
|
+
return item.detail.text;
|
|
2271
2280
|
}
|
|
2272
|
-
return;
|
|
2273
|
-
}
|
|
2274
|
-
if (event.type === "turn_completed") {
|
|
2275
|
-
usage = event.usage;
|
|
2276
|
-
settled = true;
|
|
2277
|
-
resolveCompletion();
|
|
2278
|
-
return;
|
|
2279
|
-
}
|
|
2280
|
-
if (event.type === "turn_failed") {
|
|
2281
|
-
settled = true;
|
|
2282
|
-
rejectCompletion(new Error(event.error));
|
|
2283
|
-
return;
|
|
2284
|
-
}
|
|
2285
|
-
if (event.type === "turn_canceled") {
|
|
2286
|
-
settled = true;
|
|
2287
|
-
resolveCompletion();
|
|
2288
|
-
}
|
|
2289
|
-
};
|
|
2290
|
-
const completion = new Promise((resolve, reject) => {
|
|
2291
|
-
resolveCompletion = resolve;
|
|
2292
|
-
rejectCompletion = reject;
|
|
2293
|
-
});
|
|
2294
|
-
const unsubscribe = this.subscribe((event) => {
|
|
2295
|
-
if (!turnId) {
|
|
2296
|
-
bufferedEvents.push(event);
|
|
2297
|
-
return;
|
|
2298
|
-
}
|
|
2299
|
-
processEvent(event);
|
|
2281
|
+
return current;
|
|
2282
|
+
},
|
|
2300
2283
|
});
|
|
2301
|
-
try {
|
|
2302
|
-
const result = await this.startTurn(prompt, options);
|
|
2303
|
-
turnId = result.turnId;
|
|
2304
|
-
for (const event of bufferedEvents) {
|
|
2305
|
-
processEvent(event);
|
|
2306
|
-
}
|
|
2307
|
-
if (!settled) {
|
|
2308
|
-
await completion;
|
|
2309
|
-
}
|
|
2310
|
-
}
|
|
2311
|
-
finally {
|
|
2312
|
-
unsubscribe();
|
|
2313
|
-
}
|
|
2314
|
-
const info = await this.getRuntimeInfo();
|
|
2315
|
-
return {
|
|
2316
|
-
sessionId: info.sessionId ?? "",
|
|
2317
|
-
finalText,
|
|
2318
|
-
usage,
|
|
2319
|
-
timeline,
|
|
2320
|
-
};
|
|
2321
2284
|
}
|
|
2322
2285
|
async startTurn(prompt, options) {
|
|
2323
2286
|
if (this.activeForegroundTurnId) {
|
|
@@ -2740,17 +2703,11 @@ class CodexAppServerAgentSession {
|
|
|
2740
2703
|
}
|
|
2741
2704
|
async buildUserInput(prompt) {
|
|
2742
2705
|
if (typeof prompt === "string") {
|
|
2743
|
-
return [
|
|
2706
|
+
return [toCodexTextInput(prompt)];
|
|
2744
2707
|
}
|
|
2745
|
-
|
|
2746
|
-
return await codexAppServerTurnInputFromPrompt(blocks, this.logger);
|
|
2708
|
+
return await codexAppServerTurnInputFromPrompt(prompt, this.logger);
|
|
2747
2709
|
}
|
|
2748
2710
|
emitEvent(event) {
|
|
2749
|
-
if (event.type === "timeline") {
|
|
2750
|
-
if (event.item.type === "assistant_message") {
|
|
2751
|
-
this.pendingAgentMessages.clear();
|
|
2752
|
-
}
|
|
2753
|
-
}
|
|
2754
2711
|
this.notifySubscribers(event);
|
|
2755
2712
|
}
|
|
2756
2713
|
notifySubscribers(event) {
|
|
@@ -2825,16 +2782,153 @@ class CodexAppServerAgentSession {
|
|
|
2825
2782
|
this.warnUnknownNotificationMethod(parsed.method, parsed.params);
|
|
2826
2783
|
}
|
|
2827
2784
|
}
|
|
2785
|
+
getSubAgentCallIdForThread(threadId) {
|
|
2786
|
+
if (!threadId || threadId === this.currentThreadId) {
|
|
2787
|
+
return null;
|
|
2788
|
+
}
|
|
2789
|
+
return this.subAgentCallIdByChildThreadId.get(threadId) ?? null;
|
|
2790
|
+
}
|
|
2791
|
+
registerSubAgentToolCall(timelineItem, rawItem) {
|
|
2792
|
+
if (timelineItem.detail.type !== "sub_agent") {
|
|
2793
|
+
return;
|
|
2794
|
+
}
|
|
2795
|
+
const existing = this.subAgentCallsByCallId.get(timelineItem.callId);
|
|
2796
|
+
const state = existing ??
|
|
2797
|
+
{
|
|
2798
|
+
callId: timelineItem.callId,
|
|
2799
|
+
toolCall: timelineItem,
|
|
2800
|
+
childItemOrder: [],
|
|
2801
|
+
childItems: new Map(),
|
|
2802
|
+
};
|
|
2803
|
+
state.toolCall = {
|
|
2804
|
+
...timelineItem,
|
|
2805
|
+
detail: {
|
|
2806
|
+
...timelineItem.detail,
|
|
2807
|
+
log: timelineItem.detail.log ||
|
|
2808
|
+
(state.toolCall.detail.type === "sub_agent" ? state.toolCall.detail.log : ""),
|
|
2809
|
+
},
|
|
2810
|
+
};
|
|
2811
|
+
this.subAgentCallsByCallId.set(timelineItem.callId, state);
|
|
2812
|
+
const receiverThreadIds = Array.isArray(rawItem.receiverThreadIds)
|
|
2813
|
+
? rawItem.receiverThreadIds.filter((value) => typeof value === "string")
|
|
2814
|
+
: [];
|
|
2815
|
+
for (const receiverThreadId of receiverThreadIds) {
|
|
2816
|
+
this.subAgentCallIdByChildThreadId.set(receiverThreadId, timelineItem.callId);
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
upsertSubAgentChildItem(callId, itemId, item) {
|
|
2820
|
+
const state = this.subAgentCallsByCallId.get(callId);
|
|
2821
|
+
if (!state) {
|
|
2822
|
+
return;
|
|
2823
|
+
}
|
|
2824
|
+
if (!state.childItems.has(itemId)) {
|
|
2825
|
+
state.childItemOrder.push(itemId);
|
|
2826
|
+
}
|
|
2827
|
+
state.childItems.set(itemId, item);
|
|
2828
|
+
}
|
|
2829
|
+
getSubAgentChildTimeline(state) {
|
|
2830
|
+
return state.childItemOrder
|
|
2831
|
+
.map((itemId) => state.childItems.get(itemId))
|
|
2832
|
+
.filter((item) => Boolean(item));
|
|
2833
|
+
}
|
|
2834
|
+
emitSubAgentActivityUpdate(callId, status) {
|
|
2835
|
+
const state = this.subAgentCallsByCallId.get(callId);
|
|
2836
|
+
if (!state || state.toolCall.detail.type !== "sub_agent") {
|
|
2837
|
+
return;
|
|
2838
|
+
}
|
|
2839
|
+
const childTimeline = this.getSubAgentChildTimeline(state);
|
|
2840
|
+
const log = childTimeline.length > 0
|
|
2841
|
+
? curateAgentActivity(childTimeline, { labelAssistantMessages: true })
|
|
2842
|
+
: "";
|
|
2843
|
+
const resolvedStatus = status ?? state.toolCall.status;
|
|
2844
|
+
const baseToolCall = {
|
|
2845
|
+
...state.toolCall,
|
|
2846
|
+
detail: {
|
|
2847
|
+
...state.toolCall.detail,
|
|
2848
|
+
log,
|
|
2849
|
+
},
|
|
2850
|
+
};
|
|
2851
|
+
const nextToolCall = resolvedStatus === "failed"
|
|
2852
|
+
? {
|
|
2853
|
+
...baseToolCall,
|
|
2854
|
+
status: "failed",
|
|
2855
|
+
error: state.toolCall.error ?? { message: "Sub-agent failed" },
|
|
2856
|
+
}
|
|
2857
|
+
: {
|
|
2858
|
+
...baseToolCall,
|
|
2859
|
+
status: resolvedStatus,
|
|
2860
|
+
error: null,
|
|
2861
|
+
};
|
|
2862
|
+
state.toolCall = nextToolCall;
|
|
2863
|
+
this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: nextToolCall });
|
|
2864
|
+
}
|
|
2865
|
+
handleSubAgentChildItemCompleted(callId, itemId, timelineItem) {
|
|
2866
|
+
this.applyBufferedDeltaTextToTimelineItem(timelineItem, itemId);
|
|
2867
|
+
if (itemId) {
|
|
2868
|
+
this.upsertSubAgentChildItem(callId, itemId, timelineItem);
|
|
2869
|
+
this.pendingAgentMessages.delete(itemId);
|
|
2870
|
+
this.pendingReasoning.delete(itemId);
|
|
2871
|
+
this.pendingCommandOutputDeltas.delete(itemId);
|
|
2872
|
+
this.pendingFileChangeOutputDeltas.delete(itemId);
|
|
2873
|
+
}
|
|
2874
|
+
this.emitSubAgentActivityUpdate(callId, timelineItem.type === "tool_call" && timelineItem.status === "failed" ? "failed" : "running");
|
|
2875
|
+
}
|
|
2876
|
+
shouldSkipCompletedThreadItem(timelineItem, normalizedItemType, itemId) {
|
|
2877
|
+
// For commandExecution items, codex/event/exec_command_* is authoritative.
|
|
2878
|
+
if (timelineItem.type === "tool_call" && normalizedItemType === "commandExecution") {
|
|
2879
|
+
const callId = timelineItem.callId || itemId;
|
|
2880
|
+
return Boolean(callId && this.emittedExecCommandCompletedCallIds.has(callId));
|
|
2881
|
+
}
|
|
2882
|
+
return Boolean(itemId && this.emittedItemCompletedIds.has(itemId));
|
|
2883
|
+
}
|
|
2828
2884
|
handleCodexDeltaNotification(parsed) {
|
|
2829
2885
|
if (parsed.kind === "agent_message_delta") {
|
|
2830
2886
|
const prev = this.pendingAgentMessages.get(parsed.itemId) ?? "";
|
|
2831
|
-
|
|
2887
|
+
const text = prev + parsed.delta;
|
|
2888
|
+
this.pendingAgentMessages.set(parsed.itemId, text);
|
|
2889
|
+
const subAgentCallId = this.getSubAgentCallIdForThread(parsed.threadId);
|
|
2890
|
+
if (subAgentCallId) {
|
|
2891
|
+
this.upsertSubAgentChildItem(subAgentCallId, parsed.itemId, {
|
|
2892
|
+
type: "assistant_message",
|
|
2893
|
+
text,
|
|
2894
|
+
});
|
|
2895
|
+
this.emitSubAgentActivityUpdate(subAgentCallId, "running");
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2898
|
+
const isFirstDeltaForItem = prev.length === 0;
|
|
2899
|
+
this.emitEvent({
|
|
2900
|
+
type: "timeline",
|
|
2901
|
+
provider: CODEX_PROVIDER,
|
|
2902
|
+
item: {
|
|
2903
|
+
type: "assistant_message",
|
|
2904
|
+
text: isFirstDeltaForItem && this.pendingAssistantMessageBoundary
|
|
2905
|
+
? `${ASSISTANT_MESSAGE_BOUNDARY_MARKDOWN}${parsed.delta}`
|
|
2906
|
+
: parsed.delta,
|
|
2907
|
+
},
|
|
2908
|
+
});
|
|
2909
|
+
if (isFirstDeltaForItem) {
|
|
2910
|
+
this.pendingAssistantMessageBoundary = false;
|
|
2911
|
+
}
|
|
2832
2912
|
return;
|
|
2833
2913
|
}
|
|
2834
2914
|
if (parsed.kind === "reasoning_delta") {
|
|
2835
2915
|
const prev = this.pendingReasoning.get(parsed.itemId) ?? [];
|
|
2836
2916
|
prev.push(parsed.delta);
|
|
2837
2917
|
this.pendingReasoning.set(parsed.itemId, prev);
|
|
2918
|
+
const subAgentCallId = this.getSubAgentCallIdForThread(parsed.threadId);
|
|
2919
|
+
if (subAgentCallId) {
|
|
2920
|
+
this.upsertSubAgentChildItem(subAgentCallId, parsed.itemId, {
|
|
2921
|
+
type: "reasoning",
|
|
2922
|
+
text: prev.join(""),
|
|
2923
|
+
});
|
|
2924
|
+
this.emitSubAgentActivityUpdate(subAgentCallId, "running");
|
|
2925
|
+
return;
|
|
2926
|
+
}
|
|
2927
|
+
this.emitEvent({
|
|
2928
|
+
type: "timeline",
|
|
2929
|
+
provider: CODEX_PROVIDER,
|
|
2930
|
+
item: { type: "reasoning", text: parsed.delta },
|
|
2931
|
+
});
|
|
2838
2932
|
return;
|
|
2839
2933
|
}
|
|
2840
2934
|
if (parsed.kind === "exec_command_output_delta") {
|
|
@@ -2854,11 +2948,28 @@ class CodexAppServerAgentSession {
|
|
|
2854
2948
|
});
|
|
2855
2949
|
}
|
|
2856
2950
|
handleTurnStartedNotification(parsed) {
|
|
2951
|
+
const subAgentCallId = this.getSubAgentCallIdForThread(parsed.threadId);
|
|
2952
|
+
if (subAgentCallId) {
|
|
2953
|
+
this.emitSubAgentActivityUpdate(subAgentCallId, "running");
|
|
2954
|
+
return;
|
|
2955
|
+
}
|
|
2857
2956
|
this.currentTurnId = parsed.turnId;
|
|
2858
2957
|
this.resetTurnTrackingState();
|
|
2859
2958
|
this.emitEvent({ type: "turn_started", provider: CODEX_PROVIDER });
|
|
2860
2959
|
}
|
|
2861
2960
|
handleTurnCompletedNotification(parsed) {
|
|
2961
|
+
const subAgentCallId = this.getSubAgentCallIdForThread(parsed.threadId);
|
|
2962
|
+
if (subAgentCallId) {
|
|
2963
|
+
let status = "completed";
|
|
2964
|
+
if (parsed.status === "failed") {
|
|
2965
|
+
status = "failed";
|
|
2966
|
+
}
|
|
2967
|
+
else if (parsed.status === "interrupted") {
|
|
2968
|
+
status = "canceled";
|
|
2969
|
+
}
|
|
2970
|
+
this.emitSubAgentActivityUpdate(subAgentCallId, status);
|
|
2971
|
+
return;
|
|
2972
|
+
}
|
|
2862
2973
|
if (parsed.status === "failed") {
|
|
2863
2974
|
this.emitEvent({
|
|
2864
2975
|
type: "turn_failed",
|
|
@@ -2888,8 +2999,11 @@ class CodexAppServerAgentSession {
|
|
|
2888
2999
|
this.emittedItemCompletedIds.clear();
|
|
2889
3000
|
this.emittedExecCommandStartedCallIds.clear();
|
|
2890
3001
|
this.emittedExecCommandCompletedCallIds.clear();
|
|
3002
|
+
this.pendingAgentMessages.clear();
|
|
3003
|
+
this.pendingReasoning.clear();
|
|
2891
3004
|
this.pendingCommandOutputDeltas.clear();
|
|
2892
3005
|
this.pendingFileChangeOutputDeltas.clear();
|
|
3006
|
+
this.pendingAssistantMessageBoundary = false;
|
|
2893
3007
|
this.warnedIncompleteEditToolCallIds.clear();
|
|
2894
3008
|
}
|
|
2895
3009
|
handlePlanUpdatedNotification(parsed) {
|
|
@@ -2902,6 +3016,12 @@ class CodexAppServerAgentSession {
|
|
|
2902
3016
|
});
|
|
2903
3017
|
if (timelineItem) {
|
|
2904
3018
|
this.rememberPlanResult(timelineItem);
|
|
3019
|
+
// In plan mode, the same plan is rendered through the synthetic approval
|
|
3020
|
+
// permission. Keep the remembered text for that card, but do not also
|
|
3021
|
+
// emit a static timeline plan panel.
|
|
3022
|
+
if (this.planModeEnabled) {
|
|
3023
|
+
return;
|
|
3024
|
+
}
|
|
2905
3025
|
this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
|
|
2906
3026
|
}
|
|
2907
3027
|
}
|
|
@@ -3018,26 +3138,43 @@ class CodexAppServerAgentSession {
|
|
|
3018
3138
|
if (!timelineItem) {
|
|
3019
3139
|
return;
|
|
3020
3140
|
}
|
|
3141
|
+
const childSubAgentCallId = this.getSubAgentCallIdForThread(parsed.threadId);
|
|
3142
|
+
if (childSubAgentCallId) {
|
|
3143
|
+
this.handleSubAgentChildItemCompleted(childSubAgentCallId, parsed.item.id, timelineItem);
|
|
3144
|
+
return;
|
|
3145
|
+
}
|
|
3021
3146
|
const normalizedItemType = normalizeCodexThreadItemType(typeof parsed.item.type === "string" ? parsed.item.type : undefined);
|
|
3022
3147
|
const itemId = parsed.item.id;
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
const callId = timelineItem.callId || itemId;
|
|
3026
|
-
if (callId && this.emittedExecCommandCompletedCallIds.has(callId)) {
|
|
3027
|
-
return;
|
|
3028
|
-
}
|
|
3148
|
+
if (this.shouldSkipCompletedThreadItem(timelineItem, normalizedItemType, itemId)) {
|
|
3149
|
+
return;
|
|
3029
3150
|
}
|
|
3030
|
-
if (
|
|
3151
|
+
if (this.consumeStreamedTextCompletion(timelineItem, itemId)) {
|
|
3152
|
+
if (timelineItem.type === "assistant_message") {
|
|
3153
|
+
this.pendingAssistantMessageBoundary = true;
|
|
3154
|
+
}
|
|
3155
|
+
if (itemId) {
|
|
3156
|
+
this.emittedItemCompletedIds.add(itemId);
|
|
3157
|
+
this.emittedItemStartedIds.delete(itemId);
|
|
3158
|
+
}
|
|
3031
3159
|
return;
|
|
3032
3160
|
}
|
|
3033
3161
|
this.applyBufferedDeltaTextToTimelineItem(timelineItem, itemId);
|
|
3034
3162
|
if (timelineItem.type === "tool_call") {
|
|
3163
|
+
this.registerSubAgentToolCall(timelineItem, parsed.item);
|
|
3035
3164
|
if (timelineItem.detail.type === "plan") {
|
|
3036
3165
|
this.rememberPlanResult(timelineItem);
|
|
3166
|
+
// Codex can surface plans both as turn/plan updates and as completed
|
|
3167
|
+
// thread items. In plan mode, approval owns the visible plan card.
|
|
3168
|
+
if (this.planModeEnabled) {
|
|
3169
|
+
return;
|
|
3170
|
+
}
|
|
3037
3171
|
}
|
|
3038
3172
|
this.warnOnIncompleteEditToolCall(timelineItem, "item_completed", parsed.item);
|
|
3039
3173
|
}
|
|
3040
3174
|
this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
|
|
3175
|
+
if (timelineItem.type === "assistant_message") {
|
|
3176
|
+
this.pendingAssistantMessageBoundary = true;
|
|
3177
|
+
}
|
|
3041
3178
|
if (itemId) {
|
|
3042
3179
|
this.emittedItemCompletedIds.add(itemId);
|
|
3043
3180
|
this.emittedItemStartedIds.delete(itemId);
|
|
@@ -3045,6 +3182,39 @@ class CodexAppServerAgentSession {
|
|
|
3045
3182
|
this.pendingFileChangeOutputDeltas.delete(itemId);
|
|
3046
3183
|
}
|
|
3047
3184
|
}
|
|
3185
|
+
consumeStreamedTextCompletion(timelineItem, itemId) {
|
|
3186
|
+
if (!itemId) {
|
|
3187
|
+
return false;
|
|
3188
|
+
}
|
|
3189
|
+
if (timelineItem.type === "assistant_message" && this.pendingAgentMessages.has(itemId)) {
|
|
3190
|
+
const streamedText = this.pendingAgentMessages.get(itemId) ?? "";
|
|
3191
|
+
this.pendingAgentMessages.delete(itemId);
|
|
3192
|
+
this.emitMissingFinalTextSuffix(timelineItem, streamedText);
|
|
3193
|
+
return true;
|
|
3194
|
+
}
|
|
3195
|
+
if (timelineItem.type === "reasoning" && this.pendingReasoning.has(itemId)) {
|
|
3196
|
+
const streamedText = this.pendingReasoning.get(itemId)?.join("") ?? "";
|
|
3197
|
+
this.pendingReasoning.delete(itemId);
|
|
3198
|
+
this.emitMissingFinalTextSuffix(timelineItem, streamedText);
|
|
3199
|
+
return true;
|
|
3200
|
+
}
|
|
3201
|
+
return false;
|
|
3202
|
+
}
|
|
3203
|
+
emitMissingFinalTextSuffix(timelineItem, streamedText) {
|
|
3204
|
+
if (!timelineItem.text.startsWith(streamedText)) {
|
|
3205
|
+
this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
|
|
3206
|
+
return;
|
|
3207
|
+
}
|
|
3208
|
+
const suffix = timelineItem.text.slice(streamedText.length);
|
|
3209
|
+
if (!suffix) {
|
|
3210
|
+
return;
|
|
3211
|
+
}
|
|
3212
|
+
this.emitEvent({
|
|
3213
|
+
type: "timeline",
|
|
3214
|
+
provider: CODEX_PROVIDER,
|
|
3215
|
+
item: { type: timelineItem.type, text: suffix },
|
|
3216
|
+
});
|
|
3217
|
+
}
|
|
3048
3218
|
applyBufferedDeltaTextToTimelineItem(timelineItem, itemId) {
|
|
3049
3219
|
if (!itemId) {
|
|
3050
3220
|
return;
|
|
@@ -3074,6 +3244,14 @@ class CodexAppServerAgentSession {
|
|
|
3074
3244
|
if (!timelineItem || timelineItem.type !== "tool_call") {
|
|
3075
3245
|
return;
|
|
3076
3246
|
}
|
|
3247
|
+
const childSubAgentCallId = this.getSubAgentCallIdForThread(parsed.threadId);
|
|
3248
|
+
if (childSubAgentCallId) {
|
|
3249
|
+
if (parsed.item.id) {
|
|
3250
|
+
this.upsertSubAgentChildItem(childSubAgentCallId, parsed.item.id, timelineItem);
|
|
3251
|
+
}
|
|
3252
|
+
this.emitSubAgentActivityUpdate(childSubAgentCallId, "running");
|
|
3253
|
+
return;
|
|
3254
|
+
}
|
|
3077
3255
|
const normalizedItemType = normalizeCodexThreadItemType(typeof parsed.item.type === "string" ? parsed.item.type : undefined);
|
|
3078
3256
|
const itemId = parsed.item.id;
|
|
3079
3257
|
if (normalizedItemType === "commandExecution") {
|
|
@@ -3086,6 +3264,7 @@ class CodexAppServerAgentSession {
|
|
|
3086
3264
|
return;
|
|
3087
3265
|
}
|
|
3088
3266
|
this.warnOnIncompleteEditToolCall(timelineItem, "item_started", parsed.item);
|
|
3267
|
+
this.registerSubAgentToolCall(timelineItem, parsed.item);
|
|
3089
3268
|
this.emitEvent({ type: "timeline", provider: CODEX_PROVIDER, item: timelineItem });
|
|
3090
3269
|
if (itemId) {
|
|
3091
3270
|
this.emittedItemStartedIds.add(itemId);
|
|
@@ -3167,20 +3346,6 @@ class CodexAppServerAgentSession {
|
|
|
3167
3346
|
this.emittedTerminalInteractionKeys.add(key);
|
|
3168
3347
|
return true;
|
|
3169
3348
|
}
|
|
3170
|
-
collectThreadTurnTimelineItems(items, target) {
|
|
3171
|
-
for (const item of items) {
|
|
3172
|
-
const timelineItem = threadItemToTimeline(item, {
|
|
3173
|
-
cwd: this.config.cwd ?? null,
|
|
3174
|
-
});
|
|
3175
|
-
if (!timelineItem) {
|
|
3176
|
-
continue;
|
|
3177
|
-
}
|
|
3178
|
-
if (timelineItem.type === "tool_call") {
|
|
3179
|
-
this.warnOnIncompleteEditToolCall(timelineItem, "thread_read", item);
|
|
3180
|
-
}
|
|
3181
|
-
target.push(timelineItem);
|
|
3182
|
-
}
|
|
3183
|
-
}
|
|
3184
3349
|
warnOnIncompleteEditToolCall(item, source, payload) {
|
|
3185
3350
|
if (!isEditToolCallWithoutContent(item)) {
|
|
3186
3351
|
return;
|
|
@@ -3368,23 +3533,13 @@ export class CodexAppServerAgentClient {
|
|
|
3368
3533
|
const title = typeof thread.preview === "string" ? thread.preview : null;
|
|
3369
3534
|
let timeline = [];
|
|
3370
3535
|
try {
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
}
|
|
3377
|
-
|
|
3378
|
-
const turns = read.thread?.turns ?? [];
|
|
3379
|
-
const itemsFromThreadRead = [];
|
|
3380
|
-
for (const turn of turns) {
|
|
3381
|
-
for (const item of turn.items ?? []) {
|
|
3382
|
-
const timelineItem = threadItemToTimeline(item, { cwd });
|
|
3383
|
-
if (timelineItem)
|
|
3384
|
-
itemsFromThreadRead.push(timelineItem);
|
|
3385
|
-
}
|
|
3386
|
-
}
|
|
3387
|
-
timeline = rolloutTimeline.length > 0 ? rolloutTimeline : itemsFromThreadRead;
|
|
3536
|
+
timeline = await loadCodexThreadHistoryTimeline({
|
|
3537
|
+
threadId,
|
|
3538
|
+
cwd,
|
|
3539
|
+
requestThread: (threadIdToRead) => {
|
|
3540
|
+
return readCodexThread(client, threadIdToRead);
|
|
3541
|
+
},
|
|
3542
|
+
});
|
|
3388
3543
|
}
|
|
3389
3544
|
catch {
|
|
3390
3545
|
timeline = [];
|