@openclaw/codex 2026.8.1-beta.3 → 2026.8.2
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/api.js +5 -6
- package/dist/{attempt-client-cleanup-URjUlCHg.js → attempt-client-cleanup-CpVfwctT.js} +47 -5
- package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
- package/dist/{binding-connection-DAvZwp96.js → binding-connection-CF7BmrDk.js} +2 -2
- package/dist/{bounded-turn-4BjrZEwW.js → bounded-turn-DRC3hcjm.js} +16 -20
- package/dist/{capabilities-CH3K57v4.js → capabilities-D6m_TdVy.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-D0nZ3qtd.js → command-formatters--UToCokS.js} +4 -3
- package/dist/{command-handlers-DC86lgT4.js → command-handlers-CLFx2Ypa.js} +114 -79
- package/dist/{compact-COqgBRny.js → compact-5xqW1oCh.js} +13 -12
- package/dist/{config-CpNeo5AE.js → config-CcYL77O6.js} +350 -288
- package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
- package/dist/doctor-contract-api.js +121 -16
- package/dist/{dynamic-tools-fJZhl4CE.js → dynamic-tools-BmeXjwNZ.js} +243 -1002
- package/dist/{effective-mcp-catalog-4YKn51aG.js → effective-mcp-catalog-XXQKgK1U.js} +2 -2
- package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
- package/dist/{event-projector-usage-CLwNEJqW.js → event-projector-usage-B2r5vhWH.js} +9 -14
- package/dist/{harness-DoKQcF8n.js → harness-BgeB7LnD.js} +42 -52
- package/dist/harness.js +1 -1
- package/dist/index.js +308 -306
- package/dist/{isolated-completion-DPMtlH9r.js → isolated-completion-CxTus3vZ.js} +4 -4
- package/dist/launch-args-sXOAg0SX.js +84 -0
- package/dist/{managed-binary-By4FZC6i.js → managed-binary-ZkGodW19.js} +43 -7
- package/dist/media-understanding-provider.js +1 -1
- package/dist/model-catalog-DULBcniB.js +101 -0
- package/dist/{models-CZw1wClT.js → models-DaWfETQk.js} +27 -29
- package/dist/{native-subagent-monitor-GGq3RnOo.js → native-subagent-monitor-vXYUZH37.js} +226 -129
- package/dist/{node-exec-server.runtime-Bsu1LdFZ.js → node-exec-server.runtime-DirKVZ5h.js} +9 -6
- package/dist/{plugin-approval-roundtrip-C75Yiiwc.js → plugin-approval-roundtrip-CCWQGlAI.js} +2 -1
- package/dist/{plugin-marketplace-discovery-CSWDkMrP.js → plugin-marketplace-discovery-BXjIFEiw.js} +38 -46
- package/dist/{plugin-metadata-cache-BXH5NF-4.js → plugin-metadata-cache-DQQm4gWT.js} +163 -136
- package/dist/{protocol-validators-VAVyEnDp.js → protocol-validators-Bg5rpNxk.js} +148 -5
- package/dist/{rate-limits-BI1dMHDG.js → rate-limits-BqHEHXQJ.js} +3 -2
- package/dist/{sandbox-guard-C1qEeZ5C.js → request-BWxweEdK.js} +183 -2
- package/dist/{run-attempt-BV3HzuCf.js → run-attempt-BVLE4Gbi.js} +706 -517
- package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-D9pYp4zL.js} +3 -3
- package/dist/{session-binding-BTrLf9Qm.js → session-binding-D0zinCP1.js} +195 -122
- package/dist/{session-catalog-ezP_UcRM.js → session-catalog-eMhVm0Ql.js} +448 -313
- package/dist/session-catalog-home-id-Dt2GiG5o.js +112 -0
- package/dist/{session-cli-B1hKvfkI.js → session-cli-B2lyjJA0.js} +1 -1
- package/dist/session-history-C5J1AKzG.js +87 -0
- package/dist/session-permission-policy-ScnAyG90.js +160 -0
- package/dist/session-retirement-CtUtUTr9.js +90 -0
- package/dist/{session-upstream-marker-D_2npHlA.js → session-upstream-marker-gqrYIRHk.js} +2 -3
- package/dist/settled-turn-context-Bk3IUwod.js +290 -0
- package/dist/settled-turn-finalizer-BXLN9PfJ.js +104 -0
- package/dist/{shared-client-Dw-rzii0.js → shared-client-B1tT5U6r.js} +1738 -806
- package/dist/{side-question-DbXkJZzg.js → side-question-CZ-mCw-t.js} +76 -43
- package/dist/{thread-lifecycle-DKdrnTMX.js → thread-lifecycle-CGGKP720.js} +991 -455
- package/dist/{thread-ownership-i2NBwDUL.js → thread-ownership-RkaoZCmQ.js} +18 -8
- package/dist/{plugin-app-cache-key-DMNQ8Zi8.js → thread-resume-BFt1-ZDa.js} +55 -8
- package/dist/{transcript-mirror-BU0_LKAL.js → transcript-mirror-1ep4XjzF.js} +124 -18
- package/dist/transport-stdio-NT_Dpd9V.js +724 -0
- package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
- package/dist/{upstream-session-fork-BDVJCLAD.js → upstream-session-fork-Dc8BFExw.js} +76 -90
- package/dist/{usage-9dKJCgcy.js → usage-DUhd58gI.js} +3 -3
- package/dist/{web-search-provider.runtime-DCdx4DGu.js → web-search-provider.runtime-BEmlE7ov.js} +3 -3
- package/openclaw.plugin.json +19 -1
- package/package.json +8 -8
- package/dist/app-server-policy-bg5QPSVP.js +0 -25
- package/dist/command-rpc-xUIIonsO.js +0 -90
- package/dist/incognito-session-ET_ufDH-.js +0 -2
- package/dist/model-catalog-CmGoqVKB.js +0 -48
- package/dist/request-DSK0W6YI.js +0 -157
- package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
- package/dist/session-retirement-CE4iMiLh.js +0 -36
- package/dist/settled-turn-finalizer-Dx1onIqg.js +0 -328
- package/dist/thread-resume-CdJk2Ehf.js +0 -30
- package/dist/transport-stdio-DhoGy33Z.js +0 -99
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as closeCodexStartupClientBestEffort,
|
|
1
|
+
import { Ct as retainCodexAppServerLiveThread, St as releaseCodexAppServerLiveThread, _ as retainSharedCodexAppServerClientByInstanceId, bt as isCodexAppServerLiveThreadClaimed } from "./shared-client-B1tT5U6r.js";
|
|
2
|
+
import { a as closeCodexStartupClientBestEffort, f as unsubscribeCodexThreadBestEffort, r as CodexAppServerUnsafeSubscriptionError } from "./attempt-client-cleanup-CpVfwctT.js";
|
|
3
|
+
import { isIncognitoSessionKey } from "openclaw/plugin-sdk/routing";
|
|
3
4
|
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
4
5
|
//#region extensions/codex/src/app-server/thread-ownership.ts
|
|
5
6
|
const nativeThreadOwners = new KeyedAsyncQueue();
|
|
7
|
+
/** Serialize connection-scoped unsubscribe with attach/resume of the same native thread. */
|
|
8
|
+
async function withCodexAppServerThreadMutation(threadId, run) {
|
|
9
|
+
return await nativeThreadOwners.enqueue(`thread:${threadId}`, run);
|
|
10
|
+
}
|
|
6
11
|
/** Codex subscriptions belong to a physical connection, not the native thread ID alone. */
|
|
7
12
|
function isSameCodexAppServerThreadOwner(current, expected) {
|
|
8
13
|
return current !== void 0 && expected !== void 0 && current.threadId === expected.threadId && current.clientId === expected.clientId;
|
|
9
14
|
}
|
|
10
15
|
/** Fences native subscription and commit together; Codex subscriptions are not reference-counted. */
|
|
11
16
|
async function withExclusiveCodexAppServerThread(params) {
|
|
12
|
-
return await
|
|
17
|
+
return await withCodexAppServerThreadMutation(params.threadId, async () => {
|
|
13
18
|
if (await params.bindingStore.hasOtherThreadOwner(params.threadId, params.identity)) throw new Error(`Codex thread ${params.threadId} is owned by another OpenClaw session or conversation.`);
|
|
14
19
|
return await params.run();
|
|
15
20
|
});
|
|
@@ -20,11 +25,13 @@ async function withCodexConversationThreadActivity(bindingId, run) {
|
|
|
20
25
|
}
|
|
21
26
|
/** Publishes one owned persistent subscription into the shared bounded idle registry. */
|
|
22
27
|
async function retainCodexAppServerBindingSubscription(client, threadId, ownership) {
|
|
23
|
-
return await retainCodexAppServerLiveThread(client, threadId, ownership?.release ?? (async (releasedThreadId) => {
|
|
28
|
+
return await retainCodexAppServerLiveThread(client, threadId, ownership?.release ?? (async (releasedThreadId, assertCurrent) => {
|
|
24
29
|
if (!await unsubscribeCodexThreadBestEffort(client, {
|
|
25
30
|
threadId: releasedThreadId,
|
|
26
|
-
timeoutMs: 5e3
|
|
31
|
+
timeoutMs: 5e3,
|
|
32
|
+
assertCurrent
|
|
27
33
|
})) {
|
|
34
|
+
assertCurrent?.();
|
|
28
35
|
await closeCodexStartupClientBestEffort(client);
|
|
29
36
|
throw new CodexAppServerUnsafeSubscriptionError(`Codex thread subscription could not be released: ${releasedThreadId}`);
|
|
30
37
|
}
|
|
@@ -41,15 +48,18 @@ async function rollbackCodexAppServerBindingSubscription(client, threadId, retai
|
|
|
41
48
|
}
|
|
42
49
|
/** Releases only the physical client and native thread recorded by the displaced binding owner. */
|
|
43
50
|
async function releaseCodexAppServerBindingSubscription(binding, options = {}) {
|
|
51
|
+
options.assertCurrent?.();
|
|
44
52
|
const clientLease = retainSharedCodexAppServerClientByInstanceId(binding.clientId);
|
|
45
53
|
if (!clientLease) return;
|
|
46
54
|
try {
|
|
47
|
-
if (await releaseCodexAppServerLiveThread(clientLease.client, binding.threadId)) return;
|
|
55
|
+
if (await releaseCodexAppServerLiveThread(clientLease.client, binding.threadId, options.assertCurrent)) return;
|
|
56
|
+
options.assertCurrent?.();
|
|
48
57
|
if (isCodexAppServerLiveThreadClaimed(clientLease.client, binding.threadId)) throw new Error(`Codex thread ${binding.threadId} has an active run; stop it before changing its owner.`);
|
|
49
58
|
if (!options.allowUntracked) return;
|
|
50
59
|
if (!await unsubscribeCodexThreadBestEffort(clientLease.client, {
|
|
51
60
|
threadId: binding.threadId,
|
|
52
|
-
timeoutMs: 5e3
|
|
61
|
+
timeoutMs: 5e3,
|
|
62
|
+
assertCurrent: options.assertCurrent
|
|
53
63
|
})) {
|
|
54
64
|
await closeCodexStartupClientBestEffort(clientLease.client);
|
|
55
65
|
throw new CodexAppServerUnsafeSubscriptionError(`Codex retired thread subscription could not be released: ${binding.threadId}`);
|
|
@@ -89,4 +99,4 @@ async function retireCodexConversationThreadBinding(params) {
|
|
|
89
99
|
});
|
|
90
100
|
}
|
|
91
101
|
//#endregion
|
|
92
|
-
export { rollbackCodexAppServerBindingSubscription as a, retireCodexConversationThreadBinding as i, releaseCodexAppServerBindingSubscription as n,
|
|
102
|
+
export { rollbackCodexAppServerBindingSubscription as a, withExclusiveCodexAppServerThread as c, retireCodexConversationThreadBinding as i, isIncognitoSessionKey as l, releaseCodexAppServerBindingSubscription as n, withCodexAppServerThreadMutation as o, retainCodexAppServerBindingSubscription as r, withCodexConversationThreadActivity as s, isSameCodexAppServerThreadOwner as t };
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { F as resolveCodexAppServerLocalHomeDir, I as resolveCodexAppServerUserHomeDir, P as resolveCodexAppServerHomeDir } from "./config-CcYL77O6.js";
|
|
2
|
+
import { $ as CodexAppServerRpcError, J as isCodexAppServerOverloadError, P as isCodexAppServerStartupError, Y as isCodexAppServerPrewriteRequestCancellationError, u as isCodexAppServerStartSelectionChangedError } from "./shared-client-B1tT5U6r.js";
|
|
3
|
+
import { o as assertCodexThreadResumeResponse } from "./protocol-validators-Bg5rpNxk.js";
|
|
4
|
+
import { f as unsubscribeCodexThreadBestEffort, i as assertCodexThreadResumeSubscription, r as CodexAppServerUnsafeSubscriptionError } from "./attempt-client-cleanup-CpVfwctT.js";
|
|
5
|
+
import { t as CodexAppServerScopedRequestRejectedError } from "./request-BWxweEdK.js";
|
|
3
6
|
import { createRequire } from "node:module";
|
|
4
7
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
8
|
import { readPluginPackageVersion } from "openclaw/plugin-sdk/extension-shared";
|
|
@@ -13,7 +16,7 @@ import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
|
13
16
|
* identity and safe to refresh in the background.
|
|
14
17
|
*/
|
|
15
18
|
/** Default app inventory cache freshness window. */
|
|
16
|
-
const CODEX_APP_INVENTORY_CACHE_TTL_MS =
|
|
19
|
+
const CODEX_APP_INVENTORY_CACHE_TTL_MS = 36e5;
|
|
17
20
|
const CODEX_APP_READ_BATCH_LIMIT = 100;
|
|
18
21
|
const MAX_SERIALIZED_ERROR_MESSAGE_LENGTH = 500;
|
|
19
22
|
/** In-memory app inventory cache with coalesced refreshes per key. */
|
|
@@ -264,7 +267,10 @@ async function readInstalledApps(request, options) {
|
|
|
264
267
|
apps: [],
|
|
265
268
|
installedApps: []
|
|
266
269
|
};
|
|
267
|
-
const metadataResponses = await Promise.all(Array.from({ length: Math.ceil(apps.length / CODEX_APP_READ_BATCH_LIMIT) }, (_, index) => request("app/read", {
|
|
270
|
+
const metadataResponses = await Promise.all(Array.from({ length: Math.ceil(apps.length / CODEX_APP_READ_BATCH_LIMIT) }, (_, index) => request("app/read", {
|
|
271
|
+
appIds: apps.slice(index * CODEX_APP_READ_BATCH_LIMIT, (index + 1) * CODEX_APP_READ_BATCH_LIMIT).map((app) => app.id),
|
|
272
|
+
includeTools: true
|
|
273
|
+
})));
|
|
268
274
|
const metadataById = new Map(metadataResponses.flatMap((response) => response.apps).map((metadata) => [metadata.id, metadata]));
|
|
269
275
|
return {
|
|
270
276
|
apps: apps.flatMap((installedApp) => {
|
|
@@ -283,7 +289,8 @@ async function readInstalledApps(request, options) {
|
|
|
283
289
|
installUrl: metadata.installUrl ?? null,
|
|
284
290
|
isAccessible: true,
|
|
285
291
|
isEnabled: installedApp.enabled,
|
|
286
|
-
pluginDisplayNames: metadata.pluginDisplayNames
|
|
292
|
+
pluginDisplayNames: metadata.pluginDisplayNames,
|
|
293
|
+
...metadata.toolSummaries ? { toolSummaries: metadata.toolSummaries } : {}
|
|
287
294
|
}];
|
|
288
295
|
}),
|
|
289
296
|
installedApps: apps
|
|
@@ -330,7 +337,8 @@ function isSensitiveErrorDataKey(key) {
|
|
|
330
337
|
* Builds stable Codex plugin/app inventory cache keys from app-server startup,
|
|
331
338
|
* auth, account, and version inputs without storing secret material.
|
|
332
339
|
*/
|
|
333
|
-
const
|
|
340
|
+
const require = createRequire(import.meta.url);
|
|
341
|
+
const CODEX_PLUGIN_VERSION = readPluginPackageVersion({ require });
|
|
334
342
|
let catalogConnectionHomes = /* @__PURE__ */ new Map();
|
|
335
343
|
function catalogConnectionHomeKey(fingerprint, agentDir) {
|
|
336
344
|
return `${agentDir ?? ""}\0${fingerprint}`;
|
|
@@ -348,7 +356,10 @@ function buildCodexPluginAppCacheKey(params) {
|
|
|
348
356
|
accountId: params.accountId,
|
|
349
357
|
envApiKeyFingerprint: params.envApiKeyFingerprint,
|
|
350
358
|
appServerVersion: params.appServerVersion ?? params.runtimeIdentity?.serverVersion,
|
|
351
|
-
runtimeIdentity: params.
|
|
359
|
+
runtimeIdentity: params.desktopGenerationFingerprint ? {
|
|
360
|
+
...params.runtimeIdentity,
|
|
361
|
+
desktopGeneration: params.desktopGenerationFingerprint
|
|
362
|
+
} : params.runtimeIdentity
|
|
352
363
|
}, OPENCLAW_VERSION, CODEX_PLUGIN_VERSION);
|
|
353
364
|
}
|
|
354
365
|
/** Builds a durable thread-binding fingerprint for one initialized app-server runtime. */
|
|
@@ -417,4 +428,40 @@ function fingerprintCodexPluginAppCacheCredentials(startOptions) {
|
|
|
417
428
|
return `sha256:${hash.digest("hex")}`;
|
|
418
429
|
}
|
|
419
430
|
//#endregion
|
|
420
|
-
|
|
431
|
+
//#region extensions/codex/src/app-server/thread-resume.ts
|
|
432
|
+
/** Owns Codex thread/resume subscription safety. */
|
|
433
|
+
/** Resumes one thread, releasing or isolating every possible native subscription. */
|
|
434
|
+
async function resumeCodexAppServerThread(params) {
|
|
435
|
+
const threadId = params.request.threadId;
|
|
436
|
+
let response;
|
|
437
|
+
try {
|
|
438
|
+
response = assertCodexThreadResumeResponse(await (params.requestResume ? params.requestResume(params.request) : params.client.request("thread/resume", params.request, {
|
|
439
|
+
...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
|
|
440
|
+
...params.signal ? { signal: params.signal } : {},
|
|
441
|
+
assertCurrent: params.assertCurrent
|
|
442
|
+
})));
|
|
443
|
+
assertCodexThreadResumeSubscription(threadId, response.thread.id);
|
|
444
|
+
} catch (error) {
|
|
445
|
+
if (params.isPrewriteOwnershipError?.(error) || isCodexAppServerStartSelectionChangedError(error) || isCodexAppServerStartupError(error) || error instanceof CodexAppServerScopedRequestRejectedError || isCodexAppServerPrewriteRequestCancellationError(error) || isCodexAppServerOverloadError(error)) throw error;
|
|
446
|
+
if (error instanceof CodexAppServerRpcError) {
|
|
447
|
+
if (await unsubscribeCodexThreadBestEffort(params.client, {
|
|
448
|
+
threadId,
|
|
449
|
+
timeoutMs: 5e3,
|
|
450
|
+
assertCurrent: params.assertCurrent
|
|
451
|
+
}).catch(() => false)) {
|
|
452
|
+
params.onSubscriptionReleased?.();
|
|
453
|
+
throw error;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
try {
|
|
457
|
+
await params.abandonClient();
|
|
458
|
+
} catch (abandonError) {
|
|
459
|
+
throw new CodexAppServerUnsafeSubscriptionError(`Codex thread/resume client could not be retired for ${threadId}`, { cause: abandonError });
|
|
460
|
+
}
|
|
461
|
+
if (error instanceof CodexAppServerUnsafeSubscriptionError) throw error;
|
|
462
|
+
throw new CodexAppServerUnsafeSubscriptionError(error instanceof Error ? error.message : `Codex thread/resume outcome is indeterminate for ${threadId}`, { cause: error });
|
|
463
|
+
}
|
|
464
|
+
return response;
|
|
465
|
+
}
|
|
466
|
+
//#endregion
|
|
467
|
+
export { replaceCodexCatalogConnectionHomes as a, serializeCodexAppInventoryError as c, buildCodexPluginAppCacheKey as i, buildCodexAppServerConnectionFingerprint as n, resolveCodexCatalogConnectionHome as o, buildCodexAppServerRuntimeFingerprint as r, defaultCodexAppInventoryCache as s, resumeCodexAppServerThread as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as readUpstreamUserText, n as attachUpstreamUserText, r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-
|
|
1
|
+
import { i as readUpstreamUserText, n as attachUpstreamUserText, r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-LphB8slG.js";
|
|
2
2
|
import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
-
import { embeddedAgentLog, formatErrorMessage, projectAgentHarnessTranscriptMessageForDisplay, runAgentHarnessBeforeMessageWriteHook } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
3
|
+
import { deliverAgentHarnessUserInputPrompt, embeddedAgentLog, formatErrorMessage, projectAgentHarnessTranscriptMessageForDisplay, runAgentHarnessBeforeMessageWriteHook } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
import { truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
6
6
|
import { withCodexSessionTranscriptMirrorWriteLock } from "openclaw/plugin-sdk/codex-session-transcript-runtime";
|
|
@@ -8,8 +8,8 @@ import { publishSessionTranscriptUpdateByIdentity } from "openclaw/plugin-sdk/se
|
|
|
8
8
|
import { Buffer } from "node:buffer";
|
|
9
9
|
//#region extensions/codex/src/app-server/transcript-history-projection.ts
|
|
10
10
|
const CODEX_HISTORY_IMPORT_MAX_MESSAGES = 200;
|
|
11
|
-
const CODEX_HISTORY_IMPORT_MAX_BYTES =
|
|
12
|
-
const CODEX_HISTORY_IMPORT_MAX_MESSAGE_BYTES =
|
|
11
|
+
const CODEX_HISTORY_IMPORT_MAX_BYTES = 524288;
|
|
12
|
+
const CODEX_HISTORY_IMPORT_MAX_MESSAGE_BYTES = 65536;
|
|
13
13
|
const CODEX_HISTORY_TRUNCATION_SUFFIX = "\n\n[Message truncated during Codex history import.]";
|
|
14
14
|
const CODEX_HISTORY_ASSISTANT_API = "openai-chatgpt-responses";
|
|
15
15
|
const CODEX_HISTORY_ASSISTANT_PROVIDER = "openai";
|
|
@@ -34,7 +34,8 @@ function normalizeImportedHistoryText(value) {
|
|
|
34
34
|
if (!text) return;
|
|
35
35
|
if (Buffer.byteLength(text, "utf8") <= CODEX_HISTORY_IMPORT_MAX_MESSAGE_BYTES) return text;
|
|
36
36
|
const suffixBytes = Buffer.byteLength(CODEX_HISTORY_TRUNCATION_SUFFIX, "utf8");
|
|
37
|
-
|
|
37
|
+
const contentLimitBytes = Math.max(0, CODEX_HISTORY_IMPORT_MAX_MESSAGE_BYTES - suffixBytes);
|
|
38
|
+
return `${truncateUtf8Prefix(text, contentLimitBytes)}${CODEX_HISTORY_TRUNCATION_SUFFIX}`;
|
|
38
39
|
}
|
|
39
40
|
function projectCodexUserItemText(item) {
|
|
40
41
|
if (!Array.isArray(item.content)) return;
|
|
@@ -82,6 +83,8 @@ function projectCodexThreadHistory(params) {
|
|
|
82
83
|
const role = item.type === "userMessage" ? "user" : item.type === "agentMessage" ? "assistant" : void 0;
|
|
83
84
|
itemOffset += 1;
|
|
84
85
|
if (!text || !role) continue;
|
|
86
|
+
const phase = item.phase === "commentary" || item.phase === "final_answer" ? item.phase : void 0;
|
|
87
|
+
const asyncDelivery = item.delivery === "async";
|
|
85
88
|
const message = role === "assistant" ? attachCodexMirrorIdentity({
|
|
86
89
|
role,
|
|
87
90
|
content: [{
|
|
@@ -94,13 +97,14 @@ function projectCodexThreadHistory(params) {
|
|
|
94
97
|
usage: CODEX_HISTORY_ZERO_USAGE,
|
|
95
98
|
stopReason: turn.status === "interrupted" ? "aborted" : turn.status === "failed" ? "error" : "stop",
|
|
96
99
|
...turn.status === "failed" && turn.error?.message ? { errorMessage: turn.error.message } : {},
|
|
100
|
+
...phase ? { phase } : {},
|
|
101
|
+
...asyncDelivery && itemId ? { openclawAsyncDelivery: { itemId } } : {},
|
|
97
102
|
timestamp
|
|
98
103
|
}, identity) : attachCodexMirrorIdentity({
|
|
99
104
|
role,
|
|
100
105
|
content: text,
|
|
101
106
|
timestamp
|
|
102
107
|
}, identity);
|
|
103
|
-
const phase = item.phase === "commentary" || item.phase === "final_answer" ? item.phase : void 0;
|
|
104
108
|
projected.push({
|
|
105
109
|
message,
|
|
106
110
|
responseItem: {
|
|
@@ -141,7 +145,7 @@ function projectBoundedCodexThreadHistory(params) {
|
|
|
141
145
|
return {
|
|
142
146
|
importedMessages: selected.length,
|
|
143
147
|
omittedMessages: projected.length - selected.length,
|
|
144
|
-
responseItems: selected.filter(({ message }) => message.role !== "assistant" || message.stopReason !== "aborted" && message.stopReason !== "error").map(({ responseItem }) => responseItem),
|
|
148
|
+
responseItems: selected.filter(({ message }) => message.role !== "assistant" || message.stopReason !== "aborted" && message.stopReason !== "error" && !("openclawAsyncDelivery" in message)).map(({ responseItem }) => responseItem),
|
|
145
149
|
transcriptMessages: selected.map(({ message }) => message)
|
|
146
150
|
};
|
|
147
151
|
}
|
|
@@ -150,7 +154,7 @@ function projectBoundedCodexVisibleSessionHistory(entries) {
|
|
|
150
154
|
const projected = [];
|
|
151
155
|
for (const entry of entries) {
|
|
152
156
|
if (entry.role !== "user" && entry.role !== "assistant" || !("content" in entry.message)) continue;
|
|
153
|
-
if (entry.role === "assistant" && "stopReason" in entry.message && (entry.message.stopReason === "aborted" || entry.message.stopReason === "error")) continue;
|
|
157
|
+
if (entry.role === "assistant" && ("stopReason" in entry.message && (entry.message.stopReason === "aborted" || entry.message.stopReason === "error") || "openclawAsyncDelivery" in entry.message)) continue;
|
|
154
158
|
const content = entry.message.content;
|
|
155
159
|
const text = normalizeImportedHistoryText(typeof content === "string" ? content : Array.isArray(content) ? content.flatMap((part) => part && typeof part === "object" && "text" in part && typeof part.text === "string" ? [part.text] : []).join("\n") : void 0);
|
|
156
160
|
if (!text) continue;
|
|
@@ -175,6 +179,22 @@ const MIRROR_ORIGIN_META_KEY = "mirrorOrigin";
|
|
|
175
179
|
const MIRROR_SOURCE_FINGERPRINT_META_KEY = "mirrorSourceFingerprint";
|
|
176
180
|
const CODEX_APP_SERVER_MIRROR_ORIGIN = "codex-app-server";
|
|
177
181
|
const CODEX_META_KEY = "__openclaw";
|
|
182
|
+
function applyCodexTranscriptTaint(message, state) {
|
|
183
|
+
if (message.role === "user") {
|
|
184
|
+
state.tainted = false;
|
|
185
|
+
return message;
|
|
186
|
+
}
|
|
187
|
+
const existing = CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
|
|
188
|
+
const metadata = asOptionalRecord(existing);
|
|
189
|
+
state.tainted ||= metadata?.turnTainted === true || metadata?.resultContentSource === "network";
|
|
190
|
+
return message.role === "assistant" && state.tainted ? {
|
|
191
|
+
...message,
|
|
192
|
+
__openclaw: {
|
|
193
|
+
...metadata,
|
|
194
|
+
turnTainted: true
|
|
195
|
+
}
|
|
196
|
+
} : message;
|
|
197
|
+
}
|
|
178
198
|
function attachCodexMirrorAttestation(message, sourceFingerprint) {
|
|
179
199
|
const existing = CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
|
|
180
200
|
const baseMeta = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
|
|
@@ -188,7 +208,8 @@ function attachCodexMirrorAttestation(message, sourceFingerprint) {
|
|
|
188
208
|
};
|
|
189
209
|
}
|
|
190
210
|
function attachCodexMirrorRunId(message, runId, terminal = false) {
|
|
191
|
-
const
|
|
211
|
+
const existing = CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
|
|
212
|
+
const { runTerminal: _staleTerminal, ...current } = asOptionalRecord(existing) ?? {};
|
|
192
213
|
return {
|
|
193
214
|
...message,
|
|
194
215
|
[CODEX_META_KEY]: {
|
|
@@ -198,6 +219,10 @@ function attachCodexMirrorRunId(message, runId, terminal = false) {
|
|
|
198
219
|
}
|
|
199
220
|
};
|
|
200
221
|
}
|
|
222
|
+
function hasCodexMirrorOrigin(message) {
|
|
223
|
+
const meta = CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
|
|
224
|
+
return asOptionalRecord(meta)?.[MIRROR_ORIGIN_META_KEY] === CODEX_APP_SERVER_MIRROR_ORIGIN;
|
|
225
|
+
}
|
|
201
226
|
function readCodexMirrorSourceFingerprint(message) {
|
|
202
227
|
const meta = CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
|
|
203
228
|
if (!meta || typeof meta !== "object" || Array.isArray(meta)) return;
|
|
@@ -270,6 +295,10 @@ async function buildResolvedCodexUserPromptMessage(params) {
|
|
|
270
295
|
function isMirroredAgentMessage(message) {
|
|
271
296
|
return message.role === "user" || message.role === "assistant" || message.role === "toolResult";
|
|
272
297
|
}
|
|
298
|
+
function readMirroredAssistantText(message) {
|
|
299
|
+
if (message?.role !== "assistant") return;
|
|
300
|
+
return message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("\n") || void 0;
|
|
301
|
+
}
|
|
273
302
|
/** Imports a bounded, user-visible Codex history tail into a new OpenClaw transcript. */
|
|
274
303
|
async function importCodexThreadHistoryToTranscript(params) {
|
|
275
304
|
const projection = projectBoundedCodexThreadHistory({
|
|
@@ -318,6 +347,7 @@ async function mirrorBestEffort(params) {
|
|
|
318
347
|
mirrorIdentity: `${params.turnId}:assistant`,
|
|
319
348
|
runId: params.params.runId
|
|
320
349
|
},
|
|
350
|
+
prepareAssistantTranscriptMessage: params.params.prepareAssistantTranscriptMessage,
|
|
321
351
|
config: params.params.config
|
|
322
352
|
});
|
|
323
353
|
for (const receipt of mirrorResult.userMessageReceipts) try {
|
|
@@ -431,6 +461,7 @@ function buildMirrorDedupeIdentity(message) {
|
|
|
431
461
|
async function mirror(params) {
|
|
432
462
|
const messages = params.messages.filter(isMirroredAgentMessage);
|
|
433
463
|
if (messages.length === 0) return {
|
|
464
|
+
assistantMirrorIdentitiesAppended: [],
|
|
434
465
|
assistantMirrorIdentitiesOwned: [],
|
|
435
466
|
anchorsByMirrorIdentity: /* @__PURE__ */ new Map(),
|
|
436
467
|
messagesPresent: [],
|
|
@@ -449,11 +480,12 @@ async function mirror(params) {
|
|
|
449
480
|
});
|
|
450
481
|
const candidateIdempotencyKeys = candidates.flatMap(({ idempotencyKey }) => idempotencyKey ? [idempotencyKey] : []);
|
|
451
482
|
const transcriptTarget = resolveCodexMirrorTranscriptTarget(params);
|
|
452
|
-
const { appendedUpdates, assistantMirrorIdentitiesOwned, anchorsByMirrorIdentity, messagesPresent, userMessageReceipts, userMessagesPresent } = await withCodexSessionTranscriptMirrorWriteLock({
|
|
483
|
+
const { appendedUpdates, assistantMirrorIdentitiesAppended, assistantMirrorIdentitiesOwned, anchorsByMirrorIdentity, messagesPresent, userMessageReceipts, userMessagesPresent } = await withCodexSessionTranscriptMirrorWriteLock({
|
|
453
484
|
...transcriptTarget,
|
|
454
485
|
config: params.config
|
|
455
486
|
}, async (transcript) => {
|
|
456
487
|
const nextAppendedUpdates = [];
|
|
488
|
+
const nextAssistantMirrorIdentitiesAppended = /* @__PURE__ */ new Set();
|
|
457
489
|
const nextAssistantMirrorIdentitiesOwned = /* @__PURE__ */ new Set();
|
|
458
490
|
const nextAnchorsByMirrorIdentity = /* @__PURE__ */ new Map();
|
|
459
491
|
const nextMessagesPresent = [];
|
|
@@ -486,10 +518,12 @@ async function mirror(params) {
|
|
|
486
518
|
if (message.role === "assistant") nextAssistantMirrorIdentitiesOwned.add(dedupeIdentity);
|
|
487
519
|
continue;
|
|
488
520
|
}
|
|
489
|
-
const nextMessage =
|
|
521
|
+
const nextMessage = runAgentHarnessBeforeMessageWriteHook({
|
|
490
522
|
message: transcriptMessage,
|
|
491
523
|
agentId: params.agentId,
|
|
492
|
-
sessionKey: params.sessionKey
|
|
524
|
+
sessionKey: params.sessionKey,
|
|
525
|
+
skipBeforeMessageWriteHooks: params.skipBeforeMessageWriteHooks,
|
|
526
|
+
prepareAssistantTranscriptMessage: ownsTerminal ? params.prepareAssistantTranscriptMessage : void 0
|
|
493
527
|
});
|
|
494
528
|
if (!nextMessage) {
|
|
495
529
|
if (message.role === "assistant") nextAssistantMirrorIdentitiesOwned.add(dedupeIdentity);
|
|
@@ -501,6 +535,7 @@ async function mirror(params) {
|
|
|
501
535
|
} : attachCodexMirrorAttestation(nextMessage, sourceFingerprint);
|
|
502
536
|
if (mirrorIdentity) messageToAppend = attachCodexMirrorIdentity(messageToAppend, mirrorIdentity);
|
|
503
537
|
if (ownsRun && params.runId) messageToAppend = attachCodexMirrorRunId(messageToAppend, params.runId, ownsTerminal);
|
|
538
|
+
if (message.role === "assistant" && message.openclawAsyncDelivery) messageToAppend = Object.assign(messageToAppend, { openclawAsyncDelivery: { itemId: message.openclawAsyncDelivery.itemId } });
|
|
504
539
|
messageToAppend = projectAgentHarnessTranscriptMessageForDisplay({
|
|
505
540
|
hidden: message.display === false,
|
|
506
541
|
message: messageToAppend
|
|
@@ -525,11 +560,14 @@ async function mirror(params) {
|
|
|
525
560
|
message: appendedMessage
|
|
526
561
|
});
|
|
527
562
|
}
|
|
528
|
-
if (appended.appended)
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
563
|
+
if (appended.appended) {
|
|
564
|
+
if (message.role === "assistant") nextAssistantMirrorIdentitiesAppended.add(dedupeIdentity);
|
|
565
|
+
nextAppendedUpdates.push({
|
|
566
|
+
messageId,
|
|
567
|
+
message: appendedMessage,
|
|
568
|
+
...messageSeq !== void 0 ? { messageSeq } : {}
|
|
569
|
+
});
|
|
570
|
+
}
|
|
533
571
|
if (idempotencyKey) {
|
|
534
572
|
mirrorFacts.existingIdempotencyKeys.add(idempotencyKey);
|
|
535
573
|
if (appended.anchor) mirrorFacts.anchorsByIdempotencyKey.set(idempotencyKey, appended.anchor);
|
|
@@ -537,6 +575,7 @@ async function mirror(params) {
|
|
|
537
575
|
}
|
|
538
576
|
return {
|
|
539
577
|
appendedUpdates: nextAppendedUpdates,
|
|
578
|
+
assistantMirrorIdentitiesAppended: [...nextAssistantMirrorIdentitiesAppended],
|
|
540
579
|
assistantMirrorIdentitiesOwned: [...nextAssistantMirrorIdentitiesOwned],
|
|
541
580
|
anchorsByMirrorIdentity: nextAnchorsByMirrorIdentity,
|
|
542
581
|
messagesPresent: nextMessagesPresent,
|
|
@@ -562,6 +601,7 @@ async function mirror(params) {
|
|
|
562
601
|
embeddedAgentLog.warn("failed to publish codex app-server transcript update", { error: formatErrorMessage(error) });
|
|
563
602
|
}
|
|
564
603
|
return {
|
|
604
|
+
assistantMirrorIdentitiesAppended,
|
|
565
605
|
assistantMirrorIdentitiesOwned,
|
|
566
606
|
anchorsByMirrorIdentity,
|
|
567
607
|
messagesPresent,
|
|
@@ -569,10 +609,76 @@ async function mirror(params) {
|
|
|
569
609
|
userMessagesPresent
|
|
570
610
|
};
|
|
571
611
|
}
|
|
612
|
+
async function deliverAsyncMessageBestEffort(params) {
|
|
613
|
+
const mirrorIdentity = `${params.turnId}:async:${params.itemId}`;
|
|
614
|
+
const deliveryIntentId = `block-reply:v1:codex-app-server:${[
|
|
615
|
+
params.threadId,
|
|
616
|
+
params.turnId,
|
|
617
|
+
params.itemId
|
|
618
|
+
].map(encodeURIComponent).join(":")}`;
|
|
619
|
+
const target = params.params.sessionTarget;
|
|
620
|
+
if (!target) {
|
|
621
|
+
if (!params.params.onBlockReply) return "retry";
|
|
622
|
+
try {
|
|
623
|
+
await deliverAsyncBlockReply(params.params.onBlockReply, params.text, deliveryIntentId);
|
|
624
|
+
return "settled";
|
|
625
|
+
} catch (error) {
|
|
626
|
+
embeddedAgentLog.warn("failed to deliver codex async agent message", {
|
|
627
|
+
error: formatErrorMessage(error),
|
|
628
|
+
itemId: params.itemId,
|
|
629
|
+
runId: params.params.runId,
|
|
630
|
+
threadId: params.threadId,
|
|
631
|
+
turnId: params.turnId
|
|
632
|
+
});
|
|
633
|
+
return "retry";
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
let result;
|
|
637
|
+
try {
|
|
638
|
+
result = await mirror({
|
|
639
|
+
agentId: target.agentId ?? params.params.agentId,
|
|
640
|
+
sessionId: target.sessionId ?? params.params.sessionId,
|
|
641
|
+
sessionKey: target.sessionKey ?? params.params.sessionKey,
|
|
642
|
+
storePath: target.storePath,
|
|
643
|
+
cwd: params.cwd,
|
|
644
|
+
config: params.params.config,
|
|
645
|
+
messages: [attachCodexMirrorIdentity(params.message, mirrorIdentity)],
|
|
646
|
+
idempotencyScope: `codex-app-server:${params.threadId}`
|
|
647
|
+
});
|
|
648
|
+
} catch (error) {
|
|
649
|
+
embeddedAgentLog.warn("failed to persist codex async agent message", {
|
|
650
|
+
error: formatErrorMessage(error),
|
|
651
|
+
itemId: params.itemId,
|
|
652
|
+
runId: params.params.runId,
|
|
653
|
+
threadId: params.threadId,
|
|
654
|
+
turnId: params.turnId
|
|
655
|
+
});
|
|
656
|
+
return "retry";
|
|
657
|
+
}
|
|
658
|
+
if (!result.assistantMirrorIdentitiesOwned.includes(mirrorIdentity)) return "retry";
|
|
659
|
+
const persistedText = readMirroredAssistantText(result.messagesPresent.find((message) => readMirrorIdentity(message) === mirrorIdentity));
|
|
660
|
+
if (params.params.onBlockReply && persistedText !== void 0) try {
|
|
661
|
+
await deliverAsyncBlockReply(params.params.onBlockReply, persistedText, deliveryIntentId);
|
|
662
|
+
} catch (error) {
|
|
663
|
+
embeddedAgentLog.warn("failed to deliver persisted codex async agent message", {
|
|
664
|
+
error: formatErrorMessage(error),
|
|
665
|
+
itemId: params.itemId,
|
|
666
|
+
runId: params.params.runId,
|
|
667
|
+
threadId: params.threadId,
|
|
668
|
+
turnId: params.turnId
|
|
669
|
+
});
|
|
670
|
+
return "retry";
|
|
671
|
+
}
|
|
672
|
+
return "settled";
|
|
673
|
+
}
|
|
572
674
|
const codexTranscriptMirrorRuntime = {
|
|
675
|
+
deliverAsyncMessageBestEffort,
|
|
573
676
|
mirror,
|
|
574
677
|
mirrorBestEffort
|
|
575
678
|
};
|
|
679
|
+
async function deliverAsyncBlockReply(onBlockReply, text, deliveryIntentId) {
|
|
680
|
+
await deliverAgentHarnessUserInputPrompt({ onBlockReply: (payload) => onBlockReply(payload, { deliveryIntentId }) }, [], { intro: text });
|
|
681
|
+
}
|
|
576
682
|
function resolveCodexMirrorTranscriptTarget(params) {
|
|
577
683
|
const sessionKey = params.sessionKey?.trim();
|
|
578
684
|
const storePath = params.storePath?.trim();
|
|
@@ -585,4 +691,4 @@ function resolveCodexMirrorTranscriptTarget(params) {
|
|
|
585
691
|
};
|
|
586
692
|
}
|
|
587
693
|
//#endregion
|
|
588
|
-
export { buildCodexUserPromptMessage as a,
|
|
694
|
+
export { buildCodexUserPromptMessage as a, fingerprintCodexMirrorSourceMessage as c, serializeCodexMirrorSourceEvidence as d, projectBoundedCodexThreadHistory as f, mirrorPromptAtTurnStartBestEffort as i, hasCodexMirrorOrigin as l, projectCodexUserItemText as m, createCodexAppServerUserMessagePersistenceNotifier as n, promptSnapshot as o, projectBoundedCodexVisibleSessionHistory as p, importCodexThreadHistoryToTranscript as r, applyCodexTranscriptTaint as s, codexTranscriptMirrorRuntime as t, readCodexMirrorSourceFingerprint as u };
|