@openclaw/codex 2026.7.2-beta.5 → 2026.8.1-beta.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.
Files changed (59) hide show
  1. package/README.md +2 -0
  2. package/dist/{app-server-policy-BmDgseo_.js → app-server-policy-zcBDc1JU.js} +1 -1
  3. package/dist/attempt-client-cleanup-DMLXUfa8.js +735 -0
  4. package/dist/binding-connection-I5Bo-AsX.js +33 -0
  5. package/dist/{bounded-turn-FEbUXoYT.js → bounded-turn-qgZmzy_4.js} +71 -63
  6. package/dist/{capabilities-BHRSI6Cn.js → capabilities-CybGI1oz.js} +8 -2
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-ico4ZFnk.js → command-formatters-B1AEz8ZA.js} +18 -18
  9. package/dist/{command-handlers-CRmnwI2N.js → command-handlers-Db8pu_ds.js} +484 -95
  10. package/dist/{compact-dEN49UH6.js → compact-LspQaGfl.js} +213 -199
  11. package/dist/{conversation-binding-data-BHRpYbX3.js → conversation-binding-data-CW2GuupV.js} +6 -10
  12. package/dist/doctor-contract-api.js +40 -43
  13. package/dist/{dynamic-tools-LIt9ojep.js → dynamic-tools-BVdyWkUD.js} +2984 -1221
  14. package/dist/effective-mcp-catalog-DIIhAtOZ.js +119 -0
  15. package/dist/{event-projector-assistant-message-DTgnPPVF.js → event-projector-assistant-message-BwxV4d6N.js} +11 -23
  16. package/dist/{attempt-notifications-CMR2_fmR.js → event-projector-usage-e5huIQWu.js} +113 -29
  17. package/dist/harness.js +83 -13
  18. package/dist/image-payload-sanitizer-CnfoUPCE.js +65 -0
  19. package/dist/index.js +703 -329
  20. package/dist/isolated-completion-C58NbL40.js +75 -0
  21. package/dist/local-runtime-attribution-B_2mnqhb.js +19 -0
  22. package/dist/media-understanding-provider.js +5 -5
  23. package/dist/{models-BA01NEez.js → models-BFlpn1Ex.js} +12 -17
  24. package/dist/native-subagent-monitor-DyTGmTUx.js +3111 -0
  25. package/dist/{plugin-app-cache-key-DSXX-rXO.js → plugin-app-cache-key-C3H2CVp6.js} +135 -42
  26. package/dist/plugin-marketplace-discovery-CzrGJdCR.js +385 -0
  27. package/dist/{computer-use-BjGylO-E.js → plugin-metadata-cache-CNJPj4_b.js} +211 -113
  28. package/dist/protocol-validators-B4F7L8Rf.js +2346 -0
  29. package/dist/{rate-limits-S_PXs0ul.js → rate-limits-DZXmOL8-.js} +17 -35
  30. package/dist/{request-CXpPennK.js → request-BRl5_UfX.js} +4 -4
  31. package/dist/{run-attempt-C5GTPJOE.js → run-attempt-P8BdxC1I.js} +1996 -5728
  32. package/dist/{runtime-artifact-C2ITXdhM.js → runtime-artifact-BVSPdd6g.js} +91 -40
  33. package/dist/{sandbox-guard-D1Wky__S.js → sandbox-guard-Cmwc9eIk.js} +10 -13
  34. package/dist/{session-binding-DlVQ-Pxs.js → session-binding-DPxIvMgE.js} +305 -271
  35. package/dist/{session-catalog-CP2oCcEb.js → session-catalog-xwNi_SDM.js} +418 -144
  36. package/dist/{session-cli-CqZ0Fp2a.js → session-cli-7hgXZDV7.js} +1 -1
  37. package/dist/session-retirement-DoMMJFKm.js +36 -0
  38. package/dist/{session-upstream-marker-QE-m5QFG.js → session-upstream-marker-CrIFX06J.js} +1 -1
  39. package/dist/{settled-turn-finalizer-CA_2QXIE.js → settled-turn-finalizer-BRWBO4MO.js} +36 -15
  40. package/dist/{shared-client-BVKE40c-.js → shared-client-kIBbGjk4.js} +721 -240
  41. package/dist/{side-question-CO12sHxo.js → side-question-9HAL26l9.js} +102 -53
  42. package/dist/{thread-lifecycle-DRg_FdzC.js → thread-lifecycle-Bu1BTDXr.js} +1355 -660
  43. package/dist/thread-ownership-6kOQHlyC.js +92 -0
  44. package/dist/thread-resume-CPrJNQVM.js +30 -0
  45. package/dist/{transcript-mirror-uKA-A4tB.js → transcript-mirror-B9gGgnJS.js} +202 -182
  46. package/dist/{transport-stdio-DXgGZ7Ib.js → transport-stdio-DIImwDVS.js} +11 -0
  47. package/dist/upstream-prompt-provenance-ClRBije0.js +41 -0
  48. package/dist/{upstream-session-fork-_Vrz4WJr.js → upstream-session-fork-CE-_LdnP.js} +5 -5
  49. package/dist/{usage-UpVbdX5G.js → usage-CHlV0e-o.js} +3 -3
  50. package/dist/{web-search-provider.runtime-CaQMYDbp.js → web-search-provider.runtime-DRw2Vl42.js} +8 -9
  51. package/openclaw.plugin.json +18 -3
  52. package/package.json +6 -7
  53. package/dist/attempt-client-cleanup-Ia52yRWc.js +0 -127
  54. package/dist/conversation-control-DE7d9DOj.js +0 -287
  55. package/dist/event-projector-usage-tvgb1NCX.js +0 -69
  56. package/dist/notification-correlation-Bj_Ak_jI.js +0 -67
  57. package/dist/protocol-validators-Dm4eXZmt.js +0 -6337
  58. package/dist/realtime-voice-api-BPcA1uN9.js +0 -494
  59. package/dist/realtime-voice-api.js +0 -2
