@openclaw/codex 2026.9.4 → 2026.9.6
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/assets/activity.svg +30 -0
- package/assets/icon.png +0 -0
- package/dist/.setup/account-usage-runtime-Eem_WGqY.mjs +75 -0
- package/dist/{apply-CvT8tW5i.js → .setup/apply-DDOi8uNx.mjs} +24 -30
- package/dist/.setup/async-questions-DdhOCwGi.mjs +27 -0
- package/dist/{attempt-client-cleanup-DKHzbwt5.js → .setup/attempt-client-cleanup-CEv1cKwF.mjs} +79 -49
- package/dist/.setup/attempt-terminal-gZrxQ35N.mjs +5 -0
- package/dist/.setup/attempt-workspace-context-DUVEn_CS.mjs +331 -0
- package/dist/{auth-binding-CWlKVccJ.js → .setup/auth-binding-DhLWa_7K.mjs} +1 -1
- package/dist/{auth-cache-key-7orQae_j.js → .setup/auth-cache-key-B2mpaI9D.mjs} +9 -81
- package/dist/{auth-profile-CwzO4_RG.js → .setup/auth-profile-WqZtZfXN.mjs} +1 -1
- package/dist/.setup/auth-profile-health-oHizqgye.mjs +53 -0
- package/dist/.setup/auth-profile-recovery-BREezV0L.mjs +14 -0
- package/dist/.setup/binding-connection-ThoatDcb.mjs +50 -0
- package/dist/.setup/binding-connection.runtime-yoHrABt-.mjs +48 -0
- package/dist/{bounded-turn-C_Hneydj.js → .setup/bounded-turn-B2HScEgT.mjs} +143 -32
- package/dist/{build-state-BCmg9-5p.js → .setup/build-state-C7EnDVgr.mjs} +1 -1
- package/dist/{capabilities-8vx68WLH.js → .setup/capabilities-CDXOOFdZ.mjs} +1 -1
- package/dist/{client-B57KWPQx.js → .setup/client-Cs08OXVQ.mjs} +705 -512
- package/dist/.setup/client-catalog-response-BMgt_4q4.mjs +285 -0
- package/dist/{command-dispatch-BpduNGVf.js → .setup/command-dispatch-B4JuOsOk.mjs} +8 -4
- package/dist/{command-formatters-lxlkNZgU.js → .setup/command-formatters-Bmqvr9tO.mjs} +8 -4
- package/dist/{command-handlers-tiL9iWj7.js → .setup/command-handlers-DW7Lx9oH.mjs} +137 -186
- package/dist/{command-rpc-CR5EOEZX.js → .setup/command-rpc-DixIj3HW.mjs} +47 -23
- package/dist/{compact-B_H3AOd7.js → .setup/compact-Du5UvtxA.mjs} +29 -51
- package/dist/{config-oIORaQ5T.js → .setup/config-BoTP_mrL.mjs} +5 -4
- package/dist/{config-options-CXMq1T-C.js → .setup/config-options-BvaRs51b.mjs} +50 -446
- package/dist/{protocol-5bh1G-H7.js → .setup/config-parsing-CcB9iPoq.mjs} +9 -51
- package/dist/{config-runtime-D0zGNIHu.js → .setup/config-runtime-C8Rw1m1m.mjs} +2 -2
- package/dist/.setup/config-security-BEReZ6go.mjs +380 -0
- package/dist/{conversation-binding-DsB4-O7U.js → .setup/conversation-binding-DP-gMrBP.mjs} +29 -38
- package/dist/{conversation-binding-data-BiodpIzq.js → .setup/conversation-binding-data-CrcyZk6O.mjs} +1 -1
- package/dist/{conversation-control-CtUu1b3m.js → .setup/conversation-control-uK9Jomlc.mjs} +32 -67
- package/dist/.setup/cyber-failover-DYwbmf1o.mjs +123 -0
- package/dist/.setup/cyber-failover-notice-e9G3J9-e.mjs +17 -0
- package/dist/{dynamic-tools-CmN5RAip.js → .setup/dynamic-tools-BDXl-8Cw.mjs} +936 -620
- package/dist/{effective-mcp-catalog-Bd73bqA8.js → .setup/effective-mcp-catalog-CvnvnGIe.mjs} +3 -3
- package/dist/{ephemeral-turn-D78_VmzO.js → .setup/ephemeral-turn-poidXgek.mjs} +9 -7
- package/dist/{event-projector-assistant-message-BmBM4qBV.js → .setup/event-projector-assistant-message-BsruvNrH.mjs} +8 -7
- package/dist/{event-projector-items-5VhsECCO.js → .setup/event-projector-items-C6L_5ZiT.mjs} +42 -8
- package/dist/{attempt-notifications-C9XufG6l.js → .setup/event-projector-usage-CnBS8Wa3.mjs} +102 -9
- package/dist/{harness-C7rRa7bm.js → .setup/harness-a_MsE4-_.mjs} +81 -21
- package/dist/{inference-context-Dr_mzvk4.js → .setup/inference-context-D96l9-ew.mjs} +1 -1
- package/dist/.setup/inference-proxy-b-aJMSxm.mjs +601 -0
- package/dist/{isolated-completion-DWVb5U2J.js → .setup/isolated-completion-BIZFhTNG.mjs} +18 -11
- package/dist/.setup/launch-args-DbFCehO7.mjs +196 -0
- package/dist/{managed-binary-D22rNEcR.js → .setup/managed-binary-BnshlFag.mjs} +14 -3
- package/dist/{managed-thread-store-D1t5jh3G.js → .setup/managed-thread-store-BMqgThVL.mjs} +48 -14
- package/dist/{model-catalog-Dq2n8f_p.js → .setup/model-catalog-CfXJf9Ay.mjs} +36 -12
- package/dist/{models-PCKOim-h.js → .setup/models-KnqBv0hE.mjs} +3 -3
- package/dist/.setup/native-auth-rWbGbMn3.mjs +57 -0
- package/dist/{native-subagent-history-DjtPloaU.js → .setup/native-subagent-history-0nYYgo0k.mjs} +43 -35
- package/dist/.setup/native-subagent-monitor-D3filLY2.mjs +4859 -0
- package/dist/{native-subagent-task-ids-BzTdT0Uw.js → .setup/native-subagent-task-ids-wb8CKZGN.mjs} +98 -44
- package/dist/{node-cli-sessions-DKaOmVUh.js → .setup/node-cli-sessions-r3avj02l.mjs} +86 -68
- package/dist/.setup/node-exec-server.runtime-BDwWXVpK.mjs +247 -0
- package/dist/{plan-7uG-Fp36.js → .setup/plan-CN3VwfNU.mjs} +133 -119
- package/dist/{plugin-activation-BYQculil.js → .setup/plugin-activation-DT3MNtqj.mjs} +7 -16
- package/dist/{plugin-app-cache-key-d0eKxy7b.js → .setup/plugin-app-cache-key-B2CsSdnV.mjs} +32 -44
- package/dist/{plugin-approval-roundtrip-Bz3FT8W5.js → .setup/plugin-approval-roundtrip-C0MZzCuP.mjs} +1 -1
- package/dist/{plugin-inventory-oL4Na1ZG.js → .setup/plugin-inventory-BoRei8Z4.mjs} +21 -11
- package/dist/{plugin-marketplace-discovery-P-Vndfqq.js → .setup/plugin-marketplace-discovery-CDOi8IFs.mjs} +4 -1
- package/dist/{plugin-metadata-cache-ClPJpRio.js → .setup/plugin-metadata-cache-Ctmo83k_.mjs} +226 -141
- package/dist/.setup/protocol-CANUwXJ3.mjs +17 -0
- package/dist/{provider-MQ8PVkuE.js → .setup/provider-BOsxQHOM.mjs} +9 -5
- package/dist/{provider-capabilities-BvCUL69A.js → .setup/provider-capabilities-BfE88FZ5.mjs} +31 -3
- package/dist/{rate-limits-CBMmWBr9.js → .setup/rate-limits-CMU3DUD0.mjs} +174 -151
- package/dist/{request-B7hEkBGq.js → .setup/request-D2L0zMrq.mjs} +130 -42
- package/dist/{run-attempt-CvsAAGa0.js → .setup/run-attempt-BHu11r7h.mjs} +1628 -966
- package/dist/.setup/run-attempt-lifecycle-B7JbY4-F.mjs +71 -0
- package/dist/{runtime-artifact-BJ0rXBZ_.js → .setup/runtime-artifact-CLZ8udh-.mjs} +29 -45
- package/dist/{sandbox-guard-BxgyoM8M.js → .setup/sandbox-guard-C2sRMOEY.mjs} +3 -3
- package/dist/{session-binding-CI8UuilT.js → .setup/session-binding-Cm0apEbd.mjs} +36 -83
- package/dist/{session-binding-record-Bcvslnhf.js → .setup/session-binding-record-BGoz8wOK.mjs} +202 -5
- package/dist/.setup/session-binding-sidecars-BlB5EvIS.mjs +546 -0
- package/dist/.setup/session-catalog-Pno1xGcl.mjs +2764 -0
- package/dist/{session-catalog-adoption-tcZi1IfX.js → .setup/session-catalog-adoption-BI6UTDZT.mjs} +58 -26
- package/dist/{session-catalog-archive-CwKg8Xz2.js → .setup/session-catalog-archive-lHBqzhaO.mjs} +6 -6
- package/dist/.setup/session-catalog-events-Bj6j94E_.mjs +347 -0
- package/dist/.setup/session-catalog-index-B9_VQIUz.mjs +1170 -0
- package/dist/.setup/session-catalog-index-order-hcdz07yN.mjs +48 -0
- package/dist/.setup/session-catalog-index-state-Dgh8ORJm.mjs +183 -0
- package/dist/{thread-history-page-D0JIp48V.js → .setup/session-catalog-native-projection-DowriLid.mjs} +223 -95
- package/dist/{session-catalog-node-adoption-B1tgDW-m.js → .setup/session-catalog-node-adoption-ITddWx_X.mjs} +25 -13
- package/dist/{session-catalog-node-continue-Ci-DXyJP.js → .setup/session-catalog-node-continue-6g6qi4A9.mjs} +24 -15
- package/dist/.setup/session-catalog-projection-zK_PUsiE.mjs +422 -0
- package/dist/{session-cli-DNN_jhGc.js → .setup/session-cli-irrD-uo7.mjs} +3 -3
- package/dist/{session-history-Cz-tOOYj.js → .setup/session-history-BrqhSCf9.mjs} +19 -19
- package/dist/{session-history-import-DwyijFI6.js → .setup/session-history-import-D-3wAgOP.mjs} +4 -4
- package/dist/{session-history-read-cxPUxyVV.js → .setup/session-history-read-B3ZfSUbF.mjs} +2 -2
- package/dist/{session-history.worker-BeK1YOyT.js → .setup/session-history.worker-CaCh0xF_.mjs} +10 -24
- package/dist/{session-initialization-Ct0_Hzmg.js → .setup/session-initialization-rcgbZiid.mjs} +2 -2
- package/dist/{session-permission-policy-BBmXA8Eg.js → .setup/session-permission-policy-BI1QK_98.mjs} +2 -2
- package/dist/{session-retirement-B2YfbAAT.js → .setup/session-retirement-BH-S6qkJ.mjs} +26 -7
- package/dist/{settled-turn-context-Du6gdUDd.js → .setup/settled-turn-context-fmwouT5I.mjs} +2 -2
- package/dist/{settled-turn-finalizer-Dn91stmc.js → .setup/settled-turn-finalizer-DiAi6Kx6.mjs} +12 -12
- package/dist/{shared-client-CscigXXL.js → .setup/shared-client-DA4VR4Eb.mjs} +332 -221
- package/dist/{side-question-BGMJQf4U.js → .setup/side-question-BJ1wSDcB.mjs} +183 -230
- package/dist/{source-CElXU0Oy.js → .setup/source-CUzJq5WN.mjs} +11 -10
- package/dist/.setup/spawn-error-CL3n6MAa.mjs +57 -0
- package/dist/{thread-archive-guard-DfpBr-Sz.js → .setup/thread-archive-guard-C9frICzX.mjs} +10 -3
- package/dist/.setup/thread-history-page-DoVpnHim.mjs +83 -0
- package/dist/{thread-lifecycle-DXl1-I6b.js → .setup/thread-lifecycle-B3mfz1TG.mjs} +347 -2318
- package/dist/{thread-ownership-BsDRTsyp.js → .setup/thread-ownership-DcTtAcXj.mjs} +6 -4
- package/dist/{thread-policy-BuEQfE0g.js → .setup/thread-policy-DGuQsuFC.mjs} +19 -3
- package/dist/.setup/thread-requests-BLvGkP2R.mjs +2205 -0
- package/dist/{thread-resume-DsDOZpFg.js → .setup/thread-resume-DIBXwOpE.mjs} +8 -5
- package/dist/.setup/timeout-C910MdAB.mjs +80 -0
- package/dist/{transcript-history-projection-v17wXgdK.js → .setup/transcript-history-projection-ZZpkFkJ_.mjs} +96 -61
- package/dist/{transcript-mirror-C5CKgNy6.js → .setup/transcript-mirror-BtHDBp1G.mjs} +224 -195
- package/dist/{transcript-mirror-attestation-DibE0krH.js → .setup/transcript-mirror-attestation-CzM-94NC.mjs} +4 -1
- package/dist/{transport-stdio-BGjHoYLr.js → .setup/transport-stdio-h2VHOskC.mjs} +274 -89
- package/dist/{upstream-session-fork-BZerMte_.js → .setup/upstream-session-fork-BUr4OUbC.mjs} +51 -42
- package/dist/{usage-tCk-mg_x.js → .setup/usage-BML0r-ua.mjs} +5 -4
- package/dist/.setup/usage-limit-error-DUMbefVY.mjs +166 -0
- package/dist/{web-search-provider.runtime-B7bGbGWq.js → .setup/web-search-provider.runtime-CDKlN-Rv.mjs} +4 -3
- package/dist/api.js +23 -12
- package/dist/catalog-page-worker-entrypoint.js +12 -0
- package/dist/catalog-page.worker.js +9 -0
- package/dist/cli-metadata.js +1 -1
- package/dist/doctor-contract-api.js +8 -528
- package/dist/harness.js +1 -1
- package/dist/index.js +306 -215
- package/dist/media-understanding-provider.js +3 -3
- package/dist/migration-provider-api.js +1 -1
- package/dist/native-tool-policy.js +12 -0
- package/dist/provider-discovery.js +18 -0
- package/dist/session-history-worker-runtime.js +36 -35
- package/dist/session-history.worker.js +2 -2
- package/dist/web-search-contract-api.js +1 -1
- package/openclaw.plugin.json +354 -69
- package/package.json +14 -8
- package/dist/attempt-context-D44yeDII.js +0 -636
- package/dist/binding-connection-D3udKbIE.js +0 -60
- package/dist/event-projector-usage-BfXmpOec.js +0 -102
- package/dist/inference-proxy-HGXKUIre.js +0 -311
- package/dist/launch-args-RXQwn8zV.js +0 -90
- package/dist/native-subagent-history-owner-Pcp7JuVF.js +0 -34
- package/dist/native-subagent-monitor-fQ7eIXEf.js +0 -2978
- package/dist/node-exec-server.runtime-Cl2vapEi.js +0 -226
- package/dist/rpc-error-ttN_QjEm.js +0 -30
- package/dist/session-catalog-ct-AH01I.js +0 -1477
- package/dist/session-catalog-home-id-CwhLdC03.js +0 -18
- package/dist/session-catalog-provenance-D-dIfRAH.js +0 -96
- package/dist/timeout-BVw8aaM1.js +0 -33
- package/dist/version-omm6IPI3.js +0 -12
- /package/dist/{auth-profile-selection-DFu9e167.js → .setup/auth-profile-selection-DFu9e167.mjs} +0 -0
- /package/dist/{config-utils-DujwEnhg.js → .setup/config-utils-DujwEnhg.mjs} +0 -0
- /package/dist/{context-compaction-activity-CMla5FPJ.js → .setup/context-compaction-activity-CMla5FPJ.mjs} +0 -0
- /package/dist/{elicitation-input-DPoK8F7w.js → .setup/elicitation-input-DPoK8F7w.mjs} +0 -0
- /package/dist/{history-rejection-B4nOXNXF.js → .setup/history-rejection-B4nOXNXF.mjs} +0 -0
- /package/dist/{image-payload-sanitizer-tupAr-2o.js → .setup/image-payload-sanitizer-tupAr-2o.mjs} +0 -0
- /package/dist/{incognito-session-uhrBF6wJ.js → .setup/incognito-session-uhrBF6wJ.mjs} +0 -0
- /package/dist/{local-runtime-attribution-B_2mnqhb.js → .setup/local-runtime-attribution-B_2mnqhb.mjs} +0 -0
- /package/dist/{native-execution-policy-umd0tgh4.js → .setup/native-execution-policy-umd0tgh4.mjs} +0 -0
- /package/dist/{rolldown-runtime-8H4AJuhK.js → .setup/rolldown-runtime-8H4AJuhK.mjs} +0 -0
- /package/dist/{session-binding-meta-B7aEMU7g.js → .setup/session-binding-meta-B7aEMU7g.mjs} +0 -0
- /package/dist/{session-upstream-marker-D15C9NHp.js → .setup/session-upstream-marker-D15C9NHp.mjs} +0 -0
- /package/dist/{upstream-prompt-provenance-LphB8slG.js → .setup/upstream-prompt-provenance-LphB8slG.mjs} +0 -0
- /package/dist/{web-search-provider.shared-BrZmlqyR.js → .setup/web-search-provider.shared-BrZmlqyR.mjs} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { v as CatalogParamsError } from "./session-catalog-native-projection-DowriLid.mjs";
|
|
2
2
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
|
4
|
-
import { resolveStorePath } from "openclaw/plugin-sdk/session-store-paths";
|
|
5
4
|
import { listSessionCatalogEntries, sessionCatalogAdoptedSessionKey, sessionCatalogAdoptedSourceKey } from "openclaw/plugin-sdk/session-catalog";
|
|
5
|
+
import { resolveStorePath } from "openclaw/plugin-sdk/session-store-paths";
|
|
6
6
|
//#region extensions/codex/src/session-catalog-node-adoption.ts
|
|
7
7
|
const CODEX_NODE_SESSION_KEY_PREFIX = "harness:codex:node-session:";
|
|
8
8
|
const continueOperations = /* @__PURE__ */ new Map();
|
|
@@ -21,17 +21,25 @@ function adoptionSessionKeyRest(sessionKey) {
|
|
|
21
21
|
const trimmed = sessionKey.trim();
|
|
22
22
|
return parseAgentSessionKey(trimmed)?.rest ?? trimmed;
|
|
23
23
|
}
|
|
24
|
-
function
|
|
25
|
-
|
|
24
|
+
function nodeAdoptedSourceKey(hostId, threadId, sourceHomeId) {
|
|
25
|
+
return sessionCatalogAdoptedSourceKey(JSON.stringify([hostId, sourceHomeId]), threadId);
|
|
26
|
+
}
|
|
27
|
+
function nodeAdoptionSessionKey(hostId, threadId, sourceHomeId) {
|
|
28
|
+
const source = JSON.stringify([
|
|
29
|
+
hostId,
|
|
30
|
+
sourceHomeId,
|
|
31
|
+
threadId
|
|
32
|
+
]);
|
|
26
33
|
return sessionCatalogAdoptedSessionKey(CODEX_NODE_SESSION_KEY_PREFIX, source);
|
|
27
34
|
}
|
|
28
35
|
function readNodeSessionMarker(entry) {
|
|
29
36
|
const codex = isRecord(entry.pluginExtensions?.codex) ? entry.pluginExtensions.codex : void 0;
|
|
30
37
|
const marker = codex && isRecord(codex.sessionCatalog) ? codex.sessionCatalog : void 0;
|
|
31
|
-
if (!marker || typeof marker.sourceHostId !== "string" || !marker.sourceHostId.startsWith("node:") || typeof marker.sourceThreadId !== "string" || !marker.sourceThreadId.trim() || typeof marker.nodeId !== "string" || !marker.nodeId.trim()) return;
|
|
38
|
+
if (!marker || typeof marker.sourceHostId !== "string" || !marker.sourceHostId.startsWith("node:") || typeof marker.sourceThreadId !== "string" || !marker.sourceThreadId.trim() || typeof marker.nodeId !== "string" || !marker.nodeId.trim() || marker.sourceHomeId !== void 0 && (typeof marker.sourceHomeId !== "string" || !marker.sourceHomeId.trim() || marker.sourceHomeId.length > 256)) return;
|
|
32
39
|
return {
|
|
33
40
|
sourceHostId: marker.sourceHostId,
|
|
34
41
|
sourceThreadId: marker.sourceThreadId,
|
|
42
|
+
...typeof marker.sourceHomeId === "string" ? { sourceHomeId: marker.sourceHomeId } : {},
|
|
35
43
|
nodeId: marker.nodeId,
|
|
36
44
|
...marker.initializing === true ? { initializing: true } : {}
|
|
37
45
|
};
|
|
@@ -46,8 +54,8 @@ function listNodeAdoptedSessionEntries(params) {
|
|
|
46
54
|
})) {
|
|
47
55
|
const marker = readNodeSessionMarker(entry);
|
|
48
56
|
const sessionId = entry.sessionId?.trim();
|
|
49
|
-
if (!marker || marker.initializing === true && params.includeInitializing !== true || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true || !sessionId || adoptionSessionKeyRest(sessionKey) !== nodeAdoptionSessionKey(marker.sourceHostId, marker.sourceThreadId) || marker.sourceHostId !== `node:${marker.nodeId}`) continue;
|
|
50
|
-
const sourceKey =
|
|
57
|
+
if (!marker || !marker.sourceHomeId || marker.initializing === true && params.includeInitializing !== true || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true || !sessionId || adoptionSessionKeyRest(sessionKey) !== nodeAdoptionSessionKey(marker.sourceHostId, marker.sourceThreadId, marker.sourceHomeId) || marker.sourceHostId !== `node:${marker.nodeId}`) continue;
|
|
58
|
+
const sourceKey = nodeAdoptedSourceKey(marker.sourceHostId, marker.sourceThreadId, marker.sourceHomeId);
|
|
51
59
|
if (adopted.has(sourceKey)) throw new Error(`multiple OpenClaw sessions adopt Codex thread ${marker.sourceThreadId} on ${marker.sourceHostId}`);
|
|
52
60
|
adopted.set(sourceKey, {
|
|
53
61
|
key: sessionKey,
|
|
@@ -59,12 +67,13 @@ function listNodeAdoptedSessionEntries(params) {
|
|
|
59
67
|
return adopted;
|
|
60
68
|
}
|
|
61
69
|
function findNodeAdoptedSessionEntry(params) {
|
|
62
|
-
return listNodeAdoptedSessionEntries(params).get(
|
|
70
|
+
return listNodeAdoptedSessionEntries(params).get(nodeAdoptedSourceKey(params.hostId, params.threadId, params.sourceHomeId));
|
|
63
71
|
}
|
|
64
72
|
function nodeSessionMarker(params) {
|
|
65
73
|
return {
|
|
66
74
|
sourceHostId: params.hostId,
|
|
67
75
|
sourceThreadId: params.threadId,
|
|
76
|
+
sourceHomeId: params.sourceHomeId,
|
|
68
77
|
nodeId: params.nodeId,
|
|
69
78
|
...params.initializing === true ? { initializing: true } : {}
|
|
70
79
|
};
|
|
@@ -79,7 +88,7 @@ async function finalizeNodeAdoptedSession(params) {
|
|
|
79
88
|
preserveActivity: true,
|
|
80
89
|
update: (entry) => {
|
|
81
90
|
const current = readNodeSessionMarker(entry);
|
|
82
|
-
if (entry.sessionId?.trim() !== params.adopted.sessionId || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true || !current || current.sourceHostId !== params.marker.sourceHostId || current.sourceThreadId !== params.marker.sourceThreadId || current.nodeId !== params.marker.nodeId) throw changedError();
|
|
91
|
+
if (entry.sessionId?.trim() !== params.adopted.sessionId || entry.initializationPending === true || entry.agentHarnessId !== "codex" || entry.modelSelectionLocked !== true || !current || current.sourceHostId !== params.marker.sourceHostId || current.sourceThreadId !== params.marker.sourceThreadId || current.sourceHomeId !== params.marker.sourceHomeId || current.nodeId !== params.marker.nodeId) throw changedError();
|
|
83
92
|
if (current.initializing !== true) return {
|
|
84
93
|
archivedAt: void 0,
|
|
85
94
|
archivedBy: void 0,
|
|
@@ -106,7 +115,7 @@ async function finalizeNodeAdoptedSession(params) {
|
|
|
106
115
|
readConsistency: "latest"
|
|
107
116
|
});
|
|
108
117
|
const current = currentEntry ? readNodeSessionMarker(currentEntry) : void 0;
|
|
109
|
-
if (currentEntry?.sessionId?.trim() === params.adopted.sessionId && current?.initializing !== true && current?.sourceHostId === params.marker.sourceHostId && current.sourceThreadId === params.marker.sourceThreadId && current.nodeId === params.marker.nodeId) return;
|
|
118
|
+
if (currentEntry?.sessionId?.trim() === params.adopted.sessionId && current?.initializing !== true && current?.sourceHostId === params.marker.sourceHostId && current.sourceThreadId === params.marker.sourceThreadId && current.sourceHomeId === params.marker.sourceHomeId && current.nodeId === params.marker.nodeId) return;
|
|
110
119
|
throw error;
|
|
111
120
|
}
|
|
112
121
|
if (!finalized) throw changedError();
|
|
@@ -118,6 +127,7 @@ async function createOrReuseNodeAdoptedSession(params) {
|
|
|
118
127
|
runtime: params.api.runtime,
|
|
119
128
|
hostId: params.hostId,
|
|
120
129
|
threadId: params.record.threadId,
|
|
130
|
+
sourceHomeId: params.sourceHomeId,
|
|
121
131
|
includeInitializing: true
|
|
122
132
|
});
|
|
123
133
|
if (existing) return existing;
|
|
@@ -125,6 +135,7 @@ async function createOrReuseNodeAdoptedSession(params) {
|
|
|
125
135
|
...nodeSessionMarker({
|
|
126
136
|
hostId: params.hostId,
|
|
127
137
|
threadId: params.record.threadId,
|
|
138
|
+
sourceHomeId: params.sourceHomeId,
|
|
128
139
|
nodeId: params.nodeId
|
|
129
140
|
}),
|
|
130
141
|
initializing: true
|
|
@@ -132,7 +143,7 @@ async function createOrReuseNodeAdoptedSession(params) {
|
|
|
132
143
|
try {
|
|
133
144
|
const created = await params.api.runtime.agent.session.createSessionEntry({
|
|
134
145
|
cfg: params.config,
|
|
135
|
-
key: nodeAdoptionSessionKey(params.hostId, params.record.threadId),
|
|
146
|
+
key: nodeAdoptionSessionKey(params.hostId, params.record.threadId, params.sourceHomeId),
|
|
136
147
|
agentId: params.agentId,
|
|
137
148
|
recoverMatchingInitialEntry: true,
|
|
138
149
|
displayName: params.record.name ?? void 0,
|
|
@@ -144,7 +155,7 @@ async function createOrReuseNodeAdoptedSession(params) {
|
|
|
144
155
|
},
|
|
145
156
|
afterCreate: async (entry) => {
|
|
146
157
|
const storePath = resolveStorePath(params.config.session?.store, { agentId: entry.agentId });
|
|
147
|
-
const { importCodexThreadHistoryToTranscript } = await import("./transcript-mirror-
|
|
158
|
+
const { importCodexThreadHistoryToTranscript } = await import("./transcript-mirror-BtHDBp1G.mjs").then((n) => n.a);
|
|
148
159
|
await importCodexThreadHistoryToTranscript({
|
|
149
160
|
thread: params.history.thread,
|
|
150
161
|
throughTurnId: params.history.throughTurnId,
|
|
@@ -172,6 +183,7 @@ async function createOrReuseNodeAdoptedSession(params) {
|
|
|
172
183
|
runtime: params.api.runtime,
|
|
173
184
|
hostId: params.hostId,
|
|
174
185
|
threadId: params.record.threadId,
|
|
186
|
+
sourceHomeId: params.sourceHomeId,
|
|
175
187
|
includeInitializing: true
|
|
176
188
|
});
|
|
177
189
|
if (raced) return raced;
|
|
@@ -179,4 +191,4 @@ async function createOrReuseNodeAdoptedSession(params) {
|
|
|
179
191
|
}
|
|
180
192
|
}
|
|
181
193
|
//#endregion
|
|
182
|
-
export { adoptionSessionKeyRest, continueOperations, createOrReuseNodeAdoptedSession, finalizeNodeAdoptedSession, findNodeAdoptedSessionEntry, listNodeAdoptedSessionEntries, nodeSessionMarker, runSessionActionExclusive };
|
|
194
|
+
export { CODEX_NODE_SESSION_KEY_PREFIX, adoptionSessionKeyRest, continueOperations, createOrReuseNodeAdoptedSession, finalizeNodeAdoptedSession, findNodeAdoptedSessionEntry, listNodeAdoptedSessionEntries, nodeAdoptedSourceKey, nodeSessionMarker, readNodeSessionMarker, runSessionActionExclusive };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { createOrReuseNodeAdoptedSession, finalizeNodeAdoptedSession, findNodeAdoptedSessionEntry, nodeSessionMarker, runSessionActionExclusive } from "./session-catalog-node-adoption-
|
|
1
|
+
import { A as parseCatalogPage, C as boundedCatalogString, D as filterCatalogPageByTitle, H as unwrapNodeInvokePayload, M as parseTranscriptPage, O as isInteractiveThreadSource, S as NODE_INVOKE_TIMEOUT_MS, h as CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND, m as CODEX_APP_SERVER_THREADS_LIST_COMMAND, v as CatalogParamsError, w as catalogError } from "./session-catalog-native-projection-DowriLid.mjs";
|
|
2
|
+
import { n as createCodexCliNodeConversationBindingData } from "./conversation-binding-data-CrcyZk6O.mjs";
|
|
3
|
+
import { i as withTimeout } from "./timeout-C910MdAB.mjs";
|
|
4
|
+
import { r as CODEX_CLI_SESSION_SOURCE_UPGRADE_MESSAGE, t as CODEX_CLI_SESSION_RESUME_COMMAND } from "./node-cli-sessions-r3avj02l.mjs";
|
|
5
|
+
import { o as lookupNodeCodexCatalogRecord } from "./session-catalog-Pno1xGcl.mjs";
|
|
6
|
+
import { t as codexLastTerminalTurnId } from "./session-upstream-marker-D15C9NHp.mjs";
|
|
7
|
+
import { createOrReuseNodeAdoptedSession, finalizeNodeAdoptedSession, findNodeAdoptedSessionEntry, nodeAdoptedSourceKey, nodeSessionMarker, runSessionActionExclusive } from "./session-catalog-node-adoption-ITddWx_X.mjs";
|
|
8
8
|
import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
9
9
|
import { createSessionCatalogAdoptionCoordinator, publishSessionCatalogHost, sessionCatalogAdoptedSourceKey } from "openclaw/plugin-sdk/session-catalog";
|
|
10
10
|
//#region extensions/codex/src/session-catalog-node-continue.ts
|
|
@@ -26,7 +26,7 @@ function compareNodeLabels(left, right) {
|
|
|
26
26
|
return 0;
|
|
27
27
|
}
|
|
28
28
|
function canContinueCodexOnNode(node) {
|
|
29
|
-
return node.connected === true && CODEX_NODE_CONTINUE_COMMANDS.every((command) => node.commands?.includes(command) === true && node.invocableCommands?.includes(command) === true);
|
|
29
|
+
return node.connected === true && node.caps?.includes("codex-cli-session-source") === true && CODEX_NODE_CONTINUE_COMMANDS.every((command) => node.commands?.includes(command) === true && node.invocableCommands?.includes(command) === true);
|
|
30
30
|
}
|
|
31
31
|
async function listPairedNode(params) {
|
|
32
32
|
const hostId = `node:${params.node.nodeId}`;
|
|
@@ -79,10 +79,8 @@ async function listPairedNode(params) {
|
|
|
79
79
|
...common,
|
|
80
80
|
connected: true,
|
|
81
81
|
...page,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return adopted ? Object.assign({}, session, { sessionKey: adopted.key }) : session;
|
|
85
|
-
})
|
|
82
|
+
canContinueCodex: common.canContinueCodex && page.canContinueCodex === true && Boolean(page.sourceHomeId),
|
|
83
|
+
sessions: page.sessions.map((session) => Object.assign({}, session, page.sourceHomeId ? { sourceHomeId: page.sourceHomeId } : {}))
|
|
86
84
|
};
|
|
87
85
|
}).catch((error) => ({
|
|
88
86
|
...common,
|
|
@@ -106,7 +104,10 @@ async function requireNodeForCodexContinue(params) {
|
|
|
106
104
|
const nodeId = params.hostId.slice(5).trim();
|
|
107
105
|
if (!nodeId || params.hostId !== `node:${nodeId}`) throw new CatalogParamsError("Codex session catalog hostId is invalid");
|
|
108
106
|
const node = (await params.runtime.nodes.list()).nodes.find((candidate) => candidate.nodeId === nodeId);
|
|
109
|
-
if (!node || !canContinueCodexOnNode(node))
|
|
107
|
+
if (!node || !canContinueCodexOnNode(node)) {
|
|
108
|
+
if (node?.connected && !node.caps?.includes("codex-cli-session-source")) throw new CatalogParamsError(CODEX_CLI_SESSION_SOURCE_UPGRADE_MESSAGE);
|
|
109
|
+
throw new CatalogParamsError("paired node does not permit Codex session continuation");
|
|
110
|
+
}
|
|
110
111
|
return {
|
|
111
112
|
node,
|
|
112
113
|
nodeId
|
|
@@ -125,6 +126,7 @@ async function readNodeCodexHistory(params) {
|
|
|
125
126
|
command: CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND,
|
|
126
127
|
params: {
|
|
127
128
|
agentId: params.agentId,
|
|
129
|
+
sourceHomeId: params.sourceHomeId,
|
|
128
130
|
threadId: params.record.threadId,
|
|
129
131
|
limit: 50
|
|
130
132
|
},
|
|
@@ -153,9 +155,12 @@ async function continueNodeCodexSessionInner(params) {
|
|
|
153
155
|
agentId: params.agentId,
|
|
154
156
|
runtime: params.api.runtime,
|
|
155
157
|
nodeId,
|
|
156
|
-
threadId: params.threadId
|
|
158
|
+
threadId: params.threadId,
|
|
159
|
+
sourceHomeId: params.sourceHomeId
|
|
157
160
|
});
|
|
158
161
|
if (lookup.kind !== "found") throw new CatalogParamsError(lookup.kind === "cursor-cycle" ? "Codex session eligibility could not be verified" : "Codex session is unavailable on the paired node");
|
|
162
|
+
if (lookup.canContinueCodex !== true || !lookup.sourceHomeId) throw new CatalogParamsError("Codex session source does not support Chat continuation; use a local stdio source or update the node.");
|
|
163
|
+
const sourceHomeId = lookup.sourceHomeId;
|
|
159
164
|
const record = lookup.record;
|
|
160
165
|
requireContinuableNodeRecord(record);
|
|
161
166
|
const existing = findNodeAdoptedSessionEntry({
|
|
@@ -164,6 +169,7 @@ async function continueNodeCodexSessionInner(params) {
|
|
|
164
169
|
runtime: params.api.runtime,
|
|
165
170
|
hostId: params.hostId,
|
|
166
171
|
threadId: params.threadId,
|
|
172
|
+
sourceHomeId,
|
|
167
173
|
includeInitializing: true
|
|
168
174
|
});
|
|
169
175
|
let adopted;
|
|
@@ -176,6 +182,7 @@ async function continueNodeCodexSessionInner(params) {
|
|
|
176
182
|
agentId: params.agentId,
|
|
177
183
|
runtime: params.api.runtime,
|
|
178
184
|
nodeId,
|
|
185
|
+
sourceHomeId,
|
|
179
186
|
record
|
|
180
187
|
});
|
|
181
188
|
adopted = await createOrReuseNodeAdoptedSession({
|
|
@@ -184,6 +191,7 @@ async function continueNodeCodexSessionInner(params) {
|
|
|
184
191
|
config: params.config,
|
|
185
192
|
hostId: params.hostId,
|
|
186
193
|
nodeId,
|
|
194
|
+
sourceHomeId,
|
|
187
195
|
record,
|
|
188
196
|
history
|
|
189
197
|
});
|
|
@@ -192,6 +200,7 @@ async function continueNodeCodexSessionInner(params) {
|
|
|
192
200
|
const marker = nodeSessionMarker({
|
|
193
201
|
hostId: params.hostId,
|
|
194
202
|
threadId: params.threadId,
|
|
203
|
+
sourceHomeId,
|
|
195
204
|
nodeId
|
|
196
205
|
});
|
|
197
206
|
return {
|
|
@@ -223,7 +232,7 @@ async function continueNodeCodexSession(params) {
|
|
|
223
232
|
agentId: params.agentId
|
|
224
233
|
}).sessionAgentId;
|
|
225
234
|
const sourceKey = sessionCatalogAdoptedSourceKey(`node:${nodeId}`, params.threadId);
|
|
226
|
-
const operationKey = sessionCatalogAdoptedSourceKey(agentId, sourceKey);
|
|
235
|
+
const operationKey = sessionCatalogAdoptedSourceKey(agentId, params.sourceHomeId ? nodeAdoptedSourceKey(`node:${nodeId}`, params.threadId, params.sourceHomeId) : sourceKey);
|
|
227
236
|
return await continueNodeAdoption({
|
|
228
237
|
sourceKey: operationKey,
|
|
229
238
|
findExisting: () => void 0,
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
import { B as toCatalogSession, C as boundedCatalogString, P as readControlCursor, V as truncateCodexCatalogPreview, W as detachCodexCatalogString, c as copyCodexCatalogSource, f as setCodexCatalogSource, l as getCodexCatalogSource, r as projectCodexCatalogNativeThread, z as selectCodexCatalogPreviewInput } from "./session-catalog-native-projection-DowriLid.mjs";
|
|
2
|
+
import { a as isOpenClawManagedCodexThread } from "./session-catalog-events-Bj6j94E_.mjs";
|
|
3
|
+
import { n as codexCatalogRowRecency } from "./session-catalog-index-order-hcdz07yN.mjs";
|
|
4
|
+
import { asFiniteNumber, isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import fs from "node:fs/promises";
|
|
7
|
+
import { root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
8
|
+
import { extractErrorCode, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
9
|
+
import { constants, createZstdDecompress } from "node:zlib";
|
|
10
|
+
import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
|
|
11
|
+
//#region extensions/codex/src/session-catalog-rollouts.ts
|
|
12
|
+
const WINDOW_BYTES = 131072;
|
|
13
|
+
const DIRECTORY_PARTS = [
|
|
14
|
+
/^\d{4}$/,
|
|
15
|
+
/^(?:0[1-9]|1[0-2])$/,
|
|
16
|
+
/^(?:0[1-9]|[12]\d|3[01])$/
|
|
17
|
+
];
|
|
18
|
+
const ROLLOUT_FILE_NAME = /\.jsonl(?:\.zst)?$/;
|
|
19
|
+
const ROLLOUT_SOURCE_DENIAL_CODES = /* @__PURE__ */ new Set([
|
|
20
|
+
"symlink",
|
|
21
|
+
"hardlink",
|
|
22
|
+
"outside-workspace",
|
|
23
|
+
"invalid-path",
|
|
24
|
+
"device-path",
|
|
25
|
+
"not-file",
|
|
26
|
+
"path-alias"
|
|
27
|
+
]);
|
|
28
|
+
function compareRolloutCandidates(left, right) {
|
|
29
|
+
return left[1].mtimeMs - right[1].mtimeMs || (left[0] < right[0] ? -1 : left[0] > right[0] ? 1 : 0);
|
|
30
|
+
}
|
|
31
|
+
/** Retain only the newest fingerprints while streaming an arbitrarily large home. */
|
|
32
|
+
var NewestRolloutCandidates = class {
|
|
33
|
+
constructor() {
|
|
34
|
+
this.heap = [];
|
|
35
|
+
}
|
|
36
|
+
offer(candidate) {
|
|
37
|
+
if (this.heap.length < 2e4) {
|
|
38
|
+
let childIndex = this.heap.length;
|
|
39
|
+
this.heap.push(candidate);
|
|
40
|
+
while (childIndex > 0) {
|
|
41
|
+
const parentIndex = Math.floor((childIndex - 1) / 2);
|
|
42
|
+
const parent = this.heap[parentIndex];
|
|
43
|
+
if (!parent || compareRolloutCandidates(parent, candidate) <= 0) break;
|
|
44
|
+
this.heap[childIndex] = parent;
|
|
45
|
+
childIndex = parentIndex;
|
|
46
|
+
}
|
|
47
|
+
this.heap[childIndex] = candidate;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const oldest = this.heap[0];
|
|
51
|
+
if (!oldest || compareRolloutCandidates(candidate, oldest) <= 0) return;
|
|
52
|
+
let parentIndex = 0;
|
|
53
|
+
while (true) {
|
|
54
|
+
let childIndex = parentIndex * 2 + 1;
|
|
55
|
+
let child = this.heap[childIndex];
|
|
56
|
+
if (!child) break;
|
|
57
|
+
const right = this.heap[childIndex + 1];
|
|
58
|
+
if (right && compareRolloutCandidates(right, child) < 0) {
|
|
59
|
+
child = right;
|
|
60
|
+
childIndex++;
|
|
61
|
+
}
|
|
62
|
+
if (compareRolloutCandidates(candidate, child) <= 0) break;
|
|
63
|
+
this.heap[parentIndex] = child;
|
|
64
|
+
parentIndex = childIndex;
|
|
65
|
+
}
|
|
66
|
+
this.heap[parentIndex] = candidate;
|
|
67
|
+
}
|
|
68
|
+
finish() {
|
|
69
|
+
this.heap.sort((left, right) => compareRolloutCandidates(right, left));
|
|
70
|
+
return new Map(this.heap);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
/** Codex returns the plain logical path for either rollout representation. */
|
|
74
|
+
function codexCatalogRolloutLogicalPath(rolloutPath) {
|
|
75
|
+
return rolloutPath.replace(/\.zst$/u, "");
|
|
76
|
+
}
|
|
77
|
+
function resolveCodexCatalogRolloutFingerprint(rolloutPath, previous, files) {
|
|
78
|
+
const logicalPath = rolloutPath && codexCatalogRolloutLogicalPath(rolloutPath);
|
|
79
|
+
if (!logicalPath) return;
|
|
80
|
+
return files?.get(logicalPath) ?? files?.get(`${logicalPath}.zst`) ?? (previous?.rolloutPath && codexCatalogRolloutLogicalPath(previous.rolloutPath) === logicalPath ? previous.fingerprint : void 0);
|
|
81
|
+
}
|
|
82
|
+
function indexCodexCatalogRowsByRollout(rows) {
|
|
83
|
+
return new Map([...rows].flatMap((row) => row.rolloutPath ? [[codexCatalogRolloutLogicalPath(row.rolloutPath), row]] : []));
|
|
84
|
+
}
|
|
85
|
+
/** Absence is meaningful only inside the layout visited by the currency scan. */
|
|
86
|
+
function isCodexCatalogRolloutPathCovered(sessionsRoot, rolloutPath) {
|
|
87
|
+
const directories = path.relative(sessionsRoot, rolloutPath).split(path.sep);
|
|
88
|
+
const fileName = directories.pop();
|
|
89
|
+
return fileName !== void 0 && ROLLOUT_FILE_NAME.test(fileName) && directories.length === DIRECTORY_PARTS.length && directories.every((part, index) => DIRECTORY_PARTS[index]?.test(part) === true);
|
|
90
|
+
}
|
|
91
|
+
async function unlessMissing(operation) {
|
|
92
|
+
try {
|
|
93
|
+
return await operation;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (isRecord(error) && error.code === "ENOENT") return;
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** Stat-only currency scan. Content is read separately, only for changed fingerprints. */
|
|
100
|
+
async function scanCodexCatalogRollouts(sessionsRoot, trackedPaths) {
|
|
101
|
+
const present = /* @__PURE__ */ new Set();
|
|
102
|
+
const rootStat = await unlessMissing(fs.lstat(sessionsRoot));
|
|
103
|
+
if (!rootStat?.isDirectory() || rootStat.isSymbolicLink()) return {
|
|
104
|
+
files: /* @__PURE__ */ new Map(),
|
|
105
|
+
present
|
|
106
|
+
};
|
|
107
|
+
const rootReal = await unlessMissing(fs.realpath(sessionsRoot));
|
|
108
|
+
if (!rootReal) return {
|
|
109
|
+
files: /* @__PURE__ */ new Map(),
|
|
110
|
+
present
|
|
111
|
+
};
|
|
112
|
+
const candidates = new NewestRolloutCandidates();
|
|
113
|
+
const scan = async (directory, depth) => {
|
|
114
|
+
if (await unlessMissing(fs.realpath(directory)) !== directory) return;
|
|
115
|
+
const entries = await unlessMissing(fs.opendir(directory));
|
|
116
|
+
if (!entries) return;
|
|
117
|
+
const directoryPattern = DIRECTORY_PARTS[depth];
|
|
118
|
+
for await (const entry of entries) {
|
|
119
|
+
const file = path.join(directory, entry.name);
|
|
120
|
+
if (directoryPattern) {
|
|
121
|
+
if (entry.isDirectory() && directoryPattern.test(entry.name)) await scan(file, depth + 1);
|
|
122
|
+
} else if (entry.isFile() && ROLLOUT_FILE_NAME.test(entry.name)) {
|
|
123
|
+
const stat = await unlessMissing(fs.lstat(file));
|
|
124
|
+
if (stat?.isFile() && stat.nlink === 1) {
|
|
125
|
+
const physicalPath = path.join(sessionsRoot, path.relative(rootReal, file));
|
|
126
|
+
if (physicalPath.length > 4096) continue;
|
|
127
|
+
const logicalPath = codexCatalogRolloutLogicalPath(physicalPath);
|
|
128
|
+
if (trackedPaths.has(logicalPath)) present.add(logicalPath);
|
|
129
|
+
if (physicalPath !== logicalPath) {
|
|
130
|
+
const plain = await unlessMissing(fs.lstat(codexCatalogRolloutLogicalPath(file)));
|
|
131
|
+
if (plain?.isFile() && plain.nlink === 1) continue;
|
|
132
|
+
}
|
|
133
|
+
candidates.offer([detachCodexCatalogString(physicalPath), {
|
|
134
|
+
mtimeMs: stat.mtimeMs,
|
|
135
|
+
size: stat.size
|
|
136
|
+
}]);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
await scan(rootReal, 0);
|
|
142
|
+
return {
|
|
143
|
+
files: candidates.finish(),
|
|
144
|
+
present
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function records(bytes, skipFirst) {
|
|
148
|
+
const text = bytes.toString("utf8");
|
|
149
|
+
const lines = text.slice(0, text.lastIndexOf("\n") + 1).split("\n");
|
|
150
|
+
if (skipFirst) lines.shift();
|
|
151
|
+
return lines.flatMap((line) => {
|
|
152
|
+
try {
|
|
153
|
+
const value = JSON.parse(line);
|
|
154
|
+
return isRecord(value) ? [value] : [];
|
|
155
|
+
} catch {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function sourceFromMetadata(value) {
|
|
161
|
+
if (value === void 0) return "vscode";
|
|
162
|
+
if (value === "cli" || value === "vscode" || value === "exec") return value;
|
|
163
|
+
if (value === "mcp") return "appServer";
|
|
164
|
+
if (isRecord(value)) {
|
|
165
|
+
const custom = boundedCatalogString(value.custom, 500);
|
|
166
|
+
if (custom) return { custom };
|
|
167
|
+
}
|
|
168
|
+
return "unknown";
|
|
169
|
+
}
|
|
170
|
+
function previewFromEvent(payload, sanitize) {
|
|
171
|
+
let message;
|
|
172
|
+
let image = false;
|
|
173
|
+
let audio = false;
|
|
174
|
+
if (payload.type === "user_message") {
|
|
175
|
+
message = typeof payload.message === "string" ? payload.message : void 0;
|
|
176
|
+
image = [payload.images, payload.local_images].some((items) => Array.isArray(items) && items.length > 0);
|
|
177
|
+
audio = [payload.audio, payload.local_audio].some((items) => Array.isArray(items) && items.length > 0);
|
|
178
|
+
} else if (payload.type === "item_completed" && isRecord(payload.item) && payload.item.type === "UserMessage" && Array.isArray(payload.item.content)) {
|
|
179
|
+
const content = payload.item.content.filter(isRecord);
|
|
180
|
+
message = content.flatMap((item) => item.type === "text" && typeof item.text === "string" ? [item.text] : []).join("");
|
|
181
|
+
image = content.some((item) => item.type === "image" || item.type === "local_image");
|
|
182
|
+
audio = content.some((item) => item.type === "audio" || item.type === "local_audio");
|
|
183
|
+
}
|
|
184
|
+
const prefix = "## My request for Codex:";
|
|
185
|
+
if (message?.includes(prefix)) message = message.slice(message.indexOf(prefix) + 24);
|
|
186
|
+
return truncateCodexCatalogPreview(selectCodexCatalogPreviewInput(message ?? ""), sanitize) || (image ? "[Image]" : audio ? "[Audio]" : void 0);
|
|
187
|
+
}
|
|
188
|
+
async function compressedHead(handle, size) {
|
|
189
|
+
const input = Buffer.alloc(Math.min(size, WINDOW_BYTES));
|
|
190
|
+
const { bytesRead } = await handle.read(input, 0, input.length, 0);
|
|
191
|
+
const decoder = createZstdDecompress({
|
|
192
|
+
chunkSize: 16384,
|
|
193
|
+
params: { [constants.ZSTD_d_windowLogMax]: 25 }
|
|
194
|
+
});
|
|
195
|
+
decoder.end(input.subarray(0, bytesRead));
|
|
196
|
+
const timer = setTimeout(() => decoder.destroy(/* @__PURE__ */ new Error("Rollout read timed out")), 5e3);
|
|
197
|
+
const chunks = [];
|
|
198
|
+
let sizeRead = 0;
|
|
199
|
+
try {
|
|
200
|
+
for await (const chunk of decoder) {
|
|
201
|
+
const bounded = (Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)).subarray(0, WINDOW_BYTES - sizeRead);
|
|
202
|
+
chunks.push(bounded);
|
|
203
|
+
sizeRead += bounded.length;
|
|
204
|
+
if (sizeRead === WINDOW_BYTES) break;
|
|
205
|
+
}
|
|
206
|
+
return Buffer.concat(chunks);
|
|
207
|
+
} finally {
|
|
208
|
+
clearTimeout(timer);
|
|
209
|
+
decoder.destroy();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/** Background-only display projection; never reads an entire large rollout. */
|
|
213
|
+
async function readCodexCatalogRollout(sessionsRoot, rolloutPath) {
|
|
214
|
+
let opened;
|
|
215
|
+
try {
|
|
216
|
+
const rootStat = await fs.lstat(sessionsRoot);
|
|
217
|
+
if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) return;
|
|
218
|
+
opened = await (await root(sessionsRoot, {
|
|
219
|
+
hardlinks: "reject",
|
|
220
|
+
symlinks: "reject",
|
|
221
|
+
maxBytes: Number.MAX_SAFE_INTEGER
|
|
222
|
+
})).open(path.relative(sessionsRoot, rolloutPath));
|
|
223
|
+
const { handle, stat } = opened;
|
|
224
|
+
if (!stat.size) return;
|
|
225
|
+
const compressed = rolloutPath.endsWith(".zst");
|
|
226
|
+
const head = compressed ? await compressedHead(handle, stat.size) : Buffer.alloc(Math.min(stat.size, WINDOW_BYTES));
|
|
227
|
+
if (!compressed) await handle.read(head, 0, head.length, 0);
|
|
228
|
+
const first = records(head, false);
|
|
229
|
+
const envelope = records(head.subarray(0, head.indexOf(10) + 1), false)[0];
|
|
230
|
+
if (envelope?.type !== "session_meta" || !isRecord(envelope.payload)) return;
|
|
231
|
+
const metadata = envelope.payload;
|
|
232
|
+
const id = boundedCatalogString(metadata.id, 256);
|
|
233
|
+
const createdAt = typeof metadata.timestamp === "string" ? Date.parse(metadata.timestamp) : NaN;
|
|
234
|
+
if (!id || !Number.isFinite(createdAt)) return;
|
|
235
|
+
let tail = first;
|
|
236
|
+
if (!compressed && stat.size > head.length) {
|
|
237
|
+
const offset = Math.max(head.length, stat.size - WINDOW_BYTES);
|
|
238
|
+
const bytes = Buffer.alloc(stat.size - offset);
|
|
239
|
+
await handle.read(bytes, 0, bytes.length, offset);
|
|
240
|
+
tail = records(bytes, true);
|
|
241
|
+
}
|
|
242
|
+
const current = await handle.stat();
|
|
243
|
+
if (stat.size !== current.size || stat.mtimeMs !== current.mtimeMs) return;
|
|
244
|
+
const thread = {
|
|
245
|
+
id,
|
|
246
|
+
projectId: null,
|
|
247
|
+
path: detachCodexCatalogString(rolloutPath),
|
|
248
|
+
source: sourceFromMetadata(metadata.source),
|
|
249
|
+
createdAt: createdAt / 1e3,
|
|
250
|
+
updatedAt: stat.mtimeMs / 1e3,
|
|
251
|
+
cwd: boundedCatalogString(metadata.cwd, 4096),
|
|
252
|
+
originator: typeof metadata.originator === "string" && metadata.originator.length <= 500 ? detachCodexCatalogString(metadata.originator) : void 0,
|
|
253
|
+
sessionId: boundedCatalogString(metadata.session_id, 256)
|
|
254
|
+
};
|
|
255
|
+
const { sanitizeTerminalText } = await import("openclaw/plugin-sdk/text-chunking");
|
|
256
|
+
for (const record of first) if (record.type === "event_msg" && isRecord(record.payload)) {
|
|
257
|
+
const preview = previewFromEvent(record.payload, sanitizeTerminalText);
|
|
258
|
+
if (preview) {
|
|
259
|
+
thread.preview = preview;
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
for (const record of tail === first ? first : [...first, ...tail]) {
|
|
264
|
+
if (record.type !== "event_msg" || !isRecord(record.payload)) continue;
|
|
265
|
+
const payload = record.payload;
|
|
266
|
+
if (payload.type === "task_started" || payload.type === "turn_started") {
|
|
267
|
+
const startedAt = typeof payload.started_at === "number" ? payload.started_at : typeof record.timestamp === "string" ? Date.parse(record.timestamp) / 1e3 : NaN;
|
|
268
|
+
if (Number.isFinite(startedAt)) thread.recencyAt = Math.max(thread.recencyAt ?? Number.NEGATIVE_INFINITY, Math.floor(startedAt));
|
|
269
|
+
}
|
|
270
|
+
if (payload.type === "thread_settings_applied" && isRecord(payload.thread_settings)) thread.cwd = boundedCatalogString(payload.thread_settings.cwd, 4096) ?? thread.cwd;
|
|
271
|
+
}
|
|
272
|
+
return thread;
|
|
273
|
+
} catch (error) {
|
|
274
|
+
const code = extractErrorCode(error);
|
|
275
|
+
if (code && ROLLOUT_SOURCE_DENIAL_CODES.has(code)) return;
|
|
276
|
+
throw error;
|
|
277
|
+
} finally {
|
|
278
|
+
await opened?.handle.close().catch(() => void 0);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
//#endregion
|
|
282
|
+
//#region extensions/codex/src/session-catalog-projection.ts
|
|
283
|
+
/** Single-thread responses remain owned by their native consumers. */
|
|
284
|
+
function projectCodexCatalogThread(thread, localSessionsRoot) {
|
|
285
|
+
try {
|
|
286
|
+
const prepared = projectCodexCatalogNativeThread(thread, sanitizeTerminalText);
|
|
287
|
+
return projectCodexCatalogPage({ data: [prepared] }, {
|
|
288
|
+
localSessionsRoot,
|
|
289
|
+
sanitize: sanitizeTerminalText,
|
|
290
|
+
source: getCodexCatalogSource(prepared)
|
|
291
|
+
});
|
|
292
|
+
} catch (error) {
|
|
293
|
+
return Promise.reject(toErrorObject(error, "Codex catalog projection failed"));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
var CodexCatalogProjectionCapacityError = class extends Error {
|
|
297
|
+
constructor() {
|
|
298
|
+
super("Codex catalog projection queue reached its resident row limit");
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
/** Direct mutations and events share one bound across asynchronous projection work. */
|
|
302
|
+
var CodexCatalogProjections = class {
|
|
303
|
+
constructor() {
|
|
304
|
+
this.active = 0;
|
|
305
|
+
}
|
|
306
|
+
run(work) {
|
|
307
|
+
if (this.active >= 2e4) return Promise.reject(new CodexCatalogProjectionCapacityError());
|
|
308
|
+
this.active++;
|
|
309
|
+
try {
|
|
310
|
+
return work().finally(() => {
|
|
311
|
+
this.active--;
|
|
312
|
+
});
|
|
313
|
+
} catch (error) {
|
|
314
|
+
this.active--;
|
|
315
|
+
return Promise.reject(toErrorObject(error, "Codex catalog projection failed"));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
async function projectCodexCatalogPage(response, params) {
|
|
320
|
+
const { diagnostics, sanitize } = params;
|
|
321
|
+
const responseStarted = performance.now();
|
|
322
|
+
const rows = [];
|
|
323
|
+
const excludedThreadIds = [];
|
|
324
|
+
try {
|
|
325
|
+
readControlCursor(response.backwardsCursor, "backwards response");
|
|
326
|
+
for (const thread of response.data) if (typeof thread.preview === "string" && thread.preview) thread.preview = truncateCodexCatalogPreview(selectCodexCatalogPreviewInput(thread.preview), sanitize);
|
|
327
|
+
for (const thread of response.data) {
|
|
328
|
+
if (thread.ephemeral === true) {
|
|
329
|
+
excludedThreadIds.push(thread.id);
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
const page = { sessions: [] };
|
|
333
|
+
if (await isOpenClawManagedCodexThread(thread, params.localSessionsRoot, diagnostics ?? void 0)) {
|
|
334
|
+
const rolloutPath = typeof thread.path === "string" ? thread.path.trim() : "";
|
|
335
|
+
page.managedThreads = [{
|
|
336
|
+
threadId: thread.id,
|
|
337
|
+
...rolloutPath ? { rolloutPath } : {}
|
|
338
|
+
}];
|
|
339
|
+
} else {
|
|
340
|
+
const session = toCatalogSession(thread, false, sanitize, { value: typeof thread.preview === "string" ? thread.preview : void 0 });
|
|
341
|
+
if (session) page.sessions.push(session);
|
|
342
|
+
}
|
|
343
|
+
rows.push(setCodexCatalogSource({
|
|
344
|
+
threadId: thread.id,
|
|
345
|
+
archived: false,
|
|
346
|
+
nativeMetadata: true,
|
|
347
|
+
...typeof thread.preview === "string" ? { preview: thread.preview } : {},
|
|
348
|
+
...thread.path ? { rolloutPath: thread.path } : {},
|
|
349
|
+
updatedAt: asFiniteNumber(thread.updatedAt) ?? null,
|
|
350
|
+
recencyAt: asFiniteNumber(thread.recencyAt) ?? null,
|
|
351
|
+
page
|
|
352
|
+
}, params.source ?? getCodexCatalogSource(thread)));
|
|
353
|
+
}
|
|
354
|
+
return {
|
|
355
|
+
rows,
|
|
356
|
+
...excludedThreadIds.length ? { excludedThreadIds } : {},
|
|
357
|
+
nextCursor: readControlCursor(response.nextCursor, "next response"),
|
|
358
|
+
backwardsCursor: readControlCursor(response.backwardsCursor, "backwards response")
|
|
359
|
+
};
|
|
360
|
+
} finally {
|
|
361
|
+
if (diagnostics) diagnostics.fields.postResponseMs = (diagnostics.fields.postResponseMs ?? 0) + performance.now() - responseStarted;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/** Native activity/path changes invalidate the retained first-user preview. */
|
|
365
|
+
function canReuseCodexCatalogPreview(row, thread) {
|
|
366
|
+
return Boolean(row && !row.archived && row.updatedAt === (asFiniteNumber(thread.updatedAt) ?? null) && row.recencyAt === (asFiniteNumber(thread.recencyAt) ?? null) && (row.rolloutPath ? codexCatalogRolloutLogicalPath(row.rolloutPath) : void 0) === (thread.path ? codexCatalogRolloutLogicalPath(thread.path) : void 0));
|
|
367
|
+
}
|
|
368
|
+
async function projectCodexCatalogDeltaPage(response, params) {
|
|
369
|
+
const reusable = response.data.map((thread) => {
|
|
370
|
+
const row = params.getRow(thread.id);
|
|
371
|
+
if (thread.ephemeral === true || !row || !canReuseCodexCatalogPreview(row, thread)) return;
|
|
372
|
+
if (row.page.sessions.length === 0) return copyCodexCatalogSource(thread, {
|
|
373
|
+
...row,
|
|
374
|
+
nativeMetadata: true
|
|
375
|
+
});
|
|
376
|
+
if (typeof thread.preview === "string" && Boolean(thread.preview) !== Boolean(row.preview)) return;
|
|
377
|
+
const session = toCatalogSession(thread, false, params.sanitize, { value: row.preview });
|
|
378
|
+
return copyCodexCatalogSource(thread, {
|
|
379
|
+
...row,
|
|
380
|
+
nativeMetadata: true,
|
|
381
|
+
page: { sessions: session ? [session] : [] }
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
const changed = await projectCodexCatalogPage({
|
|
385
|
+
...response,
|
|
386
|
+
data: response.data.filter((_thread, index) => !reusable[index])
|
|
387
|
+
}, params);
|
|
388
|
+
let changedIndex = 0;
|
|
389
|
+
return {
|
|
390
|
+
...changed,
|
|
391
|
+
rows: reusable.flatMap((row, index) => response.data[index]?.ephemeral === true ? [] : [row ?? changed.rows[changedIndex++]])
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
/** Sampled rollout content cannot supersede authoritative native settings. */
|
|
395
|
+
function mergeCodexCatalogRolloutRow(row, existing, fingerprint) {
|
|
396
|
+
const recencyAt = row.recencyAt === null ? existing?.recencyAt ?? null : Math.max(row.recencyAt, existing?.recencyAt ?? row.recencyAt);
|
|
397
|
+
const metadata = existing?.nativeMetadata ? existing : row;
|
|
398
|
+
const preview = row.preview ?? metadata.preview;
|
|
399
|
+
const sessions = metadata.page.sessions.map((session) => {
|
|
400
|
+
const updated = Object.assign({}, session);
|
|
401
|
+
delete updated.fallbackName;
|
|
402
|
+
if (!session.name && preview) updated.fallbackName = preview;
|
|
403
|
+
if (recencyAt !== null) updated.recencyAt = recencyAt;
|
|
404
|
+
return updated;
|
|
405
|
+
});
|
|
406
|
+
const merged = {
|
|
407
|
+
...metadata,
|
|
408
|
+
nativeMetadata: existing?.nativeMetadata ?? false,
|
|
409
|
+
archived: existing?.archived ?? false,
|
|
410
|
+
recencyAt,
|
|
411
|
+
fingerprint,
|
|
412
|
+
...preview !== void 0 ? { preview } : {},
|
|
413
|
+
page: {
|
|
414
|
+
...metadata.page,
|
|
415
|
+
sessions
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
if (existing && codexCatalogRowRecency(merged) > codexCatalogRowRecency(existing)) delete merged.sourceOrder;
|
|
419
|
+
return merged;
|
|
420
|
+
}
|
|
421
|
+
//#endregion
|
|
422
|
+
export { CodexCatalogProjectionCapacityError, CodexCatalogProjections, resolveCodexCatalogRolloutFingerprint as a, canReuseCodexCatalogPreview, readCodexCatalogRollout as i, mergeCodexCatalogRolloutRow, indexCodexCatalogRowsByRollout as n, scanCodexCatalogRollouts as o, projectCodexCatalogDeltaPage, projectCodexCatalogPage, projectCodexCatalogThread, isCodexCatalogRolloutPathCovered as r, codexCatalogRolloutLogicalPath as t };
|