@jingyi0605/codingns 0.1.4 → 0.2.0
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/public/assets/{TerminalPage-4ulgBhv9.js → TerminalPage-BlbQuWi1.js} +1 -1
- package/dist/public/assets/gemini-D4G1NbrE.png +0 -0
- package/dist/public/assets/index-1VIm8lVL.css +1 -0
- package/dist/public/assets/index-Dti93O2S.js +109 -0
- package/dist/public/assets/kimi-BWNNSh7e.png +0 -0
- package/dist/public/index.html +2 -2
- package/dist/server/config/env.d.ts +7 -0
- package/dist/server/config/env.js +150 -1
- package/dist/server/config/env.js.map +1 -1
- package/dist/server/config/opencode-system-probe-helper-process.d.ts +24 -0
- package/dist/server/config/opencode-system-probe-helper-process.js +70 -5
- package/dist/server/config/opencode-system-probe-helper-process.js.map +1 -1
- package/dist/server/modules/butler/butler-action-context-service.d.ts +30 -0
- package/dist/server/modules/butler/butler-action-context-service.js +108 -0
- package/dist/server/modules/butler/butler-action-context-service.js.map +1 -0
- package/dist/server/modules/butler/butler-auth-service.d.ts +17 -0
- package/dist/server/modules/butler/butler-auth-service.js +91 -0
- package/dist/server/modules/butler/butler-auth-service.js.map +1 -0
- package/dist/server/modules/butler/butler-control-action-service.d.ts +65 -0
- package/dist/server/modules/butler/butler-control-action-service.js +296 -0
- package/dist/server/modules/butler/butler-control-action-service.js.map +1 -0
- package/dist/server/modules/butler/butler-control-session-service.d.ts +55 -0
- package/dist/server/modules/butler/butler-control-session-service.js +367 -0
- package/dist/server/modules/butler/butler-control-session-service.js.map +1 -0
- package/dist/server/modules/butler/butler-controller.d.ts +367 -0
- package/dist/server/modules/butler/butler-controller.js +475 -0
- package/dist/server/modules/butler/butler-controller.js.map +1 -0
- package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.d.ts +34 -0
- package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js +77 -0
- package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js.map +1 -0
- package/dist/server/modules/butler/butler-follow-up-scheduler.d.ts +23 -0
- package/dist/server/modules/butler/butler-follow-up-scheduler.js +57 -0
- package/dist/server/modules/butler/butler-follow-up-scheduler.js.map +1 -0
- package/dist/server/modules/butler/butler-follow-up-service.d.ts +86 -0
- package/dist/server/modules/butler/butler-follow-up-service.js +948 -0
- package/dist/server/modules/butler/butler-follow-up-service.js.map +1 -0
- package/dist/server/modules/butler/butler-inbox-service.d.ts +35 -0
- package/dist/server/modules/butler/butler-inbox-service.js +136 -0
- package/dist/server/modules/butler/butler-inbox-service.js.map +1 -0
- package/dist/server/modules/butler/butler-notification-service.d.ts +12 -0
- package/dist/server/modules/butler/butler-notification-service.js +45 -0
- package/dist/server/modules/butler/butler-notification-service.js.map +1 -0
- package/dist/server/modules/butler/butler-profile-service.d.ts +26 -0
- package/dist/server/modules/butler/butler-profile-service.js +529 -0
- package/dist/server/modules/butler/butler-profile-service.js.map +1 -0
- package/dist/server/modules/butler/butler-project-service.d.ts +48 -0
- package/dist/server/modules/butler/butler-project-service.js +253 -0
- package/dist/server/modules/butler/butler-project-service.js.map +1 -0
- package/dist/server/modules/butler/butler-session-service.d.ts +79 -0
- package/dist/server/modules/butler/butler-session-service.js +503 -0
- package/dist/server/modules/butler/butler-session-service.js.map +1 -0
- package/dist/server/modules/butler/butler-session-summary-service.d.ts +55 -0
- package/dist/server/modules/butler/butler-session-summary-service.js +382 -0
- package/dist/server/modules/butler/butler-session-summary-service.js.map +1 -0
- package/dist/server/modules/butler/context-aggregator.d.ts +187 -0
- package/dist/server/modules/butler/context-aggregator.js +807 -0
- package/dist/server/modules/butler/context-aggregator.js.map +1 -0
- package/dist/server/modules/butler/instruction-adapter.d.ts +28 -0
- package/dist/server/modules/butler/instruction-adapter.js +101 -0
- package/dist/server/modules/butler/instruction-adapter.js.map +1 -0
- package/dist/server/modules/butler/patrol-execution-service.d.ts +47 -0
- package/dist/server/modules/butler/patrol-execution-service.js +347 -0
- package/dist/server/modules/butler/patrol-execution-service.js.map +1 -0
- package/dist/server/modules/butler/patrol-plan-service.d.ts +54 -0
- package/dist/server/modules/butler/patrol-plan-service.js +272 -0
- package/dist/server/modules/butler/patrol-plan-service.js.map +1 -0
- package/dist/server/modules/butler/patrol-run-service.d.ts +60 -0
- package/dist/server/modules/butler/patrol-run-service.js +185 -0
- package/dist/server/modules/butler/patrol-run-service.js.map +1 -0
- package/dist/server/modules/butler/patrol-scheduler.d.ts +36 -0
- package/dist/server/modules/butler/patrol-scheduler.js +99 -0
- package/dist/server/modules/butler/patrol-scheduler.js.map +1 -0
- package/dist/server/modules/butler/project-memory-service.d.ts +30 -0
- package/dist/server/modules/butler/project-memory-service.js +103 -0
- package/dist/server/modules/butler/project-memory-service.js.map +1 -0
- package/dist/server/modules/butler/provider-adapter-registry.d.ts +61 -0
- package/dist/server/modules/butler/provider-adapter-registry.js +430 -0
- package/dist/server/modules/butler/provider-adapter-registry.js.map +1 -0
- package/dist/server/modules/butler/session-summary-instruction-adapter.d.ts +28 -0
- package/dist/server/modules/butler/session-summary-instruction-adapter.js +79 -0
- package/dist/server/modules/butler/session-summary-instruction-adapter.js.map +1 -0
- package/dist/server/modules/butler/session-summary-scheduler.d.ts +23 -0
- package/dist/server/modules/butler/session-summary-scheduler.js +57 -0
- package/dist/server/modules/butler/session-summary-scheduler.js.map +1 -0
- package/dist/server/modules/butler/verification-run-service.d.ts +73 -0
- package/dist/server/modules/butler/verification-run-service.js +633 -0
- package/dist/server/modules/butler/verification-run-service.js.map +1 -0
- package/dist/server/modules/file/file-controller.d.ts +12 -1
- package/dist/server/modules/file/file-controller.js +72 -1
- package/dist/server/modules/file/file-controller.js.map +1 -1
- package/dist/server/modules/file/file-preview-link-service.d.ts +22 -0
- package/dist/server/modules/file/file-preview-link-service.js +160 -0
- package/dist/server/modules/file/file-preview-link-service.js.map +1 -0
- package/dist/server/modules/preferences/profile-service.js +8 -2
- package/dist/server/modules/preferences/profile-service.js.map +1 -1
- package/dist/server/modules/sessions/claude-runtime-helper-process.js +1 -1
- package/dist/server/modules/sessions/claude-runtime-helper-process.js.map +1 -1
- package/dist/server/modules/sessions/codex-app-server-helper-client.d.ts +7 -2
- package/dist/server/modules/sessions/codex-app-server-helper-client.js +113 -2
- package/dist/server/modules/sessions/codex-app-server-helper-client.js.map +1 -1
- package/dist/server/modules/sessions/codex-app-server-helper-process.js +106 -1
- package/dist/server/modules/sessions/codex-app-server-helper-process.js.map +1 -1
- package/dist/server/modules/sessions/session-controller.d.ts +24 -1
- package/dist/server/modules/sessions/session-controller.js +34 -3
- package/dist/server/modules/sessions/session-controller.js.map +1 -1
- package/dist/server/modules/sessions/session-history-service.d.ts +47 -2
- package/dist/server/modules/sessions/session-history-service.js +881 -56
- package/dist/server/modules/sessions/session-history-service.js.map +1 -1
- package/dist/server/modules/sessions/session-live-runtime-service.d.ts +30 -2
- package/dist/server/modules/sessions/session-live-runtime-service.js +584 -159
- package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
- package/dist/server/modules/sessions/session-provider-error-mapper.js +94 -0
- package/dist/server/modules/sessions/session-provider-error-mapper.js.map +1 -1
- package/dist/server/modules/workbench/workbench-service.d.ts +7 -1
- package/dist/server/modules/workbench/workbench-service.js +31 -7
- package/dist/server/modules/workbench/workbench-service.js.map +1 -1
- package/dist/server/routes/butler.d.ts +3 -0
- package/dist/server/routes/butler.js +54 -0
- package/dist/server/routes/butler.js.map +1 -0
- package/dist/server/routes/files.js +2 -0
- package/dist/server/routes/files.js.map +1 -1
- package/dist/server/routes/sessions.js +1 -0
- package/dist/server/routes/sessions.js.map +1 -1
- package/dist/server/server/create-server.d.ts +65 -0
- package/dist/server/server/create-server.js +154 -5
- package/dist/server/server/create-server.js.map +1 -1
- package/dist/server/shared/utils/command-availability.d.ts +1 -0
- package/dist/server/shared/utils/command-availability.js +83 -0
- package/dist/server/shared/utils/command-availability.js.map +1 -0
- package/dist/server/storage/repositories/butler-control-event-repository.d.ts +8 -0
- package/dist/server/storage/repositories/butler-control-event-repository.js +78 -0
- package/dist/server/storage/repositories/butler-control-event-repository.js.map +1 -0
- package/dist/server/storage/repositories/butler-control-session-repository.d.ts +11 -0
- package/dist/server/storage/repositories/butler-control-session-repository.js +86 -0
- package/dist/server/storage/repositories/butler-control-session-repository.js.map +1 -0
- package/dist/server/storage/repositories/butler-follow-up-task-repository.d.ts +16 -0
- package/dist/server/storage/repositories/butler-follow-up-task-repository.js +252 -0
- package/dist/server/storage/repositories/butler-follow-up-task-repository.js.map +1 -0
- package/dist/server/storage/repositories/butler-inbox-item-repository.d.ts +15 -0
- package/dist/server/storage/repositories/butler-inbox-item-repository.js +111 -0
- package/dist/server/storage/repositories/butler-inbox-item-repository.js.map +1 -0
- package/dist/server/storage/repositories/butler-notification-archive-repository.d.ts +9 -0
- package/dist/server/storage/repositories/butler-notification-archive-repository.js +48 -0
- package/dist/server/storage/repositories/butler-notification-archive-repository.js.map +1 -0
- package/dist/server/storage/repositories/butler-profile-repository.d.ts +9 -0
- package/dist/server/storage/repositories/butler-profile-repository.js +86 -0
- package/dist/server/storage/repositories/butler-profile-repository.js.map +1 -0
- package/dist/server/storage/repositories/butler-project-repository.d.ts +14 -0
- package/dist/server/storage/repositories/butler-project-repository.js +140 -0
- package/dist/server/storage/repositories/butler-project-repository.js.map +1 -0
- package/dist/server/storage/repositories/butler-session-repository.d.ts +11 -0
- package/dist/server/storage/repositories/butler-session-repository.js +106 -0
- package/dist/server/storage/repositories/butler-session-repository.js.map +1 -0
- package/dist/server/storage/repositories/butler-session-summary-state-repository.d.ts +8 -0
- package/dist/server/storage/repositories/butler-session-summary-state-repository.js +62 -0
- package/dist/server/storage/repositories/butler-session-summary-state-repository.js.map +1 -0
- package/dist/server/storage/repositories/patrol-plan-repository.d.ts +27 -0
- package/dist/server/storage/repositories/patrol-plan-repository.js +119 -0
- package/dist/server/storage/repositories/patrol-plan-repository.js.map +1 -0
- package/dist/server/storage/repositories/patrol-run-repository.d.ts +28 -0
- package/dist/server/storage/repositories/patrol-run-repository.js +121 -0
- package/dist/server/storage/repositories/patrol-run-repository.js.map +1 -0
- package/dist/server/storage/repositories/project-memory-repository.d.ts +15 -0
- package/dist/server/storage/repositories/project-memory-repository.js +150 -0
- package/dist/server/storage/repositories/project-memory-repository.js.map +1 -0
- package/dist/server/storage/repositories/session-checkpoint-repository.d.ts +9 -0
- package/dist/server/storage/repositories/session-checkpoint-repository.js +72 -0
- package/dist/server/storage/repositories/session-checkpoint-repository.js.map +1 -0
- package/dist/server/storage/repositories/session-fork-repository.d.ts +8 -0
- package/dist/server/storage/repositories/session-fork-repository.js +69 -0
- package/dist/server/storage/repositories/session-fork-repository.js.map +1 -0
- package/dist/server/storage/repositories/session-index-repository.js +40 -2
- package/dist/server/storage/repositories/session-index-repository.js.map +1 -1
- package/dist/server/storage/repositories/session-message-origin-repository.d.ts +10 -0
- package/dist/server/storage/repositories/session-message-origin-repository.js +93 -0
- package/dist/server/storage/repositories/session-message-origin-repository.js.map +1 -0
- package/dist/server/storage/repositories/verification-run-repository.d.ts +29 -0
- package/dist/server/storage/repositories/verification-run-repository.js +125 -0
- package/dist/server/storage/repositories/verification-run-repository.js.map +1 -0
- package/dist/server/storage/sqlite/client.js +146 -0
- package/dist/server/storage/sqlite/client.js.map +1 -1
- package/dist/server/storage/sqlite/schema.sql +354 -0
- package/dist/server/types/domain.d.ts +286 -2
- package/dist/server/ws/ws-server.d.ts +2 -1
- package/dist/server/ws/ws-server.js +2 -1
- package/dist/server/ws/ws-server.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/index.d.ts +4 -0
- package/node_modules/@codingns/session-sync-core/dist/index.js +4 -0
- package/node_modules/@codingns/session-sync-core/dist/index.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.d.ts +18 -0
- package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.js +659 -0
- package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/kimi-shared.d.ts +11 -0
- package/node_modules/@codingns/session-sync-core/dist/kimi-shared.js +72 -0
- package/node_modules/@codingns/session-sync-core/dist/kimi-shared.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/patch-builder.d.ts +8 -0
- package/node_modules/@codingns/session-sync-core/dist/patch-builder.js +89 -0
- package/node_modules/@codingns/session-sync-core/dist/patch-builder.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +6 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +228 -7
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +26 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +499 -3
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/gemini.d.ts +41 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js +1175 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/kimi.d.ts +29 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js +578 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +5 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +271 -4
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/utils.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/utils.js +147 -19
- package/node_modules/@codingns/session-sync-core/dist/providers/utils.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.d.ts +2 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js +43 -5
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +12 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +442 -71
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.d.ts +21 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.js +537 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.d.ts +38 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.js +911 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/services.d.ts +2 -1
- package/node_modules/@codingns/session-sync-core/dist/services.js +55 -8
- package/node_modules/@codingns/session-sync-core/dist/services.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.d.ts +6 -0
- package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.js +9 -0
- package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/types.d.ts +27 -0
- package/node_modules/@codingns/session-sync-core/package.json +8 -0
- package/package.json +1 -1
- package/dist/public/assets/index-C5lu52cQ.css +0 -1
- package/dist/public/assets/index-WpdUo_Vs.js +0 -108
|
@@ -2,12 +2,51 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
|
+
import { performance } from "node:perf_hooks";
|
|
5
6
|
import { basename, dirname, join, resolve } from "node:path";
|
|
6
7
|
import { createInterface } from "node:readline";
|
|
7
|
-
import { DatabaseSync } from "node:sqlite";
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
9
|
-
import { appendJsonLine, createRawRef, ensureDirectory, extractTextBlocks, messageIdFromRawRef, nextTimestamp, normalizeWorkspacePath } from "../providers/utils.js";
|
|
9
|
+
import { appendJsonLine, createRawRef, ensureDirectory, extractTextBlocks, messageIdFromRawRef, nextTimestamp, normalizeWorkspacePath, readJsonLines } from "../providers/utils.js";
|
|
10
|
+
import { loadDatabaseSync } from "../sqlite/node-sqlite.js";
|
|
10
11
|
import { createCodexThreadPermissionOptions } from "./codex-permissions.js";
|
|
12
|
+
const CODEX_RUNTIME_DEBUG_ENABLED = /^(1|true|yes)$/i.test(process.env.CODINGNS_PERF_DEBUG?.trim() ?? "");
|
|
13
|
+
function logCodexRuntimeStep(scope, startedAtMs, detail = {}) {
|
|
14
|
+
if (!CODEX_RUNTIME_DEBUG_ENABLED) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const durationMs = Math.round(performance.now() - startedAtMs);
|
|
18
|
+
const suffix = formatCodexRuntimeDebugDetail(detail);
|
|
19
|
+
console.info(`[perf][codex-runtime] ${scope} ${durationMs}ms${suffix ? ` ${suffix}` : ""}`);
|
|
20
|
+
}
|
|
21
|
+
function formatCodexRuntimeDebugDetail(detail) {
|
|
22
|
+
const entries = Object.entries(detail).filter(([, value]) => value !== undefined);
|
|
23
|
+
if (entries.length === 0) {
|
|
24
|
+
return "";
|
|
25
|
+
}
|
|
26
|
+
return entries
|
|
27
|
+
.map(([key, value]) => `${key}=${formatCodexRuntimeDebugValue(value)}`)
|
|
28
|
+
.join(" ");
|
|
29
|
+
}
|
|
30
|
+
function formatCodexRuntimeDebugValue(value) {
|
|
31
|
+
if (value === null) {
|
|
32
|
+
return "null";
|
|
33
|
+
}
|
|
34
|
+
if (typeof value === "string") {
|
|
35
|
+
return JSON.stringify(value);
|
|
36
|
+
}
|
|
37
|
+
if (typeof value === "number") {
|
|
38
|
+
return Number.isFinite(value) ? String(Math.round(value)) : String(value);
|
|
39
|
+
}
|
|
40
|
+
if (typeof value === "boolean") {
|
|
41
|
+
return value ? "true" : "false";
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
return JSON.stringify(value);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return String(value);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
11
50
|
export class CodexRuntimeAdapter {
|
|
12
51
|
options;
|
|
13
52
|
providerId = "codex";
|
|
@@ -16,24 +55,55 @@ export class CodexRuntimeAdapter {
|
|
|
16
55
|
}
|
|
17
56
|
async startSession(request, sink) {
|
|
18
57
|
const launchedAtMs = Date.now();
|
|
58
|
+
const launchPerfStartedAtMs = performance.now();
|
|
19
59
|
const transport = this.options.transportFactory
|
|
20
60
|
? this.options.transportFactory()
|
|
21
61
|
: createCodexAppServerTransport(this.options);
|
|
62
|
+
const initializeStartedAtMs = performance.now();
|
|
22
63
|
await transport.initialize();
|
|
64
|
+
logCodexRuntimeStep("start_session.initialize", initializeStartedAtMs, {
|
|
65
|
+
sessionId: request.sessionId,
|
|
66
|
+
workspacePath: request.workspacePath
|
|
67
|
+
});
|
|
23
68
|
const abortController = new AbortController();
|
|
24
69
|
const eventQueue = createAsyncEventQueue();
|
|
25
|
-
const
|
|
70
|
+
const resumedSyntheticSession = await this.resumeSyntheticThreadFromHistory(transport, request);
|
|
71
|
+
const startedSession = resumedSyntheticSession ??
|
|
72
|
+
await (async () => {
|
|
73
|
+
const startThreadStartedAtMs = performance.now();
|
|
74
|
+
const started = await transport.startThread(request);
|
|
75
|
+
logCodexRuntimeStep("start_session.thread_start", startThreadStartedAtMs, {
|
|
76
|
+
sessionId: request.sessionId,
|
|
77
|
+
providerSessionId: started.providerSessionId
|
|
78
|
+
});
|
|
79
|
+
return started;
|
|
80
|
+
})();
|
|
26
81
|
const providerSessionId = startedSession.providerSessionId;
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
82
|
+
const syntheticRawStoreRef = buildRuntimeRawStoreRef(resolveRuntimeStoreKey(providerSessionId, request.sessionId));
|
|
83
|
+
const rawStoreRef = pickAvailableCodexRawStoreRef(resumedSyntheticSession
|
|
84
|
+
? [resumedSyntheticSession.rawStoreRef]
|
|
85
|
+
: [startedSession.rawStoreRef, request.rawStoreRef], syntheticRawStoreRef);
|
|
86
|
+
logCodexRuntimeStep("start_session.raw_store_ref_ready", launchPerfStartedAtMs, {
|
|
87
|
+
sessionId: request.sessionId,
|
|
88
|
+
providerSessionId,
|
|
89
|
+
synthetic: isSyntheticRawStoreRef(rawStoreRef),
|
|
90
|
+
hasProviderRawStoreRef: Boolean(startedSession.rawStoreRef),
|
|
91
|
+
providerRawStoreRefExists: Boolean(startedSession.rawStoreRef && existsSync(startedSession.rawStoreRef))
|
|
92
|
+
});
|
|
32
93
|
sink.updateSessionBinding({
|
|
33
94
|
providerSessionId,
|
|
34
95
|
rawStoreRef
|
|
35
96
|
});
|
|
97
|
+
let firstNotificationLogged = false;
|
|
36
98
|
transport.setNotificationHandler(async (notification) => {
|
|
99
|
+
if (!firstNotificationLogged) {
|
|
100
|
+
firstNotificationLogged = true;
|
|
101
|
+
logCodexRuntimeStep("start_session.first_notification", launchPerfStartedAtMs, {
|
|
102
|
+
sessionId: request.sessionId,
|
|
103
|
+
providerSessionId,
|
|
104
|
+
method: ensureText(notification.method).trim() || null
|
|
105
|
+
});
|
|
106
|
+
}
|
|
37
107
|
const translated = translateCodexAppServerNotification(notification);
|
|
38
108
|
if (translated.turnId) {
|
|
39
109
|
eventQueue.setTurnId(translated.turnId);
|
|
@@ -65,7 +135,16 @@ export class CodexRuntimeAdapter {
|
|
|
65
135
|
}
|
|
66
136
|
eventQueue.close();
|
|
67
137
|
});
|
|
138
|
+
const startTurnStartedAtMs = performance.now();
|
|
68
139
|
await transport.startTurn(request, providerSessionId);
|
|
140
|
+
logCodexRuntimeStep("start_session.turn_start", startTurnStartedAtMs, {
|
|
141
|
+
sessionId: request.sessionId,
|
|
142
|
+
providerSessionId
|
|
143
|
+
});
|
|
144
|
+
logCodexRuntimeStep("start_session.ready", launchPerfStartedAtMs, {
|
|
145
|
+
sessionId: request.sessionId,
|
|
146
|
+
providerSessionId
|
|
147
|
+
});
|
|
69
148
|
return {
|
|
70
149
|
providerSessionId,
|
|
71
150
|
rawStoreRef,
|
|
@@ -77,11 +156,30 @@ export class CodexRuntimeAdapter {
|
|
|
77
156
|
transport.close();
|
|
78
157
|
},
|
|
79
158
|
isAlive: () => transport.isClosed() === false,
|
|
80
|
-
completed: this.runTurn(null, request, sink, providerSessionId, rawStoreRef, abortController, eventQueue.iterator, [], launchedAtMs).finally(() => {
|
|
159
|
+
completed: this.runTurn(null, request, sink, providerSessionId, rawStoreRef, abortController, eventQueue.iterator, [], launchedAtMs, launchPerfStartedAtMs).finally(() => {
|
|
81
160
|
transport.close();
|
|
82
161
|
})
|
|
83
162
|
};
|
|
84
163
|
}
|
|
164
|
+
async resumeSyntheticThreadFromHistory(transport, request) {
|
|
165
|
+
const history = buildSyntheticResumeHistory(request.rawStoreRef);
|
|
166
|
+
if (history.length === 0) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const resumeStartedAtMs = performance.now();
|
|
170
|
+
const resumed = await transport.resumeThreadFromHistory({
|
|
171
|
+
providerSessionId: null,
|
|
172
|
+
workspacePath: request.workspacePath,
|
|
173
|
+
history,
|
|
174
|
+
model: request.options.model
|
|
175
|
+
});
|
|
176
|
+
logCodexRuntimeStep("start_session.thread_resume_from_history", resumeStartedAtMs, {
|
|
177
|
+
sessionId: request.sessionId,
|
|
178
|
+
providerSessionId: resumed.providerSessionId,
|
|
179
|
+
messageCount: history.length
|
|
180
|
+
});
|
|
181
|
+
return resumed;
|
|
182
|
+
}
|
|
85
183
|
async continueSession(request, sink) {
|
|
86
184
|
const providerSessionId = resolveResumeThreadId(request.providerSessionId, request.rawStoreRef);
|
|
87
185
|
if (!providerSessionId) {
|
|
@@ -90,19 +188,46 @@ export class CodexRuntimeAdapter {
|
|
|
90
188
|
const transport = this.options.transportFactory
|
|
91
189
|
? this.options.transportFactory()
|
|
92
190
|
: createCodexAppServerTransport(this.options);
|
|
191
|
+
const runtimeStartedAtMs = performance.now();
|
|
192
|
+
const initializeStartedAtMs = performance.now();
|
|
93
193
|
await transport.initialize();
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
194
|
+
logCodexRuntimeStep("continue_session.initialize", initializeStartedAtMs, {
|
|
195
|
+
sessionId: request.sessionId,
|
|
196
|
+
providerSessionId
|
|
197
|
+
});
|
|
198
|
+
const syntheticRawStoreRef = buildRuntimeRawStoreRef(providerSessionId);
|
|
199
|
+
const resolvedSessionId = providerSessionId;
|
|
200
|
+
const resumeThreadStartedAtMs = performance.now();
|
|
97
201
|
const resumed = await transport.resumeThread(request, resolvedSessionId);
|
|
98
|
-
|
|
202
|
+
logCodexRuntimeStep("continue_session.thread_resume", resumeThreadStartedAtMs, {
|
|
203
|
+
sessionId: request.sessionId,
|
|
204
|
+
providerSessionId: resolvedSessionId
|
|
205
|
+
});
|
|
206
|
+
const rawStoreRef = pickAvailableCodexRawStoreRef([request.rawStoreRef, resumed.rawStoreRef], syntheticRawStoreRef);
|
|
99
207
|
const abortController = new AbortController();
|
|
100
208
|
const eventQueue = createAsyncEventQueue();
|
|
209
|
+
logCodexRuntimeStep("continue_session.raw_store_ref_ready", runtimeStartedAtMs, {
|
|
210
|
+
sessionId: request.sessionId,
|
|
211
|
+
providerSessionId: resolvedSessionId,
|
|
212
|
+
synthetic: isSyntheticRawStoreRef(rawStoreRef),
|
|
213
|
+
hasResumedRawStoreRef: Boolean(resumed.rawStoreRef),
|
|
214
|
+
hasRequestRawStoreRef: Boolean(request.rawStoreRef),
|
|
215
|
+
resumedRawStoreRefExists: Boolean(resumed.rawStoreRef && existsSync(resumed.rawStoreRef))
|
|
216
|
+
});
|
|
101
217
|
sink.updateSessionBinding({
|
|
102
218
|
providerSessionId: resolvedSessionId,
|
|
103
219
|
rawStoreRef
|
|
104
220
|
});
|
|
221
|
+
let firstNotificationLogged = false;
|
|
105
222
|
transport.setNotificationHandler(async (notification) => {
|
|
223
|
+
if (!firstNotificationLogged) {
|
|
224
|
+
firstNotificationLogged = true;
|
|
225
|
+
logCodexRuntimeStep("continue_session.first_notification", runtimeStartedAtMs, {
|
|
226
|
+
sessionId: request.sessionId,
|
|
227
|
+
providerSessionId: resolvedSessionId,
|
|
228
|
+
method: ensureText(notification.method).trim() || null
|
|
229
|
+
});
|
|
230
|
+
}
|
|
106
231
|
const translated = translateCodexAppServerNotification(notification);
|
|
107
232
|
if (translated.turnId) {
|
|
108
233
|
eventQueue.setTurnId(translated.turnId);
|
|
@@ -134,7 +259,16 @@ export class CodexRuntimeAdapter {
|
|
|
134
259
|
}
|
|
135
260
|
eventQueue.close();
|
|
136
261
|
});
|
|
262
|
+
const startTurnStartedAtMs = performance.now();
|
|
137
263
|
await transport.startTurn(request, resolvedSessionId);
|
|
264
|
+
logCodexRuntimeStep("continue_session.turn_start", startTurnStartedAtMs, {
|
|
265
|
+
sessionId: request.sessionId,
|
|
266
|
+
providerSessionId: resolvedSessionId
|
|
267
|
+
});
|
|
268
|
+
logCodexRuntimeStep("continue_session.ready", runtimeStartedAtMs, {
|
|
269
|
+
sessionId: request.sessionId,
|
|
270
|
+
providerSessionId: resolvedSessionId
|
|
271
|
+
});
|
|
138
272
|
return {
|
|
139
273
|
providerSessionId: resolvedSessionId,
|
|
140
274
|
rawStoreRef,
|
|
@@ -151,7 +285,7 @@ export class CodexRuntimeAdapter {
|
|
|
151
285
|
})
|
|
152
286
|
};
|
|
153
287
|
}
|
|
154
|
-
async runTurn(thread, request, sink, providerSessionId, rawStoreRef, abortController, preparedEvents, bufferedEvents = [], launchedAtMs = Date.now()) {
|
|
288
|
+
async runTurn(thread, request, sink, providerSessionId, rawStoreRef, abortController, preparedEvents, bufferedEvents = [], launchedAtMs = Date.now(), launchPerfStartedAtMs = performance.now()) {
|
|
155
289
|
const context = {
|
|
156
290
|
providerSessionId,
|
|
157
291
|
rawStoreRef,
|
|
@@ -159,10 +293,13 @@ export class CodexRuntimeAdapter {
|
|
|
159
293
|
// 否则前端会把新 assistant/tool 消息排到旧消息前面,表现成用户消息一直挂在底部。
|
|
160
294
|
sequence: Math.max(0, request.sequenceBase ?? 0),
|
|
161
295
|
toolNameByCallId: new Map(),
|
|
296
|
+
stableMessageRefByIdentity: new Map(),
|
|
297
|
+
lastSignatureByIdentity: new Map(),
|
|
162
298
|
sink,
|
|
163
299
|
workspacePath: request.workspacePath,
|
|
164
300
|
firstUserMessage: request.options.content,
|
|
165
|
-
launchedAtMs
|
|
301
|
+
launchedAtMs,
|
|
302
|
+
launchPerfStartedAtMs
|
|
166
303
|
};
|
|
167
304
|
try {
|
|
168
305
|
await this.refreshSessionBindingIfNeeded(context);
|
|
@@ -219,6 +356,13 @@ export class CodexRuntimeAdapter {
|
|
|
219
356
|
if (eventType.length === 0) {
|
|
220
357
|
return;
|
|
221
358
|
}
|
|
359
|
+
if (context.lastSignatureByIdentity.size === 0 && eventType.startsWith("item.")) {
|
|
360
|
+
logCodexRuntimeStep("turn.first_item_event", context.launchPerfStartedAtMs, {
|
|
361
|
+
sessionId: request.sessionId,
|
|
362
|
+
providerSessionId: context.providerSessionId,
|
|
363
|
+
eventType
|
|
364
|
+
});
|
|
365
|
+
}
|
|
222
366
|
if (eventType === "turn.completed") {
|
|
223
367
|
await context.sink.emit({
|
|
224
368
|
type: "complete",
|
|
@@ -265,36 +409,30 @@ export class CodexRuntimeAdapter {
|
|
|
265
409
|
if (itemType.length === 0) {
|
|
266
410
|
return;
|
|
267
411
|
}
|
|
268
|
-
if (itemType === "agent_message" &&
|
|
412
|
+
if (itemType === "agent_message" &&
|
|
413
|
+
(eventType === "item.updated" || eventType === "item.completed")) {
|
|
269
414
|
const content = pickFirstNonEmpty(ensureText(readProp(item, "text")).trim(), extractTextBlocks(readProp(item, "content")).trim());
|
|
270
415
|
if (content.length > 0) {
|
|
271
|
-
await
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}),
|
|
278
|
-
providerSessionId: context.providerSessionId,
|
|
279
|
-
rawStoreRef: context.rawStoreRef,
|
|
280
|
-
timestamp: pickTimestamp(item, event)
|
|
416
|
+
await this.emitStableMessage(context, {
|
|
417
|
+
identity: `assistant:text:${ensureText(readProp(item, "id")).trim() || "default"}`,
|
|
418
|
+
timestamp: pickTimestamp(item, event),
|
|
419
|
+
role: "assistant",
|
|
420
|
+
kind: "text",
|
|
421
|
+
content
|
|
281
422
|
});
|
|
282
423
|
}
|
|
283
424
|
return;
|
|
284
425
|
}
|
|
285
|
-
if (itemType === "reasoning" &&
|
|
426
|
+
if (itemType === "reasoning" &&
|
|
427
|
+
(eventType === "item.updated" || eventType === "item.completed")) {
|
|
286
428
|
const content = pickFirstNonEmpty(ensureText(readProp(item, "text")).trim(), extractTextBlocks(readProp(item, "summary")).trim(), extractTextBlocks(readProp(item, "content")).trim());
|
|
287
429
|
if (content.length > 0) {
|
|
288
|
-
await
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}),
|
|
295
|
-
providerSessionId: context.providerSessionId,
|
|
296
|
-
rawStoreRef: context.rawStoreRef,
|
|
297
|
-
timestamp: pickTimestamp(item, event)
|
|
430
|
+
await this.emitStableMessage(context, {
|
|
431
|
+
identity: `assistant:thinking:${ensureText(readProp(item, "id")).trim() || "default"}`,
|
|
432
|
+
timestamp: pickTimestamp(item, event),
|
|
433
|
+
role: "assistant",
|
|
434
|
+
kind: "thinking",
|
|
435
|
+
content
|
|
298
436
|
});
|
|
299
437
|
}
|
|
300
438
|
return;
|
|
@@ -315,17 +453,37 @@ export class CodexRuntimeAdapter {
|
|
|
315
453
|
status: "running"
|
|
316
454
|
};
|
|
317
455
|
context.toolNameByCallId.set(callId, name);
|
|
318
|
-
await
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
456
|
+
await this.emitStableMessage(context, {
|
|
457
|
+
identity: `tool:call:${callId}`,
|
|
458
|
+
timestamp: pickTimestamp(item, event),
|
|
459
|
+
role: "tool",
|
|
460
|
+
kind: "tool_call",
|
|
461
|
+
content: input,
|
|
462
|
+
toolCall
|
|
463
|
+
});
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (eventType === "item.updated") {
|
|
467
|
+
const output = pickFirstNonEmpty(extractTextBlocks(readProp(item, "result")).trim(), extractTextBlocks(readProp(item, "output")).trim(), extractTextBlocks(readProp(item, "aggregated_output")).trim(), extractTextBlocks(readProp(item, "error")).trim());
|
|
468
|
+
if (output.length === 0) {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
const knownName = context.toolNameByCallId.get(callId) ?? name;
|
|
472
|
+
context.toolNameByCallId.set(callId, knownName);
|
|
473
|
+
await this.emitStableMessage(context, {
|
|
474
|
+
identity: `tool:result:${callId}`,
|
|
475
|
+
timestamp: pickTimestamp(item, event),
|
|
476
|
+
role: "tool",
|
|
477
|
+
kind: "tool_result",
|
|
478
|
+
content: output,
|
|
479
|
+
toolCall: {
|
|
480
|
+
callId,
|
|
481
|
+
name: knownName,
|
|
482
|
+
input: "",
|
|
483
|
+
output,
|
|
484
|
+
error: null,
|
|
485
|
+
status: "running"
|
|
486
|
+
}
|
|
329
487
|
});
|
|
330
488
|
return;
|
|
331
489
|
}
|
|
@@ -341,26 +499,44 @@ export class CodexRuntimeAdapter {
|
|
|
341
499
|
error: success ? null : output,
|
|
342
500
|
status: success ? "completed" : "failed"
|
|
343
501
|
};
|
|
344
|
-
await
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
}),
|
|
352
|
-
providerSessionId: context.providerSessionId,
|
|
353
|
-
rawStoreRef: context.rawStoreRef,
|
|
354
|
-
timestamp: pickTimestamp(item, event)
|
|
502
|
+
await this.emitStableMessage(context, {
|
|
503
|
+
identity: `tool:result:${callId}`,
|
|
504
|
+
timestamp: pickTimestamp(item, event),
|
|
505
|
+
role: "tool",
|
|
506
|
+
kind: "tool_result",
|
|
507
|
+
content: output,
|
|
508
|
+
toolCall
|
|
355
509
|
});
|
|
356
510
|
}
|
|
357
511
|
}
|
|
512
|
+
async emitStableMessage(context, input) {
|
|
513
|
+
const message = this.buildMessage(context, {
|
|
514
|
+
role: input.role,
|
|
515
|
+
kind: input.kind,
|
|
516
|
+
content: input.content,
|
|
517
|
+
toolCall: input.toolCall ?? null,
|
|
518
|
+
stableIdentity: input.identity
|
|
519
|
+
});
|
|
520
|
+
const signature = buildCodexMessageSignature(message);
|
|
521
|
+
if (context.lastSignatureByIdentity.get(input.identity) === signature) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
context.lastSignatureByIdentity.set(input.identity, signature);
|
|
525
|
+
await context.sink.emit({
|
|
526
|
+
type: "message",
|
|
527
|
+
message,
|
|
528
|
+
providerSessionId: context.providerSessionId,
|
|
529
|
+
rawStoreRef: context.rawStoreRef,
|
|
530
|
+
timestamp: input.timestamp,
|
|
531
|
+
rawEventRef: message.rawRef
|
|
532
|
+
});
|
|
533
|
+
}
|
|
358
534
|
async refreshSessionBindingIfNeeded(context) {
|
|
359
535
|
if (!isSyntheticRawStoreRef(context.rawStoreRef)) {
|
|
360
536
|
return;
|
|
361
537
|
}
|
|
362
|
-
const resolved = await this.
|
|
363
|
-
await this.
|
|
538
|
+
const resolved = await this.resolveLaunchedSessionBinding(context.workspacePath, context.firstUserMessage, context.launchedAtMs) ??
|
|
539
|
+
await this.resolveExistingSessionBinding(context.providerSessionId, context.rawStoreRef, context.workspacePath);
|
|
364
540
|
if (!resolved ||
|
|
365
541
|
(resolved.providerSessionId === context.providerSessionId &&
|
|
366
542
|
resolved.rawStoreRef === context.rawStoreRef)) {
|
|
@@ -465,6 +641,7 @@ export class CodexRuntimeAdapter {
|
|
|
465
641
|
if (!dbPath) {
|
|
466
642
|
return null;
|
|
467
643
|
}
|
|
644
|
+
const DatabaseSync = loadDatabaseSync();
|
|
468
645
|
let db = null;
|
|
469
646
|
try {
|
|
470
647
|
db = new DatabaseSync(dbPath, { open: true, readOnly: true });
|
|
@@ -499,11 +676,14 @@ export class CodexRuntimeAdapter {
|
|
|
499
676
|
getCodexHomeDir() {
|
|
500
677
|
return this.options.homeDir?.trim() || process.env.CODINGNS_CODEX_HOME || join(homedir(), ".codex");
|
|
501
678
|
}
|
|
502
|
-
buildMessage(
|
|
503
|
-
context.
|
|
504
|
-
const rawRef =
|
|
679
|
+
buildMessage(context, input) {
|
|
680
|
+
const stableRef = this.resolveStableMessageRef(context, input.stableIdentity ?? null);
|
|
681
|
+
const rawRef = stableRef?.rawRef ??
|
|
682
|
+
createRawRef(this.providerId, context.rawStoreRef, ++context.sequence);
|
|
683
|
+
const sequence = stableRef?.sequence ?? context.sequence;
|
|
684
|
+
const messageId = stableRef?.messageId ?? messageIdFromRawRef(rawRef);
|
|
505
685
|
return {
|
|
506
|
-
messageId
|
|
686
|
+
messageId,
|
|
507
687
|
provider: this.providerId,
|
|
508
688
|
providerSessionId: context.providerSessionId,
|
|
509
689
|
role: input.role,
|
|
@@ -511,10 +691,28 @@ export class CodexRuntimeAdapter {
|
|
|
511
691
|
content: input.content,
|
|
512
692
|
toolCall: input.toolCall ?? null,
|
|
513
693
|
timestamp: nextTimestamp(),
|
|
514
|
-
sequence
|
|
694
|
+
sequence,
|
|
515
695
|
rawRef
|
|
516
696
|
};
|
|
517
697
|
}
|
|
698
|
+
resolveStableMessageRef(context, stableIdentity) {
|
|
699
|
+
if (!stableIdentity) {
|
|
700
|
+
return null;
|
|
701
|
+
}
|
|
702
|
+
const existing = context.stableMessageRefByIdentity.get(stableIdentity);
|
|
703
|
+
if (existing) {
|
|
704
|
+
return existing;
|
|
705
|
+
}
|
|
706
|
+
context.sequence += 1;
|
|
707
|
+
const rawRef = createRawRef(this.providerId, context.rawStoreRef, context.sequence);
|
|
708
|
+
const created = {
|
|
709
|
+
sequence: context.sequence,
|
|
710
|
+
rawRef,
|
|
711
|
+
messageId: messageIdFromRawRef(rawRef)
|
|
712
|
+
};
|
|
713
|
+
context.stableMessageRefByIdentity.set(stableIdentity, created);
|
|
714
|
+
return created;
|
|
715
|
+
}
|
|
518
716
|
async awaitThreadStarted(thread, events, workspacePath, firstUserMessage, launchedAtMs) {
|
|
519
717
|
const bufferedEvents = [];
|
|
520
718
|
while (true) {
|
|
@@ -658,6 +856,7 @@ function createCodexAppServerTransport(options) {
|
|
|
658
856
|
});
|
|
659
857
|
return {
|
|
660
858
|
async initialize() {
|
|
859
|
+
const startedAtMs = performance.now();
|
|
661
860
|
await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("initialize", () => ++requestSequence), {
|
|
662
861
|
method: "initialize",
|
|
663
862
|
params: {
|
|
@@ -673,8 +872,10 @@ function createCodexAppServerTransport(options) {
|
|
|
673
872
|
method: "initialized",
|
|
674
873
|
params: {}
|
|
675
874
|
});
|
|
875
|
+
logCodexRuntimeStep("transport.initialize", startedAtMs);
|
|
676
876
|
},
|
|
677
877
|
async startThread(request) {
|
|
878
|
+
const startedAtMs = performance.now();
|
|
678
879
|
const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("thread-start", () => ++requestSequence), {
|
|
679
880
|
method: "thread/start",
|
|
680
881
|
params: createThreadStartParams(request)
|
|
@@ -685,29 +886,64 @@ function createCodexAppServerTransport(options) {
|
|
|
685
886
|
throw new Error("CODEX_APP_SERVER_THREAD_ID_MISSING");
|
|
686
887
|
}
|
|
687
888
|
activeThreadId = providerSessionId;
|
|
889
|
+
logCodexRuntimeStep("transport.thread_start", startedAtMs, {
|
|
890
|
+
sessionId: request.sessionId,
|
|
891
|
+
providerSessionId
|
|
892
|
+
});
|
|
688
893
|
return {
|
|
689
894
|
providerSessionId,
|
|
690
895
|
rawStoreRef: normalizeText(thread?.path) || null
|
|
691
896
|
};
|
|
692
897
|
},
|
|
693
898
|
async resumeThread(request, providerSessionId) {
|
|
899
|
+
const startedAtMs = performance.now();
|
|
694
900
|
const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("thread-resume", () => ++requestSequence), {
|
|
695
901
|
method: "thread/resume",
|
|
696
902
|
params: createThreadResumeParams(request, providerSessionId)
|
|
697
903
|
});
|
|
698
904
|
const thread = toRecord(result.thread);
|
|
699
905
|
activeThreadId = ensureText(thread?.id).trim() || providerSessionId;
|
|
906
|
+
logCodexRuntimeStep("transport.thread_resume", startedAtMs, {
|
|
907
|
+
sessionId: request.sessionId,
|
|
908
|
+
providerSessionId: activeThreadId
|
|
909
|
+
});
|
|
700
910
|
return {
|
|
701
911
|
providerSessionId: activeThreadId,
|
|
702
912
|
rawStoreRef: normalizeText(thread?.path) || null
|
|
703
913
|
};
|
|
704
914
|
},
|
|
915
|
+
async resumeThreadFromHistory(input) {
|
|
916
|
+
const startedAtMs = performance.now();
|
|
917
|
+
const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("thread-resume-history", () => ++requestSequence), {
|
|
918
|
+
method: "thread/resume",
|
|
919
|
+
params: createThreadResumeWithHistoryParams(input)
|
|
920
|
+
});
|
|
921
|
+
const thread = toRecord(result.thread);
|
|
922
|
+
const providerSessionId = ensureText(thread?.id).trim();
|
|
923
|
+
if (!providerSessionId) {
|
|
924
|
+
throw new Error("CODEX_APP_SERVER_THREAD_ID_MISSING");
|
|
925
|
+
}
|
|
926
|
+
activeThreadId = providerSessionId;
|
|
927
|
+
logCodexRuntimeStep("transport.thread_resume_from_history", startedAtMs, {
|
|
928
|
+
providerSessionId
|
|
929
|
+
});
|
|
930
|
+
return {
|
|
931
|
+
providerSessionId,
|
|
932
|
+
rawStoreRef: normalizeText(thread?.path) || null
|
|
933
|
+
};
|
|
934
|
+
},
|
|
705
935
|
async startTurn(request, providerSessionId) {
|
|
936
|
+
const startedAtMs = performance.now();
|
|
706
937
|
const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("turn-start", () => ++requestSequence), {
|
|
707
938
|
method: "turn/start",
|
|
708
939
|
params: createTurnStartParams(request, providerSessionId)
|
|
709
940
|
});
|
|
710
941
|
activeTurnId = ensureText(readProp(readProp(result, "turn"), "id")).trim() || activeTurnId;
|
|
942
|
+
logCodexRuntimeStep("transport.turn_start", startedAtMs, {
|
|
943
|
+
sessionId: request.sessionId,
|
|
944
|
+
providerSessionId,
|
|
945
|
+
turnId: activeTurnId
|
|
946
|
+
});
|
|
711
947
|
},
|
|
712
948
|
async interruptTurn() {
|
|
713
949
|
if (!activeThreadId || !activeTurnId) {
|
|
@@ -849,7 +1085,27 @@ function translateCodexAppServerNotification(notification) {
|
|
|
849
1085
|
turnId: ensureText(turn?.id).trim() || null
|
|
850
1086
|
};
|
|
851
1087
|
}
|
|
852
|
-
if (method === "
|
|
1088
|
+
if (method === "error") {
|
|
1089
|
+
const error = toRecord(params.error);
|
|
1090
|
+
const detail = buildCodexAppServerErrorDetail(error);
|
|
1091
|
+
if (params.willRetry === true) {
|
|
1092
|
+
return {
|
|
1093
|
+
event: null,
|
|
1094
|
+
terminal: false,
|
|
1095
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
return {
|
|
1099
|
+
event: {
|
|
1100
|
+
type: "turn.failed",
|
|
1101
|
+
timestamp: nextTimestamp(),
|
|
1102
|
+
error: detail
|
|
1103
|
+
},
|
|
1104
|
+
terminal: true,
|
|
1105
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
if (method === "item/started" || method === "item/updated" || method === "item/completed") {
|
|
853
1109
|
const item = translateCodexAppServerItem(toRecord(params.item));
|
|
854
1110
|
if (!item) {
|
|
855
1111
|
return {
|
|
@@ -860,7 +1116,11 @@ function translateCodexAppServerNotification(notification) {
|
|
|
860
1116
|
}
|
|
861
1117
|
return {
|
|
862
1118
|
event: {
|
|
863
|
-
type: method === "item/started"
|
|
1119
|
+
type: method === "item/started"
|
|
1120
|
+
? "item.started"
|
|
1121
|
+
: method === "item/updated"
|
|
1122
|
+
? "item.updated"
|
|
1123
|
+
: "item.completed",
|
|
864
1124
|
item,
|
|
865
1125
|
timestamp: nextTimestamp()
|
|
866
1126
|
},
|
|
@@ -874,6 +1134,31 @@ function translateCodexAppServerNotification(notification) {
|
|
|
874
1134
|
turnId: null
|
|
875
1135
|
};
|
|
876
1136
|
}
|
|
1137
|
+
function buildCodexAppServerErrorDetail(error) {
|
|
1138
|
+
const message = ensureText(error?.message).trim();
|
|
1139
|
+
const additionalDetails = ensureText(error?.additionalDetails).trim();
|
|
1140
|
+
if (message && additionalDetails && !message.includes(additionalDetails)) {
|
|
1141
|
+
return `${message}\n${additionalDetails}`;
|
|
1142
|
+
}
|
|
1143
|
+
return message || additionalDetails || "codex app-server error";
|
|
1144
|
+
}
|
|
1145
|
+
function buildCodexMessageSignature(message) {
|
|
1146
|
+
return JSON.stringify({
|
|
1147
|
+
role: message.role,
|
|
1148
|
+
kind: message.kind,
|
|
1149
|
+
content: message.content,
|
|
1150
|
+
toolCall: message.toolCall
|
|
1151
|
+
? {
|
|
1152
|
+
callId: message.toolCall.callId,
|
|
1153
|
+
name: message.toolCall.name,
|
|
1154
|
+
input: message.toolCall.input,
|
|
1155
|
+
output: message.toolCall.output,
|
|
1156
|
+
error: message.toolCall.error,
|
|
1157
|
+
status: message.toolCall.status
|
|
1158
|
+
}
|
|
1159
|
+
: null
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
877
1162
|
function translateCodexAppServerItem(item) {
|
|
878
1163
|
if (!item) {
|
|
879
1164
|
return null;
|
|
@@ -886,15 +1171,15 @@ function translateCodexAppServerItem(item) {
|
|
|
886
1171
|
return {
|
|
887
1172
|
type: "agent_message",
|
|
888
1173
|
id: item.id,
|
|
889
|
-
text: item.text
|
|
1174
|
+
text: ensureText(item.text).trim()
|
|
890
1175
|
};
|
|
891
1176
|
}
|
|
892
1177
|
if (itemType === "reasoning") {
|
|
893
1178
|
return {
|
|
894
1179
|
type: "reasoning",
|
|
895
1180
|
id: item.id,
|
|
896
|
-
text: Array.isArray(item.content) ? item.content.join("\n") :
|
|
897
|
-
summary: Array.isArray(item.summary) ? item.summary.join("\n") :
|
|
1181
|
+
text: Array.isArray(item.content) ? item.content.join("\n") : ensureText(item.text).trim(),
|
|
1182
|
+
summary: Array.isArray(item.summary) ? item.summary.join("\n") : ensureText(item.summary).trim()
|
|
898
1183
|
};
|
|
899
1184
|
}
|
|
900
1185
|
if (itemType === "commandExecution") {
|
|
@@ -999,6 +1284,20 @@ function createThreadResumeParams(request, providerSessionId) {
|
|
|
999
1284
|
}
|
|
1000
1285
|
return params;
|
|
1001
1286
|
}
|
|
1287
|
+
function createThreadResumeWithHistoryParams(input) {
|
|
1288
|
+
const params = {
|
|
1289
|
+
threadId: input.providerSessionId && input.providerSessionId.trim().length > 0
|
|
1290
|
+
? input.providerSessionId.trim()
|
|
1291
|
+
: "__history_resume__",
|
|
1292
|
+
cwd: input.workspacePath,
|
|
1293
|
+
history: input.history,
|
|
1294
|
+
approvalsReviewer: "user"
|
|
1295
|
+
};
|
|
1296
|
+
if (input.model) {
|
|
1297
|
+
params.model = input.model;
|
|
1298
|
+
}
|
|
1299
|
+
return params;
|
|
1300
|
+
}
|
|
1002
1301
|
function createTurnStartParams(request, providerSessionId) {
|
|
1003
1302
|
const permissionOptions = createCodexThreadPermissionOptions(request.options.permissionMode ?? "default");
|
|
1004
1303
|
const params = {
|
|
@@ -1116,6 +1415,18 @@ function resolveNodeModulesCandidate(currentDirectory, relativeSegments) {
|
|
|
1116
1415
|
function buildRuntimeRawStoreRef(providerSessionId) {
|
|
1117
1416
|
return resolve(process.cwd(), "runtime", "codex", `${providerSessionId}.stream`);
|
|
1118
1417
|
}
|
|
1418
|
+
function pickAvailableCodexRawStoreRef(candidates, fallbackRawStoreRef) {
|
|
1419
|
+
for (const candidate of candidates) {
|
|
1420
|
+
const normalized = candidate?.trim();
|
|
1421
|
+
if (!normalized) {
|
|
1422
|
+
continue;
|
|
1423
|
+
}
|
|
1424
|
+
if (existsSync(normalized)) {
|
|
1425
|
+
return normalized;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
return fallbackRawStoreRef;
|
|
1429
|
+
}
|
|
1119
1430
|
function resolveRuntimeStoreKey(providerSessionId, sessionId) {
|
|
1120
1431
|
return providerSessionId.trim() || sessionId;
|
|
1121
1432
|
}
|
|
@@ -1204,6 +1515,66 @@ function resolveResumeThreadId(providerSessionId, rawStoreRef) {
|
|
|
1204
1515
|
}
|
|
1205
1516
|
return null;
|
|
1206
1517
|
}
|
|
1518
|
+
function buildSyntheticResumeHistory(rawStoreRef) {
|
|
1519
|
+
const filePath = ensureText(rawStoreRef).trim();
|
|
1520
|
+
if (!filePath || !existsSync(filePath)) {
|
|
1521
|
+
return [];
|
|
1522
|
+
}
|
|
1523
|
+
const threadId = readThreadIdFromRawStore(filePath);
|
|
1524
|
+
if (!threadId || looksLikeCodexThreadId(threadId)) {
|
|
1525
|
+
return [];
|
|
1526
|
+
}
|
|
1527
|
+
const history = [];
|
|
1528
|
+
for (const recordEntry of readJsonLines(filePath)) {
|
|
1529
|
+
const record = toRecord(recordEntry.data) ?? {};
|
|
1530
|
+
const recordType = ensureText(record.type).trim();
|
|
1531
|
+
if (recordType === "event_msg") {
|
|
1532
|
+
const payload = toRecord(record.payload) ?? {};
|
|
1533
|
+
const eventType = ensureText(payload.type).trim();
|
|
1534
|
+
const content = ensureText(payload.message).trim();
|
|
1535
|
+
if (content.length === 0) {
|
|
1536
|
+
continue;
|
|
1537
|
+
}
|
|
1538
|
+
if (eventType === "user_message") {
|
|
1539
|
+
history.push(createResumeHistoryMessage("user", content));
|
|
1540
|
+
continue;
|
|
1541
|
+
}
|
|
1542
|
+
if (eventType === "agent_message") {
|
|
1543
|
+
history.push(createResumeHistoryMessage("assistant", content));
|
|
1544
|
+
}
|
|
1545
|
+
continue;
|
|
1546
|
+
}
|
|
1547
|
+
if (recordType !== "response_item") {
|
|
1548
|
+
continue;
|
|
1549
|
+
}
|
|
1550
|
+
const payload = toRecord(record.payload) ?? {};
|
|
1551
|
+
if (ensureText(payload.type).trim() !== "message") {
|
|
1552
|
+
continue;
|
|
1553
|
+
}
|
|
1554
|
+
const role = ensureText(payload.role).trim();
|
|
1555
|
+
if (role !== "user" && role !== "assistant") {
|
|
1556
|
+
continue;
|
|
1557
|
+
}
|
|
1558
|
+
const content = extractTextBlocks(payload.content).trim();
|
|
1559
|
+
if (content.length === 0) {
|
|
1560
|
+
continue;
|
|
1561
|
+
}
|
|
1562
|
+
history.push(createResumeHistoryMessage(role, content));
|
|
1563
|
+
}
|
|
1564
|
+
return history;
|
|
1565
|
+
}
|
|
1566
|
+
function createResumeHistoryMessage(role, content) {
|
|
1567
|
+
return {
|
|
1568
|
+
type: "message",
|
|
1569
|
+
role,
|
|
1570
|
+
content: [
|
|
1571
|
+
{
|
|
1572
|
+
type: role === "user" ? "input_text" : "output_text",
|
|
1573
|
+
text: content
|
|
1574
|
+
}
|
|
1575
|
+
]
|
|
1576
|
+
};
|
|
1577
|
+
}
|
|
1207
1578
|
function readProp(value, key) {
|
|
1208
1579
|
if (!value || typeof value !== "object") {
|
|
1209
1580
|
return null;
|