@@ -10,6 +10,12 @@ const UNSAFE_ENVIRONMENT_KEYS = /* @__PURE__ */ new Set([
10
10
  "constructor",
11
11
  "prototype"
12
12
  ]);
13
+ const RUNTIME_INJECTION_ENVIRONMENT_KEYS = /* @__PURE__ */ new Set([
14
+ "NODE_PATH",
15
+ "LD_AUDIT",
16
+ "LD_LIBRARY_PATH",
17
+ "LD_PRELOAD"
18
+ ]);
13
19
  const QA_PARENT_PID_ENV = "OPENCLAW_QA_PARENT_PID";
14
20
  const DEFAULT_SPAWN_RUNTIME = {
15
21
  platform: process.platform,
@@ -43,8 +49,13 @@ function resolveCodexAppServerSpawnEnv(options, baseEnv = process.env, platform
43
49
  const lowerCaseKeysToClear = new Set(keysToClear.map((key) => key.toLowerCase()));
44
50
  for (const candidate of Object.keys(env)) if (lowerCaseKeysToClear.has(candidate.toLowerCase())) delete env[candidate];
45
51
  } else for (const key of keysToClear) delete env[key];
52
+ for (const key of Object.keys(env)) if (isCodexRuntimeInjectionEnvironmentKey(key)) delete env[key];
46
53
  return env;
47
54
  }
55
+ function isCodexRuntimeInjectionEnvironmentKey(rawKey) {
56
+ const key = rawKey.toUpperCase();
57
+ return RUNTIME_INJECTION_ENVIRONMENT_KEYS.has(key) || key.startsWith("DYLD_");
58
+ }
48
59
  /** Keeps QA-owned app-server processes inside the gateway process-group cleanup boundary. */
