@openclaw/codex 2026.9.1 → 2026.9.3

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.
Files changed (109) hide show
  1. package/README.md +2 -0
  2. package/dist/api.js +18 -23
  3. package/dist/apply-B6el6hdO.js +357 -0
  4. package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-D6cR54TV.js} +113 -49
  5. package/dist/{attempt-context-DmQUNWwT.js → attempt-context-AO4DSjE0.js} +11 -9
  6. package/dist/{event-projector-usage-C5mcrGjp.js → attempt-notifications--H8zXR5-.js} +3 -89
  7. package/dist/auth-cache-key-Kq6oerr6.js +498 -0
  8. package/dist/auth-profile-CwzO4_RG.js +43 -0
  9. package/dist/auth-profile-selection-DFu9e167.js +45 -0
  10. package/dist/{binding-connection-E6uDsPlx.js → binding-connection-QqgcPCgk.js} +18 -3
  11. package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-lRpmZHFv.js} +54 -150
  12. package/dist/build-state-6RL6qohz.js +19 -0
  13. package/dist/{capabilities-dIjNVCYH.js → capabilities-BeqLPbtM.js} +2 -1
  14. package/dist/cli-metadata.js +1 -1
  15. package/dist/client-BEKu4yDx.js +3983 -0
  16. package/dist/command-dispatch-CisT9Jqq.js +21 -0
  17. package/dist/{command-formatters-CLHhEB1Q.js → command-formatters-DeTfrapr.js} +2 -2
  18. package/dist/{command-handlers-CTGb2csu.js → command-handlers-BfIsJEuA.js} +158 -76
  19. package/dist/command-rpc-BMqRQOFX.js +226 -0
  20. package/dist/{compact-_t0HQrUS.js → compact-CGJZ2rlb.js} +89 -49
  21. package/dist/config-JDfTI4VI.js +106 -0
  22. package/dist/{config-BhmfC1s6.js → config-options-jnIFvwxD.js} +208 -654
  23. package/dist/config-runtime-BWf6JLWG.js +11 -0
  24. package/dist/config-utils-C57JiJrU.js +69 -0
  25. package/dist/conversation-binding-CxOlHiix.js +889 -0
  26. package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → conversation-control-CUCrSIQI.js} +36 -155
  27. package/dist/doctor-contract-api.js +8 -9
  28. package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-D-JBoaLt.js} +734 -698
  29. package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-J_5Ep5Um.js} +4 -3
  30. package/dist/{elicitation-input-DMkeki8d.js → elicitation-input-DPoK8F7w.js} +8 -22
  31. package/dist/ephemeral-turn-DSwzP8YY.js +101 -0
  32. package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-BmBM4qBV.js} +23 -27
  33. package/dist/event-projector-usage-CIyrYYid.js +102 -0
  34. package/dist/{harness-DXVZ5II5.js → harness-FR6eQgyO.js} +47 -17
  35. package/dist/harness.js +1 -1
  36. package/dist/history-rejection-B4nOXNXF.js +13 -0
  37. package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
  38. package/dist/incognito-session-uhrBF6wJ.js +15 -0
  39. package/dist/index.js +413 -2893
  40. package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-DHBefrzg.js} +12 -21
  41. package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DrjjRRUD.js} +17 -84
  42. package/dist/managed-thread-store-D1t5jh3G.js +66 -0
  43. package/dist/media-understanding-provider.js +4 -1
  44. package/dist/{model-catalog-CUM68Hkl.js → model-catalog-B_6M04Wo.js} +6 -5
  45. package/dist/{models-sYnEc0gd.js → models-P9k2qAof.js} +4 -4
  46. package/dist/native-execution-policy-umd0tgh4.js +128 -0
  47. package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-BbCUKRwC.js} +76 -48
  48. package/dist/node-cli-sessions-rj0ysJwM.js +527 -0
  49. package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-BY_ctYnT.js} +54 -23
  50. package/dist/plan-BMJdMOEF.js +711 -0
  51. package/dist/plugin-activation-BQK-f5sV.js +133 -0
  52. package/dist/{thread-resume-C7pyVKeW.js → plugin-app-cache-key-CdSQzWyX.js} +5 -53
  53. package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-DeW95wB5.js} +1 -1
  54. package/dist/plugin-inventory-CoRCzWW4.js +325 -0
  55. package/dist/plugin-marketplace-discovery-3akBizzF.js +134 -0
  56. package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-DgNfRAGA.js} +13 -9
  57. package/dist/protocol-CAAcVIKF.js +275 -0
  58. package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-W4tfK5Y5.js} +2 -2
  59. package/dist/{rate-limits-CawQJfUS.js → rate-limits-Bqnx1N4z.js} +1 -1
  60. package/dist/request-CGvGOpeR.js +198 -0
  61. package/dist/{run-attempt-D1hJO4fX.js → run-attempt-DwKds3DN.js} +1498 -1028
  62. package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-T-NwqeSH.js} +28 -28
  63. package/dist/sandbox-guard-BcT66fWy.js +165 -0
  64. package/dist/{session-binding-BHuTCRZQ.js → session-binding-CKSepwIC.js} +118 -324
  65. package/dist/session-binding-record-CaZjYwNS.js +256 -0
  66. package/dist/session-catalog-HaDcp7Sv.js +1533 -0
  67. package/dist/session-catalog-adoption-BKLtSrwi.js +251 -0
  68. package/dist/session-catalog-archive-D0i2pGj2.js +56 -0
  69. package/dist/session-catalog-home-id-D7-aLiNt.js +190 -0
  70. package/dist/session-catalog-node-adoption-BUuDYY8R.js +182 -0
  71. package/dist/session-catalog-node-continue-CBtc4wkI.js +238 -0
  72. package/dist/session-catalog-parsing-CdD3JhdM.js +280 -0
  73. package/dist/session-catalog-provenance-DkJHo735.js +124 -0
  74. package/dist/{session-cli-CmFEXMAM.js → session-cli-CbgaHh0f.js} +3 -2
  75. package/dist/session-history-Cz-tOOYj.js +96 -0
  76. package/dist/{session-upstream-marker-C351-5Qw.js → session-history-import-DFN7sWRU.js} +5 -49
  77. package/dist/session-history-read-cxPUxyVV.js +50 -0
  78. package/dist/session-history-worker-runtime.js +60 -0
  79. package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-CNEvGaU5.js} +75 -69
  80. package/dist/session-history.worker.js +2 -0
  81. package/dist/{session-initialization-BeWzjGiR.js → session-initialization-Jo86C60I.js} +2 -1
  82. package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-B22InTp_.js} +4 -7
  83. package/dist/{session-retirement-BujDjXVF.js → session-retirement-BSNG_mhf.js} +8 -7
  84. package/dist/session-upstream-marker-D15C9NHp.js +46 -0
  85. package/dist/settled-turn-context-Du6gdUDd.js +45 -0
  86. package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BuLUrZl2.js} +54 -42
  87. package/dist/shared-client-CVhez2Uo.js +2911 -0
  88. package/dist/{side-question-BTZAII4l.js → side-question-DLbr2vUU.js} +135 -191
  89. package/dist/source-Da-h6f7e.js +518 -0
  90. package/dist/thread-archive-guard-D1bP04Tf.js +53 -0
  91. package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-D1pzRwHB.js} +467 -977
  92. package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-D6oASVRu.js} +15 -17
  93. package/dist/{thread-policy-g4KbJPzp.js → thread-policy-D8kI7yAO.js} +2 -2
  94. package/dist/thread-resume-T5cveyxA.js +52 -0
  95. package/dist/timeout-BVw8aaM1.js +33 -0
  96. package/dist/transcript-mirror-attestation-DibE0krH.js +89 -0
  97. package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-t5TOccct.js} +111 -379
  98. package/dist/{transport-stdio-CyPldczm.js → transport-stdio-BGjHoYLr.js} +80 -48
  99. package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-De-sLJ2r.js} +94 -166
  100. package/dist/{usage-Bj-rrzkR.js → usage-CPPTmBvZ.js} +4 -3
  101. package/dist/version-omm6IPI3.js +12 -0
  102. package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-CSVgQL0w.js} +3 -3
  103. package/openclaw.plugin.json +22 -1
  104. package/package.json +6 -6
  105. package/dist/request-DYAI5FQE.js +0 -475
  106. package/dist/session-catalog-yyvTWFOw.js +0 -3120
  107. package/dist/session-history-C5J1AKzG.js +0 -87
  108. package/dist/shared-client-DxcfF9KX.js +0 -7494
  109. package/dist/{auth-binding-Ds_QVm-X.js → auth-binding-Co2Vfcf_.js} +1 -1
