@jingyi0605/codingns 0.9.7 → 0.9.8
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/{AdaptiveButlerPage-DclGPzEx.js → AdaptiveButlerPage-D-gXre7Y.js} +2 -2
- package/dist/public/assets/{App-CcDXqFl1.css → App-7zrCMhE-.css} +1 -1
- package/dist/public/assets/App-Dl-mcdqy.js +30 -0
- package/dist/public/assets/{BootstrapPage-Bl21SsuW.js → BootstrapPage-B-yMdfpQ.js} +1 -1
- package/dist/public/assets/ConversationPage-DRQ5Sg_d.js +9 -0
- package/dist/public/assets/{DesktopDetachPreviewPage-uaOHVsjV.js → DesktopDetachPreviewPage-D1DMaGcy.js} +1 -1
- package/dist/public/assets/{DesktopModal-BxsogpLf.js → DesktopModal-BnfGW2gk.js} +1 -1
- package/dist/public/assets/DesktopWindowPage-2SWAi0xz.js +2 -0
- package/dist/public/assets/FileContextPanel-fbPuE9dO.js +1 -0
- package/dist/public/assets/GitSidebar-BkmesJJR.js +6 -0
- package/dist/public/assets/{MobileCreateSessionSheet-CqtmfVNo.js → MobileCreateSessionSheet-CEJcDBZJ.js} +1 -1
- package/dist/public/assets/{MobileSheet-C5IVmUsO.js → MobileSheet-rkn_CUOY.js} +1 -1
- package/dist/public/assets/{MobileTopHeaderFrame-EoBm3-X0.js → MobileTopHeaderFrame-CU0wsYSS.js} +1 -1
- package/dist/public/assets/MobileWorkspaceSwitcherHeader-idl8o1OB.js +1 -0
- package/dist/public/assets/{PluginAccessOverview-CrQiQxxZ.js → PluginAccessOverview-BBgM6tb0.js} +1 -1
- package/dist/public/assets/{PluginContainerPage-_2u-9thM.js → PluginContainerPage-D-ly3i3H.js} +1 -1
- package/dist/public/assets/{PluginDetailPage-F9cKjSCp.js → PluginDetailPage-CWAHYyyG.js} +1 -1
- package/dist/public/assets/{PluginsListPage-BOhcua_4.js → PluginsListPage-Cte3vBgR.js} +1 -1
- package/dist/public/assets/{RelayConnectEntryPage-Ck_uZLzj.js → RelayConnectEntryPage-sRJlstx9.js} +1 -1
- package/dist/public/assets/{ServerSettingsModal-ICd82a_x.js → ServerSettingsModal-BBft9KEC.js} +1 -1
- package/dist/public/assets/SessionIndexPage-CN7cEdl9.js +1 -0
- package/dist/public/assets/SettingsPage-BGT-YqG2.js +2 -0
- package/dist/public/assets/TerminalManagerPanel-6-ZJ8vGn.js +1 -0
- package/dist/public/assets/TerminalPage-CUXXQYU2.js +55 -0
- package/dist/public/assets/{TerminalRuntimeFallbackModal-DGPR_CMh.js → TerminalRuntimeFallbackModal-zc3qqMKJ.js} +1 -1
- package/dist/public/assets/ToolFilesPage-QzsZyr0F.js +1 -0
- package/dist/public/assets/ToolGitPage-CXg4ncuT.js +1 -0
- package/dist/public/assets/ToolProcessesPage-BPsOsg4w.js +1 -0
- package/dist/public/assets/ToolsHomePage-D1n4FU1s.js +1 -0
- package/dist/public/assets/WorkbenchLandingPage-BaU_dXls.js +1 -0
- package/dist/public/assets/WorkbenchLayout-DViAJhHz.js +1027 -0
- package/dist/public/assets/{WorkbenchModal-CsZeLArg.js → WorkbenchModal-DWsNm2B2.js} +1 -1
- package/dist/public/assets/WorkbenchShellRoute-BGfRqBUa.js +1 -0
- package/dist/public/assets/WorkbenchShellRoute-f2jWjHWu.css +1 -0
- package/dist/public/assets/WorkspaceDebugDetailPage-BX0zVSsI.js +1 -0
- package/dist/public/assets/WorkspaceDetailPage-Dx6JX4jx.js +1 -0
- package/dist/public/assets/WorkspaceHomePage-DQVJ042Z.js +1 -0
- package/dist/public/assets/{client-runtime-manager-BgGugw8T.js → client-runtime-manager-D9VbgJZ_.js} +1 -1
- package/dist/public/assets/host-alias-0TfFnYxR.js +1 -0
- package/dist/public/assets/index-DREvg1Yu.css +1 -0
- package/dist/public/assets/index-FOhyOpGY.js +50 -0
- package/dist/public/assets/{login-direct-candidate-resolver-ty2uOY5y.js → login-direct-candidate-resolver-17wEvjhh.js} +1 -1
- package/dist/public/assets/peer-host-config-sync-vYkmqzNz.js +1 -0
- package/dist/public/assets/{plugin-permission-copy-iK3faI3n.js → plugin-permission-copy-apDn8EWG.js} +1 -1
- package/dist/public/assets/{plugins-api-CmV7aDGA.js → plugins-api-CnZYRKoS.js} +1 -1
- package/dist/public/assets/{preferences-service-BoSmT_ny.js → preferences-service-PZlLLAWH.js} +1 -1
- package/dist/public/assets/relay-entry-DhHwflXl.js +1 -0
- package/dist/public/assets/terminal-runtime-meta-2zvacxvM.js +1 -0
- package/dist/public/assets/{useRegisteredDebugTemplates-B_vXUtSe.js → useRegisteredDebugTemplates-CJ-o4tFl.js} +1 -1
- package/dist/public/assets/workbench-navigation-aqJ1ay4M.js +1 -0
- package/dist/public/index.html +2 -2
- package/dist/server/middlewares/auth-guard.js +1 -0
- package/dist/server/middlewares/auth-guard.js.map +1 -1
- package/dist/server/modules/peer-host/host-api-proxy-service.d.ts +9 -0
- package/dist/server/modules/peer-host/host-api-proxy-service.js +174 -0
- package/dist/server/modules/peer-host/host-api-proxy-service.js.map +1 -0
- package/dist/server/modules/peer-host/host-handshake-controller.d.ts +7 -0
- package/dist/server/modules/peer-host/host-handshake-controller.js +10 -0
- package/dist/server/modules/peer-host/host-handshake-controller.js.map +1 -0
- package/dist/server/modules/peer-host/host-handshake.d.ts +15 -0
- package/dist/server/modules/peer-host/host-handshake.js +20 -0
- package/dist/server/modules/peer-host/host-handshake.js.map +1 -0
- package/dist/server/modules/peer-host/host-ws-proxy-service.d.ts +14 -0
- package/dist/server/modules/peer-host/host-ws-proxy-service.js +256 -0
- package/dist/server/modules/peer-host/host-ws-proxy-service.js.map +1 -0
- package/dist/server/modules/peer-host/peer-host-controller.d.ts +55 -0
- package/dist/server/modules/peer-host/peer-host-controller.js +62 -0
- package/dist/server/modules/peer-host/peer-host-controller.js.map +1 -0
- package/dist/server/modules/peer-host/peer-host-service.d.ts +77 -0
- package/dist/server/modules/peer-host/peer-host-service.js +529 -0
- package/dist/server/modules/peer-host/peer-host-service.js.map +1 -0
- package/dist/server/modules/sessions/codex-session-title-generator.js +18 -5
- package/dist/server/modules/sessions/codex-session-title-generator.js.map +1 -1
- package/dist/server/modules/sessions/session-history-service.d.ts +12 -1
- package/dist/server/modules/sessions/session-history-service.js +51 -38
- package/dist/server/modules/sessions/session-history-service.js.map +1 -1
- package/dist/server/modules/sessions/session-live-runtime-service.d.ts +6 -0
- package/dist/server/modules/sessions/session-live-runtime-service.js +181 -80
- package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
- package/dist/server/modules/sessions/session-title-utils.d.ts +3 -0
- package/dist/server/modules/sessions/session-title-utils.js +25 -0
- package/dist/server/modules/sessions/session-title-utils.js.map +1 -0
- package/dist/server/modules/sessions/workspace-office-mcp-config.d.ts +2 -1
- package/dist/server/modules/sessions/workspace-office-mcp-config.js +44 -3
- package/dist/server/modules/sessions/workspace-office-mcp-config.js.map +1 -1
- package/dist/server/modules/tasks/task-manager.d.ts +2 -1
- package/dist/server/modules/tasks/task-manager.js +3 -0
- package/dist/server/modules/tasks/task-manager.js.map +1 -1
- package/dist/server/modules/tasks/task-scheduler.d.ts +2 -1
- package/dist/server/modules/tasks/task-scheduler.js +21 -0
- package/dist/server/modules/tasks/task-scheduler.js.map +1 -1
- package/dist/server/modules/tasks/task-types.d.ts +5 -0
- package/dist/server/modules/tasks/task-types.js.map +1 -1
- package/dist/server/modules/workbench/workbench-controller.js +3 -2
- package/dist/server/modules/workbench/workbench-controller.js.map +1 -1
- package/dist/server/modules/workspace/affairs-library-service.d.ts +1 -0
- package/dist/server/modules/workspace/affairs-library-service.js +80 -0
- package/dist/server/modules/workspace/affairs-library-service.js.map +1 -1
- package/dist/server/routes/peer-hosts.d.ts +3 -0
- package/dist/server/routes/peer-hosts.js +18 -0
- package/dist/server/routes/peer-hosts.js.map +1 -0
- package/dist/server/routes/public.d.ts +2 -1
- package/dist/server/routes/public.js +2 -1
- package/dist/server/routes/public.js.map +1 -1
- package/dist/server/server/create-server.d.ts +4 -0
- package/dist/server/server/create-server.js +30 -2
- package/dist/server/server/create-server.js.map +1 -1
- package/dist/server/shared/http/error-handler.js +12 -0
- package/dist/server/shared/http/error-handler.js.map +1 -1
- package/dist/server/storage/repositories/peer-host-repository.d.ts +44 -0
- package/dist/server/storage/repositories/peer-host-repository.js +271 -0
- package/dist/server/storage/repositories/peer-host-repository.js.map +1 -0
- package/dist/server/storage/sqlite/client.js +81 -0
- package/dist/server/storage/sqlite/client.js.map +1 -1
- package/dist/server/storage/sqlite/schema.sql +64 -0
- package/dist/server/types/domain.d.ts +43 -0
- package/dist/server/ws/workbench-ws-hub.js +5 -14
- package/dist/server/ws/workbench-ws-hub.js.map +1 -1
- package/dist/server/ws/ws-server.d.ts +2 -1
- package/dist/server/ws/ws-server.js +5 -1
- package/dist/server/ws/ws-server.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +29 -5
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js +8 -1
- 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 +3 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +144 -27
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
- package/package.json +1 -1
- package/dist/public/assets/App-BxX5mm9o.js +0 -30
- package/dist/public/assets/ConversationPage-CmiVCV0q.js +0 -9
- package/dist/public/assets/DesktopWindowPage-Bubfw1nC.js +0 -2
- package/dist/public/assets/FileContextPanel-DrYWcTkp.js +0 -1
- package/dist/public/assets/GitSidebar-CQsfJqun.js +0 -6
- package/dist/public/assets/MobileWorkspaceSwitcherHeader-BC8MMQs_.js +0 -1
- package/dist/public/assets/SessionIndexPage-Cox6P6dw.js +0 -1
- package/dist/public/assets/SettingsPage-BI5cM3j5.js +0 -2
- package/dist/public/assets/TerminalManagerPanel-DiVhBQhf.js +0 -1
- package/dist/public/assets/TerminalPage-DUMUO7Ng.js +0 -55
- package/dist/public/assets/ToolFilesPage-m88CAp-r.js +0 -1
- package/dist/public/assets/ToolGitPage-DCYpfTsb.js +0 -1
- package/dist/public/assets/ToolProcessesPage-Bk5ulsyq.js +0 -1
- package/dist/public/assets/ToolsHomePage-BrTwfjI7.js +0 -1
- package/dist/public/assets/WorkbenchLandingPage-q4AAmdMV.js +0 -1
- package/dist/public/assets/WorkbenchLayout-DD8b-m2G.js +0 -1027
- package/dist/public/assets/WorkbenchShellRoute-BaiW_vfb.js +0 -1
- package/dist/public/assets/WorkbenchShellRoute-CxKYZ6uF.css +0 -1
- package/dist/public/assets/WorkspaceDebugDetailPage-BcUUDEyw.js +0 -1
- package/dist/public/assets/WorkspaceDetailPage-zEZ1VARA.js +0 -1
- package/dist/public/assets/WorkspaceHomePage-CR0rqS4e.js +0 -1
- package/dist/public/assets/index-CFyk1rgJ.js +0 -50
- package/dist/public/assets/index-CrU73EIV.css +0 -1
- package/dist/public/assets/relay-entry-C8k5qsl5.js +0 -1
- package/dist/public/assets/terminal-runtime-meta-okQIDzfA.js +0 -1
- package/dist/public/assets/workbench-navigation-DoDaQR4z.js +0 -1
|
@@ -13,9 +13,9 @@ import { loadDatabaseSync } from "../sqlite/node-sqlite.js";
|
|
|
13
13
|
import { createCodexThreadPermissionOptions } from "./codex-permissions.js";
|
|
14
14
|
const CODEX_RUNTIME_DEBUG_ENABLED = /^(1|true|yes)$/i.test(process.env.CODINGNS_PERF_DEBUG?.trim() ?? "");
|
|
15
15
|
const CODEX_APP_SERVER_REQUEST_TIMEOUT_MS = 20_000;
|
|
16
|
-
const CODEX_APP_SERVER_SPAWN_AGENT_GRACE_MS = 6 * 60 * 60 * 1000;
|
|
16
|
+
const CODEX_APP_SERVER_SPAWN_AGENT_GRACE_MS = normalizePositiveInteger(process.env.CODINGNS_CODEX_SPAWN_AGENT_GRACE_MS, 6 * 60 * 60 * 1000);
|
|
17
17
|
const CODEX_SPAWN_AGENT_RAW_SCAN_BYTES = 2 * 1024 * 1024;
|
|
18
|
-
const CODEX_SPAWN_AGENT_POLL_INTERVAL_MS = 2_000;
|
|
18
|
+
const CODEX_SPAWN_AGENT_POLL_INTERVAL_MS = normalizePositiveInteger(process.env.CODINGNS_CODEX_SPAWN_AGENT_POLL_INTERVAL_MS, 2_000);
|
|
19
19
|
function logCodexRuntimeStep(scope, startedAtMs, detail = {}) {
|
|
20
20
|
if (!CODEX_RUNTIME_DEBUG_ENABLED) {
|
|
21
21
|
return;
|
|
@@ -24,6 +24,10 @@ function logCodexRuntimeStep(scope, startedAtMs, detail = {}) {
|
|
|
24
24
|
const suffix = formatCodexRuntimeDebugDetail(detail);
|
|
25
25
|
console.info(`[perf][codex-runtime] ${scope} ${durationMs}ms${suffix ? ` ${suffix}` : ""}`);
|
|
26
26
|
}
|
|
27
|
+
function normalizePositiveInteger(value, fallback) {
|
|
28
|
+
const parsed = Number(value);
|
|
29
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
|
|
30
|
+
}
|
|
27
31
|
function closeCodexTransportAfterTurn(transport, lifecycle, rawStoreRef) {
|
|
28
32
|
if (!shouldKeepCodexTransportAliveAfterTurn(lifecycle, rawStoreRef)) {
|
|
29
33
|
transport.close();
|
|
@@ -40,6 +44,15 @@ function closeCodexTransportAfterTurn(transport, lifecycle, rawStoreRef) {
|
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
function shouldKeepCodexTransportAliveAfterTurn(lifecycle, rawStoreRef) {
|
|
47
|
+
if (lifecycle.parentTurnStopped) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
if (lifecycle.spawnedAgentsSettledAfterTurn) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
if (lifecycle.spawnedAgentIds.size > 0) {
|
|
54
|
+
return lifecycle.closedSpawnedAgentIds.size < lifecycle.spawnedAgentIds.size;
|
|
55
|
+
}
|
|
43
56
|
return lifecycle.keepTransportAliveAfterTurn || codexRawStoreContainsSpawnAgentCall(rawStoreRef);
|
|
44
57
|
}
|
|
45
58
|
function codexRawStoreContainsSpawnAgentCall(rawStoreRef) {
|
|
@@ -86,21 +99,26 @@ function extractCodexSpawnedAgentIdsFromRawStore(rawStoreRef) {
|
|
|
86
99
|
}
|
|
87
100
|
if (isCodexSpawnAgentItem(payload)) {
|
|
88
101
|
const callId = ensureText(readProp(payload, "call_id")).trim();
|
|
102
|
+
const agentId = extractCodexAgentIdFromToolOutput(readProp(payload, "output"));
|
|
89
103
|
if (callId) {
|
|
90
104
|
spawnCallIds.add(callId);
|
|
91
105
|
}
|
|
106
|
+
if (agentId) {
|
|
107
|
+
agentIds.add(agentId);
|
|
108
|
+
}
|
|
92
109
|
continue;
|
|
93
110
|
}
|
|
94
111
|
if (ensureText(readProp(payload, "type")).trim() !== "function_call_output") {
|
|
95
112
|
continue;
|
|
96
113
|
}
|
|
97
114
|
const callId = ensureText(readProp(payload, "call_id")).trim();
|
|
98
|
-
|
|
115
|
+
const outputBelongsToSpawnAgent = ensureText(readProp(payload, "name")).trim() === "spawn_agent"
|
|
116
|
+
|| ensureText(readProp(payload, "tool")).trim() === "spawn_agent";
|
|
117
|
+
if ((!callId || !spawnCallIds.has(callId)) && !outputBelongsToSpawnAgent) {
|
|
99
118
|
continue;
|
|
100
119
|
}
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
if (looksLikeCodexThreadId(agentId)) {
|
|
120
|
+
const agentId = extractCodexAgentIdFromToolOutput(readProp(payload, "output"));
|
|
121
|
+
if (agentId) {
|
|
104
122
|
agentIds.add(agentId);
|
|
105
123
|
}
|
|
106
124
|
}
|
|
@@ -110,6 +128,28 @@ function extractCodexSpawnedAgentIdsFromRawStore(rawStoreRef) {
|
|
|
110
128
|
}
|
|
111
129
|
return [...agentIds];
|
|
112
130
|
}
|
|
131
|
+
function extractCodexSpawnedAgentIdsFromEvents(events) {
|
|
132
|
+
const agentIds = new Set();
|
|
133
|
+
for (const event of events) {
|
|
134
|
+
const item = toRecord(readProp(event, "item")) ?? event;
|
|
135
|
+
if (!isCodexSpawnAgentItem(item)) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const agentId = extractCodexAgentIdFromToolOutput(readProp(item, "output"));
|
|
139
|
+
if (agentId) {
|
|
140
|
+
agentIds.add(agentId);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return [...agentIds];
|
|
144
|
+
}
|
|
145
|
+
function extractCodexAgentIdFromToolOutput(output) {
|
|
146
|
+
const parsedOutput = typeof output === "string"
|
|
147
|
+
? parseStructuredJson(output)
|
|
148
|
+
: toRecord(output);
|
|
149
|
+
const agentId = ensureText(readProp(parsedOutput, "agent_id")).trim()
|
|
150
|
+
|| ensureText(readProp(parsedOutput, "agentId")).trim();
|
|
151
|
+
return looksLikeCodexThreadId(agentId) ? agentId : null;
|
|
152
|
+
}
|
|
113
153
|
function isCodexRawStoreTerminal(rawStoreRef) {
|
|
114
154
|
const text = readCodexRawStoreTail(rawStoreRef);
|
|
115
155
|
if (!text) {
|
|
@@ -177,10 +217,10 @@ function isCodexSpawnAgentEvent(event) {
|
|
|
177
217
|
return isCodexSpawnAgentItem(toRecord(readProp(eventRecord, "item")) ?? eventRecord);
|
|
178
218
|
}
|
|
179
219
|
function markCodexSpawnAgentLifecycleFromEvents(lifecycle, events) {
|
|
180
|
-
|
|
181
|
-
|
|
220
|
+
for (const agentId of extractCodexSpawnedAgentIdsFromEvents(events)) {
|
|
221
|
+
lifecycle.spawnedAgentIds.add(agentId);
|
|
182
222
|
}
|
|
183
|
-
if (events.some((event) => isCodexSpawnAgentEvent(event))) {
|
|
223
|
+
if (!lifecycle.keepTransportAliveAfterTurn && events.some((event) => isCodexSpawnAgentEvent(event))) {
|
|
184
224
|
lifecycle.keepTransportAliveAfterTurn = true;
|
|
185
225
|
}
|
|
186
226
|
}
|
|
@@ -255,7 +295,12 @@ export class CodexRuntimeAdapter {
|
|
|
255
295
|
const abortController = new AbortController();
|
|
256
296
|
const eventQueue = createAsyncEventQueue();
|
|
257
297
|
const lifecycle = {
|
|
258
|
-
keepTransportAliveAfterTurn: false
|
|
298
|
+
keepTransportAliveAfterTurn: false,
|
|
299
|
+
spawnedAgentsSettledAfterTurn: false,
|
|
300
|
+
parentTurnStopped: false,
|
|
301
|
+
spawnedAgentIds: new Set(),
|
|
302
|
+
pendingComplete: null,
|
|
303
|
+
closedSpawnedAgentIds: new Set()
|
|
259
304
|
};
|
|
260
305
|
const translateNotification = createCodexAppServerNotificationTranslator();
|
|
261
306
|
const forwardTranslatedNotification = createCodexTranslatedNotificationForwarder(eventQueue);
|
|
@@ -312,6 +357,7 @@ export class CodexRuntimeAdapter {
|
|
|
312
357
|
});
|
|
313
358
|
transport.setOnClose((error) => {
|
|
314
359
|
if (error) {
|
|
360
|
+
lifecycle.parentTurnStopped = true;
|
|
315
361
|
eventQueue.push({
|
|
316
362
|
type: "turn.failed",
|
|
317
363
|
timestamp: nextTimestamp(),
|
|
@@ -350,7 +396,7 @@ export class CodexRuntimeAdapter {
|
|
|
350
396
|
transport.close();
|
|
351
397
|
},
|
|
352
398
|
isAlive: () => transport.isClosed() === false,
|
|
353
|
-
completed: this.runTurn(null, request, sink, providerSessionId, rawStoreRef, abortController, eventQueue.iterator, [], launchedAtMs, launchPerfStartedAtMs, lifecycle).finally(() => {
|
|
399
|
+
completed: this.runTurn(null, request, sink, providerSessionId, rawStoreRef, abortController, eventQueue.iterator, [], launchedAtMs, launchPerfStartedAtMs, lifecycle, transport).finally(() => {
|
|
354
400
|
closeCodexTransportAfterTurn(transport, lifecycle, rawStoreRef);
|
|
355
401
|
})
|
|
356
402
|
};
|
|
@@ -446,7 +492,12 @@ export class CodexRuntimeAdapter {
|
|
|
446
492
|
const abortController = new AbortController();
|
|
447
493
|
const eventQueue = createAsyncEventQueue();
|
|
448
494
|
const lifecycle = {
|
|
449
|
-
keepTransportAliveAfterTurn: false
|
|
495
|
+
keepTransportAliveAfterTurn: false,
|
|
496
|
+
spawnedAgentsSettledAfterTurn: false,
|
|
497
|
+
parentTurnStopped: false,
|
|
498
|
+
spawnedAgentIds: new Set(),
|
|
499
|
+
pendingComplete: null,
|
|
500
|
+
closedSpawnedAgentIds: new Set()
|
|
450
501
|
};
|
|
451
502
|
const translateNotification = createCodexAppServerNotificationTranslator();
|
|
452
503
|
const forwardTranslatedNotification = createCodexTranslatedNotificationForwarder(eventQueue);
|
|
@@ -488,6 +539,7 @@ export class CodexRuntimeAdapter {
|
|
|
488
539
|
});
|
|
489
540
|
transport.setOnClose((error) => {
|
|
490
541
|
if (error) {
|
|
542
|
+
lifecycle.parentTurnStopped = true;
|
|
491
543
|
eventQueue.push({
|
|
492
544
|
type: "turn.failed",
|
|
493
545
|
timestamp: nextTimestamp(),
|
|
@@ -526,7 +578,7 @@ export class CodexRuntimeAdapter {
|
|
|
526
578
|
transport.close();
|
|
527
579
|
},
|
|
528
580
|
isAlive: () => transport.isClosed() === false,
|
|
529
|
-
completed: this.runTurn(null, request, sink, resolvedSessionId, rawStoreRef, abortController, eventQueue.iterator, [], Date.now(), performance.now(), lifecycle).finally(() => {
|
|
581
|
+
completed: this.runTurn(null, request, sink, resolvedSessionId, rawStoreRef, abortController, eventQueue.iterator, [], Date.now(), performance.now(), lifecycle, transport).finally(() => {
|
|
530
582
|
closeCodexTransportAfterTurn(transport, lifecycle, rawStoreRef);
|
|
531
583
|
})
|
|
532
584
|
};
|
|
@@ -572,8 +624,13 @@ export class CodexRuntimeAdapter {
|
|
|
572
624
|
return fallbackMatch;
|
|
573
625
|
}
|
|
574
626
|
async runTurn(thread, request, sink, providerSessionId, rawStoreRef, abortController, preparedEvents, bufferedEvents = [], launchedAtMs = Date.now(), launchPerfStartedAtMs = performance.now(), lifecycle = {
|
|
575
|
-
keepTransportAliveAfterTurn: false
|
|
576
|
-
|
|
627
|
+
keepTransportAliveAfterTurn: false,
|
|
628
|
+
spawnedAgentsSettledAfterTurn: false,
|
|
629
|
+
parentTurnStopped: false,
|
|
630
|
+
spawnedAgentIds: new Set(),
|
|
631
|
+
pendingComplete: null,
|
|
632
|
+
closedSpawnedAgentIds: new Set()
|
|
633
|
+
}, transport = null) {
|
|
577
634
|
const context = {
|
|
578
635
|
providerSessionId,
|
|
579
636
|
rawStoreRef,
|
|
@@ -581,6 +638,7 @@ export class CodexRuntimeAdapter {
|
|
|
581
638
|
// 否则前端会把新 assistant/tool 消息排到旧消息前面,表现成用户消息一直挂在底部。
|
|
582
639
|
sequence: Math.max(0, request.sequenceBase ?? 0),
|
|
583
640
|
lifecycle,
|
|
641
|
+
transport,
|
|
584
642
|
toolNameByCallId: new Map(),
|
|
585
643
|
stableMessageRefByIdentity: new Map(),
|
|
586
644
|
lastSignatureByIdentity: new Map(),
|
|
@@ -601,7 +659,7 @@ export class CodexRuntimeAdapter {
|
|
|
601
659
|
for (const event of bufferedEvents) {
|
|
602
660
|
await this.refreshSessionBindingIfNeeded(context);
|
|
603
661
|
persistSyntheticEventIfNeeded(context.rawStoreRef, context.providerSessionId, event);
|
|
604
|
-
await this.handleEvent(event, request, context, abortController.signal
|
|
662
|
+
await this.handleEvent(event, request, context, abortController.signal);
|
|
605
663
|
}
|
|
606
664
|
const events = preparedEvents ??
|
|
607
665
|
(await thread.runStreamed(createCodexInput(request), {
|
|
@@ -610,12 +668,16 @@ export class CodexRuntimeAdapter {
|
|
|
610
668
|
while (true) {
|
|
611
669
|
const next = await events.next();
|
|
612
670
|
if (next.done) {
|
|
671
|
+
if (context.lifecycle.parentTurnStopped) {
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
613
674
|
await this.waitForSpawnedCodexAgentsIfNeeded(context, abortController.signal);
|
|
675
|
+
await this.emitPendingCompleteIfReady(context);
|
|
614
676
|
return;
|
|
615
677
|
}
|
|
616
678
|
await this.refreshSessionBindingIfNeeded(context);
|
|
617
679
|
persistSyntheticEventIfNeeded(context.rawStoreRef, context.providerSessionId, next.value);
|
|
618
|
-
await this.handleEvent(next.value, request, context, abortController.signal
|
|
680
|
+
await this.handleEvent(next.value, request, context, abortController.signal);
|
|
619
681
|
}
|
|
620
682
|
}
|
|
621
683
|
catch (error) {
|
|
@@ -643,31 +705,76 @@ export class CodexRuntimeAdapter {
|
|
|
643
705
|
});
|
|
644
706
|
}
|
|
645
707
|
}
|
|
708
|
+
async emitPendingCompleteIfReady(context) {
|
|
709
|
+
const pendingComplete = context.lifecycle.pendingComplete;
|
|
710
|
+
if (!pendingComplete || context.lifecycle.parentTurnStopped) {
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
context.lifecycle.pendingComplete = null;
|
|
714
|
+
await context.sink.emit({
|
|
715
|
+
type: "complete",
|
|
716
|
+
status: "completed",
|
|
717
|
+
providerSessionId: context.providerSessionId,
|
|
718
|
+
rawStoreRef: context.rawStoreRef,
|
|
719
|
+
detail: pendingComplete.detail,
|
|
720
|
+
timestamp: pendingComplete.timestamp
|
|
721
|
+
});
|
|
722
|
+
}
|
|
646
723
|
async waitForSpawnedCodexAgentsIfNeeded(context, signal) {
|
|
647
724
|
if (!shouldKeepCodexTransportAliveAfterTurn(context.lifecycle, context.rawStoreRef)) {
|
|
648
725
|
return;
|
|
649
726
|
}
|
|
650
|
-
const agentIds =
|
|
727
|
+
const agentIds = Array.from(new Set([
|
|
728
|
+
...context.lifecycle.spawnedAgentIds,
|
|
729
|
+
...extractCodexSpawnedAgentIdsFromRawStore(context.rawStoreRef)
|
|
730
|
+
]));
|
|
651
731
|
if (agentIds.length === 0) {
|
|
652
732
|
return;
|
|
653
733
|
}
|
|
654
734
|
const deadline = Date.now() + CODEX_APP_SERVER_SPAWN_AGENT_GRACE_MS;
|
|
655
735
|
const remainingAgentIds = new Set(agentIds);
|
|
656
|
-
while (remainingAgentIds.size > 0
|
|
736
|
+
while (remainingAgentIds.size > 0
|
|
737
|
+
&& Date.now() < deadline
|
|
738
|
+
&& !signal.aborted
|
|
739
|
+
&& !context.lifecycle.parentTurnStopped) {
|
|
657
740
|
for (const agentId of [...remainingAgentIds]) {
|
|
658
741
|
const rawStoreRef = this.findRawStoreRefOnce(agentId, context.workspacePath, context.homeDir);
|
|
659
742
|
if (rawStoreRef && isCodexRawStoreTerminal(rawStoreRef)) {
|
|
743
|
+
await this.closeSpawnedCodexAgentIfNeeded(context, agentId);
|
|
660
744
|
remainingAgentIds.delete(agentId);
|
|
661
745
|
}
|
|
662
746
|
}
|
|
663
|
-
if (remainingAgentIds.size === 0
|
|
747
|
+
if (remainingAgentIds.size === 0
|
|
748
|
+
|| Date.now() >= deadline
|
|
749
|
+
|| signal.aborted
|
|
750
|
+
|| context.lifecycle.parentTurnStopped) {
|
|
664
751
|
break;
|
|
665
752
|
}
|
|
666
753
|
await sleep(CODEX_SPAWN_AGENT_POLL_INTERVAL_MS);
|
|
667
754
|
}
|
|
755
|
+
if (remainingAgentIds.size === 0) {
|
|
756
|
+
context.lifecycle.spawnedAgentsSettledAfterTurn = true;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
async closeSpawnedCodexAgentIfNeeded(context, agentId) {
|
|
760
|
+
if (context.lifecycle.closedSpawnedAgentIds.has(agentId)) {
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
context.lifecycle.closedSpawnedAgentIds.add(agentId);
|
|
764
|
+
try {
|
|
765
|
+
await context.transport?.closeSpawnedAgent?.(agentId);
|
|
766
|
+
}
|
|
767
|
+
catch (error) {
|
|
768
|
+
logCodexRuntimeStep("turn.close_spawned_agent_failed", context.launchPerfStartedAtMs, {
|
|
769
|
+
providerSessionId: context.providerSessionId,
|
|
770
|
+
agentId,
|
|
771
|
+
error: error instanceof Error ? error.message : String(error)
|
|
772
|
+
});
|
|
773
|
+
}
|
|
668
774
|
}
|
|
669
|
-
async handleEvent(event, request, context,
|
|
775
|
+
async handleEvent(event, request, context, signal) {
|
|
670
776
|
const eventType = ensureText(readProp(event, "type")).trim();
|
|
777
|
+
const interrupted = signal.aborted;
|
|
671
778
|
if (eventType.length === 0) {
|
|
672
779
|
return;
|
|
673
780
|
}
|
|
@@ -682,17 +789,14 @@ export class CodexRuntimeAdapter {
|
|
|
682
789
|
});
|
|
683
790
|
}
|
|
684
791
|
if (eventType === "turn.completed") {
|
|
685
|
-
|
|
686
|
-
type: "complete",
|
|
687
|
-
status: "completed",
|
|
688
|
-
providerSessionId: context.providerSessionId,
|
|
689
|
-
rawStoreRef: context.rawStoreRef,
|
|
792
|
+
context.lifecycle.pendingComplete = {
|
|
690
793
|
detail: "codex turn completed",
|
|
691
794
|
timestamp: pickTimestamp(event)
|
|
692
|
-
}
|
|
795
|
+
};
|
|
693
796
|
return;
|
|
694
797
|
}
|
|
695
798
|
if (eventType === "turn.failed") {
|
|
799
|
+
context.lifecycle.parentTurnStopped = true;
|
|
696
800
|
const detail = extractTextBlocks(readProp(event, "error")).trim() || "codex turn failed";
|
|
697
801
|
await context.sink.emit({
|
|
698
802
|
type: "error",
|
|
@@ -706,6 +810,7 @@ export class CodexRuntimeAdapter {
|
|
|
706
810
|
return;
|
|
707
811
|
}
|
|
708
812
|
if (eventType === "turn.interrupted") {
|
|
813
|
+
context.lifecycle.parentTurnStopped = true;
|
|
709
814
|
await context.sink.emit({
|
|
710
815
|
type: "interrupted",
|
|
711
816
|
status: "interrupted",
|
|
@@ -1314,6 +1419,18 @@ function createCodexAppServerTransport(options) {
|
|
|
1314
1419
|
}
|
|
1315
1420
|
});
|
|
1316
1421
|
},
|
|
1422
|
+
async closeSpawnedAgent(agentId) {
|
|
1423
|
+
const normalizedAgentId = agentId.trim();
|
|
1424
|
+
if (!normalizedAgentId) {
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1427
|
+
await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("thread-unsubscribe", () => ++requestSequence), {
|
|
1428
|
+
method: "thread/unsubscribe",
|
|
1429
|
+
params: {
|
|
1430
|
+
threadId: normalizedAgentId
|
|
1431
|
+
}
|
|
1432
|
+
});
|
|
1433
|
+
},
|
|
1317
1434
|
setNotificationHandler(handler) {
|
|
1318
1435
|
notificationHandler = handler;
|
|
1319
1436
|
},
|