@openclaw/codex 2026.8.1-beta.2 → 2026.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +146 -0
- package/dist/{attempt-client-cleanup-DMLXUfa8.js → attempt-client-cleanup-CVPvp9dL.js} +47 -5
- package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
- package/dist/{binding-connection-I5Bo-AsX.js → binding-connection-CCQFs8lf.js} +15 -3
- package/dist/{bounded-turn-qgZmzy_4.js → bounded-turn-rq5tiSXk.js} +27 -26
- package/dist/{capabilities-CybGI1oz.js → capabilities-CGm_94eL.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-B1AEz8ZA.js → command-formatters-C54Yg3eA.js} +2 -2
- package/dist/{command-handlers-Db8pu_ds.js → command-handlers-BvOAHTrA.js} +111 -67
- package/dist/{compact-LspQaGfl.js → compact-Hd7SAc0N.js} +35 -30
- package/dist/{session-binding-DPxIvMgE.js → config-Cxw3Cl3k.js} +361 -1161
- package/dist/context-compaction-activity-BOeJf7yo.js +58 -0
- package/dist/doctor-contract-api.js +128 -26
- package/dist/{dynamic-tools-BVdyWkUD.js → dynamic-tools-BFoUcRdx.js} +1341 -1464
- package/dist/{effective-mcp-catalog-DIIhAtOZ.js → effective-mcp-catalog-BTJHnDSx.js} +2 -2
- package/dist/elicitation-input-DMkeki8d.js +71 -0
- package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
- package/dist/{event-projector-usage-e5huIQWu.js → event-projector-usage-D3PHFFXh.js} +18 -18
- package/dist/harness-DVfUQBlQ.js +248 -0
- package/dist/harness.js +2 -226
- package/dist/index.js +405 -299
- package/dist/{isolated-completion-C58NbL40.js → isolated-completion-Cbbx_5Ed.js} +4 -4
- package/dist/launch-args-sXOAg0SX.js +84 -0
- package/dist/managed-binary-ZkGodW19.js +248 -0
- package/dist/media-understanding-provider.js +2 -2
- package/dist/model-catalog-o6Cgjoss.js +101 -0
- package/dist/{models-BFlpn1Ex.js → models-DgFWSuxA.js} +25 -28
- package/dist/{native-subagent-monitor-DyTGmTUx.js → native-subagent-monitor-CwFyoylz.js} +385 -94
- package/dist/node-exec-server.runtime-DXrqpw1c.js +195 -0
- package/dist/plugin-approval-roundtrip-D80UZiJ_.js +95 -0
- package/dist/{plugin-marketplace-discovery-CzrGJdCR.js → plugin-marketplace-discovery-mdmScYOj.js} +60 -55
- package/dist/{plugin-metadata-cache-CNJPj4_b.js → plugin-metadata-cache-CulOABwu.js} +164 -134
- package/dist/{protocol-validators-B4F7L8Rf.js → protocol-validators-Bg5rpNxk.js} +203 -7
- package/dist/{rate-limits-DZXmOL8-.js → rate-limits-hFtzt2Up.js} +1 -1
- package/dist/{sandbox-guard-Cmwc9eIk.js → request-CCm4LaED.js} +207 -20
- package/dist/{run-attempt-P8BdxC1I.js → run-attempt-BwNQDH2u.js} +1506 -836
- package/dist/{runtime-artifact-BVSPdd6g.js → runtime-artifact-DeBvleJw.js} +4 -7
- package/dist/session-binding-q2WSTVmC.js +947 -0
- package/dist/{session-catalog-xwNi_SDM.js → session-catalog-C2Tae4rI.js} +1698 -1346
- package/dist/session-catalog-home-id-DAKUrm3C.js +112 -0
- package/dist/{session-cli-7hgXZDV7.js → session-cli-BuDjm5Ou.js} +20 -7
- package/dist/session-permission-policy-gLm40Vtq.js +160 -0
- package/dist/session-retirement-CdkI0bvb.js +90 -0
- package/dist/{session-upstream-marker-CrIFX06J.js → session-upstream-marker-Bcy33kam.js} +2 -3
- package/dist/{settled-turn-finalizer-BRWBO4MO.js → settled-turn-finalizer-B8JJcxCi.js} +27 -22
- package/dist/{shared-client-kIBbGjk4.js → shared-client-kNkljY-R.js} +2023 -607
- package/dist/{side-question-9HAL26l9.js → side-question-GwD73tX6.js} +109 -57
- package/dist/{thread-lifecycle-Bu1BTDXr.js → thread-lifecycle-Ss-uwnC4.js} +1208 -497
- package/dist/{thread-ownership-6kOQHlyC.js → thread-ownership-CeYBqg_4.js} +18 -8
- package/dist/{plugin-app-cache-key-C3H2CVp6.js → thread-resume-DF54hagX.js} +64 -6
- package/dist/{transcript-mirror-B9gGgnJS.js → transcript-mirror-CkEQIna-.js} +158 -41
- package/dist/transport-stdio-C7-s9TLG.js +708 -0
- package/dist/{upstream-prompt-provenance-ClRBije0.js → upstream-prompt-provenance-CFmsKwr9.js} +12 -14
- package/dist/{upstream-session-fork-CE-_LdnP.js → upstream-session-fork-BACGlOFa.js} +86 -88
- package/dist/{usage-CHlV0e-o.js → usage-C2l8Mils.js} +3 -3
- package/dist/{web-search-provider.runtime-DRw2Vl42.js → web-search-provider.runtime-B2XgRdFv.js} +3 -3
- package/openclaw.plugin.json +50 -2
- package/package.json +9 -8
- package/dist/app-server-policy-zcBDc1JU.js +0 -49
- package/dist/incognito-session-ET_ufDH-.js +0 -2
- package/dist/request-BRl5_UfX.js +0 -157
- package/dist/session-retirement-DoMMJFKm.js +0 -36
- package/dist/thread-resume-CPrJNQVM.js +0 -30
- package/dist/transport-stdio-DIImwDVS.js +0 -99
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { n as resolveManagedCodexAppServerStartOptions, r as resolveManagedCodexNativeCommand, t as isManagedCodexDesktopCommand } from "./managed-binary-ZkGodW19.js";
|
|
2
|
+
import { i as closeCodexAppServerTransportAndWait, t as createStdioTransport } from "./transport-stdio-C7-s9TLG.js";
|
|
3
|
+
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
|
+
import { mkdir } from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
|
|
7
|
+
import { killProcessTree } from "openclaw/plugin-sdk/process-runtime";
|
|
8
|
+
import { once } from "node:events";
|
|
9
|
+
import { sanitizeEnvVars } from "openclaw/plugin-sdk/sandbox";
|
|
10
|
+
//#region extensions/codex/src/node-exec-server.runtime.ts
|
|
11
|
+
const MAX_CODEX_EXEC_SERVER_MESSAGE_BYTES = 64 * 1024 * 1024;
|
|
12
|
+
const CODEX_EXEC_SERVER_TERMINATION_GRACE_MS = 1e3;
|
|
13
|
+
const CODEX_EXEC_SERVER_REAP_TIMEOUT_MS = 5e3;
|
|
14
|
+
const NODE_EXEC_SERVER_PLATFORM_ENVIRONMENT = /^(?:SYSTEMROOT|WINDIR|COMSPEC|PATHEXT|TEMP|TMP|TMPDIR)$/iu;
|
|
15
|
+
function validateNodeExecServerMessage(message) {
|
|
16
|
+
if (message.byteLength === 0 || message.byteLength > MAX_CODEX_EXEC_SERVER_MESSAGE_BYTES) throw new Error("Codex exec-server JSON-RPC message exceeds its 64 MiB limit.");
|
|
17
|
+
const encoded = Buffer.from(message.buffer, message.byteOffset, message.byteLength);
|
|
18
|
+
if (encoded.includes(10) || encoded.includes(13)) throw new Error("Codex exec-server JSON-RPC frames must contain exactly one message.");
|
|
19
|
+
let decoded;
|
|
20
|
+
try {
|
|
21
|
+
const text = new TextDecoder("utf-8", { fatal: true }).decode(encoded);
|
|
22
|
+
decoded = JSON.parse(text);
|
|
23
|
+
} catch {
|
|
24
|
+
throw new Error("Codex exec-server received malformed UTF-8 or JSON-RPC.");
|
|
25
|
+
}
|
|
26
|
+
if (!isRecord(decoded) || decoded.jsonrpc !== void 0 && decoded.jsonrpc !== "2.0" || typeof decoded.method !== "string" && !("id" in decoded && ("result" in decoded || "error" in decoded))) throw new Error("Codex exec-server received an invalid JSON-RPC message.");
|
|
27
|
+
return encoded;
|
|
28
|
+
}
|
|
29
|
+
function nodeExecServerAbortError(signal) {
|
|
30
|
+
return signal.reason instanceof Error ? signal.reason : /* @__PURE__ */ new Error("Codex node exec-server connection closed.");
|
|
31
|
+
}
|
|
32
|
+
function writeNodeExecServerMessage(child, message, signal) {
|
|
33
|
+
if (signal.aborted) throw nodeExecServerAbortError(signal);
|
|
34
|
+
const payload = Buffer.concat([message, Buffer.from("\n")]);
|
|
35
|
+
if (!child.stdin.write(payload)) return once(child.stdin, "drain", { signal }).then(() => void 0);
|
|
36
|
+
}
|
|
37
|
+
async function relayNodeExecServerOutput(child, send) {
|
|
38
|
+
let fragments = [];
|
|
39
|
+
let pendingBytes = 0;
|
|
40
|
+
for await (const rawChunk of child.stdout) {
|
|
41
|
+
const chunk = Buffer.isBuffer(rawChunk) ? rawChunk : Buffer.from(rawChunk);
|
|
42
|
+
let offset = 0;
|
|
43
|
+
while (offset < chunk.byteLength) {
|
|
44
|
+
const newline = chunk.indexOf(10, offset);
|
|
45
|
+
const fragment = chunk.subarray(offset, newline === -1 ? chunk.byteLength : newline);
|
|
46
|
+
const nextLength = pendingBytes + fragment.byteLength;
|
|
47
|
+
if (nextLength > 67108865) throw new Error("Codex exec-server stdout message exceeds its 64 MiB limit.");
|
|
48
|
+
if (fragment.byteLength > 0) fragments.push(fragment);
|
|
49
|
+
pendingBytes = nextLength;
|
|
50
|
+
if (newline === -1) {
|
|
51
|
+
if (pendingBytes > MAX_CODEX_EXEC_SERVER_MESSAGE_BYTES && fragment[fragment.byteLength - 1] !== 13) throw new Error("Codex exec-server stdout message exceeds its 64 MiB limit.");
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
const trailing = fragments.at(-1);
|
|
55
|
+
if (trailing?.[trailing.byteLength - 1] === 13) {
|
|
56
|
+
pendingBytes -= 1;
|
|
57
|
+
if (trailing.byteLength === 1) fragments.pop();
|
|
58
|
+
else fragments[fragments.length - 1] = trailing.subarray(0, trailing.byteLength - 1);
|
|
59
|
+
}
|
|
60
|
+
const message = validateNodeExecServerMessage(fragments.length === 1 ? fragments[0] : Buffer.concat(fragments, pendingBytes));
|
|
61
|
+
fragments = [];
|
|
62
|
+
pendingBytes = 0;
|
|
63
|
+
await send(message);
|
|
64
|
+
offset = newline + 1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (pendingBytes > 0) throw new Error("Codex exec-server stdout ended with an unterminated JSON-RPC message.");
|
|
68
|
+
}
|
|
69
|
+
function createNodeExecServerProcessOwner(child, closed) {
|
|
70
|
+
let termination;
|
|
71
|
+
return { terminate: () => termination ??= (async () => {
|
|
72
|
+
if (process.platform === "win32" && child.pid) killProcessTree(child.pid, { graceMs: CODEX_EXEC_SERVER_TERMINATION_GRACE_MS });
|
|
73
|
+
if (!await closeCodexAppServerTransportAndWait(child, {
|
|
74
|
+
forceKillDelayMs: CODEX_EXEC_SERVER_TERMINATION_GRACE_MS,
|
|
75
|
+
exitTimeoutMs: CODEX_EXEC_SERVER_REAP_TIMEOUT_MS
|
|
76
|
+
})) throw new Error("Codex node exec-server process tree did not terminate.");
|
|
77
|
+
await closed;
|
|
78
|
+
})() };
|
|
79
|
+
}
|
|
80
|
+
/** Runs the one-connection paired-node exec-server after lightweight command admission. */
|
|
81
|
+
async function runCodexNodeExecServer(params) {
|
|
82
|
+
const { io } = params;
|
|
83
|
+
const frames = io.frames;
|
|
84
|
+
if (!frames) throw new Error("Codex node exec-server requires duplex frames.");
|
|
85
|
+
const cwd = params.workspaceDir;
|
|
86
|
+
let writes;
|
|
87
|
+
let rejectDisconnected;
|
|
88
|
+
const disconnected = new Promise((_resolve, reject) => {
|
|
89
|
+
rejectDisconnected = reject;
|
|
90
|
+
});
|
|
91
|
+
disconnected.catch(() => {});
|
|
92
|
+
const onAbort = () => {
|
|
93
|
+
const error = nodeExecServerAbortError(io.signal);
|
|
94
|
+
rejectDisconnected(error);
|
|
95
|
+
};
|
|
96
|
+
io.signal.addEventListener("abort", onAbort, { once: true });
|
|
97
|
+
try {
|
|
98
|
+
if (io.signal.aborted) throw nodeExecServerAbortError(io.signal);
|
|
99
|
+
return await withTempWorkspace({
|
|
100
|
+
rootDir: resolvePreferredOpenClawTmpDir(),
|
|
101
|
+
prefix: "codex-node-exec-server-"
|
|
102
|
+
}, async ({ dir }) => {
|
|
103
|
+
const codexHome = path.join(dir, ".codex");
|
|
104
|
+
await mkdir(codexHome, {
|
|
105
|
+
recursive: true,
|
|
106
|
+
mode: 448
|
|
107
|
+
});
|
|
108
|
+
const resolved = await resolveManagedCodexAppServerStartOptions({
|
|
109
|
+
transport: "stdio",
|
|
110
|
+
command: "codex",
|
|
111
|
+
commandSource: "managed",
|
|
112
|
+
managedCommandOrder: "package-first",
|
|
113
|
+
args: [
|
|
114
|
+
"exec-server",
|
|
115
|
+
"--listen",
|
|
116
|
+
"stdio"
|
|
117
|
+
],
|
|
118
|
+
headers: {}
|
|
119
|
+
});
|
|
120
|
+
const native = resolveManagedCodexNativeCommand(resolved.command);
|
|
121
|
+
if (!native || isManagedCodexDesktopCommand(resolved.command)) throw new Error("Codex node exec-server requires the pinned managed package binary.");
|
|
122
|
+
const baseEnv = sanitizeEnvVars(process.env, {
|
|
123
|
+
strictMode: true,
|
|
124
|
+
customAllowedPatterns: [NODE_EXEC_SERVER_PLATFORM_ENVIRONMENT]
|
|
125
|
+
}).allowed;
|
|
126
|
+
if (io.signal.aborted) throw nodeExecServerAbortError(io.signal);
|
|
127
|
+
params.assertExecAuthorized();
|
|
128
|
+
const child = await createStdioTransport({
|
|
129
|
+
transport: "stdio",
|
|
130
|
+
command: native,
|
|
131
|
+
commandSource: "resolved-managed",
|
|
132
|
+
args: resolved.args,
|
|
133
|
+
headers: {},
|
|
134
|
+
cwd,
|
|
135
|
+
env: {
|
|
136
|
+
HOME: dir,
|
|
137
|
+
CODEX_HOME: codexHome,
|
|
138
|
+
...process.platform === "win32" ? { USERPROFILE: dir } : {}
|
|
139
|
+
},
|
|
140
|
+
clearEnv: ["NODE_OPTIONS"]
|
|
141
|
+
}, baseEnv, () => {
|
|
142
|
+
if (io.signal.aborted) throw nodeExecServerAbortError(io.signal);
|
|
143
|
+
params.assertExecAuthorized();
|
|
144
|
+
});
|
|
145
|
+
child.stdin.on("error", (error) => {
|
|
146
|
+
rejectDisconnected(error);
|
|
147
|
+
});
|
|
148
|
+
let stderr = Buffer.alloc(0);
|
|
149
|
+
child.stderr.on("data", (chunk) => {
|
|
150
|
+
const bounded = (Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)).subarray(-4096);
|
|
151
|
+
stderr = Buffer.concat([stderr, bounded]).subarray(-4096);
|
|
152
|
+
});
|
|
153
|
+
const closed = new Promise((resolve) => {
|
|
154
|
+
child.once("close", (code, signal) => resolve({
|
|
155
|
+
code,
|
|
156
|
+
signal
|
|
157
|
+
}));
|
|
158
|
+
});
|
|
159
|
+
child.once("error", (error) => {
|
|
160
|
+
rejectDisconnected(error);
|
|
161
|
+
});
|
|
162
|
+
const owner = createNodeExecServerProcessOwner(child, closed);
|
|
163
|
+
params.activeProcesses.add(owner.terminate);
|
|
164
|
+
const output = relayNodeExecServerOutput(child, frames.send.bind(frames));
|
|
165
|
+
output.catch((error) => {
|
|
166
|
+
rejectDisconnected(error instanceof Error ? error : new Error(String(error)));
|
|
167
|
+
});
|
|
168
|
+
try {
|
|
169
|
+
if (io.signal.aborted) throw nodeExecServerAbortError(io.signal);
|
|
170
|
+
params.onFrameReceiver((message) => {
|
|
171
|
+
const encoded = validateNodeExecServerMessage(message);
|
|
172
|
+
const operation = writes ? writes.then(() => writeNodeExecServerMessage(child, encoded, io.signal)) : writeNodeExecServerMessage(child, encoded, io.signal);
|
|
173
|
+
if (!operation) return;
|
|
174
|
+
const observed = operation.catch(() => {});
|
|
175
|
+
writes = observed;
|
|
176
|
+
observed.then(() => {
|
|
177
|
+
if (writes === observed) writes = void 0;
|
|
178
|
+
});
|
|
179
|
+
return operation;
|
|
180
|
+
});
|
|
181
|
+
const outcome = await Promise.race([closed, disconnected]);
|
|
182
|
+
const diagnostic = stderr.toString("utf8").trim();
|
|
183
|
+
throw new Error(`Codex node exec-server exited (code ${outcome.code ?? "none"}, signal ${outcome.signal ?? "none"})${diagnostic ? `: ${diagnostic}` : "."}`);
|
|
184
|
+
} finally {
|
|
185
|
+
await owner.terminate();
|
|
186
|
+
params.activeProcesses.delete(owner.terminate);
|
|
187
|
+
await Promise.allSettled([output, ...writes ? [writes] : []]);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
} finally {
|
|
191
|
+
io.signal.removeEventListener("abort", onAbort);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//#endregion
|
|
195
|
+
export { runCodexNodeExecServer };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { F as resolveCodexGatewayTimeoutWithGraceMs } from "./shared-client-kNkljY-R.js";
|
|
2
|
+
import { isApprovalNotFoundError, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
3
|
+
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
4
|
+
//#region extensions/codex/src/app-server/plugin-approval-roundtrip.ts
|
|
5
|
+
const DEFAULT_CODEX_APPROVAL_TIMEOUT_MS = 12e4;
|
|
6
|
+
const MAX_PLUGIN_APPROVAL_TITLE_LENGTH = 80;
|
|
7
|
+
const MAX_PLUGIN_APPROVAL_DESCRIPTION_LENGTH = 256;
|
|
8
|
+
const ANSI_OSC_SEQUENCE_RE = new RegExp(String.raw`(?:\u001b]|\u009d)[^\u001b\u009c\u0007]*(?:\u0007|\u001b\\|\u009c)`, "g");
|
|
9
|
+
const ANSI_CONTROL_SEQUENCE_RE = new RegExp(String.raw`(?:\u001b\[[0-?]*[ -/]*[@-~]|\u009b[0-?]*[ -/]*[@-~]|\u001b[@-Z\\-_])`, "g");
|
|
10
|
+
const CONTROL_CHARACTER_RE = new RegExp(String.raw`[\u0000-\u001f\u007f-\u009f]+`, "g");
|
|
11
|
+
const INVISIBLE_FORMATTING_CONTROL_RE = new RegExp(String.raw`[\u00ad\u034f\u061c\u200b-\u200f\u202a-\u202e\u2060-\u206f\ufeff\ufe00-\ufe0f\u{e0100}-\u{e01ef}]`, "gu");
|
|
12
|
+
const DANGLING_TERMINAL_SEQUENCE_SUFFIX_RE = new RegExp(String.raw`(?:\u001b\][^\u001b\u009c\u0007]*|\u009d[^\u001b\u009c\u0007]*|\u001b\[[0-?]*[ -/]*|\u009b[0-?]*[ -/]*|\u001b)$`);
|
|
13
|
+
const CODEX_APPROVAL_TIMEOUT_SUBJECTS = {
|
|
14
|
+
command: "Command approval",
|
|
15
|
+
"file-change": "File change approval",
|
|
16
|
+
permissions: "Permission approval",
|
|
17
|
+
other: "Approval"
|
|
18
|
+
};
|
|
19
|
+
function codexApprovalTimeoutText(kind) {
|
|
20
|
+
return `${CODEX_APPROVAL_TIMEOUT_SUBJECTS[kind]} timed out before an operator responded.`;
|
|
21
|
+
}
|
|
22
|
+
/** Starts a two-phase plugin approval request through the OpenClaw gateway. */
|
|
23
|
+
async function requestPluginApproval(params) {
|
|
24
|
+
const timeoutMs = DEFAULT_CODEX_APPROVAL_TIMEOUT_MS;
|
|
25
|
+
return params.hostCapabilities.requestApproval({
|
|
26
|
+
title: truncateCodexApprovalDisplayText(params.title, MAX_PLUGIN_APPROVAL_TITLE_LENGTH),
|
|
27
|
+
description: truncateCodexApprovalDisplayText(params.description, MAX_PLUGIN_APPROVAL_DESCRIPTION_LENGTH),
|
|
28
|
+
severity: params.severity,
|
|
29
|
+
toolName: params.toolName,
|
|
30
|
+
toolCallId: params.toolCallId,
|
|
31
|
+
timeoutMs,
|
|
32
|
+
transportTimeoutMs: resolveCodexGatewayTimeoutWithGraceMs(timeoutMs),
|
|
33
|
+
...params.allowedDecisions ? { allowedDecisions: params.allowedDecisions } : {}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/** Detects the gateway's explicit null-decision marker for unavailable approvals. */
|
|
37
|
+
function approvalRequestExplicitlyUnavailable(result) {
|
|
38
|
+
if (result === null || result === void 0 || typeof result !== "object") return false;
|
|
39
|
+
let descriptor;
|
|
40
|
+
try {
|
|
41
|
+
descriptor = Object.getOwnPropertyDescriptor(result, "decision");
|
|
42
|
+
} catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return descriptor !== void 0 && "value" in descriptor && descriptor.value === null;
|
|
46
|
+
}
|
|
47
|
+
/** Waits for the gateway's final approval decision, respecting turn aborts. */
|
|
48
|
+
async function waitForPluginApprovalDecision(params) {
|
|
49
|
+
const timeoutMs = DEFAULT_CODEX_APPROVAL_TIMEOUT_MS;
|
|
50
|
+
const waitPromise = params.hostCapabilities.waitForApproval({
|
|
51
|
+
approvalId: params.approvalId,
|
|
52
|
+
timeoutMs,
|
|
53
|
+
transportTimeoutMs: resolveCodexGatewayTimeoutWithGraceMs(timeoutMs),
|
|
54
|
+
signal: params.signal
|
|
55
|
+
}).catch((error) => {
|
|
56
|
+
if (isApprovalNotFoundError(error)) return;
|
|
57
|
+
throw error;
|
|
58
|
+
});
|
|
59
|
+
if (!params.signal) return await waitPromise;
|
|
60
|
+
let onAbort;
|
|
61
|
+
const abortPromise = new Promise((_, reject) => {
|
|
62
|
+
if (params.signal.aborted) {
|
|
63
|
+
reject(toErrorObject(params.signal.reason, "Non-Error rejection"));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
onAbort = () => reject(toErrorObject(params.signal.reason, "Non-Error rejection"));
|
|
67
|
+
params.signal.addEventListener("abort", onAbort, { once: true });
|
|
68
|
+
});
|
|
69
|
+
try {
|
|
70
|
+
return await Promise.race([waitPromise, abortPromise]);
|
|
71
|
+
} finally {
|
|
72
|
+
if (onAbort) params.signal.removeEventListener("abort", onAbort);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Converts a gateway exec approval decision into the app-server approval outcome enum. */
|
|
76
|
+
function mapExecDecisionToOutcome(decision) {
|
|
77
|
+
switch (decision) {
|
|
78
|
+
case "allow-once": return "approved-once";
|
|
79
|
+
case "allow-always": return "approved-session";
|
|
80
|
+
case "deny": return "denied";
|
|
81
|
+
default: return "unavailable";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function truncateCodexApprovalDisplayText(value, maxLength) {
|
|
85
|
+
return value.length <= maxLength ? value : `${truncateUtf16Safe(value, maxLength - 3)}...`;
|
|
86
|
+
}
|
|
87
|
+
function stripDanglingCodexApprovalTerminalSequence(value) {
|
|
88
|
+
return value.replace(DANGLING_TERMINAL_SEQUENCE_SUFFIX_RE, "");
|
|
89
|
+
}
|
|
90
|
+
function sanitizeCodexApprovalVisibleText(value, options = {}) {
|
|
91
|
+
const terminalSafe = value.replace(ANSI_OSC_SEQUENCE_RE, "").replace(ANSI_CONTROL_SEQUENCE_RE, "");
|
|
92
|
+
return (options.stripDanglingTerminalSequence ? stripDanglingCodexApprovalTerminalSequence(terminalSafe) : terminalSafe).replace(INVISIBLE_FORMATTING_CONTROL_RE, " ").replace(CONTROL_CHARACTER_RE, " ").replace(/\s+/g, " ").trim();
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { sanitizeCodexApprovalVisibleText as a, waitForPluginApprovalDecision as c, requestPluginApproval as i, codexApprovalTimeoutText as n, stripDanglingCodexApprovalTerminalSequence as o, mapExecDecisionToOutcome as r, truncateCodexApprovalDisplayText as s, approvalRequestExplicitlyUnavailable as t };
|
package/dist/{plugin-marketplace-discovery-CzrGJdCR.js → plugin-marketplace-discovery-mdmScYOj.js}
RENAMED
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { k as isCodexFastServiceTier } from "./config-Cxw3Cl3k.js";
|
|
2
|
+
import { c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient } from "./shared-client-kNkljY-R.js";
|
|
3
|
+
import { o as isCodexAppServerNativeAuthProfile, r as bindingStoreKey, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-q2WSTVmC.js";
|
|
4
|
+
import { E as resolveCodexAppServerRequestModelSelection, O as resolveCodexBindingModelProviderFallback } from "./thread-lifecycle-Ss-uwnC4.js";
|
|
5
|
+
import { r as formatCodexDisplayText } from "./command-formatters-C54Yg3eA.js";
|
|
6
|
+
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-CCQFs8lf.js";
|
|
6
7
|
import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
8
|
import { resolveAgentDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
8
|
-
import { patchSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
9
|
+
import { getSessionEntry, patchSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
9
10
|
import { ModelSelectionLockedError, applyModelOverrideWithAuthProfileCompatibility } from "openclaw/plugin-sdk/model-session-runtime";
|
|
10
11
|
//#region extensions/codex/src/command-authorization.ts
|
|
11
12
|
const CODEX_NATIVE_EXECUTION_AUTH_ERROR = "Only an owner or operator.admin can control Codex native execution.";
|
|
13
|
+
const CODEX_HOST_INSPECTION_AUTH_ERROR = "Only an owner or operator.admin can inspect Codex host state.";
|
|
14
|
+
const CODEX_FULL_PERMISSIONS_AUTH_ERROR = "Full Codex permissions require operator.admin. Choose Admin in the Control UI permission picker, or use an admin-authenticated CLI.";
|
|
15
|
+
function hasCodexAdminScope(ctx) {
|
|
16
|
+
return ctx.gatewayClientScopes?.includes("operator.admin") === true;
|
|
17
|
+
}
|
|
12
18
|
function canMutateCodexHost(ctx) {
|
|
13
|
-
return ctx.senderIsOwner === true || ctx
|
|
19
|
+
return ctx.senderIsOwner === true || hasCodexAdminScope(ctx);
|
|
14
20
|
}
|
|
15
21
|
//#endregion
|
|
16
22
|
//#region extensions/codex/src/conversation-control.ts
|
|
@@ -140,23 +146,23 @@ async function setCodexConversationModel(params) {
|
|
|
140
146
|
});
|
|
141
147
|
const nextModel = modelSelection.model;
|
|
142
148
|
const modelChanged = nextModel !== binding.model || nextModelProvider !== binding.modelProvider;
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (session) {
|
|
149
|
+
const projectionPatch = modelChanged && binding.contextEngine?.projection ? { contextEngine: {
|
|
150
|
+
...binding.contextEngine,
|
|
151
|
+
projection: void 0
|
|
152
|
+
} } : {};
|
|
153
|
+
const identity = params.identity;
|
|
154
|
+
if (identity.kind === "session" && identity.sessionKey) {
|
|
149
155
|
if (!await patchSessionEntry({
|
|
150
|
-
agentId:
|
|
151
|
-
storePath: resolveStorePath(params.config?.session?.store, { agentId:
|
|
152
|
-
sessionKey:
|
|
156
|
+
agentId: identity.agentId,
|
|
157
|
+
storePath: resolveStorePath(params.config?.session?.store, { agentId: identity.agentId }),
|
|
158
|
+
sessionKey: identity.sessionKey,
|
|
153
159
|
requireWriteSuccess: true,
|
|
154
160
|
replaceEntry: true,
|
|
155
161
|
update: (entry) => {
|
|
156
|
-
if (entry.sessionId !==
|
|
162
|
+
if (entry.sessionId !== identity.sessionId) throw new Error("Codex session changed while applying the model selection.");
|
|
157
163
|
applyModelOverrideWithAuthProfileCompatibility({
|
|
158
164
|
cfg: params.config ?? {},
|
|
159
|
-
agentDir: params.agentDir ?? resolveAgentDir(params.config ?? {},
|
|
165
|
+
agentDir: params.agentDir ?? resolveAgentDir(params.config ?? {}, identity.agentId),
|
|
160
166
|
entry,
|
|
161
167
|
currentProvider: binding.modelProvider ?? "openai",
|
|
162
168
|
selection: {
|
|
@@ -168,25 +174,11 @@ async function setCodexConversationModel(params) {
|
|
|
168
174
|
return entry;
|
|
169
175
|
}
|
|
170
176
|
})) throw new Error("Codex session changed while applying the model selection.");
|
|
171
|
-
if (
|
|
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
|
-
} });
|
|
177
|
+
if (modelChanged && binding.contextEngine?.projection) await patchThreadBinding(params.bindingStore, identity, binding.threadId, projectionPatch);
|
|
183
178
|
} else await patchThreadBinding(params.bindingStore, params.identity, binding.threadId, {
|
|
184
179
|
model: nextModel,
|
|
185
180
|
modelProvider: nextModelProvider,
|
|
186
|
-
...
|
|
187
|
-
...binding.contextEngine,
|
|
188
|
-
projection: void 0
|
|
189
|
-
} } : {}
|
|
181
|
+
...projectionPatch
|
|
190
182
|
});
|
|
191
183
|
return `Codex model set to ${formatCodexDisplayText(nextModel)}.`;
|
|
192
184
|
}
|
|
@@ -198,14 +190,31 @@ async function setCodexConversationFastMode(params) {
|
|
|
198
190
|
return `Codex fast mode ${params.enabled ? "enabled" : "disabled"}.`;
|
|
199
191
|
}
|
|
200
192
|
async function setCodexConversationPermissions(params) {
|
|
201
|
-
const
|
|
202
|
-
if (!params.mode)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
193
|
+
const storePath = resolveStorePath(params.config?.session?.store, { agentId: params.session.agentId });
|
|
194
|
+
if (!params.mode) {
|
|
195
|
+
const entry = getSessionEntry({
|
|
196
|
+
agentId: params.session.agentId,
|
|
197
|
+
hydrateSkillPromptRefs: false,
|
|
198
|
+
readConsistency: "latest",
|
|
199
|
+
sessionKey: params.session.sessionKey,
|
|
200
|
+
storePath
|
|
201
|
+
});
|
|
202
|
+
if (entry?.sessionId !== params.session.sessionId) throw new Error("Codex session changed while reading the permission mode.");
|
|
203
|
+
return `Codex permissions: ${formatPermissionsMode(entry.permissionMode)}.`;
|
|
204
|
+
}
|
|
205
|
+
if (!await patchSessionEntry({
|
|
206
|
+
agentId: params.session.agentId,
|
|
207
|
+
storePath,
|
|
208
|
+
sessionKey: params.session.sessionKey,
|
|
209
|
+
requireWriteSuccess: true,
|
|
210
|
+
replaceEntry: true,
|
|
211
|
+
update: (entry) => {
|
|
212
|
+
if (entry.sessionId !== params.session.sessionId) throw new Error("Codex session changed while applying the permission mode.");
|
|
213
|
+
entry.permissionMode = params.mode === "yolo" ? "full" : "guarded";
|
|
214
|
+
return entry;
|
|
215
|
+
}
|
|
216
|
+
})) throw new Error("Codex session changed while applying the permission mode.");
|
|
217
|
+
return `Codex permissions set to ${params.mode === "yolo" ? "full access" : "guarded"}.`;
|
|
209
218
|
}
|
|
210
219
|
function parseCodexFastModeArg(arg) {
|
|
211
220
|
const normalized = arg?.trim().toLowerCase();
|
|
@@ -217,10 +226,15 @@ function parseCodexPermissionsModeArg(arg) {
|
|
|
217
226
|
const normalized = arg?.trim().toLowerCase();
|
|
218
227
|
if (!normalized || normalized === "status") return;
|
|
219
228
|
if (normalized === "yolo" || normalized === "full" || normalized === "full-access") return "yolo";
|
|
220
|
-
if (
|
|
229
|
+
if ([
|
|
230
|
+
"default",
|
|
231
|
+
"guardian",
|
|
232
|
+
"guarded",
|
|
233
|
+
"approve"
|
|
234
|
+
].includes(normalized)) return "default";
|
|
221
235
|
}
|
|
222
|
-
function formatPermissionsMode(
|
|
223
|
-
return
|
|
236
|
+
function formatPermissionsMode(mode) {
|
|
237
|
+
return mode === "full" ? "full access" : mode ?? "default";
|
|
224
238
|
}
|
|
225
239
|
async function requireThreadBinding(bindingStore, identity) {
|
|
226
240
|
const binding = await bindingStore.read(identity);
|
|
@@ -251,15 +265,6 @@ function resolveConversationControlModelProvider(params) {
|
|
|
251
265
|
if (isCodexAppServerNativeAuthProfile(params) && modelProvider.toLowerCase() === "openai") return;
|
|
252
266
|
return modelProvider.toLowerCase() === "openai" ? "openai" : modelProvider;
|
|
253
267
|
}
|
|
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
268
|
//#endregion
|
|
264
269
|
//#region extensions/codex/src/plugin-marketplace-discovery.ts
|
|
265
270
|
/** Read-only discovery of Codex-owned local, curated, and remote plugin marketplaces. */
|
|
@@ -382,4 +387,4 @@ function boundedCatalogText(value) {
|
|
|
382
387
|
return sanitized.replace(/\s+/g, " ").trim().slice(0, MAX_PLUGIN_DESCRIPTION_LENGTH);
|
|
383
388
|
}
|
|
384
389
|
//#endregion
|
|
385
|
-
export { parseCodexPermissionsModeArg as a, setCodexConversationModel as c, stopCodexConversationTurn as d, trackCodexConversationActiveTurn as f, parseCodexFastModeArg as i, setCodexConversationPermissions as l,
|
|
390
|
+
export { hasCodexAdminScope as _, parseCodexPermissionsModeArg as a, setCodexConversationModel as c, stopCodexConversationTurn as d, trackCodexConversationActiveTurn as f, canMutateCodexHost as g, CODEX_NATIVE_EXECUTION_AUTH_ERROR as h, parseCodexFastModeArg as i, setCodexConversationPermissions as l, CODEX_HOST_INSPECTION_AUTH_ERROR as m, parseCodexPluginMarketplaceId as n, readCodexConversationActiveTurn as o, CODEX_FULL_PERMISSIONS_AUTH_ERROR as p, formatPermissionsMode as r, setCodexConversationFastMode as s, discoverCodexMarketplacePlugins as t, steerCodexConversationTurn as u };
|