@openclaw/codex 2026.8.1-beta.3 → 2026.8.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 +5 -6
- package/dist/{attempt-client-cleanup-URjUlCHg.js → attempt-client-cleanup-CpVfwctT.js} +47 -5
- package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
- package/dist/{binding-connection-DAvZwp96.js → binding-connection-CF7BmrDk.js} +2 -2
- package/dist/{bounded-turn-4BjrZEwW.js → bounded-turn-DRC3hcjm.js} +16 -20
- package/dist/{capabilities-CH3K57v4.js → capabilities-D6m_TdVy.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-D0nZ3qtd.js → command-formatters--UToCokS.js} +4 -3
- package/dist/{command-handlers-DC86lgT4.js → command-handlers-CLFx2Ypa.js} +114 -79
- package/dist/{compact-COqgBRny.js → compact-5xqW1oCh.js} +13 -12
- package/dist/{config-CpNeo5AE.js → config-CcYL77O6.js} +350 -288
- package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
- package/dist/doctor-contract-api.js +121 -16
- package/dist/{dynamic-tools-fJZhl4CE.js → dynamic-tools-BmeXjwNZ.js} +243 -1002
- package/dist/{effective-mcp-catalog-4YKn51aG.js → effective-mcp-catalog-XXQKgK1U.js} +2 -2
- package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
- package/dist/{event-projector-usage-CLwNEJqW.js → event-projector-usage-B2r5vhWH.js} +9 -14
- package/dist/{harness-DoKQcF8n.js → harness-BgeB7LnD.js} +42 -52
- package/dist/harness.js +1 -1
- package/dist/index.js +308 -306
- package/dist/{isolated-completion-DPMtlH9r.js → isolated-completion-CxTus3vZ.js} +4 -4
- package/dist/launch-args-sXOAg0SX.js +84 -0
- package/dist/{managed-binary-By4FZC6i.js → managed-binary-ZkGodW19.js} +43 -7
- package/dist/media-understanding-provider.js +1 -1
- package/dist/model-catalog-DULBcniB.js +101 -0
- package/dist/{models-CZw1wClT.js → models-DaWfETQk.js} +27 -29
- package/dist/{native-subagent-monitor-GGq3RnOo.js → native-subagent-monitor-vXYUZH37.js} +226 -129
- package/dist/{node-exec-server.runtime-Bsu1LdFZ.js → node-exec-server.runtime-DirKVZ5h.js} +9 -6
- package/dist/{plugin-approval-roundtrip-C75Yiiwc.js → plugin-approval-roundtrip-CCWQGlAI.js} +2 -1
- package/dist/{plugin-marketplace-discovery-CSWDkMrP.js → plugin-marketplace-discovery-BXjIFEiw.js} +38 -46
- package/dist/{plugin-metadata-cache-BXH5NF-4.js → plugin-metadata-cache-DQQm4gWT.js} +163 -136
- package/dist/{protocol-validators-VAVyEnDp.js → protocol-validators-Bg5rpNxk.js} +148 -5
- package/dist/{rate-limits-BI1dMHDG.js → rate-limits-BqHEHXQJ.js} +3 -2
- package/dist/{sandbox-guard-C1qEeZ5C.js → request-BWxweEdK.js} +183 -2
- package/dist/{run-attempt-BV3HzuCf.js → run-attempt-BVLE4Gbi.js} +706 -517
- package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-D9pYp4zL.js} +3 -3
- package/dist/{session-binding-BTrLf9Qm.js → session-binding-D0zinCP1.js} +195 -122
- package/dist/{session-catalog-ezP_UcRM.js → session-catalog-eMhVm0Ql.js} +448 -313
- package/dist/session-catalog-home-id-Dt2GiG5o.js +112 -0
- package/dist/{session-cli-B1hKvfkI.js → session-cli-B2lyjJA0.js} +1 -1
- package/dist/session-history-C5J1AKzG.js +87 -0
- package/dist/session-permission-policy-ScnAyG90.js +160 -0
- package/dist/session-retirement-CtUtUTr9.js +90 -0
- package/dist/{session-upstream-marker-D_2npHlA.js → session-upstream-marker-gqrYIRHk.js} +2 -3
- package/dist/settled-turn-context-Bk3IUwod.js +290 -0
- package/dist/settled-turn-finalizer-BXLN9PfJ.js +104 -0
- package/dist/{shared-client-Dw-rzii0.js → shared-client-B1tT5U6r.js} +1738 -806
- package/dist/{side-question-DbXkJZzg.js → side-question-CZ-mCw-t.js} +76 -43
- package/dist/{thread-lifecycle-DKdrnTMX.js → thread-lifecycle-CGGKP720.js} +991 -455
- package/dist/{thread-ownership-i2NBwDUL.js → thread-ownership-RkaoZCmQ.js} +18 -8
- package/dist/{plugin-app-cache-key-DMNQ8Zi8.js → thread-resume-BFt1-ZDa.js} +55 -8
- package/dist/{transcript-mirror-BU0_LKAL.js → transcript-mirror-1ep4XjzF.js} +124 -18
- package/dist/transport-stdio-NT_Dpd9V.js +724 -0
- package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
- package/dist/{upstream-session-fork-BDVJCLAD.js → upstream-session-fork-Dc8BFExw.js} +76 -90
- package/dist/{usage-9dKJCgcy.js → usage-DUhd58gI.js} +3 -3
- package/dist/{web-search-provider.runtime-DCdx4DGu.js → web-search-provider.runtime-BEmlE7ov.js} +3 -3
- package/openclaw.plugin.json +19 -1
- package/package.json +8 -8
- package/dist/app-server-policy-bg5QPSVP.js +0 -25
- package/dist/command-rpc-xUIIonsO.js +0 -90
- package/dist/incognito-session-ET_ufDH-.js +0 -2
- package/dist/model-catalog-CmGoqVKB.js +0 -48
- package/dist/request-DSK0W6YI.js +0 -157
- package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
- package/dist/session-retirement-CE4iMiLh.js +0 -36
- package/dist/settled-turn-finalizer-Dx1onIqg.js +0 -328
- package/dist/thread-resume-CdJk2Ehf.js +0 -30
- package/dist/transport-stdio-DhoGy33Z.js +0 -99
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Ht as isJsonObject } from "./shared-client-B1tT5U6r.js";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import fsSync from "node:fs";
|
|
5
|
+
import { root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
6
|
+
import { createZstdDecompress } from "node:zlib";
|
|
7
|
+
//#region extensions/codex/src/session-catalog-provenance.ts
|
|
8
|
+
const MAX_SESSION_META_BYTES = 1048576;
|
|
9
|
+
const SESSION_META_READ_CHUNK_BYTES = 65536;
|
|
10
|
+
const MAX_PROVENANCE_CACHE_ENTRIES = 2e4;
|
|
11
|
+
const provenanceByPath = /* @__PURE__ */ new Map();
|
|
12
|
+
function cacheProvenance(key, value) {
|
|
13
|
+
provenanceByPath.delete(key);
|
|
14
|
+
provenanceByPath.set(key, value);
|
|
15
|
+
while (provenanceByPath.size > MAX_PROVENANCE_CACHE_ENTRIES) {
|
|
16
|
+
const oldest = provenanceByPath.keys().next().value;
|
|
17
|
+
if (oldest === void 0) break;
|
|
18
|
+
provenanceByPath.delete(oldest);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Undefined means the metadata line is not durable enough to cache yet. */
|
|
22
|
+
async function readCodexSessionMeta(sessionsRoot, rolloutPath, threadId) {
|
|
23
|
+
let safeRoot;
|
|
24
|
+
try {
|
|
25
|
+
safeRoot = await root(sessionsRoot, {
|
|
26
|
+
hardlinks: "reject",
|
|
27
|
+
maxBytes: Number.MAX_SAFE_INTEGER,
|
|
28
|
+
symlinks: "reject"
|
|
29
|
+
});
|
|
30
|
+
} catch {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const candidates = rolloutPath.endsWith(".zst") ? [rolloutPath, rolloutPath.slice(0, -4)] : [rolloutPath, `${rolloutPath}.zst`];
|
|
34
|
+
for (const candidate of candidates) {
|
|
35
|
+
let opened;
|
|
36
|
+
try {
|
|
37
|
+
opened = await safeRoot.open(path.relative(sessionsRoot, candidate));
|
|
38
|
+
} catch {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const input = opened.handle.createReadStream({
|
|
42
|
+
autoClose: false,
|
|
43
|
+
highWaterMark: SESSION_META_READ_CHUNK_BYTES
|
|
44
|
+
});
|
|
45
|
+
const reader = candidate.endsWith(".zst") ? input.pipe(createZstdDecompress()) : input;
|
|
46
|
+
try {
|
|
47
|
+
const chunks = [];
|
|
48
|
+
let bytesReadTotal = 0;
|
|
49
|
+
let line;
|
|
50
|
+
for await (const value of reader) {
|
|
51
|
+
const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
|
|
52
|
+
const remaining = MAX_SESSION_META_BYTES - bytesReadTotal;
|
|
53
|
+
if (remaining <= 0) break;
|
|
54
|
+
const bounded = chunk.subarray(0, remaining);
|
|
55
|
+
bytesReadTotal += bounded.length;
|
|
56
|
+
const newline = bounded.indexOf(10);
|
|
57
|
+
chunks.push(newline >= 0 ? bounded.subarray(0, newline) : bounded);
|
|
58
|
+
if (newline >= 0) {
|
|
59
|
+
line = Buffer.concat(chunks).toString("utf8");
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!line) continue;
|
|
64
|
+
let parsed;
|
|
65
|
+
try {
|
|
66
|
+
parsed = JSON.parse(line);
|
|
67
|
+
} catch {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (!isJsonObject(parsed) || parsed.type !== "session_meta" || !isJsonObject(parsed.payload)) return null;
|
|
71
|
+
const payload = parsed.payload;
|
|
72
|
+
return payload.id === threadId ? payload : null;
|
|
73
|
+
} catch {
|
|
74
|
+
continue;
|
|
75
|
+
} finally {
|
|
76
|
+
reader.destroy();
|
|
77
|
+
input.destroy();
|
|
78
|
+
await opened.handle.close().catch(() => void 0);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Codex 0.147 reports OpenClaw app-server rollouts as `vscode`, so the rollout's
|
|
84
|
+
* immutable session metadata is the authoritative historical provenance.
|
|
85
|
+
*/
|
|
86
|
+
async function isOpenClawManagedCodexThread(thread, localSessionsRoot) {
|
|
87
|
+
const rolloutPath = typeof thread.path === "string" ? thread.path.trim() : "";
|
|
88
|
+
if (!localSessionsRoot || !rolloutPath) return false;
|
|
89
|
+
const cacheKey = `${localSessionsRoot}\0${rolloutPath}`;
|
|
90
|
+
const cached = provenanceByPath.get(cacheKey);
|
|
91
|
+
if (cached !== void 0) return cached;
|
|
92
|
+
const metadata = await readCodexSessionMeta(localSessionsRoot, rolloutPath, thread.id);
|
|
93
|
+
const managed = metadata === void 0 ? void 0 : metadata?.originator === "openclaw";
|
|
94
|
+
if (managed !== void 0) cacheProvenance(cacheKey, managed);
|
|
95
|
+
return managed ?? false;
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region extensions/codex/src/session-catalog-home-id.ts
|
|
99
|
+
function canonicalCodexCatalogHome(value) {
|
|
100
|
+
const resolved = path.resolve(value);
|
|
101
|
+
try {
|
|
102
|
+
return fsSync.realpathSync.native(resolved);
|
|
103
|
+
} catch {
|
|
104
|
+
return resolved;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/** One canonical identity for catalog discovery and durable ownership rows. */
|
|
108
|
+
function codexCatalogHomeId(codexHome) {
|
|
109
|
+
return createHash("sha256").update("openclaw:codex-session-catalog-home:v1\0").update(canonicalCodexCatalogHome(codexHome)).digest("hex");
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
export { readCodexSessionMeta as i, codexCatalogHomeId as n, isOpenClawManagedCodexThread as r, canonicalCodexCatalogHome as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./session-catalog-
|
|
1
|
+
import "./session-catalog-eMhVm0Ql.js";
|
|
2
2
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
4
4
|
import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { n as sanitizeCodexHistoryImagePayloads } from "./image-payload-sanitizer-CnfoUPCE.js";
|
|
2
|
+
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import { getSessionEntry, parseSqliteSessionFileMarker, resolveTranscriptSessionKeyBySessionId } from "openclaw/plugin-sdk/session-store-runtime";
|
|
5
|
+
import { SessionManager, buildSessionContext, migrateSessionEntries, parseSessionEntries } from "openclaw/plugin-sdk/agent-sessions";
|
|
6
|
+
//#region extensions/codex/src/app-server/session-history.ts
|
|
7
|
+
/** Reads model context separately from full-fidelity Codex mirror evidence. */
|
|
8
|
+
/** Returns sanitized session-context messages for consumers that need an owned array. */
|
|
9
|
+
async function readCodexMirroredSessionHistoryMessages(target, admission, view = "native-evidence") {
|
|
10
|
+
return readCodexMirroredSessionHistory(target, (messages) => Array.from(messages), admission, view);
|
|
11
|
+
}
|
|
12
|
+
/** The synchronous consumer can reject before further SQLite message payloads are acquired. */
|
|
13
|
+
async function readCodexMirroredSessionHistory(target, read, admission, view = "native-evidence") {
|
|
14
|
+
const consume = (messages, header, imageLabel = "codex mirrored history") => {
|
|
15
|
+
if (!isRecord(header) || header.type !== "session") return read([]);
|
|
16
|
+
if (typeof header.id !== "string") return;
|
|
17
|
+
if (header.id !== target.sessionId) return read([]);
|
|
18
|
+
return read((function* () {
|
|
19
|
+
for (const message of messages) yield sanitizeCodexHistoryImagePayloads(message, imageLabel);
|
|
20
|
+
})());
|
|
21
|
+
};
|
|
22
|
+
const readTarget = (transcriptTarget) => {
|
|
23
|
+
if (view === "native-evidence") return SessionManager.readSessionContext(transcriptTarget, consume, { admission });
|
|
24
|
+
const loaded = SessionManager.openModelContext(transcriptTarget, { admission });
|
|
25
|
+
return consume(loaded.buildSessionContext().messages, loaded.getHeader(), "codex mirrored model context");
|
|
26
|
+
};
|
|
27
|
+
try {
|
|
28
|
+
if (target.sessionTarget) {
|
|
29
|
+
const { agentId, sessionId, sessionKey, storePath } = target.sessionTarget;
|
|
30
|
+
if (!agentId || !sessionId || !sessionKey || !storePath || sessionId !== target.sessionId || target.agentId !== void 0 && agentId !== target.agentId || target.sessionKey !== void 0 && sessionKey !== target.sessionKey) return read([]);
|
|
31
|
+
return readTarget({
|
|
32
|
+
agentId,
|
|
33
|
+
sessionId,
|
|
34
|
+
sessionKey,
|
|
35
|
+
storePath
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const sqliteMarker = parseSqliteSessionFileMarker(target.sessionFile);
|
|
39
|
+
if (sqliteMarker) {
|
|
40
|
+
if (sqliteMarker.sessionId !== target.sessionId || target.agentId !== void 0 && sqliteMarker.agentId !== target.agentId) return read([]);
|
|
41
|
+
const sessionKey = resolveSqliteMarkerSessionKey(target, sqliteMarker);
|
|
42
|
+
if (!sessionKey) return read([]);
|
|
43
|
+
return readTarget({
|
|
44
|
+
agentId: sqliteMarker.agentId,
|
|
45
|
+
sessionId: sqliteMarker.sessionId,
|
|
46
|
+
sessionKey,
|
|
47
|
+
storePath: sqliteMarker.storePath
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (admission) {
|
|
51
|
+
if (admission.sessionId !== target.sessionId || target.agentId !== void 0 && admission.agentId !== target.agentId || target.sessionKey !== void 0 && admission.sessionKey !== target.sessionKey) return read([]);
|
|
52
|
+
return readTarget({
|
|
53
|
+
agentId: admission.agentId,
|
|
54
|
+
sessionId: admission.sessionId,
|
|
55
|
+
sessionKey: admission.sessionKey,
|
|
56
|
+
storePath: admission.storePath
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const entries = parseSessionEntries(await fs.readFile(target.sessionFile, "utf-8"));
|
|
60
|
+
return consume((function* () {
|
|
61
|
+
migrateSessionEntries(entries);
|
|
62
|
+
const sessionEntries = entries.filter((entry) => isRecord(entry) && entry.type !== "session");
|
|
63
|
+
yield* buildSessionContext(sessionEntries).messages;
|
|
64
|
+
})(), entries[0]);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (isRecord(error) && error.code === "ENOENT") return read([]);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function resolveSqliteMarkerSessionKey(target, marker) {
|
|
71
|
+
const explicitSessionKey = target.sessionKey?.trim();
|
|
72
|
+
if (explicitSessionKey) {
|
|
73
|
+
const explicitEntry = getSessionEntry({
|
|
74
|
+
agentId: marker.agentId,
|
|
75
|
+
sessionKey: explicitSessionKey,
|
|
76
|
+
storePath: marker.storePath
|
|
77
|
+
});
|
|
78
|
+
if (explicitEntry) return explicitEntry.sessionId === marker.sessionId ? explicitSessionKey : void 0;
|
|
79
|
+
}
|
|
80
|
+
return resolveTranscriptSessionKeyBySessionId({
|
|
81
|
+
agentId: marker.agentId,
|
|
82
|
+
sessionId: marker.sessionId,
|
|
83
|
+
storePath: marker.storePath
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
export { readCodexMirroredSessionHistoryMessages as n, readCodexMirroredSessionHistory as t };
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { O as selectGuardianSandbox, _ as parseAllowedSandboxModesFromCodexRequirements, b as selectGuardianApprovalsReviewer, g as parseAllowedApprovalsReviewersFromCodexRequirements, h as parseAllowedApprovalPoliciesFromCodexRequirements, l as resolveCodexAppServerNetworkProxy, p as canUseCodexModelBackedApprovalsReviewerForModel, x as selectUserApprovalsReviewer, y as selectGuardianApprovalPolicy } from "./config-CcYL77O6.js";
|
|
2
|
+
import { hostname } from "node:os";
|
|
3
|
+
import { isPathInside } from "openclaw/plugin-sdk/file-access-runtime";
|
|
4
|
+
//#region extensions/codex/src/app-server/app-server-policy.ts
|
|
5
|
+
function resolveCodexAppServerForModelProvider(params) {
|
|
6
|
+
const explicitProvider = normalizeModelBackedReviewerProvider(params.provider);
|
|
7
|
+
if (!isCodexModelBackedApprovalsReviewer(params.appServer.approvalsReviewer) || canUseCodexModelBackedApprovalsReviewerForModel({
|
|
8
|
+
modelProvider: explicitProvider,
|
|
9
|
+
model: params.model,
|
|
10
|
+
config: params.config,
|
|
11
|
+
env: {
|
|
12
|
+
...params.env ?? process.env,
|
|
13
|
+
...params.appServer.start.env
|
|
14
|
+
},
|
|
15
|
+
agentDir: params.agentDir,
|
|
16
|
+
codexConfigToml: params.codexConfigToml,
|
|
17
|
+
homeScope: params.appServer.start.homeScope,
|
|
18
|
+
codexArgs: params.appServer.start.args
|
|
19
|
+
})) return params.appServer;
|
|
20
|
+
return {
|
|
21
|
+
...params.appServer,
|
|
22
|
+
approvalsReviewer: "user"
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function isCodexModelBackedApprovalsReviewer(value) {
|
|
26
|
+
return value === "auto_review" || value === "guardian_subagent";
|
|
27
|
+
}
|
|
28
|
+
function normalizeModelBackedReviewerProvider(provider) {
|
|
29
|
+
return provider?.trim().toLowerCase() || void 0;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region extensions/codex/src/app-server/session-permission-policy.ts
|
|
33
|
+
const CODEX_SESSION_PERMISSION_EXEC_MODES = {
|
|
34
|
+
"read-only": "deny",
|
|
35
|
+
guarded: "ask",
|
|
36
|
+
workspace: "auto",
|
|
37
|
+
full: "full"
|
|
38
|
+
};
|
|
39
|
+
function tupleForMode(mode, canUseAutoReview) {
|
|
40
|
+
switch (mode) {
|
|
41
|
+
case "read-only": return {
|
|
42
|
+
sandbox: "read-only",
|
|
43
|
+
approvalPolicy: "on-request",
|
|
44
|
+
approvalsReviewer: "user"
|
|
45
|
+
};
|
|
46
|
+
case "guarded": return {
|
|
47
|
+
sandbox: "workspace-write",
|
|
48
|
+
approvalPolicy: "on-request",
|
|
49
|
+
approvalsReviewer: "user"
|
|
50
|
+
};
|
|
51
|
+
case "workspace": return {
|
|
52
|
+
sandbox: "workspace-write",
|
|
53
|
+
approvalPolicy: "on-request",
|
|
54
|
+
approvalsReviewer: canUseAutoReview ? "auto_review" : "user"
|
|
55
|
+
};
|
|
56
|
+
case "full": return {
|
|
57
|
+
sandbox: "danger-full-access",
|
|
58
|
+
approvalPolicy: "never",
|
|
59
|
+
approvalsReviewer: "user"
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return mode;
|
|
63
|
+
}
|
|
64
|
+
function requirementsAllowTuple(tuple, allowed) {
|
|
65
|
+
return (allowed.sandboxes === void 0 || allowed.sandboxes.has(tuple.sandbox)) && (allowed.approvalPolicies === void 0 || allowed.approvalPolicies.has(tuple.approvalPolicy)) && (allowed.reviewers === void 0 || allowed.reviewers.has(tuple.approvalsReviewer));
|
|
66
|
+
}
|
|
67
|
+
function tightenTupleForExecMode(tuple, execMode, requiresPerCommandApproval) {
|
|
68
|
+
switch (execMode) {
|
|
69
|
+
case "deny":
|
|
70
|
+
case "allowlist": return {
|
|
71
|
+
sandbox: "read-only",
|
|
72
|
+
approvalPolicy: "on-request",
|
|
73
|
+
approvalsReviewer: "user"
|
|
74
|
+
};
|
|
75
|
+
case "ask": return {
|
|
76
|
+
...tuple,
|
|
77
|
+
approvalPolicy: requiresPerCommandApproval ? "untrusted" : "on-request",
|
|
78
|
+
approvalsReviewer: "user"
|
|
79
|
+
};
|
|
80
|
+
case "auto":
|
|
81
|
+
case "full":
|
|
82
|
+
case void 0: return tuple;
|
|
83
|
+
}
|
|
84
|
+
return execMode;
|
|
85
|
+
}
|
|
86
|
+
function clampSessionPermissionTuple(params) {
|
|
87
|
+
if (!params.requirementsToml) return params.requested;
|
|
88
|
+
const allowed = {
|
|
89
|
+
sandboxes: parseAllowedSandboxModesFromCodexRequirements(params.requirementsToml, params.hostName ?? hostname()),
|
|
90
|
+
approvalPolicies: parseAllowedApprovalPoliciesFromCodexRequirements(params.requirementsToml),
|
|
91
|
+
reviewers: parseAllowedApprovalsReviewersFromCodexRequirements(params.requirementsToml)
|
|
92
|
+
};
|
|
93
|
+
if (requirementsAllowTuple(params.requested, allowed)) return params.requested;
|
|
94
|
+
if (params.requested.approvalPolicy === "untrusted" && allowed.approvalPolicies?.has("untrusted") === false) throw new Error("tools.exec.ask=always requires Codex app-server per-command approvals");
|
|
95
|
+
const userReviewRequired = params.mode === "read-only" || params.mode === "guarded" || params.mode === "workspace" && !params.canUseAutoReview;
|
|
96
|
+
const sandboxAuthority = {
|
|
97
|
+
"read-only": 0,
|
|
98
|
+
"workspace-write": 1,
|
|
99
|
+
"danger-full-access": 2
|
|
100
|
+
};
|
|
101
|
+
const allowedSandboxes = new Set([
|
|
102
|
+
"read-only",
|
|
103
|
+
"workspace-write",
|
|
104
|
+
"danger-full-access"
|
|
105
|
+
].filter((sandbox) => sandboxAuthority[sandbox] <= sandboxAuthority[params.requested.sandbox] && (allowed.sandboxes === void 0 || allowed.sandboxes.has(sandbox))));
|
|
106
|
+
if (allowedSandboxes.size === 0) throw new Error(`Codex session permission mode=${params.mode} cannot satisfy managed sandbox requirements without widening access`);
|
|
107
|
+
return {
|
|
108
|
+
sandbox: selectGuardianSandbox(allowedSandboxes),
|
|
109
|
+
approvalPolicy: params.requested.approvalPolicy === "untrusted" ? "untrusted" : selectGuardianApprovalPolicy(allowed.approvalPolicies, userReviewRequired ? "ask" : "auto"),
|
|
110
|
+
approvalsReviewer: userReviewRequired ? selectUserApprovalsReviewer(allowed.reviewers) : selectGuardianApprovalsReviewer(allowed.reviewers, "auto")
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/** Applies one complete session-mode tuple without mixing requirements-clamped fields. */
|
|
114
|
+
function applyCodexSessionPermissionPolicy(params) {
|
|
115
|
+
if (!params.permissionMode) return params.appServer;
|
|
116
|
+
const sessionRoot = params.sessionRoot?.trim() || params.defaultRoot;
|
|
117
|
+
if (params.policyLocked) return {
|
|
118
|
+
...params.appServer,
|
|
119
|
+
sessionRoot
|
|
120
|
+
};
|
|
121
|
+
const requested = tightenTupleForExecMode(tupleForMode(params.permissionMode, params.canUseAutoReview), params.execMode, params.appServer.approvalPolicy === "untrusted");
|
|
122
|
+
const tuple = params.appServer.start.transport === "stdio" ? clampSessionPermissionTuple({
|
|
123
|
+
mode: params.permissionMode,
|
|
124
|
+
requested,
|
|
125
|
+
requirementsToml: params.requirementsToml,
|
|
126
|
+
hostName: params.hostName,
|
|
127
|
+
canUseAutoReview: params.canUseAutoReview
|
|
128
|
+
}) : requested;
|
|
129
|
+
const networkProxy = params.appServer.networkProxy ? resolveCodexAppServerNetworkProxy(params.pluginConfig.appServer?.networkProxy, tuple.sandbox).networkProxy : void 0;
|
|
130
|
+
const resolved = {
|
|
131
|
+
...params.appServer,
|
|
132
|
+
...tuple,
|
|
133
|
+
sessionRoot
|
|
134
|
+
};
|
|
135
|
+
if (networkProxy) resolved.networkProxy = networkProxy;
|
|
136
|
+
else delete resolved.networkProxy;
|
|
137
|
+
return resolved;
|
|
138
|
+
}
|
|
139
|
+
function resolveCodexEffectiveSessionPermissionPolicy(params) {
|
|
140
|
+
if (!params.permissionMode) return;
|
|
141
|
+
const root = params.sessionRoot?.trim() || params.defaultRoot;
|
|
142
|
+
const { sandbox, approvalPolicy, approvalsReviewer } = params.appServer;
|
|
143
|
+
const fullAccess = params.permissionMode === "full" && sandbox === "danger-full-access" && approvalPolicy === "never";
|
|
144
|
+
const guardianReview = params.permissionMode !== "guarded" && sandbox === "workspace-write" && approvalPolicy === "on-request" && approvalsReviewer !== "user";
|
|
145
|
+
const mode = params.permissionMode === "read-only" || sandbox === "read-only" ? "read-only" : fullAccess ? "full" : guardianReview ? "workspace" : "guarded";
|
|
146
|
+
return {
|
|
147
|
+
mode,
|
|
148
|
+
root,
|
|
149
|
+
execMode: CODEX_SESSION_PERMISSION_EXEC_MODES[mode]
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/** Keeps relative execution inside the prepared root without filesystem rediscovery. */
|
|
153
|
+
function resolveCodexSessionPermissionCwd(params) {
|
|
154
|
+
if (!params.permissionMode) return params.requestedCwd ?? params.fallbackCwd;
|
|
155
|
+
const sessionRoot = params.sessionRoot?.trim() || params.defaultRoot;
|
|
156
|
+
const requestedCwd = params.requestedCwd?.trim();
|
|
157
|
+
return requestedCwd && isPathInside(sessionRoot, requestedCwd) ? requestedCwd : sessionRoot;
|
|
158
|
+
}
|
|
159
|
+
//#endregion
|
|
160
|
+
export { resolveCodexAppServerForModelProvider as a, resolveCodexSessionPermissionCwd as i, applyCodexSessionPermissionPolicy as n, resolveCodexEffectiveSessionPermissionPolicy as r, CODEX_SESSION_PERMISSION_EXEC_MODES as t };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { St as releaseCodexAppServerLiveThread, _ as retainSharedCodexAppServerClientByInstanceId, bt as isCodexAppServerLiveThreadClaimed, vt as hasCodexAppServerLiveThread } from "./shared-client-B1tT5U6r.js";
|
|
2
|
+
import { a as closeCodexStartupClientBestEffort, f as unsubscribeCodexThreadBestEffort, n as CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS, r as CodexAppServerUnsafeSubscriptionError } from "./attempt-client-cleanup-CpVfwctT.js";
|
|
3
|
+
import { l as isIncognitoSessionKey, o as withCodexAppServerThreadMutation } from "./thread-ownership-RkaoZCmQ.js";
|
|
4
|
+
import { t as codexNativeSubagentMonitorRuntime } from "./native-subagent-monitor-vXYUZH37.js";
|
|
5
|
+
//#region extensions/codex/src/app-server/session-retirement.ts
|
|
6
|
+
async function releaseSessionSubscription(client, binding, sessionKey, assertCurrent) {
|
|
7
|
+
assertCurrent?.();
|
|
8
|
+
codexNativeSubagentMonitorRuntime.retireParent(client, binding.threadId);
|
|
9
|
+
const released = await releaseCodexAppServerLiveThread(client, binding.threadId, assertCurrent);
|
|
10
|
+
assertCurrent?.();
|
|
11
|
+
if (!released && isIncognitoSessionKey(sessionKey)) {
|
|
12
|
+
const unsubscribed = await unsubscribeCodexThreadBestEffort(client, {
|
|
13
|
+
threadId: binding.threadId,
|
|
14
|
+
timeoutMs: CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS,
|
|
15
|
+
assertCurrent
|
|
16
|
+
});
|
|
17
|
+
assertCurrent?.();
|
|
18
|
+
if (!unsubscribed) {
|
|
19
|
+
await closeCodexStartupClientBestEffort(client);
|
|
20
|
+
throw new CodexAppServerUnsafeSubscriptionError(`Codex retired session subscription could not be released: ${binding.threadId}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Prepare exact binding deletion before the session owner commits either database. */
|
|
25
|
+
async function withCodexAppServerSessionDeletion(bindingStore, params, run) {
|
|
26
|
+
const { assertCurrent } = params;
|
|
27
|
+
const identity = {
|
|
28
|
+
kind: "session",
|
|
29
|
+
agentId: params.agentId,
|
|
30
|
+
sessionKey: params.sessionKey,
|
|
31
|
+
sessionId: params.sessionId
|
|
32
|
+
};
|
|
33
|
+
return await bindingStore.withSessionDeletion(identity, assertCurrent, async (binding, mutation) => {
|
|
34
|
+
assertCurrent();
|
|
35
|
+
if (binding?.connectionScope === "supervision") throw new Error("Cannot delete a session while its Codex binding is owned by supervision");
|
|
36
|
+
const clientLease = binding?.clientId ? retainSharedCodexAppServerClientByInstanceId(binding.clientId) : void 0;
|
|
37
|
+
const assertUnclaimed = () => {
|
|
38
|
+
assertCurrent();
|
|
39
|
+
if (clientLease && binding && isCodexAppServerLiveThreadClaimed(clientLease.client, binding.threadId)) throw new Error("Cannot delete a session while its Codex thread is claimed by active work");
|
|
40
|
+
};
|
|
41
|
+
let committed = false;
|
|
42
|
+
try {
|
|
43
|
+
assertUnclaimed();
|
|
44
|
+
return await run({
|
|
45
|
+
commit() {
|
|
46
|
+
assertUnclaimed();
|
|
47
|
+
mutation.commit();
|
|
48
|
+
committed = true;
|
|
49
|
+
},
|
|
50
|
+
rollback() {
|
|
51
|
+
mutation.rollback();
|
|
52
|
+
committed = false;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
} finally {
|
|
56
|
+
try {
|
|
57
|
+
if (committed && binding && clientLease) await withCodexAppServerThreadMutation(binding.threadId, async () => {
|
|
58
|
+
assertCurrent();
|
|
59
|
+
if (!hasCodexAppServerLiveThread(clientLease.client, binding.threadId) && !isIncognitoSessionKey(params.sessionKey)) return;
|
|
60
|
+
if (await bindingStore.hasOtherThreadOwner(binding.threadId)) return;
|
|
61
|
+
await releaseSessionSubscription(clientLease.client, binding, params.sessionKey, assertUnclaimed);
|
|
62
|
+
});
|
|
63
|
+
} finally {
|
|
64
|
+
clientLease?.release();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/** Retire binding and native subscription under the same generation/physical-client ownership fence. */
|
|
70
|
+
async function retireCodexAppServerSessionGeneration(params) {
|
|
71
|
+
const retireGeneration = () => params.mode === "reset" ? params.bindingStore.resetSessionGeneration(params.identity) : params.bindingStore.retireSessionGeneration(params.identity);
|
|
72
|
+
const expectedBinding = await params.bindingStore.read(params.identity);
|
|
73
|
+
if (!expectedBinding) return await retireGeneration();
|
|
74
|
+
return await params.bindingStore.withLease(params.identity, async () => {
|
|
75
|
+
const binding = await params.bindingStore.read(params.identity);
|
|
76
|
+
if (binding?.threadId !== expectedBinding.threadId) return "conflict";
|
|
77
|
+
const result = await retireGeneration();
|
|
78
|
+
if (result !== "applied" || !binding?.clientId) return result;
|
|
79
|
+
const clientLease = retainSharedCodexAppServerClientByInstanceId(binding.clientId);
|
|
80
|
+
if (!clientLease) return result;
|
|
81
|
+
try {
|
|
82
|
+
await releaseSessionSubscription(clientLease.client, binding, params.identity.sessionKey);
|
|
83
|
+
} finally {
|
|
84
|
+
clientLease.release();
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
export { retireCodexAppServerSessionGeneration, withCodexAppServerSessionDeletion };
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-
|
|
1
|
+
import { r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-1ep4XjzF.js";
|
|
2
2
|
import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
3
3
|
//#region extensions/codex/src/app-server/session-history-import.ts
|
|
4
4
|
/** Creates a session whose transcript is derived from one verified Codex thread snapshot. */
|
|
5
5
|
async function createImportedCodexSession(params) {
|
|
6
|
-
const label = params.thread.name?.trim() || void 0;
|
|
7
6
|
const spawnedCwd = params.thread.cwd?.trim() || void 0;
|
|
8
7
|
const createParams = {
|
|
9
8
|
cfg: params.config,
|
|
10
9
|
key: params.key,
|
|
11
10
|
agentId: params.agentId,
|
|
12
|
-
...
|
|
11
|
+
...params.displayName !== void 0 ? { displayName: params.displayName } : {},
|
|
13
12
|
...spawnedCwd ? { spawnedCwd } : {},
|
|
14
13
|
initialEntry: params.initialEntry,
|
|
15
14
|
afterCreate: async (entry) => {
|