negotium 0.1.48 → 0.1.49
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 +2 -2
- package/dist/agent-helpers.js.map +2 -2
- package/dist/{chunk-d9jyt6xe.js → chunk-5rpw9d1f.js} +135 -2
- package/dist/{chunk-d9jyt6xe.js.map → chunk-5rpw9d1f.js.map} +2 -2
- package/dist/hosted-agent.js +2 -2
- package/dist/hosted-agent.js.map +2 -2
- package/dist/main.js +2 -2
- package/dist/main.js.map +2 -2
- package/dist/mcp-factories.js +548 -153
- package/dist/mcp-factories.js.map +3 -3
- package/dist/registry.js +293 -10
- package/dist/registry.js.map +7 -5
- package/dist/rollout.js +14 -2
- package/dist/rollout.js.map +3 -3
- package/dist/runtime/src/version.ts +1 -1
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/mcp-factories.js
CHANGED
|
@@ -583,6 +583,13 @@ function parseJsonlText(raw) {
|
|
|
583
583
|
return raw.trim().split(`
|
|
584
584
|
`).filter(Boolean).map((line) => JSON.parse(line));
|
|
585
585
|
}
|
|
586
|
+
function readJsonFile(filePath) {
|
|
587
|
+
try {
|
|
588
|
+
return JSON.parse(readFileSync3(filePath, "utf-8"));
|
|
589
|
+
} catch {
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
586
593
|
function lockStaleMs() {
|
|
587
594
|
const raw = Number.parseInt(process.env.NEGOTIUM_JSONL_LOCK_STALE_MS ?? "", 10);
|
|
588
595
|
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_LOCK_STALE_MS;
|
|
@@ -3498,7 +3505,7 @@ var init_registry = __esm(async () => {
|
|
|
3498
3505
|
});
|
|
3499
3506
|
|
|
3500
3507
|
// ../../packages/core/src/agents/fork.ts
|
|
3501
|
-
import { existsSync as
|
|
3508
|
+
import { existsSync as existsSync10, unlinkSync as unlinkSync8 } from "fs";
|
|
3502
3509
|
function createAgentForkHelpers(host) {
|
|
3503
3510
|
return {
|
|
3504
3511
|
async forkAgentSession(options) {
|
|
@@ -3530,7 +3537,7 @@ var init_fork = __esm(async () => {
|
|
|
3530
3537
|
await init_registry();
|
|
3531
3538
|
defaultForkHelpers = createAgentForkHelpers({
|
|
3532
3539
|
forkSession: (agent, options) => getRegistryOperations(agent).forkSession(options),
|
|
3533
|
-
exists:
|
|
3540
|
+
exists: existsSync10,
|
|
3534
3541
|
unlink: unlinkSync8,
|
|
3535
3542
|
warn: (details, message) => logger.warn(details, message)
|
|
3536
3543
|
});
|
|
@@ -3923,7 +3930,7 @@ var init_runtime_process_leases = __esm(async () => {
|
|
|
3923
3930
|
|
|
3924
3931
|
// ../../packages/core/src/platform/playwright/browser-processes.ts
|
|
3925
3932
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
3926
|
-
import { readdirSync as
|
|
3933
|
+
import { readdirSync as readdirSync4, unlinkSync as unlinkSync9 } from "fs";
|
|
3927
3934
|
import { createServer } from "net";
|
|
3928
3935
|
import { resolve as resolve7, sep } from "path";
|
|
3929
3936
|
function isPortInUse(port) {
|
|
@@ -4048,7 +4055,7 @@ function reapOrphanBrowsers(liveUserDataDirs) {
|
|
|
4048
4055
|
}
|
|
4049
4056
|
function cleanSingletonFiles(userDataDir) {
|
|
4050
4057
|
try {
|
|
4051
|
-
const files =
|
|
4058
|
+
const files = readdirSync4(userDataDir);
|
|
4052
4059
|
for (const f of files) {
|
|
4053
4060
|
if (f.startsWith("Singleton")) {
|
|
4054
4061
|
try {
|
|
@@ -4239,7 +4246,7 @@ var init_vault_crypto = __esm(() => {
|
|
|
4239
4246
|
|
|
4240
4247
|
// ../../packages/core/src/storage/vault.ts
|
|
4241
4248
|
import { chmodSync as chmodSync2, mkdirSync as mkdirSync9 } from "fs";
|
|
4242
|
-
import { join as
|
|
4249
|
+
import { join as join12 } from "path";
|
|
4243
4250
|
function initializeVaultDatabase(database) {
|
|
4244
4251
|
database.exec("PRAGMA journal_mode = WAL");
|
|
4245
4252
|
database.exec("PRAGMA busy_timeout = 5000");
|
|
@@ -4274,7 +4281,7 @@ function initializeVaultDatabase(database) {
|
|
|
4274
4281
|
}
|
|
4275
4282
|
}
|
|
4276
4283
|
function openVaultDatabase(dataDir) {
|
|
4277
|
-
const path =
|
|
4284
|
+
const path = join12(dataDir, "vault.db");
|
|
4278
4285
|
mkdirSync9(dataDir, { recursive: true });
|
|
4279
4286
|
const database = new Database(path, { create: true });
|
|
4280
4287
|
chmodSync2(path, 384);
|
|
@@ -4381,7 +4388,7 @@ import { randomBytes as randomBytes4, timingSafeEqual } from "crypto";
|
|
|
4381
4388
|
import { chmodSync as chmodSync3 } from "fs";
|
|
4382
4389
|
import { createServer as createServer2 } from "net";
|
|
4383
4390
|
import { tmpdir } from "os";
|
|
4384
|
-
import { join as
|
|
4391
|
+
import { join as join13 } from "path";
|
|
4385
4392
|
function deepMapStrings(value2, transform) {
|
|
4386
4393
|
if (typeof value2 === "string")
|
|
4387
4394
|
return transform(value2);
|
|
@@ -4468,7 +4475,7 @@ function authorized(actual, expected) {
|
|
|
4468
4475
|
}
|
|
4469
4476
|
async function createBrowserVaultBroker(userId) {
|
|
4470
4477
|
const token = randomBytes4(32).toString("hex");
|
|
4471
|
-
const socketPath =
|
|
4478
|
+
const socketPath = join13(process.platform === "win32" ? tmpdir() : "/tmp", `negotium-browser-vault-${process.pid}-${randomBytes4(8).toString("hex")}.sock`);
|
|
4472
4479
|
const retainedForms = new Map;
|
|
4473
4480
|
const leases = new Map;
|
|
4474
4481
|
const sockets = new Set;
|
|
@@ -4661,19 +4668,19 @@ var init_browser_profiles = __esm(async () => {
|
|
|
4661
4668
|
});
|
|
4662
4669
|
|
|
4663
4670
|
// ../../packages/core/src/platform/playwright/manager.ts
|
|
4664
|
-
import { execFileSync as execFileSync3, spawn as
|
|
4671
|
+
import { execFileSync as execFileSync3, spawn as spawn3 } from "child_process";
|
|
4665
4672
|
import { createHash as createHash2, randomBytes as randomBytes5, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
4666
4673
|
import {
|
|
4667
4674
|
cpSync,
|
|
4668
|
-
existsSync as
|
|
4675
|
+
existsSync as existsSync11,
|
|
4669
4676
|
mkdirSync as mkdirSync10,
|
|
4670
|
-
readFileSync as
|
|
4677
|
+
readFileSync as readFileSync9,
|
|
4671
4678
|
renameSync as renameSync5,
|
|
4672
4679
|
rmSync,
|
|
4673
4680
|
unlinkSync as unlinkSync10,
|
|
4674
4681
|
writeFileSync as writeFileSync7
|
|
4675
4682
|
} from "fs";
|
|
4676
|
-
import { dirname as dirname8, join as
|
|
4683
|
+
import { dirname as dirname8, join as join14, resolve as resolve9 } from "path";
|
|
4677
4684
|
function makeInstanceKey(userId, topic) {
|
|
4678
4685
|
return resolvePlaywrightTopicBinding(userId, topic).instanceKey;
|
|
4679
4686
|
}
|
|
@@ -4713,12 +4720,12 @@ function migrateLegacyTopicProfile(ownerId, topic) {
|
|
|
4713
4720
|
if (current2 !== "default" || !hasBrowserProfileTopic(topic))
|
|
4714
4721
|
return current2;
|
|
4715
4722
|
const legacyDir = resolve9(BROWSER_PROFILES_DIR, sanitizeTopicName(topic));
|
|
4716
|
-
if (!
|
|
4723
|
+
if (!existsSync11(legacyDir))
|
|
4717
4724
|
return current2;
|
|
4718
4725
|
const profile = legacyBrowserProfileName(topic);
|
|
4719
4726
|
const profileDir = defaultProfileDir(ownerId, profile);
|
|
4720
4727
|
mkdirSync10(dirname8(profileDir), { recursive: true });
|
|
4721
|
-
if (!
|
|
4728
|
+
if (!existsSync11(profileDir))
|
|
4722
4729
|
renameSync5(legacyDir, profileDir);
|
|
4723
4730
|
assignTopicBrowserProfile({ topicId: topic, actorUserId: ownerId, profile });
|
|
4724
4731
|
logger.info({ ownerId, topic, profile }, "Adopted legacy topic browser profile");
|
|
@@ -4768,14 +4775,14 @@ function portFileName(instanceKey) {
|
|
|
4768
4775
|
function writePortFile(instanceKey, port) {
|
|
4769
4776
|
try {
|
|
4770
4777
|
mkdirSync10(managerHost.portsDir, { recursive: true });
|
|
4771
|
-
writeFileSync7(
|
|
4778
|
+
writeFileSync7(join14(managerHost.portsDir, portFileName(instanceKey)), String(port));
|
|
4772
4779
|
} catch (e) {
|
|
4773
4780
|
logger.warn({ err: e, instanceKey, port }, "Failed to save playwright port file");
|
|
4774
4781
|
}
|
|
4775
4782
|
}
|
|
4776
4783
|
function deletePortFile(instanceKey) {
|
|
4777
4784
|
try {
|
|
4778
|
-
unlinkSync10(
|
|
4785
|
+
unlinkSync10(join14(managerHost.portsDir, portFileName(instanceKey)));
|
|
4779
4786
|
} catch (e) {
|
|
4780
4787
|
logger.warn({ err: e, instanceKey }, "Failed to delete playwright port file");
|
|
4781
4788
|
}
|
|
@@ -5029,7 +5036,7 @@ async function spawnPlaywright(instanceKey, ownerId, reservedPort, browserBin =
|
|
|
5029
5036
|
}
|
|
5030
5037
|
let proc;
|
|
5031
5038
|
try {
|
|
5032
|
-
proc =
|
|
5039
|
+
proc = spawn3(spawnSpec.command, spawnSpec.args, {
|
|
5033
5040
|
stdio: ["ignore", "ignore", "pipe"],
|
|
5034
5041
|
detached: false,
|
|
5035
5042
|
env: childEnv
|
|
@@ -5262,11 +5269,11 @@ async function cloneProfileForChild(opts) {
|
|
|
5262
5269
|
killInstance(dstKey);
|
|
5263
5270
|
await delay(500);
|
|
5264
5271
|
}
|
|
5265
|
-
if (!
|
|
5272
|
+
if (!existsSync11(srcDir)) {
|
|
5266
5273
|
return { copied: false, srcDir, dstDir, reason: "src-missing" };
|
|
5267
5274
|
}
|
|
5268
5275
|
try {
|
|
5269
|
-
if (
|
|
5276
|
+
if (existsSync11(dstDir)) {
|
|
5270
5277
|
rmSync(dstDir, { recursive: true, force: true });
|
|
5271
5278
|
}
|
|
5272
5279
|
mkdirSync10(dirname8(dstDir), { recursive: true });
|
|
@@ -5945,8 +5952,8 @@ RULES:
|
|
|
5945
5952
|
- Keep the entire summary under 1500 words.`, CHARS_PER_TEXT_TOKEN = 3.5, CHARS_PER_CJK_TOKEN = 0.9;
|
|
5946
5953
|
|
|
5947
5954
|
// ../../packages/core/src/storage/tasks.ts
|
|
5948
|
-
import { existsSync as
|
|
5949
|
-
import { dirname as dirname9, join as
|
|
5955
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync11, readFileSync as readFileSync10, renameSync as renameSync6, statSync as statSync4, writeFileSync as writeFileSync8 } from "fs";
|
|
5956
|
+
import { dirname as dirname9, join as join15 } from "path";
|
|
5950
5957
|
function safeUserIdComponent2(userId) {
|
|
5951
5958
|
const str = String(userId);
|
|
5952
5959
|
if (!str || /[/\\]|\.\./.test(str)) {
|
|
@@ -5965,14 +5972,14 @@ function taskScopeKey(opts) {
|
|
|
5965
5972
|
return opts.topicId?.trim() || opts.session || "default";
|
|
5966
5973
|
}
|
|
5967
5974
|
function getTaskFilePath(userId, scopeKey) {
|
|
5968
|
-
return
|
|
5975
|
+
return join15(resolveStorageDataDir(), "tasks", safeUserIdComponent2(userId), `${safeTaskScopeKey(scopeKey)}.json`);
|
|
5969
5976
|
}
|
|
5970
5977
|
function readTasks(userId, scopeKey) {
|
|
5971
5978
|
const path = getTaskFilePath(userId, scopeKey);
|
|
5972
|
-
if (!
|
|
5979
|
+
if (!existsSync12(path))
|
|
5973
5980
|
return [];
|
|
5974
5981
|
try {
|
|
5975
|
-
const parsed = JSON.parse(
|
|
5982
|
+
const parsed = JSON.parse(readFileSync10(path, "utf-8"));
|
|
5976
5983
|
return Array.isArray(parsed?.tasks) ? parsed.tasks : [];
|
|
5977
5984
|
} catch (e) {
|
|
5978
5985
|
logger.warn({ err: e, path }, "tasks: failed to read task store");
|
|
@@ -6141,14 +6148,14 @@ function deepMapStrings2(value2, fn) {
|
|
|
6141
6148
|
}
|
|
6142
6149
|
|
|
6143
6150
|
// ../../packages/core/src/security/sensitive-path.ts
|
|
6144
|
-
import { realpathSync as
|
|
6151
|
+
import { realpathSync as realpathSync3 } from "fs";
|
|
6145
6152
|
import { resolve as resolve10 } from "path";
|
|
6146
6153
|
function isSensitivePath(filePath) {
|
|
6147
6154
|
const normalized = resolve10(filePath);
|
|
6148
6155
|
if (SENSITIVE_PATH_PATTERNS.some((p) => p.test(normalized)))
|
|
6149
6156
|
return true;
|
|
6150
6157
|
try {
|
|
6151
|
-
const real =
|
|
6158
|
+
const real = realpathSync3(normalized);
|
|
6152
6159
|
if (real !== normalized)
|
|
6153
6160
|
return SENSITIVE_PATH_PATTERNS.some((p) => p.test(real));
|
|
6154
6161
|
} catch {}
|
|
@@ -6331,7 +6338,7 @@ function deriveBgBashContextCapability(runtimeCapability, userId, topic) {
|
|
|
6331
6338
|
var init_context = () => {};
|
|
6332
6339
|
|
|
6333
6340
|
// ../../packages/core/src/platform/background-bash/manager.ts
|
|
6334
|
-
import { execFileSync as execFileSync4, spawn as
|
|
6341
|
+
import { execFileSync as execFileSync4, spawn as spawn4 } from "child_process";
|
|
6335
6342
|
import { randomBytes as randomBytes6 } from "crypto";
|
|
6336
6343
|
function makeBgBashKey(_userId, _topic) {
|
|
6337
6344
|
return "runtime";
|
|
@@ -6358,7 +6365,7 @@ function createBackgroundBashManager(options = {}) {
|
|
|
6358
6365
|
const now = options.now ?? Date.now;
|
|
6359
6366
|
const wait = options.delay ?? delay;
|
|
6360
6367
|
const portPids = options.portPids ?? defaultPortPids;
|
|
6361
|
-
const spawnImpl = options.spawn ?? ((command, args, spawnOptions) =>
|
|
6368
|
+
const spawnImpl = options.spawn ?? ((command, args, spawnOptions) => spawn4(command, [...args], spawnOptions));
|
|
6362
6369
|
function contextKey(userId, topic) {
|
|
6363
6370
|
return `${userId}\x00${topic}`;
|
|
6364
6371
|
}
|
|
@@ -7209,8 +7216,8 @@ __export(exports_claude_provider, {
|
|
|
7209
7216
|
claudeBuiltInTools: () => claudeBuiltInTools,
|
|
7210
7217
|
buildClaudeDisallowedTools: () => buildClaudeDisallowedTools
|
|
7211
7218
|
});
|
|
7212
|
-
import { spawn as
|
|
7213
|
-
import { existsSync as
|
|
7219
|
+
import { spawn as spawn5 } from "child_process";
|
|
7220
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
|
|
7214
7221
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
7215
7222
|
function claudeBuiltInTools(opts) {
|
|
7216
7223
|
return opts.toolPolicy ? [] : undefined;
|
|
@@ -7263,7 +7270,7 @@ function buildClaudePrompt(opts) {
|
|
|
7263
7270
|
source: {
|
|
7264
7271
|
type: "base64",
|
|
7265
7272
|
media_type: attachment.mimeType,
|
|
7266
|
-
data:
|
|
7273
|
+
data: readFileSync11(attachment.path).toString("base64")
|
|
7267
7274
|
}
|
|
7268
7275
|
});
|
|
7269
7276
|
} catch (err) {
|
|
@@ -7286,7 +7293,7 @@ function buildClaudePrompt(opts) {
|
|
|
7286
7293
|
parent_tool_use_id: null
|
|
7287
7294
|
});
|
|
7288
7295
|
}
|
|
7289
|
-
function
|
|
7296
|
+
function signalProcessTree2(pid, signal) {
|
|
7290
7297
|
try {
|
|
7291
7298
|
process.kill(-pid, signal);
|
|
7292
7299
|
return true;
|
|
@@ -7301,7 +7308,7 @@ function signalProcessTree(pid, signal) {
|
|
|
7301
7308
|
}
|
|
7302
7309
|
}
|
|
7303
7310
|
function spawnClaudeCodeProcessWithTreeKill(options) {
|
|
7304
|
-
const child =
|
|
7311
|
+
const child = spawn5(options.command, options.args, {
|
|
7305
7312
|
cwd: options.cwd,
|
|
7306
7313
|
detached: true,
|
|
7307
7314
|
env: options.env,
|
|
@@ -7321,13 +7328,13 @@ function spawnClaudeCodeProcessWithTreeKill(options) {
|
|
|
7321
7328
|
const kill = (signal) => {
|
|
7322
7329
|
if (!child.pid)
|
|
7323
7330
|
return child.kill(signal);
|
|
7324
|
-
const ok =
|
|
7331
|
+
const ok = signalProcessTree2(child.pid, signal);
|
|
7325
7332
|
if (signal !== "SIGKILL") {
|
|
7326
7333
|
clearKillTimer();
|
|
7327
7334
|
killTimer = setTimeout(() => {
|
|
7328
7335
|
if (!exited && child.pid) {
|
|
7329
7336
|
logger.warn({ pid: child.pid }, "Claude process tree still alive after SIGTERM; SIGKILL");
|
|
7330
|
-
|
|
7337
|
+
signalProcessTree2(child.pid, "SIGKILL");
|
|
7331
7338
|
}
|
|
7332
7339
|
}, CLAUDE_ABORT_SIGKILL_DELAY_MS);
|
|
7333
7340
|
killTimer.unref?.();
|
|
@@ -7391,7 +7398,7 @@ function isAbortError(err) {
|
|
|
7391
7398
|
}
|
|
7392
7399
|
async function* claudeProvider(opts) {
|
|
7393
7400
|
const claudeExecutable = hostedClaudeCodeExecutablePath();
|
|
7394
|
-
if (claudeExecutable && !
|
|
7401
|
+
if (claudeExecutable && !existsSync13(claudeExecutable)) {
|
|
7395
7402
|
yield {
|
|
7396
7403
|
type: "error",
|
|
7397
7404
|
content: `Claude CLI not found at ${claudeExecutable}. Install Claude Code or configure the executable path.`
|
|
@@ -7686,17 +7693,17 @@ var init_claude_provider = __esm(async () => {
|
|
|
7686
7693
|
});
|
|
7687
7694
|
|
|
7688
7695
|
// ../../packages/core/src/version.ts
|
|
7689
|
-
var NEGOTIUM_VERSION = "0.1.
|
|
7696
|
+
var NEGOTIUM_VERSION = "0.1.49";
|
|
7690
7697
|
|
|
7691
7698
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
7692
|
-
import { spawn as
|
|
7699
|
+
import { spawn as spawn6 } from "child_process";
|
|
7693
7700
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
7694
7701
|
import {
|
|
7695
7702
|
chmodSync as chmodSync4,
|
|
7696
7703
|
copyFileSync,
|
|
7697
|
-
existsSync as
|
|
7704
|
+
existsSync as existsSync14,
|
|
7698
7705
|
mkdtempSync,
|
|
7699
|
-
readFileSync as
|
|
7706
|
+
readFileSync as readFileSync12,
|
|
7700
7707
|
renameSync as renameSync7,
|
|
7701
7708
|
rmSync as rmSync2,
|
|
7702
7709
|
unlinkSync as unlinkSync11,
|
|
@@ -7704,16 +7711,16 @@ import {
|
|
|
7704
7711
|
} from "fs";
|
|
7705
7712
|
import { createRequire as createRequire2 } from "module";
|
|
7706
7713
|
import { tmpdir as tmpdir2 } from "os";
|
|
7707
|
-
import { dirname as dirname10, join as
|
|
7714
|
+
import { dirname as dirname10, join as join16 } from "path";
|
|
7708
7715
|
function readPackageVersion(packageJsonPath) {
|
|
7709
|
-
const parsed = JSON.parse(
|
|
7716
|
+
const parsed = JSON.parse(readFileSync12(packageJsonPath, "utf8"));
|
|
7710
7717
|
if (typeof parsed.version !== "string" || !parsed.version.trim()) {
|
|
7711
7718
|
throw new Error(`Codex package has no valid version: ${packageJsonPath}`);
|
|
7712
7719
|
}
|
|
7713
7720
|
return parsed.version;
|
|
7714
7721
|
}
|
|
7715
7722
|
function codexCliScriptPath() {
|
|
7716
|
-
return
|
|
7723
|
+
return join16(dirname10(bundledCodexPackagePath), "bin", "codex.js");
|
|
7717
7724
|
}
|
|
7718
7725
|
function parseCodexModelCache(contents, sourcePath) {
|
|
7719
7726
|
let parsed;
|
|
@@ -7728,7 +7735,7 @@ function parseCodexModelCache(contents, sourcePath) {
|
|
|
7728
7735
|
return parsed;
|
|
7729
7736
|
}
|
|
7730
7737
|
function readCodexModelCache(cachePath) {
|
|
7731
|
-
const contents =
|
|
7738
|
+
const contents = readFileSync12(cachePath, "utf8");
|
|
7732
7739
|
return { contents, parsed: parseCodexModelCache(contents, cachePath) };
|
|
7733
7740
|
}
|
|
7734
7741
|
function readCompatibleCodexModelCache(cachePath) {
|
|
@@ -7740,7 +7747,7 @@ function readCompatibleCodexModelCache(cachePath) {
|
|
|
7740
7747
|
return cache;
|
|
7741
7748
|
}
|
|
7742
7749
|
function writePrivateFileAtomic(path, contents) {
|
|
7743
|
-
if (
|
|
7750
|
+
if (existsSync14(path) && readFileSync12(path, "utf8") === contents)
|
|
7744
7751
|
return;
|
|
7745
7752
|
const tempPath = `${path}.${process.pid}.${randomUUID8()}.tmp`;
|
|
7746
7753
|
try {
|
|
@@ -7754,10 +7761,10 @@ function writePrivateFileAtomic(path, contents) {
|
|
|
7754
7761
|
}
|
|
7755
7762
|
}
|
|
7756
7763
|
function bundledCodexModelCachePath(authFilePath) {
|
|
7757
|
-
return
|
|
7764
|
+
return join16(dirname10(authFilePath), NEGOTIUM_MODEL_CACHE);
|
|
7758
7765
|
}
|
|
7759
7766
|
async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
7760
|
-
const child =
|
|
7767
|
+
const child = spawn6(process.execPath, [codexCliScriptPath(), "app-server", "--stdio"], {
|
|
7761
7768
|
env: { ...process.env, CODEX_HOME: codexHome },
|
|
7762
7769
|
stdio: ["pipe", "pipe", "pipe"]
|
|
7763
7770
|
});
|
|
@@ -7777,7 +7784,7 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
7777
7784
|
} catch {}
|
|
7778
7785
|
if (error)
|
|
7779
7786
|
reject(error);
|
|
7780
|
-
else if (!
|
|
7787
|
+
else if (!existsSync14(cachePath))
|
|
7781
7788
|
reject(new Error("Codex did not create its model cache"));
|
|
7782
7789
|
else
|
|
7783
7790
|
resolve11();
|
|
@@ -7840,15 +7847,15 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
7840
7847
|
}
|
|
7841
7848
|
async function bootstrapIsolatedCodexModelCache(authFilePath, bootstrap) {
|
|
7842
7849
|
const sourceHome = dirname10(authFilePath);
|
|
7843
|
-
const isolatedHome = mkdtempSync(
|
|
7844
|
-
const isolatedCachePath =
|
|
7850
|
+
const isolatedHome = mkdtempSync(join16(tmpdir2(), "negotium-codex-models-"));
|
|
7851
|
+
const isolatedCachePath = join16(isolatedHome, "models_cache.json");
|
|
7845
7852
|
try {
|
|
7846
|
-
const isolatedAuthPath =
|
|
7853
|
+
const isolatedAuthPath = join16(isolatedHome, "auth.json");
|
|
7847
7854
|
copyFileSync(authFilePath, isolatedAuthPath);
|
|
7848
7855
|
chmodSync4(isolatedAuthPath, 384);
|
|
7849
|
-
const sourceConfigPath =
|
|
7850
|
-
if (
|
|
7851
|
-
const isolatedConfigPath =
|
|
7856
|
+
const sourceConfigPath = join16(sourceHome, "config.toml");
|
|
7857
|
+
if (existsSync14(sourceConfigPath)) {
|
|
7858
|
+
const isolatedConfigPath = join16(isolatedHome, "config.toml");
|
|
7852
7859
|
copyFileSync(sourceConfigPath, isolatedConfigPath);
|
|
7853
7860
|
chmodSync4(isolatedConfigPath, 384);
|
|
7854
7861
|
}
|
|
@@ -7862,22 +7869,22 @@ async function ensureCodexModelCache(authFilePath, bootstrap = bootstrapCodexMod
|
|
|
7862
7869
|
const codexHome = dirname10(authFilePath);
|
|
7863
7870
|
const configuredCachePath = process.env.NEGOTIUM_CODEX_MODELS_CACHE_FILE;
|
|
7864
7871
|
if (configuredCachePath) {
|
|
7865
|
-
if (!
|
|
7872
|
+
if (!existsSync14(configuredCachePath)) {
|
|
7866
7873
|
throw new Error(`Configured Codex model cache does not exist: ${configuredCachePath}`);
|
|
7867
7874
|
}
|
|
7868
7875
|
readCompatibleCodexModelCache(configuredCachePath);
|
|
7869
7876
|
return configuredCachePath;
|
|
7870
7877
|
}
|
|
7871
7878
|
const bundledCachePath = bundledCodexModelCachePath(authFilePath);
|
|
7872
|
-
const sharedCachePath =
|
|
7873
|
-
if (
|
|
7879
|
+
const sharedCachePath = join16(codexHome, "models_cache.json");
|
|
7880
|
+
if (existsSync14(sharedCachePath)) {
|
|
7874
7881
|
try {
|
|
7875
7882
|
const shared = readCompatibleCodexModelCache(sharedCachePath);
|
|
7876
7883
|
writePrivateFileAtomic(bundledCachePath, shared.contents);
|
|
7877
7884
|
return bundledCachePath;
|
|
7878
7885
|
} catch {}
|
|
7879
7886
|
}
|
|
7880
|
-
if (
|
|
7887
|
+
if (existsSync14(bundledCachePath)) {
|
|
7881
7888
|
try {
|
|
7882
7889
|
readCompatibleCodexModelCache(bundledCachePath);
|
|
7883
7890
|
return bundledCachePath;
|
|
@@ -7889,7 +7896,7 @@ async function ensureCodexModelCache(authFilePath, bootstrap = bootstrapCodexMod
|
|
|
7889
7896
|
}
|
|
7890
7897
|
function writeCodexCatalogWithNativeMultiAgentDisabled(authFilePath, sourcePath) {
|
|
7891
7898
|
const codexHome = dirname10(authFilePath);
|
|
7892
|
-
const outputPath =
|
|
7899
|
+
const outputPath = join16(codexHome, NEGOTIUM_MODEL_CATALOG);
|
|
7893
7900
|
const parsed = readCodexModelCache(sourcePath).parsed;
|
|
7894
7901
|
const models = parsed.models.map((model, index) => {
|
|
7895
7902
|
if (!model || typeof model !== "object" || Array.isArray(model)) {
|
|
@@ -8136,7 +8143,7 @@ var init_codex_tree_kill = __esm(() => {
|
|
|
8136
8143
|
});
|
|
8137
8144
|
|
|
8138
8145
|
// ../../packages/core/src/agents/tool-format.ts
|
|
8139
|
-
import { readFileSync as
|
|
8146
|
+
import { readFileSync as readFileSync13, statSync as statSync5 } from "fs";
|
|
8140
8147
|
import { isAbsolute as isAbsolute2, resolve as resolve11 } from "path";
|
|
8141
8148
|
import { diffLines as computeLineDiff } from "diff";
|
|
8142
8149
|
function summarizeDisplayText(value2) {
|
|
@@ -8465,7 +8472,7 @@ function sourceStartLine(input, before, after, cwd) {
|
|
|
8465
8472
|
try {
|
|
8466
8473
|
if (statSync5(path).size > TOOL_DIFF_SOURCE_MAX_BYTES)
|
|
8467
8474
|
return 1;
|
|
8468
|
-
const source =
|
|
8475
|
+
const source = readFileSync13(path, "utf8").replace(/\r\n?/g, `
|
|
8469
8476
|
`);
|
|
8470
8477
|
for (const candidate of [before, after].filter(Boolean)) {
|
|
8471
8478
|
const index = source.indexOf(candidate);
|
|
@@ -8658,8 +8665,8 @@ __export(exports_codex_provider, {
|
|
|
8658
8665
|
codexProvider: () => codexProvider
|
|
8659
8666
|
});
|
|
8660
8667
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
8661
|
-
import { existsSync as
|
|
8662
|
-
import { dirname as dirname11, isAbsolute as isAbsolute3, join as
|
|
8668
|
+
import { existsSync as existsSync15, readFileSync as readFileSync14, realpathSync as realpathSync4, statSync as statSync6 } from "fs";
|
|
8669
|
+
import { dirname as dirname11, isAbsolute as isAbsolute3, join as join17, relative, resolve as resolve12 } from "path";
|
|
8663
8670
|
import { Codex } from "@openai/codex-sdk";
|
|
8664
8671
|
function mapEffort(effort) {
|
|
8665
8672
|
if (!effort)
|
|
@@ -8673,12 +8680,12 @@ function codexMcpServerName(name) {
|
|
|
8673
8680
|
return CODEX_MCP_SERVER_NAME_OVERRIDES[name] ?? name;
|
|
8674
8681
|
}
|
|
8675
8682
|
function globalCodexMcpServerNames(authFilePath) {
|
|
8676
|
-
const configPath =
|
|
8677
|
-
if (!
|
|
8683
|
+
const configPath = join17(dirname11(authFilePath), "config.toml");
|
|
8684
|
+
if (!existsSync15(configPath))
|
|
8678
8685
|
return [];
|
|
8679
8686
|
try {
|
|
8680
8687
|
const names = new Set;
|
|
8681
|
-
for (const line of
|
|
8688
|
+
for (const line of readFileSync14(configPath, "utf8").split(`
|
|
8682
8689
|
`)) {
|
|
8683
8690
|
const match = line.match(/^\s*\[\s*mcp_servers\.((?:"(?:\\.|[^"])*")|(?:'[^']*')|[^.\]\s]+)(?:[.\]])/);
|
|
8684
8691
|
const raw = match?.[1];
|
|
@@ -8769,19 +8776,19 @@ function summarizeMcpToolCallResult(item) {
|
|
|
8769
8776
|
}
|
|
8770
8777
|
function canonicalPath(path) {
|
|
8771
8778
|
try {
|
|
8772
|
-
return
|
|
8779
|
+
return realpathSync4(resolve12(path));
|
|
8773
8780
|
} catch {
|
|
8774
8781
|
return resolve12(path);
|
|
8775
8782
|
}
|
|
8776
8783
|
}
|
|
8777
8784
|
function textFile(path, maxBytes = CODEX_DIFF_FILE_LIMIT) {
|
|
8778
|
-
if (!
|
|
8785
|
+
if (!existsSync15(path))
|
|
8779
8786
|
return null;
|
|
8780
8787
|
try {
|
|
8781
8788
|
const byteLimit = Math.min(CODEX_DIFF_FILE_LIMIT, Math.max(0, maxBytes));
|
|
8782
8789
|
if (statSync6(path).size > byteLimit)
|
|
8783
8790
|
return;
|
|
8784
|
-
const content =
|
|
8791
|
+
const content = readFileSync14(path);
|
|
8785
8792
|
if (content.byteLength > byteLimit || content.includes(0))
|
|
8786
8793
|
return;
|
|
8787
8794
|
return content.toString("utf8");
|
|
@@ -8987,7 +8994,7 @@ async function* codexProvider(opts) {
|
|
|
8987
8994
|
const filePreviews = new CodexFilePreviewTracker(opts.cwd);
|
|
8988
8995
|
const consumedPatchCallIds = new Set(opts.sessionId ? readCodexPatchCallIds(opts.sessionId) : []);
|
|
8989
8996
|
const codexAuthPath = hostedCodexAuthFilePath();
|
|
8990
|
-
if (!
|
|
8997
|
+
if (!existsSync15(codexAuthPath)) {
|
|
8991
8998
|
yield {
|
|
8992
8999
|
type: "error",
|
|
8993
9000
|
content: `Codex auth file not found at ${codexAuthPath}. Run \`codex login\` to authenticate.`
|
|
@@ -9026,7 +9033,7 @@ async function* codexProvider(opts) {
|
|
|
9026
9033
|
model: opts.model ?? "(sdk default)",
|
|
9027
9034
|
effort: opts.effort ?? "(off)",
|
|
9028
9035
|
cwd: opts.cwd,
|
|
9029
|
-
cwdExists:
|
|
9036
|
+
cwdExists: existsSync15(opts.cwd),
|
|
9030
9037
|
resume: Boolean(opts.sessionId),
|
|
9031
9038
|
mcpServerCount: Object.keys(codexMcpServers).length
|
|
9032
9039
|
}, "codexProvider: starting turn");
|
|
@@ -9467,9 +9474,9 @@ var init_maestro_provider = __esm(async () => {
|
|
|
9467
9474
|
});
|
|
9468
9475
|
|
|
9469
9476
|
// ../../packages/core/src/agents/index.ts
|
|
9470
|
-
import { existsSync as
|
|
9477
|
+
import { existsSync as existsSync16 } from "fs";
|
|
9471
9478
|
import { homedir as homedir8 } from "os";
|
|
9472
|
-
import { join as
|
|
9479
|
+
import { join as join18 } from "path";
|
|
9473
9480
|
async function* dispatchAgent(opts) {
|
|
9474
9481
|
switch (opts.agent) {
|
|
9475
9482
|
case "claude": {
|
|
@@ -9503,11 +9510,11 @@ async function resolveSessionFileMissing(agent, sessionId, cwd) {
|
|
|
9503
9510
|
switch (agent) {
|
|
9504
9511
|
case "claude": {
|
|
9505
9512
|
const encodedCwd = encodeClaudeCwd(cwd);
|
|
9506
|
-
const path =
|
|
9507
|
-
return !
|
|
9513
|
+
const path = join18(homedir8(), ".claude", "projects", encodedCwd, `${sessionId}.jsonl`);
|
|
9514
|
+
return !existsSync16(path);
|
|
9508
9515
|
}
|
|
9509
9516
|
case "codex": {
|
|
9510
|
-
const sessionsDir =
|
|
9517
|
+
const sessionsDir = join18(process.env.CODEX_HOME || join18(homedir8(), ".codex"), "sessions");
|
|
9511
9518
|
const glob = new Bun.Glob(`**/rollout-*-${sessionId}.jsonl`);
|
|
9512
9519
|
for await (const _rel of glob.scan({ cwd: sessionsDir, onlyFiles: true })) {
|
|
9513
9520
|
return false;
|
|
@@ -9516,7 +9523,7 @@ async function resolveSessionFileMissing(agent, sessionId, cwd) {
|
|
|
9516
9523
|
}
|
|
9517
9524
|
case "maestro": {
|
|
9518
9525
|
const { hasActiveMaestroSession, maestroSessionPath: maestroSessionPath2 } = await import("maestro-agent-sdk");
|
|
9519
|
-
return !
|
|
9526
|
+
return !existsSync16(maestroSessionPath2(sessionId)) && !hasActiveMaestroSession(sessionId);
|
|
9520
9527
|
}
|
|
9521
9528
|
default: {
|
|
9522
9529
|
const _exhaustive = agent;
|
|
@@ -9582,10 +9589,10 @@ var init_agents = __esm(async () => {
|
|
|
9582
9589
|
});
|
|
9583
9590
|
|
|
9584
9591
|
// ../../packages/core/src/prompts/builders.ts
|
|
9585
|
-
import { readFileSync as
|
|
9592
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
9586
9593
|
import { resolve as resolve14 } from "path";
|
|
9587
9594
|
function loadPrompt(filename, dir = SESSIONS_DIR) {
|
|
9588
|
-
const raw =
|
|
9595
|
+
const raw = readFileSync15(resolve14(dir, filename), "utf-8");
|
|
9589
9596
|
return raw.replace(/\{\{RESOURCES_DIR\}\}/g, RESOURCES_DIR);
|
|
9590
9597
|
}
|
|
9591
9598
|
function replaceVars(template, vars) {
|
|
@@ -9634,7 +9641,7 @@ function visualDesignGuide() {
|
|
|
9634
9641
|
return _visualDesignGuide;
|
|
9635
9642
|
}
|
|
9636
9643
|
function loadAgentPrompt(filename) {
|
|
9637
|
-
const raw =
|
|
9644
|
+
const raw = readFileSync15(resolve14(AGENTS_PROMPTS_DIR, filename), "utf-8");
|
|
9638
9645
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
9639
9646
|
if (!match)
|
|
9640
9647
|
throw new Error(`Agent prompt ${filename} is missing frontmatter`);
|
|
@@ -10023,9 +10030,9 @@ var init_api_topic_brief = __esm(async () => {
|
|
|
10023
10030
|
});
|
|
10024
10031
|
|
|
10025
10032
|
// ../../packages/core/src/storage/wiki.ts
|
|
10026
|
-
import { basename as basename3, dirname as dirname12, join as
|
|
10033
|
+
import { basename as basename3, dirname as dirname12, join as join19 } from "path";
|
|
10027
10034
|
function getSharedWikiDir(workspaceDir = resolveStorageWorkspaceDir()) {
|
|
10028
|
-
return workspaceDir === resolveStorageWorkspaceDir() ? resolveStorageSharedWikiDir() :
|
|
10035
|
+
return workspaceDir === resolveStorageWorkspaceDir() ? resolveStorageSharedWikiDir() : join19(workspaceDir, "wiki");
|
|
10029
10036
|
}
|
|
10030
10037
|
var init_wiki = __esm(async () => {
|
|
10031
10038
|
await init_storage_host();
|
|
@@ -10033,8 +10040,8 @@ var init_wiki = __esm(async () => {
|
|
|
10033
10040
|
|
|
10034
10041
|
// ../../packages/core/src/agents/archiver.ts
|
|
10035
10042
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
10036
|
-
import { existsSync as
|
|
10037
|
-
import { join as
|
|
10043
|
+
import { existsSync as existsSync17, readdirSync as readdirSync5, readFileSync as readFileSync16, statSync as statSync7 } from "fs";
|
|
10044
|
+
import { join as join20 } from "path";
|
|
10038
10045
|
function resolveMemoryLanguage() {
|
|
10039
10046
|
const override = process.env.NEGOTIUM_MEMORY_LANG?.trim();
|
|
10040
10047
|
return override && override.length > 0 ? override : resolveOutputLanguage();
|
|
@@ -10285,10 +10292,10 @@ function distillOneLine(summaryMd) {
|
|
|
10285
10292
|
return "";
|
|
10286
10293
|
}
|
|
10287
10294
|
function findSummaryFile(storage, topicTitle, date, sinceMs, topicId) {
|
|
10288
|
-
const dir =
|
|
10295
|
+
const dir = join20(storage.getWikiDir(), "summaries");
|
|
10289
10296
|
if (!storage.fileExists(dir))
|
|
10290
10297
|
return null;
|
|
10291
|
-
const predicted =
|
|
10298
|
+
const predicted = join20(dir, wikiSummaryFilename(date, topicTitle, topicId));
|
|
10292
10299
|
if (storage.fileExists(predicted) && storage.fileModifiedAt(predicted) >= sinceMs)
|
|
10293
10300
|
return predicted;
|
|
10294
10301
|
let best = null;
|
|
@@ -10296,7 +10303,7 @@ function findSummaryFile(storage, topicTitle, date, sinceMs, topicId) {
|
|
|
10296
10303
|
if (!f.startsWith(`${date}-`) || !isTopicSummaryFile(f, topicId ?? "", topicTitle)) {
|
|
10297
10304
|
continue;
|
|
10298
10305
|
}
|
|
10299
|
-
const p =
|
|
10306
|
+
const p = join20(dir, f);
|
|
10300
10307
|
try {
|
|
10301
10308
|
const m = storage.fileModifiedAt(p);
|
|
10302
10309
|
if (m >= sinceMs && (!best || m > best.mtime))
|
|
@@ -10378,9 +10385,9 @@ var init_archiver = __esm(async () => {
|
|
|
10378
10385
|
defaultArchiverRuntime = createArchiverRuntime({
|
|
10379
10386
|
storage: {
|
|
10380
10387
|
getWikiDir: getSharedWikiDir,
|
|
10381
|
-
fileExists:
|
|
10382
|
-
listDirectory:
|
|
10383
|
-
readTextFile: (path) =>
|
|
10388
|
+
fileExists: existsSync17,
|
|
10389
|
+
listDirectory: readdirSync5,
|
|
10390
|
+
readTextFile: (path) => readFileSync16(path, "utf-8"),
|
|
10384
10391
|
fileSize: (path) => statSync7(path).size,
|
|
10385
10392
|
fileModifiedAt: (path) => statSync7(path).mtimeMs,
|
|
10386
10393
|
getGeneralTopicId: (userId) => ensurePersonalGeneral(userId).id,
|
|
@@ -10494,13 +10501,13 @@ function formatTopicArchiveTranscriptRecord(row, topicTitle, index) {
|
|
|
10494
10501
|
|
|
10495
10502
|
// ../../packages/core/src/storage/topic-archive.ts
|
|
10496
10503
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
10497
|
-
import { join as
|
|
10504
|
+
import { join as join21 } from "path";
|
|
10498
10505
|
function archiveTopicMessages(topicId, topicTitle, options = {}) {
|
|
10499
10506
|
const rows = options.afterRowid !== undefined ? getMessagesForTopicAfterRowid(topicId, options.afterRowid) : getAllMessagesForTopic(topicId);
|
|
10500
10507
|
if (rows.length === 0)
|
|
10501
10508
|
return null;
|
|
10502
10509
|
const safeTopic = sanitizeTopicName(topicTitle, true);
|
|
10503
|
-
const archiveDir =
|
|
10510
|
+
const archiveDir = join21(getSharedWikiDir(), "archive");
|
|
10504
10511
|
mkdirSync12(archiveDir, { recursive: true });
|
|
10505
10512
|
const date = new Date().toISOString().slice(0, 10);
|
|
10506
10513
|
const reasonSuffix = options.reason && options.reason !== "delete" ? `_${options.reason}` : "";
|
|
@@ -10513,7 +10520,7 @@ function archiveTopicMessages(topicId, topicTitle, options = {}) {
|
|
|
10513
10520
|
let path;
|
|
10514
10521
|
while (true) {
|
|
10515
10522
|
filename = `${safeTopic}_${date}${reasonSuffix}${counter === 1 ? "" : `_${counter}`}.jsonl`;
|
|
10516
|
-
path =
|
|
10523
|
+
path = join21(archiveDir, filename);
|
|
10517
10524
|
try {
|
|
10518
10525
|
writeFileSync10(path, body, { flag: "wx" });
|
|
10519
10526
|
break;
|
|
@@ -10558,7 +10565,7 @@ function archiveConversationEvents(topicId, topicTitle, userId, options = {}) {
|
|
|
10558
10565
|
const entries = readRawConversation(userId, topicTitle);
|
|
10559
10566
|
if (entries.length === 0)
|
|
10560
10567
|
return null;
|
|
10561
|
-
const archiveDir =
|
|
10568
|
+
const archiveDir = join21(getSharedWikiDir(), "archive");
|
|
10562
10569
|
mkdirSync12(archiveDir, { recursive: true });
|
|
10563
10570
|
const safeTopic = sanitizeTopicName(topicTitle, true);
|
|
10564
10571
|
const date = new Date().toISOString().slice(0, 10);
|
|
@@ -10586,7 +10593,7 @@ function archiveConversationEvents(topicId, topicTitle, userId, options = {}) {
|
|
|
10586
10593
|
let counter = 1;
|
|
10587
10594
|
while (true) {
|
|
10588
10595
|
const suffix = counter === 1 ? "" : `_${counter}`;
|
|
10589
|
-
const path =
|
|
10596
|
+
const path = join21(archiveDir, `${safeTopic}_${date}${reasonSuffix}_events${suffix}.jsonl`);
|
|
10590
10597
|
try {
|
|
10591
10598
|
writeFileSync10(path, body, { flag: "wx" });
|
|
10592
10599
|
logger.info({ topicId, topicTitle, archive: path, eventCount: entries.length }, "archiveConversationEvents: archived raw conversation events");
|
|
@@ -11143,7 +11150,7 @@ var init_usage_alert = __esm(() => {
|
|
|
11143
11150
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
11144
11151
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync4, writeFileSync as writeFileSync12 } from "fs";
|
|
11145
11152
|
import { tmpdir as tmpdir3 } from "os";
|
|
11146
|
-
import { join as
|
|
11153
|
+
import { join as join22 } from "path";
|
|
11147
11154
|
function previousCompactedSummary(entries) {
|
|
11148
11155
|
for (let index = entries.length - 2;index >= 0; index -= 1) {
|
|
11149
11156
|
const request = entries[index]?.event;
|
|
@@ -11273,7 +11280,7 @@ function formatCompactElapsed(startedAt) {
|
|
|
11273
11280
|
async function summarizeTopicContext(request) {
|
|
11274
11281
|
const startedAt = Date.now();
|
|
11275
11282
|
const sessionIds = [];
|
|
11276
|
-
const compactCwd = mkdtempSync2(
|
|
11283
|
+
const compactCwd = mkdtempSync2(join22(tmpdir3(), "negotium-compact-"));
|
|
11277
11284
|
const abortController = new AbortController;
|
|
11278
11285
|
const relayAbort = () => abortController.abort(request.signal?.reason);
|
|
11279
11286
|
if (request.signal?.aborted)
|
|
@@ -11300,7 +11307,7 @@ async function summarizeTopicContext(request) {
|
|
|
11300
11307
|
let error = "";
|
|
11301
11308
|
let toolViolation = false;
|
|
11302
11309
|
let compactionLogCalls = 0;
|
|
11303
|
-
const compactionLogPath =
|
|
11310
|
+
const compactionLogPath = join22(compactCwd, "conversation.log");
|
|
11304
11311
|
try {
|
|
11305
11312
|
const compactionMcp = useCompactionLog ? {
|
|
11306
11313
|
compact_log: {
|
|
@@ -11896,14 +11903,14 @@ var init_derive = __esm(async () => {
|
|
|
11896
11903
|
});
|
|
11897
11904
|
|
|
11898
11905
|
// ../../packages/core/src/query/session-inbox-path.ts
|
|
11899
|
-
import { join as
|
|
11906
|
+
import { join as join23 } from "path";
|
|
11900
11907
|
function sessionInboxPath(userId, topicId) {
|
|
11901
11908
|
const key = Buffer.from(topicId, "utf8").toString("base64url");
|
|
11902
|
-
return
|
|
11909
|
+
return join23(SESSION_INBOX_DIR, userId, `${TOPIC_ID_FILE_PREFIX}${key}${JSONL_SUFFIX}`);
|
|
11903
11910
|
}
|
|
11904
11911
|
function scheduledSessionInboxPath(userId, topicId) {
|
|
11905
11912
|
const key = Buffer.from(topicId, "utf8").toString("base64url");
|
|
11906
|
-
return
|
|
11913
|
+
return join23(SESSION_INBOX_DIR, userId, `${TOPIC_ID_FILE_PREFIX}${key}${SCHEDULE_SUFFIX}`);
|
|
11907
11914
|
}
|
|
11908
11915
|
var TOPIC_ID_FILE_PREFIX = "topic-id-", JSONL_SUFFIX = ".jsonl", SCHEDULE_SUFFIX = ".schedule";
|
|
11909
11916
|
var init_session_inbox_path = __esm(() => {
|
|
@@ -11912,13 +11919,13 @@ var init_session_inbox_path = __esm(() => {
|
|
|
11912
11919
|
|
|
11913
11920
|
// ../../packages/core/src/query/session-inbox-cleanup.ts
|
|
11914
11921
|
import { unlinkSync as unlinkSync14 } from "fs";
|
|
11915
|
-
import { basename as basename4, join as
|
|
11922
|
+
import { basename as basename4, join as join24 } from "path";
|
|
11916
11923
|
function cleanupSessionInboxFiles(userId, topicId, legacyTopicTitle) {
|
|
11917
11924
|
const live = sessionInboxPath(userId, topicId);
|
|
11918
11925
|
const scheduled = scheduledSessionInboxPath(userId, topicId);
|
|
11919
11926
|
const candidates = new Set([live, `${live}.processing`, scheduled, `${scheduled}.processing`]);
|
|
11920
11927
|
if (legacyTopicTitle && legacyTopicTitle !== "." && legacyTopicTitle !== ".." && basename4(legacyTopicTitle) === legacyTopicTitle) {
|
|
11921
|
-
const legacyBase =
|
|
11928
|
+
const legacyBase = join24(SESSION_INBOX_DIR, userId, legacyTopicTitle);
|
|
11922
11929
|
for (const suffix of [".jsonl", ".jsonl.processing", ".schedule", ".schedule.processing"]) {
|
|
11923
11930
|
candidates.add(`${legacyBase}${suffix}`);
|
|
11924
11931
|
}
|
|
@@ -11944,16 +11951,16 @@ var init_session_inbox_cleanup = __esm(() => {
|
|
|
11944
11951
|
|
|
11945
11952
|
// ../../packages/core/src/query/state.ts
|
|
11946
11953
|
import { mkdirSync as mkdirSync15, renameSync as renameSync9, unlinkSync as unlinkSync15, writeFileSync as writeFileSync13 } from "fs";
|
|
11947
|
-
import { basename as basename5, join as
|
|
11954
|
+
import { basename as basename5, join as join25 } from "path";
|
|
11948
11955
|
function createQueryStateStore(options) {
|
|
11949
11956
|
const sanitize = options.sanitizeTopicId ?? sanitizeId;
|
|
11950
|
-
const queryStateDirPath = (userId) =>
|
|
11951
|
-
const queryStateFile = (userId, topicId) =>
|
|
11957
|
+
const queryStateDirPath = (userId) => join25(options.usersLogDir, String(userId), "active-queries");
|
|
11958
|
+
const queryStateFile = (userId, topicId) => join25(queryStateDirPath(userId), `${sanitize(topicId)}.json`);
|
|
11952
11959
|
const legacyQueryStateFile = (userId, topicName) => {
|
|
11953
11960
|
if (!topicName || topicName === "." || topicName === ".." || basename5(topicName) !== topicName) {
|
|
11954
11961
|
return null;
|
|
11955
11962
|
}
|
|
11956
|
-
return
|
|
11963
|
+
return join25(queryStateDirPath(userId), `${topicName}.json`);
|
|
11957
11964
|
};
|
|
11958
11965
|
return {
|
|
11959
11966
|
write(userId, topicId, topicName, task) {
|
|
@@ -12107,35 +12114,35 @@ import {
|
|
|
12107
12114
|
closeSync as closeSync3,
|
|
12108
12115
|
mkdirSync as mkdirSync16,
|
|
12109
12116
|
openSync as openSync3,
|
|
12110
|
-
readdirSync as
|
|
12111
|
-
readFileSync as
|
|
12117
|
+
readdirSync as readdirSync6,
|
|
12118
|
+
readFileSync as readFileSync17,
|
|
12112
12119
|
statSync as statSync8,
|
|
12113
12120
|
unlinkSync as unlinkSync16,
|
|
12114
12121
|
writeFileSync as writeFileSync14
|
|
12115
12122
|
} from "fs";
|
|
12116
|
-
import { dirname as dirname14, join as
|
|
12123
|
+
import { dirname as dirname14, join as join26 } from "path";
|
|
12117
12124
|
function pendingAskDir(userId) {
|
|
12118
12125
|
const rawUserId = String(userId);
|
|
12119
12126
|
const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash4("sha256").update(rawUserId).digest("hex")}`;
|
|
12120
|
-
return
|
|
12127
|
+
return join26(resolveStorageSessionAsksDir(), safeUserId);
|
|
12121
12128
|
}
|
|
12122
12129
|
function encodeAskKey(key) {
|
|
12123
12130
|
return JSON.stringify([key.from, key.to]);
|
|
12124
12131
|
}
|
|
12125
12132
|
function pendingAskPath(key) {
|
|
12126
12133
|
const digest = createHash4("sha256").update(encodeAskKey(key)).digest("hex");
|
|
12127
|
-
return
|
|
12134
|
+
return join26(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${digest}.pending`);
|
|
12128
12135
|
}
|
|
12129
12136
|
function v2PendingAskPath(key) {
|
|
12130
12137
|
const encoded = Buffer.from(encodeAskKey(key), "utf8").toString("base64url");
|
|
12131
|
-
return
|
|
12138
|
+
return join26(pendingAskDir(key.userId), `${V2_ASK_FILENAME_PREFIX}${encoded}.pending`);
|
|
12132
12139
|
}
|
|
12133
12140
|
function legacyPendingAskPath(key) {
|
|
12134
12141
|
if (key.from.includes("/") || key.from.includes("\\") || key.to.includes("/") || key.to.includes("\\") || key.from.includes("\x00") || key.to.includes("\x00")) {
|
|
12135
12142
|
return null;
|
|
12136
12143
|
}
|
|
12137
12144
|
const dir = pendingAskDir(key.userId);
|
|
12138
|
-
const candidate =
|
|
12145
|
+
const candidate = join26(dir, `${key.from}___${key.to}.pending`);
|
|
12139
12146
|
return dirname14(candidate) === dir ? candidate : null;
|
|
12140
12147
|
}
|
|
12141
12148
|
function parsePendingAskFilename(fileName) {
|
|
@@ -12157,7 +12164,7 @@ function parsePendingAskFilename(fileName) {
|
|
|
12157
12164
|
}
|
|
12158
12165
|
function readPendingAskFile(path, fallback) {
|
|
12159
12166
|
try {
|
|
12160
|
-
const raw =
|
|
12167
|
+
const raw = readFileSync17(path, "utf8").trim();
|
|
12161
12168
|
if (!raw)
|
|
12162
12169
|
return null;
|
|
12163
12170
|
if (!raw.startsWith("{")) {
|
|
@@ -12366,7 +12373,7 @@ function listPendingAsksForCaller(args) {
|
|
|
12366
12373
|
const dir = pendingAskDir(args.userId);
|
|
12367
12374
|
let files;
|
|
12368
12375
|
try {
|
|
12369
|
-
files =
|
|
12376
|
+
files = readdirSync6(dir);
|
|
12370
12377
|
} catch {
|
|
12371
12378
|
return [];
|
|
12372
12379
|
}
|
|
@@ -12376,7 +12383,7 @@ function listPendingAsksForCaller(args) {
|
|
|
12376
12383
|
const parsed = isV3 ? { from: args.from, to: "" } : parsePendingAskFilename(fileName);
|
|
12377
12384
|
if (!parsed)
|
|
12378
12385
|
continue;
|
|
12379
|
-
const path =
|
|
12386
|
+
const path = join26(dir, fileName);
|
|
12380
12387
|
const record = readPendingAskFile(path, {
|
|
12381
12388
|
userId: args.userId,
|
|
12382
12389
|
from: parsed.from,
|
|
@@ -12412,13 +12419,13 @@ function deletePendingAsksForTopic(args) {
|
|
|
12412
12419
|
const dir = pendingAskDir(args.userId);
|
|
12413
12420
|
let files;
|
|
12414
12421
|
try {
|
|
12415
|
-
files =
|
|
12422
|
+
files = readdirSync6(dir);
|
|
12416
12423
|
} catch {
|
|
12417
12424
|
return 0;
|
|
12418
12425
|
}
|
|
12419
12426
|
let deleted = 0;
|
|
12420
12427
|
for (const fileName of files) {
|
|
12421
|
-
const path =
|
|
12428
|
+
const path = join26(dir, fileName);
|
|
12422
12429
|
const parsed = parsePendingAskFilename(fileName);
|
|
12423
12430
|
const record = readPendingAskFile(path, {
|
|
12424
12431
|
userId: args.userId,
|
|
@@ -13087,7 +13094,7 @@ var init_lifecycle = __esm(async () => {
|
|
|
13087
13094
|
// ../../packages/core/src/runtime/attachments.ts
|
|
13088
13095
|
import { randomUUID as randomUUID13 } from "crypto";
|
|
13089
13096
|
import { copyFileSync as copyFileSync2, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
13090
|
-
import { basename as basename6, join as
|
|
13097
|
+
import { basename as basename6, join as join27 } from "path";
|
|
13091
13098
|
function workspaceCwdFor(topicId) {
|
|
13092
13099
|
return resolveTopicWorkspaceDir(topicId);
|
|
13093
13100
|
}
|
|
@@ -13100,7 +13107,7 @@ function materializePromptAttachments(topicId, queryId, attachmentIds) {
|
|
|
13100
13107
|
if (!attachmentIds?.length)
|
|
13101
13108
|
return [];
|
|
13102
13109
|
const out = [];
|
|
13103
|
-
const destDir =
|
|
13110
|
+
const destDir = join27(workspaceCwdFor(topicId), "attachments", queryId);
|
|
13104
13111
|
for (const rawId of attachmentIds) {
|
|
13105
13112
|
if (typeof rawId !== "string")
|
|
13106
13113
|
continue;
|
|
@@ -13117,7 +13124,7 @@ function materializePromptAttachments(topicId, queryId, attachmentIds) {
|
|
|
13117
13124
|
mkdirSync17(destDir, { recursive: true });
|
|
13118
13125
|
const index = String(out.length + 1).padStart(2, "0");
|
|
13119
13126
|
const safeName = safeAttachmentFilename(attachment.filename, fileId);
|
|
13120
|
-
const destPath =
|
|
13127
|
+
const destPath = join27(destDir, `${index}-${fileId.slice(0, 8)}-${safeName}`);
|
|
13121
13128
|
copyFileSync2(sourcePath, destPath);
|
|
13122
13129
|
out.push({
|
|
13123
13130
|
id: attachment.id,
|
|
@@ -13147,10 +13154,10 @@ function promptWithAttachments(prompt, attachments) {
|
|
|
13147
13154
|
return composeAttachmentPrompt(prompt, attachments.map(({ filename, path }) => attachmentPromptLine(filename, path)));
|
|
13148
13155
|
}
|
|
13149
13156
|
function ingestAttachment(args) {
|
|
13150
|
-
const destDir =
|
|
13157
|
+
const destDir = join27(workspaceCwdFor(args.topicId), "uploads");
|
|
13151
13158
|
mkdirSync17(destDir, { recursive: true });
|
|
13152
13159
|
const safeName = safeAttachmentFilename(args.filename, "upload");
|
|
13153
|
-
const destPath =
|
|
13160
|
+
const destPath = join27(destDir, `${Date.now()}-${randomUUID13().slice(0, 8)}-${safeName}`);
|
|
13154
13161
|
if (args.sourcePath !== undefined) {
|
|
13155
13162
|
copyFileSync2(args.sourcePath, destPath);
|
|
13156
13163
|
} else if (args.bytes !== undefined) {
|
|
@@ -14136,7 +14143,7 @@ var init_visual_html = __esm(() => {
|
|
|
14136
14143
|
});
|
|
14137
14144
|
|
|
14138
14145
|
// ../../packages/core/src/runtime/visuals.ts
|
|
14139
|
-
import { realpathSync as
|
|
14146
|
+
import { realpathSync as realpathSync5 } from "fs";
|
|
14140
14147
|
import { isAbsolute as isAbsolute4, resolve as resolve15 } from "path";
|
|
14141
14148
|
function activeVisualHtmlForPrompt(html) {
|
|
14142
14149
|
if (html.length <= ACTIVE_VISUAL_PROMPT_MAX_CHARS) {
|
|
@@ -14191,8 +14198,8 @@ function isPathInside(baseDir, filePath) {
|
|
|
14191
14198
|
const base = resolve15(baseDir);
|
|
14192
14199
|
const normalized = resolve15(filePath);
|
|
14193
14200
|
try {
|
|
14194
|
-
const realBase =
|
|
14195
|
-
const real =
|
|
14201
|
+
const realBase = realpathSync5(base);
|
|
14202
|
+
const real = realpathSync5(normalized);
|
|
14196
14203
|
return real === realBase || real.startsWith(`${realBase}/`);
|
|
14197
14204
|
} catch {
|
|
14198
14205
|
return false;
|
|
@@ -14257,7 +14264,7 @@ function resolveVisualMediaInput(topicId, input) {
|
|
|
14257
14264
|
}
|
|
14258
14265
|
let realCandidate;
|
|
14259
14266
|
try {
|
|
14260
|
-
realCandidate =
|
|
14267
|
+
realCandidate = realpathSync5(candidate);
|
|
14261
14268
|
} catch {
|
|
14262
14269
|
return { error: `file not found: ${rawPath}` };
|
|
14263
14270
|
}
|
|
@@ -14291,7 +14298,7 @@ var init_visuals = __esm(async () => {
|
|
|
14291
14298
|
// ../../packages/core/src/storage/token-stats.ts
|
|
14292
14299
|
import { createHash as createHash6 } from "crypto";
|
|
14293
14300
|
import { mkdirSync as mkdirSync18 } from "fs";
|
|
14294
|
-
import { join as
|
|
14301
|
+
import { join as join28 } from "path";
|
|
14295
14302
|
function emptyBucket() {
|
|
14296
14303
|
return {
|
|
14297
14304
|
inputTokens: 0,
|
|
@@ -14309,7 +14316,7 @@ function queriesPath(userId) {
|
|
|
14309
14316
|
const fileId = tokenStatsFileId(userId);
|
|
14310
14317
|
const logDir = resolveStorageLogDir();
|
|
14311
14318
|
mkdirSync18(logDir, { recursive: true });
|
|
14312
|
-
return
|
|
14319
|
+
return join28(logDir, `token-queries-${fileId}.jsonl`);
|
|
14313
14320
|
}
|
|
14314
14321
|
function loadRecords(userId) {
|
|
14315
14322
|
try {
|
|
@@ -14380,7 +14387,7 @@ var init_token_stats = __esm(async () => {
|
|
|
14380
14387
|
|
|
14381
14388
|
// ../../packages/core/src/runtime/turn-event-stream.ts
|
|
14382
14389
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
14383
|
-
import { realpathSync as
|
|
14390
|
+
import { realpathSync as realpathSync6, statSync as statSync9 } from "fs";
|
|
14384
14391
|
import { isAbsolute as isAbsolute5, resolve as resolve16 } from "path";
|
|
14385
14392
|
function sessionEventMatchesCurrentExecution(topicId, queryId, agent, model) {
|
|
14386
14393
|
if (getRoomQuery(topicId)?.queryId !== queryId)
|
|
@@ -14695,7 +14702,7 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14695
14702
|
}
|
|
14696
14703
|
let safePath;
|
|
14697
14704
|
try {
|
|
14698
|
-
safePath =
|
|
14705
|
+
safePath = realpathSync6(path);
|
|
14699
14706
|
if (!statSync9(safePath).isFile()) {
|
|
14700
14707
|
logger.warn({ topicId, path }, "peer output path is not a regular file");
|
|
14701
14708
|
break;
|
|
@@ -14962,10 +14969,10 @@ var init_turn_session = __esm(async () => {
|
|
|
14962
14969
|
});
|
|
14963
14970
|
|
|
14964
14971
|
// ../../packages/core/src/storage/app-settings.ts
|
|
14965
|
-
import { existsSync as
|
|
14966
|
-
import { dirname as dirname15, join as
|
|
14972
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync19, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "fs";
|
|
14973
|
+
import { dirname as dirname15, join as join29 } from "path";
|
|
14967
14974
|
function settingsFile() {
|
|
14968
|
-
return
|
|
14975
|
+
return join29(resolveStorageDataDir(), "otium-settings.json");
|
|
14969
14976
|
}
|
|
14970
14977
|
function ensureSettingsLoaded() {
|
|
14971
14978
|
const path = settingsFile();
|
|
@@ -14974,8 +14981,8 @@ function ensureSettingsLoaded() {
|
|
|
14974
14981
|
loadedSettingsFile = path;
|
|
14975
14982
|
aiName = DEFAULT_AI_NAME;
|
|
14976
14983
|
try {
|
|
14977
|
-
if (
|
|
14978
|
-
const data = JSON.parse(
|
|
14984
|
+
if (existsSync18(path)) {
|
|
14985
|
+
const data = JSON.parse(readFileSync18(path, "utf8"));
|
|
14979
14986
|
if (typeof data.aiName === "string" && data.aiName.trim()) {
|
|
14980
14987
|
aiName = data.aiName.trim();
|
|
14981
14988
|
}
|
|
@@ -15064,8 +15071,8 @@ __export(exports_turn_runner, {
|
|
|
15064
15071
|
AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
|
|
15065
15072
|
});
|
|
15066
15073
|
import { randomUUID as randomUUID16 } from "crypto";
|
|
15067
|
-
import { existsSync as
|
|
15068
|
-
import { join as
|
|
15074
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync20, readdirSync as readdirSync7, statSync as statSync10 } from "fs";
|
|
15075
|
+
import { join as join30 } from "path";
|
|
15069
15076
|
function withDefaultPlaywright(configuredMcp, isManager) {
|
|
15070
15077
|
if (isManager)
|
|
15071
15078
|
return configuredMcp;
|
|
@@ -15108,18 +15115,18 @@ function appendAskReplyMessage(topicId, text2, agentType) {
|
|
|
15108
15115
|
return message;
|
|
15109
15116
|
}
|
|
15110
15117
|
function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, matchesTitle, preferExact = true) {
|
|
15111
|
-
const preferred =
|
|
15112
|
-
if (preferExact &&
|
|
15118
|
+
const preferred = join30(directory, preferredFilename);
|
|
15119
|
+
if (preferExact && existsSync19(preferred))
|
|
15113
15120
|
return preferred;
|
|
15114
15121
|
let newestLegacyId = null;
|
|
15115
15122
|
let newestTitle = null;
|
|
15116
15123
|
try {
|
|
15117
|
-
for (const filename of
|
|
15124
|
+
for (const filename of readdirSync7(directory)) {
|
|
15118
15125
|
const titleMatch = matchesTitle(filename);
|
|
15119
15126
|
const legacyIdMatch = !titleMatch && matchesLegacyId(filename);
|
|
15120
15127
|
if (!titleMatch && !legacyIdMatch)
|
|
15121
15128
|
continue;
|
|
15122
|
-
const path =
|
|
15129
|
+
const path = join30(directory, filename);
|
|
15123
15130
|
const mtimeMs = statSync10(path).mtimeMs;
|
|
15124
15131
|
if (titleMatch) {
|
|
15125
15132
|
if (!newestTitle || mtimeMs > newestTitle.mtimeMs) {
|
|
@@ -15133,10 +15140,10 @@ function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, ma
|
|
|
15133
15140
|
return newestTitle?.path ?? newestLegacyId?.path ?? preferred;
|
|
15134
15141
|
}
|
|
15135
15142
|
function resolveWikiMemoryMirror(wikiDir, topicId, topicTitle) {
|
|
15136
|
-
const briefFile = resolveWikiMirrorPath(
|
|
15137
|
-
const hasBriefFile =
|
|
15138
|
-
const latestSummaryCandidate = resolveWikiMirrorPath(
|
|
15139
|
-
const latestSummaryFile =
|
|
15143
|
+
const briefFile = resolveWikiMirrorPath(join30(wikiDir, "topic"), `${wikiBriefStorageKey(topicTitle, topicId)}.md`, (filename) => isTopicBriefFile(filename, topicId), (filename) => isTopicBriefFile(filename, topicId, topicTitle));
|
|
15144
|
+
const hasBriefFile = existsSync19(briefFile) && statSync10(briefFile).isFile();
|
|
15145
|
+
const latestSummaryCandidate = resolveWikiMirrorPath(join30(wikiDir, "summaries"), `__missing__-${wikiSummaryFilename("0000-00-00", topicTitle, topicId)}`, (filename) => isTopicSummaryFile(filename, topicId), (filename) => isTopicSummaryFile(filename, topicId, topicTitle), false);
|
|
15146
|
+
const latestSummaryFile = existsSync19(latestSummaryCandidate) && statSync10(latestSummaryCandidate).isFile() ? latestSummaryCandidate : null;
|
|
15140
15147
|
return { briefFile, hasBriefFile, latestSummaryFile };
|
|
15141
15148
|
}
|
|
15142
15149
|
async function streamAgentEvents(topicId, topicTitle, queryId, events, control, agentType, model, effort, userId, retryableSessionExpired = true, onSessionId, execution) {
|
|
@@ -16288,9 +16295,9 @@ __export(exports_auth_check, {
|
|
|
16288
16295
|
checkAgentAuth: () => checkAgentAuth
|
|
16289
16296
|
});
|
|
16290
16297
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
16291
|
-
import { existsSync as
|
|
16298
|
+
import { existsSync as existsSync20 } from "fs";
|
|
16292
16299
|
import { homedir as homedir9, platform } from "os";
|
|
16293
|
-
import { join as
|
|
16300
|
+
import { join as join31 } from "path";
|
|
16294
16301
|
function hasMaestroCredential(host, key, userId) {
|
|
16295
16302
|
if (userId && host.getVaultValue(userId, key)?.trim())
|
|
16296
16303
|
return true;
|
|
@@ -16319,7 +16326,7 @@ function checkAgentAuth(agent, host = defaultAgentAuthHost, userId) {
|
|
|
16319
16326
|
error: "claude is not logged in (no macOS keychain entry 'Claude Code-credentials'). Run `claude` and complete login first"
|
|
16320
16327
|
};
|
|
16321
16328
|
}
|
|
16322
|
-
const path =
|
|
16329
|
+
const path = join31(host.homeDirectory(), ".claude", ".credentials.json");
|
|
16323
16330
|
if (host.exists(path))
|
|
16324
16331
|
return { ok: true };
|
|
16325
16332
|
return {
|
|
@@ -16361,7 +16368,7 @@ var init_auth_check = __esm(async () => {
|
|
|
16361
16368
|
await init_vault();
|
|
16362
16369
|
defaultAgentAuthHost = {
|
|
16363
16370
|
codexAuthFilePath,
|
|
16364
|
-
exists:
|
|
16371
|
+
exists: existsSync20,
|
|
16365
16372
|
environment: process.env,
|
|
16366
16373
|
homeDirectory: homedir9,
|
|
16367
16374
|
operatingSystem: platform,
|
|
@@ -18433,15 +18440,401 @@ await __promiseAll([
|
|
|
18433
18440
|
init_codex_registry(),
|
|
18434
18441
|
init_maestro_registry()
|
|
18435
18442
|
]);
|
|
18443
|
+
import { spawn as spawn2 } from "child_process";
|
|
18444
|
+
import { existsSync as existsSync9, readdirSync as readdirSync3 } from "fs";
|
|
18445
|
+
import { join as join11 } from "path";
|
|
18436
18446
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
18437
18447
|
import { z } from "zod";
|
|
18448
|
+
function signalProcessTree(child, signal) {
|
|
18449
|
+
try {
|
|
18450
|
+
if (child.pid && process.platform !== "win32")
|
|
18451
|
+
process.kill(-child.pid, signal);
|
|
18452
|
+
else
|
|
18453
|
+
child.kill(signal);
|
|
18454
|
+
} catch {
|
|
18455
|
+
try {
|
|
18456
|
+
child.kill(signal);
|
|
18457
|
+
} catch {}
|
|
18458
|
+
}
|
|
18459
|
+
}
|
|
18460
|
+
function spawnCapture(cmd, args, timeoutMs, signal, env) {
|
|
18461
|
+
return new Promise((resolve7, reject) => {
|
|
18462
|
+
const child = spawn2(cmd, args, {
|
|
18463
|
+
env: env ?? process.env,
|
|
18464
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
18465
|
+
detached: process.platform !== "win32"
|
|
18466
|
+
});
|
|
18467
|
+
let settled = false;
|
|
18468
|
+
let stdout = "";
|
|
18469
|
+
let stderr = "";
|
|
18470
|
+
const forceKill = () => signalProcessTree(child, "SIGKILL");
|
|
18471
|
+
let killTimer;
|
|
18472
|
+
const stop = (reason) => {
|
|
18473
|
+
if (settled)
|
|
18474
|
+
return;
|
|
18475
|
+
settled = true;
|
|
18476
|
+
signalProcessTree(child, "SIGTERM");
|
|
18477
|
+
killTimer = setTimeout(() => {
|
|
18478
|
+
forceKill();
|
|
18479
|
+
killTimer = undefined;
|
|
18480
|
+
}, 1000);
|
|
18481
|
+
killTimer.unref?.();
|
|
18482
|
+
reject(new Error(reason));
|
|
18483
|
+
};
|
|
18484
|
+
const timeout = setTimeout(() => stop("timeout"), timeoutMs);
|
|
18485
|
+
const onAbort = () => stop("aborted");
|
|
18486
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
18487
|
+
const cleanup = () => {
|
|
18488
|
+
clearTimeout(timeout);
|
|
18489
|
+
signal.removeEventListener("abort", onAbort);
|
|
18490
|
+
};
|
|
18491
|
+
child.stdout.on("data", (data) => {
|
|
18492
|
+
stdout += data.toString();
|
|
18493
|
+
});
|
|
18494
|
+
child.stderr.on("data", (data) => {
|
|
18495
|
+
stderr += data.toString();
|
|
18496
|
+
});
|
|
18497
|
+
child.on("error", (err) => {
|
|
18498
|
+
if (settled)
|
|
18499
|
+
return;
|
|
18500
|
+
settled = true;
|
|
18501
|
+
cleanup();
|
|
18502
|
+
if (killTimer)
|
|
18503
|
+
clearTimeout(killTimer);
|
|
18504
|
+
reject(err);
|
|
18505
|
+
});
|
|
18506
|
+
child.on("close", (code, exitSignal) => {
|
|
18507
|
+
cleanup();
|
|
18508
|
+
if (settled) {
|
|
18509
|
+
if (killTimer) {
|
|
18510
|
+
clearTimeout(killTimer);
|
|
18511
|
+
killTimer = undefined;
|
|
18512
|
+
}
|
|
18513
|
+
return;
|
|
18514
|
+
}
|
|
18515
|
+
settled = true;
|
|
18516
|
+
if (killTimer)
|
|
18517
|
+
clearTimeout(killTimer);
|
|
18518
|
+
if (code === 0)
|
|
18519
|
+
resolve7({ stdout, stderr });
|
|
18520
|
+
else
|
|
18521
|
+
reject(new Error(stderr.trim() || `${cmd} exited with ${code ?? exitSignal}`));
|
|
18522
|
+
});
|
|
18523
|
+
});
|
|
18524
|
+
}
|
|
18525
|
+
function resultOk(agent, model, latency, detail) {
|
|
18526
|
+
return { agent, model, ok: true, latency, detail };
|
|
18527
|
+
}
|
|
18528
|
+
function resultFail(agent, model, latency, error) {
|
|
18529
|
+
let category = "unknown";
|
|
18530
|
+
const normalized = error.toLowerCase();
|
|
18531
|
+
if (normalized.includes("auth") || normalized.includes("key") || normalized.includes("credential") || normalized.includes("unauthorized")) {
|
|
18532
|
+
category = "auth_error";
|
|
18533
|
+
} else if (normalized.includes("rate") || normalized.includes("limit") || normalized.includes("busy") || normalized.includes("overloaded")) {
|
|
18534
|
+
category = "rate_limit";
|
|
18535
|
+
} else if (normalized.includes("network") || normalized.includes("refused") || normalized.includes("dns") || normalized.includes("timeout")) {
|
|
18536
|
+
category = "network_error";
|
|
18537
|
+
}
|
|
18538
|
+
return { agent, model, ok: false, latency, error, category };
|
|
18539
|
+
}
|
|
18540
|
+
async function checkClaude(model, timeoutMs, signal) {
|
|
18541
|
+
const start = performance.now();
|
|
18542
|
+
try {
|
|
18543
|
+
const args = ["-p", "say OK", "--model", model, "--max-turns", "1", "--output-format", "text"];
|
|
18544
|
+
const { stdout, stderr } = await spawnCapture("claude", args, timeoutMs, signal);
|
|
18545
|
+
const elapsed = Math.round(performance.now() - start);
|
|
18546
|
+
const text = (stdout + stderr).trim().slice(0, 200);
|
|
18547
|
+
if (!text)
|
|
18548
|
+
return resultFail("claude", model, elapsed, "empty response");
|
|
18549
|
+
return resultOk("claude", model, elapsed, text);
|
|
18550
|
+
} catch (err) {
|
|
18551
|
+
return resultFail("claude", model, Math.round(performance.now() - start), errMsg(err));
|
|
18552
|
+
}
|
|
18553
|
+
}
|
|
18554
|
+
async function checkCodex(model, timeoutMs, signal) {
|
|
18555
|
+
const start = performance.now();
|
|
18556
|
+
try {
|
|
18557
|
+
const args = [
|
|
18558
|
+
"exec",
|
|
18559
|
+
"--model",
|
|
18560
|
+
model,
|
|
18561
|
+
"--skip-git-repo-check",
|
|
18562
|
+
"--sandbox",
|
|
18563
|
+
"danger-full-access",
|
|
18564
|
+
"say OK"
|
|
18565
|
+
];
|
|
18566
|
+
const { stdout, stderr } = await spawnCapture("codex", args, timeoutMs, signal, {
|
|
18567
|
+
...process.env,
|
|
18568
|
+
CODEX_NO_COLOR: "1"
|
|
18569
|
+
});
|
|
18570
|
+
const elapsed = Math.round(performance.now() - start);
|
|
18571
|
+
const combined = (stdout + stderr).trim();
|
|
18572
|
+
const match = combined.match(/\ncodex\s*\n(.+?)(?:\n(?:tokens|session|user|$))/);
|
|
18573
|
+
return resultOk("codex", model, elapsed, match ? match[1].trim().slice(0, 200) : "OK");
|
|
18574
|
+
} catch (err) {
|
|
18575
|
+
return resultFail("codex", model, Math.round(performance.now() - start), errMsg(err));
|
|
18576
|
+
}
|
|
18577
|
+
}
|
|
18578
|
+
async function checkMaestro(model, timeoutMs, signal) {
|
|
18579
|
+
const start = performance.now();
|
|
18580
|
+
let iterator;
|
|
18581
|
+
try {
|
|
18582
|
+
const { maestroProvider } = await import("maestro-agent-sdk");
|
|
18583
|
+
const generator = maestroProvider({
|
|
18584
|
+
model,
|
|
18585
|
+
prompt: "say OK",
|
|
18586
|
+
cwd: process.cwd(),
|
|
18587
|
+
maxTurns: 1
|
|
18588
|
+
});
|
|
18589
|
+
const deadline = Date.now() + timeoutMs;
|
|
18590
|
+
const activeIterator = generator[Symbol.asyncIterator]();
|
|
18591
|
+
iterator = activeIterator;
|
|
18592
|
+
let text = "";
|
|
18593
|
+
while (true) {
|
|
18594
|
+
const remaining = deadline - Date.now();
|
|
18595
|
+
if (remaining <= 0)
|
|
18596
|
+
throw new Error("timeout");
|
|
18597
|
+
const eventResult = await new Promise((resolve7, reject) => {
|
|
18598
|
+
const timeout = setTimeout(() => reject(new Error("timeout")), remaining);
|
|
18599
|
+
const onAbort = () => reject(new Error("aborted"));
|
|
18600
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
18601
|
+
activeIterator.next().then(resolve7, reject).finally(() => {
|
|
18602
|
+
clearTimeout(timeout);
|
|
18603
|
+
signal.removeEventListener("abort", onAbort);
|
|
18604
|
+
});
|
|
18605
|
+
});
|
|
18606
|
+
if (eventResult.done)
|
|
18607
|
+
break;
|
|
18608
|
+
const event = eventResult.value;
|
|
18609
|
+
if (event.type === "text" && event.content)
|
|
18610
|
+
text = event.content.slice(0, 200);
|
|
18611
|
+
if (event.type === "error") {
|
|
18612
|
+
return resultFail("maestro", model, Math.round(performance.now() - start), event.error || "unknown error");
|
|
18613
|
+
}
|
|
18614
|
+
}
|
|
18615
|
+
return resultOk("maestro", model, Math.round(performance.now() - start), text || "(empty response)");
|
|
18616
|
+
} catch (err) {
|
|
18617
|
+
return resultFail("maestro", model, Math.round(performance.now() - start), errMsg(err));
|
|
18618
|
+
} finally {
|
|
18619
|
+
if (iterator?.return) {
|
|
18620
|
+
try {
|
|
18621
|
+
await iterator.return();
|
|
18622
|
+
} catch {}
|
|
18623
|
+
}
|
|
18624
|
+
}
|
|
18625
|
+
}
|
|
18626
|
+
function getDefaultModel(registry) {
|
|
18627
|
+
return resolveDefaultModel(registry.kind, registry.defaultModel);
|
|
18628
|
+
}
|
|
18629
|
+
var AGENTS = [
|
|
18630
|
+
{ kind: "claude", registry: claudeRegistry, checker: checkClaude },
|
|
18631
|
+
{ kind: "codex", registry: codexRegistry, checker: checkCodex },
|
|
18632
|
+
{ kind: "maestro", registry: maestroRegistry, checker: checkMaestro }
|
|
18633
|
+
];
|
|
18634
|
+
var MAX_CONCURRENT_CHECKS = 2;
|
|
18635
|
+
var activeChecks = 0;
|
|
18636
|
+
var checkWaiters = [];
|
|
18438
18637
|
var activeCheckAllUsers = new Set;
|
|
18638
|
+
async function withCheckSlot(operation) {
|
|
18639
|
+
if (activeChecks >= MAX_CONCURRENT_CHECKS) {
|
|
18640
|
+
await new Promise((resolve7) => checkWaiters.push(resolve7));
|
|
18641
|
+
}
|
|
18642
|
+
activeChecks += 1;
|
|
18643
|
+
try {
|
|
18644
|
+
return await operation();
|
|
18645
|
+
} finally {
|
|
18646
|
+
activeChecks -= 1;
|
|
18647
|
+
checkWaiters.shift()?.();
|
|
18648
|
+
}
|
|
18649
|
+
}
|
|
18650
|
+
function createAgentHealthMcpServer(context) {
|
|
18651
|
+
const server = new McpServer({ name: "agent-health", version: "1.0.0" });
|
|
18652
|
+
const abortController = new AbortController;
|
|
18653
|
+
const originalClose = server.close.bind(server);
|
|
18654
|
+
server.close = async () => {
|
|
18655
|
+
abortController.abort();
|
|
18656
|
+
await originalClose();
|
|
18657
|
+
};
|
|
18658
|
+
server.tool("check_agent", "\uC2E4\uC81C API \uD638\uCD9C\uB85C \uD2B9\uC815 agent+model \uC870\uD569\uC774 \uC815\uC0C1 \uB3D9\uC791\uD558\uB294\uC9C0 \uCCB4\uD06C\uD569\uB2C8\uB2E4.", {
|
|
18659
|
+
agent: z.enum(["claude", "codex", "maestro"]).describe("\uCCB4\uD06C\uD560 agent"),
|
|
18660
|
+
model: z.string().optional().describe("\uCCB4\uD06C\uD560 \uBAA8\uB378 (\uC5C6\uC73C\uBA74 agent\uBCC4 default \uC0AC\uC6A9)"),
|
|
18661
|
+
timeoutMs: z.number().default(30000).describe("\uD0C0\uC784\uC544\uC6C3 (ms), \uAE30\uBCF8 30\uCD08")
|
|
18662
|
+
}, async ({ agent, model, timeoutMs }) => {
|
|
18663
|
+
const entry = AGENTS.find((candidate) => candidate.kind === agent);
|
|
18664
|
+
if (!entry)
|
|
18665
|
+
return mcpOk(`Unknown agent: ${agent}`);
|
|
18666
|
+
const resolvedModel = model || getDefaultModel(entry.registry);
|
|
18667
|
+
const result = await withCheckSlot(() => entry.checker(resolvedModel, timeoutMs, abortController.signal));
|
|
18668
|
+
if (result.ok) {
|
|
18669
|
+
return mcpOk(`OK ${result.agent} / ${result.model}
|
|
18670
|
+
latency: ${result.latency}ms
|
|
18671
|
+
detail: ${result.detail}`);
|
|
18672
|
+
}
|
|
18673
|
+
return mcpOk(`FAIL ${result.agent} / ${result.model} [${result.category}]
|
|
18674
|
+
latency: ${result.latency}ms
|
|
18675
|
+
error: ${result.error}`);
|
|
18676
|
+
});
|
|
18677
|
+
server.tool("check_all", "\uBAA8\uB4E0 agent (claude, codex, maestro)\uB97C \uAE30\uBCF8 \uBAA8\uB378\uB85C \uB3D9\uC2DC\uC5D0 \uCCB4\uD06C\uD569\uB2C8\uB2E4.", { timeoutMs: z.number().default(30000).describe("agent\uBCC4 \uD0C0\uC784\uC544\uC6C3 (ms), \uAE30\uBCF8 30\uCD08") }, async ({ timeoutMs }) => {
|
|
18678
|
+
const userKey = context.userId ?? "unscoped";
|
|
18679
|
+
if (activeCheckAllUsers.has(userKey)) {
|
|
18680
|
+
return mcpOk("FAIL check_all is already running for this user");
|
|
18681
|
+
}
|
|
18682
|
+
activeCheckAllUsers.add(userKey);
|
|
18683
|
+
try {
|
|
18684
|
+
const results = await Promise.all(AGENTS.map(async (entry) => withCheckSlot(() => entry.checker(getDefaultModel(entry.registry), timeoutMs, abortController.signal))));
|
|
18685
|
+
const lines = results.map((result) => result.ok ? `OK ${result.agent.padEnd(8)} / ${result.model.padEnd(14)} ${result.latency}ms ${result.detail}` : `FAIL ${result.agent.padEnd(8)} / ${result.model.padEnd(14)} ${result.latency}ms [${result.category}] ${result.error}`);
|
|
18686
|
+
return mcpOk(`Agent/Model Health Check
|
|
18687
|
+
${lines.join(`
|
|
18688
|
+
`)}
|
|
18689
|
+
|
|
18690
|
+
${results.every((result) => result.ok) ? "All agents healthy" : "Some agents failed"}`);
|
|
18691
|
+
} finally {
|
|
18692
|
+
activeCheckAllUsers.delete(userKey);
|
|
18693
|
+
}
|
|
18694
|
+
});
|
|
18695
|
+
server.tool("list_active_queries", "\uD604\uC7AC \uC0AC\uC6A9\uC790 \uBC94\uC704\uC5D0\uC11C \uC2E4\uD589 \uC911\uC778 \uD1A0\uD53D \uCFFC\uB9AC \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.", {}, async () => {
|
|
18696
|
+
if (!context.userId)
|
|
18697
|
+
return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC870\uD68C \uBD88\uAC00 (user context \uC5C6\uC74C)");
|
|
18698
|
+
const stateDir = join11(USERS_LOG_DIR, context.userId, "active-queries");
|
|
18699
|
+
if (!existsSync9(stateDir))
|
|
18700
|
+
return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC5C6\uC74C");
|
|
18701
|
+
let files;
|
|
18702
|
+
try {
|
|
18703
|
+
files = readdirSync3(stateDir);
|
|
18704
|
+
} catch {
|
|
18705
|
+
return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC5C6\uC74C");
|
|
18706
|
+
}
|
|
18707
|
+
const now = Date.now();
|
|
18708
|
+
const entries = files.flatMap((file) => {
|
|
18709
|
+
if (!file.endsWith(".json"))
|
|
18710
|
+
return [];
|
|
18711
|
+
const state = readJsonFile(join11(stateDir, file));
|
|
18712
|
+
if (!state)
|
|
18713
|
+
return [];
|
|
18714
|
+
const sinceMs = new Date(state.since).getTime();
|
|
18715
|
+
if (now - sinceMs > ACTIVE_QUERY_STALE_MS)
|
|
18716
|
+
return [];
|
|
18717
|
+
return [
|
|
18718
|
+
{
|
|
18719
|
+
topicName: state.topicName ?? file.slice(0, -5),
|
|
18720
|
+
elapsedSec: Math.round((now - sinceMs) / 1000),
|
|
18721
|
+
task: state.task
|
|
18722
|
+
}
|
|
18723
|
+
];
|
|
18724
|
+
});
|
|
18725
|
+
if (entries.length === 0)
|
|
18726
|
+
return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC5C6\uC74C");
|
|
18727
|
+
const lines = entries.map((entry) => `\u2022 ${entry.topicName} | ${entry.elapsedSec}s \uACBD\uACFC${entry.task ? ` "${entry.task}"` : ""}`);
|
|
18728
|
+
return mcpOk(`\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC (${entries.length}\uAC1C)
|
|
18729
|
+
${lines.join(`
|
|
18730
|
+
`)}`);
|
|
18731
|
+
});
|
|
18732
|
+
return server;
|
|
18733
|
+
}
|
|
18439
18734
|
// ../../packages/core/src/mcp/factories/compaction-log.ts
|
|
18440
18735
|
init_mcp_helpers();
|
|
18736
|
+
import { readFileSync as readFileSync8, realpathSync as realpathSync2 } from "fs";
|
|
18441
18737
|
import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
18442
18738
|
import { z as z2 } from "zod";
|
|
18739
|
+
var DEFAULT_MAX_CALLS = 12;
|
|
18443
18740
|
var DEFAULT_MAX_TOTAL_BYTES = 512 * 1024;
|
|
18444
18741
|
var DEFAULT_MAX_CHUNK_BYTES = 64 * 1024;
|
|
18742
|
+
var DEFAULT_LINE_LIMIT = 300;
|
|
18743
|
+
var MAX_LINE_LIMIT = 500;
|
|
18744
|
+
function positiveInt(value2, fallback) {
|
|
18745
|
+
return Number.isFinite(value2) && value2 && value2 > 0 ? Math.floor(value2) : fallback;
|
|
18746
|
+
}
|
|
18747
|
+
function fitUtf8(text, maxBytes) {
|
|
18748
|
+
if (Buffer.byteLength(text, "utf8") <= maxBytes)
|
|
18749
|
+
return text;
|
|
18750
|
+
const marker = `
|
|
18751
|
+
[... oversized line clipped ...]
|
|
18752
|
+
`;
|
|
18753
|
+
const markerBytes = Buffer.byteLength(marker, "utf8");
|
|
18754
|
+
const bytes = Buffer.from(text, "utf8");
|
|
18755
|
+
if (maxBytes <= markerBytes) {
|
|
18756
|
+
return bytes.subarray(0, maxBytes).toString("utf8").replace(/\uFFFD+$/u, "");
|
|
18757
|
+
}
|
|
18758
|
+
const available = Math.max(0, maxBytes - markerBytes);
|
|
18759
|
+
const headBudget = Math.ceil(available * 0.6);
|
|
18760
|
+
const tailBudget = available - headBudget;
|
|
18761
|
+
const head = bytes.subarray(0, headBudget).toString("utf8").replace(/\uFFFD+$/u, "");
|
|
18762
|
+
const tail = bytes.subarray(Math.max(0, bytes.length - tailBudget)).toString("utf8").replace(/^\uFFFD+/u, "");
|
|
18763
|
+
return `${head}${marker}${tail}`;
|
|
18764
|
+
}
|
|
18765
|
+
function createCompactionLogMcpServer(context) {
|
|
18766
|
+
if (!context.filePath)
|
|
18767
|
+
throw new Error("compaction-log MCP requires filePath");
|
|
18768
|
+
const filePath = realpathSync2(context.filePath);
|
|
18769
|
+
const lines = readFileSync8(filePath, "utf8").split(`
|
|
18770
|
+
`);
|
|
18771
|
+
const maxCalls = positiveInt(context.maxCalls, DEFAULT_MAX_CALLS);
|
|
18772
|
+
const maxTotalBytes = positiveInt(context.maxTotalBytes, DEFAULT_MAX_TOTAL_BYTES);
|
|
18773
|
+
const maxChunkBytes = positiveInt(context.maxChunkBytes, DEFAULT_MAX_CHUNK_BYTES);
|
|
18774
|
+
let calls = 0;
|
|
18775
|
+
let totalBytes = 0;
|
|
18776
|
+
const server = new McpServer2({ name: "compaction-log", version: "1.0.0" });
|
|
18777
|
+
server.tool("read_compaction_log", [
|
|
18778
|
+
`Read the immutable conversation snapshot in bounded chunks. It contains ${lines.length} lines.`,
|
|
18779
|
+
"Start at offset 1, then inspect the final chunk using total_lines from the response.",
|
|
18780
|
+
"Read intermediate chunks only when needed. Return a summary instead of calling after the budget is exhausted."
|
|
18781
|
+
].join(" "), {
|
|
18782
|
+
offset: z2.number().optional().describe("One-based line number. Defaults to 1."),
|
|
18783
|
+
limit: z2.number().optional().describe(`Number of lines. Defaults to ${DEFAULT_LINE_LIMIT}, max ${MAX_LINE_LIMIT}.`)
|
|
18784
|
+
}, async ({ offset: rawOffset, limit: rawLimit }) => {
|
|
18785
|
+
calls += 1;
|
|
18786
|
+
if (calls > maxCalls || totalBytes >= maxTotalBytes) {
|
|
18787
|
+
return mcpError(JSON.stringify({
|
|
18788
|
+
error: "compaction log read budget exhausted; produce the summary now",
|
|
18789
|
+
calls,
|
|
18790
|
+
max_calls: maxCalls,
|
|
18791
|
+
total_lines: lines.length
|
|
18792
|
+
}));
|
|
18793
|
+
}
|
|
18794
|
+
const offset = positiveInt(rawOffset, 1);
|
|
18795
|
+
const limit = Math.min(positiveInt(rawLimit, DEFAULT_LINE_LIMIT), MAX_LINE_LIMIT);
|
|
18796
|
+
const start = Math.max(0, offset - 1);
|
|
18797
|
+
if (start >= lines.length) {
|
|
18798
|
+
return mcpOk(JSON.stringify({
|
|
18799
|
+
content: "(end of compaction log)",
|
|
18800
|
+
offset,
|
|
18801
|
+
returned_lines: 0,
|
|
18802
|
+
total_lines: lines.length,
|
|
18803
|
+
calls
|
|
18804
|
+
}));
|
|
18805
|
+
}
|
|
18806
|
+
const selected = [];
|
|
18807
|
+
let returnedBytes = 0;
|
|
18808
|
+
let index = start;
|
|
18809
|
+
const callBudget = Math.min(maxChunkBytes, maxTotalBytes - totalBytes);
|
|
18810
|
+
while (index < lines.length && selected.length < limit) {
|
|
18811
|
+
const line = fitUtf8(lines[index] ?? "", Math.max(1, callBudget));
|
|
18812
|
+
const separatorBytes = selected.length > 0 ? 1 : 0;
|
|
18813
|
+
const lineBytes = Buffer.byteLength(line, "utf8");
|
|
18814
|
+
if (selected.length > 0 && returnedBytes + separatorBytes + lineBytes > callBudget)
|
|
18815
|
+
break;
|
|
18816
|
+
selected.push(line);
|
|
18817
|
+
returnedBytes += separatorBytes + lineBytes;
|
|
18818
|
+
index += 1;
|
|
18819
|
+
if (returnedBytes >= callBudget)
|
|
18820
|
+
break;
|
|
18821
|
+
}
|
|
18822
|
+
totalBytes += returnedBytes;
|
|
18823
|
+
return mcpOk(JSON.stringify({
|
|
18824
|
+
content: selected.join(`
|
|
18825
|
+
`),
|
|
18826
|
+
offset,
|
|
18827
|
+
returned_lines: selected.length,
|
|
18828
|
+
returned_bytes: returnedBytes,
|
|
18829
|
+
total_lines: lines.length,
|
|
18830
|
+
total_read_bytes: totalBytes,
|
|
18831
|
+
calls,
|
|
18832
|
+
...index < lines.length ? { next_offset: index + 1 } : {},
|
|
18833
|
+
...calls >= maxCalls || totalBytes >= maxTotalBytes ? { note: "Read budget exhausted; produce the summary now." } : {}
|
|
18834
|
+
}));
|
|
18835
|
+
});
|
|
18836
|
+
return server;
|
|
18837
|
+
}
|
|
18445
18838
|
// ../../packages/core/src/mcp/factories/session-comm.ts
|
|
18446
18839
|
import { McpServer as McpServer3 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
18447
18840
|
import { z as z5 } from "zod";
|
|
@@ -18940,7 +19333,9 @@ export {
|
|
|
18940
19333
|
createTaskMcpServer,
|
|
18941
19334
|
createSystemHealthMcpServer,
|
|
18942
19335
|
createSessionTargetCatalog,
|
|
18943
|
-
createSessionCommMcpServer
|
|
19336
|
+
createSessionCommMcpServer,
|
|
19337
|
+
createCompactionLogMcpServer,
|
|
19338
|
+
createAgentHealthMcpServer
|
|
18944
19339
|
};
|
|
18945
19340
|
|
|
18946
|
-
//# debugId=
|
|
19341
|
+
//# debugId=BC568829D61D883264756E2164756E21
|