@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.
- package/README.md +2 -0
- package/dist/{app-server-policy-BmDgseo_.js → app-server-policy-zcBDc1JU.js} +1 -1
- package/dist/attempt-client-cleanup-DMLXUfa8.js +735 -0
- package/dist/binding-connection-I5Bo-AsX.js +33 -0
- package/dist/{bounded-turn-FEbUXoYT.js → bounded-turn-qgZmzy_4.js} +71 -63
- package/dist/{capabilities-BHRSI6Cn.js → capabilities-CybGI1oz.js} +8 -2
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-ico4ZFnk.js → command-formatters-B1AEz8ZA.js} +18 -18
- package/dist/{command-handlers-CRmnwI2N.js → command-handlers-Db8pu_ds.js} +484 -95
- package/dist/{compact-dEN49UH6.js → compact-LspQaGfl.js} +213 -199
- package/dist/{conversation-binding-data-BHRpYbX3.js → conversation-binding-data-CW2GuupV.js} +6 -10
- package/dist/doctor-contract-api.js +40 -43
- package/dist/{dynamic-tools-LIt9ojep.js → dynamic-tools-BVdyWkUD.js} +2984 -1221
- package/dist/effective-mcp-catalog-DIIhAtOZ.js +119 -0
- package/dist/{event-projector-assistant-message-DTgnPPVF.js → event-projector-assistant-message-BwxV4d6N.js} +11 -23
- package/dist/{attempt-notifications-CMR2_fmR.js → event-projector-usage-e5huIQWu.js} +113 -29
- package/dist/harness.js +83 -13
- package/dist/image-payload-sanitizer-CnfoUPCE.js +65 -0
- package/dist/index.js +703 -329
- package/dist/isolated-completion-C58NbL40.js +75 -0
- package/dist/local-runtime-attribution-B_2mnqhb.js +19 -0
- package/dist/media-understanding-provider.js +5 -5
- package/dist/{models-BA01NEez.js → models-BFlpn1Ex.js} +12 -17
- package/dist/native-subagent-monitor-DyTGmTUx.js +3111 -0
- package/dist/{plugin-app-cache-key-DSXX-rXO.js → plugin-app-cache-key-C3H2CVp6.js} +135 -42
- package/dist/plugin-marketplace-discovery-CzrGJdCR.js +385 -0
- package/dist/{computer-use-BjGylO-E.js → plugin-metadata-cache-CNJPj4_b.js} +211 -113
- package/dist/protocol-validators-B4F7L8Rf.js +2346 -0
- package/dist/{rate-limits-S_PXs0ul.js → rate-limits-DZXmOL8-.js} +17 -35
- package/dist/{request-CXpPennK.js → request-BRl5_UfX.js} +4 -4
- package/dist/{run-attempt-C5GTPJOE.js → run-attempt-P8BdxC1I.js} +1996 -5728
- package/dist/{runtime-artifact-C2ITXdhM.js → runtime-artifact-BVSPdd6g.js} +91 -40
- package/dist/{sandbox-guard-D1Wky__S.js → sandbox-guard-Cmwc9eIk.js} +10 -13
- package/dist/{session-binding-DlVQ-Pxs.js → session-binding-DPxIvMgE.js} +305 -271
- package/dist/{session-catalog-CP2oCcEb.js → session-catalog-xwNi_SDM.js} +418 -144
- package/dist/{session-cli-CqZ0Fp2a.js → session-cli-7hgXZDV7.js} +1 -1
- package/dist/session-retirement-DoMMJFKm.js +36 -0
- package/dist/{session-upstream-marker-QE-m5QFG.js → session-upstream-marker-CrIFX06J.js} +1 -1
- package/dist/{settled-turn-finalizer-CA_2QXIE.js → settled-turn-finalizer-BRWBO4MO.js} +36 -15
- package/dist/{shared-client-BVKE40c-.js → shared-client-kIBbGjk4.js} +721 -240
- package/dist/{side-question-CO12sHxo.js → side-question-9HAL26l9.js} +102 -53
- package/dist/{thread-lifecycle-DRg_FdzC.js → thread-lifecycle-Bu1BTDXr.js} +1355 -660
- package/dist/thread-ownership-6kOQHlyC.js +92 -0
- package/dist/thread-resume-CPrJNQVM.js +30 -0
- package/dist/{transcript-mirror-uKA-A4tB.js → transcript-mirror-B9gGgnJS.js} +202 -182
- package/dist/{transport-stdio-DXgGZ7Ib.js → transport-stdio-DIImwDVS.js} +11 -0
- package/dist/upstream-prompt-provenance-ClRBije0.js +41 -0
- package/dist/{upstream-session-fork-_Vrz4WJr.js → upstream-session-fork-CE-_LdnP.js} +5 -5
- package/dist/{usage-UpVbdX5G.js → usage-CHlV0e-o.js} +3 -3
- package/dist/{web-search-provider.runtime-CaQMYDbp.js → web-search-provider.runtime-DRw2Vl42.js} +8 -9
- package/openclaw.plugin.json +18 -3
- package/package.json +6 -7
- package/dist/attempt-client-cleanup-Ia52yRWc.js +0 -127
- package/dist/conversation-control-DE7d9DOj.js +0 -287
- package/dist/event-projector-usage-tvgb1NCX.js +0 -69
- package/dist/notification-correlation-Bj_Ak_jI.js +0 -67
- package/dist/protocol-validators-Dm4eXZmt.js +0 -6337
- package/dist/realtime-voice-api-BPcA1uN9.js +0 -494
- package/dist/realtime-voice-api.js +0 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { A as resolveCodexAppServerUserHomeDir } from "./session-binding-DPxIvMgE.js";
|
|
2
|
+
import { dt as resolveCodexAppServerLocalHomeDir, ut as resolveCodexAppServerHomeDir } from "./shared-client-kIBbGjk4.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
|
+
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
|
+
import { readPluginPackageVersion } from "openclaw/plugin-sdk/extension-shared";
|
|
4
6
|
import { isFutureDateTimestampMs, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
5
7
|
import { OPENCLAW_VERSION, embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
6
8
|
import { createHash } from "node:crypto";
|
|
7
|
-
import { readPluginPackageVersion } from "openclaw/plugin-sdk/extension-shared";
|
|
8
|
-
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
9
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
10
10
|
//#region extensions/codex/src/app-server/app-inventory-cache.ts
|
|
11
11
|
/**
|
|
@@ -14,7 +14,7 @@ import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
|
14
14
|
*/
|
|
15
15
|
/** Default app inventory cache freshness window. */
|
|
16
16
|
const CODEX_APP_INVENTORY_CACHE_TTL_MS = 3600 * 1e3;
|
|
17
|
-
const
|
|
17
|
+
const CODEX_APP_READ_BATCH_LIMIT = 100;
|
|
18
18
|
const MAX_SERIALIZED_ERROR_MESSAGE_LENGTH = 500;
|
|
19
19
|
/** In-memory app inventory cache with coalesced refreshes per key. */
|
|
20
20
|
var CodexAppInventoryCache = class {
|
|
@@ -55,15 +55,25 @@ var CodexAppInventoryCache = class {
|
|
|
55
55
|
refreshNow(params) {
|
|
56
56
|
return this.refresh(params);
|
|
57
57
|
}
|
|
58
|
-
/**
|
|
59
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Marks a key stale and records the reason as a diagnostic. A scope names
|
|
60
|
+
* the app ids the invalidation concerns so a covering targeted refresh can
|
|
61
|
+
* clear it; without one, only a complete refresh revalidates the entry.
|
|
62
|
+
*/
|
|
63
|
+
invalidate(key, reason, nowMs = Date.now(), invalidatedAppIds) {
|
|
60
64
|
this.revision += 1;
|
|
65
|
+
this.refreshTokens.set(key, (this.refreshTokens.get(key) ?? 0) + 1);
|
|
66
|
+
this.inFlight.delete(key);
|
|
61
67
|
const diagnostic = {
|
|
62
68
|
message: reason,
|
|
63
69
|
atMs: nowMs
|
|
64
70
|
};
|
|
65
71
|
const entry = this.entries.get(key);
|
|
66
72
|
if (entry) {
|
|
73
|
+
const scope = invalidatedAppIds?.filter(Boolean) ?? [];
|
|
74
|
+
if (!entry.invalidated) entry.invalidatedAppIds = scope.length ? [...scope].toSorted() : void 0;
|
|
75
|
+
else if (entry.invalidatedAppIds && scope.length) entry.invalidatedAppIds = Array.from(/* @__PURE__ */ new Set([...entry.invalidatedAppIds, ...scope])).toSorted();
|
|
76
|
+
else entry.invalidatedAppIds = void 0;
|
|
67
77
|
entry.invalidated = true;
|
|
68
78
|
entry.lastError = diagnostic;
|
|
69
79
|
entry.revision = this.revision;
|
|
@@ -83,42 +93,60 @@ var CodexAppInventoryCache = class {
|
|
|
83
93
|
return this.revision;
|
|
84
94
|
}
|
|
85
95
|
scheduleRefresh(params) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
this.
|
|
89
|
-
promise.catch(() => void 0);
|
|
96
|
+
const existing = this.inFlight.get(params.key);
|
|
97
|
+
if (existing && !params.forceRefetch && doesInFlightRefreshCover(existing, params)) return true;
|
|
98
|
+
this.refresh(params).catch(() => void 0);
|
|
90
99
|
return true;
|
|
91
100
|
}
|
|
92
101
|
async refresh(params) {
|
|
93
102
|
const existing = this.inFlight.get(params.key);
|
|
94
|
-
if (existing && !params.forceRefetch) return existing;
|
|
103
|
+
if (existing && !params.forceRefetch && doesInFlightRefreshCover(existing, params)) return existing.promise;
|
|
95
104
|
const refreshToken = (this.refreshTokens.get(params.key) ?? 0) + 1;
|
|
96
105
|
this.refreshTokens.set(params.key, refreshToken);
|
|
97
|
-
const
|
|
98
|
-
this.
|
|
106
|
+
const previousRefresh = params.forceRefetch ? void 0 : existing?.promise;
|
|
107
|
+
const promise = this.refreshUncoalesced(params, refreshToken, previousRefresh);
|
|
108
|
+
const currentRefresh = {
|
|
109
|
+
promise,
|
|
110
|
+
targetAppIds: new Set(params.targetAppIds?.filter(Boolean) ?? [])
|
|
111
|
+
};
|
|
112
|
+
this.inFlight.set(params.key, currentRefresh);
|
|
99
113
|
try {
|
|
100
114
|
return await promise;
|
|
101
115
|
} finally {
|
|
102
|
-
if (this.inFlight.get(params.key) ===
|
|
116
|
+
if (this.inFlight.get(params.key) === currentRefresh) this.inFlight.delete(params.key);
|
|
103
117
|
}
|
|
104
118
|
}
|
|
105
|
-
async refreshUncoalesced(params, refreshToken) {
|
|
119
|
+
async refreshUncoalesced(params, refreshToken, previousRefresh) {
|
|
106
120
|
const nowMs = resolveDateTimestampMs(params.nowMs);
|
|
107
121
|
try {
|
|
108
|
-
|
|
122
|
+
let previousRefreshSucceeded = false;
|
|
123
|
+
if (previousRefresh) try {
|
|
124
|
+
await previousRefresh;
|
|
125
|
+
previousRefreshSucceeded = true;
|
|
126
|
+
} catch {}
|
|
127
|
+
const inventory = await readInstalledApps(params.request, {
|
|
128
|
+
forceRefresh: params.forceRefetch === true || !this.entries.has(params.key) && !previousRefreshSucceeded,
|
|
129
|
+
targetAppIds: params.targetAppIds
|
|
130
|
+
});
|
|
109
131
|
this.revision += 1;
|
|
110
132
|
const expiresAtMs = resolveExpiresAtMsFromDurationMs(this.ttlMs, { nowMs }) ?? 0;
|
|
111
133
|
const snapshot = {
|
|
112
134
|
key: params.key,
|
|
113
|
-
apps,
|
|
135
|
+
apps: inventory.apps,
|
|
136
|
+
installedApps: inventory.installedApps,
|
|
137
|
+
...params.targetAppIds?.some(Boolean) ? { targetAppIds: Array.from(new Set(params.targetAppIds.filter(Boolean))).toSorted() } : {},
|
|
114
138
|
fetchedAtMs: nowMs,
|
|
115
139
|
expiresAtMs,
|
|
116
140
|
revision: this.revision
|
|
117
141
|
};
|
|
118
142
|
if (this.refreshTokens.get(params.key) === refreshToken) {
|
|
143
|
+
const existingEntry = this.entries.get(params.key);
|
|
144
|
+
const published = resolvePublishedInventorySnapshot(existingEntry, snapshot, nowMs);
|
|
145
|
+
const remaining = resolveRemainingInvalidationScope(existingEntry, snapshot);
|
|
119
146
|
this.entries.set(params.key, {
|
|
120
|
-
...
|
|
121
|
-
|
|
147
|
+
...published,
|
|
148
|
+
...remaining,
|
|
149
|
+
...remaining.invalidated && existingEntry?.lastError ? { lastError: existingEntry.lastError } : {}
|
|
122
150
|
});
|
|
123
151
|
this.diagnostics.delete(params.key);
|
|
124
152
|
}
|
|
@@ -140,6 +168,59 @@ var CodexAppInventoryCache = class {
|
|
|
140
168
|
}
|
|
141
169
|
}
|
|
142
170
|
};
|
|
171
|
+
/**
|
|
172
|
+
* Publish policy for refreshed snapshots. A complete refresh replaces the
|
|
173
|
+
* entry, but a targeted refresh only rewrites its own target rows in place —
|
|
174
|
+
* replacing the whole entry with a narrow snapshot makes agents that share
|
|
175
|
+
* the runtime identity see each other's plugin apps vanish and force a hosted
|
|
176
|
+
* connector refresh per turn. The refreshed snapshot stays authoritative for
|
|
177
|
+
* its target set, so target rows it no longer returns are deleted.
|
|
178
|
+
*/
|
|
179
|
+
function resolvePublishedInventorySnapshot(existing, snapshot, nowMs) {
|
|
180
|
+
if (!snapshot.targetAppIds?.length || !existing) return snapshot;
|
|
181
|
+
if (!isFutureDateTimestampMs(existing.expiresAtMs, { nowMs })) return snapshot;
|
|
182
|
+
const refreshedTargetIds = new Set(snapshot.targetAppIds);
|
|
183
|
+
const { targetAppIds: snapshotTargetAppIds, ...snapshotBase } = snapshot;
|
|
184
|
+
return {
|
|
185
|
+
...snapshotBase,
|
|
186
|
+
fetchedAtMs: existing.fetchedAtMs,
|
|
187
|
+
expiresAtMs: existing.expiresAtMs,
|
|
188
|
+
apps: mergeRefreshedRows(existing.apps, snapshot.apps, refreshedTargetIds),
|
|
189
|
+
installedApps: mergeRefreshedRows(existing.installedApps, snapshot.installedApps, refreshedTargetIds),
|
|
190
|
+
...existing.targetAppIds?.length ? { targetAppIds: Array.from(/* @__PURE__ */ new Set([...existing.targetAppIds, ...snapshotTargetAppIds])).toSorted() } : {}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/** Replaces refreshed target rows in place, deletes vanished ones, appends new ones. */
|
|
194
|
+
function mergeRefreshedRows(existingRows, refreshedRows, refreshedTargetIds) {
|
|
195
|
+
const refreshedById = new Map(refreshedRows.map((row) => [row.id, row]));
|
|
196
|
+
const existingIds = new Set(existingRows.map((row) => row.id));
|
|
197
|
+
return [...existingRows.flatMap((row) => {
|
|
198
|
+
if (!refreshedTargetIds.has(row.id)) return [row];
|
|
199
|
+
const refreshed = refreshedById.get(row.id);
|
|
200
|
+
return refreshed ? [refreshed] : [];
|
|
201
|
+
}), ...refreshedRows.filter((row) => !existingIds.has(row.id))];
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* A refresh retires exactly the invalidation scope it re-read: a complete
|
|
205
|
+
* refresh clears everything; a targeted one subtracts its target ids so
|
|
206
|
+
* separate covering refreshes accumulate until no scope remains. Unscoped
|
|
207
|
+
* invalidations require a complete refresh.
|
|
208
|
+
*/
|
|
209
|
+
function resolveRemainingInvalidationScope(existing, snapshot) {
|
|
210
|
+
if (!existing?.invalidated || !snapshot.targetAppIds?.length) return { invalidated: false };
|
|
211
|
+
if (!existing.invalidatedAppIds) return { invalidated: true };
|
|
212
|
+
const refreshedTargetIds = new Set(snapshot.targetAppIds);
|
|
213
|
+
const remaining = existing.invalidatedAppIds.filter((appId) => !refreshedTargetIds.has(appId));
|
|
214
|
+
return remaining.length > 0 ? {
|
|
215
|
+
invalidated: true,
|
|
216
|
+
invalidatedAppIds: remaining
|
|
217
|
+
} : { invalidated: false };
|
|
218
|
+
}
|
|
219
|
+
function doesInFlightRefreshCover(existing, params) {
|
|
220
|
+
if (existing.targetAppIds.size === 0) return true;
|
|
221
|
+
const requestedAppIds = new Set(params.targetAppIds?.filter(Boolean) ?? []);
|
|
222
|
+
return requestedAppIds.size > 0 && Array.from(requestedAppIds).every((appId) => existing.targetAppIds.has(appId));
|
|
223
|
+
}
|
|
143
224
|
/** Serializes a refresh failure without leaking large or sensitive error data. */
|
|
144
225
|
function serializeCodexAppInventoryError(error) {
|
|
145
226
|
const record = isRecord(error) ? error : void 0;
|
|
@@ -175,29 +256,41 @@ function normalizeRuntimeIdentityForCacheKey(value) {
|
|
|
175
256
|
}).toSorted(([left], [right]) => left.localeCompare(right));
|
|
176
257
|
return entries.length > 0 ? Object.fromEntries(entries) : null;
|
|
177
258
|
}
|
|
178
|
-
async function
|
|
179
|
-
const
|
|
180
|
-
const targetIds = new Set(targetAppIds.filter(Boolean));
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
259
|
+
async function readInstalledApps(request, options) {
|
|
260
|
+
const installed = await request("app/installed", { forceRefresh: options.forceRefresh });
|
|
261
|
+
const targetIds = new Set((options.targetAppIds ?? []).filter(Boolean));
|
|
262
|
+
const apps = targetIds.size === 0 ? installed.apps : installed.apps.filter((app) => targetIds.has(app.id));
|
|
263
|
+
if (apps.length === 0) return {
|
|
264
|
+
apps: [],
|
|
265
|
+
installedApps: []
|
|
266
|
+
};
|
|
267
|
+
const metadataResponses = await Promise.all(Array.from({ length: Math.ceil(apps.length / CODEX_APP_READ_BATCH_LIMIT) }, (_, index) => request("app/read", { appIds: apps.slice(index * CODEX_APP_READ_BATCH_LIMIT, (index + 1) * CODEX_APP_READ_BATCH_LIMIT).map((app) => app.id) })));
|
|
268
|
+
const metadataById = new Map(metadataResponses.flatMap((response) => response.apps).map((metadata) => [metadata.id, metadata]));
|
|
269
|
+
return {
|
|
270
|
+
apps: apps.flatMap((installedApp) => {
|
|
271
|
+
const metadata = metadataById.get(installedApp.id);
|
|
272
|
+
if (!metadata) return [];
|
|
273
|
+
return [{
|
|
274
|
+
id: installedApp.id,
|
|
275
|
+
name: metadata.name,
|
|
276
|
+
description: metadata.description ?? null,
|
|
277
|
+
logoUrl: metadata.iconUrl ?? null,
|
|
278
|
+
logoUrlDark: metadata.iconUrlDark ?? null,
|
|
279
|
+
distributionChannel: metadata.distributionChannel ?? null,
|
|
280
|
+
branding: null,
|
|
281
|
+
appMetadata: null,
|
|
282
|
+
labels: null,
|
|
283
|
+
installUrl: metadata.installUrl ?? null,
|
|
284
|
+
isAccessible: true,
|
|
285
|
+
isEnabled: installedApp.enabled,
|
|
286
|
+
pluginDisplayNames: metadata.pluginDisplayNames
|
|
287
|
+
}];
|
|
288
|
+
}),
|
|
289
|
+
installedApps: apps
|
|
290
|
+
};
|
|
198
291
|
}
|
|
199
292
|
function stripEntryState(entry) {
|
|
200
|
-
const { invalidated: _invalidated, ...snapshot } = entry;
|
|
293
|
+
const { invalidated: _invalidated, invalidatedAppIds: _invalidatedAppIds, ...snapshot } = entry;
|
|
201
294
|
return snapshot;
|
|
202
295
|
}
|
|
203
296
|
function fingerprintInventoryCacheKey(key) {
|
|
@@ -277,7 +370,7 @@ function resolveCodexAppServerConnectionHome(start, agentDir) {
|
|
|
277
370
|
if (start.transport === "unix" && (!start.url || start.url === "unix://")) return resolveCodexAppServerUserHomeDir(start.env ?? process.env);
|
|
278
371
|
if (start.transport !== "stdio") return null;
|
|
279
372
|
if (start.homeScope === "user") return resolveCodexAppServerUserHomeDir(process.env);
|
|
280
|
-
return agentDir ?
|
|
373
|
+
return agentDir ? resolveCodexAppServerLocalHomeDir(start, agentDir) : null;
|
|
281
374
|
}
|
|
282
375
|
/** Serializes app-server endpoint identity, including credential fingerprints. */
|
|
283
376
|
function resolveCodexPluginAppCacheEndpoint(appServer) {
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { P as isCodexFastServiceTier, o as isCodexAppServerNativeAuthProfile, r as bindingStoreKey, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-DPxIvMgE.js";
|
|
2
|
+
import { a as getLeasedSharedCodexAppServerClient, l as releaseLeasedSharedCodexAppServerClient } from "./shared-client-kIBbGjk4.js";
|
|
3
|
+
import { g as resolveCodexAppServerRequestModelSelection, v as resolveCodexBindingModelProviderFallback } from "./thread-lifecycle-Bu1BTDXr.js";
|
|
4
|
+
import { r as formatCodexDisplayText } from "./command-formatters-B1AEz8ZA.js";
|
|
5
|
+
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-I5Bo-AsX.js";
|
|
6
|
+
import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
|
+
import { resolveAgentDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
8
|
+
import { patchSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
9
|
+
import { ModelSelectionLockedError, applyModelOverrideWithAuthProfileCompatibility } from "openclaw/plugin-sdk/model-session-runtime";
|
|
10
|
+
//#region extensions/codex/src/command-authorization.ts
|
|
11
|
+
const CODEX_NATIVE_EXECUTION_AUTH_ERROR = "Only an owner or operator.admin can control Codex native execution.";
|
|
12
|
+
function canMutateCodexHost(ctx) {
|
|
13
|
+
return ctx.senderIsOwner === true || ctx.gatewayClientScopes?.includes("operator.admin") === true;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region extensions/codex/src/conversation-control.ts
|
|
17
|
+
const CODEX_CONVERSATION_CONTROL_STATE = Symbol.for("openclaw.codex.conversationControl");
|
|
18
|
+
function getActiveTurns() {
|
|
19
|
+
const globalState = globalThis;
|
|
20
|
+
globalState[CODEX_CONVERSATION_CONTROL_STATE] ??= /* @__PURE__ */ new Map();
|
|
21
|
+
return globalState[CODEX_CONVERSATION_CONTROL_STATE];
|
|
22
|
+
}
|
|
23
|
+
function trackCodexConversationActiveTurn(active) {
|
|
24
|
+
const activeTurns = getActiveTurns();
|
|
25
|
+
const key = bindingStoreKey(active.identity);
|
|
26
|
+
activeTurns.set(key, active);
|
|
27
|
+
return () => {
|
|
28
|
+
if (activeTurns.get(key)?.turnId === active.turnId) activeTurns.delete(key);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function readCodexConversationActiveTurn(identity) {
|
|
32
|
+
return getActiveTurns().get(bindingStoreKey(identity));
|
|
33
|
+
}
|
|
34
|
+
async function stopCodexConversationTurn(params) {
|
|
35
|
+
const active = readCodexConversationActiveTurn(params.identity);
|
|
36
|
+
if (!active) return {
|
|
37
|
+
stopped: false,
|
|
38
|
+
message: "No active Codex run to stop."
|
|
39
|
+
};
|
|
40
|
+
const lookup = buildBindingLookup(params);
|
|
41
|
+
const binding = await params.bindingStore.read(params.identity);
|
|
42
|
+
if (binding?.threadId !== active.threadId) return {
|
|
43
|
+
stopped: false,
|
|
44
|
+
message: "The active Codex run no longer matches this session binding."
|
|
45
|
+
};
|
|
46
|
+
const connection = resolveCodexBindingAppServerConnection({
|
|
47
|
+
binding,
|
|
48
|
+
authProfileId: binding?.authProfileId,
|
|
49
|
+
pluginConfig: params.pluginConfig
|
|
50
|
+
});
|
|
51
|
+
const runtime = connection.appServer;
|
|
52
|
+
const client = active.client ?? await getLeasedSharedCodexAppServerClient({
|
|
53
|
+
startOptions: runtime.start,
|
|
54
|
+
timeoutMs: runtime.requestTimeoutMs,
|
|
55
|
+
authProfileId: connection.clientAuthProfileId,
|
|
56
|
+
...lookup
|
|
57
|
+
});
|
|
58
|
+
try {
|
|
59
|
+
await client.request("turn/interrupt", {
|
|
60
|
+
threadId: active.threadId,
|
|
61
|
+
turnId: active.turnId
|
|
62
|
+
}, { timeoutMs: runtime.requestTimeoutMs });
|
|
63
|
+
} finally {
|
|
64
|
+
if (!active.client) releaseLeasedSharedCodexAppServerClient(client);
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
stopped: true,
|
|
68
|
+
message: "Codex stop requested."
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
async function steerCodexConversationTurn(params) {
|
|
72
|
+
const active = readCodexConversationActiveTurn(params.identity);
|
|
73
|
+
const text = params.message.trim();
|
|
74
|
+
if (!text) return {
|
|
75
|
+
steered: false,
|
|
76
|
+
message: "Usage: /codex steer <message>"
|
|
77
|
+
};
|
|
78
|
+
if (!active) return {
|
|
79
|
+
steered: false,
|
|
80
|
+
message: "No active Codex run to steer."
|
|
81
|
+
};
|
|
82
|
+
const lookup = buildBindingLookup(params);
|
|
83
|
+
const binding = await params.bindingStore.read(params.identity);
|
|
84
|
+
if (binding?.threadId !== active.threadId) return {
|
|
85
|
+
steered: false,
|
|
86
|
+
message: "The active Codex run no longer matches this session binding."
|
|
87
|
+
};
|
|
88
|
+
const connection = resolveCodexBindingAppServerConnection({
|
|
89
|
+
binding,
|
|
90
|
+
authProfileId: binding?.authProfileId,
|
|
91
|
+
pluginConfig: params.pluginConfig
|
|
92
|
+
});
|
|
93
|
+
const runtime = connection.appServer;
|
|
94
|
+
const client = active.client ?? await getLeasedSharedCodexAppServerClient({
|
|
95
|
+
startOptions: runtime.start,
|
|
96
|
+
timeoutMs: runtime.requestTimeoutMs,
|
|
97
|
+
authProfileId: connection.clientAuthProfileId,
|
|
98
|
+
...lookup
|
|
99
|
+
});
|
|
100
|
+
try {
|
|
101
|
+
await client.request("turn/steer", {
|
|
102
|
+
threadId: active.threadId,
|
|
103
|
+
expectedTurnId: active.turnId,
|
|
104
|
+
input: [{
|
|
105
|
+
type: "text",
|
|
106
|
+
text,
|
|
107
|
+
text_elements: []
|
|
108
|
+
}]
|
|
109
|
+
}, { timeoutMs: runtime.requestTimeoutMs });
|
|
110
|
+
} finally {
|
|
111
|
+
if (!active.client) releaseLeasedSharedCodexAppServerClient(client);
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
steered: true,
|
|
115
|
+
message: "Sent steer message to Codex."
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
async function setCodexConversationModel(params) {
|
|
119
|
+
const model = params.model.trim();
|
|
120
|
+
if (!model) return "Usage: /codex model <model>";
|
|
121
|
+
const lookup = buildBindingLookup(params);
|
|
122
|
+
const binding = await requireThreadBinding(params.bindingStore, params.identity);
|
|
123
|
+
if (binding.connectionScope === "supervision") throw new ModelSelectionLockedError();
|
|
124
|
+
const modelSelection = resolveCodexAppServerRequestModelSelection({
|
|
125
|
+
model,
|
|
126
|
+
modelProvider: resolveConversationControlModelProvider({
|
|
127
|
+
authProfileId: binding.authProfileId,
|
|
128
|
+
bindingModel: binding.model,
|
|
129
|
+
bindingModelProvider: binding.modelProvider,
|
|
130
|
+
currentModel: model,
|
|
131
|
+
...lookup
|
|
132
|
+
}),
|
|
133
|
+
authProfileId: binding.authProfileId,
|
|
134
|
+
...lookup
|
|
135
|
+
});
|
|
136
|
+
const nextModelProvider = normalizeCodexAppServerBindingModelProvider({
|
|
137
|
+
authProfileId: binding.authProfileId,
|
|
138
|
+
modelProvider: modelSelection.modelProvider,
|
|
139
|
+
...lookup
|
|
140
|
+
});
|
|
141
|
+
const nextModel = modelSelection.model;
|
|
142
|
+
const modelChanged = nextModel !== binding.model || nextModelProvider !== binding.modelProvider;
|
|
143
|
+
const session = params.session ?? (params.identity.kind === "session" && params.identity.sessionKey ? {
|
|
144
|
+
agentId: params.identity.agentId,
|
|
145
|
+
sessionId: params.identity.sessionId,
|
|
146
|
+
sessionKey: params.identity.sessionKey
|
|
147
|
+
} : void 0);
|
|
148
|
+
if (session) {
|
|
149
|
+
if (!await patchSessionEntry({
|
|
150
|
+
agentId: session.agentId,
|
|
151
|
+
storePath: resolveStorePath(params.config?.session?.store, { agentId: session.agentId }),
|
|
152
|
+
sessionKey: session.sessionKey,
|
|
153
|
+
requireWriteSuccess: true,
|
|
154
|
+
replaceEntry: true,
|
|
155
|
+
update: (entry) => {
|
|
156
|
+
if (entry.sessionId !== session.sessionId) throw new Error("Codex session changed while applying the model selection.");
|
|
157
|
+
applyModelOverrideWithAuthProfileCompatibility({
|
|
158
|
+
cfg: params.config ?? {},
|
|
159
|
+
agentDir: params.agentDir ?? resolveAgentDir(params.config ?? {}, session.agentId),
|
|
160
|
+
entry,
|
|
161
|
+
currentProvider: binding.modelProvider ?? "openai",
|
|
162
|
+
selection: {
|
|
163
|
+
provider: nextModelProvider ?? "openai",
|
|
164
|
+
model: nextModel
|
|
165
|
+
},
|
|
166
|
+
markLiveSwitchPending: true
|
|
167
|
+
});
|
|
168
|
+
return entry;
|
|
169
|
+
}
|
|
170
|
+
})) throw new Error("Codex session changed while applying the model selection.");
|
|
171
|
+
if (params.identity.kind === "conversation") await patchThreadBinding(params.bindingStore, params.identity, binding.threadId, {
|
|
172
|
+
model: nextModel,
|
|
173
|
+
modelProvider: nextModelProvider,
|
|
174
|
+
...modelChanged && binding.contextEngine?.projection ? { contextEngine: {
|
|
175
|
+
...binding.contextEngine,
|
|
176
|
+
projection: void 0
|
|
177
|
+
} } : {}
|
|
178
|
+
});
|
|
179
|
+
else if (modelChanged && binding.contextEngine?.projection) await patchThreadBinding(params.bindingStore, params.identity, binding.threadId, { contextEngine: {
|
|
180
|
+
...binding.contextEngine,
|
|
181
|
+
projection: void 0
|
|
182
|
+
} });
|
|
183
|
+
} else await patchThreadBinding(params.bindingStore, params.identity, binding.threadId, {
|
|
184
|
+
model: nextModel,
|
|
185
|
+
modelProvider: nextModelProvider,
|
|
186
|
+
...modelChanged && binding.contextEngine?.projection ? { contextEngine: {
|
|
187
|
+
...binding.contextEngine,
|
|
188
|
+
projection: void 0
|
|
189
|
+
} } : {}
|
|
190
|
+
});
|
|
191
|
+
return `Codex model set to ${formatCodexDisplayText(nextModel)}.`;
|
|
192
|
+
}
|
|
193
|
+
async function setCodexConversationFastMode(params) {
|
|
194
|
+
const binding = await requireThreadBinding(params.bindingStore, params.identity);
|
|
195
|
+
if (params.enabled == null) return `Codex fast mode: ${isCodexFastServiceTier(binding.serviceTier) ? "on" : "off"}.`;
|
|
196
|
+
const serviceTier = params.enabled ? "priority" : "flex";
|
|
197
|
+
await patchThreadBinding(params.bindingStore, params.identity, binding.threadId, { serviceTier });
|
|
198
|
+
return `Codex fast mode ${params.enabled ? "enabled" : "disabled"}.`;
|
|
199
|
+
}
|
|
200
|
+
async function setCodexConversationPermissions(params) {
|
|
201
|
+
const binding = await requireThreadBinding(params.bindingStore, params.identity);
|
|
202
|
+
if (!params.mode) return `Codex permissions: ${formatPermissionsMode(binding)}.`;
|
|
203
|
+
const policy = permissionsForMode(params.mode);
|
|
204
|
+
await patchThreadBinding(params.bindingStore, params.identity, binding.threadId, {
|
|
205
|
+
approvalPolicy: policy.approvalPolicy,
|
|
206
|
+
sandbox: policy.sandbox
|
|
207
|
+
});
|
|
208
|
+
return `Codex permissions set to ${params.mode === "yolo" ? "full access" : "default"}.`;
|
|
209
|
+
}
|
|
210
|
+
function parseCodexFastModeArg(arg) {
|
|
211
|
+
const normalized = arg?.trim().toLowerCase();
|
|
212
|
+
if (!normalized || normalized === "status") return;
|
|
213
|
+
if (normalized === "on" || normalized === "true" || normalized === "fast") return true;
|
|
214
|
+
if (normalized === "off" || normalized === "false" || normalized === "flex") return false;
|
|
215
|
+
}
|
|
216
|
+
function parseCodexPermissionsModeArg(arg) {
|
|
217
|
+
const normalized = arg?.trim().toLowerCase();
|
|
218
|
+
if (!normalized || normalized === "status") return;
|
|
219
|
+
if (normalized === "yolo" || normalized === "full" || normalized === "full-access") return "yolo";
|
|
220
|
+
if (normalized === "default" || normalized === "guardian") return "default";
|
|
221
|
+
}
|
|
222
|
+
function formatPermissionsMode(binding) {
|
|
223
|
+
return binding.approvalPolicy === "never" && binding.sandbox === "danger-full-access" ? "full access" : "default";
|
|
224
|
+
}
|
|
225
|
+
async function requireThreadBinding(bindingStore, identity) {
|
|
226
|
+
const binding = await bindingStore.read(identity);
|
|
227
|
+
if (!binding?.threadId) throw new Error("No Codex thread is attached to this OpenClaw session yet.");
|
|
228
|
+
return binding;
|
|
229
|
+
}
|
|
230
|
+
async function patchThreadBinding(bindingStore, identity, threadId, patch) {
|
|
231
|
+
if (!await bindingStore.mutate(identity, {
|
|
232
|
+
kind: "patch",
|
|
233
|
+
threadId,
|
|
234
|
+
patch
|
|
235
|
+
})) throw new Error("Codex thread binding changed while applying the control update.");
|
|
236
|
+
}
|
|
237
|
+
function buildBindingLookup(params) {
|
|
238
|
+
const agentDir = params.agentDir?.trim();
|
|
239
|
+
return {
|
|
240
|
+
...agentDir ? { agentDir } : {},
|
|
241
|
+
...params.config ? { config: params.config } : {}
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function resolveConversationControlModelProvider(params) {
|
|
245
|
+
const modelProvider = resolveCodexBindingModelProviderFallback({
|
|
246
|
+
currentModel: params.currentModel,
|
|
247
|
+
bindingModel: params.bindingModel,
|
|
248
|
+
bindingModelProvider: params.bindingModelProvider
|
|
249
|
+
})?.trim();
|
|
250
|
+
if (!modelProvider || modelProvider.toLowerCase() === "codex") return;
|
|
251
|
+
if (isCodexAppServerNativeAuthProfile(params) && modelProvider.toLowerCase() === "openai") return;
|
|
252
|
+
return modelProvider.toLowerCase() === "openai" ? "openai" : modelProvider;
|
|
253
|
+
}
|
|
254
|
+
function permissionsForMode(mode) {
|
|
255
|
+
return mode === "yolo" ? {
|
|
256
|
+
approvalPolicy: "never",
|
|
257
|
+
sandbox: "danger-full-access"
|
|
258
|
+
} : {
|
|
259
|
+
approvalPolicy: "on-request",
|
|
260
|
+
sandbox: "workspace-write"
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
//#endregion
|
|
264
|
+
//#region extensions/codex/src/plugin-marketplace-discovery.ts
|
|
265
|
+
/** Read-only discovery of Codex-owned local, curated, and remote plugin marketplaces. */
|
|
266
|
+
const PLUGIN_SEGMENT_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
267
|
+
const MAX_PLUGIN_DESCRIPTION_LENGTH = 160;
|
|
268
|
+
const SUPPLEMENTAL_MARKETPLACE_KINDS = [
|
|
269
|
+
"workspace-directory",
|
|
270
|
+
"shared-with-me",
|
|
271
|
+
"created-by-me-remote",
|
|
272
|
+
"vertical"
|
|
273
|
+
];
|
|
274
|
+
/** Validates the same identifier segments required by Codex's stable PluginId parser. */
|
|
275
|
+
function parseCodexPluginMarketplaceId(value) {
|
|
276
|
+
const separator = value.lastIndexOf("@");
|
|
277
|
+
if (separator <= 0 || separator === value.length - 1) return;
|
|
278
|
+
const pluginName = value.slice(0, separator);
|
|
279
|
+
const marketplaceName = value.slice(separator + 1);
|
|
280
|
+
return PLUGIN_SEGMENT_PATTERN.test(pluginName) && PLUGIN_SEGMENT_PATTERN.test(marketplaceName) ? {
|
|
281
|
+
pluginName,
|
|
282
|
+
marketplaceName
|
|
283
|
+
} : void 0;
|
|
284
|
+
}
|
|
285
|
+
/** Lists local/global first and separately requests workspace, shared, and personal catalogs. */
|
|
286
|
+
async function discoverCodexMarketplacePlugins(params) {
|
|
287
|
+
const requestParams = { cwds: [params.workspaceDir] };
|
|
288
|
+
const primary = await params.request(requestParams);
|
|
289
|
+
const warnings = (primary.marketplaceLoadErrors ?? []).map((error) => boundedCatalogText(error.message));
|
|
290
|
+
const marketplaces = [...primary.marketplaces];
|
|
291
|
+
try {
|
|
292
|
+
const supplemental = await params.request({
|
|
293
|
+
...requestParams,
|
|
294
|
+
marketplaceKinds: [...SUPPLEMENTAL_MARKETPLACE_KINDS]
|
|
295
|
+
});
|
|
296
|
+
marketplaces.push(...supplemental.marketplaces);
|
|
297
|
+
warnings.push(...(supplemental.marketplaceLoadErrors ?? []).map((error) => boundedCatalogText(error.message)));
|
|
298
|
+
} catch (error) {
|
|
299
|
+
let recoveredSupplementalMarketplace = false;
|
|
300
|
+
for (const kind of SUPPLEMENTAL_MARKETPLACE_KINDS) try {
|
|
301
|
+
const supplemental = await params.request({
|
|
302
|
+
...requestParams,
|
|
303
|
+
marketplaceKinds: [kind]
|
|
304
|
+
});
|
|
305
|
+
marketplaces.push(...supplemental.marketplaces);
|
|
306
|
+
recoveredSupplementalMarketplace ||= supplemental.marketplaces.length > 0;
|
|
307
|
+
warnings.push(...(supplemental.marketplaceLoadErrors ?? []).map((loadError) => boundedCatalogText(loadError.message)));
|
|
308
|
+
} catch (kindError) {
|
|
309
|
+
warnings.push(boundedCatalogText(`${kind} marketplace unavailable: ${kindError instanceof Error ? kindError.message : String(kindError)}`));
|
|
310
|
+
}
|
|
311
|
+
if (!recoveredSupplementalMarketplace && warnings.length === 0) warnings.push(boundedCatalogText(`Additional marketplaces could not be listed: ${error instanceof Error ? error.message : String(error)}`));
|
|
312
|
+
}
|
|
313
|
+
const discovered = /* @__PURE__ */ new Map();
|
|
314
|
+
const ambiguous = /* @__PURE__ */ new Set();
|
|
315
|
+
for (const marketplace of marketplaces) {
|
|
316
|
+
if (!PLUGIN_SEGMENT_PATTERN.test(marketplace.name)) continue;
|
|
317
|
+
for (const summary of marketplace.plugins) {
|
|
318
|
+
const pluginName = pluginSlug(summary, marketplace.name);
|
|
319
|
+
if (!pluginName) continue;
|
|
320
|
+
const id = `${pluginName}@${marketplace.name}`;
|
|
321
|
+
if (ambiguous.has(id)) continue;
|
|
322
|
+
const previous = discovered.get(id);
|
|
323
|
+
const next = {
|
|
324
|
+
id,
|
|
325
|
+
pluginName,
|
|
326
|
+
marketplaceName: marketplace.name,
|
|
327
|
+
installed: summary.installed,
|
|
328
|
+
enabled: summary.enabled,
|
|
329
|
+
available: summary.availability !== "DISABLED_BY_ADMIN" && summary.installPolicy !== "NOT_AVAILABLE",
|
|
330
|
+
...summary.installPolicy ? { installPolicy: summary.installPolicy } : {},
|
|
331
|
+
...summary.authPolicy ? { authPolicy: summary.authPolicy } : {},
|
|
332
|
+
...marketplace.path ? { marketplacePath: marketplace.path } : {},
|
|
333
|
+
...summary.remotePluginId?.trim() ? {
|
|
334
|
+
remotePluginId: summary.remotePluginId.trim(),
|
|
335
|
+
mustShowInstallationInterstitial: summary.mustShowInstallationInterstitial ?? null
|
|
336
|
+
} : {},
|
|
337
|
+
summaryId: summary.id
|
|
338
|
+
};
|
|
339
|
+
const description = pluginDescription(summary);
|
|
340
|
+
if (description) next.description = description;
|
|
341
|
+
if (previous && (previous.marketplacePath !== next.marketplacePath || previous.remotePluginId !== next.remotePluginId)) {
|
|
342
|
+
discovered.delete(id);
|
|
343
|
+
ambiguous.add(id);
|
|
344
|
+
warnings.push(`Multiple discovered plugins share ${id}; installation requires a unique identity.`);
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
if (!previous) discovered.set(id, next);
|
|
348
|
+
else {
|
|
349
|
+
const preferred = !previous.installed && next.installed || !previous.enabled && next.installed && next.enabled ? next : previous;
|
|
350
|
+
discovered.set(id, {
|
|
351
|
+
...preferred,
|
|
352
|
+
available: previous.available && next.available,
|
|
353
|
+
...preferred.remotePluginId ? { mustShowInstallationInterstitial: previous.mustShowInstallationInterstitial === true || next.mustShowInstallationInterstitial === true ? true : previous.mustShowInstallationInterstitial === false && next.mustShowInstallationInterstitial === false ? false : null } : {},
|
|
354
|
+
...previous.installPolicy === "NOT_AVAILABLE" || next.installPolicy === "NOT_AVAILABLE" ? { installPolicy: "NOT_AVAILABLE" } : {}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return {
|
|
360
|
+
plugins: [...discovered.values()].toSorted((left, right) => left.id.localeCompare(right.id)),
|
|
361
|
+
warnings
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
function pluginSlug(summary, marketplaceName) {
|
|
365
|
+
const qualified = parseCodexPluginMarketplaceId(summary.id);
|
|
366
|
+
if (qualified?.marketplaceName === marketplaceName) return qualified.pluginName;
|
|
367
|
+
const identitySegment = summary.id.split("/").at(-1);
|
|
368
|
+
if (identitySegment && PLUGIN_SEGMENT_PATTERN.test(identitySegment)) return identitySegment;
|
|
369
|
+
return PLUGIN_SEGMENT_PATTERN.test(summary.name) ? summary.name : void 0;
|
|
370
|
+
}
|
|
371
|
+
function pluginDescription(summary) {
|
|
372
|
+
const description = asOptionalRecord(summary.interface)?.shortDescription;
|
|
373
|
+
if (typeof description !== "string") return;
|
|
374
|
+
return boundedCatalogText(description) || void 0;
|
|
375
|
+
}
|
|
376
|
+
function boundedCatalogText(value) {
|
|
377
|
+
let sanitized = "";
|
|
378
|
+
for (const character of value) {
|
|
379
|
+
const codePoint = character.codePointAt(0);
|
|
380
|
+
sanitized += codePoint !== void 0 && (codePoint <= 31 || codePoint >= 127 && codePoint <= 159) ? " " : character;
|
|
381
|
+
}
|
|
382
|
+
return sanitized.replace(/\s+/g, " ").trim().slice(0, MAX_PLUGIN_DESCRIPTION_LENGTH);
|
|
383
|
+
}
|
|
384
|
+
//#endregion
|
|
385
|
+
export { parseCodexPermissionsModeArg as a, setCodexConversationModel as c, stopCodexConversationTurn as d, trackCodexConversationActiveTurn as f, parseCodexFastModeArg as i, setCodexConversationPermissions as l, canMutateCodexHost as m, parseCodexPluginMarketplaceId as n, readCodexConversationActiveTurn as o, CODEX_NATIVE_EXECUTION_AUTH_ERROR as p, formatPermissionsMode as r, setCodexConversationFastMode as s, discoverCodexMarketplacePlugins as t, steerCodexConversationTurn as u };
|