orkestrator 2.34.5-beta → 2.35.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/dist/client.js +65 -12
- package/dist/main.js +62570 -59725
- package/package.json +3 -3
- package/resources/acp-bridge/dist/index.js +108 -30
- package/resources/claude-bridge/dist/index.js +594 -303
- package/resources/codex-bridge/dist/index.js +188 -73
- package/resources/cursor-bridge/dist/index.js +227 -38
- package/resources/cursor-bridge/runtime/install.json +1 -1
- package/resources/pi-bridge/dist/index.js +49 -0
- package/resources/pi-bridge/runtime/install.json +1 -1
|
@@ -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 mkdir9, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
|
|
334
|
-
import { join as
|
|
334
|
+
import { join as join22 } 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
|
|
@@ -13147,6 +13147,7 @@ var COORDINATOR_CONTROL_TOOL_NAMES = Object.freeze([
|
|
|
13147
13147
|
"stop_node_environment",
|
|
13148
13148
|
"stop_worker_turn",
|
|
13149
13149
|
"switch_provider_account",
|
|
13150
|
+
"set_account_auto_switch",
|
|
13150
13151
|
"transfer_files",
|
|
13151
13152
|
"update_schedule",
|
|
13152
13153
|
"update_ticket"
|
|
@@ -15153,6 +15154,87 @@ function agentMailCapabilities(tabType, agent, locked = true) {
|
|
|
15153
15154
|
}
|
|
15154
15155
|
var NATIVE_AGENT_MAIL_CAPABILITIES = Object.freeze(Object.fromEntries(AGENT_PLATFORMS.map((agent) => [agent, agentMailCapabilities("agent-native", agent)])));
|
|
15155
15156
|
|
|
15157
|
+
// ../protocol/src/agent-system-instructions.ts
|
|
15158
|
+
var AGENT_IMAGE_PREVIEW_INSTRUCTION = "Orkestrator renders Markdown images inline in the transcript. When you show the user an image in your reply (a screenshot, rendered preview, or chart) using Markdown image syntax, reference it by its absolute path. In a managed worktree or container environment, save the file inside the working directory, preferably in a git-ignored folder so preview files stay out of the change set. Local image previews are limited to Orkestrator-managed workspace storage or the container's /workspace. Project-home checkouts are excluded from host preview reads, even when they are the working directory, so images saved there cannot be previewed from a local Markdown path. Paths outside previewable storage, such as /tmp, also show a placeholder.";
|
|
15159
|
+
var AGENT_DOCUMENT_INSTRUCTION = "When the user asks for a document (a report, design doc, plan, analysis, guide, or other writing to keep), prefer writing it as a Markdown file in a `docs/` folder at the root of the working directory, and tell the user the file's path. Project instructions (such as AGENTS.md or CLAUDE.md), local skills, and the user's own request take priority over this default when they say where or how to write documents.";
|
|
15160
|
+
var GENERAL_AGENT_INSTRUCTIONS = [
|
|
15161
|
+
AGENT_IMAGE_PREVIEW_INSTRUCTION,
|
|
15162
|
+
AGENT_DOCUMENT_INSTRUCTION
|
|
15163
|
+
];
|
|
15164
|
+
function agentSystemInstructions(providerSpecific = []) {
|
|
15165
|
+
return [...GENERAL_AGENT_INSTRUCTIONS, ...providerSpecific].filter((line) => line.trim().length > 0).join(`
|
|
15166
|
+
|
|
15167
|
+
`);
|
|
15168
|
+
}
|
|
15169
|
+
var REPOSITORY_INSTRUCTIONS_FILE = "AGENTS.md";
|
|
15170
|
+
function repositoryInstructionsBlock(path, content, truncated) {
|
|
15171
|
+
return [
|
|
15172
|
+
`# Repository instructions (${REPOSITORY_INSTRUCTIONS_FILE})`,
|
|
15173
|
+
`This session does not load the repository's ${REPOSITORY_INSTRUCTIONS_FILE} on its own, so Orkestrator includes it here. Follow it as project instructions. Contents of ${path}:`,
|
|
15174
|
+
content.trimEnd(),
|
|
15175
|
+
...truncated ? [
|
|
15176
|
+
`[${REPOSITORY_INSTRUCTIONS_FILE} is longer than this session can hold, so it is cut here. Read the rest from ${path} before relying on anything it may say.]`
|
|
15177
|
+
] : []
|
|
15178
|
+
].join(`
|
|
15179
|
+
|
|
15180
|
+
`);
|
|
15181
|
+
}
|
|
15182
|
+
|
|
15183
|
+
// ../protocol/src/node/repository-instructions.ts
|
|
15184
|
+
import { open as open4, realpath } from "node:fs/promises";
|
|
15185
|
+
import { join as join12, relative as relative2, isAbsolute as isAbsolute7 } from "node:path";
|
|
15186
|
+
var MAX_REPOSITORY_INSTRUCTIONS_BYTES = 256 * 1024;
|
|
15187
|
+
async function readRepositoryInstructions(cwd, maxBytes = MAX_REPOSITORY_INSTRUCTIONS_BYTES) {
|
|
15188
|
+
const path = join12(cwd, REPOSITORY_INSTRUCTIONS_FILE);
|
|
15189
|
+
try {
|
|
15190
|
+
const [root, target] = await Promise.all([realpath(cwd), realpath(path)]);
|
|
15191
|
+
const inside = relative2(root, target);
|
|
15192
|
+
if (!inside || inside.startsWith("..") || isAbsolute7(inside))
|
|
15193
|
+
return;
|
|
15194
|
+
const handle = await open4(target, "r");
|
|
15195
|
+
try {
|
|
15196
|
+
const buffer = Buffer.alloc(maxBytes + 1);
|
|
15197
|
+
const { bytesRead } = await handle.read(buffer, 0, maxBytes + 1, 0);
|
|
15198
|
+
const truncated = bytesRead > maxBytes;
|
|
15199
|
+
const text = new TextDecoder().decode(buffer.subarray(0, Math.min(bytesRead, maxBytes))).replace(/�$/, "");
|
|
15200
|
+
return text.trim() ? repositoryInstructionsBlock(path, text, truncated) : undefined;
|
|
15201
|
+
} finally {
|
|
15202
|
+
await handle.close();
|
|
15203
|
+
}
|
|
15204
|
+
} catch {
|
|
15205
|
+
return;
|
|
15206
|
+
}
|
|
15207
|
+
}
|
|
15208
|
+
|
|
15209
|
+
// ../protocol/src/build-pipeline-key-information.ts
|
|
15210
|
+
var KEY_INFORMATION_LIMITS = Object.freeze({
|
|
15211
|
+
proseLength: 4000,
|
|
15212
|
+
itemLength: 600,
|
|
15213
|
+
listItems: 30,
|
|
15214
|
+
decisions: 12,
|
|
15215
|
+
decisionLength: 400,
|
|
15216
|
+
options: 6,
|
|
15217
|
+
optionLength: 300,
|
|
15218
|
+
prosCons: 6,
|
|
15219
|
+
rationaleLength: 1000,
|
|
15220
|
+
tests: 40,
|
|
15221
|
+
testNameLength: 400,
|
|
15222
|
+
issues: 60,
|
|
15223
|
+
issueLength: 400,
|
|
15224
|
+
severityLength: 40,
|
|
15225
|
+
resolutionLength: 1000,
|
|
15226
|
+
verifications: 20,
|
|
15227
|
+
summaryLength: 2000,
|
|
15228
|
+
checks: 30,
|
|
15229
|
+
checkLength: 400,
|
|
15230
|
+
updates: 30,
|
|
15231
|
+
maxRound: 1000
|
|
15232
|
+
});
|
|
15233
|
+
var KEY_INFORMATION_TOOL_NAMES = Object.freeze([
|
|
15234
|
+
"get_key_information",
|
|
15235
|
+
"update_key_information"
|
|
15236
|
+
]);
|
|
15237
|
+
|
|
15156
15238
|
// ../protocol/src/transcript-artifacts.ts
|
|
15157
15239
|
var ARTIFACT_TOOL_NAMES = Object.freeze([
|
|
15158
15240
|
"create_artifact",
|
|
@@ -15167,9 +15249,9 @@ var ORKESTRATOR_ARTIFACT_MCP_SERVER_NAME = "orkestrator-artifacts";
|
|
|
15167
15249
|
var ORKESTRATOR_ARTIFACT_MCP_PATH = "/artifact-mcp";
|
|
15168
15250
|
|
|
15169
15251
|
// ../../bridges/codex-bridge/src/engine/app-server-engine.ts
|
|
15170
|
-
import { open as
|
|
15252
|
+
import { open as open8 } from "node:fs/promises";
|
|
15171
15253
|
import { createHash as createHash11 } from "node:crypto";
|
|
15172
|
-
import { isAbsolute as
|
|
15254
|
+
import { isAbsolute as isAbsolute9, join as join19 } from "node:path";
|
|
15173
15255
|
|
|
15174
15256
|
// ../../bridges/codex-bridge/src/app-server/process-supervisor.ts
|
|
15175
15257
|
import { execFile as execFile3, spawn as spawn2 } from "node:child_process";
|
|
@@ -15177,14 +15259,14 @@ import { randomUUID as randomUUID6 } from "node:crypto";
|
|
|
15177
15259
|
import {
|
|
15178
15260
|
link,
|
|
15179
15261
|
mkdir as mkdir6,
|
|
15180
|
-
open as
|
|
15262
|
+
open as open5,
|
|
15181
15263
|
readFile as readFile5,
|
|
15182
15264
|
readlink,
|
|
15183
15265
|
rename as rename4,
|
|
15184
15266
|
rm as rm5,
|
|
15185
15267
|
stat as stat5
|
|
15186
15268
|
} from "node:fs/promises";
|
|
15187
|
-
import { join as
|
|
15269
|
+
import { join as join14 } from "node:path";
|
|
15188
15270
|
|
|
15189
15271
|
// ../../bridges/codex-bridge/src/app-server/errors.ts
|
|
15190
15272
|
var APP_SERVER_OVERLOAD_CODE = -32001;
|
|
@@ -15784,7 +15866,7 @@ class SerialQueue {
|
|
|
15784
15866
|
|
|
15785
15867
|
// ../../bridges/codex-bridge/src/app-server/notification-recorder.ts
|
|
15786
15868
|
import { appendFile as appendFile4, mkdir as mkdir5 } from "node:fs/promises";
|
|
15787
|
-
import { join as
|
|
15869
|
+
import { join as join13 } from "node:path";
|
|
15788
15870
|
var DEFAULT_MAX_RECORDING_BYTES = 64 * 1024 * 1024;
|
|
15789
15871
|
var DEFAULT_FLUSH_INTERVAL_MS = 250;
|
|
15790
15872
|
var DEFAULT_WARN_INTERVAL_MS = 60000;
|
|
@@ -15810,7 +15892,7 @@ class NotificationRecorder {
|
|
|
15810
15892
|
stats;
|
|
15811
15893
|
constructor(options) {
|
|
15812
15894
|
this.options = options;
|
|
15813
|
-
this.path =
|
|
15895
|
+
this.path = join13(options.directory, options.fileName);
|
|
15814
15896
|
this.maxBytes = options.maxBytes ?? DEFAULT_MAX_RECORDING_BYTES;
|
|
15815
15897
|
this.flushIntervalMs = options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
|
|
15816
15898
|
this.warnIntervalMs = options.warnIntervalMs ?? DEFAULT_WARN_INTERVAL_MS;
|
|
@@ -16537,10 +16619,10 @@ class AppServerSupervisor {
|
|
|
16537
16619
|
} catch {}
|
|
16538
16620
|
}
|
|
16539
16621
|
pidFileDir() {
|
|
16540
|
-
return
|
|
16622
|
+
return join14(this.options.codexHome, "orkestrator-bridge");
|
|
16541
16623
|
}
|
|
16542
16624
|
pidFilePath() {
|
|
16543
|
-
return
|
|
16625
|
+
return join14(this.pidFileDir(), `app-server-${hashPath(this.options.cwd)}.pid`);
|
|
16544
16626
|
}
|
|
16545
16627
|
async readOwnedPidRecord(path) {
|
|
16546
16628
|
let raw;
|
|
@@ -16579,7 +16661,7 @@ class AppServerSupervisor {
|
|
|
16579
16661
|
instanceId
|
|
16580
16662
|
}), "utf8");
|
|
16581
16663
|
const temporary = `${path}.${this.pidOwnerToken}.update`;
|
|
16582
|
-
const handle = await
|
|
16664
|
+
const handle = await open5(temporary, "wx", 384);
|
|
16583
16665
|
try {
|
|
16584
16666
|
await handle.write(payload, 0, payload.length, 0);
|
|
16585
16667
|
await handle.sync();
|
|
@@ -16603,7 +16685,7 @@ class AppServerSupervisor {
|
|
|
16603
16685
|
await mkdir6(this.pidFileDir(), { recursive: true });
|
|
16604
16686
|
for (let attempt = 0;attempt < PID_ACQUISITION_MAX_ATTEMPTS; attempt += 1) {
|
|
16605
16687
|
try {
|
|
16606
|
-
const handle = await
|
|
16688
|
+
const handle = await open5(this.pidFilePath(), "wx", 384);
|
|
16607
16689
|
try {
|
|
16608
16690
|
const record = {
|
|
16609
16691
|
ownerToken: this.pidOwnerToken,
|
|
@@ -17033,10 +17115,11 @@ function describeApproval(options) {
|
|
|
17033
17115
|
} : undefined;
|
|
17034
17116
|
const networkContext = isRecord9(params.networkApprovalContext) ? str2(params.networkApprovalContext.host) : undefined;
|
|
17035
17117
|
const command = commandText(params.command) ?? commandActionsText(params.commandActions);
|
|
17036
|
-
const
|
|
17037
|
-
const
|
|
17118
|
+
const v2Command = options.method === "item/commandExecution/requestApproval" && (params.kind === undefined || params.kind === null || params.kind === "command");
|
|
17119
|
+
const exactCommand = v2Command && typeof params.command === "string" && params.command.length > 0;
|
|
17120
|
+
const ruleEligible = networkContext !== undefined ? v2Command && (exactCommand || command === undefined) : kind === "command" ? exactCommand : kind === "file-change" ? str2(params.grantRoot) === undefined : false;
|
|
17038
17121
|
const proposal = exactCommand ? proposedPrefix(params.proposedExecpolicyAmendment) : undefined;
|
|
17039
|
-
const actionable = kind === "command" ? command !== undefined : kind === "file-change" ? Boolean(changes?.length) : permissions !== undefined && (permissions.network || permissions.fileSystem);
|
|
17122
|
+
const actionable = kind === "command" ? command !== undefined || networkContext !== undefined : kind === "file-change" ? Boolean(changes?.length) : permissions !== undefined && (permissions.network || permissions.fileSystem);
|
|
17040
17123
|
return {
|
|
17041
17124
|
approvalId: options.approvalId,
|
|
17042
17125
|
kind,
|
|
@@ -17101,7 +17184,7 @@ function describeApprovalOutcome(request, decision, resolution) {
|
|
|
17101
17184
|
return null;
|
|
17102
17185
|
if (isGrantingApprovalDecision(decision))
|
|
17103
17186
|
return null;
|
|
17104
|
-
const subject = request.kind === "command" ? request.command ? `permission to run \`${request.command}\`` : "permission to run a command" : request.kind === "file-change" ? request.changes?.length ? `permission to change ${request.changes.length} file(s)` : "permission to apply a file change" : "additional permissions";
|
|
17187
|
+
const subject = request.kind === "command" ? request.command ? `permission to run \`${request.command}\`` : request.networkHost ? `permission to reach \`${request.networkHost}\`` : "permission to run a command" : request.kind === "file-change" ? request.changes?.length ? `permission to change ${request.changes.length} file(s)` : "permission to apply a file change" : "additional permissions";
|
|
17105
17188
|
switch (resolution) {
|
|
17106
17189
|
case "timed-out":
|
|
17107
17190
|
return `Codex asked for ${subject}. The request expired without an answer, so it was declined.`;
|
|
@@ -18040,6 +18123,9 @@ function reduceNotification(notification, generation, handle) {
|
|
|
18040
18123
|
if (!isRecord10(params) || !isRecord10(params.rateLimits))
|
|
18041
18124
|
return { events: [] };
|
|
18042
18125
|
const snapshot = params.rateLimits;
|
|
18126
|
+
const limitId = str3(snapshot.limitId);
|
|
18127
|
+
if (limitId && limitId !== "codex")
|
|
18128
|
+
return { events: [] };
|
|
18043
18129
|
const windows = [];
|
|
18044
18130
|
const limitName = typeof snapshot.limitName === "string" && snapshot.limitName.length > 0 ? snapshot.limitName : undefined;
|
|
18045
18131
|
if (!isRecord10(snapshot.primary) && limitName !== undefined) {
|
|
@@ -18421,8 +18507,8 @@ function redactSecrets(value) {
|
|
|
18421
18507
|
|
|
18422
18508
|
// ../../bridges/codex-bridge/src/sessions/dispatch-journal.ts
|
|
18423
18509
|
import { createHash as createHash10 } from "node:crypto";
|
|
18424
|
-
import { mkdir as mkdir8, open as
|
|
18425
|
-
import { join as
|
|
18510
|
+
import { mkdir as mkdir8, open as open6, rename as rename6, rm as rm7, writeFile as writeFile5 } from "node:fs/promises";
|
|
18511
|
+
import { join as join16 } from "node:path";
|
|
18426
18512
|
|
|
18427
18513
|
// ../../bridges/codex-bridge/src/sessions/persistence.ts
|
|
18428
18514
|
import { createHash as createHash9, randomUUID as randomUUID7 } from "node:crypto";
|
|
@@ -18437,7 +18523,7 @@ import {
|
|
|
18437
18523
|
stat as stat6,
|
|
18438
18524
|
writeFile as writeFile4
|
|
18439
18525
|
} from "node:fs/promises";
|
|
18440
|
-
import { join as
|
|
18526
|
+
import { join as join15 } from "node:path";
|
|
18441
18527
|
var BRIDGE_SESSION_REGISTRY_VERSION = 2;
|
|
18442
18528
|
var SESSION_TITLE_SOURCES = new Set([
|
|
18443
18529
|
"codex",
|
|
@@ -18542,20 +18628,20 @@ class BridgeSessionStore {
|
|
|
18542
18628
|
return codexBridgeStateDir(this.codexHome);
|
|
18543
18629
|
}
|
|
18544
18630
|
path() {
|
|
18545
|
-
return
|
|
18631
|
+
return join15(this.dir(), `bridge-sessions-${this.cwdHash}.json`);
|
|
18546
18632
|
}
|
|
18547
18633
|
recordsDir() {
|
|
18548
|
-
return
|
|
18634
|
+
return join15(this.dir(), `bridge-sessions-${this.cwdHash}`);
|
|
18549
18635
|
}
|
|
18550
18636
|
loginRecordsDir() {
|
|
18551
|
-
const directory =
|
|
18637
|
+
const directory = join15(codexLoginBridgeDir(this.codexHome), `bridge-sessions-${this.cwdHash}`);
|
|
18552
18638
|
return directory === this.recordsDir() ? undefined : directory;
|
|
18553
18639
|
}
|
|
18554
18640
|
recordKey(bridgeSessionId) {
|
|
18555
18641
|
return createHash9("sha256").update(bridgeSessionId).digest("hex");
|
|
18556
18642
|
}
|
|
18557
18643
|
recordPath(bridgeSessionId) {
|
|
18558
|
-
return
|
|
18644
|
+
return join15(this.recordsDir(), `${this.recordKey(bridgeSessionId)}.json`);
|
|
18559
18645
|
}
|
|
18560
18646
|
async ensurePrivateStorage() {
|
|
18561
18647
|
await mkdir7(this.dir(), { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
|
|
@@ -18583,7 +18669,7 @@ class BridgeSessionStore {
|
|
|
18583
18669
|
return legacy;
|
|
18584
18670
|
}
|
|
18585
18671
|
const records = await Promise.all(names.map(async (name) => {
|
|
18586
|
-
const path =
|
|
18672
|
+
const path = join15(this.recordsDir(), name);
|
|
18587
18673
|
if (name.endsWith(".tmp")) {
|
|
18588
18674
|
await chmod(path, PRIVATE_FILE_MODE).catch(() => {
|
|
18589
18675
|
return;
|
|
@@ -18695,8 +18781,8 @@ class BridgeSessionStore {
|
|
|
18695
18781
|
return;
|
|
18696
18782
|
await this.ensurePrivateStorage();
|
|
18697
18783
|
await Promise.all(names.map(async (name) => {
|
|
18698
|
-
const from =
|
|
18699
|
-
const target =
|
|
18784
|
+
const from = join15(source, name);
|
|
18785
|
+
const target = join15(this.recordsDir(), name);
|
|
18700
18786
|
const temporary = `${target}.${process.pid}.${randomUUID7()}.tmp`;
|
|
18701
18787
|
await writeFile4(temporary, await readFile6(from), { mode: PRIVATE_FILE_MODE });
|
|
18702
18788
|
await chmod(temporary, PRIVATE_FILE_MODE);
|
|
@@ -18855,7 +18941,7 @@ class DispatchJournal {
|
|
|
18855
18941
|
this.persist = options.persist !== false;
|
|
18856
18942
|
}
|
|
18857
18943
|
path() {
|
|
18858
|
-
return
|
|
18944
|
+
return join16(codexBridgeStateDir(this.codexHome), `dispatch-journal-${this.cwdHash}.json`);
|
|
18859
18945
|
}
|
|
18860
18946
|
async load() {
|
|
18861
18947
|
if (this.loaded)
|
|
@@ -18865,7 +18951,7 @@ class DispatchJournal {
|
|
|
18865
18951
|
this.loadSettled = true;
|
|
18866
18952
|
return;
|
|
18867
18953
|
}
|
|
18868
|
-
const legacy =
|
|
18954
|
+
const legacy = join16(codexLoginBridgeDir(this.codexHome), `dispatch-journal-${this.cwdHash}.json`);
|
|
18869
18955
|
try {
|
|
18870
18956
|
const hadCurrent = await this.loadPath(this.path());
|
|
18871
18957
|
const mergedLegacy = legacy !== this.path() && await this.loadPath(legacy, true);
|
|
@@ -18941,7 +19027,7 @@ class DispatchJournal {
|
|
|
18941
19027
|
return true;
|
|
18942
19028
|
}
|
|
18943
19029
|
async readBounded(path) {
|
|
18944
|
-
const handle = await
|
|
19030
|
+
const handle = await open6(path, "r");
|
|
18945
19031
|
try {
|
|
18946
19032
|
const metadata = await handle.stat();
|
|
18947
19033
|
if (!metadata.isFile() || metadata.size > this.maxBytes) {
|
|
@@ -19417,7 +19503,7 @@ function coordinatorCapabilityPolicy(mode) {
|
|
|
19417
19503
|
// ../../bridges/codex-bridge/src/codex-config.ts
|
|
19418
19504
|
import { existsSync as existsSync3, readdirSync as readdirSync3, realpathSync, statSync as statSync2 } from "node:fs";
|
|
19419
19505
|
import { homedir as homedir2 } from "node:os";
|
|
19420
|
-
import { isAbsolute as
|
|
19506
|
+
import { isAbsolute as isAbsolute8, join as join17, relative as relative3, sep } from "node:path";
|
|
19421
19507
|
|
|
19422
19508
|
// ../../bridges/codex-bridge/src/engine/mcp-tool-availability.ts
|
|
19423
19509
|
var ORKESTRATOR_MCP_STARTUP_TIMEOUT_SEC = 15;
|
|
@@ -19503,7 +19589,7 @@ function codexNetworkDeniedConfig(policy) {
|
|
|
19503
19589
|
};
|
|
19504
19590
|
}
|
|
19505
19591
|
function codexProjectTrustConfig(policy, cwd) {
|
|
19506
|
-
if (!policy || policy.projectResources || !cwd || !
|
|
19592
|
+
if (!policy || policy.projectResources || !cwd || !isAbsolute8(cwd))
|
|
19507
19593
|
return {};
|
|
19508
19594
|
const roots = new Set([cwd]);
|
|
19509
19595
|
try {
|
|
@@ -19528,20 +19614,20 @@ function codexCoordinatorSkillExtraRoots(env = process.env, cwd = env.CWD?.trim(
|
|
|
19528
19614
|
return [];
|
|
19529
19615
|
const userDir = env[COORDINATOR_CODEX_USER_SKILLS_DIR_ENV]?.trim();
|
|
19530
19616
|
return [
|
|
19531
|
-
...userDir &&
|
|
19532
|
-
...cwd &&
|
|
19617
|
+
...userDir && isAbsolute8(userDir) ? [userDir] : [],
|
|
19618
|
+
...cwd && isAbsolute8(cwd) ? [join17(cwd, ".claude", "skills")] : []
|
|
19533
19619
|
].filter((dir) => existsSync3(dir));
|
|
19534
19620
|
}
|
|
19535
19621
|
var MAX_SKILL_READ_GRANTS = 256;
|
|
19536
19622
|
function isWithin(parent, child) {
|
|
19537
|
-
const path =
|
|
19538
|
-
return path === "" || !path.startsWith(`..${sep}`) && path !== ".." && !
|
|
19623
|
+
const path = relative3(parent, child);
|
|
19624
|
+
return path === "" || !path.startsWith(`..${sep}`) && path !== ".." && !isAbsolute8(path);
|
|
19539
19625
|
}
|
|
19540
19626
|
function codexCoordinatorSkillReadRoots(env = process.env, home = env.HOME?.trim() || homedir2()) {
|
|
19541
19627
|
const userDir = env[COORDINATOR_CODEX_USER_SKILLS_DIR_ENV]?.trim();
|
|
19542
19628
|
const roots = [
|
|
19543
|
-
...userDir &&
|
|
19544
|
-
|
|
19629
|
+
...userDir && isAbsolute8(userDir) ? [userDir] : [],
|
|
19630
|
+
join17(home, ".agents", "skills")
|
|
19545
19631
|
];
|
|
19546
19632
|
const homeReal = (() => {
|
|
19547
19633
|
try {
|
|
@@ -19575,8 +19661,8 @@ function codexCoordinatorSkillReadRoots(env = process.env, home = env.HOME?.trim
|
|
|
19575
19661
|
break;
|
|
19576
19662
|
let target;
|
|
19577
19663
|
try {
|
|
19578
|
-
target = realpathSync(
|
|
19579
|
-
if (!statSync2(target).isDirectory() || !existsSync3(
|
|
19664
|
+
target = realpathSync(join17(real, entry));
|
|
19665
|
+
if (!statSync2(target).isDirectory() || !existsSync3(join17(target, "SKILL.md")))
|
|
19580
19666
|
continue;
|
|
19581
19667
|
} catch {
|
|
19582
19668
|
continue;
|
|
@@ -19601,7 +19687,7 @@ function codexProjectSkillsConfig(listed) {
|
|
|
19601
19687
|
const { path, scope, enabled } = skill ?? {};
|
|
19602
19688
|
if (enabled === true && typeof scope === "string" && KEPT_SKILL_SCOPES.has(scope))
|
|
19603
19689
|
continue;
|
|
19604
|
-
if (typeof path !== "string" || !
|
|
19690
|
+
if (typeof path !== "string" || !isAbsolute8(path)) {
|
|
19605
19691
|
throw new Error("Codex listed a project skill without a path it can be disabled by");
|
|
19606
19692
|
}
|
|
19607
19693
|
disabled.add(path);
|
|
@@ -19730,11 +19816,11 @@ function codexAppServerConfigOverrides(env = process.env) {
|
|
|
19730
19816
|
const readableRuntimeRoot = env.CODEX_BRIDGE_READABLE_RUNTIME_ROOT?.trim();
|
|
19731
19817
|
const projectRoot = env.CWD?.trim();
|
|
19732
19818
|
const attachmentRoot = env[BRIDGE_ATTACHMENT_ROOT_ENV]?.trim();
|
|
19733
|
-
if (!permissionProfile || !/^[A-Za-z0-9_-]+$/.test(permissionProfile) || !readableRuntimeRoot || !
|
|
19819
|
+
if (!permissionProfile || !/^[A-Za-z0-9_-]+$/.test(permissionProfile) || !readableRuntimeRoot || !isAbsolute8(readableRuntimeRoot) || !projectRoot || !isAbsolute8(projectRoot)) {
|
|
19734
19820
|
throw new Error("Coordinator Codex permission profile configuration is invalid");
|
|
19735
19821
|
}
|
|
19736
19822
|
overrides.default_permissions = JSON.stringify(permissionProfile);
|
|
19737
|
-
overrides[`permissions.${permissionProfile}.filesystem`] = `{ ":root" = "deny", ":minimal" = "read", ":tmpdir" = "deny", ` + `":slash_tmp" = "deny", ${JSON.stringify(readableRuntimeRoot)} = "read", ` + (attachmentRoot &&
|
|
19823
|
+
overrides[`permissions.${permissionProfile}.filesystem`] = `{ ":root" = "deny", ":minimal" = "read", ":tmpdir" = "deny", ` + `":slash_tmp" = "deny", ${JSON.stringify(readableRuntimeRoot)} = "read", ` + (attachmentRoot && isAbsolute8(attachmentRoot) ? `${JSON.stringify(attachmentRoot)} = "read", ` : "") + codexCoordinatorSkillReadRoots(env).map((root) => `${JSON.stringify(root)} = "read", `).join("") + `":workspace_roots" = { "." = "read" } }`;
|
|
19738
19824
|
overrides[`permissions.${permissionProfile}.network.enabled`] = "false";
|
|
19739
19825
|
overrides.web_search = JSON.stringify(codexNetworkDeniedSearchMode(codexCoordinatorPolicy(env)));
|
|
19740
19826
|
overrides["features.standalone_web_search"] = "false";
|
|
@@ -19794,7 +19880,8 @@ function codexAppServerConfigOverrides(env = process.env) {
|
|
|
19794
19880
|
for (const name of [
|
|
19795
19881
|
...AGENT_MAIL_TOOL_NAMES,
|
|
19796
19882
|
...ARTIFACT_TOOL_NAMES,
|
|
19797
|
-
...AGENT_GOAL_TOOL_NAMES
|
|
19883
|
+
...AGENT_GOAL_TOOL_NAMES,
|
|
19884
|
+
...KEY_INFORMATION_TOOL_NAMES
|
|
19798
19885
|
]) {
|
|
19799
19886
|
overrides[`mcp_servers.orkestrator.tools.${name}.approval_mode`] = JSON.stringify("approve");
|
|
19800
19887
|
}
|
|
@@ -19808,7 +19895,7 @@ function codexAppServerConfigOverrides(env = process.env) {
|
|
|
19808
19895
|
// ../../bridges/codex-bridge/src/github-credential-config.ts
|
|
19809
19896
|
import { mkdtemp as mkdtemp2 } from "node:fs/promises";
|
|
19810
19897
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
19811
|
-
import { join as
|
|
19898
|
+
import { join as join18 } from "node:path";
|
|
19812
19899
|
var CODEX_INHERITED_GIT_CONFIG_PATTERNS = Object.freeze([
|
|
19813
19900
|
"GIT_CONFIG_COUNT",
|
|
19814
19901
|
"GIT_CONFIG_KEY_*",
|
|
@@ -19843,7 +19930,7 @@ function codexGitHubCredentialThreadConfig(policy, options) {
|
|
|
19843
19930
|
}
|
|
19844
19931
|
var withheldGhConfigDir;
|
|
19845
19932
|
function emptyGhConfigDir() {
|
|
19846
|
-
withheldGhConfigDir ??= mkdtemp2(
|
|
19933
|
+
withheldGhConfigDir ??= mkdtemp2(join18(tmpdir2(), "orkestrator-gh-withheld-")).catch((error) => {
|
|
19847
19934
|
withheldGhConfigDir = undefined;
|
|
19848
19935
|
throw error;
|
|
19849
19936
|
});
|
|
@@ -19851,11 +19938,11 @@ function emptyGhConfigDir() {
|
|
|
19851
19938
|
}
|
|
19852
19939
|
|
|
19853
19940
|
// ../../bridges/codex-bridge/src/sessions/tool-history-guard.ts
|
|
19854
|
-
import { open as
|
|
19941
|
+
import { open as open7 } from "node:fs/promises";
|
|
19855
19942
|
var TOOL_HISTORY_MARKER = '"type":"additional_tools"';
|
|
19856
19943
|
var MAX_TOOL_HISTORY_LINEAGE_DEPTH = 32;
|
|
19857
19944
|
async function rolloutDeclaresToolHistory(path, end) {
|
|
19858
|
-
const handle = await
|
|
19945
|
+
const handle = await open7(path, "r");
|
|
19859
19946
|
try {
|
|
19860
19947
|
const size = (await handle.stat()).size;
|
|
19861
19948
|
const limit = end === undefined ? size : Math.min(end, size);
|
|
@@ -19880,7 +19967,7 @@ async function rolloutDeclaresToolHistory(path, end) {
|
|
|
19880
19967
|
}
|
|
19881
19968
|
}
|
|
19882
19969
|
async function historyBase(path) {
|
|
19883
|
-
const handle = await
|
|
19970
|
+
const handle = await open7(path, "r");
|
|
19884
19971
|
try {
|
|
19885
19972
|
const chunks = [];
|
|
19886
19973
|
let filled = 0;
|
|
@@ -19963,10 +20050,12 @@ var APP_SERVER_CAPABILITIES = {
|
|
|
19963
20050
|
};
|
|
19964
20051
|
|
|
19965
20052
|
// ../../bridges/codex-bridge/src/engine/app-server-engine.ts
|
|
19966
|
-
var AGENT_MAIL_TOOL_APPROVALS = Object.fromEntries([
|
|
19967
|
-
|
|
19968
|
-
|
|
19969
|
-
|
|
20053
|
+
var AGENT_MAIL_TOOL_APPROVALS = Object.fromEntries([
|
|
20054
|
+
...AGENT_MAIL_TOOL_NAMES,
|
|
20055
|
+
...ARTIFACT_TOOL_NAMES,
|
|
20056
|
+
...AGENT_GOAL_TOOL_NAMES,
|
|
20057
|
+
...KEY_INFORMATION_TOOL_NAMES
|
|
20058
|
+
].map((name) => [name, { approval_mode: "approve" }]));
|
|
19970
20059
|
var ROOT_THREAD_SOURCE_KINDS = ["cli", "vscode", "exec", "appServer", "unknown"];
|
|
19971
20060
|
var CODEX_SIGN_IN_EXPIRED_NOTICE = "Codex sign-in expired. Sign in again to continue.";
|
|
19972
20061
|
var CODEX_SIGN_IN_REQUIRED_MESSAGE = "You've been signed out of Codex. Sign in again to keep working.";
|
|
@@ -20317,7 +20406,7 @@ function signedOutAccountRead(error) {
|
|
|
20317
20406
|
}
|
|
20318
20407
|
async function readStoredLoginFingerprint(codexHome) {
|
|
20319
20408
|
try {
|
|
20320
|
-
const file = await
|
|
20409
|
+
const file = await open8(join19(codexHome, "auth.json"), "r");
|
|
20321
20410
|
let raw;
|
|
20322
20411
|
try {
|
|
20323
20412
|
const bytes = Buffer.alloc(65537);
|
|
@@ -20891,7 +20980,26 @@ class AppServerEngine {
|
|
|
20891
20980
|
]);
|
|
20892
20981
|
return { ...skills, ...mcp, ...credential };
|
|
20893
20982
|
}
|
|
20894
|
-
|
|
20983
|
+
async developerInstructions(generation, config) {
|
|
20984
|
+
const loadsProject = !config.policy || config.policy.projectResources;
|
|
20985
|
+
const cwd = config.cwd ?? this.options.cwd;
|
|
20986
|
+
const ours = [
|
|
20987
|
+
...config.policy?.id === "coordinator-read-only" ? [] : [agentSystemInstructions()],
|
|
20988
|
+
...loadsProject || config.sandbox === "read-only" || config.policy?.id === "coordinator-read-only" ? [] : [await readRepositoryInstructions(cwd)]
|
|
20989
|
+
].filter((part) => Boolean(part));
|
|
20990
|
+
if (ours.length === 0)
|
|
20991
|
+
return;
|
|
20992
|
+
const read = this.options.readConfiguredDeveloperInstructions ?? ((projectCwd) => this.supervisor.requestOnGeneration(generation, "config/read", projectCwd ? { cwd: projectCwd } : {}).then((result) => result?.config?.developer_instructions));
|
|
20993
|
+
const configured = await read(loadsProject ? cwd : undefined).catch(() => {
|
|
20994
|
+
return;
|
|
20995
|
+
});
|
|
20996
|
+
if (typeof configured === "string" && configured.trim())
|
|
20997
|
+
ours.push(configured);
|
|
20998
|
+
return ours.join(`
|
|
20999
|
+
|
|
21000
|
+
`);
|
|
21001
|
+
}
|
|
21002
|
+
toThreadParams(config, extraConfig = {}, developerInstructions) {
|
|
20895
21003
|
const approveAgentMcpTools = config.policy?.approvals === "auto-approve" && (config.approvalPolicy ?? "never") === "never" && config.sandbox !== "read-only" || config.policy?.id === "coordinator-read-only" && Boolean(config.permissionProfile) || Boolean(config.workflowResultTool && config.agentMcp);
|
|
20896
21004
|
const cwd = config.cwd ?? this.options.cwd;
|
|
20897
21005
|
const threadConfig = {
|
|
@@ -20935,6 +21043,7 @@ class AppServerEngine {
|
|
|
20935
21043
|
},
|
|
20936
21044
|
...config.model ? { model: config.model } : {},
|
|
20937
21045
|
serviceTier: config.serviceTier ?? null,
|
|
21046
|
+
...developerInstructions ? { developerInstructions } : {},
|
|
20938
21047
|
...Object.keys(threadConfig).length > 0 ? { config: threadConfig } : {}
|
|
20939
21048
|
};
|
|
20940
21049
|
}
|
|
@@ -20997,7 +21106,8 @@ class AppServerEngine {
|
|
|
20997
21106
|
const generation = await this.assertHostedNetworkLock(options.config);
|
|
20998
21107
|
await this.assertToolHistoryLock(generation, options.config);
|
|
20999
21108
|
const extra = await this.policyThreadConfig(generation, options.config);
|
|
21000
|
-
const
|
|
21109
|
+
const instructions = await this.developerInstructions(generation, options.config);
|
|
21110
|
+
const response = await this.supervisor.requestOnGeneration(generation, "thread/start", this.toThreadParams(options.config, extra, instructions));
|
|
21001
21111
|
this.assertPermissionProfile(response.activePermissionProfile, options.config);
|
|
21002
21112
|
return this.bindThread(response.thread, options.config, response.model);
|
|
21003
21113
|
}
|
|
@@ -21005,7 +21115,11 @@ class AppServerEngine {
|
|
|
21005
21115
|
const generation = await this.assertHostedNetworkLock(options.config);
|
|
21006
21116
|
await this.assertToolHistoryLock(generation, options.config);
|
|
21007
21117
|
const extra = await this.policyThreadConfig(generation, options.config);
|
|
21008
|
-
const
|
|
21118
|
+
const instructions = await this.developerInstructions(generation, options.config);
|
|
21119
|
+
const response = await this.supervisor.requestOnGeneration(generation, "thread/resume", {
|
|
21120
|
+
threadId,
|
|
21121
|
+
...this.toThreadParams(options.config, extra, instructions)
|
|
21122
|
+
});
|
|
21009
21123
|
this.assertPermissionProfile(response.activePermissionProfile, options.config);
|
|
21010
21124
|
const thread = this.bindThread(response.thread, options.config, response.model);
|
|
21011
21125
|
await this.assertNoToolHistory(thread.id ?? threadId, options.config, true);
|
|
@@ -21027,10 +21141,11 @@ class AppServerEngine {
|
|
|
21027
21141
|
await this.assertToolHistoryLock(generation, config);
|
|
21028
21142
|
await this.assertNoToolHistory(threadId, config, false);
|
|
21029
21143
|
const extra = await this.policyThreadConfig(generation, config);
|
|
21144
|
+
const instructions = await this.developerInstructions(generation, config);
|
|
21030
21145
|
const response = await this.supervisor.requestOnGeneration(generation, "thread/fork", {
|
|
21031
21146
|
threadId,
|
|
21032
21147
|
...lastTurnId ? { lastTurnId } : {},
|
|
21033
|
-
...this.toThreadParams(config, extra)
|
|
21148
|
+
...this.toThreadParams(config, extra, instructions)
|
|
21034
21149
|
});
|
|
21035
21150
|
this.assertPermissionProfile(response.activePermissionProfile, config);
|
|
21036
21151
|
return this.bindThread(response.thread, config, response.model);
|
|
@@ -21360,7 +21475,7 @@ class AppServerEngine {
|
|
|
21360
21475
|
thread.model = confirmedModel.trim();
|
|
21361
21476
|
}
|
|
21362
21477
|
if (thread.id) {
|
|
21363
|
-
if (typeof raw.path === "string" &&
|
|
21478
|
+
if (typeof raw.path === "string" && isAbsolute9(raw.path)) {
|
|
21364
21479
|
this.rolloutPaths.set(thread.id, raw.path);
|
|
21365
21480
|
}
|
|
21366
21481
|
this.bindings.set(thread.id, {
|
|
@@ -23288,8 +23403,8 @@ function parseCommandToken(text, sigils = ["/"]) {
|
|
|
23288
23403
|
|
|
23289
23404
|
// ../../bridges/codex-bridge/src/prompts/template-discovery.ts
|
|
23290
23405
|
import { createHash as createHash13 } from "node:crypto";
|
|
23291
|
-
import { open as
|
|
23292
|
-
import { join as
|
|
23406
|
+
import { open as open9, readdir as readdir3, stat as stat7 } from "node:fs/promises";
|
|
23407
|
+
import { join as join20 } from "node:path";
|
|
23293
23408
|
var TEMPLATE_LIMITS = Object.freeze({
|
|
23294
23409
|
maxTemplates: 512,
|
|
23295
23410
|
maxVisitedEntries: 2048,
|
|
@@ -23309,8 +23424,8 @@ var RESERVED_TEMPLATE_PREFIXES = ["/skill:", "/prompts:"];
|
|
|
23309
23424
|
var TEMPLATE_ID_PREFIX = "codex-template:";
|
|
23310
23425
|
function templateRoots(cwd, codexHome = getCodexHomeDir()) {
|
|
23311
23426
|
return [
|
|
23312
|
-
{ origin: "project", dir:
|
|
23313
|
-
{ origin: "user", dir:
|
|
23427
|
+
{ origin: "project", dir: join20(cwd, ".codex", "prompts") },
|
|
23428
|
+
{ origin: "user", dir: join20(codexHome, "prompts") }
|
|
23314
23429
|
];
|
|
23315
23430
|
}
|
|
23316
23431
|
function templateCommandId(origin, relativePath) {
|
|
@@ -23335,7 +23450,7 @@ function isReservedName(name) {
|
|
|
23335
23450
|
var metadataCache = new Map;
|
|
23336
23451
|
var METADATA_CACHE_MAX = 1024;
|
|
23337
23452
|
async function readBounded2(absolutePath, maxBytes) {
|
|
23338
|
-
const handle = await
|
|
23453
|
+
const handle = await open9(absolutePath, "r");
|
|
23339
23454
|
try {
|
|
23340
23455
|
const info = await handle.stat();
|
|
23341
23456
|
if (!info.isFile())
|
|
@@ -23415,7 +23530,7 @@ async function scanPromptTemplates(roots, limits = TEMPLATE_LIMITS) {
|
|
|
23415
23530
|
return;
|
|
23416
23531
|
}
|
|
23417
23532
|
visited += 1;
|
|
23418
|
-
const absolutePath =
|
|
23533
|
+
const absolutePath = join20(dir, entry.name);
|
|
23419
23534
|
const relativePath = relative ? `${relative}/${entry.name}` : entry.name;
|
|
23420
23535
|
if (entry.isDirectory()) {
|
|
23421
23536
|
if (depth + 1 > limits.maxDepth) {
|
|
@@ -23582,7 +23697,7 @@ async function loadTemplateBody(entry, limits = TEMPLATE_LIMITS) {
|
|
|
23582
23697
|
}
|
|
23583
23698
|
|
|
23584
23699
|
// ../../bridges/codex-bridge/src/commands/skill-inventory.ts
|
|
23585
|
-
import { isAbsolute as
|
|
23700
|
+
import { isAbsolute as isAbsolute10 } from "node:path";
|
|
23586
23701
|
var SKILL_INVENTORY_LIMITS = Object.freeze({
|
|
23587
23702
|
maxSkills: 512,
|
|
23588
23703
|
maxDescriptionBytes: 1000,
|
|
@@ -23634,7 +23749,7 @@ function normalizeSkillsList(raw, context) {
|
|
|
23634
23749
|
}
|
|
23635
23750
|
const name = nonEmpty(candidate.name);
|
|
23636
23751
|
const path = typeof candidate.path === "string" ? candidate.path : undefined;
|
|
23637
|
-
if (!name || !usableSkillName(name) || !path || !
|
|
23752
|
+
if (!name || !usableSkillName(name) || !path || !isAbsolute10(path)) {
|
|
23638
23753
|
truncated = true;
|
|
23639
23754
|
continue;
|
|
23640
23755
|
}
|
|
@@ -27372,7 +27487,7 @@ class CodexRuntimePrompt {
|
|
|
27372
27487
|
}
|
|
27373
27488
|
|
|
27374
27489
|
// ../../bridges/codex-bridge/src/app-server-runtime-tail.ts
|
|
27375
|
-
import { join as
|
|
27490
|
+
import { join as join21, relative as relative4, isAbsolute as isAbsolute11 } from "node:path";
|
|
27376
27491
|
class CodexRuntimeTail {
|
|
27377
27492
|
ctx;
|
|
27378
27493
|
lifecycle;
|
|
@@ -27570,14 +27685,14 @@ class CodexRuntimeTail {
|
|
|
27570
27685
|
cursor = page.nextCursor ?? undefined;
|
|
27571
27686
|
} while (cursor);
|
|
27572
27687
|
} catch {}
|
|
27573
|
-
const archivedRoot =
|
|
27688
|
+
const archivedRoot = join21(this.ctx.options.codexHome, "archived_sessions");
|
|
27574
27689
|
const isArchived = (meta) => {
|
|
27575
27690
|
if (archived.has(meta.id))
|
|
27576
27691
|
return true;
|
|
27577
27692
|
if (!meta.transcriptPath)
|
|
27578
27693
|
return false;
|
|
27579
|
-
const fromRoot =
|
|
27580
|
-
return fromRoot !== "" && !fromRoot.startsWith("..") && !
|
|
27694
|
+
const fromRoot = relative4(archivedRoot, meta.transcriptPath);
|
|
27695
|
+
return fromRoot !== "" && !fromRoot.startsWith("..") && !isAbsolute11(fromRoot);
|
|
27581
27696
|
};
|
|
27582
27697
|
let persisted = [];
|
|
27583
27698
|
let generatedTitles = null;
|
|
@@ -28475,7 +28590,7 @@ async function writeCodexRawLog(sessionId, entry, logDir = codexRawLogDir) {
|
|
|
28475
28590
|
try {
|
|
28476
28591
|
await mkdir9(logDir, { recursive: true });
|
|
28477
28592
|
const filename = `${sanitizeLogFileComponent(sessionId)}.jsonl`;
|
|
28478
|
-
await appendFile5(
|
|
28593
|
+
await appendFile5(join22(logDir, filename), `${JSON.stringify({
|
|
28479
28594
|
timestamp: new Date().toISOString(),
|
|
28480
28595
|
sessionId,
|
|
28481
28596
|
...entry
|
|
@@ -28667,10 +28782,10 @@ function emit(event) {
|
|
|
28667
28782
|
}
|
|
28668
28783
|
}
|
|
28669
28784
|
function bridgeCacheDir() {
|
|
28670
|
-
return
|
|
28785
|
+
return join22(getCodexHomeDir(), "orkestrator-bridge");
|
|
28671
28786
|
}
|
|
28672
28787
|
function bridgeCachePath() {
|
|
28673
|
-
return
|
|
28788
|
+
return join22(bridgeCacheDir(), "models-cache.json");
|
|
28674
28789
|
}
|
|
28675
28790
|
var BRIDGE_MODEL_CACHE_VERSION = 2;
|
|
28676
28791
|
async function readPersistedBridgeCache() {
|
|
@@ -28694,7 +28809,7 @@ async function writePersistedBridgeCache(models) {
|
|
|
28694
28809
|
}
|
|
28695
28810
|
async function readCodexCliModelCache() {
|
|
28696
28811
|
try {
|
|
28697
|
-
const raw = await readFile7(
|
|
28812
|
+
const raw = await readFile7(join22(getCodexHomeDir(), "models_cache.json"), "utf8");
|
|
28698
28813
|
const models = parseModelCatalog(raw);
|
|
28699
28814
|
return models.length > 0 ? models : null;
|
|
28700
28815
|
} catch {
|