orkestrator 2.30.0-beta → 2.32.0-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -3
- package/dist/client.js +1728 -158
- package/dist/main.js +227795 -217168
- package/package.json +3 -3
- package/resources/claude-bridge/dist/index.js +1029 -682
- package/resources/codex-bridge/dist/index.js +474 -150
|
@@ -331,7 +331,7 @@ function createBridgeDiagnostics(bridge, state, metrics) {
|
|
|
331
331
|
import { execFile as execFileCallback2 } from "node:child_process";
|
|
332
332
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
333
333
|
import { appendFile as appendFile5, mkdir as mkdir8, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
|
|
334
|
-
import { join as
|
|
334
|
+
import { join as join17 } from "node:path";
|
|
335
335
|
import { promisify as promisify2 } from "node:util";
|
|
336
336
|
|
|
337
337
|
// ../../node_modules/.bun/@hono+node-server@2.1.5+c539cad7f494f5c9/node_modules/@hono/node-server/dist/constants-BLSFu_RU.mjs
|
|
@@ -3933,7 +3933,14 @@ var QUESTION_KEYS = new Set([
|
|
|
3933
3933
|
"allowFreeText",
|
|
3934
3934
|
"options"
|
|
3935
3935
|
]);
|
|
3936
|
-
var OPTION_KEYS = new Set([
|
|
3936
|
+
var OPTION_KEYS = new Set([
|
|
3937
|
+
"id",
|
|
3938
|
+
"label",
|
|
3939
|
+
"providerValue",
|
|
3940
|
+
"description",
|
|
3941
|
+
"preview",
|
|
3942
|
+
"amendment"
|
|
3943
|
+
]);
|
|
3937
3944
|
var AMENDMENT_KEYS = new Set(["kind", "detail"]);
|
|
3938
3945
|
var ANSWER_KEYS = new Set(["version", "interactionId", "sessionId", "answers"]);
|
|
3939
3946
|
var QUESTION_ANSWER_KEYS = new Set(["questionId", "optionIds", "freeText"]);
|
|
@@ -4060,6 +4067,15 @@ var NATIVE_AGENT_APPROVAL_MODES = Object.freeze({
|
|
|
4060
4067
|
}
|
|
4061
4068
|
]
|
|
4062
4069
|
});
|
|
4070
|
+
var CODEX_CONTAINER_APPROVAL_DESCRIPTIONS = Object.freeze({
|
|
4071
|
+
ask: {
|
|
4072
|
+
"on-request": "Codex has no sandbox of its own in a container, so this asks before any command Codex does not trust, like Untrusted"
|
|
4073
|
+
},
|
|
4074
|
+
"auto-approve": {
|
|
4075
|
+
"on-request": "Codex has no sandbox of its own in a container, so this never asks; choose Untrusted to approve commands",
|
|
4076
|
+
"auto-review": "Codex has no sandbox of its own in a container, so the reviewer is never consulted and everything runs"
|
|
4077
|
+
}
|
|
4078
|
+
});
|
|
4063
4079
|
var NATIVE_AGENT_RETIRED_DISPATCH_TTL_MS = 24 * 60 * 60 * 1000;
|
|
4064
4080
|
var SUPPRESSED_COMPOSER_PARAMETERS = Object.freeze({
|
|
4065
4081
|
claude: Object.freeze(["parameter:thinking", "parameter:context1m"]),
|
|
@@ -5925,8 +5941,18 @@ function registerCodexChangeEvidenceRoutes(app, spool) {
|
|
|
5925
5941
|
|
|
5926
5942
|
// ../../bridges/codex-bridge/src/change-evidence.ts
|
|
5927
5943
|
import { createHash as createHash5 } from "node:crypto";
|
|
5928
|
-
import { existsSync } from "node:fs";
|
|
5929
|
-
import { join as
|
|
5944
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
5945
|
+
import { basename, join as join8 } from "node:path";
|
|
5946
|
+
|
|
5947
|
+
// ../../bridges/codex-bridge/src/bridge-state-dir.ts
|
|
5948
|
+
import { isAbsolute as isAbsolute2, join as join2 } from "node:path";
|
|
5949
|
+
function codexBridgeStateDir(codexHome, env = process.env) {
|
|
5950
|
+
const override = env.CODEX_BRIDGE_STATE_DIR?.trim();
|
|
5951
|
+
return override && isAbsolute2(override) ? override : codexLoginBridgeDir(codexHome);
|
|
5952
|
+
}
|
|
5953
|
+
function codexLoginBridgeDir(codexHome) {
|
|
5954
|
+
return join2(codexHome, "orkestrator-bridge");
|
|
5955
|
+
}
|
|
5930
5956
|
|
|
5931
5957
|
// ../protocol/src/change-evidence.ts
|
|
5932
5958
|
var PROVIDER_EVIDENCE_SCHEMA_VERSION = 1;
|
|
@@ -6324,7 +6350,7 @@ function workspaceObservationReportIssues(value) {
|
|
|
6324
6350
|
import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
|
|
6325
6351
|
import { readdirSync, readFileSync } from "node:fs";
|
|
6326
6352
|
import { appendFile, mkdir, rename, rm as rm2, writeFile } from "node:fs/promises";
|
|
6327
|
-
import { join as
|
|
6353
|
+
import { join as join3 } from "node:path";
|
|
6328
6354
|
var DEFAULT_EVIDENCE_SPOOL_LIMITS = {
|
|
6329
6355
|
maxEntries: 2048,
|
|
6330
6356
|
maxEntryBytes: 256 * 1024,
|
|
@@ -6587,7 +6613,7 @@ class ChangeEvidenceSpool {
|
|
|
6587
6613
|
const lines = this.pendingLines.splice(0).join("");
|
|
6588
6614
|
this.enqueueIo(async () => {
|
|
6589
6615
|
await mkdir(directory, { recursive: true, mode: 448 });
|
|
6590
|
-
await appendFile(
|
|
6616
|
+
await appendFile(join3(directory, ENTRIES_FILE), lines, { mode: 384 });
|
|
6591
6617
|
});
|
|
6592
6618
|
}
|
|
6593
6619
|
persistBody(id, bytes) {
|
|
@@ -6595,9 +6621,9 @@ class ChangeEvidenceSpool {
|
|
|
6595
6621
|
if (!directory || this.restoring)
|
|
6596
6622
|
return;
|
|
6597
6623
|
this.enqueueIo(async () => {
|
|
6598
|
-
const bodies =
|
|
6624
|
+
const bodies = join3(directory, BODY_DIRECTORY);
|
|
6599
6625
|
await mkdir(bodies, { recursive: true, mode: 448 });
|
|
6600
|
-
await writeFile(
|
|
6626
|
+
await writeFile(join3(bodies, bodyFileName(id)), bytes, { mode: 384, flag: "wx" }).catch((error) => {
|
|
6601
6627
|
if (error.code !== "EEXIST")
|
|
6602
6628
|
throw error;
|
|
6603
6629
|
});
|
|
@@ -6607,7 +6633,7 @@ class ChangeEvidenceSpool {
|
|
|
6607
6633
|
const directory = this.directory;
|
|
6608
6634
|
if (!directory)
|
|
6609
6635
|
return;
|
|
6610
|
-
this.enqueueIo(() => rm2(
|
|
6636
|
+
this.enqueueIo(() => rm2(join3(directory, BODY_DIRECTORY, bodyFileName(id)), { force: true }));
|
|
6611
6637
|
}
|
|
6612
6638
|
compactPersisted() {
|
|
6613
6639
|
const directory = this.directory;
|
|
@@ -6618,7 +6644,7 @@ class ChangeEvidenceSpool {
|
|
|
6618
6644
|
`);
|
|
6619
6645
|
this.enqueueIo(async () => {
|
|
6620
6646
|
await mkdir(directory, { recursive: true, mode: 448 });
|
|
6621
|
-
const file =
|
|
6647
|
+
const file = join3(directory, ENTRIES_FILE);
|
|
6622
6648
|
const temp = `${file}.${process.pid}.tmp`;
|
|
6623
6649
|
await writeFile(temp, body ? `${body}
|
|
6624
6650
|
` : "", { mode: 384 });
|
|
@@ -6630,10 +6656,10 @@ class ChangeEvidenceSpool {
|
|
|
6630
6656
|
await this.io;
|
|
6631
6657
|
}
|
|
6632
6658
|
restore(directory) {
|
|
6633
|
-
const bodyDirectory =
|
|
6659
|
+
const bodyDirectory = join3(directory, BODY_DIRECTORY);
|
|
6634
6660
|
try {
|
|
6635
6661
|
for (const name of readdirSync(bodyDirectory)) {
|
|
6636
|
-
const bytes = new Uint8Array(readFileSync(
|
|
6662
|
+
const bytes = new Uint8Array(readFileSync(join3(bodyDirectory, name)));
|
|
6637
6663
|
const id = evidenceBodyId(bytes);
|
|
6638
6664
|
if (bodyFileName(id) !== name)
|
|
6639
6665
|
continue;
|
|
@@ -6645,7 +6671,7 @@ class ChangeEvidenceSpool {
|
|
|
6645
6671
|
} catch {}
|
|
6646
6672
|
let text = "";
|
|
6647
6673
|
try {
|
|
6648
|
-
text = readFileSync(
|
|
6674
|
+
text = readFileSync(join3(directory, ENTRIES_FILE), "utf8");
|
|
6649
6675
|
} catch {
|
|
6650
6676
|
return;
|
|
6651
6677
|
}
|
|
@@ -6983,7 +7009,7 @@ function canonicalEvidence(evidence) {
|
|
|
6983
7009
|
}
|
|
6984
7010
|
|
|
6985
7011
|
// ../../bridges/codex-bridge/src/messages/apply-patch.ts
|
|
6986
|
-
import { isAbsolute as
|
|
7012
|
+
import { isAbsolute as isAbsolute3, join as join4 } from "node:path";
|
|
6987
7013
|
|
|
6988
7014
|
// ../../bridges/codex-bridge/src/messages/diff-budget.ts
|
|
6989
7015
|
var MAX_INLINE_FILE_BYTES = 256 * 1024;
|
|
@@ -7137,7 +7163,7 @@ function rawPatchTitle(change) {
|
|
|
7137
7163
|
}
|
|
7138
7164
|
function rawApplyPatchParts(value, cwd, state) {
|
|
7139
7165
|
return parseRawApplyPatchChanges(value).map((change) => {
|
|
7140
|
-
const filePath =
|
|
7166
|
+
const filePath = isAbsolute3(change.targetPath) ? change.targetPath : join4(cwd, change.targetPath);
|
|
7141
7167
|
return {
|
|
7142
7168
|
type: "tool-invocation",
|
|
7143
7169
|
content: change.targetPath,
|
|
@@ -7160,7 +7186,7 @@ function rawApplyPatchParts(value, cwd, state) {
|
|
|
7160
7186
|
}
|
|
7161
7187
|
|
|
7162
7188
|
// ../../bridges/codex-bridge/src/messages/file-change-diff.ts
|
|
7163
|
-
import { isAbsolute as
|
|
7189
|
+
import { isAbsolute as isAbsolute4, join as join5, relative } from "node:path";
|
|
7164
7190
|
var MOVED_TO_SUFFIX = /\n\nMoved to: ([^\n]+)\n?$/;
|
|
7165
7191
|
var UNIFIED_START = /^(?:@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@|--- |diff --git )/;
|
|
7166
7192
|
function suppliedFileChange(change) {
|
|
@@ -7184,7 +7210,7 @@ function suppliedFileChange(change) {
|
|
|
7184
7210
|
};
|
|
7185
7211
|
}
|
|
7186
7212
|
function headerPath(cwd, path) {
|
|
7187
|
-
return
|
|
7213
|
+
return isAbsolute4(path) ? relative(cwd, path) || path : path;
|
|
7188
7214
|
}
|
|
7189
7215
|
function contentLines(content) {
|
|
7190
7216
|
if (content.length === 0)
|
|
@@ -7223,11 +7249,11 @@ ${supplied.hunks}`;
|
|
|
7223
7249
|
`);
|
|
7224
7250
|
}
|
|
7225
7251
|
function resolvedChangePath(cwd, path) {
|
|
7226
|
-
return
|
|
7252
|
+
return isAbsolute4(path) ? path : join5(cwd, path);
|
|
7227
7253
|
}
|
|
7228
7254
|
|
|
7229
7255
|
// ../../bridges/codex-bridge/src/sessions/command-changes.ts
|
|
7230
|
-
import { isAbsolute as
|
|
7256
|
+
import { isAbsolute as isAbsolute5, join as join6 } from "node:path";
|
|
7231
7257
|
import { fileURLToPath } from "node:url";
|
|
7232
7258
|
|
|
7233
7259
|
// ../protocol/src/node/command-change-journal.ts
|
|
@@ -7408,7 +7434,7 @@ function journalFileName(threadId) {
|
|
|
7408
7434
|
}
|
|
7409
7435
|
function commandChangeJournalPath(codexHome, threadId) {
|
|
7410
7436
|
const fileName = journalFileName(threadId);
|
|
7411
|
-
return fileName ?
|
|
7437
|
+
return fileName ? join6(codexBridgeStateDir(codexHome), "command-changes", fileName) : undefined;
|
|
7412
7438
|
}
|
|
7413
7439
|
function commandChangeJournalFor(codexHome, threadId) {
|
|
7414
7440
|
const path = commandChangeJournalPath(codexHome, threadId);
|
|
@@ -7433,7 +7459,13 @@ async function readCommandChanges(codexHome, threadId) {
|
|
|
7433
7459
|
const journal = commandChangeJournalFor(codexHome, threadId);
|
|
7434
7460
|
if (!journal)
|
|
7435
7461
|
return new Map;
|
|
7436
|
-
|
|
7462
|
+
const current = await journal.read().catch(() => new Map);
|
|
7463
|
+
const fileName = journalFileName(threadId);
|
|
7464
|
+
const legacyPath = fileName ? join6(codexLoginBridgeDir(codexHome), "command-changes", fileName) : undefined;
|
|
7465
|
+
if (!legacyPath || legacyPath === commandChangeJournalPath(codexHome, threadId))
|
|
7466
|
+
return current;
|
|
7467
|
+
const legacy = await new CommandChangeJournal(legacyPath).read().catch(() => new Map);
|
|
7468
|
+
return legacy.size === 0 ? current : new Map([...legacy, ...current]);
|
|
7437
7469
|
}
|
|
7438
7470
|
function recordCommandChanges(codexHome, threadId, toolUseId, change) {
|
|
7439
7471
|
if (!hasMeasuredChanges(change))
|
|
@@ -7463,7 +7495,7 @@ function commandChangeCwd(item, fallback) {
|
|
|
7463
7495
|
return fallback;
|
|
7464
7496
|
}
|
|
7465
7497
|
}
|
|
7466
|
-
return
|
|
7498
|
+
return isAbsolute5(item.cwd) ? item.cwd : fallback;
|
|
7467
7499
|
}
|
|
7468
7500
|
function commandDidNotRun(item) {
|
|
7469
7501
|
return item.type === "command_execution" && item.status === "failed" && item.exit_code === undefined;
|
|
@@ -7540,8 +7572,111 @@ async function inheritCommandChanges(codexHome, parentThreadId, forkThreadId, me
|
|
|
7540
7572
|
journal?.append(id, change);
|
|
7541
7573
|
}
|
|
7542
7574
|
|
|
7575
|
+
// ../../bridges/codex-bridge/src/change-evidence-migration.ts
|
|
7576
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
7577
|
+
import {
|
|
7578
|
+
existsSync,
|
|
7579
|
+
mkdirSync,
|
|
7580
|
+
readFileSync as readFileSync2,
|
|
7581
|
+
readdirSync as readdirSync2,
|
|
7582
|
+
renameSync,
|
|
7583
|
+
rmSync as rmSync2,
|
|
7584
|
+
statSync,
|
|
7585
|
+
writeFileSync
|
|
7586
|
+
} from "node:fs";
|
|
7587
|
+
import { join as join7, resolve as resolve2 } from "node:path";
|
|
7588
|
+
import { isDeepStrictEqual } from "node:util";
|
|
7589
|
+
function readBounded(path, limit) {
|
|
7590
|
+
if (statSync(path).size > limit)
|
|
7591
|
+
throw new Error("Evidence migration exceeds storage capacity");
|
|
7592
|
+
const bytes = readFileSync2(path);
|
|
7593
|
+
if (bytes.length > limit)
|
|
7594
|
+
throw new Error("Evidence migration exceeds storage capacity");
|
|
7595
|
+
return bytes;
|
|
7596
|
+
}
|
|
7597
|
+
function publishFile(path, contents) {
|
|
7598
|
+
const temporary = `${path}.${randomUUID4()}.tmp`;
|
|
7599
|
+
try {
|
|
7600
|
+
writeFileSync(temporary, contents, { mode: 384 });
|
|
7601
|
+
renameSync(temporary, path);
|
|
7602
|
+
} finally {
|
|
7603
|
+
rmSync2(temporary, { force: true });
|
|
7604
|
+
}
|
|
7605
|
+
}
|
|
7606
|
+
function migrateCodexChangeEvidence(legacy, shared) {
|
|
7607
|
+
if (resolve2(legacy) === resolve2(shared))
|
|
7608
|
+
return;
|
|
7609
|
+
const legacyFile = join7(legacy, "entries.jsonl");
|
|
7610
|
+
if (!existsSync(legacyFile))
|
|
7611
|
+
return;
|
|
7612
|
+
const entries = new Map;
|
|
7613
|
+
const bodyIds = new Set;
|
|
7614
|
+
for (const directory of [shared, legacy]) {
|
|
7615
|
+
const file = join7(directory, "entries.jsonl");
|
|
7616
|
+
if (!existsSync(file))
|
|
7617
|
+
continue;
|
|
7618
|
+
for (const line of readBounded(file, DEFAULT_EVIDENCE_SPOOL_LIMITS.maxQueuedBytes).toString("utf8").split(`
|
|
7619
|
+
`)) {
|
|
7620
|
+
if (!line)
|
|
7621
|
+
continue;
|
|
7622
|
+
const entry = JSON.parse(line).entry;
|
|
7623
|
+
let identity;
|
|
7624
|
+
if (entry?.type === "frame" && isProviderEvidenceFrame(entry.frame)) {
|
|
7625
|
+
identity = `frame:${entry.frame.frameId}`;
|
|
7626
|
+
for (const id of collectBodyIds(entry.frame))
|
|
7627
|
+
bodyIds.add(id);
|
|
7628
|
+
} else if (entry?.type === "observation" && workspaceObservationReportIssues(entry.report).length === 0) {
|
|
7629
|
+
identity = `observation:${entry.report.reportId}`;
|
|
7630
|
+
} else {
|
|
7631
|
+
throw new Error("Evidence migration encountered an invalid entry");
|
|
7632
|
+
}
|
|
7633
|
+
const normalized = { ...entry, seq: 0 };
|
|
7634
|
+
const existing = entries.get(identity);
|
|
7635
|
+
if (existing && !isDeepStrictEqual(existing, normalized)) {
|
|
7636
|
+
throw new Error("Evidence migration encountered conflicting identities");
|
|
7637
|
+
}
|
|
7638
|
+
entries.set(identity, normalized);
|
|
7639
|
+
}
|
|
7640
|
+
}
|
|
7641
|
+
const lines = [...entries.values()].map((entry, index) => {
|
|
7642
|
+
const serialized = JSON.stringify({ ...entry, seq: index + 1 });
|
|
7643
|
+
if (serialized.length > DEFAULT_EVIDENCE_SPOOL_LIMITS.maxEntryBytes) {
|
|
7644
|
+
throw new Error("Evidence migration exceeds entry capacity");
|
|
7645
|
+
}
|
|
7646
|
+
return JSON.stringify({ entry: { ...entry, seq: index + 1 } });
|
|
7647
|
+
});
|
|
7648
|
+
const contents = lines.length ? `${lines.join(`
|
|
7649
|
+
`)}
|
|
7650
|
+
` : "";
|
|
7651
|
+
if (entries.size >= DEFAULT_EVIDENCE_SPOOL_LIMITS.maxEntries || Buffer.byteLength(contents) > DEFAULT_EVIDENCE_SPOOL_LIMITS.maxQueuedBytes) {
|
|
7652
|
+
throw new Error("Evidence migration exceeds queue capacity");
|
|
7653
|
+
}
|
|
7654
|
+
mkdirSync(join7(shared, "bodies"), { recursive: true, mode: 448 });
|
|
7655
|
+
let bodyBytes = 0;
|
|
7656
|
+
for (const id of bodyIds) {
|
|
7657
|
+
const name = id.replace(/[^A-Za-z0-9]/g, "_");
|
|
7658
|
+
const target = join7(shared, "bodies", name);
|
|
7659
|
+
const bytes = readBounded(existsSync(target) ? target : join7(legacy, "bodies", name), DEFAULT_EVIDENCE_SPOOL_LIMITS.maxSingleBodyBytes);
|
|
7660
|
+
if (evidenceBodyId(bytes) !== id)
|
|
7661
|
+
throw new Error("Evidence migration body integrity failed");
|
|
7662
|
+
bodyBytes += bytes.length;
|
|
7663
|
+
if (bodyBytes > DEFAULT_EVIDENCE_SPOOL_LIMITS.maxBodyBytes)
|
|
7664
|
+
throw new Error("Evidence migration exceeds body capacity");
|
|
7665
|
+
if (!existsSync(target))
|
|
7666
|
+
publishFile(target, bytes);
|
|
7667
|
+
}
|
|
7668
|
+
const retainedNames = new Set([...bodyIds].map((id) => id.replace(/[^A-Za-z0-9]/g, "_")));
|
|
7669
|
+
for (const name of readdirSync2(join7(shared, "bodies"))) {
|
|
7670
|
+
if (/^sha256_[a-f0-9]{64}$/.test(name) && !retainedNames.has(name)) {
|
|
7671
|
+
rmSync2(join7(shared, "bodies", name));
|
|
7672
|
+
}
|
|
7673
|
+
}
|
|
7674
|
+
publishFile(join7(shared, "entries.jsonl"), contents);
|
|
7675
|
+
rmSync2(legacyFile);
|
|
7676
|
+
}
|
|
7677
|
+
|
|
7543
7678
|
// ../../bridges/codex-bridge/src/change-evidence.ts
|
|
7544
|
-
function detectCaptureExecutor(exists =
|
|
7679
|
+
function detectCaptureExecutor(exists = existsSync2) {
|
|
7545
7680
|
return exists("/.dockerenv") || exists("/run/.containerenv") ? "container-worker" : "host-worker";
|
|
7546
7681
|
}
|
|
7547
7682
|
function codexChangeCapabilities(executor) {
|
|
@@ -7777,13 +7912,13 @@ function suppliedMovePath(change) {
|
|
|
7777
7912
|
}
|
|
7778
7913
|
function codexChangeEvidenceDir(codexHome, cwd) {
|
|
7779
7914
|
const cwdHash = createHash5("sha256").update(cwd).digest("hex").slice(0, 16);
|
|
7780
|
-
return
|
|
7915
|
+
return join8(codexBridgeStateDir(codexHome), "change-evidence", cwdHash);
|
|
7781
7916
|
}
|
|
7782
7917
|
function createCodexChangeEvidence(options) {
|
|
7918
|
+
const directory = codexChangeEvidenceDir(options.codexHome, options.cwd);
|
|
7919
|
+
migrateCodexChangeEvidence(join8(codexLoginBridgeDir(options.codexHome), "change-evidence", basename(directory)), directory);
|
|
7783
7920
|
return new CodexChangeEvidence({
|
|
7784
|
-
spool: new ChangeEvidenceSpool({
|
|
7785
|
-
directory: codexChangeEvidenceDir(options.codexHome, options.cwd)
|
|
7786
|
-
}),
|
|
7921
|
+
spool: new ChangeEvidenceSpool({ directory }),
|
|
7787
7922
|
executor: options.executor ?? detectCaptureExecutor()
|
|
7788
7923
|
});
|
|
7789
7924
|
}
|
|
@@ -7812,7 +7947,7 @@ function codexApprovalConfig(policy, sandbox, mode) {
|
|
|
7812
7947
|
import { spawn as spawn2 } from "node:child_process";
|
|
7813
7948
|
import { appendFile as appendFile3, mkdir as mkdir3, mkdtemp as mkdtemp2, readFile as readFile2, rm as rm4, writeFile as writeFile3 } from "node:fs/promises";
|
|
7814
7949
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
7815
|
-
import { join as
|
|
7950
|
+
import { join as join9 } from "node:path";
|
|
7816
7951
|
|
|
7817
7952
|
// ../protocol/src/codex-background-task.ts
|
|
7818
7953
|
var CODEX_BACKGROUND_TASK_MODEL = "gpt-5.6-luna";
|
|
@@ -7892,7 +8027,7 @@ async function refreshRuntimeEnvironment(run = execFile2) {
|
|
|
7892
8027
|
`if [ -f "$${RUNTIME_ENV_SCRIPT_ENV}" ]; then . "$${RUNTIME_ENV_SCRIPT_ENV}" 2>/dev/null || true; orkestrator_source_runtime_env 2>/dev/null || true; fi; env`
|
|
7893
8028
|
], {
|
|
7894
8029
|
env: {
|
|
7895
|
-
...
|
|
8030
|
+
...runtimeEnvironmentSnapshot(),
|
|
7896
8031
|
[RUNTIME_ENV_SCRIPT_ENV]: runtimeEnvScript
|
|
7897
8032
|
},
|
|
7898
8033
|
maxBuffer: 256 * 1024
|
|
@@ -7916,7 +8051,9 @@ function fingerprintRuntimeEnvironment(env = process.env) {
|
|
|
7916
8051
|
return `sha256:${hash.digest("hex").slice(0, 32)}`;
|
|
7917
8052
|
}
|
|
7918
8053
|
function runtimeEnvironmentSnapshot(env = process.env) {
|
|
7919
|
-
|
|
8054
|
+
const snapshot = { ...env };
|
|
8055
|
+
delete snapshot.CODEX_BRIDGE_STATE_DIR;
|
|
8056
|
+
return snapshot;
|
|
7920
8057
|
}
|
|
7921
8058
|
function runtimeEnvironmentWithoutCredentials(env = process.env) {
|
|
7922
8059
|
const snapshot = runtimeEnvironmentSnapshot(env);
|
|
@@ -8201,10 +8338,10 @@ async function runCodexTitleCommand(codexPath, args, input, options = {}) {
|
|
|
8201
8338
|
});
|
|
8202
8339
|
}
|
|
8203
8340
|
async function generateSessionTitleWithCodexExec(codexPath, sourcePrompt, options = {}) {
|
|
8204
|
-
const temporaryDirectory = await mkdtemp2(
|
|
8205
|
-
const outputPath =
|
|
8206
|
-
const modelCatalogPath =
|
|
8207
|
-
const outputSchemaPath =
|
|
8341
|
+
const temporaryDirectory = await mkdtemp2(join9(options.temporaryRoot ?? tmpdir2(), "orkestrator-session-title-"));
|
|
8342
|
+
const outputPath = join9(temporaryDirectory, "title.txt");
|
|
8343
|
+
const modelCatalogPath = join9(temporaryDirectory, "model-catalog.json");
|
|
8344
|
+
const outputSchemaPath = join9(temporaryDirectory, "title-schema.json");
|
|
8208
8345
|
const maxOutputBytes = options.maxOutputBytes ?? MAX_COMMAND_OUTPUT_LENGTH;
|
|
8209
8346
|
try {
|
|
8210
8347
|
await Promise.all([
|
|
@@ -8235,7 +8372,11 @@ async function generateSessionTitleWithCodexExec(codexPath, sourcePrompt, option
|
|
|
8235
8372
|
}
|
|
8236
8373
|
}
|
|
8237
8374
|
function sessionTitleIndexPath(codexHome) {
|
|
8238
|
-
return
|
|
8375
|
+
return join9(codexBridgeStateDir(codexHome), SESSION_TITLE_INDEX_FILENAME);
|
|
8376
|
+
}
|
|
8377
|
+
function legacySessionTitleIndexPath(codexHome) {
|
|
8378
|
+
const legacy = join9(codexLoginBridgeDir(codexHome), SESSION_TITLE_INDEX_FILENAME);
|
|
8379
|
+
return legacy === sessionTitleIndexPath(codexHome) ? undefined : legacy;
|
|
8239
8380
|
}
|
|
8240
8381
|
function persistedSourcePriority(source) {
|
|
8241
8382
|
if (source === "explicit")
|
|
@@ -8245,7 +8386,11 @@ function persistedSourcePriority(source) {
|
|
|
8245
8386
|
return 1;
|
|
8246
8387
|
}
|
|
8247
8388
|
async function readPersistedSessionTitleEntries(codexHome) {
|
|
8248
|
-
const
|
|
8389
|
+
const legacyPath = legacySessionTitleIndexPath(codexHome);
|
|
8390
|
+
const legacy = legacyPath ? await readFile2(legacyPath, "utf8").catch(() => "") : "";
|
|
8391
|
+
const current = await readFile2(sessionTitleIndexPath(codexHome), "utf8").catch(() => "");
|
|
8392
|
+
const raw = legacy ? `${legacy}
|
|
8393
|
+
${current}` : current;
|
|
8249
8394
|
const selected = new Map;
|
|
8250
8395
|
for (const [lineIndex, line] of raw.split(`
|
|
8251
8396
|
`).entries()) {
|
|
@@ -8290,7 +8435,7 @@ async function persistSessionTitle(codexHome, threadId, title, options = {}) {
|
|
|
8290
8435
|
throw new Error("Session title updatedAt must be a valid date");
|
|
8291
8436
|
}
|
|
8292
8437
|
const updatedAt = requestedUpdatedAt.toISOString();
|
|
8293
|
-
const directory =
|
|
8438
|
+
const directory = codexBridgeStateDir(codexHome);
|
|
8294
8439
|
await mkdir3(directory, { recursive: true });
|
|
8295
8440
|
await appendFile3(sessionTitleIndexPath(codexHome), `${JSON.stringify({
|
|
8296
8441
|
threadId: normalizedThreadId,
|
|
@@ -10809,7 +10954,7 @@ async function deriveTranscriptSubagentPartsForTurn({
|
|
|
10809
10954
|
import { createHash as createHash7 } from "node:crypto";
|
|
10810
10955
|
import { readFile as readFile4, readdir, stat as stat4 } from "node:fs/promises";
|
|
10811
10956
|
import { homedir } from "node:os";
|
|
10812
|
-
import { basename, join as
|
|
10957
|
+
import { basename as basename2, join as join10 } from "node:path";
|
|
10813
10958
|
|
|
10814
10959
|
// ../../bridges/codex-bridge/src/sessions/refused-cell-tail.ts
|
|
10815
10960
|
import { open as open2, stat as stat3 } from "node:fs/promises";
|
|
@@ -11005,7 +11150,7 @@ class RefusedCellTail {
|
|
|
11005
11150
|
}
|
|
11006
11151
|
|
|
11007
11152
|
// ../../bridges/codex-bridge/src/app-server/item-adapter.ts
|
|
11008
|
-
import { isAbsolute as
|
|
11153
|
+
import { isAbsolute as isAbsolute6 } from "node:path";
|
|
11009
11154
|
function isRecord5(value) {
|
|
11010
11155
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
11011
11156
|
}
|
|
@@ -11027,7 +11172,7 @@ function imageGenerationInputPaths(value) {
|
|
|
11027
11172
|
if (paths.size >= MAX_IMAGE_GENERATION_INPUTS)
|
|
11028
11173
|
break;
|
|
11029
11174
|
const path = isRecord5(entry) ? str(entry.path) : undefined;
|
|
11030
|
-
if (path &&
|
|
11175
|
+
if (path && isAbsolute6(path))
|
|
11031
11176
|
paths.add(path);
|
|
11032
11177
|
}
|
|
11033
11178
|
return [...paths];
|
|
@@ -11374,6 +11519,28 @@ function mapTodoArgs(items) {
|
|
|
11374
11519
|
};
|
|
11375
11520
|
}
|
|
11376
11521
|
|
|
11522
|
+
// ../../bridges/codex-bridge/src/messages/turn-failure.ts
|
|
11523
|
+
var MAX_TURN_FAILURE_CHARS = 2000;
|
|
11524
|
+
function turnFailureItemId(turnId) {
|
|
11525
|
+
return `turn-error:${turnId}`;
|
|
11526
|
+
}
|
|
11527
|
+
function turnFailureText(message) {
|
|
11528
|
+
const raw = message.trim();
|
|
11529
|
+
let text = raw;
|
|
11530
|
+
if (raw.startsWith("{")) {
|
|
11531
|
+
try {
|
|
11532
|
+
const body = JSON.parse(raw);
|
|
11533
|
+
const nested = body.error && typeof body.error === "object" ? body.error.message : undefined;
|
|
11534
|
+
const candidate = typeof nested === "string" ? nested : body.message;
|
|
11535
|
+
if (typeof candidate === "string" && candidate.trim())
|
|
11536
|
+
text = candidate.trim();
|
|
11537
|
+
} catch {}
|
|
11538
|
+
}
|
|
11539
|
+
if (!text)
|
|
11540
|
+
text = "Codex ended the turn on an error.";
|
|
11541
|
+
return text.length > MAX_TURN_FAILURE_CHARS ? `${text.slice(0, MAX_TURN_FAILURE_CHARS - 1)}…` : text;
|
|
11542
|
+
}
|
|
11543
|
+
|
|
11377
11544
|
// ../../bridges/codex-bridge/src/sessions/turn-accumulator.ts
|
|
11378
11545
|
var MAX_ITEM_PROGRESS_CHARS = 200;
|
|
11379
11546
|
var MODEL_STEP_TOOL_ITEM_TYPES = new Set([
|
|
@@ -11695,6 +11862,14 @@ class TurnAccumulator {
|
|
|
11695
11862
|
this.touch(accumulator);
|
|
11696
11863
|
}
|
|
11697
11864
|
}
|
|
11865
|
+
recordProviderFailure(error) {
|
|
11866
|
+
this.onItemCompleted({
|
|
11867
|
+
id: turnFailureItemId(this.turnId),
|
|
11868
|
+
type: "status",
|
|
11869
|
+
text: turnFailureText(error.message),
|
|
11870
|
+
severity: "error"
|
|
11871
|
+
});
|
|
11872
|
+
}
|
|
11698
11873
|
interruptOpenAgentMessages(keepId) {
|
|
11699
11874
|
for (const id of Array.from(this.openAgentMessageIds)) {
|
|
11700
11875
|
if (id === keepId)
|
|
@@ -12332,7 +12507,9 @@ var COORDINATOR_CONTROL_TOOL_NAMES = Object.freeze([
|
|
|
12332
12507
|
"adopt_workflow",
|
|
12333
12508
|
"cancel_build_pipeline",
|
|
12334
12509
|
"cancel_multi_review",
|
|
12510
|
+
"cancel_schedule",
|
|
12335
12511
|
"compare_project_files",
|
|
12512
|
+
"create_schedule",
|
|
12336
12513
|
"create_ticket",
|
|
12337
12514
|
"get_build_pipeline",
|
|
12338
12515
|
"get_environment",
|
|
@@ -12354,6 +12531,7 @@ var COORDINATOR_CONTROL_TOOL_NAMES = Object.freeze([
|
|
|
12354
12531
|
"list_node_environments",
|
|
12355
12532
|
"list_nodes",
|
|
12356
12533
|
"list_projects",
|
|
12534
|
+
"list_schedules",
|
|
12357
12535
|
"list_tabs",
|
|
12358
12536
|
"list_tickets",
|
|
12359
12537
|
"list_workflows",
|
|
@@ -12393,7 +12571,7 @@ function stripCoordinatorContext(text) {
|
|
|
12393
12571
|
|
|
12394
12572
|
// ../../bridges/codex-bridge/src/history/rollout.ts
|
|
12395
12573
|
function getCodexHomeDir() {
|
|
12396
|
-
return process.env.CODEX_HOME ||
|
|
12574
|
+
return process.env.CODEX_HOME || join10(homedir(), ".codex");
|
|
12397
12575
|
}
|
|
12398
12576
|
function getWorkingDirectory(explicitCwd) {
|
|
12399
12577
|
return explicitCwd || process.env.CWD || process.cwd();
|
|
@@ -12407,7 +12585,7 @@ async function walkJsonlFiles(dir) {
|
|
|
12407
12585
|
}
|
|
12408
12586
|
const files = [];
|
|
12409
12587
|
for (const entry of entries) {
|
|
12410
|
-
const absolutePath =
|
|
12588
|
+
const absolutePath = join10(dir, entry.name);
|
|
12411
12589
|
if (entry.isDirectory()) {
|
|
12412
12590
|
files.push(...await walkJsonlFiles(absolutePath));
|
|
12413
12591
|
continue;
|
|
@@ -12419,7 +12597,7 @@ async function walkJsonlFiles(dir) {
|
|
|
12419
12597
|
return files;
|
|
12420
12598
|
}
|
|
12421
12599
|
async function listTranscriptPaths(codexHome = getCodexHomeDir()) {
|
|
12422
|
-
const searchRoots = [
|
|
12600
|
+
const searchRoots = [join10(codexHome, "sessions"), join10(codexHome, "archived_sessions")];
|
|
12423
12601
|
return (await Promise.all(searchRoots.map((root) => walkJsonlFiles(root)))).flat();
|
|
12424
12602
|
}
|
|
12425
12603
|
var cachedTranscriptPaths = new Map;
|
|
@@ -12446,7 +12624,7 @@ function rememberTranscriptPath(threadId, path) {
|
|
|
12446
12624
|
}
|
|
12447
12625
|
function selectTranscriptPath(paths, threadId) {
|
|
12448
12626
|
const anchored = paths.find((file) => {
|
|
12449
|
-
const stem =
|
|
12627
|
+
const stem = basename2(file).replace(/\.jsonl$/, "");
|
|
12450
12628
|
return stem === threadId || stem.endsWith(`-${threadId}`);
|
|
12451
12629
|
});
|
|
12452
12630
|
return anchored ?? paths.find((file) => file.includes(threadId)) ?? null;
|
|
@@ -12562,8 +12740,8 @@ async function buildTranscriptCatalog() {
|
|
|
12562
12740
|
const metaByPath = new Map;
|
|
12563
12741
|
const transcriptPathByThreadId = new Map;
|
|
12564
12742
|
for (const root of [
|
|
12565
|
-
|
|
12566
|
-
|
|
12743
|
+
join10(getCodexHomeDir(), "sessions"),
|
|
12744
|
+
join10(getCodexHomeDir(), "archived_sessions")
|
|
12567
12745
|
]) {
|
|
12568
12746
|
const files = await walkJsonlFiles(root);
|
|
12569
12747
|
for (const transcriptPath of files) {
|
|
@@ -12573,7 +12751,7 @@ async function buildTranscriptCatalog() {
|
|
|
12573
12751
|
}
|
|
12574
12752
|
metas.push(meta);
|
|
12575
12753
|
metaByPath.set(transcriptPath, meta);
|
|
12576
|
-
const fileThreadId =
|
|
12754
|
+
const fileThreadId = basename2(transcriptPath, ".jsonl");
|
|
12577
12755
|
if (!transcriptPathByThreadId.has(fileThreadId)) {
|
|
12578
12756
|
transcriptPathByThreadId.set(fileThreadId, transcriptPath);
|
|
12579
12757
|
}
|
|
@@ -12758,7 +12936,7 @@ async function listPersistedSessionsForCwd(cwd, options) {
|
|
|
12758
12936
|
return (await listPersistedSessionsWithTitlesForCwd(cwd, options)).sessions;
|
|
12759
12937
|
}
|
|
12760
12938
|
async function listPersistedSessionsWithTitlesForCwd(cwd, options) {
|
|
12761
|
-
const indexPath =
|
|
12939
|
+
const indexPath = join10(getCodexHomeDir(), "session_index.jsonl");
|
|
12762
12940
|
const lines = await readTranscriptLines(indexPath);
|
|
12763
12941
|
const sessions = new Map;
|
|
12764
12942
|
const transcriptCatalog = await buildTranscriptCatalogCached(options?.mustContainThreadId);
|
|
@@ -12807,9 +12985,16 @@ function mergePersistedSessionMeta(sessionsById, meta) {
|
|
|
12807
12985
|
indexed.updatedAt = meta.updatedAt;
|
|
12808
12986
|
}
|
|
12809
12987
|
}
|
|
12988
|
+
var CODEX_CONTEXT_FRAGMENTS = [
|
|
12989
|
+
["<environment_context>", "</environment_context>"],
|
|
12990
|
+
["<skill>", "</skill>"],
|
|
12991
|
+
["<turn_aborted>", "</turn_aborted>"],
|
|
12992
|
+
["<subagent_notification>", "</subagent_notification>"],
|
|
12993
|
+
["<user_shell_command>", "</user_shell_command>"]
|
|
12994
|
+
];
|
|
12810
12995
|
function isSyntheticPersistedUserText(text) {
|
|
12811
12996
|
const trimmed = text.trim();
|
|
12812
|
-
return trimmed.startsWith("# AGENTS.md instructions for ") || /^# AGENTS\.md instructions[ \t]*\n\s*<INSTRUCTIONS>/.test(trimmed) || trimmed.startsWith(`<recommended_plugins>
|
|
12997
|
+
return trimmed.startsWith("# AGENTS.md instructions for ") || /^# AGENTS\.md instructions[ \t]*\n\s*<INSTRUCTIONS>/.test(trimmed) || CODEX_CONTEXT_FRAGMENTS.some(([open, close]) => trimmed.startsWith(open) && trimmed.endsWith(close)) || trimmed.startsWith(`<recommended_plugins>
|
|
12813
12998
|
Here is a list of plugins that are available but not installed.`);
|
|
12814
12999
|
}
|
|
12815
13000
|
function extractPersistedMessageContent(content, role) {
|
|
@@ -12826,6 +13011,9 @@ function extractPersistedMessageContent(content, role) {
|
|
|
12826
13011
|
if (segments.length === 0) {
|
|
12827
13012
|
return null;
|
|
12828
13013
|
}
|
|
13014
|
+
if (role === "user" && segments.every((segment) => !segment.trim() || isSyntheticPersistedUserText(segment))) {
|
|
13015
|
+
return null;
|
|
13016
|
+
}
|
|
12829
13017
|
const joined = segments.join(`
|
|
12830
13018
|
`).trim();
|
|
12831
13019
|
if (!joined) {
|
|
@@ -12835,7 +13023,7 @@ function extractPersistedMessageContent(content, role) {
|
|
|
12835
13023
|
if (!text && parts.length === 0) {
|
|
12836
13024
|
return null;
|
|
12837
13025
|
}
|
|
12838
|
-
if (role === "user" && isSyntheticPersistedUserText(text)) {
|
|
13026
|
+
if (role === "user" && segments.length === 1 && isSyntheticPersistedUserText(text)) {
|
|
12839
13027
|
return null;
|
|
12840
13028
|
}
|
|
12841
13029
|
return { text, attachments: parts };
|
|
@@ -12887,7 +13075,7 @@ function persistedOutputState(payloadType, part, output) {
|
|
|
12887
13075
|
return payloadType === "custom_tool_call_output" ? resolveTranscriptToolOutputState(part.toolName, output, part.toolState ?? null) : null;
|
|
12888
13076
|
}
|
|
12889
13077
|
async function findSessionIndexEntry(threadId) {
|
|
12890
|
-
const lines = await readTranscriptLines(
|
|
13078
|
+
const lines = await readTranscriptLines(join10(getCodexHomeDir(), "session_index.jsonl"));
|
|
12891
13079
|
let match = null;
|
|
12892
13080
|
for (const line of lines) {
|
|
12893
13081
|
let parsed;
|
|
@@ -13219,6 +13407,17 @@ async function replayPersistedRollout(threadId, snapshot, meta, structuredTurns)
|
|
|
13219
13407
|
visitCompletedItem(record.payload.item, timestamp);
|
|
13220
13408
|
return;
|
|
13221
13409
|
}
|
|
13410
|
+
if (record.type === "event_msg" && record.payload?.type === "task_complete") {
|
|
13411
|
+
const error = record.payload.error;
|
|
13412
|
+
if (error && typeof error === "object" && typeof error.message === "string") {
|
|
13413
|
+
ensureAssistantMessage(timestamp).parts.push({
|
|
13414
|
+
type: "status",
|
|
13415
|
+
severity: "error",
|
|
13416
|
+
content: turnFailureText(error.message)
|
|
13417
|
+
});
|
|
13418
|
+
}
|
|
13419
|
+
return;
|
|
13420
|
+
}
|
|
13222
13421
|
if (record.type === "token_usage_record" || record.type === "event_msg" && record.payload?.type === "token_count") {
|
|
13223
13422
|
if (currentRowCalledTool)
|
|
13224
13423
|
responseCompletedInRow = true;
|
|
@@ -14108,7 +14307,7 @@ async function publishAssistantRows(context, state, turn, options) {
|
|
|
14108
14307
|
}
|
|
14109
14308
|
|
|
14110
14309
|
// ../../bridges/codex-bridge/src/app-server-runtime-sessions.ts
|
|
14111
|
-
import { createHash as createHash10, randomUUID as
|
|
14310
|
+
import { createHash as createHash10, randomUUID as randomUUID7 } from "node:crypto";
|
|
14112
14311
|
|
|
14113
14312
|
// ../protocol/src/agent-mail.ts
|
|
14114
14313
|
var AGENT_MAIL_MAX_BODY_BYTES = 32 * 1024;
|
|
@@ -14173,11 +14372,11 @@ var ORKESTRATOR_ARTIFACT_MCP_PATH = "/artifact-mcp";
|
|
|
14173
14372
|
// ../../bridges/codex-bridge/src/engine/app-server-engine.ts
|
|
14174
14373
|
import { open as open6 } from "node:fs/promises";
|
|
14175
14374
|
import { createHash as createHash9 } from "node:crypto";
|
|
14176
|
-
import { isAbsolute as
|
|
14375
|
+
import { isAbsolute as isAbsolute8, join as join15 } from "node:path";
|
|
14177
14376
|
|
|
14178
14377
|
// ../../bridges/codex-bridge/src/app-server/process-supervisor.ts
|
|
14179
14378
|
import { execFile as execFile3, spawn as spawn3 } from "node:child_process";
|
|
14180
|
-
import { randomUUID as
|
|
14379
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
14181
14380
|
import {
|
|
14182
14381
|
link,
|
|
14183
14382
|
mkdir as mkdir5,
|
|
@@ -14188,7 +14387,7 @@ import {
|
|
|
14188
14387
|
rm as rm5,
|
|
14189
14388
|
stat as stat5
|
|
14190
14389
|
} from "node:fs/promises";
|
|
14191
|
-
import { join as
|
|
14390
|
+
import { join as join12 } from "node:path";
|
|
14192
14391
|
|
|
14193
14392
|
// ../../bridges/codex-bridge/src/app-server/errors.ts
|
|
14194
14393
|
var APP_SERVER_OVERLOAD_CODE = -32001;
|
|
@@ -14257,7 +14456,7 @@ class AppServerUnavailableError extends Error {
|
|
|
14257
14456
|
class AppServerCircuitOpenError extends Error {
|
|
14258
14457
|
failures;
|
|
14259
14458
|
constructor(failures, lastError) {
|
|
14260
|
-
super(`app-server failed to start ${failures} times; not retrying${lastError ? ` (last error: ${lastError})` : ""}`);
|
|
14459
|
+
super(`app-server failed to start ${failures} times; not retrying until the cooldown ends${lastError ? ` (last error: ${lastError})` : ""}`);
|
|
14261
14460
|
this.name = "AppServerCircuitOpenError";
|
|
14262
14461
|
this.failures = failures;
|
|
14263
14462
|
}
|
|
@@ -14776,7 +14975,7 @@ class SerialQueue {
|
|
|
14776
14975
|
|
|
14777
14976
|
// ../../bridges/codex-bridge/src/app-server/notification-recorder.ts
|
|
14778
14977
|
import { appendFile as appendFile4, mkdir as mkdir4 } from "node:fs/promises";
|
|
14779
|
-
import { join as
|
|
14978
|
+
import { join as join11 } from "node:path";
|
|
14780
14979
|
var DEFAULT_MAX_RECORDING_BYTES = 64 * 1024 * 1024;
|
|
14781
14980
|
var DEFAULT_FLUSH_INTERVAL_MS = 250;
|
|
14782
14981
|
var DEFAULT_WARN_INTERVAL_MS = 60000;
|
|
@@ -14802,7 +15001,7 @@ class NotificationRecorder {
|
|
|
14802
15001
|
stats;
|
|
14803
15002
|
constructor(options) {
|
|
14804
15003
|
this.options = options;
|
|
14805
|
-
this.path =
|
|
15004
|
+
this.path = join11(options.directory, options.fileName);
|
|
14806
15005
|
this.maxBytes = options.maxBytes ?? DEFAULT_MAX_RECORDING_BYTES;
|
|
14807
15006
|
this.flushIntervalMs = options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
|
|
14808
15007
|
this.warnIntervalMs = options.warnIntervalMs ?? DEFAULT_WARN_INTERVAL_MS;
|
|
@@ -14933,6 +15132,8 @@ function isOwnershipContention(error) {
|
|
|
14933
15132
|
var DEFAULT_BACKOFF_MS = [250, 500, 1000, 2000, 5000, 1e4];
|
|
14934
15133
|
var DEFAULT_CIRCUIT_THRESHOLD = 5;
|
|
14935
15134
|
var DEFAULT_CIRCUIT_WINDOW_MS = 60000;
|
|
15135
|
+
var DEFAULT_CIRCUIT_COOLDOWN_MS = 5 * 60000;
|
|
15136
|
+
var DEFAULT_CIRCUIT_MAX_COOLDOWN_MS = 30 * 60000;
|
|
14936
15137
|
var DEFAULT_SHUTDOWN_GRACE_MS = 5000;
|
|
14937
15138
|
var INCOMPLETE_PIDFILE_GRACE_MS = 1000;
|
|
14938
15139
|
var PID_OWNERSHIP_TTL_MS = 24 * 60 * 60 * 1000;
|
|
@@ -14947,6 +15148,8 @@ class AppServerSupervisor {
|
|
|
14947
15148
|
backoffSchedule;
|
|
14948
15149
|
circuitThreshold;
|
|
14949
15150
|
circuitWindowMs;
|
|
15151
|
+
circuitCooldownMs;
|
|
15152
|
+
circuitMaxCooldownMs;
|
|
14950
15153
|
shutdownGraceMs;
|
|
14951
15154
|
fingerprintEnvironment;
|
|
14952
15155
|
notificationQueue = new SerialQueue;
|
|
@@ -14959,6 +15162,9 @@ class AppServerSupervisor {
|
|
|
14959
15162
|
restartFailures = [];
|
|
14960
15163
|
restartCount = 0;
|
|
14961
15164
|
circuitOpen = false;
|
|
15165
|
+
circuitProbeAt = 0;
|
|
15166
|
+
nextCircuitCooldownMs;
|
|
15167
|
+
stopController = new AbortController;
|
|
14962
15168
|
lastError;
|
|
14963
15169
|
lastExitCode = null;
|
|
14964
15170
|
lastExitSignal = null;
|
|
@@ -14966,7 +15172,7 @@ class AppServerSupervisor {
|
|
|
14966
15172
|
unknownNotifications = 0;
|
|
14967
15173
|
unknownServerRequests = 0;
|
|
14968
15174
|
drainPromise = null;
|
|
14969
|
-
pidOwnerToken =
|
|
15175
|
+
pidOwnerToken = randomUUID5();
|
|
14970
15176
|
pidOwnershipHeld = false;
|
|
14971
15177
|
constructor(options) {
|
|
14972
15178
|
this.options = options;
|
|
@@ -14974,6 +15180,9 @@ class AppServerSupervisor {
|
|
|
14974
15180
|
this.backoffSchedule = options.backoffScheduleMs ?? DEFAULT_BACKOFF_MS;
|
|
14975
15181
|
this.circuitThreshold = options.circuitBreakerThreshold ?? DEFAULT_CIRCUIT_THRESHOLD;
|
|
14976
15182
|
this.circuitWindowMs = options.circuitWindowMs ?? DEFAULT_CIRCUIT_WINDOW_MS;
|
|
15183
|
+
this.circuitCooldownMs = Math.max(0, options.circuitCooldownMs ?? DEFAULT_CIRCUIT_COOLDOWN_MS);
|
|
15184
|
+
this.circuitMaxCooldownMs = Math.max(this.circuitCooldownMs, options.circuitMaxCooldownMs ?? DEFAULT_CIRCUIT_MAX_COOLDOWN_MS);
|
|
15185
|
+
this.nextCircuitCooldownMs = this.circuitCooldownMs;
|
|
14977
15186
|
this.shutdownGraceMs = options.shutdownGraceMs ?? DEFAULT_SHUTDOWN_GRACE_MS;
|
|
14978
15187
|
this.fingerprintEnvironment = options.fingerprintEnvironment ?? fingerprintRuntimeEnvironment;
|
|
14979
15188
|
}
|
|
@@ -15026,13 +15235,15 @@ class AppServerSupervisor {
|
|
|
15026
15235
|
async ensureStarted() {
|
|
15027
15236
|
if (this.stopping)
|
|
15028
15237
|
throw new AppServerUnavailableError("stopped");
|
|
15029
|
-
if (this.
|
|
15238
|
+
if (this.startPromise)
|
|
15239
|
+
return this.startPromise;
|
|
15240
|
+
if (this.circuitOpen && this.now() < this.circuitProbeAt) {
|
|
15030
15241
|
throw new AppServerCircuitOpenError(this.restartFailures.length, this.lastError);
|
|
15031
15242
|
}
|
|
15032
15243
|
if (this.current && !this.current.client.isClosed() && this.state === "ready") {
|
|
15033
15244
|
return this.current;
|
|
15034
15245
|
}
|
|
15035
|
-
this.startPromise
|
|
15246
|
+
this.startPromise = this.startWithRetry(this.circuitOpen).finally(() => {
|
|
15036
15247
|
this.startPromise = null;
|
|
15037
15248
|
});
|
|
15038
15249
|
return this.startPromise;
|
|
@@ -15069,12 +15280,14 @@ class AppServerSupervisor {
|
|
|
15069
15280
|
return;
|
|
15070
15281
|
await this.current.client.respondWithError(id, code, message);
|
|
15071
15282
|
}
|
|
15072
|
-
async startWithRetry() {
|
|
15283
|
+
async startWithRetry(probe = false) {
|
|
15073
15284
|
let attempt = 0;
|
|
15074
15285
|
for (;; ) {
|
|
15075
15286
|
try {
|
|
15076
15287
|
const generation = await this.start();
|
|
15077
15288
|
this.restartFailures = [];
|
|
15289
|
+
this.circuitOpen = false;
|
|
15290
|
+
this.nextCircuitCooldownMs = this.circuitCooldownMs;
|
|
15078
15291
|
return generation;
|
|
15079
15292
|
} catch (error) {
|
|
15080
15293
|
this.lastError = error instanceof Error ? error.message : String(error);
|
|
@@ -15084,7 +15297,7 @@ class AppServerSupervisor {
|
|
|
15084
15297
|
this.setState("failed", this.lastError);
|
|
15085
15298
|
throw error;
|
|
15086
15299
|
}
|
|
15087
|
-
this.recordFailure();
|
|
15300
|
+
this.recordFailure(probe);
|
|
15088
15301
|
if (this.circuitOpen) {
|
|
15089
15302
|
this.setState("failed", this.lastError);
|
|
15090
15303
|
throw new AppServerCircuitOpenError(this.restartFailures.length, this.lastError);
|
|
@@ -15092,19 +15305,21 @@ class AppServerSupervisor {
|
|
|
15092
15305
|
const delay = this.backoffDelay(attempt);
|
|
15093
15306
|
attempt += 1;
|
|
15094
15307
|
this.setState("backoff", `retrying in ${delay}ms: ${this.lastError}`);
|
|
15095
|
-
await
|
|
15308
|
+
await sleepUnlessAborted(delay, this.stopController.signal);
|
|
15096
15309
|
if (this.stopping)
|
|
15097
15310
|
throw new AppServerUnavailableError("stopped");
|
|
15098
15311
|
}
|
|
15099
15312
|
}
|
|
15100
15313
|
}
|
|
15101
|
-
recordFailure() {
|
|
15314
|
+
recordFailure(probe = false) {
|
|
15102
15315
|
const now = this.now();
|
|
15103
15316
|
this.restartFailures = this.restartFailures.filter((at) => now - at <= this.circuitWindowMs);
|
|
15104
15317
|
this.restartFailures.push(now);
|
|
15105
|
-
if (this.restartFailures.length
|
|
15106
|
-
|
|
15107
|
-
|
|
15318
|
+
if (!probe && this.restartFailures.length < this.circuitThreshold)
|
|
15319
|
+
return;
|
|
15320
|
+
this.circuitOpen = true;
|
|
15321
|
+
this.circuitProbeAt = now + this.nextCircuitCooldownMs;
|
|
15322
|
+
this.nextCircuitCooldownMs = Math.min(this.circuitMaxCooldownMs, Math.max(1, this.nextCircuitCooldownMs) * 2);
|
|
15108
15323
|
}
|
|
15109
15324
|
backoffDelay(attempt) {
|
|
15110
15325
|
const base = this.backoffSchedule[Math.min(attempt, this.backoffSchedule.length - 1)] ?? 1000;
|
|
@@ -15116,7 +15331,7 @@ class AppServerSupervisor {
|
|
|
15116
15331
|
if (this.stopping)
|
|
15117
15332
|
throw new AppServerUnavailableError("stopped");
|
|
15118
15333
|
const environmentFingerprint = this.fingerprintEnvironment();
|
|
15119
|
-
const instanceId =
|
|
15334
|
+
const instanceId = randomUUID5();
|
|
15120
15335
|
const instanceStartedAt = this.now();
|
|
15121
15336
|
if (this.options.pidFileEnabled !== false && !this.pidOwnershipHeld) {
|
|
15122
15337
|
const available = await this.acquirePidFileOwnership(instanceId);
|
|
@@ -15134,7 +15349,7 @@ class AppServerSupervisor {
|
|
|
15134
15349
|
const child = spawnFn(this.options.codexPath, args, {
|
|
15135
15350
|
cwd: this.options.cwd,
|
|
15136
15351
|
env: {
|
|
15137
|
-
...
|
|
15352
|
+
...runtimeEnvironmentSnapshot(),
|
|
15138
15353
|
CODEX_HOME: this.options.codexHome,
|
|
15139
15354
|
LOG_FORMAT: "json",
|
|
15140
15355
|
ORKESTRATOR_APP_SERVER_INSTANCE_ID: instanceId
|
|
@@ -15349,6 +15564,7 @@ class AppServerSupervisor {
|
|
|
15349
15564
|
}
|
|
15350
15565
|
async stop() {
|
|
15351
15566
|
this.stopping = true;
|
|
15567
|
+
this.stopController.abort();
|
|
15352
15568
|
this.setState("draining", "bridge shutting down");
|
|
15353
15569
|
const pendingStart = this.startPromise;
|
|
15354
15570
|
const startingChild = this.startingChild;
|
|
@@ -15409,10 +15625,10 @@ class AppServerSupervisor {
|
|
|
15409
15625
|
} catch {}
|
|
15410
15626
|
}
|
|
15411
15627
|
pidFileDir() {
|
|
15412
|
-
return
|
|
15628
|
+
return join12(this.options.codexHome, "orkestrator-bridge");
|
|
15413
15629
|
}
|
|
15414
15630
|
pidFilePath() {
|
|
15415
|
-
return
|
|
15631
|
+
return join12(this.pidFileDir(), `app-server-${hashPath(this.options.cwd)}.pid`);
|
|
15416
15632
|
}
|
|
15417
15633
|
async readOwnedPidRecord(path) {
|
|
15418
15634
|
let raw;
|
|
@@ -15670,7 +15886,7 @@ function runPs(args) {
|
|
|
15670
15886
|
return new Promise((resolve, reject) => {
|
|
15671
15887
|
execFile3("/bin/ps", args, {
|
|
15672
15888
|
maxBuffer: 1024 * 1024,
|
|
15673
|
-
env: { ...
|
|
15889
|
+
env: { ...runtimeEnvironmentSnapshot(), LC_ALL: "C", LANG: "C", TZ: process.env.TZ }
|
|
15674
15890
|
}, (error, stdout) => {
|
|
15675
15891
|
if (error)
|
|
15676
15892
|
reject(error);
|
|
@@ -15816,6 +16032,20 @@ function sleep(ms) {
|
|
|
15816
16032
|
timer.unref?.();
|
|
15817
16033
|
});
|
|
15818
16034
|
}
|
|
16035
|
+
function sleepUnlessAborted(ms, signal) {
|
|
16036
|
+
if (signal.aborted)
|
|
16037
|
+
return Promise.resolve();
|
|
16038
|
+
return new Promise((resolve) => {
|
|
16039
|
+
const wake = () => {
|
|
16040
|
+
clearTimeout(timer);
|
|
16041
|
+
signal.removeEventListener("abort", wake);
|
|
16042
|
+
resolve();
|
|
16043
|
+
};
|
|
16044
|
+
const timer = setTimeout(wake, ms);
|
|
16045
|
+
timer.unref?.();
|
|
16046
|
+
signal.addEventListener("abort", wake, { once: true });
|
|
16047
|
+
});
|
|
16048
|
+
}
|
|
15819
16049
|
|
|
15820
16050
|
// ../../bridges/codex-bridge/src/app-server/approvals.ts
|
|
15821
16051
|
var MAX_APPROVAL_AMENDMENTS = 16;
|
|
@@ -17336,10 +17566,10 @@ function redactSecrets(value) {
|
|
|
17336
17566
|
|
|
17337
17567
|
// ../../bridges/codex-bridge/src/sessions/dispatch-journal.ts
|
|
17338
17568
|
import { mkdir as mkdir7, open as open4, rename as rename5, rm as rm7, writeFile as writeFile5 } from "node:fs/promises";
|
|
17339
|
-
import { join as
|
|
17569
|
+
import { join as join14 } from "node:path";
|
|
17340
17570
|
|
|
17341
17571
|
// ../../bridges/codex-bridge/src/sessions/persistence.ts
|
|
17342
|
-
import { createHash as createHash8, randomUUID as
|
|
17572
|
+
import { createHash as createHash8, randomUUID as randomUUID6 } from "node:crypto";
|
|
17343
17573
|
import {
|
|
17344
17574
|
chmod,
|
|
17345
17575
|
link as link2,
|
|
@@ -17351,7 +17581,7 @@ import {
|
|
|
17351
17581
|
stat as stat6,
|
|
17352
17582
|
writeFile as writeFile4
|
|
17353
17583
|
} from "node:fs/promises";
|
|
17354
|
-
import { join as
|
|
17584
|
+
import { join as join13 } from "node:path";
|
|
17355
17585
|
var BRIDGE_SESSION_REGISTRY_VERSION = 2;
|
|
17356
17586
|
var SESSION_TITLE_SOURCES = new Set([
|
|
17357
17587
|
"codex",
|
|
@@ -17453,19 +17683,23 @@ class BridgeSessionStore {
|
|
|
17453
17683
|
this.now = options.now ?? Date.now;
|
|
17454
17684
|
}
|
|
17455
17685
|
dir() {
|
|
17456
|
-
return
|
|
17686
|
+
return codexBridgeStateDir(this.codexHome);
|
|
17457
17687
|
}
|
|
17458
17688
|
path() {
|
|
17459
|
-
return
|
|
17689
|
+
return join13(this.dir(), `bridge-sessions-${this.cwdHash}.json`);
|
|
17460
17690
|
}
|
|
17461
17691
|
recordsDir() {
|
|
17462
|
-
return
|
|
17692
|
+
return join13(this.dir(), `bridge-sessions-${this.cwdHash}`);
|
|
17693
|
+
}
|
|
17694
|
+
loginRecordsDir() {
|
|
17695
|
+
const directory = join13(codexLoginBridgeDir(this.codexHome), `bridge-sessions-${this.cwdHash}`);
|
|
17696
|
+
return directory === this.recordsDir() ? undefined : directory;
|
|
17463
17697
|
}
|
|
17464
17698
|
recordKey(bridgeSessionId) {
|
|
17465
17699
|
return createHash8("sha256").update(bridgeSessionId).digest("hex");
|
|
17466
17700
|
}
|
|
17467
17701
|
recordPath(bridgeSessionId) {
|
|
17468
|
-
return
|
|
17702
|
+
return join13(this.recordsDir(), `${this.recordKey(bridgeSessionId)}.json`);
|
|
17469
17703
|
}
|
|
17470
17704
|
async ensurePrivateStorage() {
|
|
17471
17705
|
await mkdir6(this.dir(), { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
|
|
@@ -17484,6 +17718,7 @@ class BridgeSessionStore {
|
|
|
17484
17718
|
migrationFailed = true;
|
|
17485
17719
|
this.warnPersistenceFailure(error);
|
|
17486
17720
|
});
|
|
17721
|
+
await this.adoptLoginRecords().catch((error) => this.warnPersistenceFailure(error));
|
|
17487
17722
|
let names;
|
|
17488
17723
|
try {
|
|
17489
17724
|
await this.ensurePrivateStorage();
|
|
@@ -17492,7 +17727,7 @@ class BridgeSessionStore {
|
|
|
17492
17727
|
return legacy;
|
|
17493
17728
|
}
|
|
17494
17729
|
const records = await Promise.all(names.map(async (name) => {
|
|
17495
|
-
const path =
|
|
17730
|
+
const path = join13(this.recordsDir(), name);
|
|
17496
17731
|
if (name.endsWith(".tmp")) {
|
|
17497
17732
|
await chmod(path, PRIVATE_FILE_MODE).catch(() => {
|
|
17498
17733
|
return;
|
|
@@ -17575,7 +17810,7 @@ class BridgeSessionStore {
|
|
|
17575
17810
|
await this.ensurePrivateStorage();
|
|
17576
17811
|
await Promise.all(sessions.map(async (session) => {
|
|
17577
17812
|
const target = this.recordPath(session.bridgeSessionId);
|
|
17578
|
-
const temporary = `${target}.${process.pid}.${
|
|
17813
|
+
const temporary = `${target}.${process.pid}.${randomUUID6()}.tmp`;
|
|
17579
17814
|
await writeFile4(temporary, `${JSON.stringify(session, null, 2)}
|
|
17580
17815
|
`, {
|
|
17581
17816
|
encoding: "utf8",
|
|
@@ -17595,13 +17830,43 @@ class BridgeSessionStore {
|
|
|
17595
17830
|
return;
|
|
17596
17831
|
});
|
|
17597
17832
|
}
|
|
17833
|
+
async adoptLoginRecords() {
|
|
17834
|
+
const source = this.loginRecordsDir();
|
|
17835
|
+
if (!source)
|
|
17836
|
+
return;
|
|
17837
|
+
const names = (await readdir2(source).catch(() => [])).filter((name) => name.endsWith(".json"));
|
|
17838
|
+
if (names.length === 0)
|
|
17839
|
+
return;
|
|
17840
|
+
await this.ensurePrivateStorage();
|
|
17841
|
+
await Promise.all(names.map(async (name) => {
|
|
17842
|
+
const from = join13(source, name);
|
|
17843
|
+
const target = join13(this.recordsDir(), name);
|
|
17844
|
+
const temporary = `${target}.${process.pid}.${randomUUID6()}.tmp`;
|
|
17845
|
+
await writeFile4(temporary, await readFile6(from), { mode: PRIVATE_FILE_MODE });
|
|
17846
|
+
await chmod(temporary, PRIVATE_FILE_MODE);
|
|
17847
|
+
try {
|
|
17848
|
+
await link2(temporary, target).catch((error) => {
|
|
17849
|
+
if (error.code !== "EEXIST")
|
|
17850
|
+
throw error;
|
|
17851
|
+
});
|
|
17852
|
+
} finally {
|
|
17853
|
+
await rm6(temporary, { force: true }).catch(() => {
|
|
17854
|
+
return;
|
|
17855
|
+
});
|
|
17856
|
+
}
|
|
17857
|
+
await chmod(target, PRIVATE_FILE_MODE);
|
|
17858
|
+
await rm6(from, { force: true }).catch(() => {
|
|
17859
|
+
return;
|
|
17860
|
+
});
|
|
17861
|
+
}));
|
|
17862
|
+
}
|
|
17598
17863
|
async writeRecordAtomic(session) {
|
|
17599
17864
|
await this.ensurePrivateStorage();
|
|
17600
17865
|
await this.writeAtomicPath(this.recordPath(session.bridgeSessionId), `${JSON.stringify(session, null, 2)}
|
|
17601
17866
|
`);
|
|
17602
17867
|
}
|
|
17603
17868
|
async writeAtomicPath(path, payload) {
|
|
17604
|
-
const temporary = `${path}.${process.pid}.${
|
|
17869
|
+
const temporary = `${path}.${process.pid}.${randomUUID6()}.tmp`;
|
|
17605
17870
|
await writeFile4(temporary, payload, {
|
|
17606
17871
|
encoding: "utf8",
|
|
17607
17872
|
mode: PRIVATE_FILE_MODE
|
|
@@ -17693,6 +17958,9 @@ function isPersistedRecord(value) {
|
|
|
17693
17958
|
}
|
|
17694
17959
|
return (record.threadId === null || record.threadId.length > 0) && record.turnId === undefined && record.terminalStatus === undefined;
|
|
17695
17960
|
}
|
|
17961
|
+
function sameDispatchIdentity(left, right) {
|
|
17962
|
+
return left.bridgeSessionId === right.bridgeSessionId && left.threadId === right.threadId && left.turnId === right.turnId && left.state === right.state && left.terminalStatus === right.terminalStatus && left.quarantined === right.quarantined;
|
|
17963
|
+
}
|
|
17696
17964
|
|
|
17697
17965
|
class DispatchJournal {
|
|
17698
17966
|
records = new Map;
|
|
@@ -17718,7 +17986,7 @@ class DispatchJournal {
|
|
|
17718
17986
|
this.persist = options.persist !== false;
|
|
17719
17987
|
}
|
|
17720
17988
|
path() {
|
|
17721
|
-
return
|
|
17989
|
+
return join14(codexBridgeStateDir(this.codexHome), `dispatch-journal-${this.cwdHash}.json`);
|
|
17722
17990
|
}
|
|
17723
17991
|
async load() {
|
|
17724
17992
|
if (this.loaded)
|
|
@@ -17726,46 +17994,71 @@ class DispatchJournal {
|
|
|
17726
17994
|
this.loaded = true;
|
|
17727
17995
|
if (!this.persist)
|
|
17728
17996
|
return;
|
|
17997
|
+
const legacy = join14(codexLoginBridgeDir(this.codexHome), `dispatch-journal-${this.cwdHash}.json`);
|
|
17729
17998
|
try {
|
|
17730
|
-
|
|
17731
|
-
if (
|
|
17732
|
-
this.
|
|
17733
|
-
|
|
17734
|
-
|
|
17735
|
-
|
|
17736
|
-
|
|
17737
|
-
|
|
17738
|
-
if (!requestId)
|
|
17739
|
-
continue;
|
|
17740
|
-
const sequence = Number.isSafeInteger(candidate?.sequence) && Number(candidate?.sequence) > 0 ? Number(candidate.sequence) : this.nextSequence + 1;
|
|
17741
|
-
this.nextSequence = Math.max(this.nextSequence, sequence);
|
|
17742
|
-
const timestamp = new Date(this.now()).toISOString();
|
|
17743
|
-
const record = isPersistedRecord(persisted) ? { ...persisted, sequence } : {
|
|
17744
|
-
requestId,
|
|
17745
|
-
bridgeSessionId: typeof candidate?.bridgeSessionId === "string" ? candidate.bridgeSessionId : "",
|
|
17746
|
-
threadId: typeof candidate?.threadId === "string" || candidate?.threadId === null ? candidate.threadId : null,
|
|
17747
|
-
state: "terminal",
|
|
17748
|
-
terminalStatus: "failed",
|
|
17749
|
-
quarantined: true,
|
|
17750
|
-
createdAt: timestamp,
|
|
17751
|
-
updatedAt: timestamp,
|
|
17752
|
-
sequence
|
|
17753
|
-
};
|
|
17754
|
-
const existing = this.records.get(requestId);
|
|
17755
|
-
if (!existing || compareDispatchRecordsNewestFirst(record, existing) < 0) {
|
|
17756
|
-
this.records.set(requestId, record);
|
|
17757
|
-
}
|
|
17999
|
+
await this.loadPath(this.path());
|
|
18000
|
+
if (legacy !== this.path() && await this.loadPath(legacy, true)) {
|
|
18001
|
+
this.collectGarbage();
|
|
18002
|
+
this.refreshCapacityError();
|
|
18003
|
+
if (this.capacityError)
|
|
18004
|
+
throw new DispatchJournalCapacityError(this.capacityError);
|
|
18005
|
+
await this.flush({ failClosed: true });
|
|
18006
|
+
await rm7(legacy);
|
|
17758
18007
|
}
|
|
17759
18008
|
this.collectGarbage();
|
|
17760
18009
|
this.refreshCapacityError();
|
|
17761
18010
|
} catch (error) {
|
|
17762
|
-
if (error?.code === "ENOENT")
|
|
17763
|
-
return;
|
|
17764
18011
|
this.integrityError = error instanceof DispatchJournalIntegrityError ? error.message : "Dispatch journal could not be safely decoded";
|
|
17765
18012
|
}
|
|
17766
18013
|
}
|
|
17767
|
-
async
|
|
17768
|
-
|
|
18014
|
+
async loadPath(path, merging = false) {
|
|
18015
|
+
let contents;
|
|
18016
|
+
try {
|
|
18017
|
+
contents = await this.readBounded(path);
|
|
18018
|
+
} catch (error) {
|
|
18019
|
+
if (error?.code === "ENOENT")
|
|
18020
|
+
return false;
|
|
18021
|
+
throw error;
|
|
18022
|
+
}
|
|
18023
|
+
const parsed = JSON.parse(contents);
|
|
18024
|
+
if (parsed.version !== DISPATCH_JOURNAL_VERSION || !Array.isArray(parsed.records)) {
|
|
18025
|
+
throw new DispatchJournalIntegrityError("Dispatch journal has an unsupported or malformed file shape");
|
|
18026
|
+
}
|
|
18027
|
+
for (const persisted of parsed.records) {
|
|
18028
|
+
const candidate = persisted && typeof persisted === "object" ? persisted : undefined;
|
|
18029
|
+
const requestId = typeof candidate?.requestId === "string" ? candidate.requestId : "";
|
|
18030
|
+
if (!requestId)
|
|
18031
|
+
continue;
|
|
18032
|
+
const sequence = Number.isSafeInteger(candidate?.sequence) && Number(candidate?.sequence) > 0 ? Number(candidate.sequence) : this.nextSequence + 1;
|
|
18033
|
+
this.nextSequence = Math.max(this.nextSequence, sequence);
|
|
18034
|
+
const timestamp = new Date(this.now()).toISOString();
|
|
18035
|
+
const record = isPersistedRecord(persisted) ? { ...persisted, sequence } : {
|
|
18036
|
+
requestId,
|
|
18037
|
+
bridgeSessionId: typeof candidate?.bridgeSessionId === "string" ? candidate.bridgeSessionId : "",
|
|
18038
|
+
threadId: typeof candidate?.threadId === "string" || candidate?.threadId === null ? candidate.threadId : null,
|
|
18039
|
+
state: "terminal",
|
|
18040
|
+
terminalStatus: "failed",
|
|
18041
|
+
quarantined: true,
|
|
18042
|
+
createdAt: timestamp,
|
|
18043
|
+
updatedAt: timestamp,
|
|
18044
|
+
sequence
|
|
18045
|
+
};
|
|
18046
|
+
const existing = this.records.get(requestId);
|
|
18047
|
+
if (merging && existing && !sameDispatchIdentity(existing, record)) {
|
|
18048
|
+
this.records.set(requestId, {
|
|
18049
|
+
...existing,
|
|
18050
|
+
state: "terminal",
|
|
18051
|
+
terminalStatus: "failed",
|
|
18052
|
+
quarantined: true
|
|
18053
|
+
});
|
|
18054
|
+
} else if (!existing || !merging && compareDispatchRecordsNewestFirst(record, existing) < 0) {
|
|
18055
|
+
this.records.set(requestId, record);
|
|
18056
|
+
}
|
|
18057
|
+
}
|
|
18058
|
+
return true;
|
|
18059
|
+
}
|
|
18060
|
+
async readBounded(path) {
|
|
18061
|
+
const handle = await open4(path, "r");
|
|
17769
18062
|
try {
|
|
17770
18063
|
const metadata = await handle.stat();
|
|
17771
18064
|
if (!metadata.isFile() || metadata.size > this.maxBytes) {
|
|
@@ -17789,6 +18082,9 @@ class DispatchJournal {
|
|
|
17789
18082
|
}
|
|
17790
18083
|
classify(requestId) {
|
|
17791
18084
|
const record = this.records.get(requestId);
|
|
18085
|
+
if (this.integrityError) {
|
|
18086
|
+
return { duplicate: Boolean(record), action: "blocked", reason: this.integrityError, record };
|
|
18087
|
+
}
|
|
17792
18088
|
if (!record) {
|
|
17793
18089
|
const blockedReason = this.integrityError ?? this.capacityError;
|
|
17794
18090
|
if (blockedReason) {
|
|
@@ -17900,6 +18196,13 @@ class DispatchJournal {
|
|
|
17900
18196
|
latestForSession(bridgeSessionId) {
|
|
17901
18197
|
return [...this.records.values()].filter((record) => record.bridgeSessionId === bridgeSessionId).sort(compareDispatchRecordsNewestFirst)[0];
|
|
17902
18198
|
}
|
|
18199
|
+
requestIdForTurn(turnId) {
|
|
18200
|
+
for (const record of this.records.values()) {
|
|
18201
|
+
if (record.turnId === turnId && !record.quarantined)
|
|
18202
|
+
return record.requestId;
|
|
18203
|
+
}
|
|
18204
|
+
return;
|
|
18205
|
+
}
|
|
17903
18206
|
async forget(requestId) {
|
|
17904
18207
|
if (this.integrityError)
|
|
17905
18208
|
throw new DispatchJournalIntegrityError(this.integrityError);
|
|
@@ -17995,7 +18298,7 @@ class DispatchJournal {
|
|
|
17995
18298
|
const attempt = this.writeChain.then(async () => {
|
|
17996
18299
|
try {
|
|
17997
18300
|
const path = this.path();
|
|
17998
|
-
await mkdir7(
|
|
18301
|
+
await mkdir7(codexBridgeStateDir(this.codexHome), { recursive: true });
|
|
17999
18302
|
const temporary = `${path}.${process.pid}.${Math.random().toString(36).slice(2, 8)}.tmp`;
|
|
18000
18303
|
await writeFile5(temporary, `${JSON.stringify(snapshot, null, 2)}
|
|
18001
18304
|
`, "utf8");
|
|
@@ -18123,7 +18426,7 @@ function coordinatorCapabilityPolicy(mode) {
|
|
|
18123
18426
|
|
|
18124
18427
|
// ../../bridges/codex-bridge/src/codex-config.ts
|
|
18125
18428
|
import { realpathSync } from "node:fs";
|
|
18126
|
-
import { isAbsolute as
|
|
18429
|
+
import { isAbsolute as isAbsolute7 } from "node:path";
|
|
18127
18430
|
var CODEX_MAX_CONCURRENT_THREADS_ENV = "CODEX_MAX_CONCURRENT_THREADS_PER_SESSION";
|
|
18128
18431
|
var DEFAULT_CODEX_MAX_CONCURRENT_THREADS = 5;
|
|
18129
18432
|
var ORKESTRATOR_AGENT_MCP_URL_ENV = "ORKESTRATOR_AGENT_MCP_URL";
|
|
@@ -18143,7 +18446,7 @@ function codexNetworkDeniedConfig(policy) {
|
|
|
18143
18446
|
};
|
|
18144
18447
|
}
|
|
18145
18448
|
function codexProjectTrustConfig(policy, cwd) {
|
|
18146
|
-
if (!policy || policy.projectResources || !cwd || !
|
|
18449
|
+
if (!policy || policy.projectResources || !cwd || !isAbsolute7(cwd))
|
|
18147
18450
|
return {};
|
|
18148
18451
|
const roots = new Set([cwd]);
|
|
18149
18452
|
try {
|
|
@@ -18153,6 +18456,11 @@ function codexProjectTrustConfig(policy, cwd) {
|
|
|
18153
18456
|
projects: Object.fromEntries([...roots].map((root) => [root, { trust_level: "untrusted" }]))
|
|
18154
18457
|
};
|
|
18155
18458
|
}
|
|
18459
|
+
function codexRequestUserInputConfig(policy) {
|
|
18460
|
+
if (!policy || policy.id === "pipeline")
|
|
18461
|
+
return {};
|
|
18462
|
+
return { "features.default_mode_request_user_input": true };
|
|
18463
|
+
}
|
|
18156
18464
|
var MAX_CODEX_DISABLED_SKILLS = 1024;
|
|
18157
18465
|
var KEPT_SKILL_SCOPES = new Set(["user", "system", "admin"]);
|
|
18158
18466
|
function codexProjectSkillsConfig(listed) {
|
|
@@ -18166,7 +18474,7 @@ function codexProjectSkillsConfig(listed) {
|
|
|
18166
18474
|
const { path, scope, enabled } = skill ?? {};
|
|
18167
18475
|
if (enabled === true && typeof scope === "string" && KEPT_SKILL_SCOPES.has(scope))
|
|
18168
18476
|
continue;
|
|
18169
|
-
if (typeof path !== "string" || !
|
|
18477
|
+
if (typeof path !== "string" || !isAbsolute7(path)) {
|
|
18170
18478
|
throw new Error("Codex listed a project skill without a path it can be disabled by");
|
|
18171
18479
|
}
|
|
18172
18480
|
disabled.add(path);
|
|
@@ -18251,11 +18559,11 @@ function codexAppServerConfigOverrides(env = process.env) {
|
|
|
18251
18559
|
const readableRuntimeRoot = env.CODEX_BRIDGE_READABLE_RUNTIME_ROOT?.trim();
|
|
18252
18560
|
const projectRoot = env.CWD?.trim();
|
|
18253
18561
|
const attachmentRoot = env[BRIDGE_ATTACHMENT_ROOT_ENV]?.trim();
|
|
18254
|
-
if (!permissionProfile || !/^[A-Za-z0-9_-]+$/.test(permissionProfile) || !readableRuntimeRoot || !
|
|
18562
|
+
if (!permissionProfile || !/^[A-Za-z0-9_-]+$/.test(permissionProfile) || !readableRuntimeRoot || !isAbsolute7(readableRuntimeRoot) || !projectRoot || !isAbsolute7(projectRoot)) {
|
|
18255
18563
|
throw new Error("Coordinator Codex permission profile configuration is invalid");
|
|
18256
18564
|
}
|
|
18257
18565
|
overrides.default_permissions = JSON.stringify(permissionProfile);
|
|
18258
|
-
overrides[`permissions.${permissionProfile}.filesystem`] = `{ ":root" = "deny", ":minimal" = "read", ":tmpdir" = "deny", ` + `":slash_tmp" = "deny", ${JSON.stringify(readableRuntimeRoot)} = "read", ` + (attachmentRoot &&
|
|
18566
|
+
overrides[`permissions.${permissionProfile}.filesystem`] = `{ ":root" = "deny", ":minimal" = "read", ":tmpdir" = "deny", ` + `":slash_tmp" = "deny", ${JSON.stringify(readableRuntimeRoot)} = "read", ` + (attachmentRoot && isAbsolute7(attachmentRoot) ? `${JSON.stringify(attachmentRoot)} = "read", ` : "") + `":workspace_roots" = { "." = "read" } }`;
|
|
18259
18567
|
overrides[`permissions.${permissionProfile}.network.enabled`] = "false";
|
|
18260
18568
|
overrides.web_search = JSON.stringify(codexNetworkDeniedSearchMode(codexCoordinatorPolicy(env)));
|
|
18261
18569
|
overrides["features.standalone_web_search"] = "false";
|
|
@@ -18841,7 +19149,7 @@ function signedOutAccountRead(error) {
|
|
|
18841
19149
|
}
|
|
18842
19150
|
async function readStoredLoginFingerprint(codexHome) {
|
|
18843
19151
|
try {
|
|
18844
|
-
const file = await open6(
|
|
19152
|
+
const file = await open6(join15(codexHome, "auth.json"), "r");
|
|
18845
19153
|
let raw;
|
|
18846
19154
|
try {
|
|
18847
19155
|
const bytes = Buffer.alloc(65537);
|
|
@@ -19119,6 +19427,9 @@ class AppServerEngine {
|
|
|
19119
19427
|
this.invalidateAccountServing(sequence);
|
|
19120
19428
|
this.checkAccountSignIn(true);
|
|
19121
19429
|
}
|
|
19430
|
+
if (notification.method === "account/login/completed" && objectRecord(notification.params).success === true) {
|
|
19431
|
+
this.emit({ kind: "account.signedIn", engineGeneration: generation });
|
|
19432
|
+
}
|
|
19122
19433
|
const result = reduceNotification(notification, generation);
|
|
19123
19434
|
if (result.unknownMethod) {
|
|
19124
19435
|
this.unknownNotificationCount += 1;
|
|
@@ -19185,7 +19496,11 @@ class AppServerEngine {
|
|
|
19185
19496
|
if (sequence < this.accountAppliedSequence || generation !== this.supervisor.getGeneration())
|
|
19186
19497
|
return;
|
|
19187
19498
|
this.accountAppliedSequence = sequence;
|
|
19499
|
+
const wasSignInRequired = this.accountSignInRequired;
|
|
19188
19500
|
const signedIn = this.recordAccount(response);
|
|
19501
|
+
if (signedIn && wasSignInRequired) {
|
|
19502
|
+
this.emit({ kind: "account.signedIn", engineGeneration: generation });
|
|
19503
|
+
}
|
|
19189
19504
|
if (!signedIn) {
|
|
19190
19505
|
await this.requestAccountReloadFromStoredLogin(sequence, generation);
|
|
19191
19506
|
return;
|
|
@@ -19344,6 +19659,7 @@ class AppServerEngine {
|
|
|
19344
19659
|
const threadConfig = {
|
|
19345
19660
|
...codexNetworkDeniedConfig(config.policy),
|
|
19346
19661
|
...codexProjectTrustConfig(config.policy, cwd),
|
|
19662
|
+
...codexRequestUserInputConfig(config.policy),
|
|
19347
19663
|
...extraConfig,
|
|
19348
19664
|
...config.agentMcp ? {
|
|
19349
19665
|
...config.agentMcp.design ? {
|
|
@@ -19380,7 +19696,6 @@ class AppServerEngine {
|
|
|
19380
19696
|
sandbox: config.sandbox ?? (config.mode === "plan" ? "read-only" : "danger-full-access")
|
|
19381
19697
|
},
|
|
19382
19698
|
...config.model ? { model: config.model } : {},
|
|
19383
|
-
...config.personality ? { personality: config.personality } : {},
|
|
19384
19699
|
serviceTier: config.serviceTier ?? null,
|
|
19385
19700
|
...Object.keys(threadConfig).length > 0 ? { config: threadConfig } : {}
|
|
19386
19701
|
};
|
|
@@ -19798,7 +20113,7 @@ class AppServerEngine {
|
|
|
19798
20113
|
thread.model = confirmedModel.trim();
|
|
19799
20114
|
}
|
|
19800
20115
|
if (thread.id) {
|
|
19801
|
-
if (typeof raw.path === "string" &&
|
|
20116
|
+
if (typeof raw.path === "string" && isAbsolute8(raw.path)) {
|
|
19802
20117
|
this.rolloutPaths.set(thread.id, raw.path);
|
|
19803
20118
|
}
|
|
19804
20119
|
this.bindings.set(thread.id, {
|
|
@@ -19913,8 +20228,6 @@ class AppServerEngine {
|
|
|
19913
20228
|
...options.config.model ? { model: options.config.model } : {},
|
|
19914
20229
|
...options.config.serviceTier !== undefined ? { serviceTier: options.config.serviceTier } : {},
|
|
19915
20230
|
...options.config.reasoningEffort ? { effort: options.config.reasoningEffort } : {},
|
|
19916
|
-
...options.config.reasoningSummary ? { summary: options.config.reasoningSummary } : {},
|
|
19917
|
-
...options.config.personality ? { personality: options.config.personality } : {},
|
|
19918
20231
|
...options.config.permissionProfile ? {} : { sandboxPolicy: toSandboxPolicy(options.config) }
|
|
19919
20232
|
};
|
|
19920
20233
|
const { result, generation } = await this.supervisor.requestWithGeneration("turn/start", params);
|
|
@@ -20406,7 +20719,7 @@ class ThreadRegistry {
|
|
|
20406
20719
|
|
|
20407
20720
|
// ../../bridges/codex-bridge/src/app-server-runtime-sessions.ts
|
|
20408
20721
|
var SESSION_CLOSING_ERROR = "Session is closing";
|
|
20409
|
-
var ACTIVITY_PROCESS =
|
|
20722
|
+
var ACTIVITY_PROCESS = randomUUID7();
|
|
20410
20723
|
|
|
20411
20724
|
class CodexRuntimeSessions {
|
|
20412
20725
|
ctx;
|
|
@@ -21213,6 +21526,7 @@ class CodexRuntimeSessions {
|
|
|
21213
21526
|
const awaitingRecovery = session.threadId !== null && this.ctx.threadsAwaitingDispatchRecovery.has(session.threadId);
|
|
21214
21527
|
const phase = context?.phase ?? (awaitingRecovery ? "recovering" : session.restartFailure ? "failed" : "idle");
|
|
21215
21528
|
const latestDispatch = this.ctx.journal.latestForSession(sessionId);
|
|
21529
|
+
const interruptedRequestId = session.restartFailure ? this.ctx.journal.requestIdForTurn(session.restartFailure.turnId) : undefined;
|
|
21216
21530
|
const error = context?.error ?? (phase === "failed" && session.restartFailure ? CODEX_RESTARTED_MID_TURN_MESSAGE : undefined);
|
|
21217
21531
|
return {
|
|
21218
21532
|
status: phaseToExternalStatus(phase),
|
|
@@ -21220,7 +21534,10 @@ class CodexRuntimeSessions {
|
|
|
21220
21534
|
phase,
|
|
21221
21535
|
title: session.title,
|
|
21222
21536
|
error,
|
|
21223
|
-
...phase === "failed" && session.restartFailure && error === CODEX_RESTARTED_MID_TURN_MESSAGE ? {
|
|
21537
|
+
...phase === "failed" && session.restartFailure && error === CODEX_RESTARTED_MID_TURN_MESSAGE ? {
|
|
21538
|
+
interruption: "restart",
|
|
21539
|
+
...interruptedRequestId ? { interruptedRequestId } : {}
|
|
21540
|
+
} : {},
|
|
21224
21541
|
threadId: session.threadId,
|
|
21225
21542
|
turnId: context?.activeTurn?.turnId,
|
|
21226
21543
|
turnStartedAt: context?.turnStartedAt,
|
|
@@ -21761,7 +22078,7 @@ function parseCommandToken(text, sigils = ["/"]) {
|
|
|
21761
22078
|
// ../../bridges/codex-bridge/src/prompts/template-discovery.ts
|
|
21762
22079
|
import { createHash as createHash11 } from "node:crypto";
|
|
21763
22080
|
import { open as open7, readdir as readdir3, stat as stat7 } from "node:fs/promises";
|
|
21764
|
-
import { join as
|
|
22081
|
+
import { join as join16 } from "node:path";
|
|
21765
22082
|
|
|
21766
22083
|
// ../../bridges/codex-bridge/src/prompts/template-format.ts
|
|
21767
22084
|
var TEMPLATE_DESCRIPTION_MAX_BYTES = 1000;
|
|
@@ -21889,8 +22206,8 @@ var RESERVED_TEMPLATE_PREFIXES = ["/skill:", "/prompts:"];
|
|
|
21889
22206
|
var TEMPLATE_ID_PREFIX = "codex-template:";
|
|
21890
22207
|
function templateRoots(cwd, codexHome = getCodexHomeDir()) {
|
|
21891
22208
|
return [
|
|
21892
|
-
{ origin: "project", dir:
|
|
21893
|
-
{ origin: "user", dir:
|
|
22209
|
+
{ origin: "project", dir: join16(cwd, ".codex", "prompts") },
|
|
22210
|
+
{ origin: "user", dir: join16(codexHome, "prompts") }
|
|
21894
22211
|
];
|
|
21895
22212
|
}
|
|
21896
22213
|
function templateCommandId(origin, relativePath) {
|
|
@@ -21914,7 +22231,7 @@ function isReservedName(name) {
|
|
|
21914
22231
|
}
|
|
21915
22232
|
var metadataCache = new Map;
|
|
21916
22233
|
var METADATA_CACHE_MAX = 1024;
|
|
21917
|
-
async function
|
|
22234
|
+
async function readBounded2(absolutePath, maxBytes) {
|
|
21918
22235
|
const handle = await open7(absolutePath, "r");
|
|
21919
22236
|
try {
|
|
21920
22237
|
const info = await handle.stat();
|
|
@@ -21995,7 +22312,7 @@ async function scanPromptTemplates(roots, limits = TEMPLATE_LIMITS) {
|
|
|
21995
22312
|
return;
|
|
21996
22313
|
}
|
|
21997
22314
|
visited += 1;
|
|
21998
|
-
const absolutePath =
|
|
22315
|
+
const absolutePath = join16(dir, entry.name);
|
|
21999
22316
|
const relativePath = relative ? `${relative}/${entry.name}` : entry.name;
|
|
22000
22317
|
if (entry.isDirectory()) {
|
|
22001
22318
|
if (depth + 1 > limits.maxDepth) {
|
|
@@ -22057,7 +22374,7 @@ async function scanPromptTemplates(roots, limits = TEMPLATE_LIMITS) {
|
|
|
22057
22374
|
if (candidate.size > limits.maxTemplateBytes)
|
|
22058
22375
|
return null;
|
|
22059
22376
|
try {
|
|
22060
|
-
const { bytes, oversized } = await
|
|
22377
|
+
const { bytes, oversized } = await readBounded2(candidate.absolutePath, limits.maxTemplateBytes);
|
|
22061
22378
|
if (oversized)
|
|
22062
22379
|
return null;
|
|
22063
22380
|
if (bytes.length === 0)
|
|
@@ -22134,7 +22451,7 @@ async function loadTemplateBody(entry, limits = TEMPLATE_LIMITS) {
|
|
|
22134
22451
|
}
|
|
22135
22452
|
let loaded;
|
|
22136
22453
|
try {
|
|
22137
|
-
loaded = await
|
|
22454
|
+
loaded = await readBounded2(entry.absolutePath, limits.maxTemplateBytes);
|
|
22138
22455
|
} catch {
|
|
22139
22456
|
return {
|
|
22140
22457
|
ok: false,
|
|
@@ -22162,7 +22479,7 @@ async function loadTemplateBody(entry, limits = TEMPLATE_LIMITS) {
|
|
|
22162
22479
|
}
|
|
22163
22480
|
|
|
22164
22481
|
// ../../bridges/codex-bridge/src/commands/skill-inventory.ts
|
|
22165
|
-
import { isAbsolute as
|
|
22482
|
+
import { isAbsolute as isAbsolute9 } from "node:path";
|
|
22166
22483
|
var SKILL_INVENTORY_LIMITS = Object.freeze({
|
|
22167
22484
|
maxSkills: 512,
|
|
22168
22485
|
maxDescriptionBytes: 1000,
|
|
@@ -22214,7 +22531,7 @@ function normalizeSkillsList(raw, context) {
|
|
|
22214
22531
|
}
|
|
22215
22532
|
const name = nonEmpty(candidate.name);
|
|
22216
22533
|
const path = typeof candidate.path === "string" ? candidate.path : undefined;
|
|
22217
|
-
if (!name || !usableSkillName(name) || !path || !
|
|
22534
|
+
if (!name || !usableSkillName(name) || !path || !isAbsolute9(path)) {
|
|
22218
22535
|
truncated = true;
|
|
22219
22536
|
continue;
|
|
22220
22537
|
}
|
|
@@ -23593,6 +23910,12 @@ class CodexRuntimeLifecycle {
|
|
|
23593
23910
|
}
|
|
23594
23911
|
if (event.kind === "unknown.protocol")
|
|
23595
23912
|
return;
|
|
23913
|
+
if (event.kind === "account.signedIn") {
|
|
23914
|
+
for (const context of this.ctx.registry.listThreads()) {
|
|
23915
|
+
this.setThreadAuthNotice(context, undefined);
|
|
23916
|
+
}
|
|
23917
|
+
return;
|
|
23918
|
+
}
|
|
23596
23919
|
if (event.kind === "account.reload.requested") {
|
|
23597
23920
|
this.ctx.callbacks.reloadStoredAccountLogin().catch((error) => {
|
|
23598
23921
|
console.warn("[codex-bridge] Reloading the stored account login failed:", error instanceof Error ? error.message : error);
|
|
@@ -23878,8 +24201,11 @@ class CodexRuntimeLifecycle {
|
|
|
23878
24201
|
this.discardOutlivingCommandWindows(turn);
|
|
23879
24202
|
if (turn.stoppedByShutdown && event.status === "interrupted")
|
|
23880
24203
|
this.completeRecoveredTurn(turn, event.status);
|
|
23881
|
-
else
|
|
24204
|
+
else {
|
|
23882
24205
|
turn.complete(event.status, event.error);
|
|
24206
|
+
if (event.status === "failed" && event.error)
|
|
24207
|
+
turn.recordProviderFailure(event.error);
|
|
24208
|
+
}
|
|
23883
24209
|
this.ctx.options.changeEvidence?.turn(this.evidenceSource(context, turn), event.status);
|
|
23884
24210
|
const finalize = () => this.runFinalization(context, turn).catch((error) => {
|
|
23885
24211
|
console.error(`[codex-bridge] Failed to finalize turn ${turn.turnId}:`, error instanceof Error ? error.message : error);
|
|
@@ -24626,9 +24952,6 @@ class CodexRuntimeLifecycle {
|
|
|
24626
24952
|
const policy = coordinatorReadOnly ? codexCoordinatorPolicy() : requestedPolicy;
|
|
24627
24953
|
const model = typeof body.model === "string" && body.model.trim().length > 0 ? body.model.trim() : undefined;
|
|
24628
24954
|
const reasoningEffort = typeof body.modelReasoningEffort === "string" ? body.modelReasoningEffort : undefined;
|
|
24629
|
-
const rawParameters = body.parameterValues && typeof body.parameterValues === "object" && !Array.isArray(body.parameterValues) ? body.parameterValues : {};
|
|
24630
|
-
const reasoningSummary = ["auto", "concise", "detailed", "none"].includes(String(rawParameters.summary ?? "")) ? rawParameters.summary : undefined;
|
|
24631
|
-
const personality = ["none", "friendly", "pragmatic"].includes(String(rawParameters.personality ?? "")) ? rawParameters.personality : undefined;
|
|
24632
24955
|
const rawAgentMcp = body.agentMcp;
|
|
24633
24956
|
let agentMcp;
|
|
24634
24957
|
if (rawAgentMcp && typeof rawAgentMcp === "object" && !Array.isArray(rawAgentMcp)) {
|
|
@@ -24652,8 +24975,6 @@ class CodexRuntimeLifecycle {
|
|
|
24652
24975
|
mode,
|
|
24653
24976
|
model,
|
|
24654
24977
|
reasoningEffort,
|
|
24655
|
-
reasoningSummary,
|
|
24656
|
-
personality,
|
|
24657
24978
|
serviceTier: body.fastMode === true ? "fast" : null,
|
|
24658
24979
|
cwd: this.ctx.options.cwd,
|
|
24659
24980
|
approvalPolicy: policy?.approvals === "ask" ? "on-request" : policy?.approvals === "deny" ? "never" : "never",
|
|
@@ -26701,7 +27022,7 @@ async function writeCodexRawLog(sessionId, entry, logDir = codexRawLogDir) {
|
|
|
26701
27022
|
try {
|
|
26702
27023
|
await mkdir8(logDir, { recursive: true });
|
|
26703
27024
|
const filename = `${sanitizeLogFileComponent(sessionId)}.jsonl`;
|
|
26704
|
-
await appendFile5(
|
|
27025
|
+
await appendFile5(join17(logDir, filename), `${JSON.stringify({
|
|
26705
27026
|
timestamp: new Date().toISOString(),
|
|
26706
27027
|
sessionId,
|
|
26707
27028
|
...entry
|
|
@@ -26898,10 +27219,10 @@ function emit(event) {
|
|
|
26898
27219
|
}
|
|
26899
27220
|
}
|
|
26900
27221
|
function bridgeCacheDir() {
|
|
26901
|
-
return
|
|
27222
|
+
return join17(getCodexHomeDir(), "orkestrator-bridge");
|
|
26902
27223
|
}
|
|
26903
27224
|
function bridgeCachePath() {
|
|
26904
|
-
return
|
|
27225
|
+
return join17(bridgeCacheDir(), "models-cache.json");
|
|
26905
27226
|
}
|
|
26906
27227
|
var BRIDGE_MODEL_CACHE_VERSION = 2;
|
|
26907
27228
|
async function readPersistedBridgeCache() {
|
|
@@ -26925,7 +27246,7 @@ async function writePersistedBridgeCache(models) {
|
|
|
26925
27246
|
}
|
|
26926
27247
|
async function readCodexCliModelCache() {
|
|
26927
27248
|
try {
|
|
26928
|
-
const raw = await readFile7(
|
|
27249
|
+
const raw = await readFile7(join17(getCodexHomeDir(), "models_cache.json"), "utf8");
|
|
26929
27250
|
const models = parseModelCatalog(raw);
|
|
26930
27251
|
return models.length > 0 ? models : null;
|
|
26931
27252
|
} catch {
|
|
@@ -27358,7 +27679,10 @@ app.get("/session/:id/dispatch", (c) => {
|
|
|
27358
27679
|
return c.json({ dispatch: "unknown" });
|
|
27359
27680
|
const record = appServerRuntime.getJournal().get(requestId);
|
|
27360
27681
|
const dispatched = record?.bridgeSessionId === c.req.param("id") && (record.state === "accepted" || record.state === "terminal");
|
|
27361
|
-
return c.json({
|
|
27682
|
+
return c.json({
|
|
27683
|
+
dispatch: dispatched ? "dispatched" : "unknown",
|
|
27684
|
+
...dispatched ? { pending: record.state === "accepted" } : {}
|
|
27685
|
+
});
|
|
27362
27686
|
});
|
|
27363
27687
|
app.get("/session/:id/structured-output", (c) => {
|
|
27364
27688
|
const result = appServerRuntime.getStructuredOutput(c.req.param("id"), c.req.query("requestId")?.trim());
|
|
@@ -27678,7 +28002,7 @@ app.get("/session/:id/mcp", async (c) => {
|
|
|
27678
28002
|
...typeof server.pluginId === "string" ? { scope: "plugin" } : {},
|
|
27679
28003
|
toolCount: tools.length,
|
|
27680
28004
|
tools,
|
|
27681
|
-
...typeof server.error === "string" ? { error: server.error.slice(0, 1000) } : typeof server.toolsError === "string" ? { error: server.toolsError.slice(0, 1000) } : {},
|
|
28005
|
+
...typeof server.error === "string" ? { error: redactSecrets(server.error).slice(0, 1000) } : typeof server.toolsError === "string" ? { error: redactSecrets(server.toolsError).slice(0, 1000) } : {},
|
|
27682
28006
|
actions: status === "needs-auth" ? ["sign-in"] : ["reconnect"]
|
|
27683
28007
|
}
|
|
27684
28008
|
];
|