@@ -1,5 +1,6 @@
1
- import { _ as retainSharedCodexAppServerClientByInstanceId } from "./shared-client-DxcfF9KX.js";
2
- import { d as sessionBindingIdentity } from "./session-binding-BHuTCRZQ.js";
1
+ import { l as sessionBindingIdentity } from "./session-binding-record-CaZjYwNS.js";
2
+ import { _ as retainSharedCodexAppServerClientByInstanceId } from "./shared-client-CVhez2Uo.js";
3
+ import "./session-binding-CKSepwIC.js";
3
4
  import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
5
  import { assignMcpCatalogSafeServerNames } from "openclaw/plugin-sdk/agent-harness-runtime";
5
6
  //#region extensions/codex/src/app-server/effective-mcp-catalog.ts
@@ -95,7 +96,7 @@ async function loadCodexEffectiveMcpCatalogFromThread(params) {
95
96
  }
96
97
  /** Loads MCP inventory from the bound Codex client while retaining its lease through all pages. */
97
98
  async function loadCodexEffectiveMcpCatalog(params, options) {
98
- const binding = await options.bindingStore.read(sessionBindingIdentity({
99
+ const binding = options.bindingStore.read(sessionBindingIdentity({
99
100
  agentId: params.agentId,
100
101
  sessionId: params.sessionId,
101
102
  sessionKey: params.sessionKey,
@@ -1,17 +1,8 @@
1
1
  import { agentHarnessStructuredInput } from "openclaw/plugin-sdk/agent-harness-runtime";
2
2
  //#region extensions/codex/src/app-server/elicitation-input.ts
3
- /** Snapshots and compiles ordinary Codex input before it enters the per-turn queue. */
3
+ /** Compiles a validated Codex input snapshot before it enters the per-turn queue. */
4
4
  function compileCodexOrdinaryElicitation(params) {
5
- if (readRawOwnString(params.value, "threadId") !== params.threadId) return { kind: "ignored" };
6
- const snapshot = agentHarnessStructuredInput.snapshot(params.value);
7
- if (!agentHarnessStructuredInput.isRecord(snapshot)) return {
8
- kind: "compiled",
9
- input: {
10
- kind: "unsupported",
11
- message: "OpenClaw declined a malformed or over-limit MCP elicitation request."
12
- }
13
- };
14
- const requestTurnId = readValue(snapshot, "turnId");
5
+ const requestTurnId = readValue(params.snapshot, "turnId");
15
6
  if (typeof requestTurnId === "string" && requestTurnId !== params.turnId) return { kind: "ignored" };
16
7
  if (requestTurnId !== null && typeof requestTurnId !== "string") return {
17
8
  kind: "compiled",
@@ -20,13 +11,13 @@ function compileCodexOrdinaryElicitation(params) {
20
11
  message: "OpenClaw declined an MCP elicitation with invalid turn correlation."
21
12
  }
22
13
  };
23
- const mode = readCodexElicitationString(snapshot, "mode");
14
+ const mode = readCodexElicitationString(params.snapshot, "mode");
24
15
  if (mode === "url") return {
25
16
  kind: "compiled",
26
17
  input: agentHarnessStructuredInput.compileUrl({
27
- url: readValue(snapshot, "url"),
28
- elicitationId: readValue(snapshot, "elicitationId"),
29
- message: readValue(snapshot, "message"),
18
+ url: readValue(params.snapshot, "url"),
19
+ elicitationId: readValue(params.snapshot, "elicitationId"),
20
+ message: readValue(params.snapshot, "message"),
30
21
  fallbackMessage: "Codex provided a URL",
31
22
  protocolName: "MCP"
32
23
  })
@@ -41,8 +32,8 @@ function compileCodexOrdinaryElicitation(params) {
41
32
  return {
42
33
  kind: "compiled",
43
34
  input: agentHarnessStructuredInput.compileForm({
44
- schema: readValue(snapshot, "requestedSchema"),
45
- message: readCodexElicitationString(snapshot, "message"),
35
+ schema: readValue(params.snapshot, "requestedSchema"),
36
+ message: readCodexElicitationString(params.snapshot, "message"),
46
37
  fallbackMessage: "Codex needs input",
47
38
  options: {
48
39
  protocolName: mode === "openai/form" ? "OpenAI" : "MCP",
@@ -62,10 +53,5 @@ function readCodexElicitationString(record, key) {
62
53
  const value = readValue(record, key);
63
54
  return typeof value === "string" ? value : void 0;
64
55
  }
65
- function readRawOwnString(value, key) {
66
- if (!value || typeof value !== "object" || Array.isArray(value)) return;
67
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
68
- return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : void 0;
69
- }
70
56
  //#endregion
71
57
  export { compileCodexOrdinaryElicitation };
@@ -0,0 +1,101 @@
1
+ import { o as isJsonObject } from "./protocol-CAAcVIKF.js";
2
+ import { T as readCodexTurnCompletedNotification } from "./client-BEKu4yDx.js";
3
+ import { p as getCodexAppServerTurnRouter } from "./attempt-client-cleanup-D6cR54TV.js";
4
+ import { o as isTerminalTurnStatus, s as readCodexNotificationItem } from "./attempt-notifications--H8zXR5-.js";
5
+ import { t as CodexUsageProjection } from "./event-projector-usage-CIyrYYid.js";
6
+ import { readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
7
+ import { toStringifiedError } from "openclaw/plugin-sdk/error-runtime";
8
+ import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
9
+ //#region extensions/codex/src/app-server/ephemeral-turn.ts
10
+ /** One ephemeral turn; the client router owns correlation, buffering and request lifetime. */
11
+ var CodexEphemeralTurn = class {
12
+ constructor(client, threadId, options) {
13
+ this.options = options;
14
+ this.completion = createDeferred();
15
+ this.usage = new CodexUsageProjection();
16
+ this.items = /* @__PURE__ */ new Map();
17
+ this.assistantItems = /* @__PURE__ */ new Map();
18
+ this.assistantText = "";
19
+ this.route = getCodexAppServerTurnRouter(client).reserveThread({
20
+ threadId,
21
+ ...options,
22
+ onNotification: async (notification, scope) => {
23
+ const params = isJsonObject(notification.params) ? notification.params : void 0;
24
+ if (params && scope.turnId) {
25
+ if (notification.method === "item/completed" && options.textMode === "all") {
26
+ const item = readCodexNotificationItem(params);
27
+ if (item) {
28
+ this.items.set(item.id, item);
29
+ if (item.type === "agentMessage" && item.text) this.assistantItems.set(item.id, item.text);
30
+ }
31
+ } else if (notification.method === "item/agentMessage/delta") {
32
+ const delta = readStringField(params, "delta") ?? "";
33
+ const itemId = readStringField(params, "itemId") ?? readStringField(params, "id") ?? "assistant";
34
+ const firstDelta = !this.assistantText && Boolean(delta);
35
+ this.assistantText += delta;
36
+ if (delta && options.textMode === "all") this.assistantItems.set(itemId, `${this.assistantItems.get(itemId) ?? ""}${delta}`);
37
+ if (firstDelta) await options.onAssistantMessageStart?.();
38
+ } else if (notification.method === "rawResponse/completed") this.usage.record(params);
39
+ else if (notification.method === "turn/completed") {
40
+ this.turn = readCodexTurnCompletedNotification(params)?.turn ?? this.turn;
41
+ this.completion.resolve();
42
+ } else if (notification.method === "error") {
43
+ this.usage.invalidateContext();
44
+ if (params.willRetry !== true) {
45
+ this.error = params;
46
+ this.completion.resolve();
47
+ }
48
+ }
49
+ }
50
+ await options.onNotification?.(notification, scope);
51
+ }
52
+ });
53
+ this.route.armTurn();
54
+ }
55
+ get completed() {
56
+ return this.turn !== void 0;
57
+ }
58
+ async wait(turn, options) {
59
+ if (isTerminalTurnStatus(turn.status)) {
60
+ this.turn = turn;
61
+ this.completion.resolve();
62
+ }
63
+ const completion = this.route.bindTurn(turn.id, { completed: isTerminalTurnStatus(turn.status) }).then(() => this.completion.promise);
64
+ const signals = [this.route.signal, options.signal];
65
+ const abortError = () => options.signal.aborted ? options.abortError() : toStringifiedError(this.route.signal.reason);
66
+ let timer;
67
+ let abort = () => {};
68
+ try {
69
+ await Promise.race([completion, new Promise((_resolve, reject) => {
70
+ abort = () => {
71
+ if (options.signal.aborted || !this.route.completed) reject(abortError());
72
+ };
73
+ for (const signal of signals) {
74
+ signal.addEventListener("abort", abort, { once: true });
75
+ if (signal.aborted) abort();
76
+ }
77
+ const timeout = options.timeout;
78
+ if (timeout) {
79
+ timer = setTimeout(() => reject(timeout.error), timeout.ms);
80
+ timer.unref?.();
81
+ }
82
+ })]);
83
+ } finally {
84
+ clearTimeout(timer);
85
+ for (const signal of signals) signal.removeEventListener("abort", abort);
86
+ }
87
+ const items = new Map(this.items);
88
+ for (const item of this.turn?.items ?? []) items.set(item.id, item);
89
+ const messages = (this.options.textMode === "last" ? this.turn?.items ?? [] : [...items.values()]).filter((item) => item.type === "agentMessage").map((item) => item.text.trim()).filter(Boolean);
90
+ const text = this.options.textMode === "last" ? messages.at(-1) || this.assistantText : messages.join("\n\n") || [...this.assistantItems.values()].map((message) => message.trim()).filter(Boolean).join("\n\n");
91
+ return {
92
+ turn: this.turn,
93
+ error: this.error,
94
+ items: [...items.values()],
95
+ text: text.trim(),
96
+ usage: this.usage.usage
97
+ };
98
+ }
99
+ };
100
+ //#endregion
101
+ export { CodexEphemeralTurn as t };
@@ -33,6 +33,7 @@ function createAttributedCodexAssistantMessage(attribution, text, options) {
33
33
  totalTokens: options.tokenUsage.total ?? (options.tokenUsage.input ?? 0) + (options.tokenUsage.output ?? 0) + (options.tokenUsage.cacheRead ?? 0) + (options.tokenUsage.cacheWrite ?? 0),
34
34
  cost: ZERO_USAGE.cost
35
35
  } : ZERO_USAGE;
36
+ const refusal = options.providerRefusal;
36
37
  return {
37
38
  role: "assistant",
38
39
  content: [{
@@ -43,25 +44,25 @@ function createAttributedCodexAssistantMessage(attribution, text, options) {
43
44
  provider: attribution.provider,
44
45
  model: attribution.modelId,
45
46
  usage,
46
- stopReason: options.aborted ? "aborted" : options.promptError ? "error" : "stop",
47
- errorMessage: options.promptError ? formatErrorMessage(options.promptError) : void 0,
47
+ stopReason: options.aborted ? "aborted" : options.promptError || refusal ? "error" : "stop",
48
+ errorMessage: refusal?.message ?? (options.promptError ? formatErrorMessage(options.promptError) : void 0),
49
+ ...refusal ? { diagnostics: [{
50
+ type: "provider_refusal",
51
+ timestamp: Date.now(),
52
+ details: {
53
+ provider: "openai",
54
+ category: refusal.category
55
+ }
56
+ }] } : {},
48
57
  timestamp: Date.now()
49
58
  };
50
59
  }
51
60
  function createAssistantCommentaryMessage(params, text, itemId, timestamp) {
52
- const attribution = resolveCodexLocalRuntimeAttribution(params);
53
61
  return {
54
- role: "assistant",
55
- content: [{
62
+ ...createNonterminalAssistantMessage(params, [{
56
63
  type: "text",
57
64
  text
58
- }],
59
- api: attribution.api ?? "openai-chatgpt-responses",
60
- provider: attribution.provider,
61
- model: params.modelId,
62
- usage: ZERO_USAGE,
63
- stopReason: "stop",
64
- timestamp,
65
+ }], timestamp),
65
66
  openclawStreamFallback: {
66
67
  replacementText: text,
67
68
  source: "segment",
@@ -70,36 +71,31 @@ function createAssistantCommentaryMessage(params, text, itemId, timestamp) {
70
71
  };
71
72
  }
72
73
  function createAssistantAsyncMessage(params, text, itemId, timestamp) {
73
- const attribution = resolveCodexLocalRuntimeAttribution(params);
74
74
  return {
75
- role: "assistant",
76
- content: [{
75
+ ...createNonterminalAssistantMessage(params, [{
77
76
  type: "text",
78
77
  text
79
- }],
80
- api: attribution.api ?? "openai-chatgpt-responses",
81
- provider: attribution.provider,
82
- model: params.modelId,
83
- usage: ZERO_USAGE,
84
- stopReason: "stop",
85
- timestamp,
78
+ }], timestamp),
86
79
  openclawAsyncDelivery: { itemId }
87
80
  };
88
81
  }
89
82
  function createAssistantReasoningMessage(params, text) {
83
+ return createNonterminalAssistantMessage(params, [{
84
+ type: "thinking",
85
+ thinking: text
86
+ }]);
87
+ }
88
+ function createNonterminalAssistantMessage(params, content, timestamp) {
90
89
  const attribution = resolveCodexLocalRuntimeAttribution(params);
91
90
  return {
92
91
  role: "assistant",
93
- content: [{
94
- type: "thinking",
95
- thinking: text
96
- }],
92
+ content,
97
93
  api: attribution.api ?? "openai-chatgpt-responses",
98
94
  provider: attribution.provider,
99
95
  model: params.modelId,
100
96
  usage: ZERO_USAGE,
101
97
  stopReason: "stop",
102
- timestamp: Date.now()
98
+ timestamp: timestamp ?? Date.now()
103
99
  };
104
100
  }
105
101
  //#endregion
@@ -0,0 +1,102 @@
1
+ import { o as isJsonObject } from "./protocol-CAAcVIKF.js";
2
+ import { asSafeIntegerInRange, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { normalizeUsage } from "openclaw/plugin-sdk/agent-harness-runtime";
4
+ //#region extensions/codex/src/app-server/event-projector-usage.ts
5
+ function readTokenCount(record, key) {
6
+ return asSafeIntegerInRange(record[key], { min: 0 });
7
+ }
8
+ function readCodexThreadTokenUsage(params) {
9
+ const tokenUsage = isJsonObject(params.tokenUsage) ? params.tokenUsage : void 0;
10
+ const last = tokenUsage && isJsonObject(tokenUsage.last) ? tokenUsage.last : void 0;
11
+ return last ? normalizeCodexResponseTokenUsage(last) : void 0;
12
+ }
13
+ function readCodexThreadContextSnapshot(params) {
14
+ const tokenUsage = isJsonObject(params.tokenUsage) ? params.tokenUsage : void 0;
15
+ const last = tokenUsage && isJsonObject(tokenUsage.last) ? tokenUsage.last : void 0;
16
+ const modelContextWindow = tokenUsage ? readTokenCount(tokenUsage, "modelContextWindow") : void 0;
17
+ const activeContextTokens = last ? readTokenCount(last, "totalTokens") : void 0;
18
+ const inputTokens = last ? readTokenCount(last, "inputTokens") : void 0;
19
+ const cachedInputTokens = last ? readTokenCount(last, "cachedInputTokens") : void 0;
20
+ const cacheWriteInputTokens = last ? readTokenCount(last, "cacheWriteInputTokens") : void 0;
21
+ const reasoningOutputTokens = last ? readTokenCount(last, "reasoningOutputTokens") : void 0;
22
+ return {
23
+ ...activeContextTokens !== void 0 ? { activeContextTokens } : {},
24
+ ...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
25
+ ...cacheWriteInputTokens !== void 0 ? { cacheWriteInputTokens } : {},
26
+ ...inputTokens !== void 0 ? { inputTokens } : {},
27
+ ...modelContextWindow && modelContextWindow > 0 ? { modelContextWindow } : {},
28
+ ...inputTokens !== void 0 ? { promptTokens: inputTokens } : {},
29
+ ...reasoningOutputTokens !== void 0 ? { reasoningOutputTokens } : {}
30
+ };
31
+ }
32
+ function normalizeCodexResponseTokenUsage(record) {
33
+ const totalTokens = readTokenCount(record, "totalTokens");
34
+ const inputTokens = readTokenCount(record, "inputTokens");
35
+ const cacheRead = readTokenCount(record, "cachedInputTokens");
36
+ const output = readTokenCount(record, "outputTokens");
37
+ const reasoningTokens = readTokenCount(record, "reasoningOutputTokens");
38
+ const cacheWrite = record.cacheWriteInputTokens === void 0 ? 0 : readTokenCount(record, "cacheWriteInputTokens");
39
+ const hasCoherentInput = inputTokens !== void 0 && cacheRead !== void 0 && cacheWrite !== void 0 && cacheRead + cacheWrite <= inputTokens;
40
+ const hasCoherentContext = hasCoherentInput && totalTokens !== void 0 && output !== void 0 && totalTokens === inputTokens + output;
41
+ const usage = normalizeUsage({
42
+ input: hasCoherentInput ? inputTokens - cacheRead - cacheWrite : void 0,
43
+ output,
44
+ cacheRead,
45
+ cacheWrite,
46
+ reasoningTokens,
47
+ total: totalTokens
48
+ });
49
+ if (!usage) return;
50
+ return {
51
+ ...usage,
52
+ contextUsage: hasCoherentContext ? {
53
+ state: "available",
54
+ promptTokens: inputTokens,
55
+ totalTokens
56
+ } : { state: "unavailable" }
57
+ };
58
+ }
59
+ var CodexUsageProjection = class {
60
+ constructor() {
61
+ this.responseIds = /* @__PURE__ */ new Set();
62
+ }
63
+ get usage() {
64
+ const usage = this.responseUsage ?? this.threadUsage;
65
+ return usage ? {
66
+ ...usage,
67
+ contextUsage: this.contextUsage
68
+ } : void 0;
69
+ }
70
+ get modelIterations() {
71
+ return this.responseIds.size;
72
+ }
73
+ invalidateContext() {
74
+ this.contextUsage = { state: "unavailable" };
75
+ }
76
+ recordThread(params) {
77
+ const usage = readCodexThreadTokenUsage(params);
78
+ this.threadUsage = usage ?? this.threadUsage;
79
+ if (!this.responseUsage && usage) this.contextUsage = usage.contextUsage;
80
+ return readCodexThreadContextSnapshot(params);
81
+ }
82
+ record(params, reportOutputTokens) {
83
+ const responseId = readStringField(params, "responseId");
84
+ if (!responseId || this.responseIds.has(responseId)) return;
85
+ this.responseIds.add(responseId);
86
+ const usage = isJsonObject(params.usage) ? normalizeCodexResponseTokenUsage(params.usage) : void 0;
87
+ this.contextUsage = usage?.contextUsage ?? { state: "unavailable" };
88
+ this.responseUsage ??= {};
89
+ for (const field of [
90
+ "input",
91
+ "output",
92
+ "cacheRead",
93
+ "cacheWrite",
94
+ "reasoningTokens",
95
+ "total"
96
+ ]) if (usage?.[field] !== void 0) this.responseUsage[field] = (this.responseUsage[field] ?? 0) + usage[field];
97
+ const outputTokens = usage?.output;
98
+ if (outputTokens !== void 0) reportOutputTokens?.(outputTokens);
99
+ }
100
+ };
101
+ //#endregion
102
+ export { readCodexThreadContextSnapshot as n, CodexUsageProjection as t };
@@ -1,5 +1,6 @@
1
+ import { l as sessionBindingIdentity } from "./session-binding-record-CaZjYwNS.js";
2
+ import { t as codexBuildSymbol } from "./build-state-6RL6qohz.js";
1
3
  import { resolvePluginConfigObject } from "openclaw/plugin-sdk/plugin-config-runtime";
2
- import { runHostPreparedIsolatedCompletion } from "openclaw/plugin-sdk/simple-completion-runtime";
3
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
5
  //#region extensions/codex/src/app-server/model-runtime.ts
5
6
  const CODEX_APP_SERVER_RUNTIME_MODEL_PARAM = "codexAppServerRuntimeModel";
@@ -12,7 +13,7 @@ function readCodexRuntimeModelId(model, fallbackId) {
12
13
  //#endregion
13
14
  //#region extensions/codex/harness.ts
14
15
  const DEFAULT_CODEX_HARNESS_PROVIDER_IDS = /* @__PURE__ */ new Set(["codex", "openai"]);
15
- const SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER = Symbol.for("openclaw.codexAppServerClientDisposer");
16
+ const SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER = codexBuildSymbol("openclaw.codexAppServerClientDisposer");
16
17
  const CODEX_TOOL_POLICY_SAFE_DENY_NAMES = [
17
18
  "web_fetch",
18
19
  "x_search",
@@ -74,10 +75,35 @@ function createCodexAppServerAgentHarness(options) {
74
75
  conversationToolPolicySafeDenyTools: CODEX_TOOL_POLICY_SAFE_DENY_NAMES,
75
76
  deliveryDefaults: { visibleReplies: "message_tool" },
76
77
  authBootstrap: "harness",
78
+ resolveSessionRuntimeOwnership: (params) => {
79
+ const assertCurrent = () => {
80
+ params.assertCurrent();
81
+ if (disposed) throw new Error("Codex agent harness is disposed");
82
+ };
83
+ assertCurrent();
84
+ const identity = sessionBindingIdentity(params);
85
+ let binding = options.bindingStore.read(identity);
86
+ if (!binding) {
87
+ const previousSessionId = params.readPreviousSessionId?.();
88
+ binding = previousSessionId ? options.bindingStore.read({
89
+ ...identity,
90
+ sessionId: previousSessionId
91
+ }) : void 0;
92
+ }
93
+ assertCurrent();
94
+ return binding?.preserveNativeModel === true ? {
95
+ model: "native",
96
+ auth: binding.connectionScope === "supervision" ? "native" : "host",
97
+ ...binding.model?.trim() && binding.modelProvider ? { modelRef: {
98
+ provider: binding.modelProvider,
99
+ model: binding.model
100
+ } } : {}
101
+ } : void 0;
102
+ },
77
103
  ...sessionCatalogControlFactory && sessionRuntime ? { sessionFork: {
78
104
  upstreamKinds: ["codex-app-server"],
79
105
  fork: async (params) => {
80
- const { forkCodexUpstreamSession } = await import("./upstream-session-fork-CYlBIGVt.js");
106
+ const { forkCodexUpstreamSession } = await import("./upstream-session-fork-De-sLJ2r.js");
81
107
  return await forkCodexUpstreamSession(params, {
82
108
  bindingStore: options.bindingStore,
83
109
  controlFactory: sessionCatalogControlFactory,
@@ -88,26 +114,26 @@ function createCodexAppServerAgentHarness(options) {
88
114
  }
89
115
  } } : {},
90
116
  authBinding: { fingerprint: async (params) => {
91
- const { fingerprintCodexAppServerAuthBinding } = await import("./auth-binding-Ds_QVm-X.js").then((n) => n.t);
117
+ const { fingerprintCodexAppServerAuthBinding } = await import("./auth-binding-Co2Vfcf_.js").then((n) => n.t);
92
118
  return fingerprintCodexAppServerAuthBinding(params);
93
119
  } },
94
120
  runtimeArtifact: { validate: async (binding) => {
95
- const { validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-C3jVimFn.js");
121
+ const { validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-T-NwqeSH.js");
96
122
  return validateCodexAppServerRuntimeArtifact(binding);
97
123
  } },
98
124
  fetchUsageSnapshot: async (ctx) => {
99
- const { fetchCodexAppServerUsageSnapshot } = await import("./usage-Bj-rrzkR.js");
125
+ const { fetchCodexAppServerUsageSnapshot } = await import("./usage-CPPTmBvZ.js");
100
126
  return await fetchCodexAppServerUsageSnapshot(ctx, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
101
127
  },
102
128
  loadModelCatalog: async (params) => {
103
- const { createCodexAppServerModelCatalog } = await import("./model-catalog-CUM68Hkl.js");
129
+ const { createCodexAppServerModelCatalog } = await import("./model-catalog-B_6M04Wo.js");
104
130
  if (disposed) return [];
105
131
  modelCatalog ??= createCodexAppServerModelCatalog(harnessRuntimeId);
106
132
  return await modelCatalog.load(params, resolveAttemptPluginConfig(params.config));
107
133
  },
108
134
  readModelCatalogReadiness: (params) => modelCatalog?.read(params, resolveAttemptPluginConfig(params.config)),
109
135
  loadMcpToolCatalog: async (params) => {
110
- const { loadCodexEffectiveMcpCatalog } = await import("./effective-mcp-catalog-DzYBW4h1.js");
136
+ const { loadCodexEffectiveMcpCatalog } = await import("./effective-mcp-catalog-J_5Ep5Um.js");
111
137
  return await loadCodexEffectiveMcpCatalog(params, { bindingStore: options.bindingStore });
112
138
  },
113
139
  supports: (ctx) => {
@@ -150,7 +176,7 @@ function createCodexAppServerAgentHarness(options) {
150
176
  };
151
177
  },
152
178
  runAttempt: async (params) => {
153
- const { runCodexAppServerAttempt } = await import("./run-attempt-D1hJO4fX.js");
179
+ const { runCodexAppServerAttempt } = await import("./run-attempt-DwKds3DN.js");
154
180
  return runCodexAppServerAttempt(params, {
155
181
  bindingStore: options.bindingStore,
156
182
  pluginConfig: resolveAttemptPluginConfig(params.config),
@@ -160,11 +186,15 @@ function createCodexAppServerAgentHarness(options) {
160
186
  });
161
187
  },
162
188
  runIsolatedCompletionV2: async (params) => {
163
- if (params.authorization.owner === "host") return runHostPreparedIsolatedCompletion(params);
164
- const { runCodexIsolatedCompletion } = await import("./isolated-completion-kg9kv4iH.js");
189
+ if (params.authorization.owner === "host") {
190
+ const { runHostPreparedIsolatedCompletion } = await import("openclaw/plugin-sdk/simple-completion-runtime");
191
+ return runHostPreparedIsolatedCompletion(params);
192
+ }
193
+ const { runCodexIsolatedCompletion } = await import("./isolated-completion-DHBefrzg.js");
165
194
  return runCodexIsolatedCompletion(params, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
166
195
  },
167
196
  runIsolatedCompletion: async (params) => {
197
+ const { runHostPreparedIsolatedCompletion } = await import("openclaw/plugin-sdk/simple-completion-runtime");
168
198
  return runHostPreparedIsolatedCompletion({
169
199
  ...params,
170
200
  authorization: {
@@ -176,11 +206,11 @@ function createCodexAppServerAgentHarness(options) {
176
206
  });
177
207
  },
178
208
  finalizeSettledTurn: async (params) => {
179
- const { runCodexSettledTurnFinalization } = await import("./settled-turn-finalizer-BVJx4yoc.js");
209
+ const { runCodexSettledTurnFinalization } = await import("./settled-turn-finalizer-BuLUrZl2.js");
180
210
  return runCodexSettledTurnFinalization(params, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
181
211
  },
182
212
  runSideQuestion: async (params) => {
183
- const { runCodexAppServerSideQuestion } = await import("./side-question-BTZAII4l.js");
213
+ const { runCodexAppServerSideQuestion } = await import("./side-question-DLbr2vUU.js");
184
214
  return runCodexAppServerSideQuestion(params, {
185
215
  bindingStore: options.bindingStore,
186
216
  pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
@@ -190,20 +220,20 @@ function createCodexAppServerAgentHarness(options) {
190
220
  });
191
221
  },
192
222
  compact: async (params) => {
193
- const { maybeCompactCodexAppServerSession } = await import("./compact-_t0HQrUS.js");
223
+ const { maybeCompactCodexAppServerSession } = await import("./compact-CGJZ2rlb.js");
194
224
  return maybeCompactCodexAppServerSession(params, {
195
225
  bindingStore: options.bindingStore,
196
226
  pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig
197
227
  });
198
228
  },
199
229
  withSessionDeletion: async (params, run) => {
200
- const { withCodexAppServerSessionDeletion } = await import("./session-retirement-BujDjXVF.js");
230
+ const { withCodexAppServerSessionDeletion } = await import("./session-retirement-BSNG_mhf.js");
201
231
  params.assertCurrent();
202
232
  return withCodexAppServerSessionDeletion(options.bindingStore, params, run);
203
233
  },
204
234
  reset: async (params) => {
205
235
  if (params.sessionId && params.reason !== "deleted") {
206
- const [{ reclaimCurrentCodexSessionGeneration, sessionBindingIdentity }, { retireCodexAppServerSessionGeneration }] = await Promise.all([import("./session-binding-BHuTCRZQ.js").then((n) => n.f), import("./session-retirement-BujDjXVF.js")]);
236
+ const [{ reclaimCurrentCodexSessionGeneration }, { retireCodexAppServerSessionGeneration }] = await Promise.all([import("./session-binding-CKSepwIC.js").then((n) => n.c), import("./session-retirement-BSNG_mhf.js")]);
207
237
  const identity = sessionBindingIdentity({
208
238
  agentId: params.agentId,
209
239
  sessionId: params.sessionId,
@@ -235,7 +265,7 @@ function createCodexAppServerAgentHarness(options) {
235
265
  /** Creates the private native-compaction bridge registered in host-owned capability state. */
236
266
  function createCodexAppServerNativeCompaction(options) {
237
267
  return async (params) => {
238
- const { maybeCompactCodexAppServerSession } = await import("./compact-_t0HQrUS.js");
268
+ const { maybeCompactCodexAppServerSession } = await import("./compact-CGJZ2rlb.js");
239
269
  return maybeCompactCodexAppServerSession(params, {
240
270
  bindingStore: options.bindingStore,
241
271
  pluginConfig: options.resolvePluginConfig?.() ?? options.pluginConfig,
package/dist/harness.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as createCodexAppServerNativeCompaction, t as createCodexAppServerAgentHarness } from "./harness-DXVZ5II5.js";
1
+ import { n as createCodexAppServerNativeCompaction, t as createCodexAppServerAgentHarness } from "./harness-FR6eQgyO.js";
2
2
  export { createCodexAppServerAgentHarness, createCodexAppServerNativeCompaction };
@@ -0,0 +1,13 @@
1
+ //#region extensions/codex/src/app-server/history-rejection.ts
2
+ /** Only an owning rejection site can supply a diagnostic; exception text is never evidence. */
3
+ var CodexHistoryRejection = class extends Error {
4
+ constructor(reason) {
5
+ super(`Codex history rejected: ${reason}`);
6
+ this.reason = reason;
7
+ }
8
+ };
9
+ function codexHistoryRejectionReason(error) {
10
+ return error instanceof CodexHistoryRejection ? error.reason : "history_read_failed";
11
+ }
12
+ //#endregion
13
+ export { codexHistoryRejectionReason as n, CodexHistoryRejection as t };
@@ -24,42 +24,56 @@ function sanitizeImageContentRecord(record, label) {
24
24
  };
25
25
  const commaIndex = imageUrl.indexOf(",");
26
26
  const mime = imageUrl.slice(INLINE_IMAGE_DATA_URL_PREFIX.length, commaIndex).split(";")[0] ?? mimeType;
27
- return {
27
+ const data = imageUrl.slice(commaIndex + 1);
28
+ return mime === record.mimeType && data === record.data ? record : {
28
29
  ...record,
29
30
  mimeType: mime,
30
- data: imageUrl.slice(commaIndex + 1)
31
+ data
31
32
  };
32
33
  }
33
34
  if (record.type === "inputImage" && typeof record.imageUrl === "string") {
34
35
  const imageUrl = sanitizeInlineImageDataUrl$1(record.imageUrl);
35
- return imageUrl ? {
36
- ...record,
37
- imageUrl
38
- } : {
36
+ if (!imageUrl) return {
39
37
  type: "inputText",
40
38
  text: invalidInlineImageText(label)
41
39
  };
40
+ return imageUrl === record.imageUrl ? record : {
41
+ ...record,
42
+ imageUrl
43
+ };
42
44
  }
43
45
  if (record.type === "input_image" && typeof record.image_url === "string") {
44
46
  const imageUrl = sanitizeInlineImageDataUrl$1(record.image_url);
45
- return imageUrl ? {
46
- ...record,
47
- image_url: imageUrl
48
- } : {
47
+ if (!imageUrl) return {
49
48
  type: "input_text",
50
49
  text: invalidInlineImageText(label)
51
50
  };
51
+ return imageUrl === record.image_url ? record : {
52
+ ...record,
53
+ image_url: imageUrl
54
+ };
52
55
  }
53
56
  }
54
- /** Recursively sanitizes all Codex history image shapes while preserving unknown structure. */
57
+ /** Sanitizes images without copying unchanged history or mutating its owned snapshot. */
55
58
  function sanitizeCodexHistoryImagePayloads(value, label) {
56
- if (Array.isArray(value)) return value.map((entry) => sanitizeCodexHistoryImagePayloads(entry, label));
59
+ if (Array.isArray(value)) {
60
+ let next;
61
+ for (let index = 0; index < value.length; index++) {
62
+ const child = sanitizeCodexHistoryImagePayloads(value[index], label);
63
+ if (child !== value[index]) (next ??= value.slice())[index] = child;
64
+ }
65
+ return next ?? value;
66
+ }
57
67
  if (!isRecord(value)) return value;
58
68
  const imageRecord = sanitizeImageContentRecord(value, label);
59
69
  if (imageRecord) return imageRecord;
60
- const next = {};
61
- for (const [key, child] of Object.entries(value)) next[key] = sanitizeCodexHistoryImagePayloads(child, label);
62
- return next;
70
+ let next;
71
+ for (const key in value) {
72
+ if (!Object.hasOwn(value, key)) continue;
73
+ const child = sanitizeCodexHistoryImagePayloads(value[key], label);
74
+ if (child !== value[key]) (next ??= { ...value })[key] = child;
75
+ }
76
+ return next ?? value;
63
77
  }
64
78
  //#endregion
65
79
  export { sanitizeCodexHistoryImagePayloads as n, sanitizeInlineImageDataUrl$1 as r, invalidInlineImageText as t };
@@ -0,0 +1,15 @@
1
+ import { resolveGlobalSingleton } from "openclaw/plugin-sdk/global-singleton";
2
+ import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
3
+ import { isIncognitoSessionKey as isIncognitoSessionKey$1 } from "openclaw/plugin-sdk/session-key-runtime";
4
+ //#region extensions/codex/src/app-server/thread-ownership-queue.ts
5
+ const nativeThreadOwners = resolveGlobalSingleton(Symbol.for("openclaw.codexNativeThreadOwners"), () => new KeyedAsyncQueue());
6
+ /** Serialize OpenClaw-owned lifecycle changes, not native-internal thread controllers. */
7
+ async function withCodexAppServerThreadMutation(threadId, run) {
8
+ return await nativeThreadOwners.enqueue(`thread:${threadId}`, run);
9
+ }
10
+ /** Serializes bound turns and retirement so detach cannot unsubscribe an active turn. */
11
+ async function withCodexConversationThreadActivity(bindingId, run) {
12
+ return await nativeThreadOwners.enqueue(`conversation:${bindingId}`, run);
13
+ }
14
+ //#endregion
15
+ export { withCodexAppServerThreadMutation as n, withCodexConversationThreadActivity as r, isIncognitoSessionKey$1 as t };