@songsid/agend 2.1.1-beta.10 → 2.1.1-beta.12
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/backend/antigravity.js +9 -11
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.js +7 -7
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex.d.ts +16 -0
- package/dist/backend/codex.js +251 -62
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/gemini-cli.js +4 -7
- package/dist/backend/gemini-cli.js.map +1 -1
- package/dist/backend/grok.js +24 -7
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.js +22 -9
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/opencode.js +4 -7
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/types.d.ts +7 -0
- package/dist/backend/types.js +3 -3
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/discord.js +4 -5
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.js +50 -15
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/ipc-bridge.d.ts +8 -0
- package/dist/channel/ipc-bridge.js +41 -14
- package/dist/channel/ipc-bridge.js.map +1 -1
- package/dist/channel/mcp-server.js +25 -10
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.js +25 -0
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-queue.d.ts +1 -0
- package/dist/channel/message-queue.js +49 -17
- package/dist/channel/message-queue.js.map +1 -1
- package/dist/channel/reconnect-backoff.d.ts +17 -0
- package/dist/channel/reconnect-backoff.js +21 -0
- package/dist/channel/reconnect-backoff.js.map +1 -0
- package/dist/cli.js +71 -26
- package/dist/cli.js.map +1 -1
- package/dist/completion.d.ts +27 -0
- package/dist/completion.js +121 -0
- package/dist/completion.js.map +1 -0
- package/dist/config-validator.js +9 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +74 -8
- package/dist/daemon.js +254 -18
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-manager.d.ts +7 -1
- package/dist/fleet-manager.js +89 -16
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +22 -0
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +14 -23
- package/dist/general-knowledge/skills/session-management/SKILL.md +15 -34
- package/dist/instance-lifecycle.d.ts +13 -1
- package/dist/instance-lifecycle.js +70 -3
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +5 -0
- package/dist/instructions.js +9 -11
- package/dist/instructions.js.map +1 -1
- package/dist/logger.js +14 -0
- package/dist/logger.js.map +1 -1
- package/dist/mcp-liveness.d.ts +21 -0
- package/dist/mcp-liveness.js +27 -0
- package/dist/mcp-liveness.js.map +1 -0
- package/dist/outbound-handlers.d.ts +9 -0
- package/dist/outbound-handlers.js +46 -26
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.js +1 -1
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/tmux-control.js +4 -2
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-manager.d.ts +14 -0
- package/dist/tmux-manager.js +20 -6
- package/dist/tmux-manager.js.map +1 -1
- package/dist/topic-commands.d.ts +22 -1
- package/dist/topic-commands.js +95 -57
- package/dist/topic-commands.js.map +1 -1
- package/dist/tui-glyphs.d.ts +25 -0
- package/dist/tui-glyphs.js +26 -0
- package/dist/tui-glyphs.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/ui/view.html +114 -2
- package/dist/usage/providers.d.ts +26 -0
- package/dist/usage/providers.js +447 -0
- package/dist/usage/providers.js.map +1 -0
- package/dist/usage/usage-api.d.ts +35 -0
- package/dist/usage/usage-api.js +52 -0
- package/dist/usage/usage-api.js.map +1 -0
- package/dist/view-api.d.ts +3 -0
- package/dist/view-api.js +10 -2
- package/dist/view-api.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,9 +2,10 @@ import { join } from "node:path";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { execFileSync } from "node:child_process";
|
|
4
4
|
import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
5
|
-
import {
|
|
5
|
+
import { resolveBinary, shellQuote, warnIfModelMismatch } from "./types.js";
|
|
6
6
|
import { appendWithMarker } from "./marker-utils.js";
|
|
7
7
|
import { getAgendHome } from "../paths.js";
|
|
8
|
+
import { PIE_CLASS } from "../tui-glyphs.js";
|
|
8
9
|
/** Parse `agy models`, which may emit slugs or human-readable display names. */
|
|
9
10
|
export function parseAntigravityModelsOutput(output) {
|
|
10
11
|
const models = [];
|
|
@@ -34,14 +35,9 @@ export class AntigravityBackend {
|
|
|
34
35
|
if (!config.skipResume)
|
|
35
36
|
cmd += " --continue";
|
|
36
37
|
if (config.model) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
cmd += ` --model ${config.model.replace(/[^a-zA-Z0-9_./ ()-]/g, "")}`;
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
console.warn(`[agend] model "${config.model}" is not compatible with antigravity — skipping --model, using the CLI's default`);
|
|
44
|
-
}
|
|
38
|
+
warnIfModelMismatch("antigravity", config.model);
|
|
39
|
+
// agy may expose human-readable model names containing spaces/parens.
|
|
40
|
+
cmd += ` --model ${shellQuote(config.model)}`;
|
|
45
41
|
}
|
|
46
42
|
return cmd;
|
|
47
43
|
}
|
|
@@ -140,8 +136,10 @@ node -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{t
|
|
|
140
136
|
}
|
|
141
137
|
getReadyPattern() {
|
|
142
138
|
// Startup/header: Gemini shortcut text. Daily prompts observed in the TUI
|
|
143
|
-
// are either "
|
|
144
|
-
|
|
139
|
+
// are either a pie context reading ("◑ 42%") on its own footer line, or a
|
|
140
|
+
// standalone ">" between separators. Pie branch is line-anchored so agent
|
|
141
|
+
// prose like "● 45% 完成" cannot false-ready the pane (● is in PIE_CLASS).
|
|
142
|
+
return new RegExp(`\\? for shortcuts|Gemini|^\\s*${PIE_CLASS}\\s*\\d+%|^>\\s*$`, "m");
|
|
145
143
|
}
|
|
146
144
|
getContextUsage() {
|
|
147
145
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"antigravity.js","sourceRoot":"","sources":["../../src/backend/antigravity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAChG,OAAO,EAAiF,
|
|
1
|
+
{"version":3,"file":"antigravity.js","sourceRoot":"","sources":["../../src/backend/antigravity.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveBinary, shellQuote, validateModel, warnIfModelMismatch } from "./types.js";
|
|
5
5
|
export class ClaudeCodeBackend {
|
|
6
6
|
instanceDir;
|
|
7
7
|
binaryName = "claude";
|
|
@@ -28,12 +28,9 @@ export class ClaudeCodeBackend {
|
|
|
28
28
|
cmd += " --continue";
|
|
29
29
|
}
|
|
30
30
|
if (config.model) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
console.warn(`[agend] model "${config.model}" is not compatible with claude-code — skipping --model, using the CLI's default`);
|
|
36
|
-
}
|
|
31
|
+
const model = validateModel(config.model);
|
|
32
|
+
warnIfModelMismatch("claude-code", model);
|
|
33
|
+
cmd += ` --model ${model}`;
|
|
37
34
|
}
|
|
38
35
|
// Additive system prompt: append fleet instructions without overriding Claude's built-in prompt
|
|
39
36
|
const instrFile = join(this.instanceDir, "fleet-instructions.md");
|
|
@@ -133,6 +130,9 @@ export class ClaudeCodeBackend {
|
|
|
133
130
|
{ id: "opus", label: "opus" },
|
|
134
131
|
{ id: "haiku", label: "haiku" },
|
|
135
132
|
{ id: "opusplan", label: "opusplan", description: "opus plans, sonnet executes" },
|
|
133
|
+
// Capitalised because that is the form verified to work with
|
|
134
|
+
// `claude --model Fable`; the lowercase alias is unconfirmed.
|
|
135
|
+
{ id: "Fable", label: "Fable", description: "Claude Fable 5" },
|
|
136
136
|
];
|
|
137
137
|
}
|
|
138
138
|
async probeCLIEnv() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/backend/claude-code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAqG,
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/backend/claude-code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAqG,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAG9L,MAAM,OAAO,iBAAiB;IAKR;IAJX,UAAU,GAAG,QAAQ,CAAC;IACtB,4BAA4B,GAAG,IAAI,CAAC;IACrC,UAAU,CAAS;IAE3B,YAAoB,WAAmB;QAAnB,gBAAW,GAAX,WAAW,CAAQ;QACrC,IAAI,CAAC,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,YAAY,CAAC,MAAwB;QACnC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,CAAC;QACpE,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;QAChE,MAAM,SAAS,GAAG,CAAC,8BAA8B,EAAE,wCAAwC,CAAC,CAAC;QAC7F,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB;YAAE,SAAS,CAAC,IAAI,CAAC,sBAAsB,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QACvH,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YAC7D,SAAS,CAAC,IAAI,CAAC,qBAAqB,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,GAAG,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,eAAe,YAAY,iBAAiB,aAAa,EAAE,CAAC;QAC/G,IAAI,MAAM,CAAC,eAAe,KAAK,KAAK;YAAE,GAAG,IAAI,iCAAiC,CAAC;QAE/E,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YACpD,GAAG,IAAI,aAAa,CAAC;QACvB,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC1C,mBAAmB,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;YAC1C,GAAG,IAAI,YAAY,KAAK,EAAE,CAAC;QAC7B,CAAC;QAED,gGAAgG;QAChG,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC;QAClE,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1B,GAAG,IAAI,gCAAgC,SAAS,EAAE,CAAC;QACrD,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;IAED,WAAW,CAAC,MAAwB;QAClC,qEAAqE;QACrE,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;QAChE,MAAM,SAAS,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;QACpD,aAAa,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAEjE,6BAA6B;QAC7B,MAAM,iBAAiB,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAEvD,wFAAwF;QACxF,MAAM,QAAQ,GAA4B;YACxC,UAAU,EAAE;gBACV,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,iBAAiB;aAC3B;SACF,CAAC;QACF,aAAa,CACX,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,EAC9C,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CACzB,CAAC;QAEF,+DAA+D;QAC/D,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAE9B,4EAA4E;QAC5E,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,IAAI,CAAC;gBAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;QAC1H,CAAC;IACH,CAAC;IAED,eAAe;QACb,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,eAAe;QACb,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;YACrD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,cAAc,EAAE,eAAe,IAAI,IAAI,CAAC;QACtD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,4EAA4E;YAC5E,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,YAAY;QACV,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;YACrD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,gBAAgB;QACd,OAAO;YACL,EAAE,OAAO,EAAE,wBAAwB,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,wBAAwB,EAAE;YAChH,EAAE,OAAO,EAAE,iDAAiD,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,gDAAgD,EAAE;YAC/J,EAAE,OAAO,EAAE,4BAA4B,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE;YAC/G,EAAE,OAAO,EAAE,wBAAwB,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE;YACtG,EAAE,OAAO,EAAE,4BAA4B,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,0BAA0B,EAAE;SAC/G,CAAC;IACJ,CAAC;IAED,iBAAiB;QACf,OAAO;YACL,2EAA2E;YAC3E,wEAAwE;YACxE,EAAE,OAAO,EAAE,qCAAqC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,mEAAmE,EAAE;YAC7J,EAAE,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,kDAAkD,EAAE;YAC3H,EAAE,OAAO,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,qCAAqC,EAAE;YACrG,EAAE,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,4CAA4C,EAAE;SAC5G,CAAC;IACJ,CAAC;IAED,iBAAiB;QACf,OAAO;YACL;gBACE,uEAAuE;gBACvE,wEAAwE;gBACxE,OAAO,EAAE,qCAAqC;gBAC9C,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;gBACvB,WAAW,EAAE,mEAAmE;aACjF;SACF,CAAC;IACJ,CAAC;IAED,cAAc,KAAa,OAAO,OAAO,CAAC,CAAC,CAAC;IAE5C,iBAAiB,KAAa,OAAO,UAAU,CAAC,CAAC,CAAC;IAElD,YAAY,KAAa,OAAO,QAAQ,CAAC,CAAC,CAAC;IAE3C,gFAAgF;IAChF,sBAAsB,KAA4B,OAAO,SAAS,CAAC,CAAC,CAAC;IAErE,KAAK,CAAC,UAAU;QACd,OAAO;YACL,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,iBAAiB,EAAE;YACnE,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;YACjC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;YAC7B,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;YAC/B,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,6BAA6B,EAAE;YACjF,6DAA6D;YAC7D,8DAA8D;YAC9D,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE;SAC/D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW;QACf,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QACvD,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;IACxF,CAAC;IAED,OAAO,CAAC,OAAyB;QAC/B,0EAA0E;IAC5E,CAAC;IAED,qFAAqF;IAC7E,gBAAgB,CAAC,OAAyB;QAChD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC7C,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACpE,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;QAEvD,IAAI,SAAS,GAA4B,EAAE,CAAC;QAC5C,IAAI,CAAC;YACH,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,CAAC;QAAC,MAAM,CAAC,CAAC,6BAA6B,CAAC,CAAC;QAEzC,MAAM,QAAQ,GAAG,SAAS,CAAC,qBAAiF,CAAC;QAC7G,MAAM,QAAQ,GAAG,QAAQ,EAAE,QAAQ,IAAI,EAAE,CAAC;QAC1C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACpC,SAAS,CAAC,qBAAqB,GAAG;gBAChC,QAAQ,EAAE,CAAC,GAAG,QAAQ,EAAE,WAAW,CAAC;gBACpC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE;aACnC,CAAC;YACF,aAAa,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,kEAAkE;IAC1D,eAAe;QACrB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;YAC/E,OAAO,CAAC,CAAC,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAEO,qBAAqB;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;QAC7D,oFAAoF;QACpF,MAAM,MAAM,GAAG;YACb,qBAAqB;YACrB,2BAA2B;YAC3B,iBAAiB;YACjB,4CAA4C;YAC5C,oDAAoD,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,kCAAkC;SACjH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;QAC3D,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnD,OAAO,UAAU,CAAC;IACpB,CAAC;CACF"}
|
package/dist/backend/codex.d.ts
CHANGED
|
@@ -3,7 +3,10 @@ export declare class CodexBackend implements CliBackend {
|
|
|
3
3
|
private instanceDir;
|
|
4
4
|
readonly binaryName = "codex";
|
|
5
5
|
private binaryPath;
|
|
6
|
+
private readonly sharedCodexHome;
|
|
7
|
+
private readonly isolatedCodexHome;
|
|
6
8
|
constructor(instanceDir: string);
|
|
9
|
+
supportsQueuedInput(): boolean;
|
|
7
10
|
buildCommand(config: CliBackendConfig): string;
|
|
8
11
|
writeConfig(config: CliBackendConfig): void;
|
|
9
12
|
/**
|
|
@@ -20,6 +23,19 @@ export declare class CodexBackend implements CliBackend {
|
|
|
20
23
|
*/
|
|
21
24
|
private enableContextStatusLine;
|
|
22
25
|
preTrust(workDir: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Preserve Codex login/session/cache behavior while isolating config.toml.
|
|
28
|
+
* Before this fix all instances shared CODEX_HOME, so sharing these runtime
|
|
29
|
+
* files is intentionally unchanged. Only config.toml (which contains MCP
|
|
30
|
+
* capabilities and AGEND_DECISIONS) becomes private to this instance.
|
|
31
|
+
*/
|
|
32
|
+
private prepareIsolatedHome;
|
|
33
|
+
/**
|
|
34
|
+
* One-time migration for installations polluted by the old global `codex
|
|
35
|
+
* mcp add` path. The lock protects separate fleet processes/upgrades, and
|
|
36
|
+
* atomic rename prevents readers from observing a truncated config.
|
|
37
|
+
*/
|
|
38
|
+
private cleanSharedConfig;
|
|
23
39
|
getReadyPattern(): RegExp;
|
|
24
40
|
getErrorPatterns(): ErrorPattern[];
|
|
25
41
|
getStartupDialogs(): StartupDialog[];
|
package/dist/backend/codex.js
CHANGED
|
@@ -1,12 +1,94 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { chmodSync, closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, statSync, symlinkSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
3
2
|
import { homedir } from "node:os";
|
|
4
|
-
import { dirname, join } from "node:path";
|
|
5
|
-
import {
|
|
3
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
4
|
+
import { probeCliVersion, resolveBinary, shellQuote, validateModel, warnIfModelMismatch } from "./types.js";
|
|
6
5
|
import { appendWithMarker, removeMarker } from "./marker-utils.js";
|
|
7
6
|
const CODEX_PROJECT_DOC_MAX_BYTES = 32_768;
|
|
8
7
|
const CODEX_MODELS_CACHE_MAX_BYTES = 5 * 1024 * 1024;
|
|
9
8
|
const SAFE_MODEL_ID_RE = /^[A-Za-z0-9._:/-]+$/;
|
|
9
|
+
const AGEND_MCP_CLEANUP_LOCK = ".agend-mcp-cleanup.lock";
|
|
10
|
+
const AGEND_MCP_CLEANUP_LOCK_STALE_MS = 30_000;
|
|
11
|
+
/**
|
|
12
|
+
* Remove AgEnD-owned MCP tables from a Codex TOML config without touching
|
|
13
|
+
* unrelated user settings or third-party MCP servers. Track TOML multiline
|
|
14
|
+
* strings so a line such as `[heading]` inside AGEND_DECISIONS cannot be
|
|
15
|
+
* mistaken for the start of another table.
|
|
16
|
+
*/
|
|
17
|
+
function stripAgendMcpTables(content) {
|
|
18
|
+
const lines = content.split(/(?<=\n)/);
|
|
19
|
+
let skipping = false;
|
|
20
|
+
let multiline = null;
|
|
21
|
+
let removed = false;
|
|
22
|
+
const kept = [];
|
|
23
|
+
for (const line of lines) {
|
|
24
|
+
if (!multiline) {
|
|
25
|
+
const header = line.match(/^\s*\[([^\]]+)\]\s*(?:#.*)?(?:\r?\n)?$/);
|
|
26
|
+
if (header) {
|
|
27
|
+
const path = header[1].trim();
|
|
28
|
+
skipping = /^mcp_servers\.(?:"|')?agend(?:-|(?=["'.]|$))/i.test(path);
|
|
29
|
+
if (skipping)
|
|
30
|
+
removed = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (!skipping)
|
|
34
|
+
kept.push(line);
|
|
35
|
+
// TOML multiline basic/literal strings may contain table-looking lines.
|
|
36
|
+
// Count unescaped delimiters and toggle only on an odd number.
|
|
37
|
+
for (const delimiter of ['"""', "'''"]) {
|
|
38
|
+
if (multiline && multiline !== delimiter)
|
|
39
|
+
continue;
|
|
40
|
+
let count = 0;
|
|
41
|
+
let pos = 0;
|
|
42
|
+
while ((pos = line.indexOf(delimiter, pos)) !== -1) {
|
|
43
|
+
if (delimiter === "'''" || pos === 0 || line[pos - 1] !== "\\")
|
|
44
|
+
count++;
|
|
45
|
+
pos += delimiter.length;
|
|
46
|
+
}
|
|
47
|
+
if (count % 2 === 1)
|
|
48
|
+
multiline = multiline === delimiter ? null : delimiter;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Avoid rewriting a clean user config merely to normalize whitespace.
|
|
52
|
+
return removed ? kept.join("") : content;
|
|
53
|
+
}
|
|
54
|
+
function tomlString(value) {
|
|
55
|
+
// JSON strings are valid TOML basic strings for the values AgEnD emits.
|
|
56
|
+
return JSON.stringify(value);
|
|
57
|
+
}
|
|
58
|
+
function renderMcpServer(name, entry, instanceName) {
|
|
59
|
+
const mcpName = `${name}-${instanceName}`.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
60
|
+
const env = { ...entry.env, AGEND_INSTANCE_NAME: instanceName };
|
|
61
|
+
const args = entry.args.map(tomlString).join(", ");
|
|
62
|
+
const envLines = Object.entries(env)
|
|
63
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
64
|
+
.map(([key, value]) => `${key} = ${tomlString(value)}`)
|
|
65
|
+
.join("\n");
|
|
66
|
+
return [
|
|
67
|
+
`[mcp_servers.${mcpName}]`,
|
|
68
|
+
`command = ${tomlString(entry.command)}`,
|
|
69
|
+
`args = [${args}]`,
|
|
70
|
+
"",
|
|
71
|
+
`[mcp_servers.${mcpName}.env]`,
|
|
72
|
+
envLines,
|
|
73
|
+
"",
|
|
74
|
+
].join("\n");
|
|
75
|
+
}
|
|
76
|
+
function atomicWritePrivate(path, content) {
|
|
77
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
78
|
+
const tempPath = join(dirname(path), `.${basename(path)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
79
|
+
try {
|
|
80
|
+
writeFileSync(tempPath, content, { encoding: "utf-8", mode: 0o600, flag: "wx" });
|
|
81
|
+
chmodSync(tempPath, 0o600);
|
|
82
|
+
renameSync(tempPath, path);
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
try {
|
|
86
|
+
if (existsSync(tempPath))
|
|
87
|
+
unlinkSync(tempPath);
|
|
88
|
+
}
|
|
89
|
+
catch { }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
10
92
|
// Account-aware models_cache.json is preferred. These documented Codex models
|
|
11
93
|
// are only a last-resort menu when the TUI has not populated its cache yet.
|
|
12
94
|
const CODEX_FALLBACK_MODELS = [
|
|
@@ -18,9 +100,16 @@ export class CodexBackend {
|
|
|
18
100
|
instanceDir;
|
|
19
101
|
binaryName = "codex";
|
|
20
102
|
binaryPath;
|
|
103
|
+
sharedCodexHome;
|
|
104
|
+
isolatedCodexHome;
|
|
21
105
|
constructor(instanceDir) {
|
|
22
106
|
this.instanceDir = instanceDir;
|
|
23
107
|
this.binaryPath = resolveBinary("codex");
|
|
108
|
+
this.sharedCodexHome = resolve(process.env.CODEX_HOME?.trim() || join(homedir(), ".codex"));
|
|
109
|
+
this.isolatedCodexHome = resolve(instanceDir, "codex-home");
|
|
110
|
+
}
|
|
111
|
+
supportsQueuedInput() {
|
|
112
|
+
return true;
|
|
24
113
|
}
|
|
25
114
|
buildCommand(config) {
|
|
26
115
|
const approvalFlag = config.skipPermissions !== false
|
|
@@ -38,49 +127,32 @@ export class CodexBackend {
|
|
|
38
127
|
cmd = `${this.binaryPath} resume --last ${approvalFlag}`;
|
|
39
128
|
}
|
|
40
129
|
if (config.model) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
console.warn(`[agend] model "${config.model}" is not compatible with codex — skipping model override, using the CLI's default`);
|
|
46
|
-
}
|
|
130
|
+
const model = validateModel(config.model);
|
|
131
|
+
warnIfModelMismatch("codex", model);
|
|
132
|
+
cmd += ` -c model="${model}"`;
|
|
47
133
|
}
|
|
48
|
-
|
|
134
|
+
// CODEX_HOME is the only Codex-supported way to isolate the complete base
|
|
135
|
+
// config. A profile only layers over the shared config and would therefore
|
|
136
|
+
// still load every globally registered AgEnD MCP server.
|
|
137
|
+
return `CODEX_HOME=${shellQuote(this.isolatedCodexHome)} ${cmd}`;
|
|
49
138
|
}
|
|
50
139
|
writeConfig(config) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// would otherwise fail silently, leaving the instance with no reply MCP
|
|
58
|
-
// server. Sanitize to the safe charset codex accepts.
|
|
59
|
-
const mcpName = `${name}-${config.instanceName}`.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
60
|
-
const allEnv = { ...entry.env, AGEND_INSTANCE_NAME: config.instanceName };
|
|
61
|
-
const args = ["mcp", "add", mcpName];
|
|
62
|
-
for (const [k, v] of Object.entries(allEnv)) {
|
|
63
|
-
args.push("--env", `${k}=${v}`);
|
|
64
|
-
}
|
|
65
|
-
args.push("--", entry.command, ...entry.args);
|
|
66
|
-
// Remove existing entry first (codex mcp add fails if name exists)
|
|
67
|
-
try {
|
|
68
|
-
execFileSync(this.binaryPath, ["mcp", "remove", mcpName], { stdio: "ignore" });
|
|
69
|
-
}
|
|
70
|
-
catch { /* may not exist */ }
|
|
71
|
-
// Surface add failures — a silent failure means no reply MCP server.
|
|
72
|
-
try {
|
|
73
|
-
execFileSync(this.binaryPath, args, { stdio: "ignore" });
|
|
74
|
-
}
|
|
75
|
-
catch (e) {
|
|
76
|
-
console.warn(`[codex] mcp add "${mcpName}" failed: ${e.message}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
// Clean up old non-namespaced key if present (one-time migration)
|
|
140
|
+
this.prepareIsolatedHome();
|
|
141
|
+
this.cleanSharedConfig();
|
|
142
|
+
// Copy all user settings but no AgEnD MCP entries into a private base
|
|
143
|
+
// config, then append only this instance's server(s). Each instance writes
|
|
144
|
+
// a distinct file, eliminating the old concurrent global-config race.
|
|
145
|
+
let content = "";
|
|
80
146
|
try {
|
|
81
|
-
|
|
147
|
+
content = stripAgendMcpTables(readFileSync(join(this.sharedCodexHome, "config.toml"), "utf-8"));
|
|
82
148
|
}
|
|
83
|
-
catch { /* may
|
|
149
|
+
catch { /* a first-time Codex user may have no global config */ }
|
|
150
|
+
if (content && !content.endsWith("\n"))
|
|
151
|
+
content += "\n";
|
|
152
|
+
for (const [name, entry] of Object.entries(config.mcpServers)) {
|
|
153
|
+
content += `\n${renderMcpServer(name, entry, config.instanceName)}`;
|
|
154
|
+
}
|
|
155
|
+
atomicWritePrivate(join(this.isolatedCodexHome, "config.toml"), content);
|
|
84
156
|
this.enableContextStatusLine();
|
|
85
157
|
// Write fleet instructions into AGENTS.md (additive via marker block)
|
|
86
158
|
if (config.instructions) {
|
|
@@ -112,7 +184,7 @@ export class CodexBackend {
|
|
|
112
184
|
* ~/.codex/config.toml (no toml dependency); other settings untouched.
|
|
113
185
|
*/
|
|
114
186
|
enableContextStatusLine() {
|
|
115
|
-
const configPath = join(
|
|
187
|
+
const configPath = join(this.isolatedCodexHome, "config.toml");
|
|
116
188
|
let content = "";
|
|
117
189
|
try {
|
|
118
190
|
content = readFileSync(configPath, "utf-8");
|
|
@@ -143,13 +215,12 @@ export class CodexBackend {
|
|
|
143
215
|
}
|
|
144
216
|
}
|
|
145
217
|
try {
|
|
146
|
-
|
|
147
|
-
writeFileSync(configPath, content);
|
|
218
|
+
atomicWritePrivate(configPath, content);
|
|
148
219
|
}
|
|
149
220
|
catch { /* best effort — never block launch on statusline config */ }
|
|
150
221
|
}
|
|
151
222
|
preTrust(workDir) {
|
|
152
|
-
const configPath = join(
|
|
223
|
+
const configPath = join(this.isolatedCodexHome, "config.toml");
|
|
153
224
|
let content = "";
|
|
154
225
|
try {
|
|
155
226
|
content = readFileSync(configPath, "utf-8");
|
|
@@ -158,8 +229,96 @@ export class CodexBackend {
|
|
|
158
229
|
const section = `[projects."${workDir}"]`;
|
|
159
230
|
if (content.includes(section))
|
|
160
231
|
return;
|
|
161
|
-
|
|
162
|
-
|
|
232
|
+
atomicWritePrivate(configPath, `${content.trimEnd()}\n\n${section}\ntrust_level = "trusted"\n`);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Preserve Codex login/session/cache behavior while isolating config.toml.
|
|
236
|
+
* Before this fix all instances shared CODEX_HOME, so sharing these runtime
|
|
237
|
+
* files is intentionally unchanged. Only config.toml (which contains MCP
|
|
238
|
+
* capabilities and AGEND_DECISIONS) becomes private to this instance.
|
|
239
|
+
*/
|
|
240
|
+
prepareIsolatedHome() {
|
|
241
|
+
mkdirSync(this.isolatedCodexHome, { recursive: true, mode: 0o700 });
|
|
242
|
+
chmodSync(this.isolatedCodexHome, 0o700);
|
|
243
|
+
if (this.sharedCodexHome === this.isolatedCodexHome || !existsSync(this.sharedCodexHome))
|
|
244
|
+
return;
|
|
245
|
+
for (const name of readdirSync(this.sharedCodexHome)) {
|
|
246
|
+
if (name === "config.toml" || name === AGEND_MCP_CLEANUP_LOCK || name.startsWith(".config.toml."))
|
|
247
|
+
continue;
|
|
248
|
+
const source = join(this.sharedCodexHome, name);
|
|
249
|
+
const target = join(this.isolatedCodexHome, name);
|
|
250
|
+
if (existsSync(target))
|
|
251
|
+
continue;
|
|
252
|
+
try {
|
|
253
|
+
const type = lstatSync(source).isDirectory() ? "dir" : "file";
|
|
254
|
+
symlinkSync(source, target, type);
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
// State/cache links are compatibility aids; config isolation must not
|
|
258
|
+
// fail merely because a concurrently-created cache entry disappeared.
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* One-time migration for installations polluted by the old global `codex
|
|
264
|
+
* mcp add` path. The lock protects separate fleet processes/upgrades, and
|
|
265
|
+
* atomic rename prevents readers from observing a truncated config.
|
|
266
|
+
*/
|
|
267
|
+
cleanSharedConfig() {
|
|
268
|
+
if (this.sharedCodexHome === this.isolatedCodexHome)
|
|
269
|
+
return;
|
|
270
|
+
mkdirSync(this.sharedCodexHome, { recursive: true, mode: 0o700 });
|
|
271
|
+
const lockPath = join(this.sharedCodexHome, AGEND_MCP_CLEANUP_LOCK);
|
|
272
|
+
let lockFd;
|
|
273
|
+
const acquire = () => {
|
|
274
|
+
try {
|
|
275
|
+
lockFd = openSync(lockPath, "wx", 0o600);
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
if (!acquire()) {
|
|
283
|
+
try {
|
|
284
|
+
if (Date.now() - statSync(lockPath).mtimeMs > AGEND_MCP_CLEANUP_LOCK_STALE_MS) {
|
|
285
|
+
unlinkSync(lockPath);
|
|
286
|
+
if (!acquire())
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
const configPath = join(this.sharedCodexHome, "config.toml");
|
|
299
|
+
let content;
|
|
300
|
+
try {
|
|
301
|
+
content = readFileSync(configPath, "utf-8");
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const cleaned = stripAgendMcpTables(content);
|
|
307
|
+
if (cleaned !== content)
|
|
308
|
+
atomicWritePrivate(configPath, cleaned);
|
|
309
|
+
}
|
|
310
|
+
finally {
|
|
311
|
+
if (lockFd !== undefined) {
|
|
312
|
+
try {
|
|
313
|
+
closeSync(lockFd);
|
|
314
|
+
}
|
|
315
|
+
catch { }
|
|
316
|
+
}
|
|
317
|
+
try {
|
|
318
|
+
unlinkSync(lockPath);
|
|
319
|
+
}
|
|
320
|
+
catch { }
|
|
321
|
+
}
|
|
163
322
|
}
|
|
164
323
|
getReadyPattern() {
|
|
165
324
|
// Startup/header: "OpenAI Codex". Daily prompt: a line beginning with ">".
|
|
@@ -172,6 +331,28 @@ export class CodexBackend {
|
|
|
172
331
|
{ pattern: /authentication|401 Unauthorized/i, type: "auth_error", action: "pause", message: "OpenAI authentication error" },
|
|
173
332
|
{ pattern: /insufficient_quota|billing/i, type: "quota", action: "pause", message: "OpenAI quota exceeded" },
|
|
174
333
|
{ pattern: /you've hit your usage limit/i, type: "quota", action: "pause", message: "Codex usage limit reached — upgrade plan required" },
|
|
334
|
+
// Workspace (team) accounts report exhaustion differently from personal
|
|
335
|
+
// ones — the full line is:
|
|
336
|
+
// "■ Your workspace is out of credits. Ask your workspace owner to
|
|
337
|
+
// refill in order to continue."
|
|
338
|
+
// Neither `insufficient_quota|billing` nor `you've hit your usage limit`
|
|
339
|
+
// matches it, so this state went unreported.
|
|
340
|
+
//
|
|
341
|
+
// `\s+` at each word gap: capture-pane runs without -J, so tmux's hard
|
|
342
|
+
// wrap can land a newline anywhere in the phrase. The `■` prefix and the
|
|
343
|
+
// "Ask your workspace owner…" tail are deliberately left out — the prefix
|
|
344
|
+
// is decoration and the tail is what would wrap.
|
|
345
|
+
{
|
|
346
|
+
pattern: /workspace\s+is\s+out\s+of\s+credits/i,
|
|
347
|
+
type: "quota",
|
|
348
|
+
// pause, not notify: exhausted credits are a dead end until someone
|
|
349
|
+
// refills, so leaving the instance running just burns cycles failing.
|
|
350
|
+
// Matches how the other terminal quota states behave (claude-code's
|
|
351
|
+
// "credit balance is too low", codex's own "you've hit your usage
|
|
352
|
+
// limit"). Costs a manual resume after the refill.
|
|
353
|
+
action: "pause",
|
|
354
|
+
message: "Codex workspace credits exhausted — workspace owner must refill",
|
|
355
|
+
},
|
|
175
356
|
// Codex warns at 10% and 5% remaining, and scopes the limit by period —
|
|
176
357
|
// "weekly" alone missed every `monthly limit` warning.
|
|
177
358
|
//
|
|
@@ -228,8 +409,10 @@ export class CodexBackend {
|
|
|
228
409
|
*/
|
|
229
410
|
async listModels() {
|
|
230
411
|
try {
|
|
231
|
-
const
|
|
232
|
-
const cachePath =
|
|
412
|
+
const isolatedCache = join(this.isolatedCodexHome, "models_cache.json");
|
|
413
|
+
const cachePath = existsSync(isolatedCache)
|
|
414
|
+
? isolatedCache
|
|
415
|
+
: join(this.sharedCodexHome, "models_cache.json");
|
|
233
416
|
if (statSync(cachePath).size > CODEX_MODELS_CACHE_MAX_BYTES) {
|
|
234
417
|
return CODEX_FALLBACK_MODELS.map(model => ({ ...model }));
|
|
235
418
|
}
|
|
@@ -263,10 +446,15 @@ export class CodexBackend {
|
|
|
263
446
|
return CODEX_FALLBACK_MODELS.map(model => ({ ...model }));
|
|
264
447
|
}
|
|
265
448
|
async probeCLIEnv() {
|
|
266
|
-
// The configured model is readable from
|
|
449
|
+
// The configured model is readable from the isolated base config. Fall
|
|
450
|
+
// back to the shared user config before this instance has been prepared.
|
|
267
451
|
let currentModel;
|
|
268
452
|
try {
|
|
269
|
-
|
|
453
|
+
const isolatedConfig = join(this.isolatedCodexHome, "config.toml");
|
|
454
|
+
const configPath = existsSync(isolatedConfig)
|
|
455
|
+
? isolatedConfig
|
|
456
|
+
: join(this.sharedCodexHome, "config.toml");
|
|
457
|
+
currentModel = readFileSync(configPath, "utf-8")
|
|
270
458
|
.split("\n")
|
|
271
459
|
.map(l => l.trim())
|
|
272
460
|
.filter(l => !l.startsWith("#")) // skip comments
|
|
@@ -277,14 +465,15 @@ export class CodexBackend {
|
|
|
277
465
|
return { version: probeCliVersion(this.binaryPath), models: await this.listModels(), currentModel };
|
|
278
466
|
}
|
|
279
467
|
cleanup(config) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
catch { /* best effort */ }
|
|
468
|
+
// Never mutate the shared Codex config from instance cleanup. Remove the
|
|
469
|
+
// private AgEnD capability while preserving sessions and user settings.
|
|
470
|
+
try {
|
|
471
|
+
const configPath = join(this.isolatedCodexHome, "config.toml");
|
|
472
|
+
const content = readFileSync(configPath, "utf-8");
|
|
473
|
+
atomicWritePrivate(configPath, stripAgendMcpTables(content));
|
|
287
474
|
}
|
|
475
|
+
catch { /* best effort */ }
|
|
476
|
+
this.cleanSharedConfig();
|
|
288
477
|
// Remove fleet instructions marker block from AGENTS.md
|
|
289
478
|
try {
|
|
290
479
|
const agentsMd = join(config.workingDirectory, "AGENTS.md");
|
|
@@ -293,14 +482,14 @@ export class CodexBackend {
|
|
|
293
482
|
unlinkSync(agentsMd);
|
|
294
483
|
}
|
|
295
484
|
catch { /* best effort */ }
|
|
296
|
-
// Remove trust entry from
|
|
485
|
+
// Remove trust entry from the isolated Codex config.
|
|
297
486
|
try {
|
|
298
|
-
const configPath = join(
|
|
487
|
+
const configPath = join(this.isolatedCodexHome, "config.toml");
|
|
299
488
|
const content = readFileSync(configPath, "utf-8");
|
|
300
489
|
const escaped = config.workingDirectory.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
301
490
|
const re = new RegExp(`\\n?\\[projects\\."${escaped}"\\]\\ntrust_level = "trusted"\\n?`);
|
|
302
491
|
if (re.test(content)) {
|
|
303
|
-
|
|
492
|
+
atomicWritePrivate(configPath, content.replace(re, "\n"));
|
|
304
493
|
}
|
|
305
494
|
}
|
|
306
495
|
catch { /* best effort */ }
|