negotium 0.1.28 → 0.1.30
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/agent-helpers.js +972 -506
- package/dist/agent-helpers.js.map +18 -17
- package/dist/background-bash.js +60 -5
- package/dist/background-bash.js.map +4 -4
- package/dist/{chunk-7azk83mw.js → chunk-en2s6xnh.js} +60 -5
- package/dist/chunk-en2s6xnh.js.map +18 -0
- package/dist/cron.js +3797 -3224
- package/dist/cron.js.map +24 -24
- package/dist/hosted-agent.js +527 -71
- package/dist/hosted-agent.js.map +13 -12
- package/dist/main.js +2759 -1665
- package/dist/main.js.map +30 -30
- package/dist/mcp-factories.js +58 -3
- package/dist/mcp-factories.js.map +4 -4
- package/dist/prompts.js +58 -3
- package/dist/prompts.js.map +4 -4
- package/dist/registry.js +1 -1
- package/dist/rollout.js +1 -1
- package/dist/runtime/scripts/browser-passkey-policy.mjs +15 -4
- package/dist/runtime/scripts/browser-vault-transform.mjs +5 -1
- package/dist/runtime/scripts/mcp-patchright-http.mjs +241 -26
- package/dist/runtime/src/agents/api-topic-agent-switch.ts +1 -1
- package/dist/runtime/src/agents/auth-check.ts +36 -10
- package/dist/runtime/src/agents/claude-provider.ts +6 -11
- package/dist/runtime/src/agents/codex-native-multi-agent.ts +159 -42
- package/dist/runtime/src/agents/codex-provider.ts +198 -8
- package/dist/runtime/src/agents/maestro-provider.ts +26 -0
- package/dist/runtime/src/agents/mcp-tools/spawn-subagent.ts +1 -1
- package/dist/runtime/src/agents/rollout/codex.ts +198 -2
- package/dist/runtime/src/agents/rollout/index.ts +6 -0
- package/dist/runtime/src/agents/self-config-core.ts +1 -1
- package/dist/runtime/src/agents/tool-format.ts +228 -15
- package/dist/runtime/src/agents/topic-agent-switch.ts +1 -1
- package/dist/runtime/src/application/switch-topic-model.ts +1 -1
- package/dist/runtime/src/bus.ts +21 -3
- package/dist/runtime/src/mcp/browser-sse-proxy-server.ts +48 -0
- package/dist/runtime/src/platform/config.ts +80 -4
- package/dist/runtime/src/platform/mcp-config.ts +13 -9
- package/dist/runtime/src/platform/playwright/manager.ts +24 -14
- package/dist/runtime/src/runtime/turn-runner.ts +11 -5
- package/dist/runtime/src/types/api.ts +2 -0
- package/dist/runtime/src/types.ts +2 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js +58 -3
- package/dist/runtime-helpers.js.map +4 -4
- package/dist/storage.js.map +1 -1
- package/dist/types/packages/core/src/agents/auth-check.d.ts +3 -2
- package/dist/types/packages/core/src/agents/codex-native-multi-agent.d.ts +6 -4
- package/dist/types/packages/core/src/agents/maestro-provider.d.ts +13 -0
- package/dist/types/packages/core/src/agents/rollout/codex.d.ts +24 -0
- package/dist/types/packages/core/src/agents/rollout/index.d.ts +2 -2
- package/dist/types/packages/core/src/agents/tool-format.d.ts +16 -9
- package/dist/types/packages/core/src/bus.d.ts +2 -2
- package/dist/types/packages/core/src/platform/config.d.ts +13 -1
- package/dist/types/packages/core/src/types/api.d.ts +2 -0
- package/dist/types/packages/core/src/types.d.ts +2 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +58 -3
- package/dist/vault.js.map +4 -4
- package/install-browser-rs.mjs +77 -0
- package/package.json +6 -3
- package/dist/chunk-7azk83mw.js.map +0 -18
package/dist/hosted-agent.js
CHANGED
|
@@ -28,8 +28,17 @@ import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
|
|
|
28
28
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
29
29
|
|
|
30
30
|
// ../../packages/core/src/platform/config.ts
|
|
31
|
+
import { execFileSync } from "child_process";
|
|
31
32
|
import { randomBytes } from "crypto";
|
|
32
|
-
import {
|
|
33
|
+
import {
|
|
34
|
+
accessSync,
|
|
35
|
+
chmodSync,
|
|
36
|
+
constants,
|
|
37
|
+
existsSync,
|
|
38
|
+
mkdirSync,
|
|
39
|
+
readFileSync,
|
|
40
|
+
writeFileSync
|
|
41
|
+
} from "fs";
|
|
33
42
|
import { homedir } from "os";
|
|
34
43
|
import { dirname, join, resolve } from "path";
|
|
35
44
|
import { fileURLToPath } from "url";
|
|
@@ -122,7 +131,8 @@ var CONTEXTS_DIR = resolve(WORKSPACE_DIR, "contexts");
|
|
|
122
131
|
var BROWSER_PROFILES_DIR = resolve(WORKSPACE_DIR, "browser-profiles");
|
|
123
132
|
var DM_WORKSPACE_DIR = resolve(WORKSPACE_DIR, "dm");
|
|
124
133
|
var SESSION_WORKSPACE_DIR = resolve(WORKSPACE_DIR, "sessions");
|
|
125
|
-
var
|
|
134
|
+
var CLAUDE_EXECUTABLE_ENV = envText("NEGOTIUM_CLAUDE_EXECUTABLE");
|
|
135
|
+
var CLAUDE_EXECUTABLE = CLAUDE_EXECUTABLE_ENV ? resolve(CLAUDE_EXECUTABLE_ENV) : undefined;
|
|
126
136
|
function resolveBrowserMcpBin(envValue) {
|
|
127
137
|
const override = envValue?.trim();
|
|
128
138
|
if (override) {
|
|
@@ -135,10 +145,55 @@ function resolveBrowserMcpBin(envValue) {
|
|
|
135
145
|
}
|
|
136
146
|
var PATCHRIGHT_MCP_BIN = resolve(PROJECT_ROOT, "scripts/mcp-patchright-http.mjs");
|
|
137
147
|
var PLAYWRIGHT_MCP_BIN = resolveBrowserMcpBin(envText("NEGOTIUM_BROWSER_MCP_BIN"));
|
|
148
|
+
var BROWSER_RS_VERSION = "v0.1.12";
|
|
149
|
+
var BROWSER_RS_MIN_SECURE_VERSION = "0.1.12";
|
|
150
|
+
function versionAtLeast(actualVersion, minimumVersion) {
|
|
151
|
+
const actual = actualVersion.split(".").map(Number);
|
|
152
|
+
const minimum = minimumVersion.split(".").map(Number);
|
|
153
|
+
if (actual.some(Number.isNaN) || minimum.some(Number.isNaN))
|
|
154
|
+
return false;
|
|
155
|
+
for (let index = 0;index < minimum.length; index += 1) {
|
|
156
|
+
if ((actual[index] ?? 0) > (minimum[index] ?? 0))
|
|
157
|
+
return true;
|
|
158
|
+
if ((actual[index] ?? 0) < (minimum[index] ?? 0))
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
function browserRsMeetsMinimumVersion(candidate) {
|
|
164
|
+
try {
|
|
165
|
+
const output = execFileSync(candidate, ["--version"], {
|
|
166
|
+
encoding: "utf8",
|
|
167
|
+
timeout: 2000,
|
|
168
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
169
|
+
}).trim();
|
|
170
|
+
const match = output.match(/^browser-rs (\d+)\.(\d+)\.(\d+)$/);
|
|
171
|
+
if (!match)
|
|
172
|
+
return false;
|
|
173
|
+
return versionAtLeast(match.slice(1).join("."), BROWSER_RS_MIN_SECURE_VERSION);
|
|
174
|
+
} catch {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function resolveBrowserRsBin(envValue) {
|
|
179
|
+
const override = envValue?.trim();
|
|
180
|
+
if (!override && !versionAtLeast(BROWSER_RS_VERSION.replace(/^v/, ""), BROWSER_RS_MIN_SECURE_VERSION)) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const candidate = override ? resolve(override) : resolve(STATE_DIR, "bin", "browser-rs", BROWSER_RS_VERSION, "browser-rs");
|
|
184
|
+
try {
|
|
185
|
+
accessSync(candidate, constants.X_OK);
|
|
186
|
+
return browserRsMeetsMinimumVersion(candidate) ? candidate : undefined;
|
|
187
|
+
} catch {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
var BROWSER_RS_BIN = resolveBrowserRsBin(envText("NEGOTIUM_BROWSER_RS_BIN"));
|
|
138
192
|
var TSX_BIN = resolveDependencyBin("tsx");
|
|
139
193
|
var TSCONFIG_PATH = resolve(PROJECT_ROOT, "tsconfig.json");
|
|
140
194
|
var SESSION_COMM_SERVER = resolve(PROJECT_ROOT, "src/mcp/session-comm/server.ts");
|
|
141
195
|
var TASK_SERVER = resolve(PROJECT_ROOT, "src/mcp/task-server.ts");
|
|
196
|
+
var BROWSER_MCP_SSE_PROXY_SERVER = resolve(PROJECT_ROOT, "src/mcp/browser-sse-proxy-server.ts");
|
|
142
197
|
var CANONICAL_MCP_PROXY_SERVER = resolve(PROJECT_ROOT, "src/mcp/canonical-proxy-server.ts");
|
|
143
198
|
var WIKI_SERVER = resolve(PROJECT_ROOT, "src/mcp/wiki-server.ts");
|
|
144
199
|
var TOKEN_STATS_SERVER = resolve(PROJECT_ROOT, "src/mcp/token-stats-server.ts");
|
|
@@ -780,7 +835,7 @@ function peerSessionBridgeIpcEnv() {
|
|
|
780
835
|
}
|
|
781
836
|
|
|
782
837
|
// ../../packages/core/src/platform/background-bash/manager.ts
|
|
783
|
-
import { execFileSync, spawn } from "child_process";
|
|
838
|
+
import { execFileSync as execFileSync2, spawn } from "child_process";
|
|
784
839
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
785
840
|
|
|
786
841
|
// ../../packages/core/src/platform/delay.ts
|
|
@@ -798,7 +853,7 @@ function makeBgBashKey(_userId, _topic) {
|
|
|
798
853
|
}
|
|
799
854
|
function defaultPortPids(port) {
|
|
800
855
|
try {
|
|
801
|
-
return
|
|
856
|
+
return execFileSync2("lsof", ["-i", `:${port}`, "-t"], { stdio: "pipe" }).toString().trim().split(`
|
|
802
857
|
`).map((pid) => Number.parseInt(pid, 10)).filter((pid) => !Number.isNaN(pid));
|
|
803
858
|
} catch {
|
|
804
859
|
return [];
|
|
@@ -1049,23 +1104,23 @@ function browserOwnerForContext(ctx) {
|
|
|
1049
1104
|
function playwrightTransport(port, owner, capability, agent) {
|
|
1050
1105
|
const ownerCapability = browserOwnerCapability(capability, owner);
|
|
1051
1106
|
if (agent === "codex") {
|
|
1107
|
+
const query2 = new URLSearchParams({ owner });
|
|
1052
1108
|
return {
|
|
1053
|
-
url: `http://127.0.0.1:${port}/mcp`,
|
|
1054
|
-
http_headers: { "X-Browser-Owner": owner },
|
|
1109
|
+
url: `http://127.0.0.1:${port}/mcp?${query2}`,
|
|
1055
1110
|
env_http_headers: { "X-Browser-Capability": CODEX_BROWSER_CAPABILITY_ENV }
|
|
1056
1111
|
};
|
|
1057
1112
|
}
|
|
1113
|
+
const query = new URLSearchParams({ owner });
|
|
1058
1114
|
if (agent === "maestro") {
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
};
|
|
1115
|
+
return buildStdioMcpServer("maestro", BROWSER_MCP_SSE_PROXY_SERVER, [], {
|
|
1116
|
+
NEGOTIUM_BROWSER_SSE_URL: `http://127.0.0.1:${port}/sse?${query}`,
|
|
1117
|
+
NEGOTIUM_BROWSER_OWNER_CAPABILITY: ownerCapability
|
|
1118
|
+
});
|
|
1064
1119
|
}
|
|
1065
1120
|
return {
|
|
1066
1121
|
type: "sse",
|
|
1067
|
-
url: `http://127.0.0.1:${port}/sse`,
|
|
1068
|
-
headers: { "X-Browser-
|
|
1122
|
+
url: `http://127.0.0.1:${port}/sse?${query}`,
|
|
1123
|
+
headers: { "X-Browser-Capability": ownerCapability }
|
|
1069
1124
|
};
|
|
1070
1125
|
}
|
|
1071
1126
|
function longLivedHttpMcp(agent, port) {
|
|
@@ -1626,6 +1681,11 @@ function vaultListWithValues(userId) {
|
|
|
1626
1681
|
value: decryptRow(userId, row.key, row.value)
|
|
1627
1682
|
}));
|
|
1628
1683
|
}
|
|
1684
|
+
function vaultGetValue(userId, key) {
|
|
1685
|
+
const normalizedKey = normalizeVaultKey(key);
|
|
1686
|
+
const row = activeVaultDatabase().prepare("SELECT key, value FROM vault WHERE user_id = ? AND key = ?").get(userId, normalizedKey);
|
|
1687
|
+
return row ? decryptRow(userId, row.key, row.value) : undefined;
|
|
1688
|
+
}
|
|
1629
1689
|
function vaultSubstituteDetailed(userId, text) {
|
|
1630
1690
|
const entries = new Map(vaultListWithValues(userId).map((entry) => [entry.key, entry.value]));
|
|
1631
1691
|
const usedKeys = new Set;
|
|
@@ -2139,12 +2199,6 @@ async function* claudeProvider(opts) {
|
|
|
2139
2199
|
const m = message;
|
|
2140
2200
|
if (m.subtype === "init") {
|
|
2141
2201
|
yield { type: "session", sessionId: m.session_id };
|
|
2142
|
-
} else if (m.subtype === "task_started") {
|
|
2143
|
-
const t = m;
|
|
2144
|
-
if (t.subagent_type && !t.skip_transcript) {
|
|
2145
|
-
const desc = t.description ? ` ${t.description.slice(0, 60)}` : "";
|
|
2146
|
-
yield { type: "status", content: `\u25B6 [${t.subagent_type}]${desc}` };
|
|
2147
|
-
}
|
|
2148
2202
|
} else {
|
|
2149
2203
|
logger.debug({ subtype: m.subtype, msg: m }, "claudeProvider: system message (unhandled subtype)");
|
|
2150
2204
|
}
|
|
@@ -2228,7 +2282,8 @@ async function* claudeProvider(opts) {
|
|
|
2228
2282
|
yield {
|
|
2229
2283
|
type: "tool_result",
|
|
2230
2284
|
toolUseId: trBlock.tool_use_id || "",
|
|
2231
|
-
content: trContent
|
|
2285
|
+
content: trContent,
|
|
2286
|
+
...trBlock.is_error ? { isError: true } : {}
|
|
2232
2287
|
};
|
|
2233
2288
|
}
|
|
2234
2289
|
}
|
|
@@ -2242,32 +2297,91 @@ async function* claudeProvider(opts) {
|
|
|
2242
2297
|
}
|
|
2243
2298
|
|
|
2244
2299
|
// ../../packages/core/src/agents/codex-provider.ts
|
|
2245
|
-
import {
|
|
2300
|
+
import { execFileSync as execFileSync4 } from "child_process";
|
|
2301
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, realpathSync as realpathSync3, statSync as statSync3 } from "fs";
|
|
2302
|
+
import { isAbsolute, relative, resolve as resolve5 } from "path";
|
|
2246
2303
|
import { Codex } from "@openai/codex-sdk";
|
|
2247
2304
|
|
|
2248
2305
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
2249
2306
|
import { spawn as spawn3 } from "child_process";
|
|
2307
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2250
2308
|
import {
|
|
2251
2309
|
chmodSync as chmodSync3,
|
|
2310
|
+
copyFileSync,
|
|
2252
2311
|
existsSync as existsSync5,
|
|
2312
|
+
mkdtempSync,
|
|
2253
2313
|
readFileSync as readFileSync5,
|
|
2254
2314
|
renameSync as renameSync3,
|
|
2315
|
+
rmSync,
|
|
2255
2316
|
unlinkSync as unlinkSync4,
|
|
2256
2317
|
writeFileSync as writeFileSync4
|
|
2257
2318
|
} from "fs";
|
|
2258
2319
|
import { createRequire } from "module";
|
|
2320
|
+
import { tmpdir } from "os";
|
|
2259
2321
|
import { dirname as dirname4, join as join6 } from "path";
|
|
2260
2322
|
|
|
2261
2323
|
// ../../packages/core/src/version.ts
|
|
2262
|
-
var NEGOTIUM_VERSION = "0.1.
|
|
2324
|
+
var NEGOTIUM_VERSION = "0.1.30";
|
|
2263
2325
|
|
|
2264
2326
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
2265
|
-
var NEGOTIUM_MODEL_CATALOG = "negotium-model-catalog.json";
|
|
2266
2327
|
var moduleRequire = createRequire(import.meta.url);
|
|
2328
|
+
var codexSdkPackagePath = moduleRequire.resolve("@openai/codex-sdk/package.json");
|
|
2329
|
+
var codexSdkRequire = createRequire(codexSdkPackagePath);
|
|
2330
|
+
var bundledCodexPackagePath = codexSdkRequire.resolve("@openai/codex/package.json");
|
|
2331
|
+
function readPackageVersion(packageJsonPath) {
|
|
2332
|
+
const parsed = JSON.parse(readFileSync5(packageJsonPath, "utf8"));
|
|
2333
|
+
if (typeof parsed.version !== "string" || !parsed.version.trim()) {
|
|
2334
|
+
throw new Error(`Codex package has no valid version: ${packageJsonPath}`);
|
|
2335
|
+
}
|
|
2336
|
+
return parsed.version;
|
|
2337
|
+
}
|
|
2338
|
+
var BUNDLED_CODEX_VERSION = readPackageVersion(bundledCodexPackagePath);
|
|
2339
|
+
var SAFE_BUNDLED_CODEX_VERSION = BUNDLED_CODEX_VERSION.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
2340
|
+
var NEGOTIUM_MODEL_CACHE = `negotium-models-cache-${SAFE_BUNDLED_CODEX_VERSION}.json`;
|
|
2341
|
+
var NEGOTIUM_MODEL_CATALOG = `negotium-model-catalog-${SAFE_BUNDLED_CODEX_VERSION}.json`;
|
|
2267
2342
|
function codexCliScriptPath() {
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2343
|
+
return join6(dirname4(bundledCodexPackagePath), "bin", "codex.js");
|
|
2344
|
+
}
|
|
2345
|
+
function parseCodexModelCache(contents, sourcePath) {
|
|
2346
|
+
let parsed;
|
|
2347
|
+
try {
|
|
2348
|
+
parsed = JSON.parse(contents);
|
|
2349
|
+
} catch (error) {
|
|
2350
|
+
throw new Error(`Codex model cache is invalid JSON: ${sourcePath}`, { cause: error });
|
|
2351
|
+
}
|
|
2352
|
+
if (!Array.isArray(parsed.models) || parsed.models.length === 0) {
|
|
2353
|
+
throw new Error(`Codex model cache has no models: ${sourcePath}`);
|
|
2354
|
+
}
|
|
2355
|
+
return parsed;
|
|
2356
|
+
}
|
|
2357
|
+
function readCodexModelCache(cachePath) {
|
|
2358
|
+
const contents = readFileSync5(cachePath, "utf8");
|
|
2359
|
+
return { contents, parsed: parseCodexModelCache(contents, cachePath) };
|
|
2360
|
+
}
|
|
2361
|
+
function readCompatibleCodexModelCache(cachePath) {
|
|
2362
|
+
const cache = readCodexModelCache(cachePath);
|
|
2363
|
+
if (cache.parsed.client_version !== BUNDLED_CODEX_VERSION) {
|
|
2364
|
+
const found = typeof cache.parsed.client_version === "string" ? cache.parsed.client_version : "missing or invalid";
|
|
2365
|
+
throw new Error(`Codex model cache version ${found} does not match Negotium's bundled Codex ${BUNDLED_CODEX_VERSION}: ${cachePath}`);
|
|
2366
|
+
}
|
|
2367
|
+
return cache;
|
|
2368
|
+
}
|
|
2369
|
+
function writePrivateFileAtomic(path, contents) {
|
|
2370
|
+
if (existsSync5(path) && readFileSync5(path, "utf8") === contents)
|
|
2371
|
+
return;
|
|
2372
|
+
const tempPath = `${path}.${process.pid}.${randomUUID2()}.tmp`;
|
|
2373
|
+
try {
|
|
2374
|
+
writeFileSync4(tempPath, contents, { encoding: "utf8", mode: 384 });
|
|
2375
|
+
renameSync3(tempPath, path);
|
|
2376
|
+
chmodSync3(path, 384);
|
|
2377
|
+
} finally {
|
|
2378
|
+
try {
|
|
2379
|
+
unlinkSync4(tempPath);
|
|
2380
|
+
} catch {}
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
function bundledCodexModelCachePath(authFilePath) {
|
|
2384
|
+
return join6(dirname4(authFilePath), NEGOTIUM_MODEL_CACHE);
|
|
2271
2385
|
}
|
|
2272
2386
|
async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
2273
2387
|
const child = spawn3(process.execPath, [codexCliScriptPath(), "app-server", "--stdio"], {
|
|
@@ -2351,25 +2465,59 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
2351
2465
|
});
|
|
2352
2466
|
});
|
|
2353
2467
|
}
|
|
2468
|
+
async function bootstrapIsolatedCodexModelCache(authFilePath, bootstrap) {
|
|
2469
|
+
const sourceHome = dirname4(authFilePath);
|
|
2470
|
+
const isolatedHome = mkdtempSync(join6(tmpdir(), "negotium-codex-models-"));
|
|
2471
|
+
const isolatedCachePath = join6(isolatedHome, "models_cache.json");
|
|
2472
|
+
try {
|
|
2473
|
+
const isolatedAuthPath = join6(isolatedHome, "auth.json");
|
|
2474
|
+
copyFileSync(authFilePath, isolatedAuthPath);
|
|
2475
|
+
chmodSync3(isolatedAuthPath, 384);
|
|
2476
|
+
const sourceConfigPath = join6(sourceHome, "config.toml");
|
|
2477
|
+
if (existsSync5(sourceConfigPath)) {
|
|
2478
|
+
const isolatedConfigPath = join6(isolatedHome, "config.toml");
|
|
2479
|
+
copyFileSync(sourceConfigPath, isolatedConfigPath);
|
|
2480
|
+
chmodSync3(isolatedConfigPath, 384);
|
|
2481
|
+
}
|
|
2482
|
+
await bootstrap(isolatedHome, isolatedCachePath);
|
|
2483
|
+
return readCompatibleCodexModelCache(isolatedCachePath).contents;
|
|
2484
|
+
} finally {
|
|
2485
|
+
rmSync(isolatedHome, { recursive: true, force: true });
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2354
2488
|
async function ensureCodexModelCache(authFilePath, bootstrap = bootstrapCodexModelCache) {
|
|
2355
2489
|
const codexHome = dirname4(authFilePath);
|
|
2356
|
-
const
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2490
|
+
const configuredCachePath = process.env.NEGOTIUM_CODEX_MODELS_CACHE_FILE;
|
|
2491
|
+
if (configuredCachePath) {
|
|
2492
|
+
if (!existsSync5(configuredCachePath)) {
|
|
2493
|
+
throw new Error(`Configured Codex model cache does not exist: ${configuredCachePath}`);
|
|
2494
|
+
}
|
|
2495
|
+
readCompatibleCodexModelCache(configuredCachePath);
|
|
2496
|
+
return configuredCachePath;
|
|
2362
2497
|
}
|
|
2363
|
-
|
|
2498
|
+
const bundledCachePath = bundledCodexModelCachePath(authFilePath);
|
|
2499
|
+
const sharedCachePath = join6(codexHome, "models_cache.json");
|
|
2500
|
+
if (existsSync5(sharedCachePath)) {
|
|
2501
|
+
try {
|
|
2502
|
+
const shared = readCompatibleCodexModelCache(sharedCachePath);
|
|
2503
|
+
writePrivateFileAtomic(bundledCachePath, shared.contents);
|
|
2504
|
+
return bundledCachePath;
|
|
2505
|
+
} catch {}
|
|
2506
|
+
}
|
|
2507
|
+
if (existsSync5(bundledCachePath)) {
|
|
2508
|
+
try {
|
|
2509
|
+
readCompatibleCodexModelCache(bundledCachePath);
|
|
2510
|
+
return bundledCachePath;
|
|
2511
|
+
} catch {}
|
|
2512
|
+
}
|
|
2513
|
+
const refreshedContents = await bootstrapIsolatedCodexModelCache(authFilePath, bootstrap);
|
|
2514
|
+
writePrivateFileAtomic(bundledCachePath, refreshedContents);
|
|
2515
|
+
return bundledCachePath;
|
|
2364
2516
|
}
|
|
2365
|
-
function writeCodexCatalogWithNativeMultiAgentDisabled(authFilePath) {
|
|
2517
|
+
function writeCodexCatalogWithNativeMultiAgentDisabled(authFilePath, sourcePath) {
|
|
2366
2518
|
const codexHome = dirname4(authFilePath);
|
|
2367
|
-
const sourcePath = process.env.NEGOTIUM_CODEX_MODELS_CACHE_FILE ?? (existsSync5(join6(codexHome, "models_cache.json")) ? join6(codexHome, "models_cache.json") : join6(codexHome, NEGOTIUM_MODEL_CATALOG));
|
|
2368
2519
|
const outputPath = join6(codexHome, NEGOTIUM_MODEL_CATALOG);
|
|
2369
|
-
const parsed =
|
|
2370
|
-
if (!Array.isArray(parsed.models) || parsed.models.length === 0) {
|
|
2371
|
-
throw new Error(`Codex model cache has no models: ${sourcePath}`);
|
|
2372
|
-
}
|
|
2520
|
+
const parsed = readCodexModelCache(sourcePath).parsed;
|
|
2373
2521
|
const models = parsed.models.map((model, index) => {
|
|
2374
2522
|
if (!model || typeof model !== "object" || Array.isArray(model)) {
|
|
2375
2523
|
throw new Error(`Codex model cache entry ${index} is invalid: ${sourcePath}`);
|
|
@@ -2378,24 +2526,12 @@ function writeCodexCatalogWithNativeMultiAgentDisabled(authFilePath) {
|
|
|
2378
2526
|
});
|
|
2379
2527
|
const contents = `${JSON.stringify({ models }, null, 2)}
|
|
2380
2528
|
`;
|
|
2381
|
-
|
|
2382
|
-
return outputPath;
|
|
2383
|
-
}
|
|
2384
|
-
const tempPath = `${outputPath}.${process.pid}.${Date.now()}.tmp`;
|
|
2385
|
-
try {
|
|
2386
|
-
writeFileSync4(tempPath, contents, { encoding: "utf8", mode: 384 });
|
|
2387
|
-
renameSync3(tempPath, outputPath);
|
|
2388
|
-
chmodSync3(outputPath, 384);
|
|
2389
|
-
} finally {
|
|
2390
|
-
try {
|
|
2391
|
-
unlinkSync4(tempPath);
|
|
2392
|
-
} catch {}
|
|
2393
|
-
}
|
|
2529
|
+
writePrivateFileAtomic(outputPath, contents);
|
|
2394
2530
|
return outputPath;
|
|
2395
2531
|
}
|
|
2396
2532
|
|
|
2397
2533
|
// ../../packages/core/src/agents/codex-tree-kill.ts
|
|
2398
|
-
import { execFileSync as
|
|
2534
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
2399
2535
|
|
|
2400
2536
|
// ../../packages/core/src/agents/codex-tree-manager.ts
|
|
2401
2537
|
function createCodexTreeManager(host, options = {}) {
|
|
@@ -2581,7 +2717,7 @@ function createCodexTreeManager(host, options = {}) {
|
|
|
2581
2717
|
// ../../packages/core/src/agents/codex-tree-kill.ts
|
|
2582
2718
|
function execText(command, args) {
|
|
2583
2719
|
try {
|
|
2584
|
-
return
|
|
2720
|
+
return execFileSync3(command, args, {
|
|
2585
2721
|
encoding: "utf8",
|
|
2586
2722
|
stdio: ["ignore", "pipe", "ignore"]
|
|
2587
2723
|
}).trim();
|
|
@@ -2614,12 +2750,145 @@ var killCodexTrees = manager.killTrees;
|
|
|
2614
2750
|
var killOwnedCodexTreesForShutdown = manager.killOwnedTreesForShutdown;
|
|
2615
2751
|
|
|
2616
2752
|
// ../../packages/core/src/agents/rollout/codex.ts
|
|
2617
|
-
import { existsSync as existsSync6, readFileSync as readFileSync6, statSync as statSync2, unlinkSync as unlinkSync5 } from "fs";
|
|
2753
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, realpathSync as realpathSync2, statSync as statSync2, unlinkSync as unlinkSync5 } from "fs";
|
|
2618
2754
|
import { homedir as homedir4 } from "os";
|
|
2619
|
-
import { join as join7 } from "path";
|
|
2755
|
+
import { basename, dirname as dirname5, join as join7, resolve as resolve4 } from "path";
|
|
2620
2756
|
function codexSessionsDir() {
|
|
2621
2757
|
return join7(process.env.CODEX_HOME || join7(homedir4(), ".codex"), "sessions");
|
|
2622
2758
|
}
|
|
2759
|
+
function canonicalFilePath(path) {
|
|
2760
|
+
const absolute = resolve4(path);
|
|
2761
|
+
try {
|
|
2762
|
+
return realpathSync2(absolute);
|
|
2763
|
+
} catch {
|
|
2764
|
+
try {
|
|
2765
|
+
return join7(realpathSync2(dirname5(absolute)), basename(absolute));
|
|
2766
|
+
} catch {
|
|
2767
|
+
return absolute;
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
function changedPatchLines(value) {
|
|
2772
|
+
const removed = [];
|
|
2773
|
+
const added = [];
|
|
2774
|
+
const diffPreview = [];
|
|
2775
|
+
let oldLine = 0;
|
|
2776
|
+
let newLine = 0;
|
|
2777
|
+
let sawHunk = false;
|
|
2778
|
+
for (const line of value.split(`
|
|
2779
|
+
`)) {
|
|
2780
|
+
const hunk = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(line);
|
|
2781
|
+
if (hunk) {
|
|
2782
|
+
if (sawHunk)
|
|
2783
|
+
diffPreview.push("\u2026");
|
|
2784
|
+
sawHunk = true;
|
|
2785
|
+
oldLine = Number.parseInt(hunk[1] ?? "0", 10);
|
|
2786
|
+
newLine = Number.parseInt(hunk[2] ?? "0", 10);
|
|
2787
|
+
continue;
|
|
2788
|
+
}
|
|
2789
|
+
if (!sawHunk && (line.startsWith("--- ") || line.startsWith("+++ ")))
|
|
2790
|
+
continue;
|
|
2791
|
+
if (line.startsWith("\\ No newline"))
|
|
2792
|
+
continue;
|
|
2793
|
+
if (line.startsWith("-")) {
|
|
2794
|
+
removed.push(line.slice(1));
|
|
2795
|
+
diffPreview.push(`${oldLine} -${line.slice(1)}`);
|
|
2796
|
+
oldLine += 1;
|
|
2797
|
+
continue;
|
|
2798
|
+
}
|
|
2799
|
+
if (line.startsWith("+")) {
|
|
2800
|
+
added.push(line.slice(1));
|
|
2801
|
+
diffPreview.push(`${newLine} +${line.slice(1)}`);
|
|
2802
|
+
newLine += 1;
|
|
2803
|
+
continue;
|
|
2804
|
+
}
|
|
2805
|
+
if (line.startsWith(" ")) {
|
|
2806
|
+
diffPreview.push(`${newLine} ${line.slice(1)}`);
|
|
2807
|
+
oldLine += 1;
|
|
2808
|
+
newLine += 1;
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
return {
|
|
2812
|
+
...removed.length > 0 ? { before: removed.join(`
|
|
2813
|
+
`) } : {},
|
|
2814
|
+
...added.length > 0 ? { after: added.join(`
|
|
2815
|
+
`) } : {},
|
|
2816
|
+
...diffPreview.length > 0 ? { diffPreview: diffPreview.join(`
|
|
2817
|
+
`) } : {}
|
|
2818
|
+
};
|
|
2819
|
+
}
|
|
2820
|
+
function extractLatestCodexPatchPreview(jsonl, expectedPaths, consumedCallIds = new Set, expectedCallId) {
|
|
2821
|
+
const expected = expectedPaths.map(canonicalFilePath);
|
|
2822
|
+
const lines = jsonl.trimEnd().split(`
|
|
2823
|
+
`);
|
|
2824
|
+
for (let index = lines.length - 1;index >= 0; index -= 1) {
|
|
2825
|
+
try {
|
|
2826
|
+
const entry = JSON.parse(lines[index] ?? "");
|
|
2827
|
+
if (entry.type !== "event_msg" || entry.payload?.type !== "patch_apply_end")
|
|
2828
|
+
continue;
|
|
2829
|
+
const callId = entry.payload.call_id;
|
|
2830
|
+
const rawChanges = entry.payload.changes;
|
|
2831
|
+
if (!callId || consumedCallIds.has(callId) || expectedCallId !== undefined && callId !== expectedCallId || !rawChanges) {
|
|
2832
|
+
continue;
|
|
2833
|
+
}
|
|
2834
|
+
const entries = Object.entries(rawChanges);
|
|
2835
|
+
const matched = expected.map((path) => entries.find(([candidate]) => canonicalFilePath(candidate) === path));
|
|
2836
|
+
const complete = matched.filter((change) => change !== undefined);
|
|
2837
|
+
if (complete.length !== expected.length)
|
|
2838
|
+
continue;
|
|
2839
|
+
return {
|
|
2840
|
+
callId,
|
|
2841
|
+
changes: complete.map(([path, change]) => {
|
|
2842
|
+
if (typeof change.unified_diff === "string") {
|
|
2843
|
+
return { path, ...changedPatchLines(change.unified_diff) };
|
|
2844
|
+
}
|
|
2845
|
+
const content = typeof change.content === "string" ? change.content.replace(/\n$/, "") : undefined;
|
|
2846
|
+
return {
|
|
2847
|
+
path,
|
|
2848
|
+
...change.type === "delete" && content !== undefined ? { before: content } : {},
|
|
2849
|
+
...change.type === "add" && content !== undefined ? { after: content } : {}
|
|
2850
|
+
};
|
|
2851
|
+
})
|
|
2852
|
+
};
|
|
2853
|
+
} catch {}
|
|
2854
|
+
}
|
|
2855
|
+
return;
|
|
2856
|
+
}
|
|
2857
|
+
function extractCodexPatchCallIds(jsonl) {
|
|
2858
|
+
const callIds = [];
|
|
2859
|
+
for (const line of jsonl.trimEnd().split(`
|
|
2860
|
+
`)) {
|
|
2861
|
+
try {
|
|
2862
|
+
const entry = JSON.parse(line);
|
|
2863
|
+
if (entry.type === "event_msg" && entry.payload?.type === "patch_apply_end" && typeof entry.payload.call_id === "string") {
|
|
2864
|
+
callIds.push(entry.payload.call_id);
|
|
2865
|
+
}
|
|
2866
|
+
} catch {}
|
|
2867
|
+
}
|
|
2868
|
+
return callIds;
|
|
2869
|
+
}
|
|
2870
|
+
function readCodexPatchCallIds(threadId) {
|
|
2871
|
+
const path = latestCodexRolloutPath(threadId);
|
|
2872
|
+
if (!path)
|
|
2873
|
+
return [];
|
|
2874
|
+
try {
|
|
2875
|
+
return extractCodexPatchCallIds(readFileSync6(path, "utf8"));
|
|
2876
|
+
} catch (error) {
|
|
2877
|
+
logger.debug({ error, threadId }, "codex patch ids: rollout read failed");
|
|
2878
|
+
return [];
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
function readLatestCodexPatchPreview(threadId, expectedPaths, consumedCallIds = new Set, expectedCallId) {
|
|
2882
|
+
const path = latestCodexRolloutPath(threadId);
|
|
2883
|
+
if (!path)
|
|
2884
|
+
return;
|
|
2885
|
+
try {
|
|
2886
|
+
return extractLatestCodexPatchPreview(readFileSync6(path, "utf8"), expectedPaths, consumedCallIds, expectedCallId);
|
|
2887
|
+
} catch (error) {
|
|
2888
|
+
logger.debug({ error, threadId }, "codex patch preview: rollout read failed");
|
|
2889
|
+
return;
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2623
2892
|
function extractLatestCodexContextUsage(jsonl) {
|
|
2624
2893
|
const lines = jsonl.trimEnd().split(`
|
|
2625
2894
|
`);
|
|
@@ -2764,6 +3033,52 @@ function formatDateBucket(d) {
|
|
|
2764
3033
|
return `${yyyy}/${mm}/${dd}`;
|
|
2765
3034
|
}
|
|
2766
3035
|
|
|
3036
|
+
// ../../packages/core/src/agents/tool-format.ts
|
|
3037
|
+
import { diffLines as computeLineDiff } from "diff";
|
|
3038
|
+
function changedDiffLines(value) {
|
|
3039
|
+
const lines = value.split(`
|
|
3040
|
+
`);
|
|
3041
|
+
if (lines.at(-1) === "")
|
|
3042
|
+
lines.pop();
|
|
3043
|
+
return lines;
|
|
3044
|
+
}
|
|
3045
|
+
function buildNumberedDiffSummary(before, after, startLine = 1) {
|
|
3046
|
+
const removed = [];
|
|
3047
|
+
const added = [];
|
|
3048
|
+
const preview = [];
|
|
3049
|
+
let oldLine = startLine;
|
|
3050
|
+
let newLine = startLine;
|
|
3051
|
+
for (const part of computeLineDiff(before, after)) {
|
|
3052
|
+
const lines = changedDiffLines(part.value);
|
|
3053
|
+
if (part.removed) {
|
|
3054
|
+
for (const line of lines) {
|
|
3055
|
+
removed.push(line);
|
|
3056
|
+
preview.push(`${oldLine} -${line}`);
|
|
3057
|
+
oldLine += 1;
|
|
3058
|
+
}
|
|
3059
|
+
continue;
|
|
3060
|
+
}
|
|
3061
|
+
if (part.added) {
|
|
3062
|
+
for (const line of lines) {
|
|
3063
|
+
added.push(line);
|
|
3064
|
+
preview.push(`${newLine} +${line}`);
|
|
3065
|
+
newLine += 1;
|
|
3066
|
+
}
|
|
3067
|
+
continue;
|
|
3068
|
+
}
|
|
3069
|
+
oldLine += lines.length;
|
|
3070
|
+
newLine += lines.length;
|
|
3071
|
+
}
|
|
3072
|
+
return {
|
|
3073
|
+
...removed.length > 0 ? { before: removed.join(`
|
|
3074
|
+
`) } : {},
|
|
3075
|
+
...added.length > 0 ? { after: added.join(`
|
|
3076
|
+
`) } : {},
|
|
3077
|
+
...preview.length > 0 ? { diffPreview: preview.join(`
|
|
3078
|
+
`) } : {}
|
|
3079
|
+
};
|
|
3080
|
+
}
|
|
3081
|
+
|
|
2767
3082
|
// ../../packages/core/src/agents/codex-provider.ts
|
|
2768
3083
|
function mapEffort(effort) {
|
|
2769
3084
|
if (!effort)
|
|
@@ -2846,22 +3161,142 @@ function summarizeMcpToolCallResult(item) {
|
|
|
2846
3161
|
return text.slice(0, 200);
|
|
2847
3162
|
return JSON.stringify(item.result.structured_content ?? "").slice(0, 200);
|
|
2848
3163
|
}
|
|
2849
|
-
|
|
3164
|
+
var CODEX_DIFF_FILE_LIMIT = 512 * 1024;
|
|
3165
|
+
var CODEX_DIFF_BASELINE_FILE_LIMIT = 200;
|
|
3166
|
+
var CODEX_DIFF_BASELINE_BYTE_LIMIT = 16 * 1024 * 1024;
|
|
3167
|
+
function canonicalPath(path) {
|
|
3168
|
+
try {
|
|
3169
|
+
return realpathSync3(resolve5(path));
|
|
3170
|
+
} catch {
|
|
3171
|
+
return resolve5(path);
|
|
3172
|
+
}
|
|
3173
|
+
}
|
|
3174
|
+
function textFile(path, maxBytes = CODEX_DIFF_FILE_LIMIT) {
|
|
3175
|
+
if (!existsSync7(path))
|
|
3176
|
+
return null;
|
|
3177
|
+
try {
|
|
3178
|
+
const byteLimit = Math.min(CODEX_DIFF_FILE_LIMIT, Math.max(0, maxBytes));
|
|
3179
|
+
if (statSync3(path).size > byteLimit)
|
|
3180
|
+
return;
|
|
3181
|
+
const content = readFileSync7(path);
|
|
3182
|
+
if (content.byteLength > byteLimit || content.includes(0))
|
|
3183
|
+
return;
|
|
3184
|
+
return content.toString("utf8");
|
|
3185
|
+
} catch {
|
|
3186
|
+
return;
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
|
|
3190
|
+
class CodexFilePreviewTracker {
|
|
3191
|
+
#cwd;
|
|
3192
|
+
#root;
|
|
3193
|
+
#baseline = new Map;
|
|
3194
|
+
#baselineAvailable = false;
|
|
3195
|
+
constructor(cwd) {
|
|
3196
|
+
this.#cwd = canonicalPath(cwd);
|
|
3197
|
+
const root = this.#git(["rev-parse", "--show-toplevel"], this.#cwd)?.trim();
|
|
3198
|
+
this.#root = root ? canonicalPath(root) : null;
|
|
3199
|
+
if (!this.#root)
|
|
3200
|
+
return;
|
|
3201
|
+
const status = this.#git(["status", "--porcelain=v1", "-z", "--untracked-files=all"]);
|
|
3202
|
+
if (status === undefined)
|
|
3203
|
+
return;
|
|
3204
|
+
this.#baselineAvailable = true;
|
|
3205
|
+
let loadedFiles = 0;
|
|
3206
|
+
let loadedBytes = 0;
|
|
3207
|
+
const records = status.split("\x00");
|
|
3208
|
+
for (let index = 0;index < records.length; index += 1) {
|
|
3209
|
+
const record = records[index];
|
|
3210
|
+
if (!record || record.length < 4)
|
|
3211
|
+
continue;
|
|
3212
|
+
const code = record.slice(0, 2);
|
|
3213
|
+
const path = record.slice(3);
|
|
3214
|
+
const remainingBytes = CODEX_DIFF_BASELINE_BYTE_LIMIT - loadedBytes;
|
|
3215
|
+
const content = loadedFiles < CODEX_DIFF_BASELINE_FILE_LIMIT && remainingBytes > 0 ? textFile(resolve5(this.#root, path), remainingBytes) : undefined;
|
|
3216
|
+
this.#baseline.set(path, content);
|
|
3217
|
+
if (typeof content === "string") {
|
|
3218
|
+
loadedFiles += 1;
|
|
3219
|
+
loadedBytes += Buffer.byteLength(content);
|
|
3220
|
+
}
|
|
3221
|
+
if (/[RC]/.test(code))
|
|
3222
|
+
index += 1;
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
preview(path, succeeded) {
|
|
3226
|
+
if (!this.#root || !this.#baselineAvailable || !succeeded)
|
|
3227
|
+
return {};
|
|
3228
|
+
const absolute = canonicalPath(isAbsolute(path) ? path : resolve5(this.#cwd, path));
|
|
3229
|
+
const relativePath = relative(this.#root, absolute);
|
|
3230
|
+
if (!relativePath || relativePath.startsWith("..") || isAbsolute(relativePath))
|
|
3231
|
+
return {};
|
|
3232
|
+
const before = this.#baseline.has(relativePath) ? this.#baseline.get(relativePath) : this.#headFile(relativePath);
|
|
3233
|
+
const after = textFile(absolute);
|
|
3234
|
+
this.#baseline.set(relativePath, after);
|
|
3235
|
+
if (before === undefined || after === undefined)
|
|
3236
|
+
return {};
|
|
3237
|
+
const diff = buildNumberedDiffSummary(before ?? "", after ?? "");
|
|
3238
|
+
return {
|
|
3239
|
+
...diff.before !== undefined ? { before: diff.before } : {},
|
|
3240
|
+
...diff.after !== undefined ? { after: diff.after } : {},
|
|
3241
|
+
...diff.diffPreview !== undefined ? { diff_preview: diff.diffPreview } : {}
|
|
3242
|
+
};
|
|
3243
|
+
}
|
|
3244
|
+
#headFile(path) {
|
|
3245
|
+
const content = this.#git(["show", `HEAD:${path}`]);
|
|
3246
|
+
if (content === undefined)
|
|
3247
|
+
return null;
|
|
3248
|
+
return Buffer.byteLength(content) > CODEX_DIFF_FILE_LIMIT || content.includes("\x00") ? undefined : content;
|
|
3249
|
+
}
|
|
3250
|
+
#git(args, cwd = this.#root ?? undefined) {
|
|
3251
|
+
try {
|
|
3252
|
+
return execFileSync4("git", ["-C", cwd ?? ".", ...args], {
|
|
3253
|
+
encoding: "utf8",
|
|
3254
|
+
maxBuffer: CODEX_DIFF_FILE_LIMIT * 4,
|
|
3255
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
3256
|
+
});
|
|
3257
|
+
} catch {
|
|
3258
|
+
return;
|
|
3259
|
+
}
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
async function fileChangeEvents(item, previews, cwd, threadId, consumedPatchCallIds) {
|
|
3263
|
+
const expectedPaths = item.changes.map((change) => isAbsolute(change.path) ? change.path : resolve5(cwd, change.path));
|
|
3264
|
+
let nativePreview;
|
|
3265
|
+
if (threadId && item.status === "completed") {
|
|
3266
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, 20));
|
|
3267
|
+
nativePreview = readLatestCodexPatchPreview(threadId, expectedPaths, consumedPatchCallIds);
|
|
3268
|
+
}
|
|
3269
|
+
for (const delayMs of [20, 40, 80, 120]) {
|
|
3270
|
+
if (nativePreview || !threadId || item.status !== "completed")
|
|
3271
|
+
break;
|
|
3272
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, delayMs));
|
|
3273
|
+
nativePreview = readLatestCodexPatchPreview(threadId, expectedPaths, consumedPatchCallIds);
|
|
3274
|
+
}
|
|
3275
|
+
if (nativePreview)
|
|
3276
|
+
consumedPatchCallIds.add(nativePreview.callId);
|
|
2850
3277
|
return item.changes.flatMap((change, index) => {
|
|
2851
3278
|
const name = change.kind === "add" ? "Write" : change.kind === "delete" ? "Delete" : "Edit";
|
|
2852
3279
|
const toolUseId = `${item.id}:${index}`;
|
|
2853
3280
|
const success = item.status === "completed";
|
|
3281
|
+
const nativeChange = nativePreview?.changes[index];
|
|
3282
|
+
const fallbackPreview = previews.preview(change.path, success);
|
|
3283
|
+
const preview = success && nativeChange ? {
|
|
3284
|
+
...nativeChange.before !== undefined ? { before: nativeChange.before } : {},
|
|
3285
|
+
...nativeChange.after !== undefined ? { after: nativeChange.after } : {},
|
|
3286
|
+
...nativeChange.diffPreview !== undefined ? { diff_preview: nativeChange.diffPreview } : {}
|
|
3287
|
+
} : fallbackPreview;
|
|
2854
3288
|
return [
|
|
2855
3289
|
{
|
|
2856
3290
|
type: "tool_use",
|
|
2857
3291
|
name,
|
|
2858
|
-
input: { file_path: change.path, change_kind: change.kind },
|
|
3292
|
+
input: { file_path: change.path, change_kind: change.kind, ...preview },
|
|
2859
3293
|
toolUseId
|
|
2860
3294
|
},
|
|
2861
3295
|
{
|
|
2862
3296
|
type: "tool_result",
|
|
2863
3297
|
toolUseId,
|
|
2864
|
-
content: success ? `${change.kind} applied: ${change.path}` : `${change.kind} failed: ${change.path}
|
|
3298
|
+
content: success ? `${change.kind} applied: ${change.path}` : `${change.kind} failed: ${change.path}`,
|
|
3299
|
+
...success ? {} : { isError: true }
|
|
2865
3300
|
}
|
|
2866
3301
|
];
|
|
2867
3302
|
});
|
|
@@ -2947,6 +3382,8 @@ function prependFirstEvent(iter, firstEvent, alreadyDone) {
|
|
|
2947
3382
|
};
|
|
2948
3383
|
}
|
|
2949
3384
|
async function* codexProvider(opts) {
|
|
3385
|
+
const filePreviews = new CodexFilePreviewTracker(opts.cwd);
|
|
3386
|
+
const consumedPatchCallIds = new Set(opts.sessionId ? readCodexPatchCallIds(opts.sessionId) : []);
|
|
2950
3387
|
const codexAuthPath = hostedCodexAuthFilePath();
|
|
2951
3388
|
if (!existsSync7(codexAuthPath)) {
|
|
2952
3389
|
yield {
|
|
@@ -2957,8 +3394,8 @@ async function* codexProvider(opts) {
|
|
|
2957
3394
|
}
|
|
2958
3395
|
let codexModelCatalogPath;
|
|
2959
3396
|
try {
|
|
2960
|
-
await ensureCodexModelCache(codexAuthPath);
|
|
2961
|
-
codexModelCatalogPath = writeCodexCatalogWithNativeMultiAgentDisabled(codexAuthPath);
|
|
3397
|
+
const codexModelCachePath = await ensureCodexModelCache(codexAuthPath);
|
|
3398
|
+
codexModelCatalogPath = writeCodexCatalogWithNativeMultiAgentDisabled(codexAuthPath, codexModelCachePath);
|
|
2962
3399
|
if (opts.sessionId)
|
|
2963
3400
|
migrateCodexRolloutNativeMultiAgentMetadata(opts.sessionId);
|
|
2964
3401
|
} catch (err) {
|
|
@@ -3081,10 +3518,11 @@ async function* codexProvider(opts) {
|
|
|
3081
3518
|
if (!item)
|
|
3082
3519
|
break;
|
|
3083
3520
|
if (item.type === "command_execution") {
|
|
3521
|
+
const command = String(item.command ?? "");
|
|
3084
3522
|
yield {
|
|
3085
3523
|
type: "tool_use",
|
|
3086
3524
|
name: "Bash",
|
|
3087
|
-
input: { command
|
|
3525
|
+
input: { command },
|
|
3088
3526
|
toolUseId: String(item.id ?? "")
|
|
3089
3527
|
};
|
|
3090
3528
|
} else if (item.type === "mcp_tool_call") {
|
|
@@ -3130,19 +3568,24 @@ async function* codexProvider(opts) {
|
|
|
3130
3568
|
if (reasoning)
|
|
3131
3569
|
yield { type: "reasoning", content: reasoning };
|
|
3132
3570
|
} else if (item.type === "mcp_tool_call") {
|
|
3571
|
+
const isError = item.status === "failed" || Boolean(item.error);
|
|
3133
3572
|
yield {
|
|
3134
3573
|
type: "tool_result",
|
|
3135
3574
|
toolUseId: String(item.id ?? ""),
|
|
3136
|
-
content: summarizeMcpToolCallResult(item)
|
|
3575
|
+
content: summarizeMcpToolCallResult(item),
|
|
3576
|
+
...isError ? { isError: true } : {}
|
|
3137
3577
|
};
|
|
3138
3578
|
} else if (item.type === "command_execution") {
|
|
3579
|
+
const isError = item.status === "failed" || typeof item.exit_code === "number" && item.exit_code !== 0;
|
|
3139
3580
|
yield {
|
|
3140
3581
|
type: "tool_result",
|
|
3141
3582
|
toolUseId: String(item.id ?? ""),
|
|
3142
|
-
content: String(item.aggregated_output ?? "").slice(0, 200)
|
|
3583
|
+
content: String(item.aggregated_output ?? "").slice(0, 200),
|
|
3584
|
+
...isError ? { isError: true } : {}
|
|
3143
3585
|
};
|
|
3144
3586
|
} else if (item.type === "file_change") {
|
|
3145
|
-
|
|
3587
|
+
const fileEvents = await fileChangeEvents(item, filePreviews, opts.cwd, currentSessionId, consumedPatchCallIds);
|
|
3588
|
+
for (const fileEvent of fileEvents) {
|
|
3146
3589
|
yield fileEvent;
|
|
3147
3590
|
}
|
|
3148
3591
|
} else if (item.type === "error") {
|
|
@@ -3294,6 +3737,18 @@ function providerOwnedToolRedirect(toolName) {
|
|
|
3294
3737
|
}
|
|
3295
3738
|
return "Use the shared task MCP tools instead " + "(mcp__task__task_create / task_update / task_list / task_get / task_delete).";
|
|
3296
3739
|
}
|
|
3740
|
+
function resolveMaestroApiKeyOverrides(userId) {
|
|
3741
|
+
if (!userId)
|
|
3742
|
+
return;
|
|
3743
|
+
const deepseek = vaultGetValue(userId, "DEEPSEEK_API_KEY")?.trim();
|
|
3744
|
+
const moonshot = vaultGetValue(userId, "MOONSHOT_API_KEY")?.trim();
|
|
3745
|
+
if (!deepseek && !moonshot)
|
|
3746
|
+
return;
|
|
3747
|
+
return {
|
|
3748
|
+
...deepseek ? { deepseek } : {},
|
|
3749
|
+
...moonshot ? { moonshot } : {}
|
|
3750
|
+
};
|
|
3751
|
+
}
|
|
3297
3752
|
function buildProviderOwnedToolBlockHook() {
|
|
3298
3753
|
return {
|
|
3299
3754
|
name: "provider-owned-tool-redirect",
|
|
@@ -3320,6 +3775,7 @@ function maestroProvider(opts) {
|
|
|
3320
3775
|
maxTokens: MAESTRO_DEFAULT_MAX_TOKENS,
|
|
3321
3776
|
enableToolSearch: true,
|
|
3322
3777
|
...opts,
|
|
3778
|
+
apiKeyOverrides: resolveMaestroApiKeyOverrides(userId),
|
|
3323
3779
|
agent: "maestro",
|
|
3324
3780
|
disallowedTools: buildMaestroDisallowedTools(callerDisallowedTools),
|
|
3325
3781
|
toolHooks: [...buildMaestroToolHooks(userId), ...callerToolHooks]
|
|
@@ -3327,18 +3783,18 @@ function maestroProvider(opts) {
|
|
|
3327
3783
|
return sdkMaestroProvider(sdkOpts);
|
|
3328
3784
|
}
|
|
3329
3785
|
// ../../packages/core/src/agents/claude-runtime-inspection.ts
|
|
3330
|
-
import { readFileSync as
|
|
3786
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
3331
3787
|
import { createRequire as createRequire2 } from "module";
|
|
3332
|
-
import { dirname as
|
|
3788
|
+
import { dirname as dirname6, join as join8 } from "path";
|
|
3333
3789
|
var cached;
|
|
3334
3790
|
function inspectBundledClaudeRuntime() {
|
|
3335
3791
|
if (cached)
|
|
3336
3792
|
return cached;
|
|
3337
3793
|
try {
|
|
3338
3794
|
const require2 = createRequire2(import.meta.url);
|
|
3339
|
-
const sdkDir =
|
|
3340
|
-
const sdkPackage = JSON.parse(
|
|
3341
|
-
const manifest = JSON.parse(
|
|
3795
|
+
const sdkDir = dirname6(require2.resolve("@anthropic-ai/claude-agent-sdk"));
|
|
3796
|
+
const sdkPackage = JSON.parse(readFileSync8(join8(sdkDir, "package.json"), "utf8"));
|
|
3797
|
+
const manifest = JSON.parse(readFileSync8(join8(sdkDir, "manifest.json"), "utf8"));
|
|
3342
3798
|
const sdkVersion = typeof sdkPackage.version === "string" ? sdkPackage.version : "";
|
|
3343
3799
|
const claudeCodeVersion = typeof manifest.version === "string" ? manifest.version : "";
|
|
3344
3800
|
if (!sdkVersion || !claudeCodeVersion) {
|
|
@@ -3411,4 +3867,4 @@ export {
|
|
|
3411
3867
|
buildClaudeDisallowedTools
|
|
3412
3868
|
};
|
|
3413
3869
|
|
|
3414
|
-
//# debugId=
|
|
3870
|
+
//# debugId=46373C1AE0198E0264756E2164756E21
|