49
60
  function resolveCodexAppServerDetachedMode(env, platform = process.platform) {
50
61
  return platform !== "win32" && !env[QA_PARENT_PID_ENV]?.trim();
@@ -0,0 +1,41 @@
1
+ //#region extensions/codex/src/app-server/upstream-prompt-provenance.ts
2
+ const UPSTREAM_USER_TEXT_META_KEY = "upstreamUserText";
3
+ const MIRROR_IDENTITY_META_KEY = "mirrorIdentity";
4
+ function attachCodexMirrorIdentity(message, identity) {
5
+ const record = message;
6
+ const existing = record["__openclaw"];
7
+ const baseMeta = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
8
+ return {
9
+ ...record,
10
+ __openclaw: {
11
+ ...baseMeta,
12
+ [MIRROR_IDENTITY_META_KEY]: identity
13
+ }
14
+ };
15
+ }
16
+ function readMirrorIdentity(message) {
17
+ const meta = message["__openclaw"];
18
+ if (!meta || typeof meta !== "object" || Array.isArray(meta)) return;
19
+ const id = meta[MIRROR_IDENTITY_META_KEY];
20
+ return typeof id === "string" && id ? id : void 0;
21
+ }
22
+ function attachUpstreamUserText(message, text) {
23
+ const record = message;
24
+ const existing = record["__openclaw"];
25
+ const baseMeta = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
26
+ return {
27
+ ...record,
28
+ __openclaw: {
29
+ ...baseMeta,
30
+ [UPSTREAM_USER_TEXT_META_KEY]: text
31
+ }
32
+ };
33
+ }
34
+ function readUpstreamUserText(message) {
35
+ const meta = message?.["__openclaw"];
36
+ if (!meta || typeof meta !== "object" || Array.isArray(meta)) return;
37
+ const text = meta[UPSTREAM_USER_TEXT_META_KEY];
38
+ return typeof text === "string" && text ? text : void 0;
39
+ }
40
+ //#endregion
41
+ export { readUpstreamUserText as i, attachUpstreamUserText as n, readMirrorIdentity as r, attachCodexMirrorIdentity as t };
@@ -1,8 +1,8 @@
1
- import { l as sessionBindingIdentity } from "./session-binding-DlVQ-Pxs.js";
2
- import { n as assertCodexThreadForkResponse } from "./protocol-validators-Dm4eXZmt.js";
1
+ import { d as sessionBindingIdentity } from "./session-binding-DPxIvMgE.js";
2
+ import { r as assertCodexThreadForkResponse } from "./protocol-validators-B4F7L8Rf.js";
3
3
  import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
4
- import { i as createImportedCodexSession, n as codexUpstreamBaseline, t as codexLastTerminalTurnId } from "./session-upstream-marker-QE-m5QFG.js";
5
- import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
4
+ import { i as createImportedCodexSession, n as codexUpstreamBaseline, t as codexLastTerminalTurnId } from "./session-upstream-marker-CrIFX06J.js";
5
+ import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import { readVisibleSessionTranscriptMessageEntries } from "openclaw/plugin-sdk/session-transcript-runtime";
7
7
  import { deleteSessionUpstreamLink, upsertSessionUpstreamLink } from "openclaw/plugin-sdk/session-catalog";
8
8
  //#region extensions/codex/src/app-server/upstream-fork-boundary.ts
@@ -167,7 +167,7 @@ function readConnectionFingerprint(ref) {
167
167
  return typeof ref.connectionFingerprint === "string" && ref.connectionFingerprint.trim() ? ref.connectionFingerprint : void 0;
168
168
  }
169
169
  function normalizeTurnId(value) {
170
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
170
+ return normalizeOptionalString(value);
171
171
  }
172
172
  async function forkCodexUpstreamSession(params, options) {
173
173
  try {
@@ -1,6 +1,6 @@
1
- import { p as resolveCodexAppServerRuntimeOptions } from "./session-binding-DlVQ-Pxs.js";
2
- import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-S_PXs0ul.js";
3
- import { t as readCodexAppServerUsage } from "./request-CXpPennK.js";
1
+ import { g as resolveCodexAppServerRuntimeOptions } from "./session-binding-DPxIvMgE.js";
2
+ import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-DZXmOL8-.js";
3
+ import { t as readCodexAppServerUsage } from "./request-BRl5_UfX.js";
4
4
  import { CODEX_APP_SERVER_AUTH_MARKER } from "openclaw/plugin-sdk/agent-runtime";
5
5
  //#region extensions/codex/src/app-server/usage.ts
6
6
  /** Handles the synthetic usage credential for a Codex-backed OpenAI route. */
@@ -1,6 +1,7 @@
1
- import { V as isJsonObject } from "./shared-client-BVKE40c-.js";
2
- import { m as buildCodexNativeWebSearchThreadConfig } from "./thread-lifecycle-DRg_FdzC.js";
3
- import { t as runBoundedCodexAppServerTurn } from "./bounded-turn-FEbUXoYT.js";
1
+ import { ct as isJsonObject } from "./shared-client-kIBbGjk4.js";
2
+ import { d as buildCodexNativeWebSearchThreadConfig } from "./thread-lifecycle-Bu1BTDXr.js";
3
+ import { t as runBoundedCodexAppServerTurn } from "./bounded-turn-qgZmzy_4.js";
4
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
5
  import { readStringParam, resolveSearchTimeoutSeconds, wrapWebContent } from "openclaw/plugin-sdk/provider-web-search";
5
6
  //#region extensions/codex/src/web-search-provider.runtime.ts
6
7
  async function executeCodexWebSearchProviderTool(ctx, args, executionContext, options) {
@@ -9,6 +10,7 @@ async function executeCodexWebSearchProviderTool(ctx, args, executionContext, op
9
10
  const result = await runBoundedCodexAppServerTurn({
10
11
  config: ctx.config,
11
12
  model: { mode: "live-default" },
13
+ modelProvider: "openai",
12
14
  timeoutMs: resolveSearchTimeoutSeconds(ctx.searchConfig) * 1e3,
13
15
  signal: executionContext?.signal,
14
16
  agentDir: ctx.agentDir,
@@ -45,7 +47,7 @@ function summarizeCodexWebSearchItem(item) {
45
47
  const action = isJsonObject(item.action) ? item.action : void 0;
46
48
  const actionType = readNonEmptyString(action, "type");
47
49
  const queries = actionType === "search" ? readNonEmptyStringArray(action, "queries") : [];
48
- const query = normalizeNonEmptyString(item.query) ?? (actionType === "search" ? readNonEmptyString(action, "query") : void 0) ?? queries[0];
50
+ const query = normalizeOptionalString(item.query) ?? (actionType === "search" ? readNonEmptyString(action, "query") : void 0) ?? queries[0];
49
51
  const url = readNonEmptyString(action, "url");
50
52
  const pattern = readNonEmptyString(action, "pattern");
51
53
  return {
@@ -57,18 +59,15 @@ function summarizeCodexWebSearchItem(item) {
57
59
  };
58
60
  }
59
61
  function readNonEmptyString(record, key) {
60
- return record ? normalizeNonEmptyString(record[key]) : void 0;
62
+ return record ? normalizeOptionalString(record[key]) : void 0;
61
63
  }
62
64
  function readNonEmptyStringArray(record, key) {
63
65
  const value = record?.[key];
64
66
  if (!Array.isArray(value)) return [];
65
67
  return value.flatMap((entry) => {
66
- const normalized = normalizeNonEmptyString(entry);
68
+ const normalized = normalizeOptionalString(entry);
67
69
  return normalized ? [normalized] : [];
68
70
  });
69
71
  }
70
- function normalizeNonEmptyString(value) {
71
- return typeof value === "string" ? value.trim() || void 0 : void 0;
72
- }
73
72
  //#endregion
74
73
  export { executeCodexWebSearchProviderTool };
@@ -1,5 +1,19 @@
1
1
  {
2
2
  "id": "codex",
3
+ "doctorContract": {
4
+ "configRepair": true,
5
+ "stateMigrations": true
6
+ },
7
+ "sessionRouteStateOwners": [
8
+ {
9
+ "id": "codex",
10
+ "label": "Codex",
11
+ "providerIds": ["codex", "codex-cli", "openai-codex"],
12
+ "runtimeIds": ["codex", "codex-cli"],
13
+ "cliSessionKeys": ["codex-cli"],
14
+ "authProfilePrefixes": ["codex:", "codex-cli:", "openai-codex:"]
15
+ }
16
+ ],
3
17
  "name": "Codex",
4
18
  "description": "Codex app-server harness and native session catalog.",
5
19
  "contracts": {
@@ -7,6 +21,7 @@
7
21
  "migrationProviders": ["codex"],
8
22
  "tools": [
9
23
  "codex_threads",
24
+ "codex_plugins",
10
25
  "codex_endpoint_probe",
11
26
  "codex_sessions_list",
12
27
  "codex_session_read",
@@ -28,6 +43,7 @@
28
43
  "onAgentHarnesses": ["codex"],
29
44
  "onCommands": ["codex"],
30
45
  "onConfigPaths": [
46
+ "plugins.entries.codex.config.appServer.transport",
31
47
  "plugins.entries.codex.config.sessionCatalog.enabled",
32
48
  "plugins.entries.codex.config.supervision.enabled"
33
49
  ]
@@ -167,7 +183,7 @@
167
183
  },
168
184
  "marketplaceName": {
169
185
  "type": "string",
170
- "enum": ["openai-curated", "workspace-directory"]
186
+ "pattern": "^[A-Za-z0-9_-]+$"
171
187
  },
172
188
  "pluginName": {
173
189
  "type": "string"
@@ -235,8 +251,7 @@
235
251
  },
236
252
  "homeScope": {
237
253
  "type": "string",
238
- "enum": ["agent", "user"],
239
- "default": "agent"
254
+ "enum": ["agent", "user"]
240
255
  },
241
256
  "command": { "type": "string" },
242
257
  "args": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/codex",
3
- "version": "2026.7.2-beta.5",
3
+ "version": "2026.8.1-beta.2",
4
4
  "description": "OpenClaw Codex app-server harness and native session supervision plugin.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,9 +8,8 @@
8
8
  },
9
9
  "type": "module",
10
10
  "dependencies": {
11
- "@openai/codex": "0.145.0",
12
- "semver": "7.8.5",
13
- "smol-toml": "1.7.0",
11
+ "@openai/codex": "0.147.0",
12
+ "smol-toml": "1.7.1",
14
13
  "typebox": "1.3.6",
15
14
  "ws": "8.21.1",
16
15
  "zod": "4.4.3"
@@ -36,10 +35,10 @@
36
35
  ]
37
36
  },
38
37
  "compat": {
39
- "pluginApi": ">=2026.7.2-beta.5"
38
+ "pluginApi": ">=2026.8.1-beta.2"
40
39
  },
41
40
  "build": {
42
- "openclawVersion": "2026.7.2-beta.5"
41
+ "openclawVersion": "2026.8.1-beta.2"
43
42
  },
44
43
  "release": {
45
44
  "publishToClawHub": true,
@@ -59,7 +58,7 @@
59
58
  "README.md"
60
59
  ],
61
60
  "peerDependencies": {
62
- "openclaw": ">=2026.7.2-beta.5"
61
+ "openclaw": ">=2026.8.1-beta.2"
63
62
  },
64
63
  "peerDependenciesMeta": {
65
64
  "openclaw": {
@@ -1,127 +0,0 @@
1
- import { f as retireSharedCodexAppServerClientIfCurrent, n as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, t as clearSharedCodexAppServerClientIfCurrent } from "./shared-client-BVKE40c-.js";
2
- import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
3
- //#region extensions/codex/src/app-server/attempt-client-cleanup.ts
4
- /**
5
- * Best-effort cleanup helpers for Codex app-server startup attempts and turns.
6
- */
7
- /** Timeout for best-effort app-server turn interruption during cleanup. */
8
- const CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS = 5e3;
9
- /** Timeout for best-effort thread unsubscribe during cleanup. */
10
- const CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS = 5e3;
11
- /** Raised when a thread subscription may be live on a client OpenClaw no longer controls. */
12
- var CodexAppServerUnsafeSubscriptionError = class extends Error {
13
- constructor(message, options) {
14
- super(message, options);
15
- this.name = "CodexAppServerUnsafeSubscriptionError";
16
- }
17
- };
18
- function isCodexAppServerUnsafeSubscriptionError(error) {
19
- return error instanceof CodexAppServerUnsafeSubscriptionError;
20
- }
21
- /** Asserts Codex resumed the exact thread this attempt subscribed to. */
22
- function assertCodexThreadResumeSubscription(requestedThreadId, returnedThreadId) {
23
- if (returnedThreadId !== requestedThreadId) throw new CodexAppServerUnsafeSubscriptionError(`Codex thread/resume returned ${returnedThreadId} for ${requestedThreadId}`);
24
- }
25
- async function closeClientAndWaitIfAvailable(client) {
26
- const closeable = client;
27
- if (typeof closeable.closeAndWait === "function") {
28
- await closeable.closeAndWait();
29
- return;
30
- }
31
- closeable.close?.();
32
- }
33
- async function closeCodexStartupClientBestEffort(client) {
34
- if (!client) return;
35
- const unclaimedSharedClient = clearSharedCodexAppServerClientIfCurrentAndUnclaimed(client);
36
- if (unclaimedSharedClient.closed) {
37
- await closeClientAndWaitIfAvailable(client);
38
- return;
39
- }
40
- if (unclaimedSharedClient.found) {
41
- if (retireSharedCodexAppServerClientIfCurrent(client)?.closed) await closeClientAndWaitIfAvailable(client);
42
- return;
43
- }
44
- const retiredSharedClient = retireSharedCodexAppServerClientIfCurrent(client);
45
- if (retiredSharedClient) {
46
- if (retiredSharedClient.closed) await closeClientAndWaitIfAvailable(client);
47
- return;
48
- }
49
- if (clearSharedCodexAppServerClientIfCurrent(client)) {
50
- await closeClientAndWaitIfAvailable(client);
51
- return;
52
- }
53
- await closeClientAndWaitIfAvailable(client);
54
- }
55
- /** Sends a turn interrupt without blocking abort cleanup on app-server errors. */
56
- function interruptCodexTurnBestEffort(client, params) {
57
- interruptCodexTurnAndWaitBestEffort(client, params);
58
- }
59
- /** Sends a bounded turn interrupt and waits for Codex to confirm terminal abort handling. */
60
- async function interruptCodexTurnAndWaitBestEffort(client, params) {
61
- const requestOptions = params.timeoutMs && Number.isFinite(params.timeoutMs) && params.timeoutMs > 0 ? { timeoutMs: params.timeoutMs } : void 0;
62
- const requestParams = {
63
- threadId: params.threadId,
64
- turnId: params.turnId
65
- };
66
- try {
67
- await (requestOptions ? client.request("turn/interrupt", requestParams, requestOptions) : client.request("turn/interrupt", requestParams));
68
- } catch (error) {
69
- embeddedAgentLog.debug("codex app-server turn interrupt failed during abort", { error });
70
- }
71
- }
72
- /** Unsubscribes from a thread while swallowing cleanup-only failures. */
73
- async function unsubscribeCodexThreadBestEffort(client, params) {
74
- try {
75
- await client.request("thread/unsubscribe", { threadId: params.threadId }, { timeoutMs: params.timeoutMs });
76
- return true;
77
- } catch (error) {
78
- embeddedAgentLog.debug("codex app-server thread unsubscribe cleanup failed", {
79
- threadId: params.threadId,
80
- error
81
- });
82
- return false;
83
- }
84
- }
85
- /**
86
- * Retires the shared client after a timed-out turn so later runs do not reuse a
87
- * potentially wedged app-server connection.
88
- */
89
- async function retireCodexAppServerClientAfterTimedOutTurn(client, params) {
90
- const retiredSharedClient = retireSharedCodexAppServerClientIfCurrent(client, { failActiveLeases: params.suspectPhysicalClient });
91
- const detachedSharedClient = Boolean(retiredSharedClient);
92
- if (!(params.suspectPhysicalClient && (retiredSharedClient?.closed ?? false))) {
93
- interruptCodexTurnBestEffort(client, {
94
- threadId: params.threadId,
95
- turnId: params.turnId,
96
- timeoutMs: CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS
97
- });
98
- await unsubscribeCodexThreadBestEffort(client, {
99
- threadId: params.threadId,
100
- timeoutMs: CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS
101
- });
102
- }
103
- let closedClient = retiredSharedClient?.closed ?? false;
104
- if (!detachedSharedClient) {
105
- const close = client.close;
106
- if (typeof close === "function") try {
107
- close.call(client);
108
- closedClient = true;
109
- } catch (error) {
110
- embeddedAgentLog.debug("codex app-server client close failed during timeout cleanup", {
111
- threadId: params.threadId,
112
- turnId: params.turnId,
113
- error
114
- });
115
- }
116
- }
117
- embeddedAgentLog.warn("codex app-server client retired after timed-out turn", {
118
- threadId: params.threadId,
119
- turnId: params.turnId,
120
- reason: params.reason,
121
- detachedSharedClient,
122
- closedClient,
123
- activeSharedClientLeases: retiredSharedClient?.activeLeases ?? 0
124
- });
125
- }
126
- //#endregion
127
- export { closeCodexStartupClientBestEffort as a, isCodexAppServerUnsafeSubscriptionError as c, assertCodexThreadResumeSubscription as i, retireCodexAppServerClientAfterTimedOutTurn as l, CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS as n, interruptCodexTurnAndWaitBestEffort as o, CodexAppServerUnsafeSubscriptionError as r, interruptCodexTurnBestEffort as s, CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS as t, unsubscribeCodexThreadBestEffort as u };
@@ -1,287 +0,0 @@
1
- import { a as getLeasedSharedCodexAppServerClient, c as releaseCodexAppServerClientLease, l as releaseLeasedSharedCodexAppServerClient, m as withLeasedCodexAppServerClientStartSelectionRetry } from "./shared-client-BVKE40c-.js";
2
- import { O as isCodexFastServiceTier, S as resolveCodexModelBackedReviewerPolicyContext, o as isCodexAppServerNativeAuthProfile, p as resolveCodexAppServerRuntimeOptions, r as bindingStoreKey, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-DlVQ-Pxs.js";
3
- import { x as resolveCodexBindingModelProviderFallback, y as resolveCodexAppServerRequestModelSelection } from "./thread-lifecycle-DRg_FdzC.js";
4
- import { t as CODEX_CONTROL_METHODS } from "./capabilities-BHRSI6Cn.js";
5
- import { r as formatCodexDisplayText } from "./command-formatters-ico4ZFnk.js";
6
- import { a as resolveCodexBindingAppServerConnection } from "./notification-correlation-Bj_Ak_jI.js";
7
- import { ModelSelectionLockedError } from "openclaw/plugin-sdk/model-session-runtime";
8
- //#region extensions/codex/src/command-authorization.ts
9
- const CODEX_NATIVE_EXECUTION_AUTH_ERROR = "Only an owner or operator.admin can control Codex native execution.";
10
- function canMutateCodexHost(ctx) {
11
- return ctx.senderIsOwner === true || ctx.gatewayClientScopes?.includes("operator.admin") === true;
12
- }
13
- //#endregion
14
- //#region extensions/codex/src/conversation-control.ts
15
- const CODEX_CONVERSATION_CONTROL_STATE = Symbol.for("openclaw.codex.conversationControl");
16
- function getActiveTurns() {
17
- const globalState = globalThis;
18
- globalState[CODEX_CONVERSATION_CONTROL_STATE] ??= /* @__PURE__ */ new Map();
19
- return globalState[CODEX_CONVERSATION_CONTROL_STATE];
20
- }
21
- function trackCodexConversationActiveTurn(active) {
22
- const activeTurns = getActiveTurns();
23
- const key = bindingStoreKey(active.identity);
24
- activeTurns.set(key, active);
25
- return () => {
26
- if (activeTurns.get(key)?.turnId === active.turnId) activeTurns.delete(key);
27
- };
28
- }
29
- function readCodexConversationActiveTurn(identity) {
30
- return getActiveTurns().get(bindingStoreKey(identity));
31
- }
32
- async function stopCodexConversationTurn(params) {
33
- const active = readCodexConversationActiveTurn(params.identity);
34
- if (!active) return {
35
- stopped: false,
36
- message: "No active Codex run to stop."
37
- };
38
- const lookup = buildBindingLookup(params);
39
- const binding = await params.bindingStore.read(params.identity);
40
- if (binding?.threadId !== active.threadId) return {
41
- stopped: false,
42
- message: "The active Codex run no longer matches this session binding."
43
- };
44
- const connection = resolveCodexBindingAppServerConnection({
45
- binding,
46
- authProfileId: binding?.authProfileId,
47
- pluginConfig: params.pluginConfig
48
- });
49
- const runtime = connection.appServer;
50
- const client = active.client ?? await getLeasedSharedCodexAppServerClient({
51
- startOptions: runtime.start,
52
- timeoutMs: runtime.requestTimeoutMs,
53
- authProfileId: connection.clientAuthProfileId,
54
- ...lookup
55
- });
56
- try {
57
- await client.request("turn/interrupt", {
58
- threadId: active.threadId,
59
- turnId: active.turnId
60
- }, { timeoutMs: runtime.requestTimeoutMs });
61
- } finally {
62
- if (!active.client) releaseLeasedSharedCodexAppServerClient(client);
63
- }
64
- return {
65
- stopped: true,
66
- message: "Codex stop requested."
67
- };
68
- }
69
- async function steerCodexConversationTurn(params) {
70
- const active = readCodexConversationActiveTurn(params.identity);
71
- const text = params.message.trim();
72
- if (!text) return {
73
- steered: false,
74
- message: "Usage: /codex steer <message>"
75
- };
76
- if (!active) return {
77
- steered: false,
78
- message: "No active Codex run to steer."
79
- };
80
- const lookup = buildBindingLookup(params);
81
- const binding = await params.bindingStore.read(params.identity);
82
- if (binding?.threadId !== active.threadId) return {
83
- steered: false,
84
- message: "The active Codex run no longer matches this session binding."
85
- };
86
- const connection = resolveCodexBindingAppServerConnection({
87
- binding,
88
- authProfileId: binding?.authProfileId,
89
- pluginConfig: params.pluginConfig
90
- });
91
- const runtime = connection.appServer;
92
- const client = active.client ?? await getLeasedSharedCodexAppServerClient({
93
- startOptions: runtime.start,
94
- timeoutMs: runtime.requestTimeoutMs,
95
- authProfileId: connection.clientAuthProfileId,
96
- ...lookup
97
- });
98
- try {
99
- await client.request("turn/steer", {
100
- threadId: active.threadId,
101
- expectedTurnId: active.turnId,
102
- input: [{
103
- type: "text",
104
- text,
105
- text_elements: []
106
- }]
107
- }, { timeoutMs: runtime.requestTimeoutMs });
108
- } finally {
109
- if (!active.client) releaseLeasedSharedCodexAppServerClient(client);
110
- }
111
- return {
112
- steered: true,
113
- message: "Sent steer message to Codex."
114
- };
115
- }
116
- async function setCodexConversationModel(params) {
117
- const model = params.model.trim();
118
- if (!model) return "Usage: /codex model <model>";
119
- const lookup = buildBindingLookup(params);
120
- const binding = await requireThreadBinding(params.bindingStore, params.identity);
121
- if (binding.connectionScope === "supervision") throw new ModelSelectionLockedError();
122
- const reviewerPolicyContext = resolveCodexModelBackedReviewerPolicyContext({
123
- provider: "codex",
124
- model,
125
- bindingModelProvider: binding.modelProvider,
126
- bindingModel: binding.model,
127
- nativeAuthProfile: isCodexAppServerNativeAuthProfile({
128
- authProfileId: binding.authProfileId,
129
- ...lookup
130
- })
131
- });
132
- const runtime = resolveCodexAppServerRuntimeOptions({
133
- pluginConfig: params.pluginConfig,
134
- modelProvider: reviewerPolicyContext.modelProvider,
135
- model: reviewerPolicyContext.model,
136
- config: params.config,
137
- agentDir: params.agentDir
138
- });
139
- const modelSelection = resolveCodexAppServerRequestModelSelection({
140
- model,
141
- modelProvider: resolveConversationControlModelProvider({
142
- authProfileId: binding.authProfileId,
143
- bindingModel: binding.model,
144
- bindingModelProvider: binding.modelProvider,
145
- currentModel: model,
146
- ...lookup
147
- }),
148
- authProfileId: binding.authProfileId,
149
- ...lookup
150
- });
151
- const resumed = await resumeThreadWithOverrides({
152
- runtime,
153
- threadId: binding.threadId,
154
- authProfileId: binding.authProfileId,
155
- ...lookup,
156
- model: modelSelection.model,
157
- modelProvider: modelSelection.modelProvider
158
- });
159
- const response = resumed.response;
160
- const nextModel = response.model ?? modelSelection.model;
161
- const nextModelProvider = normalizeCodexAppServerBindingModelProvider({
162
- authProfileId: binding.authProfileId,
163
- modelProvider: response.modelProvider ?? modelSelection.modelProvider,
164
- ...lookup
165
- });
166
- const modelChanged = nextModel !== binding.model || nextModelProvider !== binding.modelProvider;
167
- await patchThreadBinding(params.bindingStore, params.identity, binding.threadId, {
168
- clientId: resumed.clientId,
169
- cwd: response.thread.cwd ?? binding.cwd,
170
- model: nextModel,
171
- modelProvider: nextModelProvider,
172
- ...modelChanged && binding.contextEngine?.projection ? { contextEngine: {
173
- ...binding.contextEngine,
174
- projection: void 0
175
- } } : {},
176
- approvalPolicy: binding.approvalPolicy,
177
- sandbox: binding.sandbox,
178
- serviceTier: binding.serviceTier ?? runtime.serviceTier ?? void 0
179
- });
180
- return `Codex model set to ${formatCodexDisplayText(response.model ?? model)}.`;
181
- }
182
- async function setCodexConversationFastMode(params) {
183
- const binding = await requireThreadBinding(params.bindingStore, params.identity);
184
- if (params.enabled == null) return `Codex fast mode: ${isCodexFastServiceTier(binding.serviceTier) ? "on" : "off"}.`;
185
- const serviceTier = params.enabled ? "priority" : "flex";
186
- await patchThreadBinding(params.bindingStore, params.identity, binding.threadId, { serviceTier });
187
- return `Codex fast mode ${params.enabled ? "enabled" : "disabled"}.`;
188
- }
189
- async function setCodexConversationPermissions(params) {
190
- const binding = await requireThreadBinding(params.bindingStore, params.identity);
191
- if (!params.mode) return `Codex permissions: ${formatPermissionsMode(binding)}.`;
192
- const policy = permissionsForMode(params.mode);
193
- await patchThreadBinding(params.bindingStore, params.identity, binding.threadId, {
194
- approvalPolicy: policy.approvalPolicy,
195
- sandbox: policy.sandbox
196
- });
197
- return `Codex permissions set to ${params.mode === "yolo" ? "full access" : "default"}.`;
198
- }
199
- function parseCodexFastModeArg(arg) {
200
- const normalized = arg?.trim().toLowerCase();
201
- if (!normalized || normalized === "status") return;
202
- if (normalized === "on" || normalized === "true" || normalized === "fast") return true;
203
- if (normalized === "off" || normalized === "false" || normalized === "flex") return false;
204
- }
205
- function parseCodexPermissionsModeArg(arg) {
206
- const normalized = arg?.trim().toLowerCase();
207
- if (!normalized || normalized === "status") return;
208
- if (normalized === "yolo" || normalized === "full" || normalized === "full-access") return "yolo";
209
- if (normalized === "default" || normalized === "guardian") return "default";
210
- }
211
- function formatPermissionsMode(binding) {
212
- return binding.approvalPolicy === "never" && binding.sandbox === "danger-full-access" ? "full access" : "default";
213
- }
214
- async function requireThreadBinding(bindingStore, identity) {
215
- const binding = await bindingStore.read(identity);
216
- if (!binding?.threadId) throw new Error("No Codex thread is attached to this OpenClaw session yet.");
217
- return binding;
218
- }
219
- async function patchThreadBinding(bindingStore, identity, threadId, patch) {
220
- if (!await bindingStore.mutate(identity, {
221
- kind: "patch",
222
- threadId,
223
- patch
224
- })) throw new Error("Codex thread binding changed while applying the control update.");
225
- }
226
- async function resumeThreadWithOverrides(params) {
227
- const runtime = params.runtime;
228
- const clientOptions = {
229
- startOptions: runtime.start,
230
- timeoutMs: runtime.requestTimeoutMs,
231
- authProfileId: params.authProfileId,
232
- ...buildBindingLookup(params)
233
- };
234
- let client = await getLeasedSharedCodexAppServerClient(clientOptions);
235
- const clientLease = { client };
236
- try {
237
- return {
238
- response: await withLeasedCodexAppServerClientStartSelectionRetry({
239
- lease: clientLease,
240
- options: clientOptions,
241
- run: async (requestClient, requestOptions) => await requestClient.request(CODEX_CONTROL_METHODS.resumeThread, {
242
- threadId: params.threadId,
243
- ...params.model ? { model: params.model } : {},
244
- ...params.modelProvider ? { modelProvider: params.modelProvider } : {},
245
- approvalPolicy: params.approvalPolicy ?? runtime.approvalPolicy,
246
- sandbox: params.sandbox ?? runtime.sandbox,
247
- approvalsReviewer: runtime.approvalsReviewer,
248
- ...params.serviceTier ? { serviceTier: params.serviceTier } : {}
249
- }, requestOptions),
250
- onClientChange: (nextClient) => {
251
- client = nextClient;
252
- }
253
- }),
254
- clientId: client.getInstanceId()
255
- };
256
- } finally {
257
- releaseCodexAppServerClientLease(clientLease);
258
- }
259
- }
260
- function buildBindingLookup(params) {
261
- const agentDir = params.agentDir?.trim();
262
- return {
263
- ...agentDir ? { agentDir } : {},
264
- ...params.config ? { config: params.config } : {}
265
- };
266
- }
267
- function resolveConversationControlModelProvider(params) {
268
- const modelProvider = resolveCodexBindingModelProviderFallback({
269
- currentModel: params.currentModel,
270
- bindingModel: params.bindingModel,
271
- bindingModelProvider: params.bindingModelProvider
272
- })?.trim();
273
- if (!modelProvider || modelProvider.toLowerCase() === "codex") return;
274
- if (isCodexAppServerNativeAuthProfile(params) && modelProvider.toLowerCase() === "openai") return;
275
- return modelProvider.toLowerCase() === "openai" ? "openai" : modelProvider;
276
- }
277
- function permissionsForMode(mode) {
278
- return mode === "yolo" ? {
279
- approvalPolicy: "never",
280
- sandbox: "danger-full-access"
281
- } : {
282
- approvalPolicy: "on-request",
283
- sandbox: "workspace-write"
284
- };
285
- }
286
- //#endregion
287
- export { setCodexConversationFastMode as a, steerCodexConversationTurn as c, CODEX_NATIVE_EXECUTION_AUTH_ERROR as d, canMutateCodexHost as f, readCodexConversationActiveTurn as i, stopCodexConversationTurn as l, parseCodexFastModeArg as n, setCodexConversationModel as o, parseCodexPermissionsModeArg as r, setCodexConversationPermissions as s, formatPermissionsMode as t, trackCodexConversationActiveTurn as u };