negotium 0.1.29 → 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 +366 -50
- package/dist/agent-helpers.js.map +10 -9
- package/dist/background-bash.js.map +1 -1
- package/dist/{chunk-yk55n9dk.js → chunk-en2s6xnh.js} +3 -3
- package/dist/{chunk-yk55n9dk.js.map → chunk-en2s6xnh.js.map} +4 -4
- package/dist/cron.js +4903 -4479
- package/dist/cron.js.map +11 -11
- package/dist/hosted-agent.js +328 -18
- package/dist/hosted-agent.js.map +9 -8
- package/dist/main.js +5711 -5039
- package/dist/main.js.map +16 -16
- package/dist/mcp-factories.js.map +1 -1
- package/dist/prompts.js.map +1 -1
- package/dist/registry.js +1 -1
- package/dist/rollout.js +1 -1
- package/dist/runtime/src/agents/claude-provider.ts +2 -0
- package/dist/runtime/src/agents/codex-provider.ts +192 -5
- 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/tool-format.ts +228 -15
- package/dist/runtime/src/bus.ts +21 -3
- 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.map +1 -1
- package/dist/storage.js.map +1 -1
- 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/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.map +1 -1
- package/package.json +2 -1
package/dist/agent-helpers.js
CHANGED
|
@@ -1296,9 +1296,9 @@ import { join as join10 } from "path";
|
|
|
1296
1296
|
|
|
1297
1297
|
// ../../packages/core/src/agents/rollout/codex.ts
|
|
1298
1298
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
1299
|
-
import { existsSync as existsSync5, readFileSync as readFileSync4, statSync as statSync2, unlinkSync as unlinkSync4 } from "fs";
|
|
1299
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, realpathSync, statSync as statSync2, unlinkSync as unlinkSync4 } from "fs";
|
|
1300
1300
|
import { homedir as homedir5 } from "os";
|
|
1301
|
-
import { join as join7 } from "path";
|
|
1301
|
+
import { basename, dirname as dirname4, join as join7, resolve as resolve3 } from "path";
|
|
1302
1302
|
function codexSessionsDir() {
|
|
1303
1303
|
return join7(process.env.CODEX_HOME || join7(homedir5(), ".codex"), "sessions");
|
|
1304
1304
|
}
|
|
@@ -1364,6 +1364,139 @@ function patchEnvContext(envContext, cwd, currentDate, timezone) {
|
|
|
1364
1364
|
}
|
|
1365
1365
|
}
|
|
1366
1366
|
}
|
|
1367
|
+
function canonicalFilePath(path) {
|
|
1368
|
+
const absolute = resolve3(path);
|
|
1369
|
+
try {
|
|
1370
|
+
return realpathSync(absolute);
|
|
1371
|
+
} catch {
|
|
1372
|
+
try {
|
|
1373
|
+
return join7(realpathSync(dirname4(absolute)), basename(absolute));
|
|
1374
|
+
} catch {
|
|
1375
|
+
return absolute;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
function changedPatchLines(value) {
|
|
1380
|
+
const removed = [];
|
|
1381
|
+
const added = [];
|
|
1382
|
+
const diffPreview = [];
|
|
1383
|
+
let oldLine = 0;
|
|
1384
|
+
let newLine = 0;
|
|
1385
|
+
let sawHunk = false;
|
|
1386
|
+
for (const line of value.split(`
|
|
1387
|
+
`)) {
|
|
1388
|
+
const hunk = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(line);
|
|
1389
|
+
if (hunk) {
|
|
1390
|
+
if (sawHunk)
|
|
1391
|
+
diffPreview.push("\u2026");
|
|
1392
|
+
sawHunk = true;
|
|
1393
|
+
oldLine = Number.parseInt(hunk[1] ?? "0", 10);
|
|
1394
|
+
newLine = Number.parseInt(hunk[2] ?? "0", 10);
|
|
1395
|
+
continue;
|
|
1396
|
+
}
|
|
1397
|
+
if (!sawHunk && (line.startsWith("--- ") || line.startsWith("+++ ")))
|
|
1398
|
+
continue;
|
|
1399
|
+
if (line.startsWith("\\ No newline"))
|
|
1400
|
+
continue;
|
|
1401
|
+
if (line.startsWith("-")) {
|
|
1402
|
+
removed.push(line.slice(1));
|
|
1403
|
+
diffPreview.push(`${oldLine} -${line.slice(1)}`);
|
|
1404
|
+
oldLine += 1;
|
|
1405
|
+
continue;
|
|
1406
|
+
}
|
|
1407
|
+
if (line.startsWith("+")) {
|
|
1408
|
+
added.push(line.slice(1));
|
|
1409
|
+
diffPreview.push(`${newLine} +${line.slice(1)}`);
|
|
1410
|
+
newLine += 1;
|
|
1411
|
+
continue;
|
|
1412
|
+
}
|
|
1413
|
+
if (line.startsWith(" ")) {
|
|
1414
|
+
diffPreview.push(`${newLine} ${line.slice(1)}`);
|
|
1415
|
+
oldLine += 1;
|
|
1416
|
+
newLine += 1;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
return {
|
|
1420
|
+
...removed.length > 0 ? { before: removed.join(`
|
|
1421
|
+
`) } : {},
|
|
1422
|
+
...added.length > 0 ? { after: added.join(`
|
|
1423
|
+
`) } : {},
|
|
1424
|
+
...diffPreview.length > 0 ? { diffPreview: diffPreview.join(`
|
|
1425
|
+
`) } : {}
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
function extractLatestCodexPatchPreview(jsonl, expectedPaths, consumedCallIds = new Set, expectedCallId) {
|
|
1429
|
+
const expected = expectedPaths.map(canonicalFilePath);
|
|
1430
|
+
const lines = jsonl.trimEnd().split(`
|
|
1431
|
+
`);
|
|
1432
|
+
for (let index = lines.length - 1;index >= 0; index -= 1) {
|
|
1433
|
+
try {
|
|
1434
|
+
const entry = JSON.parse(lines[index] ?? "");
|
|
1435
|
+
if (entry.type !== "event_msg" || entry.payload?.type !== "patch_apply_end")
|
|
1436
|
+
continue;
|
|
1437
|
+
const callId = entry.payload.call_id;
|
|
1438
|
+
const rawChanges = entry.payload.changes;
|
|
1439
|
+
if (!callId || consumedCallIds.has(callId) || expectedCallId !== undefined && callId !== expectedCallId || !rawChanges) {
|
|
1440
|
+
continue;
|
|
1441
|
+
}
|
|
1442
|
+
const entries = Object.entries(rawChanges);
|
|
1443
|
+
const matched = expected.map((path) => entries.find(([candidate]) => canonicalFilePath(candidate) === path));
|
|
1444
|
+
const complete = matched.filter((change) => change !== undefined);
|
|
1445
|
+
if (complete.length !== expected.length)
|
|
1446
|
+
continue;
|
|
1447
|
+
return {
|
|
1448
|
+
callId,
|
|
1449
|
+
changes: complete.map(([path, change]) => {
|
|
1450
|
+
if (typeof change.unified_diff === "string") {
|
|
1451
|
+
return { path, ...changedPatchLines(change.unified_diff) };
|
|
1452
|
+
}
|
|
1453
|
+
const content = typeof change.content === "string" ? change.content.replace(/\n$/, "") : undefined;
|
|
1454
|
+
return {
|
|
1455
|
+
path,
|
|
1456
|
+
...change.type === "delete" && content !== undefined ? { before: content } : {},
|
|
1457
|
+
...change.type === "add" && content !== undefined ? { after: content } : {}
|
|
1458
|
+
};
|
|
1459
|
+
})
|
|
1460
|
+
};
|
|
1461
|
+
} catch {}
|
|
1462
|
+
}
|
|
1463
|
+
return;
|
|
1464
|
+
}
|
|
1465
|
+
function extractCodexPatchCallIds(jsonl) {
|
|
1466
|
+
const callIds = [];
|
|
1467
|
+
for (const line of jsonl.trimEnd().split(`
|
|
1468
|
+
`)) {
|
|
1469
|
+
try {
|
|
1470
|
+
const entry = JSON.parse(line);
|
|
1471
|
+
if (entry.type === "event_msg" && entry.payload?.type === "patch_apply_end" && typeof entry.payload.call_id === "string") {
|
|
1472
|
+
callIds.push(entry.payload.call_id);
|
|
1473
|
+
}
|
|
1474
|
+
} catch {}
|
|
1475
|
+
}
|
|
1476
|
+
return callIds;
|
|
1477
|
+
}
|
|
1478
|
+
function readCodexPatchCallIds(threadId) {
|
|
1479
|
+
const path = latestCodexRolloutPath(threadId);
|
|
1480
|
+
if (!path)
|
|
1481
|
+
return [];
|
|
1482
|
+
try {
|
|
1483
|
+
return extractCodexPatchCallIds(readFileSync4(path, "utf8"));
|
|
1484
|
+
} catch (error) {
|
|
1485
|
+
logger.debug({ error, threadId }, "codex patch ids: rollout read failed");
|
|
1486
|
+
return [];
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
function readLatestCodexPatchPreview(threadId, expectedPaths, consumedCallIds = new Set, expectedCallId) {
|
|
1490
|
+
const path = latestCodexRolloutPath(threadId);
|
|
1491
|
+
if (!path)
|
|
1492
|
+
return;
|
|
1493
|
+
try {
|
|
1494
|
+
return extractLatestCodexPatchPreview(readFileSync4(path, "utf8"), expectedPaths, consumedCallIds, expectedCallId);
|
|
1495
|
+
} catch (error) {
|
|
1496
|
+
logger.debug({ error, threadId }, "codex patch preview: rollout read failed");
|
|
1497
|
+
return;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1367
1500
|
function extractLatestCodexContextUsage(jsonl) {
|
|
1368
1501
|
const lines = jsonl.trimEnd().split(`
|
|
1369
1502
|
`);
|
|
@@ -1671,7 +1804,7 @@ import {
|
|
|
1671
1804
|
unlinkSync as unlinkSync5,
|
|
1672
1805
|
writeFileSync as writeFileSync4
|
|
1673
1806
|
} from "fs";
|
|
1674
|
-
import { dirname as
|
|
1807
|
+
import { dirname as dirname6, join as join9 } from "path";
|
|
1675
1808
|
|
|
1676
1809
|
// ../../packages/core/src/security/sanitize.ts
|
|
1677
1810
|
function sanitizeTopicName(name, lowercase = false) {
|
|
@@ -1688,7 +1821,7 @@ function sanitizeFileName(name) {
|
|
|
1688
1821
|
// ../../packages/core/src/storage/storage-host.ts
|
|
1689
1822
|
import { mkdirSync as mkdirSync6 } from "fs";
|
|
1690
1823
|
import { homedir as homedir6 } from "os";
|
|
1691
|
-
import { dirname as
|
|
1824
|
+
import { dirname as dirname5, join as join8, resolve as resolve4 } from "path";
|
|
1692
1825
|
var configuredHost = {};
|
|
1693
1826
|
var fallbackDatabase = null;
|
|
1694
1827
|
var fallbackDatabasePath = null;
|
|
@@ -1697,7 +1830,7 @@ var initializedSchemas = new WeakMap;
|
|
|
1697
1830
|
var initializingDatabases = new WeakSet;
|
|
1698
1831
|
function envPath(name, fallback) {
|
|
1699
1832
|
const value = process.env[name]?.trim();
|
|
1700
|
-
return
|
|
1833
|
+
return resolve4(value || fallback);
|
|
1701
1834
|
}
|
|
1702
1835
|
function defaultStateDir() {
|
|
1703
1836
|
return envPath("NEGOTIUM_STATE_DIR", join8(homedir6(), ".negotium"));
|
|
@@ -1726,7 +1859,7 @@ function defaultDatabase() {
|
|
|
1726
1859
|
return fallbackDatabase;
|
|
1727
1860
|
if (fallbackDatabase)
|
|
1728
1861
|
fallbackDatabase.close();
|
|
1729
|
-
mkdirSync6(
|
|
1862
|
+
mkdirSync6(dirname5(path), { recursive: true });
|
|
1730
1863
|
fallbackDatabase = new Database(path, { create: true });
|
|
1731
1864
|
fallbackDatabasePath = path;
|
|
1732
1865
|
initializeDatabase(fallbackDatabase);
|
|
@@ -1819,7 +1952,7 @@ function appendConversationEventStrict(userId, topicName, agent, event) {
|
|
|
1819
1952
|
agent,
|
|
1820
1953
|
event
|
|
1821
1954
|
};
|
|
1822
|
-
mkdirSync7(
|
|
1955
|
+
mkdirSync7(dirname6(path), { recursive: true });
|
|
1823
1956
|
appendJsonlLine(path, JSON.stringify(entry));
|
|
1824
1957
|
}
|
|
1825
1958
|
function readConversation(userId, topicName) {
|
|
@@ -1981,7 +2114,7 @@ function cleanupAgentFork(handle) {
|
|
|
1981
2114
|
}
|
|
1982
2115
|
// ../../packages/core/src/agents/archiver.ts
|
|
1983
2116
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
1984
|
-
import { existsSync as existsSync13, readdirSync as readdirSync2, readFileSync as
|
|
2117
|
+
import { existsSync as existsSync13, readdirSync as readdirSync2, readFileSync as readFileSync11, statSync as statSync5 } from "fs";
|
|
1985
2118
|
import { join as join15 } from "path";
|
|
1986
2119
|
|
|
1987
2120
|
// ../../packages/core/src/agents/index.ts
|
|
@@ -2014,8 +2147,8 @@ function deepMapStrings(value, fn) {
|
|
|
2014
2147
|
import { AsyncLocalStorage } from "async_hooks";
|
|
2015
2148
|
|
|
2016
2149
|
// ../../packages/core/src/security/sensitive-path.ts
|
|
2017
|
-
import { realpathSync } from "fs";
|
|
2018
|
-
import { resolve as
|
|
2150
|
+
import { realpathSync as realpathSync2 } from "fs";
|
|
2151
|
+
import { resolve as resolve5 } from "path";
|
|
2019
2152
|
var SENSITIVE_PATH_PATTERNS = [
|
|
2020
2153
|
/\/\.env(\.|$)/i,
|
|
2021
2154
|
/\/\.ssh\//i,
|
|
@@ -2032,11 +2165,11 @@ var SENSITIVE_PATH_PATTERNS = [
|
|
|
2032
2165
|
/\/sessions\.db(-wal|-shm|-journal)?$/i
|
|
2033
2166
|
];
|
|
2034
2167
|
function isSensitivePath(filePath) {
|
|
2035
|
-
const normalized =
|
|
2168
|
+
const normalized = resolve5(filePath);
|
|
2036
2169
|
if (SENSITIVE_PATH_PATTERNS.some((p) => p.test(normalized)))
|
|
2037
2170
|
return true;
|
|
2038
2171
|
try {
|
|
2039
|
-
const real =
|
|
2172
|
+
const real = realpathSync2(normalized);
|
|
2040
2173
|
if (real !== normalized)
|
|
2041
2174
|
return SENSITIVE_PATH_PATTERNS.some((p) => p.test(real));
|
|
2042
2175
|
} catch {}
|
|
@@ -2340,12 +2473,12 @@ function createBackgroundBashManager(options = {}) {
|
|
|
2340
2473
|
usedPorts.clear();
|
|
2341
2474
|
knownContexts.clear();
|
|
2342
2475
|
const deadline = now() + 3000;
|
|
2343
|
-
await Promise.all(entries.map((instance) => new Promise((
|
|
2476
|
+
await Promise.all(entries.map((instance) => new Promise((resolve6) => {
|
|
2344
2477
|
if (instance.process.exitCode !== null || instance.process.killed)
|
|
2345
|
-
return
|
|
2346
|
-
instance.process.once("exit",
|
|
2347
|
-
instance.process.once("error",
|
|
2348
|
-
const timer = setTimeout(
|
|
2478
|
+
return resolve6();
|
|
2479
|
+
instance.process.once("exit", resolve6);
|
|
2480
|
+
instance.process.once("error", resolve6);
|
|
2481
|
+
const timer = setTimeout(resolve6, Math.max(0, deadline - now()));
|
|
2349
2482
|
timer.unref?.();
|
|
2350
2483
|
})));
|
|
2351
2484
|
}
|
|
@@ -3365,7 +3498,8 @@ async function* claudeProvider(opts) {
|
|
|
3365
3498
|
yield {
|
|
3366
3499
|
type: "tool_result",
|
|
3367
3500
|
toolUseId: trBlock.tool_use_id || "",
|
|
3368
|
-
content: trContent
|
|
3501
|
+
content: trContent,
|
|
3502
|
+
...trBlock.is_error ? { isError: true } : {}
|
|
3369
3503
|
};
|
|
3370
3504
|
}
|
|
3371
3505
|
}
|
|
@@ -3379,7 +3513,9 @@ async function* claudeProvider(opts) {
|
|
|
3379
3513
|
}
|
|
3380
3514
|
|
|
3381
3515
|
// ../../packages/core/src/agents/codex-provider.ts
|
|
3382
|
-
import {
|
|
3516
|
+
import { execFileSync as execFileSync5 } from "child_process";
|
|
3517
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8, realpathSync as realpathSync3, statSync as statSync3 } from "fs";
|
|
3518
|
+
import { isAbsolute, relative, resolve as resolve6 } from "path";
|
|
3383
3519
|
import { Codex } from "@openai/codex-sdk";
|
|
3384
3520
|
|
|
3385
3521
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
@@ -3398,10 +3534,10 @@ import {
|
|
|
3398
3534
|
} from "fs";
|
|
3399
3535
|
import { createRequire } from "module";
|
|
3400
3536
|
import { tmpdir } from "os";
|
|
3401
|
-
import { dirname as
|
|
3537
|
+
import { dirname as dirname7, join as join11 } from "path";
|
|
3402
3538
|
|
|
3403
3539
|
// ../../packages/core/src/version.ts
|
|
3404
|
-
var NEGOTIUM_VERSION = "0.1.
|
|
3540
|
+
var NEGOTIUM_VERSION = "0.1.30";
|
|
3405
3541
|
|
|
3406
3542
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
3407
3543
|
var moduleRequire = createRequire(import.meta.url);
|
|
@@ -3420,7 +3556,7 @@ var SAFE_BUNDLED_CODEX_VERSION = BUNDLED_CODEX_VERSION.replace(/[^a-zA-Z0-9._-]/
|
|
|
3420
3556
|
var NEGOTIUM_MODEL_CACHE = `negotium-models-cache-${SAFE_BUNDLED_CODEX_VERSION}.json`;
|
|
3421
3557
|
var NEGOTIUM_MODEL_CATALOG = `negotium-model-catalog-${SAFE_BUNDLED_CODEX_VERSION}.json`;
|
|
3422
3558
|
function codexCliScriptPath() {
|
|
3423
|
-
return join11(
|
|
3559
|
+
return join11(dirname7(bundledCodexPackagePath), "bin", "codex.js");
|
|
3424
3560
|
}
|
|
3425
3561
|
function parseCodexModelCache(contents, sourcePath) {
|
|
3426
3562
|
let parsed;
|
|
@@ -3461,14 +3597,14 @@ function writePrivateFileAtomic(path, contents) {
|
|
|
3461
3597
|
}
|
|
3462
3598
|
}
|
|
3463
3599
|
function bundledCodexModelCachePath(authFilePath) {
|
|
3464
|
-
return join11(
|
|
3600
|
+
return join11(dirname7(authFilePath), NEGOTIUM_MODEL_CACHE);
|
|
3465
3601
|
}
|
|
3466
3602
|
async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
3467
3603
|
const child = spawn3(process.execPath, [codexCliScriptPath(), "app-server", "--stdio"], {
|
|
3468
3604
|
env: { ...process.env, CODEX_HOME: codexHome },
|
|
3469
3605
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3470
3606
|
});
|
|
3471
|
-
await new Promise((
|
|
3607
|
+
await new Promise((resolve6, reject) => {
|
|
3472
3608
|
let settled = false;
|
|
3473
3609
|
let stdoutBuffer = "";
|
|
3474
3610
|
let stderr = "";
|
|
@@ -3487,7 +3623,7 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
3487
3623
|
else if (!existsSync9(cachePath))
|
|
3488
3624
|
reject(new Error("Codex did not create its model cache"));
|
|
3489
3625
|
else
|
|
3490
|
-
|
|
3626
|
+
resolve6();
|
|
3491
3627
|
};
|
|
3492
3628
|
const send = (message) => {
|
|
3493
3629
|
child.stdin.write(`${JSON.stringify(message)}
|
|
@@ -3546,7 +3682,7 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
3546
3682
|
});
|
|
3547
3683
|
}
|
|
3548
3684
|
async function bootstrapIsolatedCodexModelCache(authFilePath, bootstrap) {
|
|
3549
|
-
const sourceHome =
|
|
3685
|
+
const sourceHome = dirname7(authFilePath);
|
|
3550
3686
|
const isolatedHome = mkdtempSync(join11(tmpdir(), "negotium-codex-models-"));
|
|
3551
3687
|
const isolatedCachePath = join11(isolatedHome, "models_cache.json");
|
|
3552
3688
|
try {
|
|
@@ -3566,7 +3702,7 @@ async function bootstrapIsolatedCodexModelCache(authFilePath, bootstrap) {
|
|
|
3566
3702
|
}
|
|
3567
3703
|
}
|
|
3568
3704
|
async function ensureCodexModelCache(authFilePath, bootstrap = bootstrapCodexModelCache) {
|
|
3569
|
-
const codexHome =
|
|
3705
|
+
const codexHome = dirname7(authFilePath);
|
|
3570
3706
|
const configuredCachePath = process.env.NEGOTIUM_CODEX_MODELS_CACHE_FILE;
|
|
3571
3707
|
if (configuredCachePath) {
|
|
3572
3708
|
if (!existsSync9(configuredCachePath)) {
|
|
@@ -3595,7 +3731,7 @@ async function ensureCodexModelCache(authFilePath, bootstrap = bootstrapCodexMod
|
|
|
3595
3731
|
return bundledCachePath;
|
|
3596
3732
|
}
|
|
3597
3733
|
function writeCodexCatalogWithNativeMultiAgentDisabled(authFilePath, sourcePath) {
|
|
3598
|
-
const codexHome =
|
|
3734
|
+
const codexHome = dirname7(authFilePath);
|
|
3599
3735
|
const outputPath = join11(codexHome, NEGOTIUM_MODEL_CATALOG);
|
|
3600
3736
|
const parsed = readCodexModelCache(sourcePath).parsed;
|
|
3601
3737
|
const models = parsed.models.map((model, index) => {
|
|
@@ -3610,6 +3746,52 @@ function writeCodexCatalogWithNativeMultiAgentDisabled(authFilePath, sourcePath)
|
|
|
3610
3746
|
return outputPath;
|
|
3611
3747
|
}
|
|
3612
3748
|
|
|
3749
|
+
// ../../packages/core/src/agents/tool-format.ts
|
|
3750
|
+
import { diffLines as computeLineDiff } from "diff";
|
|
3751
|
+
function changedDiffLines(value) {
|
|
3752
|
+
const lines = value.split(`
|
|
3753
|
+
`);
|
|
3754
|
+
if (lines.at(-1) === "")
|
|
3755
|
+
lines.pop();
|
|
3756
|
+
return lines;
|
|
3757
|
+
}
|
|
3758
|
+
function buildNumberedDiffSummary(before, after, startLine = 1) {
|
|
3759
|
+
const removed = [];
|
|
3760
|
+
const added = [];
|
|
3761
|
+
const preview = [];
|
|
3762
|
+
let oldLine = startLine;
|
|
3763
|
+
let newLine = startLine;
|
|
3764
|
+
for (const part of computeLineDiff(before, after)) {
|
|
3765
|
+
const lines = changedDiffLines(part.value);
|
|
3766
|
+
if (part.removed) {
|
|
3767
|
+
for (const line of lines) {
|
|
3768
|
+
removed.push(line);
|
|
3769
|
+
preview.push(`${oldLine} -${line}`);
|
|
3770
|
+
oldLine += 1;
|
|
3771
|
+
}
|
|
3772
|
+
continue;
|
|
3773
|
+
}
|
|
3774
|
+
if (part.added) {
|
|
3775
|
+
for (const line of lines) {
|
|
3776
|
+
added.push(line);
|
|
3777
|
+
preview.push(`${newLine} +${line}`);
|
|
3778
|
+
newLine += 1;
|
|
3779
|
+
}
|
|
3780
|
+
continue;
|
|
3781
|
+
}
|
|
3782
|
+
oldLine += lines.length;
|
|
3783
|
+
newLine += lines.length;
|
|
3784
|
+
}
|
|
3785
|
+
return {
|
|
3786
|
+
...removed.length > 0 ? { before: removed.join(`
|
|
3787
|
+
`) } : {},
|
|
3788
|
+
...added.length > 0 ? { after: added.join(`
|
|
3789
|
+
`) } : {},
|
|
3790
|
+
...preview.length > 0 ? { diffPreview: preview.join(`
|
|
3791
|
+
`) } : {}
|
|
3792
|
+
};
|
|
3793
|
+
}
|
|
3794
|
+
|
|
3613
3795
|
// ../../packages/core/src/agents/codex-provider.ts
|
|
3614
3796
|
function mapEffort(effort) {
|
|
3615
3797
|
if (!effort)
|
|
@@ -3692,22 +3874,142 @@ function summarizeMcpToolCallResult(item) {
|
|
|
3692
3874
|
return text.slice(0, 200);
|
|
3693
3875
|
return JSON.stringify(item.result.structured_content ?? "").slice(0, 200);
|
|
3694
3876
|
}
|
|
3695
|
-
|
|
3877
|
+
var CODEX_DIFF_FILE_LIMIT = 512 * 1024;
|
|
3878
|
+
var CODEX_DIFF_BASELINE_FILE_LIMIT = 200;
|
|
3879
|
+
var CODEX_DIFF_BASELINE_BYTE_LIMIT = 16 * 1024 * 1024;
|
|
3880
|
+
function canonicalPath(path) {
|
|
3881
|
+
try {
|
|
3882
|
+
return realpathSync3(resolve6(path));
|
|
3883
|
+
} catch {
|
|
3884
|
+
return resolve6(path);
|
|
3885
|
+
}
|
|
3886
|
+
}
|
|
3887
|
+
function textFile(path, maxBytes = CODEX_DIFF_FILE_LIMIT) {
|
|
3888
|
+
if (!existsSync10(path))
|
|
3889
|
+
return null;
|
|
3890
|
+
try {
|
|
3891
|
+
const byteLimit = Math.min(CODEX_DIFF_FILE_LIMIT, Math.max(0, maxBytes));
|
|
3892
|
+
if (statSync3(path).size > byteLimit)
|
|
3893
|
+
return;
|
|
3894
|
+
const content = readFileSync8(path);
|
|
3895
|
+
if (content.byteLength > byteLimit || content.includes(0))
|
|
3896
|
+
return;
|
|
3897
|
+
return content.toString("utf8");
|
|
3898
|
+
} catch {
|
|
3899
|
+
return;
|
|
3900
|
+
}
|
|
3901
|
+
}
|
|
3902
|
+
|
|
3903
|
+
class CodexFilePreviewTracker {
|
|
3904
|
+
#cwd;
|
|
3905
|
+
#root;
|
|
3906
|
+
#baseline = new Map;
|
|
3907
|
+
#baselineAvailable = false;
|
|
3908
|
+
constructor(cwd) {
|
|
3909
|
+
this.#cwd = canonicalPath(cwd);
|
|
3910
|
+
const root = this.#git(["rev-parse", "--show-toplevel"], this.#cwd)?.trim();
|
|
3911
|
+
this.#root = root ? canonicalPath(root) : null;
|
|
3912
|
+
if (!this.#root)
|
|
3913
|
+
return;
|
|
3914
|
+
const status = this.#git(["status", "--porcelain=v1", "-z", "--untracked-files=all"]);
|
|
3915
|
+
if (status === undefined)
|
|
3916
|
+
return;
|
|
3917
|
+
this.#baselineAvailable = true;
|
|
3918
|
+
let loadedFiles = 0;
|
|
3919
|
+
let loadedBytes = 0;
|
|
3920
|
+
const records = status.split("\x00");
|
|
3921
|
+
for (let index = 0;index < records.length; index += 1) {
|
|
3922
|
+
const record = records[index];
|
|
3923
|
+
if (!record || record.length < 4)
|
|
3924
|
+
continue;
|
|
3925
|
+
const code = record.slice(0, 2);
|
|
3926
|
+
const path = record.slice(3);
|
|
3927
|
+
const remainingBytes = CODEX_DIFF_BASELINE_BYTE_LIMIT - loadedBytes;
|
|
3928
|
+
const content = loadedFiles < CODEX_DIFF_BASELINE_FILE_LIMIT && remainingBytes > 0 ? textFile(resolve6(this.#root, path), remainingBytes) : undefined;
|
|
3929
|
+
this.#baseline.set(path, content);
|
|
3930
|
+
if (typeof content === "string") {
|
|
3931
|
+
loadedFiles += 1;
|
|
3932
|
+
loadedBytes += Buffer.byteLength(content);
|
|
3933
|
+
}
|
|
3934
|
+
if (/[RC]/.test(code))
|
|
3935
|
+
index += 1;
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
preview(path, succeeded) {
|
|
3939
|
+
if (!this.#root || !this.#baselineAvailable || !succeeded)
|
|
3940
|
+
return {};
|
|
3941
|
+
const absolute = canonicalPath(isAbsolute(path) ? path : resolve6(this.#cwd, path));
|
|
3942
|
+
const relativePath = relative(this.#root, absolute);
|
|
3943
|
+
if (!relativePath || relativePath.startsWith("..") || isAbsolute(relativePath))
|
|
3944
|
+
return {};
|
|
3945
|
+
const before = this.#baseline.has(relativePath) ? this.#baseline.get(relativePath) : this.#headFile(relativePath);
|
|
3946
|
+
const after = textFile(absolute);
|
|
3947
|
+
this.#baseline.set(relativePath, after);
|
|
3948
|
+
if (before === undefined || after === undefined)
|
|
3949
|
+
return {};
|
|
3950
|
+
const diff = buildNumberedDiffSummary(before ?? "", after ?? "");
|
|
3951
|
+
return {
|
|
3952
|
+
...diff.before !== undefined ? { before: diff.before } : {},
|
|
3953
|
+
...diff.after !== undefined ? { after: diff.after } : {},
|
|
3954
|
+
...diff.diffPreview !== undefined ? { diff_preview: diff.diffPreview } : {}
|
|
3955
|
+
};
|
|
3956
|
+
}
|
|
3957
|
+
#headFile(path) {
|
|
3958
|
+
const content = this.#git(["show", `HEAD:${path}`]);
|
|
3959
|
+
if (content === undefined)
|
|
3960
|
+
return null;
|
|
3961
|
+
return Buffer.byteLength(content) > CODEX_DIFF_FILE_LIMIT || content.includes("\x00") ? undefined : content;
|
|
3962
|
+
}
|
|
3963
|
+
#git(args, cwd = this.#root ?? undefined) {
|
|
3964
|
+
try {
|
|
3965
|
+
return execFileSync5("git", ["-C", cwd ?? ".", ...args], {
|
|
3966
|
+
encoding: "utf8",
|
|
3967
|
+
maxBuffer: CODEX_DIFF_FILE_LIMIT * 4,
|
|
3968
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
3969
|
+
});
|
|
3970
|
+
} catch {
|
|
3971
|
+
return;
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3974
|
+
}
|
|
3975
|
+
async function fileChangeEvents(item, previews, cwd, threadId, consumedPatchCallIds) {
|
|
3976
|
+
const expectedPaths = item.changes.map((change) => isAbsolute(change.path) ? change.path : resolve6(cwd, change.path));
|
|
3977
|
+
let nativePreview;
|
|
3978
|
+
if (threadId && item.status === "completed") {
|
|
3979
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, 20));
|
|
3980
|
+
nativePreview = readLatestCodexPatchPreview(threadId, expectedPaths, consumedPatchCallIds);
|
|
3981
|
+
}
|
|
3982
|
+
for (const delayMs of [20, 40, 80, 120]) {
|
|
3983
|
+
if (nativePreview || !threadId || item.status !== "completed")
|
|
3984
|
+
break;
|
|
3985
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, delayMs));
|
|
3986
|
+
nativePreview = readLatestCodexPatchPreview(threadId, expectedPaths, consumedPatchCallIds);
|
|
3987
|
+
}
|
|
3988
|
+
if (nativePreview)
|
|
3989
|
+
consumedPatchCallIds.add(nativePreview.callId);
|
|
3696
3990
|
return item.changes.flatMap((change, index) => {
|
|
3697
3991
|
const name = change.kind === "add" ? "Write" : change.kind === "delete" ? "Delete" : "Edit";
|
|
3698
3992
|
const toolUseId = `${item.id}:${index}`;
|
|
3699
3993
|
const success = item.status === "completed";
|
|
3994
|
+
const nativeChange = nativePreview?.changes[index];
|
|
3995
|
+
const fallbackPreview = previews.preview(change.path, success);
|
|
3996
|
+
const preview = success && nativeChange ? {
|
|
3997
|
+
...nativeChange.before !== undefined ? { before: nativeChange.before } : {},
|
|
3998
|
+
...nativeChange.after !== undefined ? { after: nativeChange.after } : {},
|
|
3999
|
+
...nativeChange.diffPreview !== undefined ? { diff_preview: nativeChange.diffPreview } : {}
|
|
4000
|
+
} : fallbackPreview;
|
|
3700
4001
|
return [
|
|
3701
4002
|
{
|
|
3702
4003
|
type: "tool_use",
|
|
3703
4004
|
name,
|
|
3704
|
-
input: { file_path: change.path, change_kind: change.kind },
|
|
4005
|
+
input: { file_path: change.path, change_kind: change.kind, ...preview },
|
|
3705
4006
|
toolUseId
|
|
3706
4007
|
},
|
|
3707
4008
|
{
|
|
3708
4009
|
type: "tool_result",
|
|
3709
4010
|
toolUseId,
|
|
3710
|
-
content: success ? `${change.kind} applied: ${change.path}` : `${change.kind} failed: ${change.path}
|
|
4011
|
+
content: success ? `${change.kind} applied: ${change.path}` : `${change.kind} failed: ${change.path}`,
|
|
4012
|
+
...success ? {} : { isError: true }
|
|
3711
4013
|
}
|
|
3712
4014
|
];
|
|
3713
4015
|
});
|
|
@@ -3793,6 +4095,8 @@ function prependFirstEvent(iter, firstEvent, alreadyDone) {
|
|
|
3793
4095
|
};
|
|
3794
4096
|
}
|
|
3795
4097
|
async function* codexProvider(opts) {
|
|
4098
|
+
const filePreviews = new CodexFilePreviewTracker(opts.cwd);
|
|
4099
|
+
const consumedPatchCallIds = new Set(opts.sessionId ? readCodexPatchCallIds(opts.sessionId) : []);
|
|
3796
4100
|
const codexAuthPath = hostedCodexAuthFilePath();
|
|
3797
4101
|
if (!existsSync10(codexAuthPath)) {
|
|
3798
4102
|
yield {
|
|
@@ -3927,10 +4231,11 @@ async function* codexProvider(opts) {
|
|
|
3927
4231
|
if (!item)
|
|
3928
4232
|
break;
|
|
3929
4233
|
if (item.type === "command_execution") {
|
|
4234
|
+
const command = String(item.command ?? "");
|
|
3930
4235
|
yield {
|
|
3931
4236
|
type: "tool_use",
|
|
3932
4237
|
name: "Bash",
|
|
3933
|
-
input: { command
|
|
4238
|
+
input: { command },
|
|
3934
4239
|
toolUseId: String(item.id ?? "")
|
|
3935
4240
|
};
|
|
3936
4241
|
} else if (item.type === "mcp_tool_call") {
|
|
@@ -3976,19 +4281,24 @@ async function* codexProvider(opts) {
|
|
|
3976
4281
|
if (reasoning)
|
|
3977
4282
|
yield { type: "reasoning", content: reasoning };
|
|
3978
4283
|
} else if (item.type === "mcp_tool_call") {
|
|
4284
|
+
const isError = item.status === "failed" || Boolean(item.error);
|
|
3979
4285
|
yield {
|
|
3980
4286
|
type: "tool_result",
|
|
3981
4287
|
toolUseId: String(item.id ?? ""),
|
|
3982
|
-
content: summarizeMcpToolCallResult(item)
|
|
4288
|
+
content: summarizeMcpToolCallResult(item),
|
|
4289
|
+
...isError ? { isError: true } : {}
|
|
3983
4290
|
};
|
|
3984
4291
|
} else if (item.type === "command_execution") {
|
|
4292
|
+
const isError = item.status === "failed" || typeof item.exit_code === "number" && item.exit_code !== 0;
|
|
3985
4293
|
yield {
|
|
3986
4294
|
type: "tool_result",
|
|
3987
4295
|
toolUseId: String(item.id ?? ""),
|
|
3988
|
-
content: String(item.aggregated_output ?? "").slice(0, 200)
|
|
4296
|
+
content: String(item.aggregated_output ?? "").slice(0, 200),
|
|
4297
|
+
...isError ? { isError: true } : {}
|
|
3989
4298
|
};
|
|
3990
4299
|
} else if (item.type === "file_change") {
|
|
3991
|
-
|
|
4300
|
+
const fileEvents = await fileChangeEvents(item, filePreviews, opts.cwd, currentSessionId, consumedPatchCallIds);
|
|
4301
|
+
for (const fileEvent of fileEvents) {
|
|
3992
4302
|
yield fileEvent;
|
|
3993
4303
|
}
|
|
3994
4304
|
} else if (item.type === "error") {
|
|
@@ -4184,8 +4494,8 @@ function maestroProvider(opts) {
|
|
|
4184
4494
|
}
|
|
4185
4495
|
|
|
4186
4496
|
// ../../packages/core/src/storage/tasks.ts
|
|
4187
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as
|
|
4188
|
-
import { dirname as
|
|
4497
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync9, renameSync as renameSync5, statSync as statSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
4498
|
+
import { dirname as dirname8, join as join12 } from "path";
|
|
4189
4499
|
function safeUserIdComponent2(userId) {
|
|
4190
4500
|
const str = String(userId);
|
|
4191
4501
|
if (!str || /[/\\]|\.\./.test(str)) {
|
|
@@ -4211,7 +4521,7 @@ function readTasks(userId, scopeKey) {
|
|
|
4211
4521
|
if (!existsSync11(path))
|
|
4212
4522
|
return [];
|
|
4213
4523
|
try {
|
|
4214
|
-
const parsed = JSON.parse(
|
|
4524
|
+
const parsed = JSON.parse(readFileSync9(path, "utf-8"));
|
|
4215
4525
|
return Array.isArray(parsed?.tasks) ? parsed.tasks : [];
|
|
4216
4526
|
} catch (e) {
|
|
4217
4527
|
logger.warn({ err: e, path }, "tasks: failed to read task store");
|
|
@@ -4220,7 +4530,7 @@ function readTasks(userId, scopeKey) {
|
|
|
4220
4530
|
}
|
|
4221
4531
|
function taskFileMtimeNs(userId, scopeKey) {
|
|
4222
4532
|
try {
|
|
4223
|
-
return
|
|
4533
|
+
return statSync4(getTaskFilePath(userId, scopeKey), { bigint: true }).mtimeNs;
|
|
4224
4534
|
} catch {
|
|
4225
4535
|
return null;
|
|
4226
4536
|
}
|
|
@@ -4541,9 +4851,15 @@ class SqliteRuntimeBus {
|
|
|
4541
4851
|
toolUseId: id
|
|
4542
4852
|
});
|
|
4543
4853
|
}
|
|
4544
|
-
broadcastToolOutput(topicId, queryId, toolUseId, content) {
|
|
4854
|
+
broadcastToolOutput(topicId, queryId, toolUseId, content, isError) {
|
|
4545
4855
|
const id = toolUseId.trim() || `${queryId}:tool`;
|
|
4546
|
-
this.broadcastAiStatus(topicId, {
|
|
4856
|
+
this.broadcastAiStatus(topicId, {
|
|
4857
|
+
kind: "tool_output",
|
|
4858
|
+
queryId,
|
|
4859
|
+
toolUseId: id,
|
|
4860
|
+
content,
|
|
4861
|
+
...isError ? { isError: true } : {}
|
|
4862
|
+
});
|
|
4547
4863
|
}
|
|
4548
4864
|
broadcastToolStatus(topicId, queryId, kind, content, meta) {
|
|
4549
4865
|
this.broadcastAiStatus(topicId, {
|
|
@@ -4585,8 +4901,8 @@ var WsHub = {
|
|
|
4585
4901
|
};
|
|
4586
4902
|
|
|
4587
4903
|
// ../../packages/core/src/prompts/builders.ts
|
|
4588
|
-
import { readFileSync as
|
|
4589
|
-
import { resolve as
|
|
4904
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
4905
|
+
import { resolve as resolve7 } from "path";
|
|
4590
4906
|
|
|
4591
4907
|
// ../../packages/core/src/agents/model-catalog.ts
|
|
4592
4908
|
var CODEX_PRO_20X_COST = "ChatGPT Pro 20x subscription: $200/month";
|
|
@@ -4687,10 +5003,10 @@ var SELECTABLE_MODELS = [
|
|
|
4687
5003
|
];
|
|
4688
5004
|
|
|
4689
5005
|
// ../../packages/core/src/prompts/builders.ts
|
|
4690
|
-
var PROMPTS_DIR =
|
|
4691
|
-
var SESSIONS_DIR =
|
|
5006
|
+
var PROMPTS_DIR = resolve7(PROJECT_ROOT, "src/prompts");
|
|
5007
|
+
var SESSIONS_DIR = resolve7(PROMPTS_DIR, "sessions");
|
|
4692
5008
|
function loadAgentPrompt(filename) {
|
|
4693
|
-
const raw =
|
|
5009
|
+
const raw = readFileSync10(resolve7(AGENTS_PROMPTS_DIR, filename), "utf-8");
|
|
4694
5010
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
4695
5011
|
if (!match)
|
|
4696
5012
|
throw new Error(`Agent prompt ${filename} is missing frontmatter`);
|
|
@@ -4871,7 +5187,7 @@ function setTopicBrief(topicId, fields) {
|
|
|
4871
5187
|
}
|
|
4872
5188
|
|
|
4873
5189
|
// ../../packages/core/src/storage/wiki.ts
|
|
4874
|
-
import { basename, dirname as
|
|
5190
|
+
import { basename as basename2, dirname as dirname9, join as join14 } from "path";
|
|
4875
5191
|
function getSharedWikiDir(workspaceDir = resolveStorageWorkspaceDir()) {
|
|
4876
5192
|
return workspaceDir === resolveStorageWorkspaceDir() ? resolveStorageSharedWikiDir() : join14(workspaceDir, "wiki");
|
|
4877
5193
|
}
|
|
@@ -5595,7 +5911,7 @@ function findSummaryFile(topicTitle, date, sinceMs, topicId) {
|
|
|
5595
5911
|
continue;
|
|
5596
5912
|
const p = join15(dir, f);
|
|
5597
5913
|
try {
|
|
5598
|
-
const m =
|
|
5914
|
+
const m = statSync5(p).mtimeMs;
|
|
5599
5915
|
if (m >= sinceMs && (!best || m > best.mtime))
|
|
5600
5916
|
best = { path: p, mtime: m };
|
|
5601
5917
|
} catch {}
|
|
@@ -5607,7 +5923,7 @@ function finalizeGeneralMemory(userId, topicTitle, messageCount, startMs, ok, to
|
|
|
5607
5923
|
const date = new Date().toISOString().slice(0, 10);
|
|
5608
5924
|
try {
|
|
5609
5925
|
const summaryPath = ok ? findSummaryFile(topicTitle, date, startMs, topicId) : null;
|
|
5610
|
-
const summaryMd = summaryPath ?
|
|
5926
|
+
const summaryMd = summaryPath ? readFileSync11(summaryPath, "utf-8") : "";
|
|
5611
5927
|
const oneLine = summaryMd && distillOneLine(summaryMd) || `${messageCount}\uAC1C \uBA54\uC2DC\uC9C0 \uC544\uCE74\uC774\uBE0C`;
|
|
5612
5928
|
const prev = getTopicBrief(generalTopicId);
|
|
5613
5929
|
const prevEntries = (prev?.briefMd ?? "").split(`
|
|
@@ -6567,4 +6883,4 @@ export {
|
|
|
6567
6883
|
MIN_MEMORY_ARCHIVE_EXCHANGES
|
|
6568
6884
|
};
|
|
6569
6885
|
|
|
6570
|
-
//# debugId=
|
|
6886
|
+
//# debugId=CC442F5FF6F506FC64756E2164756E21
|