@openclaw/codex 2026.9.1 → 2026.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +6 -6
- package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-Bp1ZOnk2.js} +76 -32
- package/dist/{attempt-context-DmQUNWwT.js → attempt-context-CSazkWns.js} +6 -6
- package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-DxGJRYbY.js} +46 -45
- package/dist/{capabilities-dIjNVCYH.js → capabilities-B1mgvpP8.js} +2 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-CLHhEB1Q.js → command-formatters-DSbGMXA0.js} +2 -2
- package/dist/{command-handlers-CTGb2csu.js → command-handlers-DOJvGv6-.js} +146 -74
- package/dist/{compact-_t0HQrUS.js → compact-Y_xBqrHN.js} +83 -48
- package/dist/{config-BhmfC1s6.js → config-CyapYSji.js} +47 -105
- package/dist/config-utils-C57JiJrU.js +69 -0
- package/dist/doctor-contract-api.js +4 -5
- package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-BwpvTxaX.js} +678 -638
- package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
- package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-B9kp6iGC.js} +11 -2
- package/dist/{event-projector-usage-C5mcrGjp.js → event-projector-usage-ZqEVbAEY.js} +30 -13
- package/dist/{harness-DXVZ5II5.js → harness-Czh2Sdoc.js} +36 -13
- package/dist/harness.js +1 -1
- package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
- package/dist/index.js +68 -84
- package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-CRh-51AK.js} +9 -21
- package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DcpnJF9x.js} +105 -73
- package/dist/media-understanding-provider.js +1 -1
- package/dist/{model-catalog-CUM68Hkl.js → model-catalog-DT5vo6qo.js} +5 -5
- package/dist/{models-sYnEc0gd.js → models-CcrgSMQR.js} +4 -4
- package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-B3bvQGcg.js} +12 -11
- package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-nfbUOtUB.js} +3 -3
- package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-aQVdyL5g.js} +1 -1
- package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → plugin-marketplace-discovery-B7gHXJ3d.js} +35 -22
- package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-BwCLTY_U.js} +5 -5
- package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-BpG9Ltc5.js} +2 -2
- package/dist/{rate-limits-CawQJfUS.js → rate-limits-Fx_l4eNa.js} +1 -1
- package/dist/{request-DYAI5FQE.js → request-C8H22rPi.js} +2 -2
- package/dist/{run-attempt-D1hJO4fX.js → run-attempt-BzthFQSM.js} +977 -723
- package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-Bh_gf6-t.js} +3 -3
- package/dist/{session-binding-BHuTCRZQ.js → session-binding-4Ki04sW-.js} +94 -282
- package/dist/session-binding-record-CyaXZvTe.js +270 -0
- package/dist/{session-catalog-yyvTWFOw.js → session-catalog-B47uwekb.js} +266 -114
- package/dist/{session-cli-CmFEXMAM.js → session-cli-BjLhpmS1.js} +1 -1
- package/dist/session-history-DWmMqiqW.js +93 -0
- package/dist/session-history-read-LHldwvyh.js +36 -0
- package/dist/session-history-worker-runtime.js +48 -0
- package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-zZVcx0ME.js} +30 -31
- package/dist/session-history.worker.js +2 -0
- package/dist/{session-initialization-BeWzjGiR.js → session-initialization-BCFVnLL4.js} +2 -1
- package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-BaueHmSj.js} +1 -1
- package/dist/{session-retirement-BujDjXVF.js → session-retirement-DNdmYdFc.js} +7 -7
- package/dist/{session-upstream-marker-C351-5Qw.js → session-upstream-marker-DReTpGz6.js} +4 -3
- package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
- package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BI-b1sry.js} +53 -42
- package/dist/{shared-client-DxcfF9KX.js → shared-client-CKhX2kFt.js} +279 -268
- package/dist/{side-question-BTZAII4l.js → side-question-B6DWAw1A.js} +85 -36
- package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-DPK30jad.js} +382 -388
- package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-CbucAmmp.js} +5 -5
- package/dist/thread-policy-CTalhWFy.js +105 -0
- package/dist/{thread-resume-C7pyVKeW.js → thread-resume-BLgqkUc1.js} +7 -7
- package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-_njEB84z.js} +67 -125
- package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
- package/dist/{transport-stdio-CyPldczm.js → transport-stdio-CzTngV0j.js} +10 -8
- package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-1fwbNKzQ.js} +85 -165
- package/dist/{usage-Bj-rrzkR.js → usage-i9fv5-4m.js} +3 -3
- package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
- package/package.json +6 -6
- package/dist/binding-connection-E6uDsPlx.js +0 -45
- package/dist/launch-args-RXQwn8zV.js +0 -90
- package/dist/session-history-C5J1AKzG.js +0 -87
- package/dist/thread-policy-g4KbJPzp.js +0 -54
|
@@ -1,83 +1,50 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
1
|
+
import { l as sessionBindingIdentity } from "./session-binding-record-CyaXZvTe.js";
|
|
2
|
+
import { A as resolveOpenClawExecPolicyForCodexAppServer, B as isJsonObject, O as readCodexPluginConfig, p as assertCodexModelBackedReviewerEffectiveConfig, s as resolveCodexSupervisionAppServerRuntimeOptions, z as flattenCodexDynamicToolFunctions } from "./config-CyapYSji.js";
|
|
3
|
+
import { Ct as claimCodexAppServerLiveThread, Et as hasCodexAppServerLiveThread, Q as assertCodexThreadAcceptsDirectInput, Xt as readCodexSessionMeta, et as assertCodexThreadForkResponse, f as readCodexAppServerClientDesktopGenerationFingerprint } from "./shared-client-CKhX2kFt.js";
|
|
4
|
+
import "./session-binding-4Ki04sW-.js";
|
|
5
|
+
import { i as buildCodexPluginAppCacheKey } from "./thread-resume-BLgqkUc1.js";
|
|
6
|
+
import { $ as resolveCodexNativeSkillIsolation, C as buildDeveloperInstructions, Et as mergeCodexThreadConfigs, F as assertCodexNativeHookRelayAllowed, I as buildCodexNativeHookRelayConfig, Ot as shouldBuildCodexPluginThreadConfig, Q as applyCodexNativeSkillIsolation, R as buildCodexNativeHookRelayId, S as resolveCodexWebSearchPlan, St as buildCodexPluginThreadConfig, V as resolveCodexNativeHookRelayEvents, W as checkCodexThreadAppAvailability, Z as parseCodexNativeToolCatalog, it as fingerprintUserMcpServersConfigPatch, rt as fingerprintJsonObject, tt as codexDynamicToolsFingerprint, y as buildCodexThreadConfiguration } from "./thread-lifecycle-DPK30jad.js";
|
|
7
|
+
import { o as withCodexAppServerThreadMutation } from "./thread-ownership-CbucAmmp.js";
|
|
8
|
+
import { i as refreshCodexThreadPolicy, n as CodexThreadPolicyHandoffError } from "./thread-policy-CTalhWFy.js";
|
|
9
|
+
import { l as projectCodexUserItemText } from "./transcript-mirror-_njEB84z.js";
|
|
10
|
+
import { l as resolveCodexNativeExecutionPolicy, t as CodexAppServerScopedRequestRejectedError } from "./request-C8H22rPi.js";
|
|
10
11
|
import { i as readUpstreamUserText, r as readMirrorIdentity } from "./upstream-prompt-provenance-LphB8slG.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
12
|
+
import { i as fingerprintCodexMirrorSourceMessage, o as readCodexMirrorSourceFingerprint } from "./transcript-mirror-attestation-Byl34PC-.js";
|
|
13
|
+
import { n as prepareCodexSessionInitialization } from "./session-initialization-BCFVnLL4.js";
|
|
14
|
+
import { i as createImportedCodexSession, n as codexUpstreamBaseline, t as codexLastTerminalTurnId } from "./session-upstream-marker-DReTpGz6.js";
|
|
15
|
+
import { l as isCodexDynamicToolExcluded, n as resolveCodexProviderWebSearchSupportForClient } from "./provider-capabilities-BpG9Ltc5.js";
|
|
16
|
+
import { o as prepareCodexWorkspaceDeveloperInstructions } from "./attempt-context-CSazkWns.js";
|
|
15
17
|
import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
18
|
+
import { randomUUID } from "node:crypto";
|
|
19
|
+
import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
16
20
|
import { lstat } from "node:fs/promises";
|
|
17
21
|
import path from "node:path";
|
|
18
22
|
import { loadCodexBundleMcpThreadConfig } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
19
23
|
import { constants, createZstdDecompress } from "node:zlib";
|
|
20
24
|
import { root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
21
|
-
import { randomUUID } from "node:crypto";
|
|
22
25
|
import { isDeepStrictEqual } from "node:util";
|
|
23
26
|
import { resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
24
27
|
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
25
|
-
import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
26
28
|
import { buildCodexUserMcpServersThreadConfigPatchForRuntime, resolveCodexMcpToolOverridesForAgent } from "openclaw/plugin-sdk/codex-mcp-projection";
|
|
27
29
|
import { buildNativeHookRelayCommandPlan } from "openclaw/plugin-sdk/native-hook-relay-runtime";
|
|
28
30
|
import { appendSessionTranscriptMessagesByIdentity, readVisibleSessionTranscriptMessageEntries } from "openclaw/plugin-sdk/session-transcript-runtime";
|
|
29
|
-
//#region extensions/codex/src/session-rollout-
|
|
31
|
+
//#region extensions/codex/src/session-rollout-snapshot.ts
|
|
30
32
|
const CHUNK_BYTES = 65536;
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const DECOMPRESSED_BYTES = 33554432;
|
|
33
|
+
const META_BYTES = 1048576;
|
|
34
|
+
const COMPRESSED_BYTES = 8388608;
|
|
34
35
|
const DEADLINE_MS = 5e3;
|
|
35
36
|
const utf8Decoder = new TextDecoder("utf-8", { fatal: true });
|
|
36
|
-
function
|
|
37
|
-
if (typeof value !== "string" || !value.trim() || Buffer.byteLength(value) > 256) throw new Error("Codex rollout has an invalid model or provider selection");
|
|
38
|
-
return value;
|
|
39
|
-
}
|
|
40
|
-
function record(line) {
|
|
41
|
-
if (!line.length || line.length > RECORD_BYTES) throw new Error("Codex rollout record exceeds the observation limit");
|
|
37
|
+
function parseMetadata(line, threadId) {
|
|
42
38
|
const parsed = JSON.parse(utf8Decoder.decode(line));
|
|
43
|
-
if (!isRecord(parsed) ||
|
|
44
|
-
return
|
|
45
|
-
type: parsed.type,
|
|
46
|
-
payload: parsed.payload
|
|
47
|
-
};
|
|
39
|
+
if (!isRecord(parsed) || parsed.type !== "session_meta" || !isRecord(parsed.payload) || parsed.payload.id !== threadId) throw new Error("Codex rollout does not belong to the bound thread");
|
|
40
|
+
return parsed.payload;
|
|
48
41
|
}
|
|
49
|
-
/**
|
|
50
|
-
function
|
|
51
|
-
const payload = parsed.payload;
|
|
52
|
-
if (parsed.type === "session_meta") {
|
|
53
|
-
if (typeof payload.id !== "string") throw new Error("Codex rollout metadata is missing its thread identity");
|
|
54
|
-
return payload.id === threadId ? { provider: scalar(payload.model_provider) } : {};
|
|
55
|
-
}
|
|
56
|
-
if (parsed.type === "turn_context") return { model: scalar(payload.model) };
|
|
57
|
-
if (parsed.type === "event_msg" && payload.type === "thread_settings_applied") {
|
|
58
|
-
if (!isRecord(payload.thread_settings)) throw new Error("Codex rollout settings are incomplete");
|
|
59
|
-
return {
|
|
60
|
-
model: scalar(payload.thread_settings.model),
|
|
61
|
-
provider: scalar(payload.thread_settings.model_provider_id)
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
return {};
|
|
65
|
-
}
|
|
66
|
-
async function readExtent(handle, start, length) {
|
|
67
|
-
const buffer = Buffer.alloc(length);
|
|
68
|
-
for (let offset = 0; offset < length;) {
|
|
69
|
-
const { bytesRead } = await handle.read(buffer, offset, length - offset, start + offset);
|
|
70
|
-
if (!bytesRead) throw new Error("Codex rollout changed during model observation");
|
|
71
|
-
offset += bytesRead;
|
|
72
|
-
}
|
|
73
|
-
return buffer;
|
|
74
|
-
}
|
|
75
|
-
/** Latest durable selection at one verified local rollout snapshot, not live-memory state. */
|
|
76
|
-
async function readCodexRolloutSelection(params) {
|
|
42
|
+
/** Read immutable metadata while pinning the entire rollout against concurrent writers. */
|
|
43
|
+
async function readCodexRolloutSnapshot(params) {
|
|
77
44
|
const deadline = Date.now() + DEADLINE_MS;
|
|
78
45
|
const check = () => {
|
|
79
46
|
params.assertCurrent();
|
|
80
|
-
if (Date.now() >= deadline) throw new Error("Codex rollout
|
|
47
|
+
if (Date.now() >= deadline) throw new Error("Codex rollout metadata observation timed out");
|
|
81
48
|
};
|
|
82
49
|
check();
|
|
83
50
|
const rootStat = await lstat(params.sessionsRoot);
|
|
@@ -100,94 +67,49 @@ async function readCodexRolloutSelection(params) {
|
|
|
100
67
|
try {
|
|
101
68
|
check();
|
|
102
69
|
const snapshot = opened.stat;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
});
|
|
118
|
-
const decoder = createZstdDecompress({
|
|
119
|
-
chunkSize: CHUNK_BYTES,
|
|
120
|
-
params: { [constants.ZSTD_d_windowLogMax]: 25 }
|
|
121
|
-
});
|
|
122
|
-
const timer = setTimeout(() => decoder.destroy(/* @__PURE__ */ new Error("Codex rollout observation timed out")), Math.max(1, deadline - Date.now()));
|
|
70
|
+
const unchanged = (stat) => stat.dev === snapshot.dev && stat.ino === snapshot.ino && stat.size === snapshot.size && stat.mtimeMs === snapshot.mtimeMs && stat.ctimeMs === snapshot.ctimeMs && stat.nlink === 1;
|
|
71
|
+
if (!snapshot.size) throw new Error("Codex rollout metadata is incomplete");
|
|
72
|
+
const compressed = selected.endsWith(".zst");
|
|
73
|
+
if (compressed && snapshot.size > COMPRESSED_BYTES) throw new Error("Compressed Codex rollout exceeds the observation limit");
|
|
74
|
+
const input = opened.handle.createReadStream({
|
|
75
|
+
autoClose: false,
|
|
76
|
+
highWaterMark: CHUNK_BYTES,
|
|
77
|
+
end: snapshot.size - 1
|
|
78
|
+
});
|
|
79
|
+
const decoder = compressed ? createZstdDecompress({
|
|
80
|
+
chunkSize: CHUNK_BYTES,
|
|
81
|
+
params: { [constants.ZSTD_d_windowLogMax]: 25 }
|
|
82
|
+
}) : void 0;
|
|
83
|
+
if (decoder) {
|
|
123
84
|
input.on("error", (error) => decoder.destroy(error));
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
tail = Buffer.concat([tail, bytes]);
|
|
134
|
-
let newline;
|
|
135
|
-
while ((newline = tail.indexOf(10)) >= 0) {
|
|
136
|
-
const parsed = record(tail.subarray(0, newline));
|
|
137
|
-
if (!metadata) header(parsed);
|
|
138
|
-
const value = observation(parsed, params.threadId);
|
|
139
|
-
model = value.model ?? model;
|
|
140
|
-
provider = value.provider ?? provider;
|
|
141
|
-
tail = tail.subarray(newline + 1);
|
|
142
|
-
}
|
|
143
|
-
if (tail.length > RECORD_BYTES) throw new Error("Codex rollout record exceeds the observation limit");
|
|
144
|
-
}
|
|
145
|
-
if (tail.length) throw new Error("Codex rollout has an incomplete trailing record");
|
|
146
|
-
} finally {
|
|
147
|
-
clearTimeout(timer);
|
|
148
|
-
if (!input.readableEnded) input.destroy();
|
|
149
|
-
decoder.destroy();
|
|
150
|
-
}
|
|
151
|
-
} else {
|
|
152
|
-
let first = Buffer.alloc(0);
|
|
153
|
-
for (let offset = 0; offset < snapshot.size && first.length <= RECORD_BYTES;) {
|
|
85
|
+
input.pipe(decoder);
|
|
86
|
+
}
|
|
87
|
+
const reader = decoder ?? input;
|
|
88
|
+
const timer = setTimeout(() => reader.destroy(/* @__PURE__ */ new Error("Codex rollout metadata observation timed out")), Math.max(1, deadline - Date.now()));
|
|
89
|
+
let metadata;
|
|
90
|
+
const chunks = [];
|
|
91
|
+
let total = 0;
|
|
92
|
+
try {
|
|
93
|
+
for await (const chunk of reader) {
|
|
154
94
|
check();
|
|
155
|
-
const bytes =
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
95
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
96
|
+
const newline = bytes.indexOf(10);
|
|
97
|
+
const prefix = newline < 0 ? bytes : bytes.subarray(0, newline);
|
|
98
|
+
total += prefix.length;
|
|
99
|
+
if (total > META_BYTES) throw new Error("Codex rollout metadata exceeds the observation limit");
|
|
100
|
+
chunks.push(prefix);
|
|
159
101
|
if (newline >= 0) {
|
|
160
|
-
|
|
102
|
+
metadata = parseMetadata(Buffer.concat(chunks), params.threadId);
|
|
103
|
+
if (!unchanged(await opened.handle.stat())) throw new Error("Codex rollout changed during metadata observation");
|
|
161
104
|
break;
|
|
162
105
|
}
|
|
163
106
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
while (end > 0 && (!model || !provider)) {
|
|
169
|
-
check();
|
|
170
|
-
const length = Math.min(CHUNK_BYTES, end, SCAN_BYTES - scanned);
|
|
171
|
-
if (!length) throw new Error("Codex rollout model observation exhausted its scan budget");
|
|
172
|
-
end -= length;
|
|
173
|
-
const bytes = await readExtent(opened.handle, end, length);
|
|
174
|
-
if (!scanned) {
|
|
175
|
-
if (bytes.at(-1) !== 10) throw new Error("Codex rollout has an incomplete trailing record");
|
|
176
|
-
tail = bytes.subarray(0, -1);
|
|
177
|
-
} else tail = Buffer.concat([bytes, tail]);
|
|
178
|
-
scanned += length;
|
|
179
|
-
for (;;) {
|
|
180
|
-
const newline = tail.lastIndexOf(10);
|
|
181
|
-
if (newline < 0 && (end !== 0 || tail.length === 0)) break;
|
|
182
|
-
const value = observation(record(tail.subarray(newline + 1)), params.threadId);
|
|
183
|
-
model ??= value.model;
|
|
184
|
-
provider ??= value.provider;
|
|
185
|
-
tail = newline < 0 ? Buffer.alloc(0) : tail.subarray(0, newline);
|
|
186
|
-
if (model && provider) break;
|
|
187
|
-
}
|
|
188
|
-
if (tail.length > RECORD_BYTES) throw new Error("Codex rollout record exceeds the observation limit");
|
|
189
|
-
}
|
|
107
|
+
} finally {
|
|
108
|
+
clearTimeout(timer);
|
|
109
|
+
reader.destroy();
|
|
110
|
+
input.destroy();
|
|
190
111
|
}
|
|
112
|
+
if (!metadata) throw new Error("Codex rollout metadata is incomplete");
|
|
191
113
|
const assertUnchanged = async () => {
|
|
192
114
|
params.assertCurrent();
|
|
193
115
|
if (selected !== plain) {
|
|
@@ -197,7 +119,7 @@ async function readCodexRolloutSelection(params) {
|
|
|
197
119
|
if (!isRecord(error) || error.code !== "ENOENT") throw error;
|
|
198
120
|
return await verifySelected();
|
|
199
121
|
}
|
|
200
|
-
throw new Error("Codex rollout selection changed during
|
|
122
|
+
throw new Error("Codex rollout selection changed during metadata observation");
|
|
201
123
|
}
|
|
202
124
|
await verifySelected();
|
|
203
125
|
};
|
|
@@ -207,20 +129,15 @@ async function readCodexRolloutSelection(params) {
|
|
|
207
129
|
const fresh = await safeRoot.open(path.relative(params.sessionsRoot, selected));
|
|
208
130
|
try {
|
|
209
131
|
const stat = fresh.stat;
|
|
210
|
-
if (stat
|
|
132
|
+
if (!unchanged(stat) || currentRoot.isSymbolicLink() || currentRoot.ino !== rootStat.ino || currentRoot.dev !== rootStat.dev) throw new Error("Codex rollout changed during metadata observation");
|
|
211
133
|
} finally {
|
|
212
134
|
await fresh.handle.close();
|
|
213
135
|
}
|
|
214
136
|
params.assertCurrent();
|
|
215
137
|
};
|
|
216
|
-
const descriptor = await opened.handle.stat();
|
|
217
|
-
if (descriptor.dev !== snapshot.dev || descriptor.ino !== snapshot.ino || descriptor.size !== snapshot.size || descriptor.mtimeMs !== snapshot.mtimeMs || descriptor.ctimeMs !== snapshot.ctimeMs || descriptor.nlink !== 1) throw new Error("Codex rollout changed during model observation");
|
|
218
138
|
await assertUnchanged();
|
|
219
139
|
check();
|
|
220
|
-
if (!model || !provider || !metadata) throw new Error("Codex rollout has no complete durable model selection");
|
|
221
140
|
return {
|
|
222
|
-
model,
|
|
223
|
-
modelProvider: provider,
|
|
224
141
|
metadata,
|
|
225
142
|
assertUnchanged
|
|
226
143
|
};
|
|
@@ -552,7 +469,7 @@ async function resolveCodexUpstreamForkBoundary(params) {
|
|
|
552
469
|
if (index < 0 || !isDeepStrictEqual(current.slice(0, index + 1), frozen)) throw new Error("The local Codex fork prefix changed during initialization");
|
|
553
470
|
const currentThread = await params.control.readThread(threadId, false);
|
|
554
471
|
assertCodexThreadAcceptsDirectInput(currentThread);
|
|
555
|
-
if (currentThread.id !== thread.id || currentThread.path !== thread.path || currentThread.cwd !== thread.cwd || currentThread.historyMode !== thread.historyMode || currentThread.status?.type === "active") throw new Error("The canonical Codex source changed during initialization");
|
|
472
|
+
if (currentThread.id !== thread.id || currentThread.path !== thread.path || currentThread.cwd !== thread.cwd || currentThread.historyMode !== thread.historyMode || currentThread.model !== thread.model || currentThread.modelProvider !== thread.modelProvider || currentThread.status?.type === "active") throw new Error("The canonical Codex source changed during initialization");
|
|
556
473
|
const currentTurns = await listCodexUpstreamTurns(params.control, threadId);
|
|
557
474
|
const cut = turns.findIndex((turn) => turn.id === resolved.boundary.beforeTurnId);
|
|
558
475
|
if (!isDeepStrictEqual(currentTurns.slice(0, cut + 1), turns.slice(0, cut + 1))) throw new Error("The canonical Codex fork boundary changed during initialization");
|
|
@@ -579,12 +496,15 @@ async function forkCanonicalCodexSession(params) {
|
|
|
579
496
|
const { fork, resolved, control, bindingStore, sourceBinding, config } = params;
|
|
580
497
|
const context = control.forkContext;
|
|
581
498
|
if (!context?.localSessionsRoot || !resolved.canonical.thread.path) throw new Error("Canonical Codex forks require the verified local rollout on its selected connection. Fork an original imported message instead.");
|
|
499
|
+
const model = normalizeOptionalString(resolved.canonical.thread.model);
|
|
500
|
+
const modelProvider = normalizeOptionalString(resolved.canonical.thread.modelProvider);
|
|
501
|
+
if (!model || !modelProvider) throw new Error("Codex did not report the canonical thread's model selection. Use Codex 0.153.0 or newer, or fork an original imported message instead.");
|
|
582
502
|
const sourceIdentity = sessionBindingIdentity({
|
|
583
503
|
...fork.source,
|
|
584
504
|
config
|
|
585
505
|
});
|
|
586
506
|
return bindingStore.withLease(sourceIdentity, async () => {
|
|
587
|
-
if (!isDeepStrictEqual(
|
|
507
|
+
if (!isDeepStrictEqual(bindingStore.read(sourceIdentity), sourceBinding)) throw new Error("Codex canonical source binding changed before initialization");
|
|
588
508
|
let freshThreadId;
|
|
589
509
|
let ownership;
|
|
590
510
|
let subscriptionReleased = false;
|
|
@@ -641,7 +561,7 @@ async function forkCanonicalCodexSession(params) {
|
|
|
641
561
|
initialization.assertCurrent();
|
|
642
562
|
if (ownership && !subscriptionReleased) ownership.assertCurrent();
|
|
643
563
|
};
|
|
644
|
-
const
|
|
564
|
+
const snapshot = await readCodexRolloutSnapshot({
|
|
645
565
|
sessionsRoot: context.localSessionsRoot,
|
|
646
566
|
rolloutPath: resolved.canonical.thread.path,
|
|
647
567
|
threadId: sourceBinding.threadId,
|
|
@@ -649,23 +569,23 @@ async function forkCanonicalCodexSession(params) {
|
|
|
649
569
|
});
|
|
650
570
|
assertCurrent();
|
|
651
571
|
if (!sourceBinding.dynamicToolsFingerprint) throw new Error("The canonical source has no verified native catalog binding");
|
|
652
|
-
const sourceCatalog = parseCodexNativeToolCatalog(
|
|
572
|
+
const sourceCatalog = parseCodexNativeToolCatalog(snapshot.metadata, sourceBinding.threadId, sourceBinding.dynamicToolsFingerprint);
|
|
653
573
|
const prepared = await prepareCanonicalCodexFork({
|
|
654
574
|
created,
|
|
655
575
|
initialization: host,
|
|
656
576
|
config,
|
|
657
577
|
context,
|
|
658
|
-
model
|
|
659
|
-
modelProvider
|
|
578
|
+
model,
|
|
579
|
+
modelProvider,
|
|
660
580
|
sandbox: fork.sandbox,
|
|
661
581
|
dynamicTools: sourceCatalog
|
|
662
582
|
});
|
|
663
583
|
assertCurrent();
|
|
664
|
-
await
|
|
584
|
+
await snapshot.assertUnchanged();
|
|
665
585
|
assertCurrent();
|
|
666
586
|
await resolved.canonical.assertUnchanged();
|
|
667
587
|
assertCurrent();
|
|
668
|
-
if (!isDeepStrictEqual(
|
|
588
|
+
if (!isDeepStrictEqual(bindingStore.read(sourceIdentity), sourceBinding)) throw new Error("Codex canonical source binding changed during preparation");
|
|
669
589
|
assertCurrent();
|
|
670
590
|
let raw;
|
|
671
591
|
try {
|
|
@@ -673,8 +593,8 @@ async function forkCanonicalCodexSession(params) {
|
|
|
673
593
|
...prepared.request,
|
|
674
594
|
threadId: sourceBinding.threadId,
|
|
675
595
|
beforeTurnId: resolved.boundary.beforeTurnId,
|
|
676
|
-
model
|
|
677
|
-
modelProvider
|
|
596
|
+
model,
|
|
597
|
+
modelProvider,
|
|
678
598
|
threadSource: "appServer",
|
|
679
599
|
excludeTurns: true
|
|
680
600
|
}, assertCurrent);
|
|
@@ -700,19 +620,19 @@ async function forkCanonicalCodexSession(params) {
|
|
|
700
620
|
throw new Error("Codex fork subscription ownership could not be acquired");
|
|
701
621
|
}
|
|
702
622
|
assertCurrent();
|
|
703
|
-
if (response.model !==
|
|
623
|
+
if (response.model !== model || response.thread.model !== model || response.modelProvider !== modelProvider || response.thread.modelProvider !== modelProvider) throw new Error("Codex fork did not preserve the exact canonical source and selected native model");
|
|
704
624
|
const turns = await listCodexUpstreamTurns(control, freshThreadId);
|
|
705
625
|
assertCurrent();
|
|
706
626
|
const cut = resolved.canonical.turns.findIndex((turn) => turn.id === resolved.boundary.beforeTurnId);
|
|
707
627
|
if (cut < 0 || !isDeepStrictEqual(turns, resolved.canonical.turns.slice(0, cut))) throw new Error("Codex did not apply the exact beforeTurnId cut. Reconnect to a compatible server and retry.");
|
|
708
628
|
const metadata = response.thread.path ? await readCodexSessionMeta(context.localSessionsRoot, response.thread.path, freshThreadId) : void 0;
|
|
709
629
|
assertCurrent();
|
|
710
|
-
if (!metadata || metadata.model_provider !==
|
|
630
|
+
if (!metadata || metadata.model_provider !== modelProvider) throw new Error("The fresh Codex fork metadata could not be verified");
|
|
711
631
|
const childCatalog = parseCodexNativeToolCatalog(metadata, freshThreadId);
|
|
712
632
|
if (!isDeepStrictEqual(sourceCatalog, childCatalog)) throw new Error("Codex fork did not preserve the actual native tool catalog");
|
|
713
|
-
await
|
|
633
|
+
await snapshot.assertUnchanged();
|
|
714
634
|
assertCurrent();
|
|
715
|
-
await
|
|
635
|
+
await checkCodexThreadAppAvailability({
|
|
716
636
|
client: context.client,
|
|
717
637
|
threadId: freshThreadId,
|
|
718
638
|
appIds: prepared.provisionalAppIds
|
|
@@ -769,8 +689,8 @@ async function forkCanonicalCodexSession(params) {
|
|
|
769
689
|
conversationSourceTransferComplete: true,
|
|
770
690
|
cwd: prepared.request.cwd ?? "",
|
|
771
691
|
rolloutPath: response.thread.path ?? void 0,
|
|
772
|
-
model
|
|
773
|
-
modelProvider
|
|
692
|
+
model,
|
|
693
|
+
modelProvider,
|
|
774
694
|
appServerRuntimeFingerprint: control.connectionFingerprint,
|
|
775
695
|
dynamicToolsFingerprint: codexDynamicToolsFingerprint(childCatalog),
|
|
776
696
|
dynamicToolsContainDeferred: flattenCodexDynamicToolFunctions(childCatalog).some((tool) => tool.deferLoading === true),
|
|
@@ -783,7 +703,7 @@ async function forkCanonicalCodexSession(params) {
|
|
|
783
703
|
initialization.assertCurrent();
|
|
784
704
|
await resolved.canonical.assertUnchanged();
|
|
785
705
|
initialization.assertCurrent();
|
|
786
|
-
if (!isDeepStrictEqual(
|
|
706
|
+
if (!isDeepStrictEqual(bindingStore.read(sourceIdentity), sourceBinding)) throw new Error("Codex source binding changed before fork readiness");
|
|
787
707
|
initialization.assertCurrent();
|
|
788
708
|
return { pluginExtensions: created.entry.pluginExtensions };
|
|
789
709
|
}
|
|
@@ -810,7 +730,7 @@ async function forkCodexUpstreamSession(params, options) {
|
|
|
810
730
|
message: "This Codex thread is not available on the current connection. Reconnect to its host and try again."
|
|
811
731
|
};
|
|
812
732
|
return await requestControl.withPinnedConnection(async (control) => {
|
|
813
|
-
const sourceBinding =
|
|
733
|
+
const sourceBinding = options.bindingStore.read(sessionBindingIdentity({
|
|
814
734
|
...params.source,
|
|
815
735
|
config: options.resolveConfig?.()
|
|
816
736
|
}));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as resolveCodexAppServerRuntimeOptions } from "./config-
|
|
2
|
-
import { n as readCodexAppServerUsage } from "./request-
|
|
3
|
-
import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-
|
|
1
|
+
import { i as resolveCodexAppServerRuntimeOptions } from "./config-CyapYSji.js";
|
|
2
|
+
import { n as readCodexAppServerUsage } from "./request-C8H22rPi.js";
|
|
3
|
+
import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-Fx_l4eNa.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. */
|
package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-DKQn67A7.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { x as buildCodexNativeWebSearchThreadConfig } from "./thread-lifecycle-
|
|
3
|
-
import { t as runBoundedCodexAppServerTurn } from "./bounded-turn-
|
|
1
|
+
import { B as isJsonObject } from "./config-CyapYSji.js";
|
|
2
|
+
import { x as buildCodexNativeWebSearchThreadConfig } from "./thread-lifecycle-DPK30jad.js";
|
|
3
|
+
import { t as runBoundedCodexAppServerTurn } from "./bounded-turn-DxGJRYbY.js";
|
|
4
4
|
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
5
|
import { readStringParam, resolveSearchTimeoutSeconds, wrapWebContent } from "openclaw/plugin-sdk/provider-web-search";
|
|
6
6
|
//#region extensions/codex/src/web-search-provider.runtime.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/codex",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.2",
|
|
4
4
|
"description": "OpenClaw Codex app-server harness and native session supervision plugin.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@openai/codex": "0.
|
|
11
|
+
"@openai/codex": "0.153.4",
|
|
12
12
|
"semver": "7.8.5",
|
|
13
13
|
"smol-toml": "1.8.0",
|
|
14
|
-
"typebox": "1.3.
|
|
14
|
+
"typebox": "1.3.18",
|
|
15
15
|
"ws": "8.21.3",
|
|
16
16
|
"zod": "4.4.3"
|
|
17
17
|
},
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
]
|
|
37
37
|
},
|
|
38
38
|
"compat": {
|
|
39
|
-
"pluginApi": ">=2026.9.
|
|
39
|
+
"pluginApi": ">=2026.9.2"
|
|
40
40
|
},
|
|
41
41
|
"build": {
|
|
42
|
-
"openclawVersion": "2026.9.
|
|
42
|
+
"openclawVersion": "2026.9.2"
|
|
43
43
|
},
|
|
44
44
|
"release": {
|
|
45
45
|
"publishToClawHub": true,
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"README.md"
|
|
60
60
|
],
|
|
61
61
|
"peerDependencies": {
|
|
62
|
-
"openclaw": ">=2026.9.
|
|
62
|
+
"openclaw": ">=2026.9.2"
|
|
63
63
|
},
|
|
64
64
|
"peerDependenciesMeta": {
|
|
65
65
|
"openclaw": {
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { E as readCodexPluginConfig, i as resolveCodexAppServerRuntimeOptions, s as resolveCodexSupervisionAppServerRuntimeOptions } from "./config-BhmfC1s6.js";
|
|
2
|
-
import { n as buildCodexAppServerConnectionFingerprint, o as resolveCodexCatalogConnectionHome } from "./thread-resume-C7pyVKeW.js";
|
|
3
|
-
//#region extensions/codex/src/app-server/binding-connection.ts
|
|
4
|
-
/** Requires the native model pair after a supervised pending branch has materialized. */
|
|
5
|
-
function requireCodexSupervisionModelSelection(binding) {
|
|
6
|
-
const model = binding.model?.trim();
|
|
7
|
-
const modelProvider = binding.modelProvider?.trim();
|
|
8
|
-
if (binding.connectionScope !== "supervision" || !model || !modelProvider) throw new Error("Codex supervised binding is missing its native model and provider; refusing request selection");
|
|
9
|
-
return {
|
|
10
|
-
model,
|
|
11
|
-
modelProvider
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
/** Resolves connection and auth ownership exclusively from the private thread binding. */
|
|
15
|
-
function resolveCodexBindingAppServerConnection(params) {
|
|
16
|
-
const { binding, authProfileId, ...runtimeParams } = params;
|
|
17
|
-
const usesSupervisionConnection = binding?.connectionScope === "supervision";
|
|
18
|
-
if (usesSupervisionConnection && readCodexPluginConfig(runtimeParams.pluginConfig).supervision?.enabled !== true) throw new Error("Codex supervision is disabled; refusing to open a native user-home supervised session");
|
|
19
|
-
let appServer = (usesSupervisionConnection ? resolveCodexSupervisionAppServerRuntimeOptions : resolveCodexAppServerRuntimeOptions)(runtimeParams);
|
|
20
|
-
if (usesSupervisionConnection) {
|
|
21
|
-
const persistedFingerprint = binding.pendingSupervisionBranch?.connectionFingerprint ?? binding.appServerRuntimeFingerprint;
|
|
22
|
-
const catalogHome = persistedFingerprint ? resolveCodexCatalogConnectionHome(persistedFingerprint, runtimeParams.agentDir) : void 0;
|
|
23
|
-
if (catalogHome) appServer = {
|
|
24
|
-
...appServer,
|
|
25
|
-
start: {
|
|
26
|
-
...appServer.start,
|
|
27
|
-
homeScope: "user",
|
|
28
|
-
env: {
|
|
29
|
-
...appServer.start.env,
|
|
30
|
-
CODEX_HOME: catalogHome
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
const currentFingerprint = buildCodexAppServerConnectionFingerprint(appServer, runtimeParams.agentDir);
|
|
35
|
-
if (!persistedFingerprint || persistedFingerprint !== currentFingerprint) throw new Error("Codex supervision connection changed; refusing to operate on its bound native thread");
|
|
36
|
-
}
|
|
37
|
-
return {
|
|
38
|
-
appServer,
|
|
39
|
-
usesSupervisionConnection,
|
|
40
|
-
requestAuthProfileId: usesSupervisionConnection ? void 0 : authProfileId,
|
|
41
|
-
clientAuthProfileId: usesSupervisionConnection ? null : authProfileId
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
//#endregion
|
|
45
|
-
export { resolveCodexBindingAppServerConnection as n, requireCodexSupervisionModelSelection as t };
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
//#region extensions/codex/src/app-server/launch-args.ts
|
|
2
|
-
const CODEX_VALUE_OPTIONS = /* @__PURE__ */ new Set([
|
|
3
|
-
"-m",
|
|
4
|
-
"--model",
|
|
5
|
-
"--local-provider",
|
|
6
|
-
"-p",
|
|
7
|
-
"--profile",
|
|
8
|
-
"-s",
|
|
9
|
-
"--sandbox",
|
|
10
|
-
"-a",
|
|
11
|
-
"--ask-for-approval",
|
|
12
|
-
"-C",
|
|
13
|
-
"--cd",
|
|
14
|
-
"--add-dir",
|
|
15
|
-
"--remote",
|
|
16
|
-
"--remote-auth-token-env",
|
|
17
|
-
"-c",
|
|
18
|
-
"--config",
|
|
19
|
-
"--enable",
|
|
20
|
-
"--disable",
|
|
21
|
-
"--listen",
|
|
22
|
-
"--code-mode-host",
|
|
23
|
-
"--ws-auth",
|
|
24
|
-
"--ws-token-file",
|
|
25
|
-
"--ws-token-sha256",
|
|
26
|
-
"--ws-shared-secret-file",
|
|
27
|
-
"--ws-issuer",
|
|
28
|
-
"--ws-audience",
|
|
29
|
-
"--ws-max-clock-skew-seconds"
|
|
30
|
-
]);
|
|
31
|
-
/** One tokenization owner for launch, turn policy, reviewer trust, and private turns. */
|
|
32
|
-
function readCodexArgs(args) {
|
|
33
|
-
const tokens = [];
|
|
34
|
-
let nativeSubcommand = false;
|
|
35
|
-
let end = 0;
|
|
36
|
-
for (const [index, arg] of args.entries()) {
|
|
37
|
-
if (index < end) continue;
|
|
38
|
-
end = index + 1;
|
|
39
|
-
const attached = /^(--[^=]+)=([\s\S]*)$/u.exec(arg) ?? /^(-[cmpisaC])=?([\s\S]+)$/u.exec(arg);
|
|
40
|
-
const name = attached?.[1] ?? arg;
|
|
41
|
-
let value = attached?.[2];
|
|
42
|
-
if (name === "-i" || name === "--image") while (args[end]?.startsWith("-") === false) end += 1;
|
|
43
|
-
else if (!attached && CODEX_VALUE_OPTIONS.has(name)) {
|
|
44
|
-
value = args[end];
|
|
45
|
-
if (value !== void 0) end += 1;
|
|
46
|
-
}
|
|
47
|
-
tokens.push({
|
|
48
|
-
index,
|
|
49
|
-
end,
|
|
50
|
-
name,
|
|
51
|
-
value
|
|
52
|
-
});
|
|
53
|
-
if (name === "app-server") nativeSubcommand = true;
|
|
54
|
-
if (name === "--" && nativeSubcommand) break;
|
|
55
|
-
}
|
|
56
|
-
return tokens;
|
|
57
|
-
}
|
|
58
|
-
function readCodexAppServerConfigOptions(args) {
|
|
59
|
-
return readCodexArgs(args).filter(({ name }) => name === "-c" || name === "--config" || name === "-p" || name === "--profile");
|
|
60
|
-
}
|
|
61
|
-
/** The stdio proxy forwards to an external server; it does not own that runtime. */
|
|
62
|
-
function isCodexAppServerProxyLaunch(args) {
|
|
63
|
-
const tokens = readCodexArgs(args);
|
|
64
|
-
const server = tokens.findLastIndex(({ name }) => name === "app-server");
|
|
65
|
-
return server >= 0 && tokens.slice(server + 1).find(({ name }) => !name.startsWith("-"))?.name === "proxy";
|
|
66
|
-
}
|
|
67
|
-
/** Keeps Codex overrides in one CLI scope without rewriting raw TOML or wrapper prefixes. */
|
|
68
|
-
function normalizeCodexAppServerArgs(rawArgs, enforcedOverride) {
|
|
69
|
-
const tokens = readCodexArgs(rawArgs);
|
|
70
|
-
const subcommandIndex = tokens.findLast(({ name }) => name === "app-server")?.index ?? -1;
|
|
71
|
-
const prefix = subcommandIndex < 0 ? [...rawArgs] : rawArgs.slice(0, subcommandIndex);
|
|
72
|
-
const suffix = [];
|
|
73
|
-
if (subcommandIndex >= 0) for (const token of tokens) {
|
|
74
|
-
if (token.index <= subcommandIndex) continue;
|
|
75
|
-
if (token.name === "--") {
|
|
76
|
-
suffix.push(...rawArgs.slice(token.index));
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
(token.name === "-c" || token.name === "--config" ? prefix : suffix).push(...rawArgs.slice(token.index, token.end));
|
|
80
|
-
}
|
|
81
|
-
if (enforcedOverride && !(prefix.at(-2) === "-c" && prefix.at(-1) === enforcedOverride)) prefix.push("-c", enforcedOverride);
|
|
82
|
-
const normalized = subcommandIndex < 0 ? prefix : [
|
|
83
|
-
...prefix,
|
|
84
|
-
"app-server",
|
|
85
|
-
...suffix
|
|
86
|
-
];
|
|
87
|
-
return normalized.length === rawArgs.length && normalized.every((arg, index) => arg === rawArgs[index]) ? rawArgs : normalized;
|
|
88
|
-
}
|
|
89
|
-
//#endregion
|
|
90
|
-
export { normalizeCodexAppServerArgs as n, readCodexAppServerConfigOptions as r, isCodexAppServerProxyLaunch as t };
|