cogpit 2.1.3 → 2.3.0
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/cli.js +1603 -773
- package/dist/web/assets/CommandPaletteHost-D-VvT_HL.js +1 -0
- package/dist/web/assets/ConfigBrowser-Cc2lrh85.js +1 -0
- package/dist/web/assets/{HighlightedEditor-qhEWgnBF.js → HighlightedEditor-DWNz1Jcz.js} +2 -2
- package/dist/web/assets/{KeyboardShortcutsDialog-B9nMtf5U.js → KeyboardShortcutsDialog-yOs1u5D6.js} +1 -1
- package/dist/web/assets/{MobileFileChanges-j9DCxvz6.js → MobileFileChanges-B1dtcdSZ.js} +1 -1
- package/dist/web/assets/PreviewPanel-BJwfunf9.js +1 -0
- package/dist/web/assets/ProjectFilesPanel-DppuIFEt.js +4 -0
- package/dist/web/assets/{ProjectSwitcherModal-o8NhzySH.js → ProjectSwitcherModal-DgsuH5CY.js} +1 -1
- package/dist/web/assets/{TerminalOutput-CcWkSv29.js → TerminalOutput-DlGDS0Wx.js} +1 -1
- package/dist/web/assets/ThemeSelectorModal-oI9Vm3EH.js +1 -0
- package/dist/web/assets/WorkflowsPanel-SKbsv_IK.js +1 -0
- package/dist/web/assets/WorktreePanel-CcSLupr7.js +1 -0
- package/dist/web/assets/{index-_0HhakEy.js → index-7FuVzOBC.js} +4 -4
- package/dist/web/assets/index-BVkjlOVU.js +1 -0
- package/dist/web/assets/index-Bw-DFQut.js +1 -0
- package/dist/web/assets/index-Du17HzQD.js +151 -0
- package/dist/web/assets/index-xdv0cIL2.css +1 -0
- package/dist/web/assets/{session-parser.worker-DycJL0jJ.js → session-parser.worker-RMitC4X_.js} +17 -17
- package/dist/web/assets/{vendor-ui-Bg9q4lA4.js → vendor-ui-CdA11Wfh.js} +162 -147
- package/dist/web/index.html +3 -3
- package/package.json +1 -1
- package/dist/web/assets/CommandPaletteHost-1UPdv9Nv.js +0 -1
- package/dist/web/assets/ConfigBrowser-B5lZsJDw.js +0 -1
- package/dist/web/assets/PreviewPanel-DZSVN3mt.js +0 -1
- package/dist/web/assets/ProjectFilesPanel-DSvO4CrB.js +0 -4
- package/dist/web/assets/ThemeSelectorModal-CnbSCgJj.js +0 -1
- package/dist/web/assets/WorkflowsPanel-CvBweQMf.js +0 -1
- package/dist/web/assets/WorktreePanel-DahbK2L0.js +0 -1
- package/dist/web/assets/index-7UiltNKa.js +0 -1
- package/dist/web/assets/index-BESnPMZk.js +0 -144
- package/dist/web/assets/index-Bif4Kdtn.css +0 -1
- package/dist/web/assets/index-DXTQExVH.js +0 -1
package/dist/cli.js
CHANGED
|
@@ -73,7 +73,7 @@ var init_compression = __esm({
|
|
|
73
73
|
import { StringDecoder } from "node:string_decoder";
|
|
74
74
|
function readJsonBody(req, options = {}) {
|
|
75
75
|
const maxBytes = options.maxBytes ?? DEFAULT_MAX_REQUEST_BODY_BYTES;
|
|
76
|
-
return new Promise((
|
|
76
|
+
return new Promise((resolve22, reject) => {
|
|
77
77
|
let body = "";
|
|
78
78
|
let bytesRead = 0;
|
|
79
79
|
let settled = false;
|
|
@@ -97,11 +97,11 @@ function readJsonBody(req, options = {}) {
|
|
|
97
97
|
settled = true;
|
|
98
98
|
body += decoder.end();
|
|
99
99
|
if (!body.trim() && options.allowEmpty) {
|
|
100
|
-
|
|
100
|
+
resolve22({});
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
try {
|
|
104
|
-
|
|
104
|
+
resolve22(JSON.parse(body));
|
|
105
105
|
} catch {
|
|
106
106
|
reject(new HttpBodyError("Invalid JSON body", 400));
|
|
107
107
|
}
|
|
@@ -486,8 +486,8 @@ async function mint(device, generation2) {
|
|
|
486
486
|
if (prev?.generation === generation2 && prev.error && Date.now() - prev.at < MINT_COOLDOWN_MS) {
|
|
487
487
|
throw prev.error;
|
|
488
488
|
}
|
|
489
|
-
const
|
|
490
|
-
lastAttempt.set(id,
|
|
489
|
+
const record4 = { at: Date.now(), generation: generation2 };
|
|
490
|
+
lastAttempt.set(id, record4);
|
|
491
491
|
const url = `${device.tls ? "https" : "http"}://${device.host}:${device.port}/api/auth/verify`;
|
|
492
492
|
const credential = device.username ? `${device.username}:${device.password ?? ""}` : device.password ?? "";
|
|
493
493
|
let res;
|
|
@@ -503,7 +503,7 @@ async function mint(device, generation2) {
|
|
|
503
503
|
`Could not reach device "${device.name}" at ${device.host}:${device.port}`,
|
|
504
504
|
{ cause: err }
|
|
505
505
|
);
|
|
506
|
-
|
|
506
|
+
record4.error = error;
|
|
507
507
|
if (generationIsCurrent(id, generation2)) {
|
|
508
508
|
setDeviceRuntime(id, { lastProbe: Date.now() });
|
|
509
509
|
}
|
|
@@ -511,7 +511,7 @@ async function mint(device, generation2) {
|
|
|
511
511
|
}
|
|
512
512
|
if (res.status === 401 || res.status === 403) {
|
|
513
513
|
const error = new DeviceAuthError(id, `Device "${device.name}" rejected the password`, res.status);
|
|
514
|
-
|
|
514
|
+
record4.error = error;
|
|
515
515
|
if (generationIsCurrent(id, generation2)) {
|
|
516
516
|
setDeviceRuntime(id, { authState: "bad-password", lastProbe: Date.now() });
|
|
517
517
|
}
|
|
@@ -522,7 +522,7 @@ async function mint(device, generation2) {
|
|
|
522
522
|
id,
|
|
523
523
|
`Device "${device.name}" returned HTTP ${res.status} while minting a token`
|
|
524
524
|
);
|
|
525
|
-
|
|
525
|
+
record4.error = error;
|
|
526
526
|
if (generationIsCurrent(id, generation2)) {
|
|
527
527
|
setDeviceRuntime(id, { lastProbe: Date.now() });
|
|
528
528
|
}
|
|
@@ -536,7 +536,7 @@ async function mint(device, generation2) {
|
|
|
536
536
|
}
|
|
537
537
|
if (!body || body.valid === false || typeof body.token !== "string" || !body.token) {
|
|
538
538
|
const error = new DeviceAuthError(id, `Device "${device.name}" did not return a valid token`, res.status);
|
|
539
|
-
|
|
539
|
+
record4.error = error;
|
|
540
540
|
if (generationIsCurrent(id, generation2)) {
|
|
541
541
|
setDeviceRuntime(id, { authState: "bad-password", lastProbe: Date.now() });
|
|
542
542
|
}
|
|
@@ -779,6 +779,7 @@ var init_agent_descriptors = __esm({
|
|
|
779
779
|
args: ["update"],
|
|
780
780
|
matches: (path) => path.endsWith("/.local/bin/claude") || path.endsWith("/.local/bin/claude.exe") || path.includes("/.local/share/claude/")
|
|
781
781
|
},
|
|
782
|
+
bundledBySdk: true,
|
|
782
783
|
homeDirName: ".claude",
|
|
783
784
|
homeEnvVar: null,
|
|
784
785
|
installMarker: "projects",
|
|
@@ -915,6 +916,7 @@ var init_agent_descriptors = __esm({
|
|
|
915
916
|
// Codex ships no self-updater; a hand-placed binary has to be replaced by
|
|
916
917
|
// whatever put it there.
|
|
917
918
|
selfUpdate: null,
|
|
919
|
+
bundledBySdk: false,
|
|
918
920
|
homeDirName: ".codex",
|
|
919
921
|
homeEnvVar: "CODEX_HOME",
|
|
920
922
|
installMarker: "",
|
|
@@ -1025,6 +1027,7 @@ var init_agent_descriptors = __esm({
|
|
|
1025
1027
|
// only do because the caller passes the realpath in as well.
|
|
1026
1028
|
matches: (path) => path.endsWith("/.local/bin/copilot") || path === "/usr/local/bin/copilot"
|
|
1027
1029
|
},
|
|
1030
|
+
bundledBySdk: false,
|
|
1028
1031
|
homeDirName: ".copilot",
|
|
1029
1032
|
homeEnvVar: "COPILOT_HOME",
|
|
1030
1033
|
installMarker: "session-state",
|
|
@@ -1161,7 +1164,7 @@ function verifyPassword(password, stored) {
|
|
|
1161
1164
|
async function verifyPasswordAsync(password, stored) {
|
|
1162
1165
|
const scryptHash = parseScryptHash(stored);
|
|
1163
1166
|
if (!scryptHash) return verifyPassword(password, stored);
|
|
1164
|
-
const candidate = await new Promise((
|
|
1167
|
+
const candidate = await new Promise((resolve22, reject) => {
|
|
1165
1168
|
scrypt(
|
|
1166
1169
|
password,
|
|
1167
1170
|
Buffer.from(scryptHash.salt, "hex"),
|
|
@@ -1172,7 +1175,7 @@ async function verifyPasswordAsync(password, stored) {
|
|
|
1172
1175
|
p: SCRYPT_PARALLELISM,
|
|
1173
1176
|
maxmem: SCRYPT_MAX_MEMORY
|
|
1174
1177
|
},
|
|
1175
|
-
(error, derivedKey) => error ? reject(error) :
|
|
1178
|
+
(error, derivedKey) => error ? reject(error) : resolve22(derivedKey)
|
|
1176
1179
|
);
|
|
1177
1180
|
});
|
|
1178
1181
|
return safeCompareBuffers(candidate, Buffer.from(scryptHash.hash, "hex"));
|
|
@@ -1236,6 +1239,9 @@ function hasExtension(binName, extensions) {
|
|
|
1236
1239
|
function hasExecutableExtension(fileName, env = process.env) {
|
|
1237
1240
|
return hasExtension(fileName, pathExtensions({ env }));
|
|
1238
1241
|
}
|
|
1242
|
+
function isDirectlyLaunchable(fileName) {
|
|
1243
|
+
return DIRECT_EXTENSIONS.includes(win32.extname(fileName).toLowerCase());
|
|
1244
|
+
}
|
|
1239
1245
|
function findExecutableOnPath(binName, options = {}) {
|
|
1240
1246
|
const windows = isWindows(options);
|
|
1241
1247
|
const path = windows ? win32 : posix;
|
|
@@ -1280,7 +1286,7 @@ function resolveAgentCommand(binName, args = [], options = {}) {
|
|
|
1280
1286
|
if (!isWindows(options)) return { command: binName, args, spawnOptions: {} };
|
|
1281
1287
|
const resolved = /[\\/]/.test(binName) ? binName : findExecutableOnPath(binName, options);
|
|
1282
1288
|
if (!resolved) return { command: binName, args, spawnOptions: {} };
|
|
1283
|
-
if (
|
|
1289
|
+
if (isDirectlyLaunchable(resolved)) {
|
|
1284
1290
|
return { command: resolved, args, spawnOptions: {} };
|
|
1285
1291
|
}
|
|
1286
1292
|
return throughCmdExe(resolved, args, options);
|
|
@@ -1297,6 +1303,38 @@ var init_binaryResolver = __esm({
|
|
|
1297
1303
|
}
|
|
1298
1304
|
});
|
|
1299
1305
|
|
|
1306
|
+
// ../../shared/contracts/agentExecutable.ts
|
|
1307
|
+
function isExecutableSource(value) {
|
|
1308
|
+
return EXECUTABLE_SOURCES.includes(value);
|
|
1309
|
+
}
|
|
1310
|
+
function parseExecutableChoice(value) {
|
|
1311
|
+
if (!value || typeof value !== "object") return void 0;
|
|
1312
|
+
const { source, path } = value;
|
|
1313
|
+
if (!isExecutableSource(source) || source === "auto") return void 0;
|
|
1314
|
+
if (source === "custom") {
|
|
1315
|
+
return typeof path === "string" && path.trim() ? { source, path: path.trim() } : void 0;
|
|
1316
|
+
}
|
|
1317
|
+
return { source };
|
|
1318
|
+
}
|
|
1319
|
+
var EXECUTABLE_SOURCES, DEFAULT_EXECUTABLE_CHOICE, DETECTED_EXECUTABLE_SOURCES;
|
|
1320
|
+
var init_agentExecutable = __esm({
|
|
1321
|
+
"../../shared/contracts/agentExecutable.ts"() {
|
|
1322
|
+
EXECUTABLE_SOURCES = [
|
|
1323
|
+
"auto",
|
|
1324
|
+
"path",
|
|
1325
|
+
"npm",
|
|
1326
|
+
"bundled",
|
|
1327
|
+
"custom"
|
|
1328
|
+
];
|
|
1329
|
+
DEFAULT_EXECUTABLE_CHOICE = { source: "auto" };
|
|
1330
|
+
DETECTED_EXECUTABLE_SOURCES = [
|
|
1331
|
+
"path",
|
|
1332
|
+
"npm",
|
|
1333
|
+
"bundled"
|
|
1334
|
+
];
|
|
1335
|
+
}
|
|
1336
|
+
});
|
|
1337
|
+
|
|
1300
1338
|
// ../../server/config.ts
|
|
1301
1339
|
import { readFile as readFile2, stat, readdir, chmod as chmod3 } from "node:fs/promises";
|
|
1302
1340
|
import { join as join2, resolve } from "node:path";
|
|
@@ -1405,7 +1443,8 @@ async function loadConfig() {
|
|
|
1405
1443
|
networkPassword,
|
|
1406
1444
|
terminalApp: parsed.terminalApp || void 0,
|
|
1407
1445
|
editorApp: parsed.editorApp || void 0,
|
|
1408
|
-
useBuiltInEditor: !!parsed.useBuiltInEditor
|
|
1446
|
+
useBuiltInEditor: !!parsed.useBuiltInEditor,
|
|
1447
|
+
agentExecutable: parseExecutableChoice(parsed.agentExecutable)
|
|
1409
1448
|
};
|
|
1410
1449
|
return cachedConfig;
|
|
1411
1450
|
}
|
|
@@ -1460,6 +1499,7 @@ var init_config = __esm({
|
|
|
1460
1499
|
init_password_utils();
|
|
1461
1500
|
init_atomicJsonFile();
|
|
1462
1501
|
init_binaryResolver();
|
|
1502
|
+
init_agentExecutable();
|
|
1463
1503
|
CONFIG_FILE_MODE = 384;
|
|
1464
1504
|
__dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
1465
1505
|
PROJECT_ROOT = resolve(__dirname, "..");
|
|
@@ -3959,7 +3999,7 @@ async function createShare(input) {
|
|
|
3959
3999
|
const passwordHash = hashPassword(passphrase);
|
|
3960
4000
|
const share = await commitShareMutation((draft) => {
|
|
3961
4001
|
const existing = draft.get(input.sessionId);
|
|
3962
|
-
const
|
|
4002
|
+
const record4 = {
|
|
3963
4003
|
sessionId: input.sessionId,
|
|
3964
4004
|
dirName: input.dirName,
|
|
3965
4005
|
fileName: input.fileName,
|
|
@@ -3968,8 +4008,8 @@ async function createShare(input) {
|
|
|
3968
4008
|
// No guest has ever used this passphrase; the UI renders 0 as "never".
|
|
3969
4009
|
lastAccessAt: 0
|
|
3970
4010
|
};
|
|
3971
|
-
draft.set(
|
|
3972
|
-
return { changed: true, value: toPublicShare(
|
|
4011
|
+
draft.set(record4.sessionId, record4);
|
|
4012
|
+
return { changed: true, value: toPublicShare(record4) };
|
|
3973
4013
|
});
|
|
3974
4014
|
return { share, passphrase };
|
|
3975
4015
|
}
|
|
@@ -4819,6 +4859,8 @@ var init_policy = __esm({
|
|
|
4819
4859
|
"project-files": admin("/api/project-files"),
|
|
4820
4860
|
"project-file": admin("/api/project-file"),
|
|
4821
4861
|
"git-status": admin("/api/git-status"),
|
|
4862
|
+
"github-actions": admin("/api/github-actions"),
|
|
4863
|
+
"vercel-deployments": admin("/api/vercel-deployments"),
|
|
4822
4864
|
"project-icon": admin("/api/project-icon"),
|
|
4823
4865
|
"git-diff": admin("/api/git-diff"),
|
|
4824
4866
|
mcp: admin("/api/mcp-servers"),
|
|
@@ -4847,6 +4889,10 @@ var init_policy = __esm({
|
|
|
4847
4889
|
"provider-updates": [
|
|
4848
4890
|
{ prefix: "/api/provider-updates", methods: ["GET"], requires: "authed" },
|
|
4849
4891
|
{ prefix: "/api/provider-updates/run", requires: "admin" }
|
|
4892
|
+
],
|
|
4893
|
+
// Reports which binary the server spawns; the choice itself is saved through /api/config.
|
|
4894
|
+
"agent-executable": [
|
|
4895
|
+
{ prefix: "/api/agent-executable", methods: ["GET"], requires: "authed" }
|
|
4850
4896
|
]
|
|
4851
4897
|
};
|
|
4852
4898
|
ALL_RULES = Object.values(ROUTE_POLICIES).flat();
|
|
@@ -5619,6 +5665,274 @@ var init_subagentWatcher = __esm({
|
|
|
5619
5665
|
}
|
|
5620
5666
|
});
|
|
5621
5667
|
|
|
5668
|
+
// ../../shared/versions.ts
|
|
5669
|
+
function parseVersion(raw) {
|
|
5670
|
+
const match = raw.trim().replace(/^v/i, "").match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/);
|
|
5671
|
+
if (!match) return null;
|
|
5672
|
+
return {
|
|
5673
|
+
parts: [Number(match[1]), Number(match[2]), Number(match[3])],
|
|
5674
|
+
prerelease: match[4] ? match[4].split(".") : []
|
|
5675
|
+
};
|
|
5676
|
+
}
|
|
5677
|
+
function extractVersion(output) {
|
|
5678
|
+
const match = output.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/);
|
|
5679
|
+
return match ? match[0] : null;
|
|
5680
|
+
}
|
|
5681
|
+
function comparePrerelease(a, b) {
|
|
5682
|
+
if (a.length === 0 && b.length === 0) return 0;
|
|
5683
|
+
if (a.length === 0) return 1;
|
|
5684
|
+
if (b.length === 0) return -1;
|
|
5685
|
+
for (let i = 0; i < Math.max(a.length, b.length); i += 1) {
|
|
5686
|
+
const left = a[i];
|
|
5687
|
+
const right = b[i];
|
|
5688
|
+
if (left === void 0) return -1;
|
|
5689
|
+
if (right === void 0) return 1;
|
|
5690
|
+
const leftNumeric = /^\d+$/.test(left);
|
|
5691
|
+
const rightNumeric = /^\d+$/.test(right);
|
|
5692
|
+
if (leftNumeric && rightNumeric) {
|
|
5693
|
+
if (Number(left) !== Number(right)) return Number(left) < Number(right) ? -1 : 1;
|
|
5694
|
+
continue;
|
|
5695
|
+
}
|
|
5696
|
+
if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1;
|
|
5697
|
+
if (left !== right) return left < right ? -1 : 1;
|
|
5698
|
+
}
|
|
5699
|
+
return 0;
|
|
5700
|
+
}
|
|
5701
|
+
function compareVersions(a, b) {
|
|
5702
|
+
const left = parseVersion(a);
|
|
5703
|
+
const right = parseVersion(b);
|
|
5704
|
+
if (!left || !right) return null;
|
|
5705
|
+
for (let i = 0; i < 3; i += 1) {
|
|
5706
|
+
if (left.parts[i] !== right.parts[i]) return left.parts[i] < right.parts[i] ? -1 : 1;
|
|
5707
|
+
}
|
|
5708
|
+
return comparePrerelease(left.prerelease, right.prerelease);
|
|
5709
|
+
}
|
|
5710
|
+
var init_versions = __esm({
|
|
5711
|
+
"../../shared/versions.ts"() {
|
|
5712
|
+
}
|
|
5713
|
+
});
|
|
5714
|
+
|
|
5715
|
+
// ../../server/lib/cliProcess.ts
|
|
5716
|
+
import { spawn } from "node:child_process";
|
|
5717
|
+
function runCli(executable, args, timeoutMs) {
|
|
5718
|
+
return new Promise((resolve22) => {
|
|
5719
|
+
const resolved = resolveAgentCommand(executable, [...args]);
|
|
5720
|
+
const child = spawn(resolved.command, resolved.args, {
|
|
5721
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
5722
|
+
...resolved.spawnOptions
|
|
5723
|
+
});
|
|
5724
|
+
let stdout = "";
|
|
5725
|
+
let stderr = "";
|
|
5726
|
+
let timedOut = false;
|
|
5727
|
+
const timer = setTimeout(() => {
|
|
5728
|
+
timedOut = true;
|
|
5729
|
+
child.kill("SIGKILL");
|
|
5730
|
+
}, timeoutMs);
|
|
5731
|
+
const append = (buffer, chunk) => buffer.length >= CLI_OUTPUT_MAX_CHARS ? buffer : buffer + chunk.toString();
|
|
5732
|
+
child.stdout?.on("data", (chunk) => {
|
|
5733
|
+
stdout = append(stdout, chunk);
|
|
5734
|
+
});
|
|
5735
|
+
child.stderr?.on("data", (chunk) => {
|
|
5736
|
+
stderr = append(stderr, chunk);
|
|
5737
|
+
});
|
|
5738
|
+
child.on("error", () => {
|
|
5739
|
+
clearTimeout(timer);
|
|
5740
|
+
resolve22({ code: null, stdout, stderr, timedOut });
|
|
5741
|
+
});
|
|
5742
|
+
child.on("close", (code) => {
|
|
5743
|
+
clearTimeout(timer);
|
|
5744
|
+
resolve22({ code, stdout, stderr, timedOut });
|
|
5745
|
+
});
|
|
5746
|
+
});
|
|
5747
|
+
}
|
|
5748
|
+
async function probeCliVersion(command, versionArgs, timeoutMs = DEFAULT_PROBE_TIMEOUT_MS) {
|
|
5749
|
+
const probe = await runCli(command, versionArgs, timeoutMs);
|
|
5750
|
+
return extractVersion(`${probe.stdout}
|
|
5751
|
+
${probe.stderr}`);
|
|
5752
|
+
}
|
|
5753
|
+
var DEFAULT_PROBE_TIMEOUT_MS, CLI_OUTPUT_MAX_CHARS;
|
|
5754
|
+
var init_cliProcess = __esm({
|
|
5755
|
+
"../../server/lib/cliProcess.ts"() {
|
|
5756
|
+
init_versions();
|
|
5757
|
+
init_binaryResolver();
|
|
5758
|
+
DEFAULT_PROBE_TIMEOUT_MS = 5e3;
|
|
5759
|
+
CLI_OUTPUT_MAX_CHARS = 1e4;
|
|
5760
|
+
}
|
|
5761
|
+
});
|
|
5762
|
+
|
|
5763
|
+
// ../../server/agents/claudeExecutable.ts
|
|
5764
|
+
import { execFileSync } from "node:child_process";
|
|
5765
|
+
import { readFileSync, statSync as statSync2 } from "node:fs";
|
|
5766
|
+
import { createRequire } from "node:module";
|
|
5767
|
+
import { posix as posix2, win32 as win322 } from "node:path";
|
|
5768
|
+
function realIsFile(path) {
|
|
5769
|
+
try {
|
|
5770
|
+
return statSync2(path).isFile();
|
|
5771
|
+
} catch {
|
|
5772
|
+
return false;
|
|
5773
|
+
}
|
|
5774
|
+
}
|
|
5775
|
+
function realReadFile(path) {
|
|
5776
|
+
try {
|
|
5777
|
+
return readFileSync(path, "utf-8");
|
|
5778
|
+
} catch {
|
|
5779
|
+
return void 0;
|
|
5780
|
+
}
|
|
5781
|
+
}
|
|
5782
|
+
function binField(manifest) {
|
|
5783
|
+
let bin;
|
|
5784
|
+
try {
|
|
5785
|
+
bin = JSON.parse(manifest).bin;
|
|
5786
|
+
} catch {
|
|
5787
|
+
return void 0;
|
|
5788
|
+
}
|
|
5789
|
+
if (typeof bin === "string") return bin;
|
|
5790
|
+
if (!bin || typeof bin !== "object") return void 0;
|
|
5791
|
+
const entry = bin[BIN_NAME];
|
|
5792
|
+
return typeof entry === "string" ? entry : void 0;
|
|
5793
|
+
}
|
|
5794
|
+
function findNpmClaude(options = {}) {
|
|
5795
|
+
const platform2 = options.platform ?? process.platform;
|
|
5796
|
+
const windows = platform2 === "win32";
|
|
5797
|
+
const path = windows ? win322 : posix2;
|
|
5798
|
+
const isFile = options.isFile ?? realIsFile;
|
|
5799
|
+
const readFile22 = options.readFile ?? realReadFile;
|
|
5800
|
+
const shim = findExecutableOnPath(BIN_NAME, { platform: platform2, env: options.env, isExecutable: isFile });
|
|
5801
|
+
if (!shim) return void 0;
|
|
5802
|
+
const shimDir = path.dirname(shim);
|
|
5803
|
+
const packageDirs = [
|
|
5804
|
+
path.join(shimDir, "node_modules", NPM_PACKAGE),
|
|
5805
|
+
path.join(shimDir, "..", "lib", "node_modules", NPM_PACKAGE)
|
|
5806
|
+
];
|
|
5807
|
+
for (const packageDir of packageDirs) {
|
|
5808
|
+
const manifest = readFile22(path.join(packageDir, "package.json"));
|
|
5809
|
+
if (!manifest) continue;
|
|
5810
|
+
const relative11 = binField(manifest);
|
|
5811
|
+
if (!relative11) continue;
|
|
5812
|
+
const target = path.normalize(path.join(packageDir, relative11));
|
|
5813
|
+
if (windows && !isDirectlyLaunchable(target)) continue;
|
|
5814
|
+
if (isFile(target)) return target;
|
|
5815
|
+
}
|
|
5816
|
+
return void 0;
|
|
5817
|
+
}
|
|
5818
|
+
function findInstalledClaude() {
|
|
5819
|
+
return findExecutableOnPath(BIN_NAME, { directOnly: true });
|
|
5820
|
+
}
|
|
5821
|
+
function findBundledClaude(resolveModule2) {
|
|
5822
|
+
try {
|
|
5823
|
+
const platformPkg = `@anthropic-ai/claude-agent-sdk-${process.platform}-${process.arch}`;
|
|
5824
|
+
return resolveModule2(`${platformPkg}/package.json`).replace(/package\.json$/, CLI_BIN_NAME).replace(ASAR_SEGMENT, "$1app.asar.unpacked$2");
|
|
5825
|
+
} catch {
|
|
5826
|
+
return void 0;
|
|
5827
|
+
}
|
|
5828
|
+
}
|
|
5829
|
+
function discoverClaudeExecutables(resolveModule2, probes = {}) {
|
|
5830
|
+
return {
|
|
5831
|
+
installed: (probes.findOnPath ?? findInstalledClaude)(),
|
|
5832
|
+
npm: (probes.findNpm ?? findNpmClaude)(),
|
|
5833
|
+
bundled: findBundledClaude(resolveModule2)
|
|
5834
|
+
};
|
|
5835
|
+
}
|
|
5836
|
+
function readCliVersionSync(binPath) {
|
|
5837
|
+
try {
|
|
5838
|
+
const output = execFileSync(binPath, ["--version"], {
|
|
5839
|
+
encoding: "utf-8",
|
|
5840
|
+
timeout: 5e3,
|
|
5841
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
5842
|
+
});
|
|
5843
|
+
const match = output.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
5844
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : void 0;
|
|
5845
|
+
} catch {
|
|
5846
|
+
return void 0;
|
|
5847
|
+
}
|
|
5848
|
+
}
|
|
5849
|
+
function isAtLeast(version, floor) {
|
|
5850
|
+
for (let i = 0; i < 3; i += 1) {
|
|
5851
|
+
if (version[i] !== floor[i]) return version[i] > floor[i];
|
|
5852
|
+
}
|
|
5853
|
+
return true;
|
|
5854
|
+
}
|
|
5855
|
+
function chooseAutomatically(found, readVersion) {
|
|
5856
|
+
const bundled = found.bundled ? { source: "bundled", path: found.bundled } : void 0;
|
|
5857
|
+
if (!found.installed) return bundled;
|
|
5858
|
+
const installed = { source: "path", path: found.installed };
|
|
5859
|
+
const installedVersion = readVersion(found.installed);
|
|
5860
|
+
if (!installedVersion) return bundled ?? installed;
|
|
5861
|
+
const bundledVersion = bundled ? readVersion(bundled.path) : void 0;
|
|
5862
|
+
if (bundledVersion && !isAtLeast(installedVersion, bundledVersion)) return bundled;
|
|
5863
|
+
return installed;
|
|
5864
|
+
}
|
|
5865
|
+
function chooseClaudeExecutable(choice, found, readVersion) {
|
|
5866
|
+
switch (choice.source) {
|
|
5867
|
+
case "auto":
|
|
5868
|
+
return chooseAutomatically(found, readVersion);
|
|
5869
|
+
case "custom":
|
|
5870
|
+
return choice.path ? { source: "custom", path: choice.path } : void 0;
|
|
5871
|
+
case "path":
|
|
5872
|
+
return found.installed ? { source: "path", path: found.installed } : void 0;
|
|
5873
|
+
case "npm":
|
|
5874
|
+
return found.npm ? { source: "npm", path: found.npm } : void 0;
|
|
5875
|
+
case "bundled":
|
|
5876
|
+
return found.bundled ? { source: "bundled", path: found.bundled } : void 0;
|
|
5877
|
+
}
|
|
5878
|
+
}
|
|
5879
|
+
function configuredChoice() {
|
|
5880
|
+
return getConfig()?.agentExecutable ?? DEFAULT_EXECUTABLE_CHOICE;
|
|
5881
|
+
}
|
|
5882
|
+
function resolveClaudeExecutable() {
|
|
5883
|
+
const choice = configuredChoice();
|
|
5884
|
+
const key2 = JSON.stringify(choice);
|
|
5885
|
+
if (memo?.key !== key2) {
|
|
5886
|
+
memo = {
|
|
5887
|
+
key: key2,
|
|
5888
|
+
resolved: chooseClaudeExecutable(choice, discoverClaudeExecutables(resolveModule), readCliVersionSync)
|
|
5889
|
+
};
|
|
5890
|
+
}
|
|
5891
|
+
return memo.resolved;
|
|
5892
|
+
}
|
|
5893
|
+
function claudeCliPath() {
|
|
5894
|
+
return resolveClaudeExecutable()?.path;
|
|
5895
|
+
}
|
|
5896
|
+
async function describeClaudeExecutable() {
|
|
5897
|
+
const choice = configuredChoice();
|
|
5898
|
+
const found = discoverClaudeExecutables(resolveModule);
|
|
5899
|
+
const active = resolveClaudeExecutable();
|
|
5900
|
+
const pathBySource = {
|
|
5901
|
+
path: found.installed,
|
|
5902
|
+
npm: found.npm,
|
|
5903
|
+
bundled: found.bundled
|
|
5904
|
+
};
|
|
5905
|
+
const detected = DETECTED_EXECUTABLE_SOURCES.filter((source) => pathBySource[source] !== void 0).map((source) => ({ source, path: pathBySource[source] }));
|
|
5906
|
+
const paths = /* @__PURE__ */ new Set([...detected.map(({ path }) => path), ...active ? [active.path] : []]);
|
|
5907
|
+
const versions = new Map(
|
|
5908
|
+
await Promise.all(
|
|
5909
|
+
[...paths].map(async (path) => [path, await probeCliVersion(path, ["--version"])])
|
|
5910
|
+
)
|
|
5911
|
+
);
|
|
5912
|
+
return {
|
|
5913
|
+
choice,
|
|
5914
|
+
candidates: detected.map((candidate) => ({
|
|
5915
|
+
...candidate,
|
|
5916
|
+
version: versions.get(candidate.path) ?? null
|
|
5917
|
+
})),
|
|
5918
|
+
active: active ? { ...active, version: versions.get(active.path) ?? null } : null
|
|
5919
|
+
};
|
|
5920
|
+
}
|
|
5921
|
+
var BIN_NAME, NPM_PACKAGE, CLI_BIN_NAME, ASAR_SEGMENT, resolveModule, memo;
|
|
5922
|
+
var init_claudeExecutable = __esm({
|
|
5923
|
+
"../../server/agents/claudeExecutable.ts"() {
|
|
5924
|
+
init_agentExecutable();
|
|
5925
|
+
init_config();
|
|
5926
|
+
init_binaryResolver();
|
|
5927
|
+
init_cliProcess();
|
|
5928
|
+
BIN_NAME = "claude";
|
|
5929
|
+
NPM_PACKAGE = "@anthropic-ai/claude-code";
|
|
5930
|
+
CLI_BIN_NAME = nativeBinaryName(BIN_NAME);
|
|
5931
|
+
ASAR_SEGMENT = /([\\/])app\.asar([\\/])/;
|
|
5932
|
+
resolveModule = (id) => createRequire(import.meta.url).resolve(id);
|
|
5933
|
+
}
|
|
5934
|
+
});
|
|
5935
|
+
|
|
5622
5936
|
// ../../server/lib/streamBus.ts
|
|
5623
5937
|
function getOrCreate(sessionId) {
|
|
5624
5938
|
let state = sessions2.get(sessionId);
|
|
@@ -5887,58 +6201,6 @@ var init_streamBus = __esm({
|
|
|
5887
6201
|
|
|
5888
6202
|
// ../../server/sdk-session.ts
|
|
5889
6203
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
5890
|
-
import { execFileSync } from "node:child_process";
|
|
5891
|
-
import { createRequire } from "node:module";
|
|
5892
|
-
function findClaudeOnPath() {
|
|
5893
|
-
return findExecutableOnPath("claude", { directOnly: true });
|
|
5894
|
-
}
|
|
5895
|
-
function readCliVersion(binPath) {
|
|
5896
|
-
try {
|
|
5897
|
-
const output = execFileSync(binPath, ["--version"], {
|
|
5898
|
-
encoding: "utf-8",
|
|
5899
|
-
timeout: 5e3,
|
|
5900
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
5901
|
-
});
|
|
5902
|
-
const match = output.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
5903
|
-
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : void 0;
|
|
5904
|
-
} catch {
|
|
5905
|
-
return void 0;
|
|
5906
|
-
}
|
|
5907
|
-
}
|
|
5908
|
-
function isAtLeast(version, floor) {
|
|
5909
|
-
for (let i = 0; i < 3; i += 1) {
|
|
5910
|
-
if (version[i] !== floor[i]) return version[i] > floor[i];
|
|
5911
|
-
}
|
|
5912
|
-
return true;
|
|
5913
|
-
}
|
|
5914
|
-
function resolveClaudeCliPath(resolveModule, probes = {}) {
|
|
5915
|
-
const findOnPath = probes.findOnPath ?? findClaudeOnPath;
|
|
5916
|
-
const readVersion = probes.readVersion ?? readCliVersion;
|
|
5917
|
-
let vendored;
|
|
5918
|
-
try {
|
|
5919
|
-
const platformPkg = `@anthropic-ai/claude-agent-sdk-${process.platform}-${process.arch}`;
|
|
5920
|
-
vendored = resolveModule(`${platformPkg}/package.json`).replace(/package\.json$/, CLI_BIN_NAME);
|
|
5921
|
-
} catch {
|
|
5922
|
-
vendored = void 0;
|
|
5923
|
-
}
|
|
5924
|
-
const insideAsar = vendored !== void 0 && ASAR_SEGMENT.test(vendored);
|
|
5925
|
-
const vendoredExecutable = insideAsar ? vendored.replace(ASAR_SEGMENT, "$1app.asar.unpacked$2") : vendored;
|
|
5926
|
-
const fallback = insideAsar ? vendoredExecutable : void 0;
|
|
5927
|
-
const installed = findOnPath();
|
|
5928
|
-
if (!installed) return fallback;
|
|
5929
|
-
const installedVersion = readVersion(installed);
|
|
5930
|
-
if (!installedVersion) return vendoredExecutable ? fallback : installed;
|
|
5931
|
-
const vendoredVersion = vendoredExecutable ? readVersion(vendoredExecutable) : void 0;
|
|
5932
|
-
if (vendoredVersion && !isAtLeast(installedVersion, vendoredVersion)) return fallback;
|
|
5933
|
-
return installed;
|
|
5934
|
-
}
|
|
5935
|
-
function claudeCliPath() {
|
|
5936
|
-
if (!cliPathProbed) {
|
|
5937
|
-
cliPath = resolveClaudeCliPath((id) => createRequire(import.meta.url).resolve(id));
|
|
5938
|
-
cliPathProbed = true;
|
|
5939
|
-
}
|
|
5940
|
-
return cliPath;
|
|
5941
|
-
}
|
|
5942
6204
|
function streamingEnabled() {
|
|
5943
6205
|
const raw = process.env.COGPIT_STREAM_PARTIAL;
|
|
5944
6206
|
if (raw === void 0) return true;
|
|
@@ -5956,16 +6218,16 @@ function makeCanUseTool(state) {
|
|
|
5956
6218
|
return (toolName, input, options) => {
|
|
5957
6219
|
if (toolName === "AskUserQuestion") {
|
|
5958
6220
|
const toolUseId = options.toolUseID;
|
|
5959
|
-
return new Promise((
|
|
6221
|
+
return new Promise((resolve22) => {
|
|
5960
6222
|
const pending = {
|
|
5961
6223
|
input,
|
|
5962
6224
|
askedAt: Date.now(),
|
|
5963
|
-
resolve:
|
|
6225
|
+
resolve: resolve22
|
|
5964
6226
|
};
|
|
5965
6227
|
state.pendingUserQuestions.set(toolUseId, pending);
|
|
5966
6228
|
const onAbort = () => {
|
|
5967
6229
|
if (state.pendingUserQuestions.delete(toolUseId)) {
|
|
5968
|
-
|
|
6230
|
+
resolve22({ behavior: "deny", message: "Session aborted", interrupt: true });
|
|
5969
6231
|
}
|
|
5970
6232
|
};
|
|
5971
6233
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -5978,7 +6240,7 @@ function makeCanUseTool(state) {
|
|
|
5978
6240
|
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
5979
6241
|
}
|
|
5980
6242
|
const requestId = options.toolUseID;
|
|
5981
|
-
return new Promise((
|
|
6243
|
+
return new Promise((resolve22) => {
|
|
5982
6244
|
const pending = {
|
|
5983
6245
|
requestId,
|
|
5984
6246
|
toolName,
|
|
@@ -5991,12 +6253,12 @@ function makeCanUseTool(state) {
|
|
|
5991
6253
|
blockedPath: options.blockedPath,
|
|
5992
6254
|
suggestions: options.suggestions,
|
|
5993
6255
|
timestamp: Date.now(),
|
|
5994
|
-
resolve:
|
|
6256
|
+
resolve: resolve22
|
|
5995
6257
|
};
|
|
5996
6258
|
state.pendingPermissions.set(requestId, pending);
|
|
5997
6259
|
const onAbort = () => {
|
|
5998
6260
|
if (state.pendingPermissions.delete(requestId)) {
|
|
5999
|
-
|
|
6261
|
+
resolve22({ behavior: "deny", message: "Session aborted", interrupt: true });
|
|
6000
6262
|
}
|
|
6001
6263
|
};
|
|
6002
6264
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -6073,16 +6335,16 @@ function makeOnElicitation(state) {
|
|
|
6073
6335
|
);
|
|
6074
6336
|
return Promise.resolve({ action: "decline" });
|
|
6075
6337
|
}
|
|
6076
|
-
return new Promise((
|
|
6338
|
+
return new Promise((resolve22) => {
|
|
6077
6339
|
const requestId = options.requestId;
|
|
6078
6340
|
state.pendingElicitations.set(requestId, {
|
|
6079
6341
|
request,
|
|
6080
6342
|
fields: projection.fields,
|
|
6081
6343
|
askedAt: Date.now(),
|
|
6082
|
-
resolve:
|
|
6344
|
+
resolve: resolve22
|
|
6083
6345
|
});
|
|
6084
6346
|
const onAbort = () => {
|
|
6085
|
-
if (state.pendingElicitations.delete(requestId))
|
|
6347
|
+
if (state.pendingElicitations.delete(requestId)) resolve22({ action: "decline" });
|
|
6086
6348
|
};
|
|
6087
6349
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
6088
6350
|
});
|
|
@@ -6106,14 +6368,14 @@ function makeOnUserDialog(state) {
|
|
|
6106
6368
|
if (!(request.dialogKind in DIALOG_CHOICES)) return Promise.resolve(null);
|
|
6107
6369
|
const projected = projectUserDialog(request);
|
|
6108
6370
|
if (!projected) return Promise.resolve({ behavior: "cancelled" });
|
|
6109
|
-
return new Promise((
|
|
6371
|
+
return new Promise((resolve22) => {
|
|
6110
6372
|
const requestId = options.requestId;
|
|
6111
6373
|
state.pendingUserDialogs.set(requestId, {
|
|
6112
6374
|
dialog: { ...projected, requestId, askedAt: Date.now() },
|
|
6113
|
-
resolve:
|
|
6375
|
+
resolve: resolve22
|
|
6114
6376
|
});
|
|
6115
6377
|
const onAbort = () => {
|
|
6116
|
-
if (state.pendingUserDialogs.delete(requestId))
|
|
6378
|
+
if (state.pendingUserDialogs.delete(requestId)) resolve22({ behavior: "cancelled" });
|
|
6117
6379
|
};
|
|
6118
6380
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
6119
6381
|
});
|
|
@@ -6824,15 +7086,12 @@ function cleanupAllSDKSessions() {
|
|
|
6824
7086
|
sdkSessions.clear();
|
|
6825
7087
|
return killed;
|
|
6826
7088
|
}
|
|
6827
|
-
var
|
|
7089
|
+
var sdkSessions, REFUSAL_FALLBACK_DIALOG, DIALOG_CHOICES, SUPPORTED_DIALOG_KINDS, SDKMessageStream, EDIT_TOOL_NAMES;
|
|
6828
7090
|
var init_sdk_session = __esm({
|
|
6829
7091
|
"../../server/sdk-session.ts"() {
|
|
6830
7092
|
init_subagentWatcher();
|
|
6831
|
-
|
|
7093
|
+
init_claudeExecutable();
|
|
6832
7094
|
init_streamBus();
|
|
6833
|
-
CLI_BIN_NAME = nativeBinaryName("claude");
|
|
6834
|
-
ASAR_SEGMENT = /([\\/])app\.asar([\\/])/;
|
|
6835
|
-
cliPathProbed = false;
|
|
6836
7095
|
sdkSessions = /* @__PURE__ */ new Map();
|
|
6837
7096
|
REFUSAL_FALLBACK_DIALOG = "refusal_fallback_prompt";
|
|
6838
7097
|
DIALOG_CHOICES = {
|
|
@@ -6845,8 +7104,8 @@ var init_sdk_session = __esm({
|
|
|
6845
7104
|
closed = false;
|
|
6846
7105
|
enqueue(message) {
|
|
6847
7106
|
if (this.closed) return false;
|
|
6848
|
-
const
|
|
6849
|
-
if (
|
|
7107
|
+
const resolve22 = this.waiting.shift();
|
|
7108
|
+
if (resolve22) resolve22({ value: message, done: false });
|
|
6850
7109
|
else this.queued.push(message);
|
|
6851
7110
|
return true;
|
|
6852
7111
|
}
|
|
@@ -6854,15 +7113,15 @@ var init_sdk_session = __esm({
|
|
|
6854
7113
|
if (this.closed) return;
|
|
6855
7114
|
this.closed = true;
|
|
6856
7115
|
this.queued.length = 0;
|
|
6857
|
-
for (const
|
|
6858
|
-
|
|
7116
|
+
for (const resolve22 of this.waiting.splice(0)) {
|
|
7117
|
+
resolve22({ value: void 0, done: true });
|
|
6859
7118
|
}
|
|
6860
7119
|
}
|
|
6861
7120
|
next() {
|
|
6862
7121
|
const message = this.queued.shift();
|
|
6863
7122
|
if (message) return Promise.resolve({ value: message, done: false });
|
|
6864
7123
|
if (this.closed) return Promise.resolve({ value: void 0, done: true });
|
|
6865
|
-
return new Promise((
|
|
7124
|
+
return new Promise((resolve22) => this.waiting.push(resolve22));
|
|
6866
7125
|
}
|
|
6867
7126
|
return() {
|
|
6868
7127
|
this.close();
|
|
@@ -6998,8 +7257,8 @@ var init_agent_prompts = __esm({
|
|
|
6998
7257
|
function observeExit(proc) {
|
|
6999
7258
|
let didExit = proc.exitCode !== null && proc.exitCode !== void 0 || proc.signalCode !== null && proc.signalCode !== void 0;
|
|
7000
7259
|
let resolveExit = () => void 0;
|
|
7001
|
-
const exited = new Promise((
|
|
7002
|
-
resolveExit =
|
|
7260
|
+
const exited = new Promise((resolve22) => {
|
|
7261
|
+
resolveExit = resolve22;
|
|
7003
7262
|
});
|
|
7004
7263
|
if (didExit) resolveExit();
|
|
7005
7264
|
const markExited = () => {
|
|
@@ -7025,14 +7284,14 @@ function observeExit(proc) {
|
|
|
7025
7284
|
async function waitForExit(observers, timeoutMs, onTimeout = () => void 0) {
|
|
7026
7285
|
const pending = observers.filter((observer) => !observer.hasExited());
|
|
7027
7286
|
if (pending.length === 0) return;
|
|
7028
|
-
await new Promise((
|
|
7287
|
+
await new Promise((resolve22) => {
|
|
7029
7288
|
const timer = setTimeout(() => {
|
|
7030
7289
|
onTimeout();
|
|
7031
|
-
|
|
7290
|
+
resolve22();
|
|
7032
7291
|
}, timeoutMs);
|
|
7033
7292
|
void Promise.all(pending.map((observer) => observer.exited)).then(() => {
|
|
7034
7293
|
clearTimeout(timer);
|
|
7035
|
-
|
|
7294
|
+
resolve22();
|
|
7036
7295
|
});
|
|
7037
7296
|
});
|
|
7038
7297
|
}
|
|
@@ -7315,7 +7574,7 @@ async function readClaudeSessionMeta(filePath, head) {
|
|
|
7315
7574
|
let cwd = "";
|
|
7316
7575
|
let firstUserMessage = "";
|
|
7317
7576
|
let lastUserMessage = "";
|
|
7318
|
-
let
|
|
7577
|
+
let timestamp2 = "";
|
|
7319
7578
|
let lastTimestamp = "";
|
|
7320
7579
|
let turnCount = 0;
|
|
7321
7580
|
let aiTitle = "";
|
|
@@ -7354,8 +7613,8 @@ async function readClaudeSessionMeta(filePath, head) {
|
|
|
7354
7613
|
if (obj.type === "assistant" && obj.message?.model && !model) {
|
|
7355
7614
|
model = obj.message.model;
|
|
7356
7615
|
}
|
|
7357
|
-
if (obj.type === "user" && !obj.isMeta && !
|
|
7358
|
-
|
|
7616
|
+
if (obj.type === "user" && !obj.isMeta && !timestamp2) {
|
|
7617
|
+
timestamp2 = obj.timestamp || "";
|
|
7359
7618
|
}
|
|
7360
7619
|
if (obj.type === "user" && !obj.isMeta) {
|
|
7361
7620
|
if (obj.timestamp) lastTimestamp = obj.timestamp;
|
|
@@ -7450,8 +7709,8 @@ async function readClaudeSessionMeta(filePath, head) {
|
|
|
7450
7709
|
cwd,
|
|
7451
7710
|
firstUserMessage,
|
|
7452
7711
|
lastUserMessage,
|
|
7453
|
-
timestamp,
|
|
7454
|
-
lastTimestamp: lastTimestamp ||
|
|
7712
|
+
timestamp: timestamp2,
|
|
7713
|
+
lastTimestamp: lastTimestamp || timestamp2,
|
|
7455
7714
|
turnCount,
|
|
7456
7715
|
lineCount: isPartialRead ? Math.round(head.size / (HEAD_BYTES / lines.length)) : lines.length,
|
|
7457
7716
|
branchedFrom,
|
|
@@ -7740,7 +7999,7 @@ var init_sessionStats = __esm({
|
|
|
7740
7999
|
});
|
|
7741
8000
|
|
|
7742
8001
|
// ../../shared/session/turnContent.ts
|
|
7743
|
-
function appendAssistantText(turn, text,
|
|
8002
|
+
function appendAssistantText(turn, text, timestamp2) {
|
|
7744
8003
|
if (!text) return;
|
|
7745
8004
|
turn.assistantText.push(text);
|
|
7746
8005
|
const last = turn.contentBlocks[turn.contentBlocks.length - 1];
|
|
@@ -7748,7 +8007,7 @@ function appendAssistantText(turn, text, timestamp) {
|
|
|
7748
8007
|
last.text.push(text);
|
|
7749
8008
|
return;
|
|
7750
8009
|
}
|
|
7751
|
-
turn.contentBlocks.push({ kind: "text", text: [text], timestamp });
|
|
8010
|
+
turn.contentBlocks.push({ kind: "text", text: [text], timestamp: timestamp2 });
|
|
7752
8011
|
}
|
|
7753
8012
|
var init_turnContent = __esm({
|
|
7754
8013
|
"../../shared/session/turnContent.ts"() {
|
|
@@ -8118,7 +8377,7 @@ function resolveCodexPatchPath(filePath, cwd) {
|
|
|
8118
8377
|
const relative11 = filePath.replace(/^\.[\\/]/, "");
|
|
8119
8378
|
return /^[A-Za-z]:[\\/]/.test(cwd) ? `${base}\\${relative11.replace(/\//g, "\\")}` : `${base}/${relative11}`;
|
|
8120
8379
|
}
|
|
8121
|
-
function parseApplyPatch(patchText, callId,
|
|
8380
|
+
function parseApplyPatch(patchText, callId, timestamp2, cwd = "") {
|
|
8122
8381
|
const toolCalls = [];
|
|
8123
8382
|
const filePattern = /^\*\*\*\s+(Update File|Add File|Delete File):\s*(.+)$/gm;
|
|
8124
8383
|
const sections = [];
|
|
@@ -8161,7 +8420,7 @@ function parseApplyPatch(patchText, callId, timestamp, cwd = "") {
|
|
|
8161
8420
|
input: { file_path: filePath, content: newLines.join("\n") },
|
|
8162
8421
|
result: null,
|
|
8163
8422
|
isError: false,
|
|
8164
|
-
timestamp
|
|
8423
|
+
timestamp: timestamp2
|
|
8165
8424
|
});
|
|
8166
8425
|
} else if (section.action === "Delete File") {
|
|
8167
8426
|
toolCalls.push({
|
|
@@ -8170,7 +8429,7 @@ function parseApplyPatch(patchText, callId, timestamp, cwd = "") {
|
|
|
8170
8429
|
input: { file_path: filePath, old_string: oldLines.join("\n"), new_string: "" },
|
|
8171
8430
|
result: null,
|
|
8172
8431
|
isError: false,
|
|
8173
|
-
timestamp
|
|
8432
|
+
timestamp: timestamp2
|
|
8174
8433
|
});
|
|
8175
8434
|
} else {
|
|
8176
8435
|
toolCalls.push({
|
|
@@ -8184,18 +8443,18 @@ function parseApplyPatch(patchText, callId, timestamp, cwd = "") {
|
|
|
8184
8443
|
},
|
|
8185
8444
|
result: null,
|
|
8186
8445
|
isError: false,
|
|
8187
|
-
timestamp
|
|
8446
|
+
timestamp: timestamp2
|
|
8188
8447
|
});
|
|
8189
8448
|
}
|
|
8190
8449
|
}
|
|
8191
8450
|
return toolCalls;
|
|
8192
8451
|
}
|
|
8193
|
-
function parseCodexToolPatches(toolName, rawInput, callId,
|
|
8452
|
+
function parseCodexToolPatches(toolName, rawInput, callId, timestamp2, cwd = "") {
|
|
8194
8453
|
if (toolName === "apply_patch") {
|
|
8195
|
-
return parseApplyPatch(rawInput, callId,
|
|
8454
|
+
return parseApplyPatch(rawInput, callId, timestamp2, cwd);
|
|
8196
8455
|
}
|
|
8197
8456
|
return extractApplyPatchInputs(rawInput).flatMap(
|
|
8198
|
-
(patch, patchIndex) => parseApplyPatch(patch, `${callId}:patch-${patchIndex}`,
|
|
8457
|
+
(patch, patchIndex) => parseApplyPatch(patch, `${callId}:patch-${patchIndex}`, timestamp2, cwd)
|
|
8199
8458
|
);
|
|
8200
8459
|
}
|
|
8201
8460
|
function findFailedNestedPatchCallIds(output, wrapperIsError, calls) {
|
|
@@ -8320,9 +8579,9 @@ function safeParseLine(line) {
|
|
|
8320
8579
|
function isObject2(value) {
|
|
8321
8580
|
return typeof value === "object" && value !== null;
|
|
8322
8581
|
}
|
|
8323
|
-
function isCodexRecord(
|
|
8324
|
-
if (!
|
|
8325
|
-
return
|
|
8582
|
+
function isCodexRecord(record4) {
|
|
8583
|
+
if (!record4 || typeof record4.type !== "string") return false;
|
|
8584
|
+
return record4.type === "session_meta" || record4.type === "turn_context" || record4.type === "event_msg" || record4.type === "response_item" || record4.type === "inter_agent_communication_metadata" || record4.type === "compacted" || record4.type === "world_state";
|
|
8326
8585
|
}
|
|
8327
8586
|
function extractMessageText(payload, blockType) {
|
|
8328
8587
|
const content = payload?.content;
|
|
@@ -8439,7 +8698,7 @@ function parseTokenUsage(value) {
|
|
|
8439
8698
|
cache_read_input_tokens: cacheRead
|
|
8440
8699
|
};
|
|
8441
8700
|
}
|
|
8442
|
-
function appendThinking(turn, text,
|
|
8701
|
+
function appendThinking(turn, text, timestamp2) {
|
|
8443
8702
|
if (!text) return;
|
|
8444
8703
|
const block = { type: "thinking", thinking: text, signature: "" };
|
|
8445
8704
|
turn.thinking.push(block);
|
|
@@ -8448,16 +8707,16 @@ function appendThinking(turn, text, timestamp) {
|
|
|
8448
8707
|
last.blocks.push(block);
|
|
8449
8708
|
return;
|
|
8450
8709
|
}
|
|
8451
|
-
turn.contentBlocks.push({ kind: "thinking", blocks: [block], timestamp });
|
|
8710
|
+
turn.contentBlocks.push({ kind: "thinking", blocks: [block], timestamp: timestamp2 });
|
|
8452
8711
|
}
|
|
8453
|
-
function appendToolCall(turn, toolCall,
|
|
8712
|
+
function appendToolCall(turn, toolCall, timestamp2) {
|
|
8454
8713
|
turn.toolCalls.push(toolCall);
|
|
8455
8714
|
const last = turn.contentBlocks[turn.contentBlocks.length - 1];
|
|
8456
|
-
if (last && last.kind === "tool_calls" && last.timestamp ===
|
|
8715
|
+
if (last && last.kind === "tool_calls" && last.timestamp === timestamp2) {
|
|
8457
8716
|
last.toolCalls.push(toolCall);
|
|
8458
8717
|
return;
|
|
8459
8718
|
}
|
|
8460
|
-
turn.contentBlocks.push({ kind: "tool_calls", toolCalls: [toolCall], timestamp });
|
|
8719
|
+
turn.contentBlocks.push({ kind: "tool_calls", toolCalls: [toolCall], timestamp: timestamp2 });
|
|
8461
8720
|
}
|
|
8462
8721
|
function finalizeTurn(turns, current, lastTimestamp) {
|
|
8463
8722
|
if (!current) return null;
|
|
@@ -8508,37 +8767,37 @@ function parseMcpEventResult(value) {
|
|
|
8508
8767
|
isError: ok.isError === true || parsedContent.isError
|
|
8509
8768
|
};
|
|
8510
8769
|
}
|
|
8511
|
-
function createTurn(turnId,
|
|
8770
|
+
function createTurn(turnId, timestamp2, model) {
|
|
8512
8771
|
return {
|
|
8513
|
-
id: turnId ? `${turnId}@${
|
|
8772
|
+
id: turnId ? `${turnId}@${timestamp2}` : randomTurnId("codex-turn"),
|
|
8514
8773
|
userMessage: null,
|
|
8515
8774
|
contentBlocks: [],
|
|
8516
8775
|
thinking: [],
|
|
8517
8776
|
assistantText: [],
|
|
8518
8777
|
toolCalls: [],
|
|
8519
8778
|
subAgentActivity: [],
|
|
8520
|
-
timestamp,
|
|
8779
|
+
timestamp: timestamp2,
|
|
8521
8780
|
durationMs: null,
|
|
8522
8781
|
tokenUsage: null,
|
|
8523
8782
|
model
|
|
8524
8783
|
};
|
|
8525
8784
|
}
|
|
8526
|
-
function extractPromptFromRecord(
|
|
8527
|
-
if (
|
|
8528
|
-
return normalizePromptText(
|
|
8785
|
+
function extractPromptFromRecord(record4) {
|
|
8786
|
+
if (record4.type === "event_msg" && isObject2(record4.payload) && record4.payload.type === "user_message" && typeof record4.payload.message === "string") {
|
|
8787
|
+
return normalizePromptText(record4.payload.message);
|
|
8529
8788
|
}
|
|
8530
|
-
if (
|
|
8531
|
-
return normalizePromptText(extractMessageText(
|
|
8789
|
+
if (record4.type === "response_item" && isObject2(record4.payload) && record4.payload.type === "message" && record4.payload.role === "user") {
|
|
8790
|
+
return normalizePromptText(extractMessageText(record4.payload, "input_text"));
|
|
8532
8791
|
}
|
|
8533
8792
|
return "";
|
|
8534
8793
|
}
|
|
8535
|
-
function recordOpensTurn(
|
|
8536
|
-
if (
|
|
8537
|
-
if (
|
|
8538
|
-
if (
|
|
8794
|
+
function recordOpensTurn(record4, payload) {
|
|
8795
|
+
if (record4.type === "session_meta") return false;
|
|
8796
|
+
if (record4.type === "event_msg" && payload?.type === "task_started") return false;
|
|
8797
|
+
if (record4.type === "response_item" && payload?.type === "message") {
|
|
8539
8798
|
if (payload.role === "developer" || payload.role === "system") return false;
|
|
8540
8799
|
if (payload.role === "user") {
|
|
8541
|
-
return extractPromptFromRecord(
|
|
8800
|
+
return extractPromptFromRecord(record4) !== "" || extractResponseMessageImages(payload).length > 0 || extractResponseMessageAudio(payload).length > 0;
|
|
8542
8801
|
}
|
|
8543
8802
|
}
|
|
8544
8803
|
return true;
|
|
@@ -8552,29 +8811,29 @@ function extractMetadataFromRecords(records) {
|
|
|
8552
8811
|
let branchedFrom;
|
|
8553
8812
|
let firstUserMessage = "";
|
|
8554
8813
|
let lastUserMessage = "";
|
|
8555
|
-
let
|
|
8814
|
+
let timestamp2 = "";
|
|
8556
8815
|
let lastTimestamp = "";
|
|
8557
8816
|
let turnCount = 0;
|
|
8558
8817
|
let isSubagent = false;
|
|
8559
8818
|
let parentSessionId = null;
|
|
8560
8819
|
let agentPath = "/root";
|
|
8561
8820
|
let previousPrompt = "";
|
|
8562
|
-
for (const
|
|
8563
|
-
if (!isObject2(
|
|
8564
|
-
if (
|
|
8565
|
-
sessionId ||= typeof
|
|
8566
|
-
version ||= typeof
|
|
8567
|
-
cwd ||= typeof
|
|
8568
|
-
if (!branchedFrom && isObject2(
|
|
8569
|
-
const sourceId = typeof
|
|
8821
|
+
for (const record4 of records) {
|
|
8822
|
+
if (!isObject2(record4.payload)) continue;
|
|
8823
|
+
if (record4.type === "session_meta") {
|
|
8824
|
+
sessionId ||= typeof record4.payload.id === "string" ? record4.payload.id : "";
|
|
8825
|
+
version ||= typeof record4.payload.cli_version === "string" ? record4.payload.cli_version : "";
|
|
8826
|
+
cwd ||= typeof record4.payload.cwd === "string" ? record4.payload.cwd : "";
|
|
8827
|
+
if (!branchedFrom && isObject2(record4.payload.branchedFrom)) {
|
|
8828
|
+
const sourceId = typeof record4.payload.branchedFrom.sessionId === "string" ? record4.payload.branchedFrom.sessionId : "";
|
|
8570
8829
|
if (sourceId) {
|
|
8571
8830
|
branchedFrom = {
|
|
8572
8831
|
sessionId: sourceId,
|
|
8573
|
-
turnIndex: typeof
|
|
8832
|
+
turnIndex: typeof record4.payload.branchedFrom.turnIndex === "number" ? record4.payload.branchedFrom.turnIndex : null
|
|
8574
8833
|
};
|
|
8575
8834
|
}
|
|
8576
8835
|
}
|
|
8577
|
-
const source = isObject2(
|
|
8836
|
+
const source = isObject2(record4.payload.source) ? record4.payload.source : null;
|
|
8578
8837
|
if (source && isObject2(source.subagent)) {
|
|
8579
8838
|
isSubagent = true;
|
|
8580
8839
|
const threadSpawn = isObject2(source.subagent.thread_spawn) ? source.subagent.thread_spawn : null;
|
|
@@ -8582,27 +8841,27 @@ function extractMetadataFromRecords(records) {
|
|
|
8582
8841
|
agentPath = threadSpawn.agent_path;
|
|
8583
8842
|
}
|
|
8584
8843
|
}
|
|
8585
|
-
if (typeof
|
|
8586
|
-
parentSessionId =
|
|
8844
|
+
if (typeof record4.payload.forked_from_id === "string" && record4.payload.forked_from_id) {
|
|
8845
|
+
parentSessionId = record4.payload.forked_from_id;
|
|
8587
8846
|
}
|
|
8588
|
-
const git = isObject2(
|
|
8847
|
+
const git = isObject2(record4.payload.git) ? record4.payload.git : null;
|
|
8589
8848
|
gitBranch ||= git && typeof git.branch === "string" ? git.branch : "";
|
|
8590
8849
|
}
|
|
8591
|
-
if (
|
|
8592
|
-
model ||= typeof
|
|
8593
|
-
cwd ||= typeof
|
|
8850
|
+
if (record4.type === "turn_context") {
|
|
8851
|
+
model ||= typeof record4.payload.model === "string" ? record4.payload.model : "";
|
|
8852
|
+
cwd ||= typeof record4.payload.cwd === "string" ? record4.payload.cwd : "";
|
|
8594
8853
|
}
|
|
8595
|
-
const prompt = extractPromptFromRecord(
|
|
8854
|
+
const prompt = extractPromptFromRecord(record4);
|
|
8596
8855
|
if (!prompt) continue;
|
|
8597
8856
|
if (prompt === previousPrompt) continue;
|
|
8598
8857
|
if (!firstUserMessage) firstUserMessage = prompt;
|
|
8599
8858
|
lastUserMessage = prompt;
|
|
8600
8859
|
previousPrompt = prompt;
|
|
8601
8860
|
turnCount++;
|
|
8602
|
-
if (!
|
|
8603
|
-
lastTimestamp =
|
|
8861
|
+
if (!timestamp2) timestamp2 = record4.timestamp ?? "";
|
|
8862
|
+
lastTimestamp = record4.timestamp ?? lastTimestamp;
|
|
8604
8863
|
}
|
|
8605
|
-
if (lastTimestamp === "") lastTimestamp =
|
|
8864
|
+
if (lastTimestamp === "") lastTimestamp = timestamp2;
|
|
8606
8865
|
return {
|
|
8607
8866
|
sessionId,
|
|
8608
8867
|
version,
|
|
@@ -8614,7 +8873,7 @@ function extractMetadataFromRecords(records) {
|
|
|
8614
8873
|
branchedFrom,
|
|
8615
8874
|
firstUserMessage,
|
|
8616
8875
|
lastUserMessage,
|
|
8617
|
-
timestamp,
|
|
8876
|
+
timestamp: timestamp2,
|
|
8618
8877
|
lastTimestamp,
|
|
8619
8878
|
turnCount,
|
|
8620
8879
|
isSubagent,
|
|
@@ -8727,8 +8986,8 @@ function walkCodexRecords(records, options) {
|
|
|
8727
8986
|
pendingTurnStart = null;
|
|
8728
8987
|
return result;
|
|
8729
8988
|
}
|
|
8730
|
-
function createActiveTurn(turnId,
|
|
8731
|
-
const turn = createTurn(turnId,
|
|
8989
|
+
function createActiveTurn(turnId, timestamp2, model) {
|
|
8990
|
+
const turn = createTurn(turnId, timestamp2, model);
|
|
8732
8991
|
pendingTurnStart = pendingContextIndex ?? recordIndex;
|
|
8733
8992
|
pendingContextIndex = null;
|
|
8734
8993
|
if (!sawTurnStart) turn.isFragment = true;
|
|
@@ -8738,7 +8997,7 @@ function walkCodexRecords(records, options) {
|
|
|
8738
8997
|
}
|
|
8739
8998
|
return turn;
|
|
8740
8999
|
}
|
|
8741
|
-
function upsertWebSearchCall(targetTurn, id, input, status,
|
|
9000
|
+
function upsertWebSearchCall(targetTurn, id, input, status, timestamp2) {
|
|
8742
9001
|
const existing = webSearchCalls.get(id);
|
|
8743
9002
|
if (existing) {
|
|
8744
9003
|
existing.input = { ...existing.input, ...input };
|
|
@@ -8752,39 +9011,39 @@ function walkCodexRecords(records, options) {
|
|
|
8752
9011
|
input,
|
|
8753
9012
|
result: status,
|
|
8754
9013
|
isError: status === "failed",
|
|
8755
|
-
timestamp
|
|
9014
|
+
timestamp: timestamp2
|
|
8756
9015
|
};
|
|
8757
9016
|
webSearchCalls.set(id, toolCall);
|
|
8758
|
-
appendToolCall(targetTurn, toolCall,
|
|
9017
|
+
appendToolCall(targetTurn, toolCall, timestamp2);
|
|
8759
9018
|
}
|
|
8760
9019
|
for (let index = 0; index < records.length; index++) {
|
|
8761
|
-
const
|
|
8762
|
-
if (!isCodexRecord(
|
|
9020
|
+
const record4 = records[index];
|
|
9021
|
+
if (!isCodexRecord(record4)) continue;
|
|
8763
9022
|
recordIndex = index;
|
|
8764
|
-
const payload = isObject2(
|
|
8765
|
-
const
|
|
8766
|
-
if (
|
|
9023
|
+
const payload = isObject2(record4.payload) ? record4.payload : void 0;
|
|
9024
|
+
const timestamp2 = record4.timestamp ?? "";
|
|
9025
|
+
if (record4.type === "compacted") {
|
|
8767
9026
|
current = commitTurn(current);
|
|
8768
9027
|
pendingCompaction = "Conversation compacted";
|
|
8769
|
-
lastTurnTimestamp =
|
|
9028
|
+
lastTurnTimestamp = timestamp2;
|
|
8770
9029
|
continue;
|
|
8771
9030
|
}
|
|
8772
|
-
if (
|
|
8773
|
-
if (
|
|
9031
|
+
if (record4.type === "world_state") continue;
|
|
9032
|
+
if (record4.type === "turn_context") {
|
|
8774
9033
|
current = commitTurn(current);
|
|
8775
9034
|
pendingContextIndex = index;
|
|
8776
9035
|
currentTurnId = typeof payload?.turn_id === "string" ? payload.turn_id : null;
|
|
8777
9036
|
currentModel = typeof payload?.model === "string" ? payload.model : currentModel;
|
|
8778
|
-
lastTurnTimestamp =
|
|
9037
|
+
lastTurnTimestamp = timestamp2;
|
|
8779
9038
|
sawTurnStart = true;
|
|
8780
9039
|
continue;
|
|
8781
9040
|
}
|
|
8782
|
-
if (
|
|
9041
|
+
if (record4.type === "event_msg" && payload?.type === "user_message" && typeof payload.message === "string") {
|
|
8783
9042
|
if (current && (current.assistantText.length > 0 || current.toolCalls.length > 0 || current.thinking.length > 0)) {
|
|
8784
9043
|
current = commitTurn(current);
|
|
8785
9044
|
}
|
|
8786
9045
|
sawTurnStart = true;
|
|
8787
|
-
current ??= createActiveTurn(currentTurnId,
|
|
9046
|
+
current ??= createActiveTurn(currentTurnId, timestamp2, currentModel);
|
|
8788
9047
|
const localImages = (Array.isArray(payload.local_images) ? payload.local_images : []).filter(
|
|
8789
9048
|
(p) => typeof p === "string" && p.length > 0
|
|
8790
9049
|
);
|
|
@@ -8799,16 +9058,16 @@ function walkCodexRecords(records, options) {
|
|
|
8799
9058
|
localAudio
|
|
8800
9059
|
);
|
|
8801
9060
|
current.isFragment = false;
|
|
8802
|
-
current.timestamp = current.timestamp ||
|
|
8803
|
-
lastTurnTimestamp =
|
|
9061
|
+
current.timestamp = current.timestamp || timestamp2;
|
|
9062
|
+
lastTurnTimestamp = timestamp2;
|
|
8804
9063
|
continue;
|
|
8805
9064
|
}
|
|
8806
|
-
if (!current && !recordOpensTurn(
|
|
8807
|
-
current ??= createActiveTurn(currentTurnId,
|
|
9065
|
+
if (!current && !recordOpensTurn(record4, payload)) continue;
|
|
9066
|
+
current ??= createActiveTurn(currentTurnId, timestamp2, currentModel);
|
|
8808
9067
|
if (!current.model && currentModel) current.model = currentModel;
|
|
8809
|
-
if (!current.timestamp) current.timestamp =
|
|
8810
|
-
if (
|
|
8811
|
-
if (
|
|
9068
|
+
if (!current.timestamp) current.timestamp = timestamp2;
|
|
9069
|
+
if (timestamp2) lastTurnTimestamp = timestamp2;
|
|
9070
|
+
if (record4.type === "event_msg" && payload?.type === "token_count") {
|
|
8812
9071
|
const info = isObject2(payload.info) ? payload.info : null;
|
|
8813
9072
|
const lastUsage = info ? parseTokenUsage(info.last_token_usage) : null;
|
|
8814
9073
|
if (lastUsage) {
|
|
@@ -8816,14 +9075,14 @@ function walkCodexRecords(records, options) {
|
|
|
8816
9075
|
}
|
|
8817
9076
|
continue;
|
|
8818
9077
|
}
|
|
8819
|
-
if (
|
|
9078
|
+
if (record4.type === "event_msg" && payload?.type === "web_search_end" && typeof payload.call_id === "string") {
|
|
8820
9079
|
const input = {};
|
|
8821
9080
|
if (typeof payload.query === "string" && payload.query) input.query = payload.query;
|
|
8822
9081
|
if (isObject2(payload.action)) input.action = payload.action;
|
|
8823
|
-
upsertWebSearchCall(current, payload.call_id, input, "completed",
|
|
9082
|
+
upsertWebSearchCall(current, payload.call_id, input, "completed", timestamp2);
|
|
8824
9083
|
continue;
|
|
8825
9084
|
}
|
|
8826
|
-
if (
|
|
9085
|
+
if (record4.type === "event_msg" && payload?.type === "mcp_tool_call_end" && typeof payload.call_id === "string" && isObject2(payload.invocation)) {
|
|
8827
9086
|
const invocation = payload.invocation;
|
|
8828
9087
|
const server = typeof invocation.server === "string" ? invocation.server : "mcp";
|
|
8829
9088
|
const tool = typeof invocation.tool === "string" ? invocation.tool : "tool";
|
|
@@ -8841,12 +9100,12 @@ function walkCodexRecords(records, options) {
|
|
|
8841
9100
|
input,
|
|
8842
9101
|
result: result.text,
|
|
8843
9102
|
isError: result.isError,
|
|
8844
|
-
timestamp
|
|
8845
|
-
},
|
|
9103
|
+
timestamp: timestamp2
|
|
9104
|
+
}, timestamp2);
|
|
8846
9105
|
}
|
|
8847
9106
|
continue;
|
|
8848
9107
|
}
|
|
8849
|
-
if (
|
|
9108
|
+
if (record4.type === "event_msg" && payload?.type === "sub_agent_activity" && typeof payload.agent_thread_id === "string" && typeof payload.agent_path === "string") {
|
|
8850
9109
|
const agentId = payload.agent_thread_id;
|
|
8851
9110
|
const eventId2 = typeof payload.event_id === "string" ? payload.event_id : "";
|
|
8852
9111
|
const kind = typeof payload.kind === "string" ? payload.kind : "started";
|
|
@@ -8870,24 +9129,24 @@ function walkCodexRecords(records, options) {
|
|
|
8870
9129
|
message: existing?.message ?? spawnInfo?.message ?? "",
|
|
8871
9130
|
model: existing?.model ?? spawnInfo?.model ?? null,
|
|
8872
9131
|
agentType: existing?.agentType ?? spawnInfo?.agentType ?? null,
|
|
8873
|
-
timestamp: existing?.timestamp ?? (
|
|
9132
|
+
timestamp: existing?.timestamp ?? (timestamp2 || spawnInfo?.timestamp || ""),
|
|
8874
9133
|
parentToolCallId: existing?.parentToolCallId ?? eventId2
|
|
8875
9134
|
};
|
|
8876
9135
|
agentRegistry.set(agentId, info);
|
|
8877
9136
|
agentIdByPath.set(payload.agent_path, agentId);
|
|
8878
9137
|
if (eventId2 && (kind === "started" || spawnInfo)) agentIdBySpawnCall.set(eventId2, agentId);
|
|
8879
9138
|
const status = kind === "interrupted" ? "interrupted" : "running";
|
|
8880
|
-
upsertAgentMessage(agentId, current,
|
|
9139
|
+
upsertAgentMessage(agentId, current, timestamp2, { status });
|
|
8881
9140
|
continue;
|
|
8882
9141
|
}
|
|
8883
|
-
if (
|
|
9142
|
+
if (record4.type !== "response_item" || !payload) continue;
|
|
8884
9143
|
if (payload.type === "reasoning") {
|
|
8885
9144
|
const summary = Array.isArray(payload.summary) ? payload.summary.filter((item) => typeof item === "string").join("\n") : "";
|
|
8886
|
-
appendThinking(current, summary.trim(),
|
|
9145
|
+
appendThinking(current, summary.trim(), timestamp2);
|
|
8887
9146
|
continue;
|
|
8888
9147
|
}
|
|
8889
9148
|
if (payload.type === "message" && payload.role === "assistant") {
|
|
8890
|
-
appendAssistantText(current, extractMessageText(payload, "output_text"),
|
|
9149
|
+
appendAssistantText(current, extractMessageText(payload, "output_text"), timestamp2);
|
|
8891
9150
|
continue;
|
|
8892
9151
|
}
|
|
8893
9152
|
if (payload.type === "message" && payload.role === "user" && current.userMessage === null) {
|
|
@@ -8905,7 +9164,7 @@ function walkCodexRecords(records, options) {
|
|
|
8905
9164
|
const input = {};
|
|
8906
9165
|
if (isObject2(payload.action)) input.action = payload.action;
|
|
8907
9166
|
const status = typeof payload.status === "string" ? payload.status : "completed";
|
|
8908
|
-
upsertWebSearchCall(current, payload.id, input, status,
|
|
9167
|
+
upsertWebSearchCall(current, payload.id, input, status, timestamp2);
|
|
8909
9168
|
continue;
|
|
8910
9169
|
}
|
|
8911
9170
|
if (payload.type === "tool_search_call") {
|
|
@@ -8917,10 +9176,10 @@ function walkCodexRecords(records, options) {
|
|
|
8917
9176
|
input: isObject2(payload.arguments) ? payload.arguments : {},
|
|
8918
9177
|
result: null,
|
|
8919
9178
|
isError: false,
|
|
8920
|
-
timestamp
|
|
9179
|
+
timestamp: timestamp2
|
|
8921
9180
|
};
|
|
8922
9181
|
pendingToolCalls.set(callId, toolCall);
|
|
8923
|
-
appendToolCall(current, toolCall,
|
|
9182
|
+
appendToolCall(current, toolCall, timestamp2);
|
|
8924
9183
|
}
|
|
8925
9184
|
continue;
|
|
8926
9185
|
}
|
|
@@ -8954,7 +9213,7 @@ function walkCodexRecords(records, options) {
|
|
|
8954
9213
|
message: "",
|
|
8955
9214
|
model: null,
|
|
8956
9215
|
agentType: null,
|
|
8957
|
-
timestamp,
|
|
9216
|
+
timestamp: timestamp2,
|
|
8958
9217
|
parentToolCallId: ""
|
|
8959
9218
|
});
|
|
8960
9219
|
agentIdByPath.set(author, agentId);
|
|
@@ -8964,7 +9223,7 @@ function walkCodexRecords(records, options) {
|
|
|
8964
9223
|
else if (interAgentMessage.messageType === "ERROR" || interAgentMessage.messageType === "FAILED") status = "failed";
|
|
8965
9224
|
else if (interAgentMessage.messageType === "INTERRUPTED") status = "interrupted";
|
|
8966
9225
|
else if (interAgentMessage.messageType === "MESSAGE") status = "running";
|
|
8967
|
-
upsertAgentMessage(agentId, current,
|
|
9226
|
+
upsertAgentMessage(agentId, current, timestamp2, {
|
|
8968
9227
|
status,
|
|
8969
9228
|
text: interAgentMessage.text || void 0
|
|
8970
9229
|
});
|
|
@@ -8989,7 +9248,7 @@ function walkCodexRecords(records, options) {
|
|
|
8989
9248
|
taskName: typeof parsedInput.task_name === "string" ? parsedInput.task_name : null,
|
|
8990
9249
|
model: typeof parsedInput.model === "string" ? parsedInput.model : null,
|
|
8991
9250
|
agentType: typeof parsedInput.agent_type === "string" ? parsedInput.agent_type : null,
|
|
8992
|
-
timestamp
|
|
9251
|
+
timestamp: timestamp2
|
|
8993
9252
|
});
|
|
8994
9253
|
}
|
|
8995
9254
|
const toolCall = {
|
|
@@ -8998,10 +9257,10 @@ function walkCodexRecords(records, options) {
|
|
|
8998
9257
|
input,
|
|
8999
9258
|
result: null,
|
|
9000
9259
|
isError: false,
|
|
9001
|
-
timestamp
|
|
9260
|
+
timestamp: timestamp2
|
|
9002
9261
|
};
|
|
9003
9262
|
pendingToolCalls.set(toolCall.id, toolCall);
|
|
9004
|
-
appendToolCall(current, toolCall,
|
|
9263
|
+
appendToolCall(current, toolCall, timestamp2);
|
|
9005
9264
|
continue;
|
|
9006
9265
|
}
|
|
9007
9266
|
if (payload.type === "function_call_output" && typeof payload.call_id === "string") {
|
|
@@ -9027,13 +9286,13 @@ function walkCodexRecords(records, options) {
|
|
|
9027
9286
|
message: existing?.message ?? spawnInfo?.message ?? "",
|
|
9028
9287
|
model: existing?.model ?? spawnInfo?.model ?? null,
|
|
9029
9288
|
agentType: existing?.agentType ?? spawnInfo?.agentType ?? null,
|
|
9030
|
-
timestamp: existing?.timestamp ?? spawnInfo?.timestamp ??
|
|
9289
|
+
timestamp: existing?.timestamp ?? spawnInfo?.timestamp ?? timestamp2,
|
|
9031
9290
|
parentToolCallId: existing?.parentToolCallId ?? toolCall.id
|
|
9032
9291
|
};
|
|
9033
9292
|
agentRegistry.set(agentId, info);
|
|
9034
9293
|
agentIdBySpawnCall.set(toolCall.id, agentId);
|
|
9035
9294
|
if (info.agentPath) agentIdByPath.set(info.agentPath, agentId);
|
|
9036
|
-
upsertAgentMessage(agentId, current,
|
|
9295
|
+
upsertAgentMessage(agentId, current, timestamp2, { status: "running" });
|
|
9037
9296
|
}
|
|
9038
9297
|
} catch {
|
|
9039
9298
|
}
|
|
@@ -9056,11 +9315,11 @@ function walkCodexRecords(records, options) {
|
|
|
9056
9315
|
message: "",
|
|
9057
9316
|
model: null,
|
|
9058
9317
|
agentType: null,
|
|
9059
|
-
timestamp,
|
|
9318
|
+
timestamp: timestamp2,
|
|
9060
9319
|
parentToolCallId: ""
|
|
9061
9320
|
});
|
|
9062
9321
|
}
|
|
9063
|
-
upsertAgentMessage(agentId, current,
|
|
9322
|
+
upsertAgentMessage(agentId, current, timestamp2, {
|
|
9064
9323
|
status: lifecycle,
|
|
9065
9324
|
text: completedText || failedText || interruptedText || void 0
|
|
9066
9325
|
});
|
|
@@ -9074,7 +9333,7 @@ function walkCodexRecords(records, options) {
|
|
|
9074
9333
|
const name = typeof payload.name === "string" ? payload.name : "tool";
|
|
9075
9334
|
const rawInput = typeof payload.input === "string" ? payload.input : "";
|
|
9076
9335
|
const callId = payload.call_id;
|
|
9077
|
-
const perFileCalls = rawInput ? parseCodexToolPatches(name, rawInput, callId,
|
|
9336
|
+
const perFileCalls = rawInput ? parseCodexToolPatches(name, rawInput, callId, timestamp2, metadata.cwd) : [];
|
|
9078
9337
|
if (name !== "apply_patch") {
|
|
9079
9338
|
const toolCall = {
|
|
9080
9339
|
id: callId,
|
|
@@ -9082,14 +9341,14 @@ function walkCodexRecords(records, options) {
|
|
|
9082
9341
|
input: parseToolInput(rawInput),
|
|
9083
9342
|
result: null,
|
|
9084
9343
|
isError: false,
|
|
9085
|
-
timestamp
|
|
9344
|
+
timestamp: timestamp2
|
|
9086
9345
|
};
|
|
9087
9346
|
pendingToolCalls.set(toolCall.id, toolCall);
|
|
9088
|
-
appendToolCall(current, toolCall,
|
|
9347
|
+
appendToolCall(current, toolCall, timestamp2);
|
|
9089
9348
|
}
|
|
9090
9349
|
for (const tc of perFileCalls) {
|
|
9091
9350
|
pendingToolCalls.set(tc.id, tc);
|
|
9092
|
-
appendToolCall(current, tc,
|
|
9351
|
+
appendToolCall(current, tc, timestamp2);
|
|
9093
9352
|
}
|
|
9094
9353
|
if (perFileCalls.length > 0) {
|
|
9095
9354
|
patchCallIds.set(callId, {
|
|
@@ -9150,7 +9409,7 @@ function parseCodexSession(jsonlText, options) {
|
|
|
9150
9409
|
return session;
|
|
9151
9410
|
}
|
|
9152
9411
|
function appendCodexSession(existing, newJsonlText) {
|
|
9153
|
-
const prefix = existing.rawMessages.map((
|
|
9412
|
+
const prefix = existing.rawMessages.map((record4) => JSON.stringify(record4)).join("\n");
|
|
9154
9413
|
return parseCodexSession(prefix ? `${prefix}
|
|
9155
9414
|
${newJsonlText}` : newJsonlText);
|
|
9156
9415
|
}
|
|
@@ -9345,16 +9604,16 @@ async function readCodexSessionIdentity(filePath) {
|
|
|
9345
9604
|
let parentSessionId = null;
|
|
9346
9605
|
let sawSessionMeta = false;
|
|
9347
9606
|
for (const line of await readHeadLines(filePath, HEAD_BYTES)) {
|
|
9348
|
-
let
|
|
9607
|
+
let record4;
|
|
9349
9608
|
try {
|
|
9350
|
-
|
|
9609
|
+
record4 = JSON.parse(line);
|
|
9351
9610
|
} catch {
|
|
9352
9611
|
continue;
|
|
9353
9612
|
}
|
|
9354
|
-
if (!isRecord2(
|
|
9355
|
-
if (
|
|
9613
|
+
if (!isRecord2(record4) || !isRecord2(record4.payload)) continue;
|
|
9614
|
+
if (record4.type === "session_meta") {
|
|
9356
9615
|
sawSessionMeta = true;
|
|
9357
|
-
const payload =
|
|
9616
|
+
const payload = record4.payload;
|
|
9358
9617
|
if (!sessionId && typeof payload.id === "string") sessionId = payload.id;
|
|
9359
9618
|
if (!cwd && typeof payload.cwd === "string") cwd = payload.cwd;
|
|
9360
9619
|
if (!parentSessionId && typeof payload.forked_from_id === "string") {
|
|
@@ -9364,8 +9623,8 @@ async function readCodexSessionIdentity(filePath) {
|
|
|
9364
9623
|
if (source && isRecord2(source.subagent)) isSubagent = true;
|
|
9365
9624
|
const git = isRecord2(payload.git) ? payload.git : null;
|
|
9366
9625
|
if (!gitBranch && git && typeof git.branch === "string") gitBranch = git.branch;
|
|
9367
|
-
} else if (
|
|
9368
|
-
if (!cwd && typeof
|
|
9626
|
+
} else if (record4.type === "turn_context") {
|
|
9627
|
+
if (!cwd && typeof record4.payload.cwd === "string") cwd = record4.payload.cwd;
|
|
9369
9628
|
}
|
|
9370
9629
|
}
|
|
9371
9630
|
if (!sawSessionMeta || !cwd) return null;
|
|
@@ -9688,8 +9947,8 @@ function extractMetadata(events) {
|
|
|
9688
9947
|
for (const event of events) {
|
|
9689
9948
|
if (!isRootEvent(event)) continue;
|
|
9690
9949
|
const { data } = event;
|
|
9691
|
-
const
|
|
9692
|
-
if (
|
|
9950
|
+
const timestamp2 = eventTimestamp(event);
|
|
9951
|
+
if (timestamp2) metadata.lastTimestamp = timestamp2;
|
|
9693
9952
|
if (event.type === "session.start") {
|
|
9694
9953
|
metadata.sessionId ||= readString(data.sessionId);
|
|
9695
9954
|
metadata.version ||= readString(data.copilotVersion) || (typeof data.version === "number" ? String(data.version) : readString(data.version));
|
|
@@ -9727,7 +9986,7 @@ function extractMetadata(events) {
|
|
|
9727
9986
|
}
|
|
9728
9987
|
if (event.type !== "user.message") continue;
|
|
9729
9988
|
metadata.turnCount++;
|
|
9730
|
-
metadata.timestamp ||=
|
|
9989
|
+
metadata.timestamp ||= timestamp2;
|
|
9731
9990
|
const content = readString(data.content).trim();
|
|
9732
9991
|
if (!content) continue;
|
|
9733
9992
|
metadata.firstUserMessage ||= content;
|
|
@@ -9951,7 +10210,7 @@ function extractToolResult(data) {
|
|
|
9951
10210
|
if (result.structuredContent !== void 0) return safeStringify2(result.structuredContent);
|
|
9952
10211
|
return safeStringify2(result);
|
|
9953
10212
|
}
|
|
9954
|
-
function appendThinking2(turn, text,
|
|
10213
|
+
function appendThinking2(turn, text, timestamp2, signature) {
|
|
9955
10214
|
if (!text || turn.thinking.some((block2) => block2.thinking === text)) return;
|
|
9956
10215
|
const block = { type: "thinking", thinking: text, signature };
|
|
9957
10216
|
turn.thinking.push(block);
|
|
@@ -9960,21 +10219,21 @@ function appendThinking2(turn, text, timestamp, signature) {
|
|
|
9960
10219
|
last.blocks.push(block);
|
|
9961
10220
|
return;
|
|
9962
10221
|
}
|
|
9963
|
-
turn.contentBlocks.push({ kind: "thinking", blocks: [block], timestamp });
|
|
10222
|
+
turn.contentBlocks.push({ kind: "thinking", blocks: [block], timestamp: timestamp2 });
|
|
9964
10223
|
}
|
|
9965
|
-
function appendToolCall2(turn, call,
|
|
10224
|
+
function appendToolCall2(turn, call, timestamp2) {
|
|
9966
10225
|
turn.toolCalls.push(call);
|
|
9967
10226
|
const last = turn.contentBlocks[turn.contentBlocks.length - 1];
|
|
9968
10227
|
if (last?.kind === "tool_calls") {
|
|
9969
10228
|
last.toolCalls.push(call);
|
|
9970
10229
|
return;
|
|
9971
10230
|
}
|
|
9972
|
-
turn.contentBlocks.push({ kind: "tool_calls", toolCalls: [call], timestamp });
|
|
10231
|
+
turn.contentBlocks.push({ kind: "tool_calls", toolCalls: [call], timestamp: timestamp2 });
|
|
9973
10232
|
}
|
|
9974
|
-
function newToolCall(id, name, input,
|
|
9975
|
-
return { id, name, input, result: null, isError: false, timestamp };
|
|
10233
|
+
function newToolCall(id, name, input, timestamp2) {
|
|
10234
|
+
return { id, name, input, result: null, isError: false, timestamp: timestamp2 };
|
|
9976
10235
|
}
|
|
9977
|
-
function toolCallsFromRequests(value,
|
|
10236
|
+
function toolCallsFromRequests(value, timestamp2, isPending) {
|
|
9978
10237
|
if (!Array.isArray(value)) return [];
|
|
9979
10238
|
const calls = [];
|
|
9980
10239
|
for (const request of value) {
|
|
@@ -9983,14 +10242,14 @@ function toolCallsFromRequests(value, timestamp, isPending) {
|
|
|
9983
10242
|
const rawName = readString(request.name);
|
|
9984
10243
|
if (!id || !rawName || isPending(id)) continue;
|
|
9985
10244
|
const name = normalizeToolName(rawName);
|
|
9986
|
-
calls.push(newToolCall(id, name, normalizeToolInput(name, request.arguments),
|
|
10245
|
+
calls.push(newToolCall(id, name, normalizeToolInput(name, request.arguments), timestamp2));
|
|
9987
10246
|
}
|
|
9988
10247
|
return calls;
|
|
9989
10248
|
}
|
|
9990
|
-
function updateToolCallStart(call, name, input,
|
|
10249
|
+
function updateToolCallStart(call, name, input, timestamp2) {
|
|
9991
10250
|
call.name = name;
|
|
9992
10251
|
call.input = normalizeToolInput(name, input);
|
|
9993
|
-
call.timestamp =
|
|
10252
|
+
call.timestamp = timestamp2 || call.timestamp;
|
|
9994
10253
|
}
|
|
9995
10254
|
function updateToolCallResult(call, data, binaryAssets) {
|
|
9996
10255
|
call.result = extractToolResult(data);
|
|
@@ -9998,7 +10257,7 @@ function updateToolCallResult(call, data, binaryAssets) {
|
|
|
9998
10257
|
if (resultImages.length > 0) call.resultImages = resultImages;
|
|
9999
10258
|
call.isError = data.success === false || data.error !== void 0 && data.error !== null;
|
|
10000
10259
|
}
|
|
10001
|
-
function createTurn2(id,
|
|
10260
|
+
function createTurn2(id, timestamp2, userMessage, model, effort, isFragment) {
|
|
10002
10261
|
return {
|
|
10003
10262
|
id,
|
|
10004
10263
|
userMessage,
|
|
@@ -10007,7 +10266,7 @@ function createTurn2(id, timestamp, userMessage, model, effort, isFragment) {
|
|
|
10007
10266
|
assistantText: [],
|
|
10008
10267
|
toolCalls: [],
|
|
10009
10268
|
subAgentActivity: [],
|
|
10010
|
-
timestamp,
|
|
10269
|
+
timestamp: timestamp2,
|
|
10011
10270
|
durationMs: null,
|
|
10012
10271
|
tokenUsage: null,
|
|
10013
10272
|
model,
|
|
@@ -10034,8 +10293,8 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10034
10293
|
let sawAssistantUsage = false;
|
|
10035
10294
|
let sawAssistantDuration = false;
|
|
10036
10295
|
let shutdownUsage = null;
|
|
10037
|
-
function noteTimestamp(turn,
|
|
10038
|
-
if (
|
|
10296
|
+
function noteTimestamp(turn, timestamp2) {
|
|
10297
|
+
if (timestamp2) endTimestamps.set(turn, timestamp2);
|
|
10039
10298
|
}
|
|
10040
10299
|
function ensureTurn(event) {
|
|
10041
10300
|
if (!current) {
|
|
@@ -10096,7 +10355,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10096
10355
|
const message = ensureAgent(event);
|
|
10097
10356
|
if (!message) return true;
|
|
10098
10357
|
const { data } = event;
|
|
10099
|
-
const
|
|
10358
|
+
const timestamp2 = eventTimestamp(event);
|
|
10100
10359
|
if (event.type === "subagent.started" || event.type === "subagent.configured") {
|
|
10101
10360
|
message.parentToolUseId ||= readString(data.toolCallId) || void 0;
|
|
10102
10361
|
message.agentName = readString(data.agentDisplayName, data.agentName) || message.agentName;
|
|
@@ -10135,7 +10394,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10135
10394
|
if (text && !message.text.includes(text)) message.text.push(text);
|
|
10136
10395
|
for (const call of toolCallsFromRequests(
|
|
10137
10396
|
data.toolRequests,
|
|
10138
|
-
|
|
10397
|
+
timestamp2,
|
|
10139
10398
|
(id) => pendingAgentToolCalls.has(id)
|
|
10140
10399
|
)) {
|
|
10141
10400
|
message.toolCalls.push(call);
|
|
@@ -10155,13 +10414,13 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10155
10414
|
const name = normalizeToolName(rawName);
|
|
10156
10415
|
const existing = pendingAgentToolCalls.get(callId);
|
|
10157
10416
|
if (existing) {
|
|
10158
|
-
updateToolCallStart(existing.call, name, data.arguments,
|
|
10417
|
+
updateToolCallStart(existing.call, name, data.arguments, timestamp2);
|
|
10159
10418
|
} else {
|
|
10160
10419
|
const call = newToolCall(
|
|
10161
10420
|
callId,
|
|
10162
10421
|
name,
|
|
10163
10422
|
normalizeToolInput(name, data.arguments),
|
|
10164
|
-
|
|
10423
|
+
timestamp2
|
|
10165
10424
|
);
|
|
10166
10425
|
message.toolCalls.push(call);
|
|
10167
10426
|
pendingAgentToolCalls.set(callId, { call, message });
|
|
@@ -10174,7 +10433,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10174
10433
|
if (!pending) {
|
|
10175
10434
|
const rawName = readString(data.toolName) || "Tool";
|
|
10176
10435
|
const name = normalizeToolName(rawName);
|
|
10177
|
-
const call = newToolCall(callId, name, {},
|
|
10436
|
+
const call = newToolCall(callId, name, {}, timestamp2);
|
|
10178
10437
|
message.toolCalls.push(call);
|
|
10179
10438
|
pending = { call, message };
|
|
10180
10439
|
}
|
|
@@ -10187,7 +10446,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10187
10446
|
for (const event of events) {
|
|
10188
10447
|
if (applyAgentEvent(event)) continue;
|
|
10189
10448
|
const { data } = event;
|
|
10190
|
-
const
|
|
10449
|
+
const timestamp2 = eventTimestamp(event);
|
|
10191
10450
|
if (event.type === "session.start" || event.type === "session.resume") {
|
|
10192
10451
|
currentModel = readString(data.selectedModel) || currentModel;
|
|
10193
10452
|
currentEffort = readString(data.reasoningEffort) || currentEffort;
|
|
@@ -10220,13 +10479,13 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10220
10479
|
finalizeCurrent();
|
|
10221
10480
|
current = createTurn2(
|
|
10222
10481
|
turnEventId(event),
|
|
10223
|
-
|
|
10482
|
+
timestamp2,
|
|
10224
10483
|
buildUserContent(data, binaryAssets),
|
|
10225
10484
|
currentModel,
|
|
10226
10485
|
currentEffort,
|
|
10227
10486
|
false
|
|
10228
10487
|
);
|
|
10229
|
-
noteTimestamp(current,
|
|
10488
|
+
noteTimestamp(current, timestamp2);
|
|
10230
10489
|
continue;
|
|
10231
10490
|
}
|
|
10232
10491
|
if (event.type === "assistant.turn_start") {
|
|
@@ -10234,7 +10493,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10234
10493
|
const turn = ensureTurn(event);
|
|
10235
10494
|
turn.model = currentModel;
|
|
10236
10495
|
if (currentEffort) turn.effort = currentEffort;
|
|
10237
|
-
noteTimestamp(turn,
|
|
10496
|
+
noteTimestamp(turn, timestamp2);
|
|
10238
10497
|
continue;
|
|
10239
10498
|
}
|
|
10240
10499
|
if (event.type === "assistant.reasoning") {
|
|
@@ -10242,10 +10501,10 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10242
10501
|
appendThinking2(
|
|
10243
10502
|
turn,
|
|
10244
10503
|
readString(data.content),
|
|
10245
|
-
|
|
10504
|
+
timestamp2,
|
|
10246
10505
|
readString(data.reasoningId) || eventId(event, "copilot-thinking")
|
|
10247
10506
|
);
|
|
10248
|
-
noteTimestamp(turn,
|
|
10507
|
+
noteTimestamp(turn, timestamp2);
|
|
10249
10508
|
continue;
|
|
10250
10509
|
}
|
|
10251
10510
|
if (event.type === "assistant.message") {
|
|
@@ -10256,19 +10515,19 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10256
10515
|
appendThinking2(
|
|
10257
10516
|
turn,
|
|
10258
10517
|
readString(data.reasoningText),
|
|
10259
|
-
|
|
10518
|
+
timestamp2,
|
|
10260
10519
|
eventId(event, "copilot-thinking")
|
|
10261
10520
|
);
|
|
10262
|
-
appendAssistantText(turn, textFromValue(data.content),
|
|
10521
|
+
appendAssistantText(turn, textFromValue(data.content), timestamp2);
|
|
10263
10522
|
for (const call of toolCallsFromRequests(
|
|
10264
10523
|
data.toolRequests,
|
|
10265
|
-
|
|
10524
|
+
timestamp2,
|
|
10266
10525
|
(id) => pendingToolCalls.has(id)
|
|
10267
10526
|
)) {
|
|
10268
|
-
appendToolCall2(turn, call,
|
|
10527
|
+
appendToolCall2(turn, call, timestamp2);
|
|
10269
10528
|
pendingToolCalls.set(call.id, { call, turn });
|
|
10270
10529
|
}
|
|
10271
|
-
noteTimestamp(turn,
|
|
10530
|
+
noteTimestamp(turn, timestamp2);
|
|
10272
10531
|
continue;
|
|
10273
10532
|
}
|
|
10274
10533
|
if (event.type === "assistant.usage") {
|
|
@@ -10283,7 +10542,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10283
10542
|
if (currentEffort) turn.effort = currentEffort;
|
|
10284
10543
|
if (usage) turn.tokenUsage = mergeTokenUsage2(turn.tokenUsage, usage);
|
|
10285
10544
|
if (duration) apiDurationMs.set(turn, (apiDurationMs.get(turn) ?? 0) + duration);
|
|
10286
|
-
noteTimestamp(turn,
|
|
10545
|
+
noteTimestamp(turn, timestamp2);
|
|
10287
10546
|
continue;
|
|
10288
10547
|
}
|
|
10289
10548
|
if (event.type === "tool.execution_start") {
|
|
@@ -10295,18 +10554,18 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10295
10554
|
const name = normalizeToolName(rawName);
|
|
10296
10555
|
const existing = pendingToolCalls.get(callId);
|
|
10297
10556
|
if (existing) {
|
|
10298
|
-
updateToolCallStart(existing.call, name, data.arguments,
|
|
10557
|
+
updateToolCallStart(existing.call, name, data.arguments, timestamp2);
|
|
10299
10558
|
} else {
|
|
10300
10559
|
const call = newToolCall(
|
|
10301
10560
|
callId,
|
|
10302
10561
|
name,
|
|
10303
10562
|
normalizeToolInput(name, data.arguments),
|
|
10304
|
-
|
|
10563
|
+
timestamp2
|
|
10305
10564
|
);
|
|
10306
|
-
appendToolCall2(turn, call,
|
|
10565
|
+
appendToolCall2(turn, call, timestamp2);
|
|
10307
10566
|
pendingToolCalls.set(callId, { call, turn });
|
|
10308
10567
|
}
|
|
10309
|
-
noteTimestamp(turn,
|
|
10568
|
+
noteTimestamp(turn, timestamp2);
|
|
10310
10569
|
continue;
|
|
10311
10570
|
}
|
|
10312
10571
|
if (event.type === "tool.execution_complete") {
|
|
@@ -10317,13 +10576,13 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10317
10576
|
const turn = ensureTurn(event);
|
|
10318
10577
|
const rawName = readString(data.toolName) || "Tool";
|
|
10319
10578
|
const name = normalizeToolName(rawName);
|
|
10320
|
-
const call = newToolCall(callId, name, {},
|
|
10321
|
-
appendToolCall2(turn, call,
|
|
10579
|
+
const call = newToolCall(callId, name, {}, timestamp2);
|
|
10580
|
+
appendToolCall2(turn, call, timestamp2);
|
|
10322
10581
|
pending = { call, turn };
|
|
10323
10582
|
}
|
|
10324
10583
|
updateToolCallResult(pending.call, data, binaryAssets);
|
|
10325
10584
|
pendingToolCalls.delete(callId);
|
|
10326
|
-
noteTimestamp(pending.turn,
|
|
10585
|
+
noteTimestamp(pending.turn, timestamp2);
|
|
10327
10586
|
continue;
|
|
10328
10587
|
}
|
|
10329
10588
|
if (event.type === "session.error") {
|
|
@@ -10338,13 +10597,13 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10338
10597
|
input,
|
|
10339
10598
|
result: readString(data.message) || "Copilot session error",
|
|
10340
10599
|
isError: true,
|
|
10341
|
-
timestamp
|
|
10342
|
-
},
|
|
10343
|
-
noteTimestamp(turn,
|
|
10600
|
+
timestamp: timestamp2
|
|
10601
|
+
}, timestamp2);
|
|
10602
|
+
noteTimestamp(turn, timestamp2);
|
|
10344
10603
|
continue;
|
|
10345
10604
|
}
|
|
10346
10605
|
if (event.type === "assistant.turn_end" || event.type === "assistant.idle" || event.type === "session.idle") {
|
|
10347
|
-
if (current) noteTimestamp(current,
|
|
10606
|
+
if (current) noteTimestamp(current, timestamp2);
|
|
10348
10607
|
}
|
|
10349
10608
|
}
|
|
10350
10609
|
finalizeCurrent();
|
|
@@ -10387,7 +10646,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10387
10646
|
};
|
|
10388
10647
|
}
|
|
10389
10648
|
function appendCopilotSession(existing, newJsonlText) {
|
|
10390
|
-
const prefix = existing.rawMessages.map((
|
|
10649
|
+
const prefix = existing.rawMessages.map((record4) => JSON.stringify(record4)).join("\n");
|
|
10391
10650
|
return parseCopilotSession(prefix ? `${prefix}
|
|
10392
10651
|
${newJsonlText}` : newJsonlText);
|
|
10393
10652
|
}
|
|
@@ -10495,11 +10754,11 @@ function brandCopilotBranch() {
|
|
|
10495
10754
|
function copilotTurnBoundaries(records) {
|
|
10496
10755
|
const boundaries = [];
|
|
10497
10756
|
for (let index = 0; index < records.length; index++) {
|
|
10498
|
-
const
|
|
10499
|
-
if (
|
|
10500
|
-
const data =
|
|
10757
|
+
const record4 = records[index];
|
|
10758
|
+
if (record4.type !== "user.message" || typeof record4.agentId === "string") continue;
|
|
10759
|
+
const data = record4.data;
|
|
10501
10760
|
if (!data || typeof data !== "object" || Array.isArray(data)) continue;
|
|
10502
|
-
if (typeof
|
|
10761
|
+
if (typeof record4.id !== "string" || !record4.id) continue;
|
|
10503
10762
|
boundaries.push(index);
|
|
10504
10763
|
}
|
|
10505
10764
|
return boundaries;
|
|
@@ -10556,14 +10815,14 @@ async function readCopilotSessionIdentity(filePath) {
|
|
|
10556
10815
|
let cwd = "";
|
|
10557
10816
|
let gitBranch = "";
|
|
10558
10817
|
for (const line of await readHeadLines(filePath, HEAD_BYTES)) {
|
|
10559
|
-
let
|
|
10818
|
+
let record4;
|
|
10560
10819
|
try {
|
|
10561
|
-
|
|
10820
|
+
record4 = JSON.parse(line);
|
|
10562
10821
|
} catch {
|
|
10563
10822
|
continue;
|
|
10564
10823
|
}
|
|
10565
|
-
if (!isRecord3(
|
|
10566
|
-
const data = isRecord3(
|
|
10824
|
+
if (!isRecord3(record4) || record4.type !== "session.start" && record4.type !== "session.resume") continue;
|
|
10825
|
+
const data = isRecord3(record4.data) ? record4.data : null;
|
|
10567
10826
|
if (!data) continue;
|
|
10568
10827
|
if (typeof data.sessionId === "string" && data.sessionId) sessionId = data.sessionId;
|
|
10569
10828
|
const context = isRecord3(data.context) ? data.context : null;
|
|
@@ -10883,7 +11142,7 @@ function groupPlanModeBlocks(blocks) {
|
|
|
10883
11142
|
if (enterIdx !== -1) {
|
|
10884
11143
|
const enterCall = block.toolCalls[enterIdx];
|
|
10885
11144
|
const plan = String(enterCall.input.plan ?? "");
|
|
10886
|
-
const
|
|
11145
|
+
const timestamp2 = block.timestamp;
|
|
10887
11146
|
const before = block.toolCalls.slice(0, enterIdx);
|
|
10888
11147
|
if (before.length > 0) {
|
|
10889
11148
|
result.push({ kind: "tool_calls", toolCalls: before, timestamp: block.timestamp });
|
|
@@ -10899,7 +11158,7 @@ function groupPlanModeBlocks(blocks) {
|
|
|
10899
11158
|
if (exitCall.result !== null) {
|
|
10900
11159
|
status = exitCall.isError ? "rejected" : "approved";
|
|
10901
11160
|
}
|
|
10902
|
-
result.push({ kind: "plan_mode", plan, planFilePath, status, toolCalls: embedded, timestamp });
|
|
11161
|
+
result.push({ kind: "plan_mode", plan, planFilePath, status, toolCalls: embedded, timestamp: timestamp2 });
|
|
10903
11162
|
const after = afterEnterInSameBlock.slice(exitInSameBlock + 1);
|
|
10904
11163
|
if (after.length > 0) {
|
|
10905
11164
|
result.push({ kind: "tool_calls", toolCalls: after, timestamp: block.timestamp });
|
|
@@ -10925,7 +11184,7 @@ function groupPlanModeBlocks(blocks) {
|
|
|
10925
11184
|
status = exitCall.isError ? "rejected" : "approved";
|
|
10926
11185
|
}
|
|
10927
11186
|
const tail = next.toolCalls.slice(exitIdx + 1);
|
|
10928
|
-
result.push({ kind: "plan_mode", plan, planFilePath, status, toolCalls: embedded, timestamp });
|
|
11187
|
+
result.push({ kind: "plan_mode", plan, planFilePath, status, toolCalls: embedded, timestamp: timestamp2 });
|
|
10929
11188
|
result.push(...passthroughBlocks);
|
|
10930
11189
|
if (tail.length > 0) {
|
|
10931
11190
|
result.push({ kind: "tool_calls", toolCalls: tail, timestamp: next.timestamp });
|
|
@@ -10944,7 +11203,7 @@ function groupPlanModeBlocks(blocks) {
|
|
|
10944
11203
|
}
|
|
10945
11204
|
}
|
|
10946
11205
|
if (!exitCall) {
|
|
10947
|
-
result.push({ kind: "plan_mode", plan, planFilePath: void 0, status: "pending", toolCalls: embedded, timestamp });
|
|
11206
|
+
result.push({ kind: "plan_mode", plan, planFilePath: void 0, status: "pending", toolCalls: embedded, timestamp: timestamp2 });
|
|
10948
11207
|
result.push(...passthroughBlocks);
|
|
10949
11208
|
i = j;
|
|
10950
11209
|
}
|
|
@@ -11926,9 +12185,9 @@ function nonEmpty(value) {
|
|
|
11926
12185
|
function stripTaggedBlocks(text) {
|
|
11927
12186
|
return text.replace(/<[^>]+>[\s\S]*?<\/[^>]+>/g, "").trim();
|
|
11928
12187
|
}
|
|
11929
|
-
function effortFromRecord(
|
|
12188
|
+
function effortFromRecord(record4) {
|
|
11930
12189
|
for (const kind of AGENT_KINDS) {
|
|
11931
|
-
const effort = READERS[kind].effort(
|
|
12190
|
+
const effort = READERS[kind].effort(record4);
|
|
11932
12191
|
if (effort) return effort;
|
|
11933
12192
|
}
|
|
11934
12193
|
return null;
|
|
@@ -11938,15 +12197,15 @@ function userMessageTextFromLine(line) {
|
|
|
11938
12197
|
(kind) => READERS[kind].userMessageMarkers.some((marker) => line.includes(marker))
|
|
11939
12198
|
);
|
|
11940
12199
|
if (candidates.length === 0) return null;
|
|
11941
|
-
let
|
|
12200
|
+
let record4;
|
|
11942
12201
|
try {
|
|
11943
|
-
|
|
12202
|
+
record4 = JSON.parse(line);
|
|
11944
12203
|
} catch {
|
|
11945
12204
|
return null;
|
|
11946
12205
|
}
|
|
11947
|
-
if (!isRecord4(
|
|
12206
|
+
if (!isRecord4(record4)) return null;
|
|
11948
12207
|
for (const kind of candidates) {
|
|
11949
|
-
const text = READERS[kind].userMessageText(
|
|
12208
|
+
const text = READERS[kind].userMessageText(record4);
|
|
11950
12209
|
if (text !== null) return text;
|
|
11951
12210
|
}
|
|
11952
12211
|
return null;
|
|
@@ -11958,11 +12217,11 @@ var init_recordReaders = __esm({
|
|
|
11958
12217
|
claudeReader = {
|
|
11959
12218
|
kind: "claude",
|
|
11960
12219
|
// Every assistant record is tagged with the effort that turn ran at.
|
|
11961
|
-
effort: (
|
|
12220
|
+
effort: (record4) => record4.type === "assistant" ? nonEmpty(record4.effort) : null,
|
|
11962
12221
|
userMessageMarkers: ['"user"'],
|
|
11963
|
-
userMessageText(
|
|
11964
|
-
if (
|
|
11965
|
-
const content = isRecord4(
|
|
12222
|
+
userMessageText(record4) {
|
|
12223
|
+
if (record4.type !== "user" || record4.isMeta) return null;
|
|
12224
|
+
const content = isRecord4(record4.message) ? record4.message.content : void 0;
|
|
11966
12225
|
if (typeof content === "string") return stripTaggedBlocks(content);
|
|
11967
12226
|
if (!Array.isArray(content)) return "";
|
|
11968
12227
|
let text = "";
|
|
@@ -11977,32 +12236,32 @@ var init_recordReaders = __esm({
|
|
|
11977
12236
|
codexReader = {
|
|
11978
12237
|
kind: "codex",
|
|
11979
12238
|
// Effort is recorded per turn; newer CLI versions moved it under `thread_settings`.
|
|
11980
|
-
effort(
|
|
11981
|
-
if (
|
|
11982
|
-
const { payload } =
|
|
12239
|
+
effort(record4) {
|
|
12240
|
+
if (record4.type !== "turn_context" || !isRecord4(record4.payload)) return null;
|
|
12241
|
+
const { payload } = record4;
|
|
11983
12242
|
const direct = nonEmpty(payload.effort);
|
|
11984
12243
|
if (direct) return direct;
|
|
11985
12244
|
const settings = isRecord4(payload.thread_settings) ? payload.thread_settings : null;
|
|
11986
12245
|
return nonEmpty(settings?.reasoning_effort);
|
|
11987
12246
|
},
|
|
11988
12247
|
userMessageMarkers: ['"event_msg"'],
|
|
11989
|
-
userMessageText(
|
|
11990
|
-
if (
|
|
11991
|
-
const { payload } =
|
|
12248
|
+
userMessageText(record4) {
|
|
12249
|
+
if (record4.type !== "event_msg" || !isRecord4(record4.payload)) return null;
|
|
12250
|
+
const { payload } = record4;
|
|
11992
12251
|
return payload.type === "user_message" && typeof payload.message === "string" ? payload.message.trim() : null;
|
|
11993
12252
|
}
|
|
11994
12253
|
};
|
|
11995
12254
|
copilotReader = {
|
|
11996
12255
|
kind: "copilot",
|
|
11997
|
-
effort(
|
|
11998
|
-
if (
|
|
11999
|
-
return nonEmpty(
|
|
12256
|
+
effort(record4) {
|
|
12257
|
+
if (record4.type !== "session.start" && record4.type !== "session.resume" && record4.type !== "session.model_change" || !isRecord4(record4.data)) return null;
|
|
12258
|
+
return nonEmpty(record4.data.reasoningEffort ?? record4.data.effort);
|
|
12000
12259
|
},
|
|
12001
12260
|
userMessageMarkers: ['"user.message"'],
|
|
12002
|
-
userMessageText(
|
|
12003
|
-
if (
|
|
12004
|
-
if (typeof
|
|
12005
|
-
const data = isRecord4(
|
|
12261
|
+
userMessageText(record4) {
|
|
12262
|
+
if (record4.type !== "user.message") return null;
|
|
12263
|
+
if (typeof record4.agentId === "string" && record4.agentId) return null;
|
|
12264
|
+
const data = isRecord4(record4.data) ? record4.data : null;
|
|
12006
12265
|
return typeof data?.content === "string" ? data.content.trim() : "";
|
|
12007
12266
|
}
|
|
12008
12267
|
};
|
|
@@ -12015,16 +12274,16 @@ var init_recordReaders = __esm({
|
|
|
12015
12274
|
});
|
|
12016
12275
|
|
|
12017
12276
|
// ../../server/agents/tailRecords.ts
|
|
12018
|
-
function isSubagentLifecycle(
|
|
12019
|
-
return
|
|
12277
|
+
function isSubagentLifecycle(record4) {
|
|
12278
|
+
return record4.type.startsWith("subagent.") && typeof record4.agentId === "string" && record4.agentId.length > 0;
|
|
12020
12279
|
}
|
|
12021
|
-
function isSubagentNoise(
|
|
12022
|
-
return typeof
|
|
12280
|
+
function isSubagentNoise(record4) {
|
|
12281
|
+
return typeof record4.agentId === "string" && record4.agentId.length > 0;
|
|
12023
12282
|
}
|
|
12024
|
-
function classifyTailRecord(
|
|
12283
|
+
function classifyTailRecord(record4) {
|
|
12025
12284
|
for (const kind of AGENT_KINDS) {
|
|
12026
12285
|
const format = TAIL_FORMATS[kind];
|
|
12027
|
-
const verdict = format.classify(
|
|
12286
|
+
const verdict = format.classify(record4);
|
|
12028
12287
|
if (verdict.kind !== "ignore") return { format, verdict };
|
|
12029
12288
|
}
|
|
12030
12289
|
return null;
|
|
@@ -12041,31 +12300,31 @@ var init_tailRecords = __esm({
|
|
|
12041
12300
|
// Background agent/workflow launches, task notifications and TaskStop calls
|
|
12042
12301
|
// can all still change a verdict that a turn-ending line looked to settle.
|
|
12043
12302
|
markers: ["async_launched", "task-notification", '"TaskStop"'],
|
|
12044
|
-
classify(
|
|
12045
|
-
if (
|
|
12046
|
-
const reason =
|
|
12303
|
+
classify(record4) {
|
|
12304
|
+
if (record4.type === "system" && record4.subtype === "terminal_reason") {
|
|
12305
|
+
const reason = record4.reason;
|
|
12047
12306
|
return reason ? { kind: "final", status: { status: "completed", terminalReason: reason } } : IGNORE;
|
|
12048
12307
|
}
|
|
12049
|
-
if (
|
|
12050
|
-
const data =
|
|
12308
|
+
if (record4.type === "progress") {
|
|
12309
|
+
const data = record4.data;
|
|
12051
12310
|
if (data?.type !== "hook_progress") return IGNORE;
|
|
12052
12311
|
const decision = data.decision ?? data.hookSpecificOutput?.permissionDecision;
|
|
12053
12312
|
return decision === "defer" ? ANSWER : IGNORE;
|
|
12054
12313
|
}
|
|
12055
|
-
if (
|
|
12056
|
-
if (
|
|
12057
|
-
const stopReason =
|
|
12058
|
-
if (
|
|
12314
|
+
if (record4.type === "attachment") return KEEP;
|
|
12315
|
+
if (record4.type === "assistant" || record4.type === "user" || record4.type === "queue-operation") {
|
|
12316
|
+
const stopReason = record4.message?.stop_reason;
|
|
12317
|
+
if (record4.type === "assistant" && stopReason === "end_turn") {
|
|
12059
12318
|
return { kind: "turn-end", awaitUserActivity: true };
|
|
12060
12319
|
}
|
|
12061
|
-
const canDerive =
|
|
12320
|
+
const canDerive = record4.type === "assistant" || record4.type === "user" && !record4.isMeta;
|
|
12062
12321
|
return canDerive ? ANSWER : KEEP;
|
|
12063
12322
|
}
|
|
12064
12323
|
return IGNORE;
|
|
12065
12324
|
},
|
|
12066
|
-
classifyAfterTurnEnd(
|
|
12067
|
-
if (
|
|
12068
|
-
const isRealUserTurn =
|
|
12325
|
+
classifyAfterTurnEnd(record4) {
|
|
12326
|
+
if (record4.type !== "user" && record4.type !== "assistant" && record4.type !== "queue-operation" && record4.type !== "attachment") return IGNORE;
|
|
12327
|
+
const isRealUserTurn = record4.type === "user" && !record4.isMeta;
|
|
12069
12328
|
return { kind: "keep", sawUserActivity: isRealUserTurn };
|
|
12070
12329
|
}
|
|
12071
12330
|
};
|
|
@@ -12084,9 +12343,9 @@ var init_tailRecords = __esm({
|
|
|
12084
12343
|
"agent_message",
|
|
12085
12344
|
"function_call_output"
|
|
12086
12345
|
],
|
|
12087
|
-
classify(
|
|
12088
|
-
if (
|
|
12089
|
-
const payload =
|
|
12346
|
+
classify(record4) {
|
|
12347
|
+
if (record4.type === "event_msg") {
|
|
12348
|
+
const payload = record4.payload;
|
|
12090
12349
|
switch (payload?.type) {
|
|
12091
12350
|
case "task_complete":
|
|
12092
12351
|
return { kind: "turn-end" };
|
|
@@ -12098,32 +12357,32 @@ var init_tailRecords = __esm({
|
|
|
12098
12357
|
return IGNORE;
|
|
12099
12358
|
}
|
|
12100
12359
|
}
|
|
12101
|
-
if (
|
|
12102
|
-
const payload =
|
|
12360
|
+
if (record4.type === "response_item") {
|
|
12361
|
+
const payload = record4.payload;
|
|
12103
12362
|
const decides = payload?.type === "function_call" || payload?.type === "message" && (payload.role === "assistant" || payload.role === "user");
|
|
12104
12363
|
return decides ? ANSWER : IGNORE;
|
|
12105
12364
|
}
|
|
12106
12365
|
return IGNORE;
|
|
12107
12366
|
},
|
|
12108
|
-
classifyAfterTurnEnd(
|
|
12109
|
-
return
|
|
12367
|
+
classifyAfterTurnEnd(record4) {
|
|
12368
|
+
return record4.type === "event_msg" || record4.type === "response_item" ? KEEP : IGNORE;
|
|
12110
12369
|
}
|
|
12111
12370
|
};
|
|
12112
12371
|
copilotTail = {
|
|
12113
12372
|
kind: "copilot",
|
|
12114
12373
|
markers: ['"abort"', '"assistant.message"', '"user.message"', '"subagent.'],
|
|
12115
|
-
classify(
|
|
12116
|
-
if (isSubagentLifecycle(
|
|
12117
|
-
const decidable =
|
|
12118
|
-
if (!decidable || isSubagentNoise(
|
|
12119
|
-
if (
|
|
12120
|
-
if (
|
|
12374
|
+
classify(record4) {
|
|
12375
|
+
if (isSubagentLifecycle(record4)) return KEEP;
|
|
12376
|
+
const decidable = record4.type === "abort" || record4.type === "user.message" || record4.type.startsWith("assistant.") || record4.type.startsWith("permission.") || record4.type.startsWith("session.") || record4.type.startsWith("tool.") || record4.type.startsWith("user_input.");
|
|
12377
|
+
if (!decidable || isSubagentNoise(record4)) return IGNORE;
|
|
12378
|
+
if (record4.type === "assistant.turn_end") return { kind: "turn-end" };
|
|
12379
|
+
if (record4.type === "session.start" || record4.type === "session.resume") return ANSWER;
|
|
12121
12380
|
return { kind: "answer-if-active" };
|
|
12122
12381
|
},
|
|
12123
|
-
classifyAfterTurnEnd(
|
|
12124
|
-
if (isSubagentLifecycle(
|
|
12125
|
-
if (isSubagentNoise(
|
|
12126
|
-
const decides =
|
|
12382
|
+
classifyAfterTurnEnd(record4) {
|
|
12383
|
+
if (isSubagentLifecycle(record4)) return KEEP;
|
|
12384
|
+
if (isSubagentNoise(record4)) return IGNORE;
|
|
12385
|
+
const decides = record4.type === "abort" || record4.type === "assistant.message" || record4.type === "user.message";
|
|
12127
12386
|
return decides ? ANSWER : IGNORE;
|
|
12128
12387
|
}
|
|
12129
12388
|
};
|
|
@@ -12178,14 +12437,14 @@ async function readTranscriptEffort(filePath) {
|
|
|
12178
12437
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
12179
12438
|
const line = lines[i];
|
|
12180
12439
|
if (!line || !line.includes("effort") && !line.includes("Effort")) continue;
|
|
12181
|
-
let
|
|
12440
|
+
let record4;
|
|
12182
12441
|
try {
|
|
12183
|
-
|
|
12442
|
+
record4 = JSON.parse(line);
|
|
12184
12443
|
} catch {
|
|
12185
12444
|
continue;
|
|
12186
12445
|
}
|
|
12187
|
-
if (typeof
|
|
12188
|
-
const effort = effortFromRecord(
|
|
12446
|
+
if (typeof record4 !== "object" || record4 === null) continue;
|
|
12447
|
+
const effort = effortFromRecord(record4);
|
|
12189
12448
|
if (effort) return effort;
|
|
12190
12449
|
}
|
|
12191
12450
|
}
|
|
@@ -12221,14 +12480,14 @@ async function getSessionStatus(filePath) {
|
|
|
12221
12480
|
const line = lines[i];
|
|
12222
12481
|
if (!line) continue;
|
|
12223
12482
|
if (turnEnded && !isTailCandidate(line, turnEnded)) continue;
|
|
12224
|
-
let
|
|
12483
|
+
let record4;
|
|
12225
12484
|
try {
|
|
12226
|
-
|
|
12485
|
+
record4 = JSON.parse(line);
|
|
12227
12486
|
} catch {
|
|
12228
12487
|
continue;
|
|
12229
12488
|
}
|
|
12230
|
-
if (typeof
|
|
12231
|
-
const match = turnEnded ? { format: turnEnded, verdict: turnEnded.classifyAfterTurnEnd(
|
|
12489
|
+
if (typeof record4?.type !== "string") continue;
|
|
12490
|
+
const match = turnEnded ? { format: turnEnded, verdict: turnEnded.classifyAfterTurnEnd(record4) } : classifyTailRecord(record4);
|
|
12232
12491
|
if (!match) continue;
|
|
12233
12492
|
const { verdict } = match;
|
|
12234
12493
|
switch (verdict.kind) {
|
|
@@ -12237,20 +12496,20 @@ async function getSessionStatus(filePath) {
|
|
|
12237
12496
|
case "final":
|
|
12238
12497
|
return verdict.status;
|
|
12239
12498
|
case "keep":
|
|
12240
|
-
meaningful.unshift(
|
|
12499
|
+
meaningful.unshift(record4);
|
|
12241
12500
|
if (verdict.sawUserActivity) needUserActivity = false;
|
|
12242
12501
|
continue;
|
|
12243
12502
|
case "answer":
|
|
12244
|
-
meaningful.unshift(
|
|
12503
|
+
meaningful.unshift(record4);
|
|
12245
12504
|
return deriveSessionStatus(meaningful);
|
|
12246
12505
|
case "answer-if-active": {
|
|
12247
|
-
meaningful.unshift(
|
|
12506
|
+
meaningful.unshift(record4);
|
|
12248
12507
|
const status = deriveSessionStatus(meaningful);
|
|
12249
12508
|
if (status.status !== "idle") return status;
|
|
12250
12509
|
continue;
|
|
12251
12510
|
}
|
|
12252
12511
|
case "turn-end":
|
|
12253
|
-
meaningful.unshift(
|
|
12512
|
+
meaningful.unshift(record4);
|
|
12254
12513
|
turnEnded = match.format;
|
|
12255
12514
|
needUserActivity = verdict.awaitUserActivity === true;
|
|
12256
12515
|
continue;
|
|
@@ -12352,7 +12611,7 @@ var init_sessionPaths = __esm({
|
|
|
12352
12611
|
});
|
|
12353
12612
|
|
|
12354
12613
|
// ../../server/helpers.ts
|
|
12355
|
-
import { spawn } from "node:child_process";
|
|
12614
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
12356
12615
|
import { homedir as homedir4 } from "node:os";
|
|
12357
12616
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
12358
12617
|
import { createInterface } from "node:readline";
|
|
@@ -12395,12 +12654,12 @@ var init_modelCatalog = __esm({
|
|
|
12395
12654
|
|
|
12396
12655
|
// ../../server/agents/timeout.ts
|
|
12397
12656
|
function withTimeout(promise, ms, label) {
|
|
12398
|
-
return new Promise((
|
|
12657
|
+
return new Promise((resolve22, reject) => {
|
|
12399
12658
|
const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
12400
12659
|
promise.then(
|
|
12401
12660
|
(value) => {
|
|
12402
12661
|
clearTimeout(timer);
|
|
12403
|
-
|
|
12662
|
+
resolve22(value);
|
|
12404
12663
|
},
|
|
12405
12664
|
(error) => {
|
|
12406
12665
|
clearTimeout(timer);
|
|
@@ -12525,7 +12784,7 @@ async function fetchClaudeModels() {
|
|
|
12525
12784
|
}
|
|
12526
12785
|
var init_claudeModels = __esm({
|
|
12527
12786
|
"../../server/agents/claudeModels.ts"() {
|
|
12528
|
-
|
|
12787
|
+
init_claudeExecutable();
|
|
12529
12788
|
init_modelCatalog();
|
|
12530
12789
|
init_timeout();
|
|
12531
12790
|
init_model_names();
|
|
@@ -12603,7 +12862,7 @@ async function awaitTranscript(filePath, isSettled) {
|
|
|
12603
12862
|
return true;
|
|
12604
12863
|
} catch {
|
|
12605
12864
|
}
|
|
12606
|
-
await new Promise((
|
|
12865
|
+
await new Promise((resolve22) => setTimeout(resolve22, TRANSCRIPT_POLL_INTERVAL_MS));
|
|
12607
12866
|
}
|
|
12608
12867
|
return false;
|
|
12609
12868
|
}
|
|
@@ -12634,7 +12893,7 @@ function startOneShot(req) {
|
|
|
12634
12893
|
]);
|
|
12635
12894
|
const cleanEnv = { ...process.env };
|
|
12636
12895
|
delete cleanEnv.CLAUDECODE;
|
|
12637
|
-
const child =
|
|
12896
|
+
const child = spawn2(cli.command, cli.args, {
|
|
12638
12897
|
cwd: req.cwd,
|
|
12639
12898
|
env: cleanEnv,
|
|
12640
12899
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -12650,7 +12909,7 @@ function startOneShot(req) {
|
|
|
12650
12909
|
child.on("close", () => {
|
|
12651
12910
|
activeProcesses.delete(sessionId);
|
|
12652
12911
|
});
|
|
12653
|
-
return new Promise((
|
|
12912
|
+
return new Promise((resolve22, reject) => {
|
|
12654
12913
|
let settled = false;
|
|
12655
12914
|
const fail = (message) => {
|
|
12656
12915
|
if (settled) return;
|
|
@@ -12672,7 +12931,7 @@ function startOneShot(req) {
|
|
|
12672
12931
|
await stat7(filePath);
|
|
12673
12932
|
settled = true;
|
|
12674
12933
|
clearTimeout(timer);
|
|
12675
|
-
|
|
12934
|
+
resolve22({ sessionId, dirName: req.dirName, fileName, filePath });
|
|
12676
12935
|
} catch {
|
|
12677
12936
|
fail(
|
|
12678
12937
|
stderr.trim() || `${descriptor4.binName} exited with code ${code} before creating session`
|
|
@@ -12702,7 +12961,7 @@ function startInteractive(req) {
|
|
|
12702
12961
|
worktreeName: req.worktreeName,
|
|
12703
12962
|
mcpConfig: req.mcpConfig
|
|
12704
12963
|
});
|
|
12705
|
-
return new Promise((
|
|
12964
|
+
return new Promise((resolve22, reject) => {
|
|
12706
12965
|
let settled = false;
|
|
12707
12966
|
const succeed = async () => {
|
|
12708
12967
|
if (settled) return;
|
|
@@ -12712,7 +12971,7 @@ function startInteractive(req) {
|
|
|
12712
12971
|
initialContent = await readFile9(filePath, "utf-8");
|
|
12713
12972
|
} catch {
|
|
12714
12973
|
}
|
|
12715
|
-
|
|
12974
|
+
resolve22({ sessionId, dirName: req.dirName, fileName, filePath, initialContent });
|
|
12716
12975
|
};
|
|
12717
12976
|
const fail = (message) => {
|
|
12718
12977
|
if (settled) return;
|
|
@@ -12795,6 +13054,7 @@ var init_claudeRuntime = __esm({
|
|
|
12795
13054
|
"../../server/agents/claudeRuntime.ts"() {
|
|
12796
13055
|
init_agent_descriptors();
|
|
12797
13056
|
init_helpers();
|
|
13057
|
+
init_claudeExecutable();
|
|
12798
13058
|
init_claudeModels();
|
|
12799
13059
|
init_spawnError();
|
|
12800
13060
|
init_binaryResolver();
|
|
@@ -12852,10 +13112,10 @@ var init_claudeRuntime = __esm({
|
|
|
12852
13112
|
mcpConfig: req.mcpConfig
|
|
12853
13113
|
});
|
|
12854
13114
|
watchSubagentsFor(state, req.filePath ?? null);
|
|
12855
|
-
const completion = new Promise((
|
|
13115
|
+
const completion = new Promise((resolve22) => {
|
|
12856
13116
|
state.onResult = (result) => {
|
|
12857
13117
|
state.onResult = null;
|
|
12858
|
-
|
|
13118
|
+
resolve22(turnResultFrom(result));
|
|
12859
13119
|
};
|
|
12860
13120
|
});
|
|
12861
13121
|
return { delivery: "started", completion };
|
|
@@ -12941,7 +13201,7 @@ var init_package = __esm({
|
|
|
12941
13201
|
package_default = {
|
|
12942
13202
|
name: "cogpit",
|
|
12943
13203
|
private: true,
|
|
12944
|
-
version: "2.
|
|
13204
|
+
version: "2.3.0",
|
|
12945
13205
|
description: "Control center for Claude Code, OpenAI Codex, and GitHub Copilot CLI sessions",
|
|
12946
13206
|
license: "MIT",
|
|
12947
13207
|
author: {
|
|
@@ -13051,11 +13311,11 @@ var init_package = __esm({
|
|
|
13051
13311
|
overrides: {
|
|
13052
13312
|
"@babel/core": "7.29.7",
|
|
13053
13313
|
"@hono/node-server": "1.19.15",
|
|
13054
|
-
"@xmldom/xmldom": "0.8.
|
|
13314
|
+
"@xmldom/xmldom": "0.8.15",
|
|
13055
13315
|
"app-builder-lib": "26.15.3",
|
|
13056
13316
|
"body-parser": "2.3.0",
|
|
13057
13317
|
"builder-util-runtime": "9.7.0",
|
|
13058
|
-
"fast-uri": "
|
|
13318
|
+
"fast-uri": "4.1.4",
|
|
13059
13319
|
flatted: "3.4.2",
|
|
13060
13320
|
"form-data": "4.0.6",
|
|
13061
13321
|
hono: "4.13.1",
|
|
@@ -13064,7 +13324,7 @@ var init_package = __esm({
|
|
|
13064
13324
|
lodash: "4.18.1",
|
|
13065
13325
|
nanoid: "3.3.18",
|
|
13066
13326
|
postcss: "8.5.26",
|
|
13067
|
-
qs: "6.
|
|
13327
|
+
qs: "6.16.0",
|
|
13068
13328
|
tar: "7.5.21",
|
|
13069
13329
|
tmp: "0.2.7",
|
|
13070
13330
|
undici: "7.29.0"
|
|
@@ -13169,109 +13429,14 @@ function forwardCodexStreamNotification(notification) {
|
|
|
13169
13429
|
// stale overlay behind.
|
|
13170
13430
|
case "turn/started":
|
|
13171
13431
|
case "turn/completed":
|
|
13172
|
-
case "thread/closed":
|
|
13173
|
-
clear(threadId);
|
|
13174
|
-
return;
|
|
13175
|
-
}
|
|
13176
|
-
}
|
|
13177
|
-
var init_codexStreamAdapter = __esm({
|
|
13178
|
-
"../../server/lib/codexStreamAdapter.ts"() {
|
|
13179
|
-
init_streamBus();
|
|
13180
|
-
}
|
|
13181
|
-
});
|
|
13182
|
-
|
|
13183
|
-
// ../../shared/versions.ts
|
|
13184
|
-
function parseVersion(raw) {
|
|
13185
|
-
const match = raw.trim().replace(/^v/i, "").match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/);
|
|
13186
|
-
if (!match) return null;
|
|
13187
|
-
return {
|
|
13188
|
-
parts: [Number(match[1]), Number(match[2]), Number(match[3])],
|
|
13189
|
-
prerelease: match[4] ? match[4].split(".") : []
|
|
13190
|
-
};
|
|
13191
|
-
}
|
|
13192
|
-
function extractVersion(output) {
|
|
13193
|
-
const match = output.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/);
|
|
13194
|
-
return match ? match[0] : null;
|
|
13195
|
-
}
|
|
13196
|
-
function comparePrerelease(a, b) {
|
|
13197
|
-
if (a.length === 0 && b.length === 0) return 0;
|
|
13198
|
-
if (a.length === 0) return 1;
|
|
13199
|
-
if (b.length === 0) return -1;
|
|
13200
|
-
for (let i = 0; i < Math.max(a.length, b.length); i += 1) {
|
|
13201
|
-
const left = a[i];
|
|
13202
|
-
const right = b[i];
|
|
13203
|
-
if (left === void 0) return -1;
|
|
13204
|
-
if (right === void 0) return 1;
|
|
13205
|
-
const leftNumeric = /^\d+$/.test(left);
|
|
13206
|
-
const rightNumeric = /^\d+$/.test(right);
|
|
13207
|
-
if (leftNumeric && rightNumeric) {
|
|
13208
|
-
if (Number(left) !== Number(right)) return Number(left) < Number(right) ? -1 : 1;
|
|
13209
|
-
continue;
|
|
13210
|
-
}
|
|
13211
|
-
if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1;
|
|
13212
|
-
if (left !== right) return left < right ? -1 : 1;
|
|
13213
|
-
}
|
|
13214
|
-
return 0;
|
|
13215
|
-
}
|
|
13216
|
-
function compareVersions(a, b) {
|
|
13217
|
-
const left = parseVersion(a);
|
|
13218
|
-
const right = parseVersion(b);
|
|
13219
|
-
if (!left || !right) return null;
|
|
13220
|
-
for (let i = 0; i < 3; i += 1) {
|
|
13221
|
-
if (left.parts[i] !== right.parts[i]) return left.parts[i] < right.parts[i] ? -1 : 1;
|
|
13222
|
-
}
|
|
13223
|
-
return comparePrerelease(left.prerelease, right.prerelease);
|
|
13224
|
-
}
|
|
13225
|
-
var init_versions = __esm({
|
|
13226
|
-
"../../shared/versions.ts"() {
|
|
13227
|
-
}
|
|
13228
|
-
});
|
|
13229
|
-
|
|
13230
|
-
// ../../server/lib/cliProcess.ts
|
|
13231
|
-
import { spawn as spawn2 } from "node:child_process";
|
|
13232
|
-
function runCli(executable, args, timeoutMs) {
|
|
13233
|
-
return new Promise((resolve21) => {
|
|
13234
|
-
const resolved = resolveAgentCommand(executable, [...args]);
|
|
13235
|
-
const child = spawn2(resolved.command, resolved.args, {
|
|
13236
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
13237
|
-
...resolved.spawnOptions
|
|
13238
|
-
});
|
|
13239
|
-
let stdout = "";
|
|
13240
|
-
let stderr = "";
|
|
13241
|
-
let timedOut = false;
|
|
13242
|
-
const timer = setTimeout(() => {
|
|
13243
|
-
timedOut = true;
|
|
13244
|
-
child.kill("SIGKILL");
|
|
13245
|
-
}, timeoutMs);
|
|
13246
|
-
const append = (buffer, chunk) => buffer.length >= CLI_OUTPUT_MAX_CHARS ? buffer : buffer + chunk.toString();
|
|
13247
|
-
child.stdout?.on("data", (chunk) => {
|
|
13248
|
-
stdout = append(stdout, chunk);
|
|
13249
|
-
});
|
|
13250
|
-
child.stderr?.on("data", (chunk) => {
|
|
13251
|
-
stderr = append(stderr, chunk);
|
|
13252
|
-
});
|
|
13253
|
-
child.on("error", () => {
|
|
13254
|
-
clearTimeout(timer);
|
|
13255
|
-
resolve21({ code: null, stdout, stderr, timedOut });
|
|
13256
|
-
});
|
|
13257
|
-
child.on("close", (code) => {
|
|
13258
|
-
clearTimeout(timer);
|
|
13259
|
-
resolve21({ code, stdout, stderr, timedOut });
|
|
13260
|
-
});
|
|
13261
|
-
});
|
|
13262
|
-
}
|
|
13263
|
-
async function probeCliVersion(command, versionArgs, timeoutMs = DEFAULT_PROBE_TIMEOUT_MS) {
|
|
13264
|
-
const probe = await runCli(command, versionArgs, timeoutMs);
|
|
13265
|
-
return extractVersion(`${probe.stdout}
|
|
13266
|
-
${probe.stderr}`);
|
|
13267
|
-
}
|
|
13268
|
-
var DEFAULT_PROBE_TIMEOUT_MS, CLI_OUTPUT_MAX_CHARS;
|
|
13269
|
-
var init_cliProcess = __esm({
|
|
13270
|
-
"../../server/lib/cliProcess.ts"() {
|
|
13271
|
-
init_versions();
|
|
13272
|
-
init_binaryResolver();
|
|
13273
|
-
DEFAULT_PROBE_TIMEOUT_MS = 5e3;
|
|
13274
|
-
CLI_OUTPUT_MAX_CHARS = 1e4;
|
|
13432
|
+
case "thread/closed":
|
|
13433
|
+
clear(threadId);
|
|
13434
|
+
return;
|
|
13435
|
+
}
|
|
13436
|
+
}
|
|
13437
|
+
var init_codexStreamAdapter = __esm({
|
|
13438
|
+
"../../server/lib/codexStreamAdapter.ts"() {
|
|
13439
|
+
init_streamBus();
|
|
13275
13440
|
}
|
|
13276
13441
|
});
|
|
13277
13442
|
|
|
@@ -13908,7 +14073,7 @@ var init_codexAppServer = __esm({
|
|
|
13908
14073
|
);
|
|
13909
14074
|
}
|
|
13910
14075
|
const id = this.nextRequestId++;
|
|
13911
|
-
return new Promise((
|
|
14076
|
+
return new Promise((resolve22, reject) => {
|
|
13912
14077
|
const timer = timeoutMs > 0 ? this.setTimer(() => {
|
|
13913
14078
|
const pending = this.pendingRequests.get(id);
|
|
13914
14079
|
if (!pending) return;
|
|
@@ -13921,7 +14086,7 @@ var init_codexAppServer = __esm({
|
|
|
13921
14086
|
}, timeoutMs) : null;
|
|
13922
14087
|
this.pendingRequests.set(id, {
|
|
13923
14088
|
method,
|
|
13924
|
-
resolve: (result) =>
|
|
14089
|
+
resolve: (result) => resolve22(result),
|
|
13925
14090
|
reject,
|
|
13926
14091
|
timer
|
|
13927
14092
|
});
|
|
@@ -13947,12 +14112,12 @@ var init_codexAppServer = __esm({
|
|
|
13947
14112
|
new CodexAppServerError("Codex app-server stdin is not writable")
|
|
13948
14113
|
);
|
|
13949
14114
|
}
|
|
13950
|
-
return new Promise((
|
|
14115
|
+
return new Promise((resolve22, reject) => {
|
|
13951
14116
|
try {
|
|
13952
14117
|
child.stdin.write(`${JSON.stringify(message)}
|
|
13953
14118
|
`, (error) => {
|
|
13954
14119
|
if (error) reject(error);
|
|
13955
|
-
else
|
|
14120
|
+
else resolve22();
|
|
13956
14121
|
});
|
|
13957
14122
|
} catch (error) {
|
|
13958
14123
|
reject(error);
|
|
@@ -14053,13 +14218,13 @@ var init_codexAppServer = __esm({
|
|
|
14053
14218
|
}
|
|
14054
14219
|
}
|
|
14055
14220
|
waitForChildClose(closed, timeoutMs) {
|
|
14056
|
-
return new Promise((
|
|
14221
|
+
return new Promise((resolve22) => {
|
|
14057
14222
|
let settled = false;
|
|
14058
14223
|
const finish = (didClose) => {
|
|
14059
14224
|
if (settled) return;
|
|
14060
14225
|
settled = true;
|
|
14061
14226
|
this.clearTimer(timer);
|
|
14062
|
-
|
|
14227
|
+
resolve22(didClose);
|
|
14063
14228
|
};
|
|
14064
14229
|
const timer = this.setTimer(() => finish(false), timeoutMs);
|
|
14065
14230
|
void closed.then(() => finish(true));
|
|
@@ -14068,8 +14233,8 @@ var init_codexAppServer = __esm({
|
|
|
14068
14233
|
async terminateChild(child, error) {
|
|
14069
14234
|
let didClose = false;
|
|
14070
14235
|
let resolveClose = () => void 0;
|
|
14071
|
-
const closed = new Promise((
|
|
14072
|
-
resolveClose =
|
|
14236
|
+
const closed = new Promise((resolve22) => {
|
|
14237
|
+
resolveClose = resolve22;
|
|
14073
14238
|
});
|
|
14074
14239
|
child.on("close", () => {
|
|
14075
14240
|
didClose = true;
|
|
@@ -14429,7 +14594,7 @@ async function waitForNewSession(cwd, knownPaths, startedAt2, timeoutMs = SESSIO
|
|
|
14429
14594
|
while (Date.now() < deadline) {
|
|
14430
14595
|
const match = await findNewestCodexSessionForCwd(cwd, knownPaths, startedAt2);
|
|
14431
14596
|
if (match) return match;
|
|
14432
|
-
await new Promise((
|
|
14597
|
+
await new Promise((resolve22) => setTimeout(resolve22, SESSION_DISCOVERY_INTERVAL_MS));
|
|
14433
14598
|
}
|
|
14434
14599
|
return null;
|
|
14435
14600
|
}
|
|
@@ -14443,9 +14608,9 @@ function identityFromMetaLine(line) {
|
|
|
14443
14608
|
const sessionId = typeof payload.id === "string" ? payload.id : "";
|
|
14444
14609
|
const timestampText = typeof payload.timestamp === "string" ? payload.timestamp : typeof parsed.timestamp === "string" ? parsed.timestamp : "";
|
|
14445
14610
|
if (!sessionId || !timestampText) return null;
|
|
14446
|
-
const
|
|
14447
|
-
if (Number.isNaN(
|
|
14448
|
-
const fileName = descriptor5.sessionFile.name(sessionId,
|
|
14611
|
+
const timestamp2 = new Date(timestampText);
|
|
14612
|
+
if (Number.isNaN(timestamp2.getTime())) return null;
|
|
14613
|
+
const fileName = descriptor5.sessionFile.name(sessionId, timestamp2);
|
|
14449
14614
|
return { sessionId, fileName, filePath: join11(sessionsRoot2(), fileName) };
|
|
14450
14615
|
} catch {
|
|
14451
14616
|
return null;
|
|
@@ -14505,7 +14670,7 @@ async function startLegacy(req, knownPaths) {
|
|
|
14505
14670
|
...args.turnArgs,
|
|
14506
14671
|
...args.promptArgs
|
|
14507
14672
|
]);
|
|
14508
|
-
const child =
|
|
14673
|
+
const child = spawn2(cli.command, cli.args, {
|
|
14509
14674
|
cwd: req.cwd,
|
|
14510
14675
|
env: process.env,
|
|
14511
14676
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -14516,7 +14681,7 @@ async function startLegacy(req, knownPaths) {
|
|
|
14516
14681
|
child.stderr?.on("data", (data) => {
|
|
14517
14682
|
stderr += data.toString();
|
|
14518
14683
|
});
|
|
14519
|
-
return new Promise((
|
|
14684
|
+
return new Promise((resolve22, reject) => {
|
|
14520
14685
|
let settled = false;
|
|
14521
14686
|
let sessionId = null;
|
|
14522
14687
|
const discovery = waitForNewSession(req.cwd, knownPaths, startedAt2);
|
|
@@ -14534,7 +14699,7 @@ async function startLegacy(req, knownPaths) {
|
|
|
14534
14699
|
} catch {
|
|
14535
14700
|
}
|
|
14536
14701
|
}
|
|
14537
|
-
|
|
14702
|
+
resolve22({
|
|
14538
14703
|
sessionId: identity.sessionId,
|
|
14539
14704
|
dirName: req.dirName,
|
|
14540
14705
|
fileName: identity.fileName,
|
|
@@ -14597,7 +14762,7 @@ async function sendLegacy(sessionId, req) {
|
|
|
14597
14762
|
sessionId,
|
|
14598
14763
|
...args.promptArgs
|
|
14599
14764
|
]);
|
|
14600
|
-
const child =
|
|
14765
|
+
const child = spawn2(cli.command, cli.args, {
|
|
14601
14766
|
cwd: req.cwd,
|
|
14602
14767
|
env: process.env,
|
|
14603
14768
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -14611,10 +14776,10 @@ async function sendLegacy(sessionId, req) {
|
|
|
14611
14776
|
child.stderr?.on("data", (data) => {
|
|
14612
14777
|
stderr += data.toString();
|
|
14613
14778
|
});
|
|
14614
|
-
const completion = new Promise((
|
|
14779
|
+
const completion = new Promise((resolve22) => {
|
|
14615
14780
|
session.onResult = (result) => {
|
|
14616
14781
|
session.onResult = null;
|
|
14617
|
-
|
|
14782
|
+
resolve22({
|
|
14618
14783
|
isError: result.is_error === true,
|
|
14619
14784
|
message: result.result
|
|
14620
14785
|
});
|
|
@@ -15652,7 +15817,7 @@ var init_copilotTransport = __esm({
|
|
|
15652
15817
|
}
|
|
15653
15818
|
waitForRequest(request, method, timeoutMs = this.transportTimeoutMs, onTimeout) {
|
|
15654
15819
|
if (timeoutMs <= 0) return request;
|
|
15655
|
-
return new Promise((
|
|
15820
|
+
return new Promise((resolve22, reject) => {
|
|
15656
15821
|
const timer = setTimeout(() => {
|
|
15657
15822
|
try {
|
|
15658
15823
|
onTimeout?.();
|
|
@@ -15663,7 +15828,7 @@ var init_copilotTransport = __esm({
|
|
|
15663
15828
|
request.then(
|
|
15664
15829
|
(value) => {
|
|
15665
15830
|
clearTimeout(timer);
|
|
15666
|
-
|
|
15831
|
+
resolve22(value);
|
|
15667
15832
|
},
|
|
15668
15833
|
(error) => {
|
|
15669
15834
|
clearTimeout(timer);
|
|
@@ -15789,10 +15954,10 @@ var init_copilotTransport = __esm({
|
|
|
15789
15954
|
...typeof params.allowFreeform === "boolean" ? { allowFreeform: params.allowFreeform } : {},
|
|
15790
15955
|
askedAt: Date.now()
|
|
15791
15956
|
};
|
|
15792
|
-
return new Promise((
|
|
15957
|
+
return new Promise((resolve22, reject) => {
|
|
15793
15958
|
this.pendingUserInputs.set(
|
|
15794
15959
|
this.pendingInteractionKey(sessionId, requestId),
|
|
15795
|
-
{ value, resolve:
|
|
15960
|
+
{ value, resolve: resolve22, reject }
|
|
15796
15961
|
);
|
|
15797
15962
|
});
|
|
15798
15963
|
}
|
|
@@ -15812,10 +15977,10 @@ var init_copilotTransport = __esm({
|
|
|
15812
15977
|
recommendedAction: typeof params.recommendedAction === "string" ? params.recommendedAction : actions[0] ?? "interactive",
|
|
15813
15978
|
askedAt: Date.now()
|
|
15814
15979
|
};
|
|
15815
|
-
return new Promise((
|
|
15980
|
+
return new Promise((resolve22, reject) => {
|
|
15816
15981
|
this.pendingExitPlans.set(
|
|
15817
15982
|
this.pendingInteractionKey(sessionId, requestId),
|
|
15818
|
-
{ value, resolve:
|
|
15983
|
+
{ value, resolve: resolve22, reject }
|
|
15819
15984
|
);
|
|
15820
15985
|
});
|
|
15821
15986
|
}
|
|
@@ -16040,17 +16205,17 @@ function parseJsonRecord(line) {
|
|
|
16040
16205
|
}
|
|
16041
16206
|
}
|
|
16042
16207
|
function parseClaudeUsageLine(line) {
|
|
16043
|
-
const
|
|
16044
|
-
if (!
|
|
16045
|
-
const message = asRecord3(
|
|
16208
|
+
const record4 = parseJsonRecord(line);
|
|
16209
|
+
if (!record4 || record4.type !== "assistant") return null;
|
|
16210
|
+
const message = asRecord3(record4.message);
|
|
16046
16211
|
const usage = message ? asRecord3(message.usage) : null;
|
|
16047
16212
|
if (!message || !usage) return null;
|
|
16048
|
-
const timestampMs = parseTimestampMs(
|
|
16213
|
+
const timestampMs = parseTimestampMs(record4.timestamp);
|
|
16049
16214
|
if (timestampMs === null) return null;
|
|
16050
16215
|
const model = typeof message.model === "string" ? message.model : "";
|
|
16051
16216
|
if (model.length === 0) return null;
|
|
16052
16217
|
const messageId = typeof message.id === "string" ? message.id : null;
|
|
16053
|
-
const requestId = typeof
|
|
16218
|
+
const requestId = typeof record4.requestId === "string" ? record4.requestId : null;
|
|
16054
16219
|
const dedupeKey = messageId === null && requestId === null ? null : `${messageId ?? ""}:${requestId ?? ""}`;
|
|
16055
16220
|
const cacheCreationTokens = int(usage.cache_creation_input_tokens);
|
|
16056
16221
|
const byTtl = asRecord3(usage.cache_creation);
|
|
@@ -16069,12 +16234,12 @@ function parseClaudeUsageLine(line) {
|
|
|
16069
16234
|
reasoningTokens: 0
|
|
16070
16235
|
};
|
|
16071
16236
|
if (totalUsageCostTokens(totals) === 0) return null;
|
|
16072
|
-
const cost =
|
|
16237
|
+
const cost = record4.costUSD;
|
|
16073
16238
|
return {
|
|
16074
16239
|
provider: "claude",
|
|
16075
16240
|
timestampMs,
|
|
16076
16241
|
model,
|
|
16077
|
-
sessionId: typeof
|
|
16242
|
+
sessionId: typeof record4.sessionId === "string" ? record4.sessionId : "",
|
|
16078
16243
|
totals,
|
|
16079
16244
|
reportedCostUsd: typeof cost === "number" && Number.isFinite(cost) ? cost : null,
|
|
16080
16245
|
dedupeKey
|
|
@@ -16096,30 +16261,30 @@ function isForkedSessionMeta(payload) {
|
|
|
16096
16261
|
return typeof spawn5?.parent_thread_id === "string";
|
|
16097
16262
|
}
|
|
16098
16263
|
function parseCodexUsageLine(line, state) {
|
|
16099
|
-
const
|
|
16100
|
-
if (!
|
|
16101
|
-
const payload = asRecord3(
|
|
16264
|
+
const record4 = parseJsonRecord(line);
|
|
16265
|
+
if (!record4) return null;
|
|
16266
|
+
const payload = asRecord3(record4.payload);
|
|
16102
16267
|
if (!payload) return null;
|
|
16103
|
-
if (
|
|
16268
|
+
if (record4.type === "session_meta") {
|
|
16104
16269
|
if (state.sawSessionMeta) return null;
|
|
16105
16270
|
state.sawSessionMeta = true;
|
|
16106
16271
|
const id = payload.id ?? payload.session_id;
|
|
16107
16272
|
if (typeof id === "string") state.sessionId = id;
|
|
16108
|
-
const metaTimestampMs = parseTimestampMs(
|
|
16273
|
+
const metaTimestampMs = parseTimestampMs(record4.timestamp);
|
|
16109
16274
|
if (metaTimestampMs !== null && isForkedSessionMeta(payload)) {
|
|
16110
16275
|
state.suppressingForkCopies = true;
|
|
16111
16276
|
state.forkCopyAnchorMs = metaTimestampMs;
|
|
16112
16277
|
}
|
|
16113
16278
|
return null;
|
|
16114
16279
|
}
|
|
16115
|
-
if (
|
|
16280
|
+
if (record4.type === "turn_context") {
|
|
16116
16281
|
if (typeof payload.model === "string") state.model = payload.model;
|
|
16117
16282
|
return null;
|
|
16118
16283
|
}
|
|
16119
16284
|
if (payload.type !== "token_count") return null;
|
|
16120
16285
|
const last = asRecord3(asRecord3(payload.info)?.last_token_usage);
|
|
16121
16286
|
if (!last) return null;
|
|
16122
|
-
const timestampMs = parseTimestampMs(
|
|
16287
|
+
const timestampMs = parseTimestampMs(record4.timestamp);
|
|
16123
16288
|
if (timestampMs === null) return null;
|
|
16124
16289
|
if (state.model.length === 0) return null;
|
|
16125
16290
|
const signature = JSON.stringify(last);
|
|
@@ -16218,17 +16383,17 @@ function parseCopilotUsageMetrics(value, state, timestampMs) {
|
|
|
16218
16383
|
return records;
|
|
16219
16384
|
}
|
|
16220
16385
|
function parseCopilotUsageLine(line, state) {
|
|
16221
|
-
const
|
|
16222
|
-
if (!
|
|
16223
|
-
const data = asRecord3(
|
|
16386
|
+
const record4 = parseJsonRecord(line);
|
|
16387
|
+
if (!record4 || typeof record4.agentId === "string" && record4.agentId.length > 0) return [];
|
|
16388
|
+
const data = asRecord3(record4.data);
|
|
16224
16389
|
if (!data) return [];
|
|
16225
|
-
if (
|
|
16390
|
+
if (record4.type === "session.start") {
|
|
16226
16391
|
const sessionId = data.sessionId;
|
|
16227
16392
|
if (typeof sessionId === "string" && sessionId.length > 0) state.sessionId = sessionId;
|
|
16228
16393
|
return [];
|
|
16229
16394
|
}
|
|
16230
|
-
if (
|
|
16231
|
-
const timestampMs = parseTimestampMs(
|
|
16395
|
+
if (record4.type !== "session.shutdown") return [];
|
|
16396
|
+
const timestampMs = parseTimestampMs(record4.timestamp);
|
|
16232
16397
|
return timestampMs === null ? [] : parseCopilotUsageMetrics(data, state, timestampMs);
|
|
16233
16398
|
}
|
|
16234
16399
|
function createUsageScanner(provider, filePath) {
|
|
@@ -16245,8 +16410,8 @@ var init_usageScanners = __esm({
|
|
|
16245
16410
|
// object, so a line is either self-contained or of no interest.
|
|
16246
16411
|
wantsLine: (line) => line.includes('"usage"'),
|
|
16247
16412
|
accept: (line) => {
|
|
16248
|
-
const
|
|
16249
|
-
return
|
|
16413
|
+
const record4 = parseClaudeUsageLine(line);
|
|
16414
|
+
return record4 === null ? [] : [record4];
|
|
16250
16415
|
}
|
|
16251
16416
|
}),
|
|
16252
16417
|
codex: () => {
|
|
@@ -16257,8 +16422,8 @@ var init_usageScanners = __esm({
|
|
|
16257
16422
|
// at all but still have to reach the reducer.
|
|
16258
16423
|
wantsLine: (line) => line.includes('"token_count"') || line.includes('"turn_context"') || line.includes('"session_meta"'),
|
|
16259
16424
|
accept: (line) => {
|
|
16260
|
-
const
|
|
16261
|
-
return
|
|
16425
|
+
const record4 = parseCodexUsageLine(line, state);
|
|
16426
|
+
return record4 === null ? [] : [record4];
|
|
16262
16427
|
}
|
|
16263
16428
|
};
|
|
16264
16429
|
},
|
|
@@ -16504,7 +16669,7 @@ var init_copilotRuntime = __esm({
|
|
|
16504
16669
|
initialContent = await readFile9(filePath, "utf-8");
|
|
16505
16670
|
break;
|
|
16506
16671
|
} catch {
|
|
16507
|
-
await new Promise((
|
|
16672
|
+
await new Promise((resolve22) => setTimeout(resolve22, TRANSCRIPT_POLL_INTERVAL_MS2));
|
|
16508
16673
|
}
|
|
16509
16674
|
}
|
|
16510
16675
|
return { sessionId, dirName: req.dirName, fileName, filePath, initialContent };
|
|
@@ -17140,11 +17305,11 @@ function registerRunningProcessesRoute(use) {
|
|
|
17140
17305
|
if (url.pathname.split("/").filter(Boolean).length > 0) return next();
|
|
17141
17306
|
const isWindows2 = process.platform === "win32";
|
|
17142
17307
|
const nameFilter = allDescriptors().map(windowsProcessNameFilter).join(" or ");
|
|
17143
|
-
const child = isWindows2 ?
|
|
17308
|
+
const child = isWindows2 ? spawn2("powershell", [
|
|
17144
17309
|
"-NoProfile",
|
|
17145
17310
|
"-Command",
|
|
17146
17311
|
`Get-CimInstance Win32_Process -Filter "${nameFilter}" | Select-Object ProcessId, WorkingSetSize, CommandLine | ConvertTo-Json -Compress`
|
|
17147
|
-
]) :
|
|
17312
|
+
]) : spawn2("ps", ["aux"]);
|
|
17148
17313
|
let stdout = "";
|
|
17149
17314
|
let responded = false;
|
|
17150
17315
|
child.stdout?.on("data", (data) => {
|
|
@@ -17507,12 +17672,12 @@ function registerBranchSessionRoute(use) {
|
|
|
17507
17672
|
}
|
|
17508
17673
|
}
|
|
17509
17674
|
const newSessionId = randomUUID2();
|
|
17510
|
-
const { record:
|
|
17675
|
+
const { record: record4, originalId } = format.brandBranch(
|
|
17511
17676
|
JSON.parse(lines[0]),
|
|
17512
17677
|
newSessionId,
|
|
17513
17678
|
turnIndex ?? null
|
|
17514
17679
|
);
|
|
17515
|
-
lines[0] = JSON.stringify(
|
|
17680
|
+
lines[0] = JSON.stringify(record4);
|
|
17516
17681
|
const target = storeForDirName(dirName).transcriptPath(dirName, newSessionId);
|
|
17517
17682
|
if (!target) {
|
|
17518
17683
|
res.statusCode = 500;
|
|
@@ -18055,11 +18220,11 @@ import {
|
|
|
18055
18220
|
dirname as dirname5,
|
|
18056
18221
|
isAbsolute as isAbsolute3,
|
|
18057
18222
|
join as join13,
|
|
18058
|
-
posix as
|
|
18223
|
+
posix as posix3,
|
|
18059
18224
|
relative as relative4,
|
|
18060
18225
|
resolve as resolve9,
|
|
18061
18226
|
sep as sep5,
|
|
18062
|
-
win32 as
|
|
18227
|
+
win32 as win323
|
|
18063
18228
|
} from "node:path";
|
|
18064
18229
|
function configuredAgentHomes() {
|
|
18065
18230
|
return new Set(AGENT_KINDS.map((kind) => agentHomeDir(kind)));
|
|
@@ -18168,7 +18333,7 @@ async function resolveConfigBrowserPath(filePath, options = {}) {
|
|
|
18168
18333
|
function isSafeConfigName(name) {
|
|
18169
18334
|
if (!name || name === "." || name === ".." || name.includes("\0")) return false;
|
|
18170
18335
|
if (name.includes("/") || name.includes("\\")) return false;
|
|
18171
|
-
if (isAbsolute3(name) ||
|
|
18336
|
+
if (isAbsolute3(name) || posix3.parse(name).root || win323.parse(name).root) return false;
|
|
18172
18337
|
return true;
|
|
18173
18338
|
}
|
|
18174
18339
|
function isUnderDir(parentDir, dirName) {
|
|
@@ -19411,7 +19576,8 @@ function registerConfigRoutes(use) {
|
|
|
19411
19576
|
networkPassword: config.networkPassword ? "set" : null,
|
|
19412
19577
|
terminalApp: config.terminalApp || null,
|
|
19413
19578
|
editorApp: config.editorApp || null,
|
|
19414
|
-
useBuiltInEditor: config.useBuiltInEditor || false
|
|
19579
|
+
useBuiltInEditor: config.useBuiltInEditor || false,
|
|
19580
|
+
agentExecutable: config.agentExecutable ?? DEFAULT_EXECUTABLE_CHOICE
|
|
19415
19581
|
} : null));
|
|
19416
19582
|
return;
|
|
19417
19583
|
}
|
|
@@ -19474,7 +19640,8 @@ function registerConfigRoutes(use) {
|
|
|
19474
19640
|
networkPassword: finalPassword,
|
|
19475
19641
|
terminalApp: parsed.terminalApp || void 0,
|
|
19476
19642
|
editorApp: parsed.editorApp || void 0,
|
|
19477
|
-
useBuiltInEditor: !!parsed.useBuiltInEditor
|
|
19643
|
+
useBuiltInEditor: !!parsed.useBuiltInEditor,
|
|
19644
|
+
agentExecutable: parseExecutableChoice(parsed.agentExecutable)
|
|
19478
19645
|
});
|
|
19479
19646
|
refreshDirs();
|
|
19480
19647
|
if (currentConfig && resolve11(resolvedClaudeDir) !== resolve11(currentConfig.claudeDir)) {
|
|
@@ -19509,12 +19676,13 @@ var init_config2 = __esm({
|
|
|
19509
19676
|
init_users();
|
|
19510
19677
|
init_config();
|
|
19511
19678
|
init_agent_descriptors();
|
|
19679
|
+
init_agentExecutable();
|
|
19512
19680
|
init_sessionPersistence();
|
|
19513
19681
|
}
|
|
19514
19682
|
});
|
|
19515
19683
|
|
|
19516
19684
|
// ../../server/routes/hello.ts
|
|
19517
|
-
import { readFileSync } from "node:fs";
|
|
19685
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
19518
19686
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19519
19687
|
import { hostname } from "node:os";
|
|
19520
19688
|
import { join as join18 } from "node:path";
|
|
@@ -19563,7 +19731,7 @@ var init_hello = __esm({
|
|
|
19563
19731
|
join18(__dirname2, "../package.json")
|
|
19564
19732
|
]) {
|
|
19565
19733
|
try {
|
|
19566
|
-
const pkg = JSON.parse(
|
|
19734
|
+
const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
|
|
19567
19735
|
if (typeof pkg.version === "string") return pkg.version;
|
|
19568
19736
|
} catch {
|
|
19569
19737
|
}
|
|
@@ -19676,21 +19844,21 @@ function toPublic(device) {
|
|
|
19676
19844
|
return rest;
|
|
19677
19845
|
}
|
|
19678
19846
|
function readJsonBody2(req) {
|
|
19679
|
-
return new Promise((
|
|
19847
|
+
return new Promise((resolve22) => {
|
|
19680
19848
|
let raw = "";
|
|
19681
19849
|
req.on("data", (chunk) => {
|
|
19682
19850
|
raw += chunk.toString();
|
|
19683
19851
|
});
|
|
19684
19852
|
req.on("end", () => {
|
|
19685
|
-
if (!raw.trim()) return
|
|
19853
|
+
if (!raw.trim()) return resolve22({});
|
|
19686
19854
|
try {
|
|
19687
19855
|
const parsed = JSON.parse(raw);
|
|
19688
|
-
|
|
19856
|
+
resolve22(parsed && typeof parsed === "object" ? parsed : null);
|
|
19689
19857
|
} catch {
|
|
19690
|
-
|
|
19858
|
+
resolve22(null);
|
|
19691
19859
|
}
|
|
19692
19860
|
});
|
|
19693
|
-
req.on("error", () =>
|
|
19861
|
+
req.on("error", () => resolve22(null));
|
|
19694
19862
|
});
|
|
19695
19863
|
}
|
|
19696
19864
|
function handleList(res) {
|
|
@@ -20078,9 +20246,9 @@ function terminalCommand(terminal, dirPath) {
|
|
|
20078
20246
|
return { cmd: terminal, args: ["--working-directory", dirPath] };
|
|
20079
20247
|
}
|
|
20080
20248
|
function whichEditor(name) {
|
|
20081
|
-
return new Promise((
|
|
20249
|
+
return new Promise((resolve22) => {
|
|
20082
20250
|
const cmd = platform() === "win32" ? "where" : "which";
|
|
20083
|
-
execFile(cmd, [name], (err) =>
|
|
20251
|
+
execFile(cmd, [name], (err) => resolve22(err ? null : name));
|
|
20084
20252
|
});
|
|
20085
20253
|
}
|
|
20086
20254
|
async function resolveEditor(configuredEditor) {
|
|
@@ -20094,10 +20262,10 @@ async function resolveEditor(configuredEditor) {
|
|
|
20094
20262
|
return null;
|
|
20095
20263
|
}
|
|
20096
20264
|
function openWithEditor(editor, args) {
|
|
20097
|
-
return new Promise((
|
|
20265
|
+
return new Promise((resolve22, reject) => {
|
|
20098
20266
|
execFile(editor, args, (err) => {
|
|
20099
20267
|
if (err) reject(err);
|
|
20100
|
-
else
|
|
20268
|
+
else resolve22();
|
|
20101
20269
|
});
|
|
20102
20270
|
});
|
|
20103
20271
|
}
|
|
@@ -20110,14 +20278,14 @@ function editorOpenArgs(editor, filePath, line, column) {
|
|
|
20110
20278
|
return [filePath];
|
|
20111
20279
|
}
|
|
20112
20280
|
function getGitHeadContent(filePath) {
|
|
20113
|
-
return new Promise((
|
|
20281
|
+
return new Promise((resolve22, reject) => {
|
|
20114
20282
|
execFile(
|
|
20115
20283
|
"git",
|
|
20116
20284
|
["-C", dirname7(filePath), "show", `HEAD:./${basename7(filePath)}`],
|
|
20117
20285
|
{ maxBuffer: 10 * 1024 * 1024 },
|
|
20118
20286
|
(err, stdout) => {
|
|
20119
20287
|
if (err) reject(err);
|
|
20120
|
-
else
|
|
20288
|
+
else resolve22(stdout);
|
|
20121
20289
|
}
|
|
20122
20290
|
);
|
|
20123
20291
|
});
|
|
@@ -20793,23 +20961,23 @@ function registerFileRoutes(use) {
|
|
|
20793
20961
|
req.on("end", async () => {
|
|
20794
20962
|
try {
|
|
20795
20963
|
let spawnLines = function(args, cwd) {
|
|
20796
|
-
return new Promise((
|
|
20797
|
-
const proc =
|
|
20964
|
+
return new Promise((resolve22) => {
|
|
20965
|
+
const proc = spawn2("git", args, { cwd });
|
|
20798
20966
|
let out = "";
|
|
20799
20967
|
proc.stdout.on("data", (d) => out += d.toString());
|
|
20800
20968
|
proc.on("close", (code) => {
|
|
20801
|
-
if (code !== 0 || !out) return
|
|
20802
|
-
|
|
20969
|
+
if (code !== 0 || !out) return resolve22(0);
|
|
20970
|
+
resolve22(out.split("\n").length);
|
|
20803
20971
|
});
|
|
20804
|
-
proc.on("error", () =>
|
|
20972
|
+
proc.on("error", () => resolve22(0));
|
|
20805
20973
|
});
|
|
20806
20974
|
}, spawnOutput = function(args, cwd) {
|
|
20807
|
-
return new Promise((
|
|
20808
|
-
const proc =
|
|
20975
|
+
return new Promise((resolve22) => {
|
|
20976
|
+
const proc = spawn2("git", args, { cwd });
|
|
20809
20977
|
let out = "";
|
|
20810
20978
|
proc.stdout.on("data", (d) => out += d.toString());
|
|
20811
|
-
proc.on("close", () =>
|
|
20812
|
-
proc.on("error", () =>
|
|
20979
|
+
proc.on("close", () => resolve22(out.trim()));
|
|
20980
|
+
proc.on("error", () => resolve22(""));
|
|
20813
20981
|
});
|
|
20814
20982
|
};
|
|
20815
20983
|
const { files, dirs: dirs2 } = JSON.parse(body);
|
|
@@ -20833,18 +21001,18 @@ function registerFileRoutes(use) {
|
|
|
20833
21001
|
cwd = cwd.substring(0, cwd.lastIndexOf("/")) || "/";
|
|
20834
21002
|
}
|
|
20835
21003
|
}
|
|
20836
|
-
return new Promise((
|
|
20837
|
-
const proc =
|
|
21004
|
+
return new Promise((resolve22) => {
|
|
21005
|
+
const proc = spawn2("git", ["rev-parse", "--show-toplevel"], { cwd });
|
|
20838
21006
|
let out = "";
|
|
20839
21007
|
proc.stdout.on("data", (d) => out += d.toString());
|
|
20840
21008
|
proc.on("close", (code) => {
|
|
20841
21009
|
const root = code === 0 ? out.trim() : null;
|
|
20842
21010
|
gitRootCache.set(dir, root);
|
|
20843
|
-
|
|
21011
|
+
resolve22(root);
|
|
20844
21012
|
});
|
|
20845
21013
|
proc.on("error", () => {
|
|
20846
21014
|
gitRootCache.set(dir, null);
|
|
20847
|
-
|
|
21015
|
+
resolve22(null);
|
|
20848
21016
|
});
|
|
20849
21017
|
});
|
|
20850
21018
|
}
|
|
@@ -21079,11 +21247,11 @@ function parseGitStatus(output) {
|
|
|
21079
21247
|
const branch = parseBranchHeader(header);
|
|
21080
21248
|
const files = [];
|
|
21081
21249
|
for (let index = 0; index < records.length; index += 1) {
|
|
21082
|
-
const
|
|
21083
|
-
if (!
|
|
21084
|
-
const indexStatus =
|
|
21085
|
-
const workTreeStatus =
|
|
21086
|
-
const path =
|
|
21250
|
+
const record4 = records[index];
|
|
21251
|
+
if (!record4 || record4.length < 3) continue;
|
|
21252
|
+
const indexStatus = record4[0];
|
|
21253
|
+
const workTreeStatus = record4[1];
|
|
21254
|
+
const path = record4.slice(3);
|
|
21087
21255
|
const renamedOrCopied = /[RC]/.test(`${indexStatus}${workTreeStatus}`);
|
|
21088
21256
|
const originalPath = renamedOrCopied ? records[index += 1] || void 0 : void 0;
|
|
21089
21257
|
files.push({ path, originalPath, indexStatus, workTreeStatus });
|
|
@@ -21138,14 +21306,630 @@ var init_git_status = __esm({
|
|
|
21138
21306
|
}
|
|
21139
21307
|
});
|
|
21140
21308
|
|
|
21309
|
+
// ../../server/routes/github-actions.ts
|
|
21310
|
+
import { execFile as execFileCallback2 } from "node:child_process";
|
|
21311
|
+
import { promisify as promisify2 } from "node:util";
|
|
21312
|
+
function record2(value) {
|
|
21313
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
21314
|
+
}
|
|
21315
|
+
function stringValue(value, fallback = "") {
|
|
21316
|
+
return typeof value === "string" ? value : fallback;
|
|
21317
|
+
}
|
|
21318
|
+
function numberValue(value) {
|
|
21319
|
+
return typeof value === "number" && Number.isSafeInteger(value) ? value : null;
|
|
21320
|
+
}
|
|
21321
|
+
function nullableDate(value) {
|
|
21322
|
+
return typeof value === "string" && value ? value : null;
|
|
21323
|
+
}
|
|
21324
|
+
function workflowStatus(value) {
|
|
21325
|
+
return typeof value === "string" && RUN_STATUSES.has(value) ? value : "pending";
|
|
21326
|
+
}
|
|
21327
|
+
function workflowConclusion(value) {
|
|
21328
|
+
return typeof value === "string" && RUN_CONCLUSIONS.has(value) ? value : null;
|
|
21329
|
+
}
|
|
21330
|
+
function parseGitHubRemote(remoteUrl) {
|
|
21331
|
+
const trimmed = remoteUrl.trim();
|
|
21332
|
+
let host = "";
|
|
21333
|
+
let pathname = "";
|
|
21334
|
+
try {
|
|
21335
|
+
const parsed = new URL(trimmed);
|
|
21336
|
+
host = parsed.hostname;
|
|
21337
|
+
pathname = parsed.pathname;
|
|
21338
|
+
} catch {
|
|
21339
|
+
const scp = trimmed.match(/^(?:[^@\s]+@)?([^:/\s]+):(.+)$/);
|
|
21340
|
+
if (!scp) return null;
|
|
21341
|
+
host = scp[1];
|
|
21342
|
+
pathname = scp[2];
|
|
21343
|
+
}
|
|
21344
|
+
const parts = pathname.replace(/^\/+/, "").replace(/\.git$/, "").split("/");
|
|
21345
|
+
if (parts.length !== 2 || !GITHUB_HOST.test(host) || host.toLowerCase() !== "github.com" && !host.toLowerCase().startsWith("github.") || !GITHUB_NAME.test(parts[0]) || !GITHUB_NAME.test(parts[1])) {
|
|
21346
|
+
return null;
|
|
21347
|
+
}
|
|
21348
|
+
return { host: host.toLowerCase(), owner: parts[0], name: parts[1] };
|
|
21349
|
+
}
|
|
21350
|
+
function parseRun(value) {
|
|
21351
|
+
const source = record2(value);
|
|
21352
|
+
if (!source) return null;
|
|
21353
|
+
const id = numberValue(source.id);
|
|
21354
|
+
const url = stringValue(source.html_url);
|
|
21355
|
+
if (id === null || !url.startsWith("https://")) return null;
|
|
21356
|
+
const actor = record2(source.actor);
|
|
21357
|
+
return {
|
|
21358
|
+
id,
|
|
21359
|
+
name: stringValue(source.name, "Workflow"),
|
|
21360
|
+
displayTitle: stringValue(source.display_title, stringValue(source.name, "Workflow run")),
|
|
21361
|
+
status: workflowStatus(source.status),
|
|
21362
|
+
conclusion: workflowConclusion(source.conclusion),
|
|
21363
|
+
url,
|
|
21364
|
+
runNumber: numberValue(source.run_number) ?? 0,
|
|
21365
|
+
event: stringValue(source.event, "workflow"),
|
|
21366
|
+
branch: stringValue(source.head_branch),
|
|
21367
|
+
commitSha: stringValue(source.head_sha),
|
|
21368
|
+
createdAt: stringValue(source.created_at),
|
|
21369
|
+
updatedAt: stringValue(source.updated_at),
|
|
21370
|
+
actor: stringValue(actor?.login)
|
|
21371
|
+
};
|
|
21372
|
+
}
|
|
21373
|
+
function parseStep(value) {
|
|
21374
|
+
const source = record2(value);
|
|
21375
|
+
if (!source) return null;
|
|
21376
|
+
const number = numberValue(source.number);
|
|
21377
|
+
if (number === null) return null;
|
|
21378
|
+
return {
|
|
21379
|
+
number,
|
|
21380
|
+
name: stringValue(source.name, `Step ${number}`),
|
|
21381
|
+
status: workflowStatus(source.status),
|
|
21382
|
+
conclusion: workflowConclusion(source.conclusion),
|
|
21383
|
+
startedAt: nullableDate(source.started_at),
|
|
21384
|
+
completedAt: nullableDate(source.completed_at)
|
|
21385
|
+
};
|
|
21386
|
+
}
|
|
21387
|
+
function parseJob(value) {
|
|
21388
|
+
const source = record2(value);
|
|
21389
|
+
if (!source) return null;
|
|
21390
|
+
const id = numberValue(source.id);
|
|
21391
|
+
const url = stringValue(source.html_url);
|
|
21392
|
+
if (id === null || !url.startsWith("https://")) return null;
|
|
21393
|
+
return {
|
|
21394
|
+
id,
|
|
21395
|
+
name: stringValue(source.name, "Job"),
|
|
21396
|
+
status: workflowStatus(source.status),
|
|
21397
|
+
conclusion: workflowConclusion(source.conclusion),
|
|
21398
|
+
url,
|
|
21399
|
+
startedAt: nullableDate(source.started_at),
|
|
21400
|
+
completedAt: nullableDate(source.completed_at),
|
|
21401
|
+
steps: Array.isArray(source.steps) ? source.steps.map(parseStep).filter((step) => step !== null) : []
|
|
21402
|
+
};
|
|
21403
|
+
}
|
|
21404
|
+
function parseRunsResponse(value) {
|
|
21405
|
+
const source = record2(value);
|
|
21406
|
+
if (!source || !Array.isArray(source.workflow_runs)) {
|
|
21407
|
+
throw new GitHubActionsRouteError(502, "invalid_response", "GitHub returned an invalid workflow response");
|
|
21408
|
+
}
|
|
21409
|
+
return source.workflow_runs.map(parseRun).filter((run2) => run2 !== null);
|
|
21410
|
+
}
|
|
21411
|
+
function parseJobsResponse(value) {
|
|
21412
|
+
const source = record2(value);
|
|
21413
|
+
if (!source || !Array.isArray(source.jobs)) {
|
|
21414
|
+
throw new GitHubActionsRouteError(502, "invalid_response", "GitHub returned an invalid jobs response");
|
|
21415
|
+
}
|
|
21416
|
+
return source.jobs.map(parseJob).filter((job) => job !== null);
|
|
21417
|
+
}
|
|
21418
|
+
async function runGitHubApi(repository, endpoint) {
|
|
21419
|
+
try {
|
|
21420
|
+
const result = await execFile3("gh", [
|
|
21421
|
+
"api",
|
|
21422
|
+
endpoint,
|
|
21423
|
+
"--hostname",
|
|
21424
|
+
repository.host,
|
|
21425
|
+
"-H",
|
|
21426
|
+
"Accept: application/vnd.github+json"
|
|
21427
|
+
], {
|
|
21428
|
+
encoding: "utf-8",
|
|
21429
|
+
env: { ...process.env, GH_PAGER: "cat", NO_COLOR: "1" },
|
|
21430
|
+
maxBuffer: 8 * 1024 * 1024,
|
|
21431
|
+
timeout: 2e4,
|
|
21432
|
+
windowsHide: true
|
|
21433
|
+
});
|
|
21434
|
+
return JSON.parse(result.stdout);
|
|
21435
|
+
} catch (error) {
|
|
21436
|
+
const failure = error;
|
|
21437
|
+
if (failure.code === "ENOENT") {
|
|
21438
|
+
throw new GitHubActionsRouteError(503, "gh_missing", "Install the GitHub CLI to view workflow runs");
|
|
21439
|
+
}
|
|
21440
|
+
const detail = `${failure.message ?? ""}
|
|
21441
|
+
${failure.stderr ?? ""}`;
|
|
21442
|
+
if (/auth login|not logged|authentication|oauth token/i.test(detail)) {
|
|
21443
|
+
throw new GitHubActionsRouteError(503, "gh_auth_required", "Sign in with `gh auth login` to view workflow runs");
|
|
21444
|
+
}
|
|
21445
|
+
throw new GitHubActionsRouteError(502, "github_api_failed", "GitHub workflow data is unavailable");
|
|
21446
|
+
}
|
|
21447
|
+
}
|
|
21448
|
+
async function resolveRepository(cwd, dependencies) {
|
|
21449
|
+
const project = await dependencies.resolveProject(cwd);
|
|
21450
|
+
if (!project.ok) throw new GitHubActionsRouteError(project.status, "no_git_repository", project.error);
|
|
21451
|
+
if (!project.root) {
|
|
21452
|
+
throw new GitHubActionsRouteError(400, "no_git_repository", "This project is not a Git repository");
|
|
21453
|
+
}
|
|
21454
|
+
let remoteUrl = "";
|
|
21455
|
+
try {
|
|
21456
|
+
remoteUrl = (await dependencies.git(project.root, ["remote", "get-url", "origin"])).stdout;
|
|
21457
|
+
} catch {
|
|
21458
|
+
throw new GitHubActionsRouteError(400, "no_github_remote", "This repository has no origin remote");
|
|
21459
|
+
}
|
|
21460
|
+
const repository = parseGitHubRemote(remoteUrl);
|
|
21461
|
+
if (!repository) {
|
|
21462
|
+
throw new GitHubActionsRouteError(400, "no_github_remote", "The origin remote is not a supported GitHub repository");
|
|
21463
|
+
}
|
|
21464
|
+
const branchResult = await dependencies.git(project.root, ["branch", "--show-current"]);
|
|
21465
|
+
return {
|
|
21466
|
+
repository,
|
|
21467
|
+
branch: branchResult.stdout.trim() || null
|
|
21468
|
+
};
|
|
21469
|
+
}
|
|
21470
|
+
function repositoryName(repository) {
|
|
21471
|
+
return `${repository.owner}/${repository.name}`;
|
|
21472
|
+
}
|
|
21473
|
+
function repositoryUrl(repository) {
|
|
21474
|
+
return `https://${repository.host}/${repository.owner}/${repository.name}`;
|
|
21475
|
+
}
|
|
21476
|
+
function sendRouteError2(res, error) {
|
|
21477
|
+
if (error instanceof GitHubActionsRouteError) {
|
|
21478
|
+
sendJson(res, error.status, { error: error.message, code: error.code });
|
|
21479
|
+
return;
|
|
21480
|
+
}
|
|
21481
|
+
sendJson(res, 500, { error: "Unable to load GitHub Actions", code: "github_api_failed" });
|
|
21482
|
+
}
|
|
21483
|
+
function registerGitHubActionsRoutes(use, dependencies = defaultDependencies) {
|
|
21484
|
+
use("/api/github-actions", async (req, res, next) => {
|
|
21485
|
+
if (req.method !== "GET") return next();
|
|
21486
|
+
const url = new URL(req.url || "", "http://localhost");
|
|
21487
|
+
if (url.pathname !== "/" && url.pathname !== "") return next();
|
|
21488
|
+
const cwd = url.searchParams.get("cwd") ?? "";
|
|
21489
|
+
const requestedLimit = Number(url.searchParams.get("limit") ?? DEFAULT_RUNS);
|
|
21490
|
+
const limit = Number.isInteger(requestedLimit) ? Math.min(MAX_RUNS, Math.max(1, requestedLimit)) : DEFAULT_RUNS;
|
|
21491
|
+
try {
|
|
21492
|
+
const { repository, branch } = await resolveRepository(cwd, dependencies);
|
|
21493
|
+
const endpoint = `repos/${repository.owner}/${repository.name}/actions/runs?per_page=${limit}`;
|
|
21494
|
+
const runs = parseRunsResponse(await dependencies.githubApi(repository, endpoint));
|
|
21495
|
+
const response = {
|
|
21496
|
+
repository: repositoryName(repository),
|
|
21497
|
+
repositoryUrl: repositoryUrl(repository),
|
|
21498
|
+
branch,
|
|
21499
|
+
runs
|
|
21500
|
+
};
|
|
21501
|
+
sendJson(res, 200, response);
|
|
21502
|
+
} catch (error) {
|
|
21503
|
+
sendRouteError2(res, error);
|
|
21504
|
+
}
|
|
21505
|
+
});
|
|
21506
|
+
use("/api/github-actions/jobs", async (req, res, next) => {
|
|
21507
|
+
if (req.method !== "GET") return next();
|
|
21508
|
+
const url = new URL(req.url || "", "http://localhost");
|
|
21509
|
+
if (url.pathname !== "/" && url.pathname !== "") return next();
|
|
21510
|
+
const cwd = url.searchParams.get("cwd") ?? "";
|
|
21511
|
+
const runIdText = url.searchParams.get("runId") ?? "";
|
|
21512
|
+
if (!/^\d+$/.test(runIdText)) {
|
|
21513
|
+
return sendJson(res, 400, { error: "runId must be a positive integer", code: "github_api_failed" });
|
|
21514
|
+
}
|
|
21515
|
+
try {
|
|
21516
|
+
const { repository } = await resolveRepository(cwd, dependencies);
|
|
21517
|
+
const runId = Number(runIdText);
|
|
21518
|
+
const endpoint = `repos/${repository.owner}/${repository.name}/actions/runs/${runId}/jobs?filter=latest&per_page=100`;
|
|
21519
|
+
const jobs = parseJobsResponse(await dependencies.githubApi(repository, endpoint));
|
|
21520
|
+
const response = {
|
|
21521
|
+
repository: repositoryName(repository),
|
|
21522
|
+
runId,
|
|
21523
|
+
jobs
|
|
21524
|
+
};
|
|
21525
|
+
sendJson(res, 200, response);
|
|
21526
|
+
} catch (error) {
|
|
21527
|
+
sendRouteError2(res, error);
|
|
21528
|
+
}
|
|
21529
|
+
});
|
|
21530
|
+
}
|
|
21531
|
+
var execFile3, MAX_RUNS, DEFAULT_RUNS, GITHUB_NAME, GITHUB_HOST, RUN_STATUSES, RUN_CONCLUSIONS, GitHubActionsRouteError, defaultDependencies;
|
|
21532
|
+
var init_github_actions = __esm({
|
|
21533
|
+
"../../server/routes/github-actions.ts"() {
|
|
21534
|
+
init_http();
|
|
21535
|
+
init_gitProject();
|
|
21536
|
+
execFile3 = promisify2(execFileCallback2);
|
|
21537
|
+
MAX_RUNS = 30;
|
|
21538
|
+
DEFAULT_RUNS = 20;
|
|
21539
|
+
GITHUB_NAME = /^[A-Za-z0-9_.-]+$/;
|
|
21540
|
+
GITHUB_HOST = /^[A-Za-z0-9.-]+$/;
|
|
21541
|
+
RUN_STATUSES = /* @__PURE__ */ new Set([
|
|
21542
|
+
"completed",
|
|
21543
|
+
"in_progress",
|
|
21544
|
+
"pending",
|
|
21545
|
+
"queued",
|
|
21546
|
+
"requested",
|
|
21547
|
+
"waiting"
|
|
21548
|
+
]);
|
|
21549
|
+
RUN_CONCLUSIONS = /* @__PURE__ */ new Set([
|
|
21550
|
+
"action_required",
|
|
21551
|
+
"cancelled",
|
|
21552
|
+
"failure",
|
|
21553
|
+
"neutral",
|
|
21554
|
+
"skipped",
|
|
21555
|
+
"stale",
|
|
21556
|
+
"startup_failure",
|
|
21557
|
+
"success",
|
|
21558
|
+
"timed_out"
|
|
21559
|
+
]);
|
|
21560
|
+
GitHubActionsRouteError = class extends Error {
|
|
21561
|
+
constructor(status, code, message) {
|
|
21562
|
+
super(message);
|
|
21563
|
+
this.status = status;
|
|
21564
|
+
this.code = code;
|
|
21565
|
+
}
|
|
21566
|
+
};
|
|
21567
|
+
defaultDependencies = {
|
|
21568
|
+
resolveProject: resolveGitProject,
|
|
21569
|
+
git: runGit,
|
|
21570
|
+
githubApi: runGitHubApi
|
|
21571
|
+
};
|
|
21572
|
+
}
|
|
21573
|
+
});
|
|
21574
|
+
|
|
21575
|
+
// ../../server/routes/vercel-deployments.ts
|
|
21576
|
+
import { execFile as execFileCallback3 } from "node:child_process";
|
|
21577
|
+
import { readFile as readFile15, realpath as realpath8, stat as stat13 } from "node:fs/promises";
|
|
21578
|
+
import { isAbsolute as isAbsolute8, join as join20, resolve as resolve15 } from "node:path";
|
|
21579
|
+
import { promisify as promisify3 } from "node:util";
|
|
21580
|
+
function record3(value) {
|
|
21581
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
21582
|
+
}
|
|
21583
|
+
function stringValue2(value, fallback = "") {
|
|
21584
|
+
return typeof value === "string" ? value : fallback;
|
|
21585
|
+
}
|
|
21586
|
+
function nullableString(value) {
|
|
21587
|
+
return typeof value === "string" && value ? value : null;
|
|
21588
|
+
}
|
|
21589
|
+
function timestamp(value) {
|
|
21590
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
21591
|
+
}
|
|
21592
|
+
function firstString2(source, keys) {
|
|
21593
|
+
if (!source) return "";
|
|
21594
|
+
for (const key2 of keys) {
|
|
21595
|
+
const value = stringValue2(source[key2]);
|
|
21596
|
+
if (value) return value;
|
|
21597
|
+
}
|
|
21598
|
+
return "";
|
|
21599
|
+
}
|
|
21600
|
+
function deploymentState(value) {
|
|
21601
|
+
return typeof value === "string" && DEPLOYMENT_STATES.has(value) ? value : "QUEUED";
|
|
21602
|
+
}
|
|
21603
|
+
function httpsUrl(value, hostnameOnly = false) {
|
|
21604
|
+
const text = stringValue2(value);
|
|
21605
|
+
if (!text) return null;
|
|
21606
|
+
const candidate = hostnameOnly && !text.includes("://") ? `https://${text}` : text;
|
|
21607
|
+
try {
|
|
21608
|
+
const url = new URL(candidate);
|
|
21609
|
+
return url.protocol === "https:" ? url.toString().replace(/\/$/, "") : null;
|
|
21610
|
+
} catch {
|
|
21611
|
+
return null;
|
|
21612
|
+
}
|
|
21613
|
+
}
|
|
21614
|
+
function projectUrlFromInspector(value) {
|
|
21615
|
+
if (!value) return null;
|
|
21616
|
+
try {
|
|
21617
|
+
const url = new URL(value);
|
|
21618
|
+
const parts = url.pathname.split("/").filter(Boolean);
|
|
21619
|
+
if (parts.length < 3) return null;
|
|
21620
|
+
url.pathname = `/${parts.slice(0, -1).join("/")}`;
|
|
21621
|
+
url.search = "";
|
|
21622
|
+
url.hash = "";
|
|
21623
|
+
return url.toString().replace(/\/$/, "");
|
|
21624
|
+
} catch {
|
|
21625
|
+
return null;
|
|
21626
|
+
}
|
|
21627
|
+
}
|
|
21628
|
+
function parseDeployment(value) {
|
|
21629
|
+
const source = record3(value);
|
|
21630
|
+
if (!source) return null;
|
|
21631
|
+
const id = stringValue2(source.uid);
|
|
21632
|
+
const createdAt = timestamp(source.createdAt) ?? timestamp(source.created);
|
|
21633
|
+
if (!DEPLOYMENT_ID.test(id) || createdAt === null) return null;
|
|
21634
|
+
const meta = record3(source.meta);
|
|
21635
|
+
const creator = record3(source.creator);
|
|
21636
|
+
return {
|
|
21637
|
+
id,
|
|
21638
|
+
name: stringValue2(source.name, "Deployment"),
|
|
21639
|
+
url: httpsUrl(source.url, true),
|
|
21640
|
+
inspectorUrl: httpsUrl(source.inspectorUrl),
|
|
21641
|
+
state: deploymentState(source.readyState ?? source.state),
|
|
21642
|
+
target: nullableString(source.target),
|
|
21643
|
+
createdAt,
|
|
21644
|
+
buildingAt: timestamp(source.buildingAt),
|
|
21645
|
+
readyAt: timestamp(source.ready),
|
|
21646
|
+
branch: firstString2(meta, [
|
|
21647
|
+
"githubCommitRef",
|
|
21648
|
+
"gitlabCommitRef",
|
|
21649
|
+
"bitbucketCommitRef",
|
|
21650
|
+
"branchAlias"
|
|
21651
|
+
]),
|
|
21652
|
+
commitSha: firstString2(meta, [
|
|
21653
|
+
"githubCommitSha",
|
|
21654
|
+
"gitlabCommitSha",
|
|
21655
|
+
"bitbucketCommitSha"
|
|
21656
|
+
]),
|
|
21657
|
+
commitMessage: firstString2(meta, [
|
|
21658
|
+
"githubCommitMessage",
|
|
21659
|
+
"gitlabCommitMessage",
|
|
21660
|
+
"bitbucketCommitMessage"
|
|
21661
|
+
]),
|
|
21662
|
+
creator: firstString2(creator, ["username", "githubLogin", "email"]),
|
|
21663
|
+
errorCode: nullableString(source.errorCode),
|
|
21664
|
+
errorMessage: nullableString(source.errorMessage)
|
|
21665
|
+
};
|
|
21666
|
+
}
|
|
21667
|
+
function parseDeploymentsResponse(value) {
|
|
21668
|
+
const source = record3(value);
|
|
21669
|
+
if (!source || !Array.isArray(source.deployments)) {
|
|
21670
|
+
throw new VercelDeploymentsRouteError(
|
|
21671
|
+
502,
|
|
21672
|
+
"invalid_response",
|
|
21673
|
+
"Vercel returned an invalid deployments response"
|
|
21674
|
+
);
|
|
21675
|
+
}
|
|
21676
|
+
return source.deployments.map(parseDeployment).filter((deployment) => deployment !== null);
|
|
21677
|
+
}
|
|
21678
|
+
function parseBuildLog(value) {
|
|
21679
|
+
const source = record3(value);
|
|
21680
|
+
if (!source) return null;
|
|
21681
|
+
const createdAt = timestamp(source.created) ?? timestamp(source.date);
|
|
21682
|
+
const text = stringValue2(source.text);
|
|
21683
|
+
if (createdAt === null || !text) return null;
|
|
21684
|
+
return {
|
|
21685
|
+
id: stringValue2(source.id, `${createdAt}-${text}`),
|
|
21686
|
+
createdAt,
|
|
21687
|
+
type: stringValue2(source.type, "stdout"),
|
|
21688
|
+
text
|
|
21689
|
+
};
|
|
21690
|
+
}
|
|
21691
|
+
function parseBuildLogsResponse(value) {
|
|
21692
|
+
if (!Array.isArray(value)) {
|
|
21693
|
+
throw new VercelDeploymentsRouteError(
|
|
21694
|
+
502,
|
|
21695
|
+
"invalid_response",
|
|
21696
|
+
"Vercel returned an invalid build log response"
|
|
21697
|
+
);
|
|
21698
|
+
}
|
|
21699
|
+
return value.map(parseBuildLog).filter((event) => event !== null).sort((left, right) => left.createdAt - right.createdAt);
|
|
21700
|
+
}
|
|
21701
|
+
function parseProjectFile(value, root) {
|
|
21702
|
+
const source = record3(value);
|
|
21703
|
+
const projectId = stringValue2(source?.projectId);
|
|
21704
|
+
const teamId = stringValue2(source?.orgId);
|
|
21705
|
+
const projectName = stringValue2(source?.projectName, "Vercel project");
|
|
21706
|
+
if (!VERCEL_ID.test(projectId) || !VERCEL_ID.test(teamId)) {
|
|
21707
|
+
throw new VercelDeploymentsRouteError(
|
|
21708
|
+
400,
|
|
21709
|
+
"vercel_project_unlinked",
|
|
21710
|
+
"This project has an invalid .vercel/project.json link"
|
|
21711
|
+
);
|
|
21712
|
+
}
|
|
21713
|
+
return { root, projectId, projectName, teamId };
|
|
21714
|
+
}
|
|
21715
|
+
async function resolveLinkedVercelProject(cwd) {
|
|
21716
|
+
if (!isAbsolute8(cwd)) {
|
|
21717
|
+
throw new VercelDeploymentsRouteError(400, "vercel_project_unlinked", "cwd must be an absolute path");
|
|
21718
|
+
}
|
|
21719
|
+
let root;
|
|
21720
|
+
try {
|
|
21721
|
+
root = await realpath8(resolve15(cwd));
|
|
21722
|
+
if (!(await stat13(root)).isDirectory()) throw new Error("not a directory");
|
|
21723
|
+
} catch {
|
|
21724
|
+
throw new VercelDeploymentsRouteError(404, "vercel_project_unlinked", "Project directory not found");
|
|
21725
|
+
}
|
|
21726
|
+
const projectFile = join20(root, ".vercel", "project.json");
|
|
21727
|
+
try {
|
|
21728
|
+
const info = await stat13(projectFile);
|
|
21729
|
+
if (!info.isFile() || info.size > MAX_PROJECT_FILE_BYTES) throw new Error("invalid project file");
|
|
21730
|
+
return parseProjectFile(JSON.parse(await readFile15(projectFile, "utf8")), root);
|
|
21731
|
+
} catch (error) {
|
|
21732
|
+
if (error instanceof VercelDeploymentsRouteError) throw error;
|
|
21733
|
+
const detail = error;
|
|
21734
|
+
if (detail.code === "ENOENT") {
|
|
21735
|
+
throw new VercelDeploymentsRouteError(
|
|
21736
|
+
400,
|
|
21737
|
+
"vercel_project_unlinked",
|
|
21738
|
+
"Link this project with `vercel link` before viewing deployments"
|
|
21739
|
+
);
|
|
21740
|
+
}
|
|
21741
|
+
throw new VercelDeploymentsRouteError(
|
|
21742
|
+
400,
|
|
21743
|
+
"vercel_project_unlinked",
|
|
21744
|
+
"Unable to read this project's .vercel/project.json link"
|
|
21745
|
+
);
|
|
21746
|
+
}
|
|
21747
|
+
}
|
|
21748
|
+
async function executeVercel(cwd, args) {
|
|
21749
|
+
const cli = resolveAgentCommand("vercel", args);
|
|
21750
|
+
const result = await execFile4(cli.command, cli.args, {
|
|
21751
|
+
cwd,
|
|
21752
|
+
encoding: "utf-8",
|
|
21753
|
+
env: {
|
|
21754
|
+
...process.env,
|
|
21755
|
+
NO_COLOR: "1",
|
|
21756
|
+
VERCEL_TELEMETRY_DISABLED: "1"
|
|
21757
|
+
},
|
|
21758
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
21759
|
+
timeout: 3e4,
|
|
21760
|
+
windowsHide: true,
|
|
21761
|
+
...cli.spawnOptions
|
|
21762
|
+
});
|
|
21763
|
+
return { stdout: result.stdout, stderr: result.stderr };
|
|
21764
|
+
}
|
|
21765
|
+
function parseCliVersion(output) {
|
|
21766
|
+
const match = output.match(/(?:^|\s)(\d+)\.(\d+)\.(\d+)(?:\s|$)/);
|
|
21767
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
|
|
21768
|
+
}
|
|
21769
|
+
function isVersionAtLeast(actual, minimum) {
|
|
21770
|
+
for (let index = 0; index < minimum.length; index += 1) {
|
|
21771
|
+
if (actual[index] > minimum[index]) return true;
|
|
21772
|
+
if (actual[index] < minimum[index]) return false;
|
|
21773
|
+
}
|
|
21774
|
+
return true;
|
|
21775
|
+
}
|
|
21776
|
+
function mapVercelFailure(error) {
|
|
21777
|
+
if (error instanceof VercelDeploymentsRouteError) return error;
|
|
21778
|
+
const failure = error;
|
|
21779
|
+
if (failure.code === "ENOENT") {
|
|
21780
|
+
return new VercelDeploymentsRouteError(503, "vercel_missing", "Install Vercel CLI to view deployments");
|
|
21781
|
+
}
|
|
21782
|
+
const detail = `${failure.message ?? ""}
|
|
21783
|
+
${failure.stderr ?? ""}
|
|
21784
|
+
${failure.stdout ?? ""}`;
|
|
21785
|
+
if (/not authenticated|not logged|log in|login|authentication|invalid token|unauthorized|401/i.test(detail)) {
|
|
21786
|
+
return new VercelDeploymentsRouteError(
|
|
21787
|
+
503,
|
|
21788
|
+
"vercel_auth_required",
|
|
21789
|
+
"Sign in with `vercel login` to view deployments"
|
|
21790
|
+
);
|
|
21791
|
+
}
|
|
21792
|
+
if (/forbidden|access denied|not authorized|permission|403/i.test(detail)) {
|
|
21793
|
+
return new VercelDeploymentsRouteError(
|
|
21794
|
+
403,
|
|
21795
|
+
"vercel_access_denied",
|
|
21796
|
+
"Your Vercel account cannot access this linked project"
|
|
21797
|
+
);
|
|
21798
|
+
}
|
|
21799
|
+
return new VercelDeploymentsRouteError(502, "vercel_api_failed", "Vercel deployment data is unavailable");
|
|
21800
|
+
}
|
|
21801
|
+
async function runVercelApi(project, endpoint, runCommand = executeVercel) {
|
|
21802
|
+
try {
|
|
21803
|
+
const versionResult = await runCommand(project.root, ["--version"]);
|
|
21804
|
+
const version = parseCliVersion(`${versionResult.stdout}
|
|
21805
|
+
${versionResult.stderr}`);
|
|
21806
|
+
if (!version || !isVersionAtLeast(version, MINIMUM_API_CLI_VERSION)) {
|
|
21807
|
+
throw new VercelDeploymentsRouteError(
|
|
21808
|
+
503,
|
|
21809
|
+
"vercel_cli_too_old",
|
|
21810
|
+
"Update Vercel CLI to version 50.5.1 or newer to view deployments safely"
|
|
21811
|
+
);
|
|
21812
|
+
}
|
|
21813
|
+
const result = await runCommand(project.root, [
|
|
21814
|
+
"api",
|
|
21815
|
+
endpoint,
|
|
21816
|
+
"--raw",
|
|
21817
|
+
"--cwd",
|
|
21818
|
+
project.root,
|
|
21819
|
+
"--non-interactive",
|
|
21820
|
+
"--no-color"
|
|
21821
|
+
]);
|
|
21822
|
+
try {
|
|
21823
|
+
return JSON.parse(result.stdout);
|
|
21824
|
+
} catch {
|
|
21825
|
+
throw new VercelDeploymentsRouteError(
|
|
21826
|
+
502,
|
|
21827
|
+
"invalid_response",
|
|
21828
|
+
"Vercel returned invalid JSON"
|
|
21829
|
+
);
|
|
21830
|
+
}
|
|
21831
|
+
} catch (error) {
|
|
21832
|
+
throw mapVercelFailure(error);
|
|
21833
|
+
}
|
|
21834
|
+
}
|
|
21835
|
+
function boundedLimit(value, fallback, maximum) {
|
|
21836
|
+
const requested = Number(value ?? fallback);
|
|
21837
|
+
return Number.isInteger(requested) ? Math.min(maximum, Math.max(1, requested)) : fallback;
|
|
21838
|
+
}
|
|
21839
|
+
function sendRouteError3(res, error) {
|
|
21840
|
+
const detail = mapVercelFailure(error);
|
|
21841
|
+
sendJson(res, detail.status, { error: detail.message, code: detail.code });
|
|
21842
|
+
}
|
|
21843
|
+
function registerVercelDeploymentRoutes(use, dependencies = defaultDependencies2) {
|
|
21844
|
+
use("/api/vercel-deployments", async (req, res, next) => {
|
|
21845
|
+
if (req.method !== "GET") return next();
|
|
21846
|
+
const url = new URL(req.url || "", "http://localhost");
|
|
21847
|
+
if (url.pathname !== "/" && url.pathname !== "") return next();
|
|
21848
|
+
const limit = boundedLimit(url.searchParams.get("limit"), DEFAULT_DEPLOYMENT_LIMIT, MAX_DEPLOYMENT_LIMIT);
|
|
21849
|
+
try {
|
|
21850
|
+
const project = await dependencies.resolveProject(url.searchParams.get("cwd") ?? "");
|
|
21851
|
+
const endpoint = `/v7/deployments?projectId=${encodeURIComponent(project.projectId)}&teamId=${encodeURIComponent(project.teamId)}&limit=${limit}`;
|
|
21852
|
+
const deployments = parseDeploymentsResponse(await dependencies.vercelApi(project, endpoint));
|
|
21853
|
+
const response = {
|
|
21854
|
+
projectId: project.projectId,
|
|
21855
|
+
projectName: project.projectName,
|
|
21856
|
+
teamId: project.teamId,
|
|
21857
|
+
projectUrl: projectUrlFromInspector(deployments[0]?.inspectorUrl ?? null),
|
|
21858
|
+
deployments
|
|
21859
|
+
};
|
|
21860
|
+
sendJson(res, 200, response);
|
|
21861
|
+
} catch (error) {
|
|
21862
|
+
sendRouteError3(res, error);
|
|
21863
|
+
}
|
|
21864
|
+
});
|
|
21865
|
+
use("/api/vercel-deployments/build-logs", async (req, res, next) => {
|
|
21866
|
+
if (req.method !== "GET") return next();
|
|
21867
|
+
const url = new URL(req.url || "", "http://localhost");
|
|
21868
|
+
if (url.pathname !== "/" && url.pathname !== "") return next();
|
|
21869
|
+
const deploymentId = url.searchParams.get("deploymentId") ?? "";
|
|
21870
|
+
if (!DEPLOYMENT_ID.test(deploymentId)) {
|
|
21871
|
+
return sendJson(res, 400, {
|
|
21872
|
+
error: "deploymentId must be a Vercel deployment ID",
|
|
21873
|
+
code: "vercel_api_failed"
|
|
21874
|
+
});
|
|
21875
|
+
}
|
|
21876
|
+
const limit = boundedLimit(url.searchParams.get("limit"), DEFAULT_LOG_LIMIT, MAX_LOG_LIMIT);
|
|
21877
|
+
try {
|
|
21878
|
+
const project = await dependencies.resolveProject(url.searchParams.get("cwd") ?? "");
|
|
21879
|
+
const endpoint = `/v3/deployments/${deploymentId}/events?teamId=${encodeURIComponent(project.teamId)}&direction=backward&limit=${limit}`;
|
|
21880
|
+
const events = parseBuildLogsResponse(await dependencies.vercelApi(project, endpoint));
|
|
21881
|
+
const response = { deploymentId, events };
|
|
21882
|
+
sendJson(res, 200, response);
|
|
21883
|
+
} catch (error) {
|
|
21884
|
+
sendRouteError3(res, error);
|
|
21885
|
+
}
|
|
21886
|
+
});
|
|
21887
|
+
}
|
|
21888
|
+
var execFile4, DEFAULT_DEPLOYMENT_LIMIT, MAX_DEPLOYMENT_LIMIT, DEFAULT_LOG_LIMIT, MAX_LOG_LIMIT, MAX_PROJECT_FILE_BYTES, MINIMUM_API_CLI_VERSION, VERCEL_ID, DEPLOYMENT_ID, DEPLOYMENT_STATES, VercelDeploymentsRouteError, defaultDependencies2;
|
|
21889
|
+
var init_vercel_deployments = __esm({
|
|
21890
|
+
"../../server/routes/vercel-deployments.ts"() {
|
|
21891
|
+
init_http();
|
|
21892
|
+
init_binaryResolver();
|
|
21893
|
+
execFile4 = promisify3(execFileCallback3);
|
|
21894
|
+
DEFAULT_DEPLOYMENT_LIMIT = 20;
|
|
21895
|
+
MAX_DEPLOYMENT_LIMIT = 30;
|
|
21896
|
+
DEFAULT_LOG_LIMIT = 200;
|
|
21897
|
+
MAX_LOG_LIMIT = 500;
|
|
21898
|
+
MAX_PROJECT_FILE_BYTES = 64 * 1024;
|
|
21899
|
+
MINIMUM_API_CLI_VERSION = [50, 5, 1];
|
|
21900
|
+
VERCEL_ID = /^[A-Za-z0-9_-]+$/;
|
|
21901
|
+
DEPLOYMENT_ID = /^dpl_[A-Za-z0-9]+$/;
|
|
21902
|
+
DEPLOYMENT_STATES = /* @__PURE__ */ new Set([
|
|
21903
|
+
"BLOCKED",
|
|
21904
|
+
"BUILDING",
|
|
21905
|
+
"CANCELED",
|
|
21906
|
+
"ERROR",
|
|
21907
|
+
"INITIALIZING",
|
|
21908
|
+
"QUEUED",
|
|
21909
|
+
"READY"
|
|
21910
|
+
]);
|
|
21911
|
+
VercelDeploymentsRouteError = class extends Error {
|
|
21912
|
+
constructor(status, code, message) {
|
|
21913
|
+
super(message);
|
|
21914
|
+
this.status = status;
|
|
21915
|
+
this.code = code;
|
|
21916
|
+
}
|
|
21917
|
+
};
|
|
21918
|
+
defaultDependencies2 = {
|
|
21919
|
+
resolveProject: resolveLinkedVercelProject,
|
|
21920
|
+
vercelApi: runVercelApi
|
|
21921
|
+
};
|
|
21922
|
+
}
|
|
21923
|
+
});
|
|
21924
|
+
|
|
21141
21925
|
// ../../server/lib/projectIcon.ts
|
|
21142
|
-
import { realpath as
|
|
21143
|
-
import { basename as basename9, extname, join as
|
|
21926
|
+
import { realpath as realpath9, stat as stat14 } from "node:fs/promises";
|
|
21927
|
+
import { basename as basename9, extname, join as join21, relative as relative8, sep as sep10 } from "node:path";
|
|
21144
21928
|
function namedIconCandidates(root) {
|
|
21145
21929
|
const name = basename9(root);
|
|
21146
21930
|
if (!name || name.startsWith(".")) return [];
|
|
21147
21931
|
return ["public", "assets", "static", "."].flatMap(
|
|
21148
|
-
(dir) => NAMED_ICON_EXTENSIONS.map((ext) =>
|
|
21932
|
+
(dir) => NAMED_ICON_EXTENSIONS.map((ext) => join21(dir, `${name}${ext}`))
|
|
21149
21933
|
);
|
|
21150
21934
|
}
|
|
21151
21935
|
function iconContentType(path) {
|
|
@@ -21158,7 +21942,7 @@ function isInside(root, candidate) {
|
|
|
21158
21942
|
async function resolveProjectIcon(projectPath) {
|
|
21159
21943
|
let root;
|
|
21160
21944
|
try {
|
|
21161
|
-
root = await
|
|
21945
|
+
root = await realpath9(projectPath);
|
|
21162
21946
|
} catch {
|
|
21163
21947
|
return null;
|
|
21164
21948
|
}
|
|
@@ -21168,11 +21952,11 @@ async function resolveProjectIcon(projectPath) {
|
|
|
21168
21952
|
...PROJECT_ICON_CANDIDATES.slice(6)
|
|
21169
21953
|
];
|
|
21170
21954
|
for (const candidate of candidates) {
|
|
21171
|
-
const guess =
|
|
21955
|
+
const guess = join21(root, candidate);
|
|
21172
21956
|
try {
|
|
21173
|
-
const resolved = await
|
|
21957
|
+
const resolved = await realpath9(guess);
|
|
21174
21958
|
if (!isInside(root, resolved)) continue;
|
|
21175
|
-
const info = await
|
|
21959
|
+
const info = await stat14(resolved);
|
|
21176
21960
|
if (!info.isFile() || info.size === 0 || info.size > MAX_ICON_BYTES) continue;
|
|
21177
21961
|
if (!iconContentType(resolved)) continue;
|
|
21178
21962
|
return resolved;
|
|
@@ -21230,13 +22014,13 @@ var init_projectIcon = __esm({
|
|
|
21230
22014
|
|
|
21231
22015
|
// ../../server/routes/project-icon.ts
|
|
21232
22016
|
import { createReadStream } from "node:fs";
|
|
21233
|
-
import { isAbsolute as
|
|
22017
|
+
import { isAbsolute as isAbsolute9 } from "node:path";
|
|
21234
22018
|
function registerProjectIconRoutes(use) {
|
|
21235
22019
|
use("/api/project-icon", async (req, res, next) => {
|
|
21236
22020
|
if (req.method !== "GET") return next();
|
|
21237
22021
|
const url = new URL(req.url || "", "http://localhost");
|
|
21238
22022
|
const cwd = url.searchParams.get("cwd") ?? "";
|
|
21239
|
-
if (!
|
|
22023
|
+
if (!isAbsolute9(cwd)) {
|
|
21240
22024
|
return sendJson(res, 400, { error: "cwd must be an absolute path" });
|
|
21241
22025
|
}
|
|
21242
22026
|
const icon = await resolveProjectIcon(cwd);
|
|
@@ -21321,14 +22105,14 @@ var init_local_file = __esm({
|
|
|
21321
22105
|
});
|
|
21322
22106
|
|
|
21323
22107
|
// ../../server/routes/mcp.ts
|
|
21324
|
-
import { execFile as
|
|
21325
|
-
import { isAbsolute as
|
|
21326
|
-
import { readFile as
|
|
22108
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
22109
|
+
import { isAbsolute as isAbsolute10, join as join22 } from "node:path";
|
|
22110
|
+
import { readFile as readFile16 } from "node:fs/promises";
|
|
21327
22111
|
import { homedir as homedir7 } from "node:os";
|
|
21328
22112
|
async function readMcpConfigs(cwd) {
|
|
21329
22113
|
const configs = {};
|
|
21330
22114
|
try {
|
|
21331
|
-
const raw = await
|
|
22115
|
+
const raw = await readFile16(join22(homedir7(), ".claude.json"), "utf-8");
|
|
21332
22116
|
const parsed = JSON.parse(raw);
|
|
21333
22117
|
if (parsed.mcpServers && typeof parsed.mcpServers === "object") {
|
|
21334
22118
|
Object.assign(configs, parsed.mcpServers);
|
|
@@ -21346,16 +22130,16 @@ async function readMcpConfigs(cwd) {
|
|
|
21346
22130
|
} catch {
|
|
21347
22131
|
}
|
|
21348
22132
|
const otherSources = [
|
|
21349
|
-
|
|
22133
|
+
join22(homedir7(), ".claude", "settings.json"),
|
|
21350
22134
|
// global settings
|
|
21351
|
-
|
|
22135
|
+
join22(cwd, ".mcp.json"),
|
|
21352
22136
|
// project
|
|
21353
|
-
|
|
22137
|
+
join22(cwd, ".claude", "settings.local.json")
|
|
21354
22138
|
// project local
|
|
21355
22139
|
];
|
|
21356
22140
|
for (const path of otherSources) {
|
|
21357
22141
|
try {
|
|
21358
|
-
const raw = await
|
|
22142
|
+
const raw = await readFile16(path, "utf-8");
|
|
21359
22143
|
const parsed = JSON.parse(raw);
|
|
21360
22144
|
if (parsed.mcpServers && typeof parsed.mcpServers === "object") {
|
|
21361
22145
|
Object.assign(configs, parsed.mcpServers);
|
|
@@ -21398,18 +22182,18 @@ async function getMcpServers(cwd) {
|
|
|
21398
22182
|
return { servers: cached.servers, configs: cached.configs };
|
|
21399
22183
|
}
|
|
21400
22184
|
const configs = await readMcpConfigs(cwd);
|
|
21401
|
-
return new Promise((
|
|
22185
|
+
return new Promise((resolve22) => {
|
|
21402
22186
|
const env = { ...process.env };
|
|
21403
22187
|
delete env.CLAUDECODE;
|
|
21404
22188
|
const cli = resolveAgentCommand("claude", ["mcp", "list"]);
|
|
21405
|
-
|
|
22189
|
+
execFile5(cli.command, cli.args, { cwd, env, timeout: 15e3, ...cli.spawnOptions }, (err, stdout) => {
|
|
21406
22190
|
if (err) {
|
|
21407
|
-
|
|
22191
|
+
resolve22({ servers: cached?.servers ?? [], configs });
|
|
21408
22192
|
return;
|
|
21409
22193
|
}
|
|
21410
22194
|
const servers = parseMcpListOutput(stdout);
|
|
21411
22195
|
cache.set(cwd, { servers, configs, timestamp: Date.now() });
|
|
21412
|
-
|
|
22196
|
+
resolve22({ servers, configs });
|
|
21413
22197
|
});
|
|
21414
22198
|
});
|
|
21415
22199
|
}
|
|
@@ -21419,7 +22203,7 @@ function registerMcpRoutes(use) {
|
|
|
21419
22203
|
const url = new URL(req.url || "", `http://${req.headers.host}`);
|
|
21420
22204
|
const cwd = url.searchParams.get("cwd");
|
|
21421
22205
|
const refresh = url.searchParams.get("refresh") === "1";
|
|
21422
|
-
if (!cwd || !
|
|
22206
|
+
if (!cwd || !isAbsolute10(cwd)) {
|
|
21423
22207
|
return sendJson(res, 400, { error: "cwd must be an absolute path" });
|
|
21424
22208
|
}
|
|
21425
22209
|
if (refresh) clearMcpCache(cwd);
|
|
@@ -21531,7 +22315,7 @@ var init_diff_utils = __esm({
|
|
|
21531
22315
|
function isObject9(value) {
|
|
21532
22316
|
return typeof value === "object" && value !== null;
|
|
21533
22317
|
}
|
|
21534
|
-
function
|
|
22318
|
+
function firstString3(...values) {
|
|
21535
22319
|
return values.find((value) => typeof value === "string") ?? "";
|
|
21536
22320
|
}
|
|
21537
22321
|
function truncate(value, length = 140) {
|
|
@@ -21778,19 +22562,19 @@ function nativeWebPresentation(input) {
|
|
|
21778
22562
|
if (type === "open_page" || type === "openPage") {
|
|
21779
22563
|
return {
|
|
21780
22564
|
label: "Open page",
|
|
21781
|
-
summary:
|
|
22565
|
+
summary: firstString3(action?.url, input.query),
|
|
21782
22566
|
styleName: "WebSearch"
|
|
21783
22567
|
};
|
|
21784
22568
|
}
|
|
21785
22569
|
if (type === "find_in_page" || type === "findInPage") {
|
|
21786
22570
|
return {
|
|
21787
22571
|
label: "Find on page",
|
|
21788
|
-
summary: [
|
|
22572
|
+
summary: [firstString3(action?.pattern), firstString3(action?.url)].filter(Boolean).join(" \xB7 "),
|
|
21789
22573
|
styleName: "WebSearch"
|
|
21790
22574
|
};
|
|
21791
22575
|
}
|
|
21792
22576
|
const queries = Array.isArray(action?.queries) ? action.queries.filter((query5) => typeof query5 === "string") : [];
|
|
21793
|
-
const query4 =
|
|
22577
|
+
const query4 = firstString3(action?.query, input.query);
|
|
21794
22578
|
return {
|
|
21795
22579
|
label: "Search web",
|
|
21796
22580
|
summary: compactValues([query4, ...queries]),
|
|
@@ -21798,7 +22582,7 @@ function nativeWebPresentation(input) {
|
|
|
21798
22582
|
};
|
|
21799
22583
|
}
|
|
21800
22584
|
function schemaFreeSummary(input) {
|
|
21801
|
-
const gist =
|
|
22585
|
+
const gist = firstString3(...SCHEMA_FREE_GIST_KEYS.map((key2) => input[key2]));
|
|
21802
22586
|
if (gist) return truncate(gist);
|
|
21803
22587
|
for (const [key2, value] of Object.entries(input)) {
|
|
21804
22588
|
if (!Array.isArray(value)) continue;
|
|
@@ -21808,11 +22592,11 @@ function schemaFreeSummary(input) {
|
|
|
21808
22592
|
return "";
|
|
21809
22593
|
}
|
|
21810
22594
|
function workflowSummary(input) {
|
|
21811
|
-
const description =
|
|
22595
|
+
const description = firstString3(input.description);
|
|
21812
22596
|
if (description) return truncate(description);
|
|
21813
|
-
const script =
|
|
22597
|
+
const script = firstString3(input.script);
|
|
21814
22598
|
const metaName = script ? extractJsStringPropertyValues(script, "name")[0] ?? "" : "";
|
|
21815
|
-
return metaName ||
|
|
22599
|
+
return metaName || firstString3(input.scriptPath);
|
|
21816
22600
|
}
|
|
21817
22601
|
function firstStringValue(input) {
|
|
21818
22602
|
const keys = Object.keys(input);
|
|
@@ -21889,19 +22673,19 @@ function defaultToolSummary(tc) {
|
|
|
21889
22673
|
case "ToolSearch":
|
|
21890
22674
|
return String(input.query ?? "");
|
|
21891
22675
|
case "SendMessage": {
|
|
21892
|
-
const recipient =
|
|
21893
|
-
const gist = truncate(
|
|
22676
|
+
const recipient = firstString3(input.to, input.recipient);
|
|
22677
|
+
const gist = truncate(firstString3(input.summary, input.message, input.content));
|
|
21894
22678
|
return [recipient, gist].filter(Boolean).join(" \xB7 ");
|
|
21895
22679
|
}
|
|
21896
22680
|
case "ListAgents":
|
|
21897
22681
|
case "TaskList":
|
|
21898
22682
|
return "";
|
|
21899
22683
|
case "TaskCreate":
|
|
21900
|
-
return truncate(
|
|
22684
|
+
return truncate(firstString3(input.subject, input.description));
|
|
21901
22685
|
case "TaskUpdate": {
|
|
21902
22686
|
const taskId = String(input.taskId ?? "");
|
|
21903
22687
|
const blockers = Array.isArray(input.addBlockedBy) ? input.addBlockedBy.filter((id) => typeof id === "string") : [];
|
|
21904
|
-
const change =
|
|
22688
|
+
const change = firstString3(input.status) || (blockers.length > 0 ? `blocked by ${blockers.join(", ")}` : "");
|
|
21905
22689
|
return change ? `${taskId} \u2192 ${change}` : taskId;
|
|
21906
22690
|
}
|
|
21907
22691
|
case "TaskOutput":
|
|
@@ -22201,8 +22985,8 @@ function copilotText(value) {
|
|
|
22201
22985
|
if (!Array.isArray(value)) return "";
|
|
22202
22986
|
return value.flatMap((part) => {
|
|
22203
22987
|
if (typeof part === "string") return part ? [part] : [];
|
|
22204
|
-
const
|
|
22205
|
-
const text = str(
|
|
22988
|
+
const record4 = asRecord5(part);
|
|
22989
|
+
const text = str(record4.text) || str(record4.content);
|
|
22206
22990
|
return text ? [text] : [];
|
|
22207
22991
|
}).join("\n");
|
|
22208
22992
|
}
|
|
@@ -22534,7 +23318,7 @@ var init_summaryFolds = __esm({
|
|
|
22534
23318
|
});
|
|
22535
23319
|
|
|
22536
23320
|
// ../../server/lib/missionControlSummary.ts
|
|
22537
|
-
import { open as open7, stat as
|
|
23321
|
+
import { open as open7, stat as stat15 } from "node:fs/promises";
|
|
22538
23322
|
function foldLine(acc, line) {
|
|
22539
23323
|
const trimmed = line.trim();
|
|
22540
23324
|
if (!trimmed) return;
|
|
@@ -22544,10 +23328,10 @@ function foldLine(acc, line) {
|
|
|
22544
23328
|
} catch {
|
|
22545
23329
|
return;
|
|
22546
23330
|
}
|
|
22547
|
-
const
|
|
22548
|
-
if (
|
|
22549
|
-
acc.startedAt ??=
|
|
22550
|
-
acc.lastEventAt =
|
|
23331
|
+
const timestamp2 = str(entry.timestamp);
|
|
23332
|
+
if (timestamp2) {
|
|
23333
|
+
acc.startedAt ??= timestamp2;
|
|
23334
|
+
acc.lastEventAt = timestamp2;
|
|
22551
23335
|
}
|
|
22552
23336
|
foldSummaryEntry(acc, entry);
|
|
22553
23337
|
}
|
|
@@ -22609,7 +23393,7 @@ async function readSince(filePath, from, to) {
|
|
|
22609
23393
|
async function summarizeSession(sessionId, filePath) {
|
|
22610
23394
|
let size;
|
|
22611
23395
|
try {
|
|
22612
|
-
size = (await
|
|
23396
|
+
size = (await stat15(filePath)).size;
|
|
22613
23397
|
} catch {
|
|
22614
23398
|
return null;
|
|
22615
23399
|
}
|
|
@@ -22766,14 +23550,14 @@ var init_models = __esm({
|
|
|
22766
23550
|
});
|
|
22767
23551
|
|
|
22768
23552
|
// ../../server/lib/notificationHistory.ts
|
|
22769
|
-
import { mkdir as mkdir5, readFile as
|
|
23553
|
+
import { mkdir as mkdir5, readFile as readFile17 } from "node:fs/promises";
|
|
22770
23554
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
22771
23555
|
import { homedir as homedir8 } from "node:os";
|
|
22772
|
-
import { dirname as dirname9, join as
|
|
23556
|
+
import { dirname as dirname9, join as join23 } from "node:path";
|
|
22773
23557
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
22774
23558
|
async function load() {
|
|
22775
23559
|
if (entries) return entries;
|
|
22776
|
-
loadPromise ??=
|
|
23560
|
+
loadPromise ??= readFile17(NOTIFICATION_HISTORY_FILE, "utf-8").then((raw) => {
|
|
22777
23561
|
const parsed = JSON.parse(raw);
|
|
22778
23562
|
return Array.isArray(parsed) ? parsed.filter(isEntry) : [];
|
|
22779
23563
|
}).catch(() => []).then((loaded2) => {
|
|
@@ -22857,7 +23641,7 @@ var NOTIFICATION_HISTORY_FILE, MAX_ENTRIES, PERSIST_DEBOUNCE_MS, entries, loadPr
|
|
|
22857
23641
|
var init_notificationHistory = __esm({
|
|
22858
23642
|
"../../server/lib/notificationHistory.ts"() {
|
|
22859
23643
|
init_atomicJsonFile();
|
|
22860
|
-
NOTIFICATION_HISTORY_FILE =
|
|
23644
|
+
NOTIFICATION_HISTORY_FILE = join23(homedir8(), ".cogpit", "notifications.json");
|
|
22861
23645
|
MAX_ENTRIES = 200;
|
|
22862
23646
|
PERSIST_DEBOUNCE_MS = 500;
|
|
22863
23647
|
entries = null;
|
|
@@ -22905,7 +23689,7 @@ var init_notifications = __esm({
|
|
|
22905
23689
|
});
|
|
22906
23690
|
|
|
22907
23691
|
// ../../server/lib/systemProcesses.ts
|
|
22908
|
-
import { execFile as
|
|
23692
|
+
import { execFile as execFile6 } from "node:child_process";
|
|
22909
23693
|
function parseEtimeSeconds(etime) {
|
|
22910
23694
|
const match = /^(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+)$/.exec(etime.trim());
|
|
22911
23695
|
if (!match) return 0;
|
|
@@ -23026,12 +23810,12 @@ function classifyProcesses(rows, selfPid) {
|
|
|
23026
23810
|
}).slice(0, MAX_LISTED_PROCESSES);
|
|
23027
23811
|
}
|
|
23028
23812
|
function listSystemProcesses() {
|
|
23029
|
-
return new Promise((
|
|
23030
|
-
|
|
23813
|
+
return new Promise((resolve22, reject) => {
|
|
23814
|
+
execFile6(
|
|
23031
23815
|
"ps",
|
|
23032
23816
|
["-axo", "pid=,ppid=,pcpu=,rss=,etime=,args="],
|
|
23033
23817
|
{ maxBuffer: 8 * 1024 * 1024 },
|
|
23034
|
-
(error, stdout) => error ? reject(error) :
|
|
23818
|
+
(error, stdout) => error ? reject(error) : resolve22(stdout)
|
|
23035
23819
|
);
|
|
23036
23820
|
});
|
|
23037
23821
|
}
|
|
@@ -23065,7 +23849,7 @@ var init_systemProcesses = __esm({
|
|
|
23065
23849
|
});
|
|
23066
23850
|
|
|
23067
23851
|
// ../../server/lib/desktopNotify.ts
|
|
23068
|
-
import { execFile as
|
|
23852
|
+
import { execFile as execFile7 } from "node:child_process";
|
|
23069
23853
|
function parentMessagePort() {
|
|
23070
23854
|
const { parentPort } = process;
|
|
23071
23855
|
return parentPort && typeof parentPort.postMessage === "function" ? parentPort : null;
|
|
@@ -23078,7 +23862,7 @@ function showNotification(title, body, nav, historyId) {
|
|
|
23078
23862
|
return;
|
|
23079
23863
|
}
|
|
23080
23864
|
if (process.platform === "darwin") {
|
|
23081
|
-
|
|
23865
|
+
execFile7(
|
|
23082
23866
|
"osascript",
|
|
23083
23867
|
["-e", `display notification "${escapeAppleScript(body)}" with title "${escapeAppleScript(title)}"`],
|
|
23084
23868
|
// This is the standalone server's only desktop channel, so a silent
|
|
@@ -23119,9 +23903,9 @@ var init_notifications2 = __esm({
|
|
|
23119
23903
|
});
|
|
23120
23904
|
|
|
23121
23905
|
// ../../server/lib/pushConfig.ts
|
|
23122
|
-
import { readFileSync as
|
|
23906
|
+
import { readFileSync as readFileSync3, statSync as statSync3 } from "node:fs";
|
|
23123
23907
|
import { homedir as homedir9 } from "node:os";
|
|
23124
|
-
import { join as
|
|
23908
|
+
import { join as join24 } from "node:path";
|
|
23125
23909
|
function warnOnce(message) {
|
|
23126
23910
|
if (lastWarning === message) return;
|
|
23127
23911
|
lastWarning = message;
|
|
@@ -23132,7 +23916,7 @@ function asString(value) {
|
|
|
23132
23916
|
}
|
|
23133
23917
|
function fileMtime(path) {
|
|
23134
23918
|
try {
|
|
23135
|
-
return
|
|
23919
|
+
return statSync3(path).mtimeMs;
|
|
23136
23920
|
} catch {
|
|
23137
23921
|
return null;
|
|
23138
23922
|
}
|
|
@@ -23147,8 +23931,8 @@ function warnIfExposed(path, mode) {
|
|
|
23147
23931
|
function readConfigFile(path) {
|
|
23148
23932
|
let raw;
|
|
23149
23933
|
try {
|
|
23150
|
-
warnIfExposed(path,
|
|
23151
|
-
raw =
|
|
23934
|
+
warnIfExposed(path, statSync3(path).mode);
|
|
23935
|
+
raw = readFileSync3(path, "utf8");
|
|
23152
23936
|
} catch (err) {
|
|
23153
23937
|
const code = err.code;
|
|
23154
23938
|
if (code !== "ENOENT") warnOnce(`Could not read ${path}: ${code ?? String(err)}`);
|
|
@@ -23181,7 +23965,7 @@ function normalizeBaseUrl(value, label) {
|
|
|
23181
23965
|
}
|
|
23182
23966
|
return parsed.toString().replace(/\/+$/, "");
|
|
23183
23967
|
}
|
|
23184
|
-
function
|
|
23968
|
+
function resolve16(path) {
|
|
23185
23969
|
const file = readConfigFile(path);
|
|
23186
23970
|
const topic = asString(process.env.COGPIT_NTFY_TOPIC) ?? asString(file.topic);
|
|
23187
23971
|
if (!topic) return null;
|
|
@@ -23209,14 +23993,14 @@ function getPushConfig(path = PUSH_CONFIG_FILE) {
|
|
|
23209
23993
|
process.env.COGPIT_PUBLIC_URL
|
|
23210
23994
|
].join("\0");
|
|
23211
23995
|
if (cache3?.key === key2) return cache3.config;
|
|
23212
|
-
const config =
|
|
23996
|
+
const config = resolve16(path);
|
|
23213
23997
|
cache3 = { key: key2, config };
|
|
23214
23998
|
return config;
|
|
23215
23999
|
}
|
|
23216
24000
|
var PUSH_CONFIG_FILE, DEFAULT_NTFY_URL, TOPIC_PATTERN, cache3, lastWarning;
|
|
23217
24001
|
var init_pushConfig = __esm({
|
|
23218
24002
|
"../../server/lib/pushConfig.ts"() {
|
|
23219
|
-
PUSH_CONFIG_FILE =
|
|
24003
|
+
PUSH_CONFIG_FILE = join24(homedir9(), ".cogpit", "push.json");
|
|
23220
24004
|
DEFAULT_NTFY_URL = "https://ntfy.sh";
|
|
23221
24005
|
TOPIC_PATTERN = /^[-_A-Za-z0-9]{1,64}$/;
|
|
23222
24006
|
cache3 = null;
|
|
@@ -23831,22 +24615,22 @@ async function handleBackgroundTasks(req, res, next) {
|
|
|
23831
24615
|
const portAlive = {};
|
|
23832
24616
|
await Promise.all(
|
|
23833
24617
|
allPorts.map(
|
|
23834
|
-
(port) => new Promise((
|
|
24618
|
+
(port) => new Promise((resolve22) => {
|
|
23835
24619
|
const socket = createConnection({ port, host: "127.0.0.1" });
|
|
23836
24620
|
socket.setTimeout(500);
|
|
23837
24621
|
socket.on("connect", () => {
|
|
23838
24622
|
portAlive[port] = true;
|
|
23839
24623
|
socket.destroy();
|
|
23840
|
-
|
|
24624
|
+
resolve22();
|
|
23841
24625
|
});
|
|
23842
24626
|
socket.on("timeout", () => {
|
|
23843
24627
|
portAlive[port] = false;
|
|
23844
24628
|
socket.destroy();
|
|
23845
|
-
|
|
24629
|
+
resolve22();
|
|
23846
24630
|
});
|
|
23847
24631
|
socket.on("error", () => {
|
|
23848
24632
|
portAlive[port] = false;
|
|
23849
|
-
|
|
24633
|
+
resolve22();
|
|
23850
24634
|
});
|
|
23851
24635
|
})
|
|
23852
24636
|
)
|
|
@@ -23950,14 +24734,14 @@ var init_backgroundAgents = __esm({
|
|
|
23950
24734
|
|
|
23951
24735
|
// ../../server/routes/ports/listeningProcesses.ts
|
|
23952
24736
|
function runCapture(command, args) {
|
|
23953
|
-
return new Promise((
|
|
23954
|
-
const child =
|
|
24737
|
+
return new Promise((resolve22, reject) => {
|
|
24738
|
+
const child = spawn2(command, args);
|
|
23955
24739
|
let stdout = "";
|
|
23956
24740
|
child.stdout?.on("data", (data) => {
|
|
23957
24741
|
stdout += data.toString();
|
|
23958
24742
|
});
|
|
23959
24743
|
child.on("error", reject);
|
|
23960
|
-
child.on("close", () =>
|
|
24744
|
+
child.on("close", () => resolve22(stdout));
|
|
23961
24745
|
});
|
|
23962
24746
|
}
|
|
23963
24747
|
async function findListeningPids(port) {
|
|
@@ -23997,22 +24781,22 @@ function registerPortRoutes(use) {
|
|
|
23997
24781
|
const results = {};
|
|
23998
24782
|
await Promise.all(
|
|
23999
24783
|
ports.map(
|
|
24000
|
-
(port) => new Promise((
|
|
24784
|
+
(port) => new Promise((resolve22) => {
|
|
24001
24785
|
const socket = createConnection({ port, host: "127.0.0.1" });
|
|
24002
24786
|
socket.setTimeout(500);
|
|
24003
24787
|
socket.on("connect", () => {
|
|
24004
24788
|
results[port] = true;
|
|
24005
24789
|
socket.destroy();
|
|
24006
|
-
|
|
24790
|
+
resolve22();
|
|
24007
24791
|
});
|
|
24008
24792
|
socket.on("timeout", () => {
|
|
24009
24793
|
results[port] = false;
|
|
24010
24794
|
socket.destroy();
|
|
24011
|
-
|
|
24795
|
+
resolve22();
|
|
24012
24796
|
});
|
|
24013
24797
|
socket.on("error", () => {
|
|
24014
24798
|
results[port] = false;
|
|
24015
|
-
|
|
24799
|
+
resolve22();
|
|
24016
24800
|
});
|
|
24017
24801
|
})
|
|
24018
24802
|
)
|
|
@@ -24082,8 +24866,8 @@ var init_ports2 = __esm({
|
|
|
24082
24866
|
|
|
24083
24867
|
// ../../server/routes/project-file.ts
|
|
24084
24868
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
24085
|
-
import { readFile as
|
|
24086
|
-
import { dirname as dirname10, isAbsolute as
|
|
24869
|
+
import { readFile as readFile18, realpath as realpath10, rename as rename3, stat as stat16, unlink as unlink6, writeFile as writeFile6 } from "node:fs/promises";
|
|
24870
|
+
import { dirname as dirname10, isAbsolute as isAbsolute11, resolve as resolve17 } from "node:path";
|
|
24087
24871
|
function readBody(req) {
|
|
24088
24872
|
return new Promise((resolveBody, reject) => {
|
|
24089
24873
|
let body = "";
|
|
@@ -24101,26 +24885,26 @@ function readBody(req) {
|
|
|
24101
24885
|
});
|
|
24102
24886
|
}
|
|
24103
24887
|
async function resolveProjectFile(cwd, filePath) {
|
|
24104
|
-
if (!
|
|
24105
|
-
if (!filePath ||
|
|
24888
|
+
if (!isAbsolute11(cwd)) throw new ProjectFileError(400, "cwd must be an absolute path");
|
|
24889
|
+
if (!filePath || isAbsolute11(filePath) || filePath.includes("\0")) {
|
|
24106
24890
|
throw new ProjectFileError(400, "path must be a relative project file");
|
|
24107
24891
|
}
|
|
24108
24892
|
let root;
|
|
24109
24893
|
try {
|
|
24110
|
-
root = await
|
|
24894
|
+
root = await realpath10(resolve17(cwd));
|
|
24111
24895
|
} catch {
|
|
24112
24896
|
throw new ProjectFileError(404, "Project directory not found");
|
|
24113
24897
|
}
|
|
24114
|
-
const candidate =
|
|
24898
|
+
const candidate = resolve17(root, filePath);
|
|
24115
24899
|
if (!isWithinDir(root, candidate)) throw new ProjectFileError(403, "File is outside the project");
|
|
24116
24900
|
let absolutePath;
|
|
24117
24901
|
try {
|
|
24118
|
-
absolutePath = await
|
|
24902
|
+
absolutePath = await realpath10(candidate);
|
|
24119
24903
|
} catch {
|
|
24120
24904
|
throw new ProjectFileError(404, "File not found");
|
|
24121
24905
|
}
|
|
24122
24906
|
if (!isWithinDir(root, absolutePath)) throw new ProjectFileError(403, "File is outside the project");
|
|
24123
|
-
const info = await
|
|
24907
|
+
const info = await stat16(absolutePath);
|
|
24124
24908
|
if (!info.isFile()) throw new ProjectFileError(400, "Path must point to a file");
|
|
24125
24909
|
if (info.size > MAX_FILE_BYTES) throw new ProjectFileError(413, "File is larger than 2 MB");
|
|
24126
24910
|
return { absolutePath, info };
|
|
@@ -24140,14 +24924,14 @@ function decodeTextFile(buffer) {
|
|
|
24140
24924
|
}
|
|
24141
24925
|
}
|
|
24142
24926
|
async function writeAtomically(absolutePath, content, mode, expectedMtimeMs) {
|
|
24143
|
-
const latest = await
|
|
24927
|
+
const latest = await stat16(absolutePath);
|
|
24144
24928
|
if (latest.mtimeMs !== expectedMtimeMs) {
|
|
24145
24929
|
throw new ProjectFileError(409, "File changed on disk. Reload it before saving.");
|
|
24146
24930
|
}
|
|
24147
|
-
const temporaryPath =
|
|
24931
|
+
const temporaryPath = resolve17(dirname10(absolutePath), `.${randomUUID5()}.cogpit-save`);
|
|
24148
24932
|
try {
|
|
24149
24933
|
await writeFile6(temporaryPath, content, { encoding: "utf-8", mode });
|
|
24150
|
-
const beforeRename = await
|
|
24934
|
+
const beforeRename = await stat16(absolutePath);
|
|
24151
24935
|
if (beforeRename.mtimeMs !== expectedMtimeMs) {
|
|
24152
24936
|
throw new ProjectFileError(409, "File changed on disk. Reload it before saving.");
|
|
24153
24937
|
}
|
|
@@ -24164,7 +24948,7 @@ function registerProjectFileContentRoutes(use) {
|
|
|
24164
24948
|
const filePath = url.searchParams.get("path") ?? "";
|
|
24165
24949
|
try {
|
|
24166
24950
|
const file = await resolveProjectFile(cwd, filePath);
|
|
24167
|
-
const buffer = await
|
|
24951
|
+
const buffer = await readFile18(file.absolutePath);
|
|
24168
24952
|
return sendJson(res, 200, {
|
|
24169
24953
|
content: decodeTextFile(buffer),
|
|
24170
24954
|
mtimeMs: file.info.mtimeMs,
|
|
@@ -24188,7 +24972,7 @@ function registerProjectFileContentRoutes(use) {
|
|
|
24188
24972
|
throw new ProjectFileError(409, "File changed on disk. Reload it before saving.");
|
|
24189
24973
|
}
|
|
24190
24974
|
await writeAtomically(file.absolutePath, body.content, file.info.mode, body.expectedMtimeMs);
|
|
24191
|
-
const saved = await
|
|
24975
|
+
const saved = await stat16(file.absolutePath);
|
|
24192
24976
|
return sendJson(res, 200, { ok: true, mtimeMs: saved.mtimeMs, size: saved.size });
|
|
24193
24977
|
} catch (error) {
|
|
24194
24978
|
return respondWithError(res, error);
|
|
@@ -24238,13 +25022,13 @@ var init_project_files_ranking = __esm({
|
|
|
24238
25022
|
});
|
|
24239
25023
|
|
|
24240
25024
|
// ../../server/routes/project-files.ts
|
|
24241
|
-
import { execFile as
|
|
24242
|
-
import { readdir as readdir11, realpath as
|
|
24243
|
-
import { isAbsolute as
|
|
24244
|
-
import { promisify as
|
|
25025
|
+
import { execFile as execFileCallback4 } from "node:child_process";
|
|
25026
|
+
import { readdir as readdir11, realpath as realpath11, stat as stat17 } from "node:fs/promises";
|
|
25027
|
+
import { isAbsolute as isAbsolute12, relative as relative9, resolve as resolve18, sep as sep11 } from "node:path";
|
|
25028
|
+
import { promisify as promisify4 } from "node:util";
|
|
24245
25029
|
async function listGitProjectFiles(root) {
|
|
24246
25030
|
try {
|
|
24247
|
-
const result = await
|
|
25031
|
+
const result = await execFile8(
|
|
24248
25032
|
"git",
|
|
24249
25033
|
["ls-files", "--cached", "--others", "--exclude-standard", "-z", "--", "."],
|
|
24250
25034
|
{
|
|
@@ -24280,7 +25064,7 @@ async function listProjectFiles(root, { skipCache = false } = {}) {
|
|
|
24280
25064
|
}
|
|
24281
25065
|
for (const entry of entries3) {
|
|
24282
25066
|
if (entry.isSymbolicLink()) continue;
|
|
24283
|
-
const absolutePath =
|
|
25067
|
+
const absolutePath = resolve18(directory, entry.name);
|
|
24284
25068
|
if (entry.isDirectory()) {
|
|
24285
25069
|
if (!IGNORED_DIRECTORIES.has(entry.name)) pending.push(absolutePath);
|
|
24286
25070
|
continue;
|
|
@@ -24302,12 +25086,12 @@ function registerProjectFileRoutes(use) {
|
|
|
24302
25086
|
const query4 = url.searchParams.get("q") ?? "";
|
|
24303
25087
|
const limit = Math.min(Math.max(Number(url.searchParams.get("limit")) || 30, 1), 100);
|
|
24304
25088
|
const skipCache = url.searchParams.get("refresh") === "1";
|
|
24305
|
-
if (!
|
|
24306
|
-
let root =
|
|
25089
|
+
if (!isAbsolute12(cwd)) return sendJson(res, 400, { error: "cwd must be an absolute path" });
|
|
25090
|
+
let root = resolve18(cwd);
|
|
24307
25091
|
try {
|
|
24308
|
-
const info = await
|
|
25092
|
+
const info = await stat17(root);
|
|
24309
25093
|
if (!info.isDirectory()) return sendJson(res, 400, { error: "cwd must be a directory" });
|
|
24310
|
-
root = await
|
|
25094
|
+
root = await realpath11(root);
|
|
24311
25095
|
const files = await listProjectFiles(root, { skipCache });
|
|
24312
25096
|
const ranked = rankProjectFiles(files, query4, limit);
|
|
24313
25097
|
return sendJson(res, 200, {
|
|
@@ -24320,7 +25104,7 @@ function registerProjectFileRoutes(use) {
|
|
|
24320
25104
|
}
|
|
24321
25105
|
});
|
|
24322
25106
|
}
|
|
24323
|
-
var MAX_FILES, CACHE_TTL_MS3, IGNORED_DIRECTORIES, fileCache,
|
|
25107
|
+
var MAX_FILES, CACHE_TTL_MS3, IGNORED_DIRECTORIES, fileCache, execFile8;
|
|
24324
25108
|
var init_project_files = __esm({
|
|
24325
25109
|
"../../server/routes/project-files.ts"() {
|
|
24326
25110
|
init_http();
|
|
@@ -24341,7 +25125,7 @@ var init_project_files = __esm({
|
|
|
24341
25125
|
"target"
|
|
24342
25126
|
]);
|
|
24343
25127
|
fileCache = /* @__PURE__ */ new Map();
|
|
24344
|
-
|
|
25128
|
+
execFile8 = promisify4(execFileCallback4);
|
|
24345
25129
|
}
|
|
24346
25130
|
});
|
|
24347
25131
|
|
|
@@ -24555,7 +25339,7 @@ function createCollector() {
|
|
|
24555
25339
|
return {
|
|
24556
25340
|
pullRequests,
|
|
24557
25341
|
add,
|
|
24558
|
-
record(output, command, toolCallId,
|
|
25342
|
+
record(output, command, toolCallId, timestamp2) {
|
|
24559
25343
|
const match = PR_URL.exec(output);
|
|
24560
25344
|
if (!match) return;
|
|
24561
25345
|
add({
|
|
@@ -24565,7 +25349,7 @@ function createCollector() {
|
|
|
24565
25349
|
title: extractTitle(command),
|
|
24566
25350
|
isDraft: /(?:^|\s)--draft(?:\s|$)/.test(command),
|
|
24567
25351
|
toolCallId,
|
|
24568
|
-
timestamp
|
|
25352
|
+
timestamp: timestamp2
|
|
24569
25353
|
});
|
|
24570
25354
|
}
|
|
24571
25355
|
};
|
|
@@ -24594,22 +25378,22 @@ function createPullRequestScanner() {
|
|
|
24594
25378
|
seenReferences.add(key2);
|
|
24595
25379
|
references.push(reference);
|
|
24596
25380
|
}
|
|
24597
|
-
function recordToolCall(id, input,
|
|
25381
|
+
function recordToolCall(id, input, timestamp2) {
|
|
24598
25382
|
const reference = findPullRequestReference(input);
|
|
24599
25383
|
if (reference) recordReference(reference);
|
|
24600
|
-
recordCreate(id, input,
|
|
25384
|
+
recordCreate(id, input, timestamp2);
|
|
24601
25385
|
}
|
|
24602
|
-
function recordCreate(id, input,
|
|
25386
|
+
function recordCreate(id, input, timestamp2) {
|
|
24603
25387
|
if (typeof id !== "string" || !id) return;
|
|
24604
25388
|
const command = findCreateCommand(input);
|
|
24605
|
-
if (command) openCreates.set(id, { command, timestamp });
|
|
25389
|
+
if (command) openCreates.set(id, { command, timestamp: timestamp2 });
|
|
24606
25390
|
}
|
|
24607
|
-
function recordPrLink(
|
|
24608
|
-
const url =
|
|
24609
|
-
const number =
|
|
25391
|
+
function recordPrLink(record4, timestamp2) {
|
|
25392
|
+
const url = record4.prUrl;
|
|
25393
|
+
const number = record4.prNumber;
|
|
24610
25394
|
if (typeof url !== "string" || !url) return;
|
|
24611
25395
|
if (typeof number !== "number" || !Number.isInteger(number) || number <= 0) return;
|
|
24612
|
-
const repo = typeof
|
|
25396
|
+
const repo = typeof record4.prRepository === "string" ? record4.prRepository : "";
|
|
24613
25397
|
collector.add({
|
|
24614
25398
|
url,
|
|
24615
25399
|
number,
|
|
@@ -24617,7 +25401,7 @@ function createPullRequestScanner() {
|
|
|
24617
25401
|
title: null,
|
|
24618
25402
|
isDraft: false,
|
|
24619
25403
|
toolCallId: "",
|
|
24620
|
-
timestamp
|
|
25404
|
+
timestamp: timestamp2
|
|
24621
25405
|
});
|
|
24622
25406
|
recordReference({ number, repo });
|
|
24623
25407
|
}
|
|
@@ -24644,37 +25428,37 @@ function createPullRequestScanner() {
|
|
|
24644
25428
|
if (!line.includes(GH_PR_HINT) && !line.includes(URL_HINT) && !line.includes(PR_LINK_HINT)) {
|
|
24645
25429
|
return;
|
|
24646
25430
|
}
|
|
24647
|
-
let
|
|
25431
|
+
let record4;
|
|
24648
25432
|
try {
|
|
24649
|
-
|
|
25433
|
+
record4 = JSON.parse(line);
|
|
24650
25434
|
} catch {
|
|
24651
25435
|
return;
|
|
24652
25436
|
}
|
|
24653
|
-
if (!isRecord5(
|
|
24654
|
-
const
|
|
24655
|
-
if (
|
|
24656
|
-
recordPrLink(
|
|
25437
|
+
if (!isRecord5(record4)) return;
|
|
25438
|
+
const timestamp2 = typeof record4.timestamp === "string" ? record4.timestamp : "";
|
|
25439
|
+
if (record4.type === "pr-link") {
|
|
25440
|
+
recordPrLink(record4, timestamp2);
|
|
24657
25441
|
return;
|
|
24658
25442
|
}
|
|
24659
|
-
const payload =
|
|
25443
|
+
const payload = record4.payload;
|
|
24660
25444
|
if (isRecord5(payload)) {
|
|
24661
25445
|
const type = payload.type;
|
|
24662
25446
|
if (type === "function_call" || type === "custom_tool_call") {
|
|
24663
|
-
recordToolCall(payload.call_id, parseArgs2(payload.arguments ?? payload.input),
|
|
25447
|
+
recordToolCall(payload.call_id, parseArgs2(payload.arguments ?? payload.input), timestamp2);
|
|
24664
25448
|
} else if (type === "function_call_output" || type === "custom_tool_call_output") {
|
|
24665
25449
|
recordResult(payload.call_id, payload.output, false);
|
|
24666
25450
|
}
|
|
24667
25451
|
return;
|
|
24668
25452
|
}
|
|
24669
|
-
const data =
|
|
25453
|
+
const data = record4.data;
|
|
24670
25454
|
if (isRecord5(data)) {
|
|
24671
|
-
if (
|
|
25455
|
+
if (record4.type === "tool.execution_start") {
|
|
24672
25456
|
recordToolCall(
|
|
24673
25457
|
data.toolCallId,
|
|
24674
25458
|
parseArgs2(data.arguments ?? data.input),
|
|
24675
|
-
|
|
25459
|
+
timestamp2
|
|
24676
25460
|
);
|
|
24677
|
-
} else if (
|
|
25461
|
+
} else if (record4.type === "tool.execution_complete") {
|
|
24678
25462
|
recordResult(
|
|
24679
25463
|
data.toolCallId,
|
|
24680
25464
|
data.result ?? data.output ?? data.error,
|
|
@@ -24683,12 +25467,12 @@ function createPullRequestScanner() {
|
|
|
24683
25467
|
}
|
|
24684
25468
|
return;
|
|
24685
25469
|
}
|
|
24686
|
-
const message =
|
|
25470
|
+
const message = record4.message;
|
|
24687
25471
|
if (!isRecord5(message) || !Array.isArray(message.content)) return;
|
|
24688
25472
|
for (const block of message.content) {
|
|
24689
25473
|
if (!isRecord5(block)) continue;
|
|
24690
25474
|
if (block.type === "tool_use" && isRecord5(block.input)) {
|
|
24691
|
-
recordToolCall(block.id, block.input,
|
|
25475
|
+
recordToolCall(block.id, block.input, timestamp2);
|
|
24692
25476
|
} else if (block.type === "tool_result") {
|
|
24693
25477
|
recordResult(block.tool_use_id, block.content, block.is_error === true);
|
|
24694
25478
|
}
|
|
@@ -24793,15 +25577,15 @@ var init_sessionPrIndex = __esm({
|
|
|
24793
25577
|
});
|
|
24794
25578
|
|
|
24795
25579
|
// ../../server/lib/sessionPrSearchIndex.ts
|
|
24796
|
-
import { mkdir as mkdir6, readFile as
|
|
24797
|
-
import { join as
|
|
25580
|
+
import { mkdir as mkdir6, readFile as readFile19 } from "node:fs/promises";
|
|
25581
|
+
import { join as join25 } from "node:path";
|
|
24798
25582
|
function isIndexEntry(value) {
|
|
24799
25583
|
if (typeof value !== "object" || value === null) return false;
|
|
24800
25584
|
const entry = value;
|
|
24801
25585
|
return typeof entry.size === "number" && typeof entry.mtimeMs === "number" && Array.isArray(entry.pullRequests) && Array.isArray(entry.references);
|
|
24802
25586
|
}
|
|
24803
25587
|
function currentIndexPath() {
|
|
24804
|
-
return
|
|
25588
|
+
return join25(dirs.SESSION_CONFIG_DIR, INDEX_FILE);
|
|
24805
25589
|
}
|
|
24806
25590
|
function resetForPath(indexPath) {
|
|
24807
25591
|
activeIndexPath = indexPath;
|
|
@@ -24818,7 +25602,7 @@ async function loadIndex() {
|
|
|
24818
25602
|
if (loaded) return;
|
|
24819
25603
|
if (loading) return loading;
|
|
24820
25604
|
const expectedGeneration = generation;
|
|
24821
|
-
const pendingLoad =
|
|
25605
|
+
const pendingLoad = readFile19(indexPath, "utf-8").then((raw) => {
|
|
24822
25606
|
if (expectedGeneration !== generation) return;
|
|
24823
25607
|
const parsed = JSON.parse(raw);
|
|
24824
25608
|
if (typeof parsed !== "object" || parsed === null) return;
|
|
@@ -24862,7 +25646,7 @@ async function runQueue(expectedGeneration) {
|
|
|
24862
25646
|
await persistIndex(expectedGeneration).catch(() => void 0);
|
|
24863
25647
|
sincePersist = 0;
|
|
24864
25648
|
}
|
|
24865
|
-
await new Promise((
|
|
25649
|
+
await new Promise((resolve22) => setImmediate(resolve22));
|
|
24866
25650
|
}
|
|
24867
25651
|
if (sincePersist > 0) await persistIndex(expectedGeneration).catch(() => void 0);
|
|
24868
25652
|
} finally {
|
|
@@ -25547,6 +26331,19 @@ var init_projects2 = __esm({
|
|
|
25547
26331
|
}
|
|
25548
26332
|
});
|
|
25549
26333
|
|
|
26334
|
+
// ../../server/agents/executables.ts
|
|
26335
|
+
function activeExecutableFor(kind) {
|
|
26336
|
+
return kind === "claude" ? claudeCliPath() : void 0;
|
|
26337
|
+
}
|
|
26338
|
+
function describeExecutableFor(kind) {
|
|
26339
|
+
return kind === "claude" ? describeClaudeExecutable() : null;
|
|
26340
|
+
}
|
|
26341
|
+
var init_executables = __esm({
|
|
26342
|
+
"../../server/agents/executables.ts"() {
|
|
26343
|
+
init_claudeExecutable();
|
|
26344
|
+
}
|
|
26345
|
+
});
|
|
26346
|
+
|
|
25550
26347
|
// ../../server/lib/providerUpdates.ts
|
|
25551
26348
|
import { realpathSync } from "node:fs";
|
|
25552
26349
|
function deriveStatus(current, latest) {
|
|
@@ -25649,8 +26446,8 @@ function buildUpdateCommand(provider, method) {
|
|
|
25649
26446
|
function formatCommand(command) {
|
|
25650
26447
|
return [command.executable, ...command.args].join(" ");
|
|
25651
26448
|
}
|
|
25652
|
-
function resolveBinaryPaths(
|
|
25653
|
-
const onPath = findExecutableOnPath(binName);
|
|
26449
|
+
function resolveBinaryPaths(descriptor7) {
|
|
26450
|
+
const onPath = activeExecutableFor(descriptor7.kind) ?? findExecutableOnPath(descriptor7.binName);
|
|
25654
26451
|
if (!onPath) return [];
|
|
25655
26452
|
try {
|
|
25656
26453
|
const real = realpathSync(onPath);
|
|
@@ -25699,7 +26496,7 @@ function fetchLatestVersion(packageName) {
|
|
|
25699
26496
|
});
|
|
25700
26497
|
}
|
|
25701
26498
|
async function probeProvider(descriptor7) {
|
|
25702
|
-
const paths = resolveBinaryPaths(descriptor7
|
|
26499
|
+
const paths = resolveBinaryPaths(descriptor7);
|
|
25703
26500
|
const base = {
|
|
25704
26501
|
provider: descriptor7.kind,
|
|
25705
26502
|
displayName: descriptor7.displayName,
|
|
@@ -25808,6 +26605,7 @@ var init_providerUpdates = __esm({
|
|
|
25808
26605
|
"../../server/lib/providerUpdates.ts"() {
|
|
25809
26606
|
init_agent_descriptors();
|
|
25810
26607
|
init_versions();
|
|
26608
|
+
init_executables();
|
|
25811
26609
|
init_binaryResolver();
|
|
25812
26610
|
init_cliProcess();
|
|
25813
26611
|
REGISTRY_TIMEOUT_MS = 4e3;
|
|
@@ -25864,12 +26662,38 @@ var init_provider_updates = __esm({
|
|
|
25864
26662
|
}
|
|
25865
26663
|
});
|
|
25866
26664
|
|
|
26665
|
+
// ../../server/routes/agent-executable.ts
|
|
26666
|
+
function registerAgentExecutableRoutes(use) {
|
|
26667
|
+
use("/api/agent-executable", async (req, res, next) => {
|
|
26668
|
+
if (req.method !== "GET") return next();
|
|
26669
|
+
const kind = new URL(req.url || "/", "http://localhost").pathname.slice(1);
|
|
26670
|
+
if (!AGENT_KINDS.includes(kind)) return next();
|
|
26671
|
+
const report = describeExecutableFor(kind);
|
|
26672
|
+
if (!report) {
|
|
26673
|
+
sendJson(res, 404, { error: `${kind} has a single executable; nothing to choose` });
|
|
26674
|
+
return;
|
|
26675
|
+
}
|
|
26676
|
+
try {
|
|
26677
|
+
sendJson(res, 200, await report);
|
|
26678
|
+
} catch (err) {
|
|
26679
|
+
sendJson(res, 500, { error: String(err) });
|
|
26680
|
+
}
|
|
26681
|
+
});
|
|
26682
|
+
}
|
|
26683
|
+
var init_agent_executable = __esm({
|
|
26684
|
+
"../../server/routes/agent-executable.ts"() {
|
|
26685
|
+
init_agent_descriptors();
|
|
26686
|
+
init_executables();
|
|
26687
|
+
init_http();
|
|
26688
|
+
}
|
|
26689
|
+
});
|
|
26690
|
+
|
|
25867
26691
|
// ../../server/routes/scripts/discovery.ts
|
|
25868
|
-
import { readdir as readdir12, readFile as
|
|
25869
|
-
import { join as
|
|
26692
|
+
import { readdir as readdir12, readFile as readFile20 } from "node:fs/promises";
|
|
26693
|
+
import { join as join26, relative as relative10 } from "node:path";
|
|
25870
26694
|
async function extractScripts(dir, dirLabel) {
|
|
25871
26695
|
try {
|
|
25872
|
-
const raw = await
|
|
26696
|
+
const raw = await readFile20(join26(dir, "package.json"), "utf-8");
|
|
25873
26697
|
const pkg = JSON.parse(raw);
|
|
25874
26698
|
const scripts = pkg.scripts;
|
|
25875
26699
|
if (!scripts || typeof scripts !== "object") return [];
|
|
@@ -25895,7 +26719,7 @@ async function discoverScripts(projectDir) {
|
|
|
25895
26719
|
);
|
|
25896
26720
|
const childResults = await Promise.all(
|
|
25897
26721
|
childDirs.map(async (entry) => {
|
|
25898
|
-
const childPath =
|
|
26722
|
+
const childPath = join26(projectDir, entry.name);
|
|
25899
26723
|
const label = relative10(projectDir, childPath) + "/";
|
|
25900
26724
|
return extractScripts(childPath, label);
|
|
25901
26725
|
})
|
|
@@ -25942,12 +26766,12 @@ var init_discovery = __esm({
|
|
|
25942
26766
|
});
|
|
25943
26767
|
|
|
25944
26768
|
// ../../server/routes/scripts/index.ts
|
|
25945
|
-
import { stat as
|
|
25946
|
-
import { resolve as
|
|
26769
|
+
import { stat as stat18 } from "node:fs/promises";
|
|
26770
|
+
import { resolve as resolve19 } from "node:path";
|
|
25947
26771
|
async function validateDir(dir) {
|
|
25948
26772
|
try {
|
|
25949
|
-
const resolved =
|
|
25950
|
-
const info = await
|
|
26773
|
+
const resolved = resolve19(dir);
|
|
26774
|
+
const info = await stat18(resolved);
|
|
25951
26775
|
return info.isDirectory() ? resolved : null;
|
|
25952
26776
|
} catch {
|
|
25953
26777
|
return null;
|
|
@@ -26012,7 +26836,7 @@ async function withTranscriptEffort(key2, stored) {
|
|
|
26012
26836
|
}
|
|
26013
26837
|
}
|
|
26014
26838
|
function collectBody(req) {
|
|
26015
|
-
return new Promise((
|
|
26839
|
+
return new Promise((resolve22, reject) => {
|
|
26016
26840
|
let body = "";
|
|
26017
26841
|
req.on("data", (chunk) => {
|
|
26018
26842
|
body += chunk.toString();
|
|
@@ -26021,7 +26845,7 @@ function collectBody(req) {
|
|
|
26021
26845
|
req.destroy();
|
|
26022
26846
|
}
|
|
26023
26847
|
});
|
|
26024
|
-
req.on("end", () =>
|
|
26848
|
+
req.on("end", () => resolve22(body));
|
|
26025
26849
|
req.on("error", reject);
|
|
26026
26850
|
});
|
|
26027
26851
|
}
|
|
@@ -26081,12 +26905,12 @@ var init_session_config = __esm({
|
|
|
26081
26905
|
|
|
26082
26906
|
// ../../server/lib/agentTeamIdentity.ts
|
|
26083
26907
|
import { open as open9, readdir as readdir13 } from "node:fs/promises";
|
|
26084
|
-
import { join as
|
|
26908
|
+
import { join as join27 } from "node:path";
|
|
26085
26909
|
async function matchSubagentToMember(leadSessionId, subagentFileName, members) {
|
|
26086
26910
|
const entries3 = await readdir13(dirs.PROJECTS_DIR, { withFileTypes: true });
|
|
26087
26911
|
for (const entry of entries3) {
|
|
26088
26912
|
if (!entry.isDirectory() || entry.name === "memory") continue;
|
|
26089
|
-
const filePath =
|
|
26913
|
+
const filePath = join27(
|
|
26090
26914
|
dirs.PROJECTS_DIR,
|
|
26091
26915
|
entry.name,
|
|
26092
26916
|
leadSessionId,
|
|
@@ -26779,7 +27603,7 @@ function normalizeCopilotFileChangeEvents(jsonlContent) {
|
|
|
26779
27603
|
}
|
|
26780
27604
|
});
|
|
26781
27605
|
}
|
|
26782
|
-
return records.map((
|
|
27606
|
+
return records.map((record4) => JSON.stringify(record4)).join("\n");
|
|
26783
27607
|
}
|
|
26784
27608
|
async function parseSessionFileChanges(jsonlContent, includeContent) {
|
|
26785
27609
|
if (formatForText(jsonlContent).kind === "copilot") {
|
|
@@ -28199,8 +29023,8 @@ var init_paths = __esm({
|
|
|
28199
29023
|
});
|
|
28200
29024
|
|
|
28201
29025
|
// ../../server/routes/undo/fileOperations.ts
|
|
28202
|
-
import { basename as basename12, dirname as dirname13, isAbsolute as
|
|
28203
|
-
import { lstat as lstat6, realpath as
|
|
29026
|
+
import { basename as basename12, dirname as dirname13, isAbsolute as isAbsolute13 } from "node:path";
|
|
29027
|
+
import { lstat as lstat6, realpath as realpath12 } from "node:fs/promises";
|
|
28204
29028
|
function hasTraversalSegment(filePath) {
|
|
28205
29029
|
return filePath.split(/[\\/]+/).includes("..");
|
|
28206
29030
|
}
|
|
@@ -28211,7 +29035,7 @@ function isForbiddenPath(filePath) {
|
|
|
28211
29035
|
return FORBIDDEN_PREFIXES.some((prefix) => isWithinDir(prefix, filePath));
|
|
28212
29036
|
}
|
|
28213
29037
|
async function resolveSafeOperationPath(filePath, home, canonicalHome) {
|
|
28214
|
-
if (typeof filePath !== "string" || !
|
|
29038
|
+
if (typeof filePath !== "string" || !isAbsolute13(filePath) || hasTraversalSegment(filePath)) {
|
|
28215
29039
|
return null;
|
|
28216
29040
|
}
|
|
28217
29041
|
const resolved = resolve7(filePath);
|
|
@@ -28219,12 +29043,12 @@ async function resolveSafeOperationPath(filePath, home, canonicalHome) {
|
|
|
28219
29043
|
try {
|
|
28220
29044
|
const stats = await lstat6(resolved);
|
|
28221
29045
|
if (stats.isSymbolicLink()) return null;
|
|
28222
|
-
const canonicalTarget = await
|
|
29046
|
+
const canonicalTarget = await realpath12(resolved);
|
|
28223
29047
|
return isWithinDir(canonicalHome, canonicalTarget) && !isForbiddenPath(canonicalTarget) ? canonicalTarget : null;
|
|
28224
29048
|
} catch (error) {
|
|
28225
29049
|
if (!isMissingPathError(error)) return null;
|
|
28226
29050
|
try {
|
|
28227
|
-
const canonicalParent = await
|
|
29051
|
+
const canonicalParent = await realpath12(dirname13(resolved));
|
|
28228
29052
|
const canonicalTarget = join11(canonicalParent, basename12(resolved));
|
|
28229
29053
|
return isWithinDir(canonicalHome, canonicalTarget) && !isForbiddenPath(canonicalTarget) ? canonicalTarget : null;
|
|
28230
29054
|
} catch {
|
|
@@ -28272,7 +29096,7 @@ async function prepareFileOperations(operationValues, options = {}) {
|
|
|
28272
29096
|
const home = resolve7(homedir4());
|
|
28273
29097
|
let canonicalHome;
|
|
28274
29098
|
try {
|
|
28275
|
-
canonicalHome = await
|
|
29099
|
+
canonicalHome = await realpath12(home);
|
|
28276
29100
|
} catch {
|
|
28277
29101
|
throw new UndoOperationError(403, "File operations restricted to home directory");
|
|
28278
29102
|
}
|
|
@@ -28476,7 +29300,7 @@ function applySessionMutation(content, mutation) {
|
|
|
28476
29300
|
` : "";
|
|
28477
29301
|
}
|
|
28478
29302
|
async function readBody2(req) {
|
|
28479
|
-
return await new Promise((
|
|
29303
|
+
return await new Promise((resolve22, reject) => {
|
|
28480
29304
|
let body = "";
|
|
28481
29305
|
let bytes = 0;
|
|
28482
29306
|
let settled = false;
|
|
@@ -28495,7 +29319,7 @@ async function readBody2(req) {
|
|
|
28495
29319
|
req.on("end", () => {
|
|
28496
29320
|
if (!settled) {
|
|
28497
29321
|
settled = true;
|
|
28498
|
-
|
|
29322
|
+
resolve22(body);
|
|
28499
29323
|
}
|
|
28500
29324
|
});
|
|
28501
29325
|
req.on("error", (error) => {
|
|
@@ -28748,20 +29572,20 @@ var init_aggregate = __esm({
|
|
|
28748
29572
|
this.#toDay = makeDayFormatter(options.timeZone);
|
|
28749
29573
|
}
|
|
28750
29574
|
/** Folds one record in; returns whether it actually contributed. */
|
|
28751
|
-
add(
|
|
28752
|
-
if (
|
|
28753
|
-
if (this.#seen.has(
|
|
28754
|
-
this.#seen.add(
|
|
29575
|
+
add(record4) {
|
|
29576
|
+
if (record4.dedupeKey !== null) {
|
|
29577
|
+
if (this.#seen.has(record4.dedupeKey)) return false;
|
|
29578
|
+
this.#seen.add(record4.dedupeKey);
|
|
28755
29579
|
}
|
|
28756
|
-
const day = this.#toDay(
|
|
29580
|
+
const day = this.#toDay(record4.timestampMs);
|
|
28757
29581
|
if (day < this.#options.sinceDay || day > this.#options.untilDay) return false;
|
|
28758
|
-
const key2 = [day,
|
|
29582
|
+
const key2 = [day, record4.provider, record4.model].join(KEY_SEPARATOR);
|
|
28759
29583
|
let bucket = this.#buckets.get(key2);
|
|
28760
29584
|
if (bucket === void 0) {
|
|
28761
29585
|
bucket = {
|
|
28762
29586
|
day,
|
|
28763
|
-
provider:
|
|
28764
|
-
model:
|
|
29587
|
+
provider: record4.provider,
|
|
29588
|
+
model: record4.model,
|
|
28765
29589
|
totals: emptyUsageCostTotals(),
|
|
28766
29590
|
costUsd: 0,
|
|
28767
29591
|
cacheSavingsUsd: 0,
|
|
@@ -28774,19 +29598,19 @@ var init_aggregate = __esm({
|
|
|
28774
29598
|
}
|
|
28775
29599
|
const priced = priceUsage(
|
|
28776
29600
|
this.#options.rates,
|
|
28777
|
-
|
|
28778
|
-
|
|
28779
|
-
|
|
29601
|
+
record4.model,
|
|
29602
|
+
record4.totals,
|
|
29603
|
+
record4.reportedCostUsd
|
|
28780
29604
|
);
|
|
28781
|
-
bucket.totals = addUsageCostTotals(bucket.totals,
|
|
29605
|
+
bucket.totals = addUsageCostTotals(bucket.totals, record4.totals);
|
|
28782
29606
|
bucket.costUsd += priced.costUsd;
|
|
28783
|
-
bucket.cacheSavingsUsd += cacheSavingsUsd(this.#options.rates,
|
|
29607
|
+
bucket.cacheSavingsUsd += cacheSavingsUsd(this.#options.rates, record4.model, record4.totals);
|
|
28784
29608
|
bucket.records += 1;
|
|
28785
29609
|
if (priced.costSource === "unpriced") bucket.unpricedRecords += 1;
|
|
28786
29610
|
if (priced.costSource === "providerReported") bucket.providerReportedRecords += 1;
|
|
28787
|
-
if (
|
|
28788
|
-
bucket.sessions.add(
|
|
28789
|
-
this.#sessions.add(
|
|
29611
|
+
if (record4.sessionId.length > 0) {
|
|
29612
|
+
bucket.sessions.add(record4.sessionId);
|
|
29613
|
+
this.#sessions.add(record4.sessionId);
|
|
28790
29614
|
}
|
|
28791
29615
|
return true;
|
|
28792
29616
|
}
|
|
@@ -28816,8 +29640,8 @@ var init_aggregate = __esm({
|
|
|
28816
29640
|
|
|
28817
29641
|
// ../../server/lib/usageCost/reader.ts
|
|
28818
29642
|
import { createReadStream as createReadStream3 } from "node:fs";
|
|
28819
|
-
import { readdir as readdir14, stat as
|
|
28820
|
-
import { join as
|
|
29643
|
+
import { readdir as readdir14, stat as stat19 } from "node:fs/promises";
|
|
29644
|
+
import { join as join28 } from "node:path";
|
|
28821
29645
|
import { createInterface as createInterface3 } from "node:readline";
|
|
28822
29646
|
async function listTranscriptFiles(root, sinceMs) {
|
|
28823
29647
|
const found = [];
|
|
@@ -28829,14 +29653,14 @@ async function listTranscriptFiles(root, sinceMs) {
|
|
|
28829
29653
|
return;
|
|
28830
29654
|
}
|
|
28831
29655
|
for (const entry of entries3) {
|
|
28832
|
-
const child =
|
|
29656
|
+
const child = join28(dir, entry.name);
|
|
28833
29657
|
if (entry.isDirectory()) {
|
|
28834
29658
|
await walk2(child);
|
|
28835
29659
|
continue;
|
|
28836
29660
|
}
|
|
28837
29661
|
if (!entry.name.endsWith(".jsonl")) continue;
|
|
28838
29662
|
try {
|
|
28839
|
-
const stats = await
|
|
29663
|
+
const stats = await stat19(child);
|
|
28840
29664
|
if (stats.mtimeMs >= sinceMs) {
|
|
28841
29665
|
found.push({ path: child, size: stats.size, mtimeMs: stats.mtimeMs });
|
|
28842
29666
|
}
|
|
@@ -28867,17 +29691,17 @@ async function readTranscriptRecords(filePath, provider) {
|
|
|
28867
29691
|
function dedupeWithinFile(records) {
|
|
28868
29692
|
const slotByKey = /* @__PURE__ */ new Map();
|
|
28869
29693
|
const kept = [];
|
|
28870
|
-
for (const
|
|
28871
|
-
if (
|
|
28872
|
-
kept.push(
|
|
29694
|
+
for (const record4 of records) {
|
|
29695
|
+
if (record4.dedupeKey === null) {
|
|
29696
|
+
kept.push(record4);
|
|
28873
29697
|
continue;
|
|
28874
29698
|
}
|
|
28875
|
-
const slot = slotByKey.get(
|
|
29699
|
+
const slot = slotByKey.get(record4.dedupeKey);
|
|
28876
29700
|
if (slot === void 0) {
|
|
28877
|
-
slotByKey.set(
|
|
29701
|
+
slotByKey.set(record4.dedupeKey, kept.push(record4) - 1);
|
|
28878
29702
|
continue;
|
|
28879
29703
|
}
|
|
28880
|
-
if (
|
|
29704
|
+
if (record4.totals.outputTokens > kept[slot].totals.outputTokens) kept[slot] = record4;
|
|
28881
29705
|
}
|
|
28882
29706
|
return kept;
|
|
28883
29707
|
}
|
|
@@ -28888,10 +29712,10 @@ var init_reader = __esm({
|
|
|
28888
29712
|
});
|
|
28889
29713
|
|
|
28890
29714
|
// ../../server/lib/usageCost/service.ts
|
|
28891
|
-
import { readFile as
|
|
28892
|
-
import { join as
|
|
29715
|
+
import { readFile as readFile21, writeFile as writeFile7 } from "node:fs/promises";
|
|
29716
|
+
import { join as join29 } from "node:path";
|
|
28893
29717
|
function ratesCachePath() {
|
|
28894
|
-
return
|
|
29718
|
+
return join29(getDataRoot(), "usage-model-rates.json");
|
|
28895
29719
|
}
|
|
28896
29720
|
function ratesFetchedAt() {
|
|
28897
29721
|
return ratesFetchedAtMs === null ? null : new Date(ratesFetchedAtMs).toISOString();
|
|
@@ -28901,7 +29725,7 @@ async function ensureRatesInner() {
|
|
|
28901
29725
|
if (ratesFetchedAtMs !== null && now - ratesFetchedAtMs < RATES_TTL_MS) return;
|
|
28902
29726
|
if (ratesFetchedAtMs === null) {
|
|
28903
29727
|
try {
|
|
28904
|
-
const raw = JSON.parse(await
|
|
29728
|
+
const raw = JSON.parse(await readFile21(ratesCachePath(), "utf8"));
|
|
28905
29729
|
if (typeof raw.fetchedAtMs === "number") {
|
|
28906
29730
|
const parsed2 = parseRateTable(raw.document);
|
|
28907
29731
|
if (parsed2.size > 0) {
|
|
@@ -28986,23 +29810,23 @@ async function readUsageCostSummary(input) {
|
|
|
28986
29810
|
for (const file of files) {
|
|
28987
29811
|
const records = await readFileRecords(file, provider);
|
|
28988
29812
|
scannedFiles += 1;
|
|
28989
|
-
for (const
|
|
28990
|
-
aggregator.add(
|
|
28991
|
-
if (!liveSessionIds.has(
|
|
28992
|
-
const byModel = durableTotals.get(
|
|
29813
|
+
for (const record4 of records) {
|
|
29814
|
+
aggregator.add(record4);
|
|
29815
|
+
if (!liveSessionIds.has(record4.sessionId)) continue;
|
|
29816
|
+
const byModel = durableTotals.get(record4.sessionId) ?? /* @__PURE__ */ new Map();
|
|
28993
29817
|
byModel.set(
|
|
28994
|
-
|
|
29818
|
+
record4.model,
|
|
28995
29819
|
addUsageCostTotals(
|
|
28996
|
-
byModel.get(
|
|
28997
|
-
|
|
29820
|
+
byModel.get(record4.model) ?? emptyUsageCostTotals(),
|
|
29821
|
+
record4.totals
|
|
28998
29822
|
)
|
|
28999
29823
|
);
|
|
29000
|
-
durableTotals.set(
|
|
29824
|
+
durableTotals.set(record4.sessionId, byModel);
|
|
29001
29825
|
}
|
|
29002
29826
|
}
|
|
29003
29827
|
}
|
|
29004
29828
|
for (const runtime of runtimes2) {
|
|
29005
|
-
for (const
|
|
29829
|
+
for (const record4 of await runtime.liveUsageRecords(durableTotals)) aggregator.add(record4);
|
|
29006
29830
|
}
|
|
29007
29831
|
const retentionCutoffMs = startedAtMs - 90 * 24 * 60 * 60 * 1e3;
|
|
29008
29832
|
for (const [path, entry] of fileCache2) {
|
|
@@ -29088,12 +29912,12 @@ async function readKeychainCredentials() {
|
|
|
29088
29912
|
if (process.platform !== "darwin") {
|
|
29089
29913
|
return null;
|
|
29090
29914
|
}
|
|
29091
|
-
return new Promise((
|
|
29915
|
+
return new Promise((resolve22) => {
|
|
29092
29916
|
let resolved = false;
|
|
29093
29917
|
const done = (value) => {
|
|
29094
29918
|
if (resolved) return;
|
|
29095
29919
|
resolved = true;
|
|
29096
|
-
|
|
29920
|
+
resolve22(value);
|
|
29097
29921
|
};
|
|
29098
29922
|
const child = spawn3("/usr/bin/security", [
|
|
29099
29923
|
"find-generic-password",
|
|
@@ -29729,8 +30553,8 @@ var init_workflows2 = __esm({
|
|
|
29729
30553
|
});
|
|
29730
30554
|
|
|
29731
30555
|
// ../../server/routes/worktrees/worktreeIo.ts
|
|
29732
|
-
import { execFile as
|
|
29733
|
-
import { promisify as
|
|
30556
|
+
import { execFile as execFile9 } from "node:child_process";
|
|
30557
|
+
import { promisify as promisify5 } from "node:util";
|
|
29734
30558
|
async function runWorktreeCommand(file, args, { cwd, timeoutMs = WORKTREE_COMMAND_TIMEOUT_MS }) {
|
|
29735
30559
|
const result = await execFileAsync(file, [...args], {
|
|
29736
30560
|
cwd,
|
|
@@ -29769,7 +30593,7 @@ var init_worktreeIo = __esm({
|
|
|
29769
30593
|
WORKTREE_COMMAND_MAX_BUFFER = 4 * 1024 * 1024;
|
|
29770
30594
|
WORKTREE_SCAN_CONCURRENCY = 4;
|
|
29771
30595
|
SESSION_HEADER_CONCURRENCY = 8;
|
|
29772
|
-
execFileAsync =
|
|
30596
|
+
execFileAsync = promisify5(execFile9);
|
|
29773
30597
|
NONINTERACTIVE_ENV = {
|
|
29774
30598
|
...process.env,
|
|
29775
30599
|
GCM_INTERACTIVE: "Never",
|
|
@@ -29782,7 +30606,7 @@ var init_worktreeIo = __esm({
|
|
|
29782
30606
|
});
|
|
29783
30607
|
|
|
29784
30608
|
// ../../server/routes/worktrees/worktreeUtils.ts
|
|
29785
|
-
import { resolve as
|
|
30609
|
+
import { resolve as resolve20, dirname as dirname14 } from "node:path";
|
|
29786
30610
|
function isValidWorktreeName(name) {
|
|
29787
30611
|
return /^[a-zA-Z0-9._-]+$/.test(name) && name.length <= 40;
|
|
29788
30612
|
}
|
|
@@ -29845,7 +30669,7 @@ async function getMainWorktreeRoot(projectPath) {
|
|
|
29845
30669
|
const commonDir = (await runWorktreeCommand("git", ["rev-parse", "--git-common-dir"], {
|
|
29846
30670
|
cwd: projectPath
|
|
29847
30671
|
})).trim();
|
|
29848
|
-
return dirname14(
|
|
30672
|
+
return dirname14(resolve20(projectPath, commonDir));
|
|
29849
30673
|
} catch {
|
|
29850
30674
|
return null;
|
|
29851
30675
|
}
|
|
@@ -29870,7 +30694,7 @@ var init_worktreeUtils = __esm({
|
|
|
29870
30694
|
});
|
|
29871
30695
|
|
|
29872
30696
|
// ../../server/routes/worktrees/worktreeListRoute.ts
|
|
29873
|
-
import { stat as
|
|
30697
|
+
import { stat as stat20 } from "node:fs/promises";
|
|
29874
30698
|
async function loadSessionBranches(projectDir) {
|
|
29875
30699
|
const sessionBranches = /* @__PURE__ */ new Map();
|
|
29876
30700
|
try {
|
|
@@ -29985,7 +30809,7 @@ async function buildWorktreeInfo(worktree, defaultBranch, sessionBranches) {
|
|
|
29985
30809
|
}
|
|
29986
30810
|
let createdAt = "";
|
|
29987
30811
|
try {
|
|
29988
|
-
createdAt = (await
|
|
30812
|
+
createdAt = (await stat20(worktree.path)).birthtime.toISOString();
|
|
29989
30813
|
} catch {
|
|
29990
30814
|
}
|
|
29991
30815
|
return {
|
|
@@ -30046,9 +30870,9 @@ var init_worktreeListRoute = __esm({
|
|
|
30046
30870
|
});
|
|
30047
30871
|
|
|
30048
30872
|
// ../../server/routes/worktrees/index.ts
|
|
30049
|
-
import { stat as
|
|
30873
|
+
import { stat as stat21 } from "node:fs/promises";
|
|
30050
30874
|
async function readJsonRequestBody(req) {
|
|
30051
|
-
const body = await new Promise((
|
|
30875
|
+
const body = await new Promise((resolve22, reject) => {
|
|
30052
30876
|
let data = "";
|
|
30053
30877
|
let bytesRead = 0;
|
|
30054
30878
|
let settled = false;
|
|
@@ -30065,7 +30889,7 @@ async function readJsonRequestBody(req) {
|
|
|
30065
30889
|
req.on("end", () => {
|
|
30066
30890
|
if (!settled) {
|
|
30067
30891
|
settled = true;
|
|
30068
|
-
|
|
30892
|
+
resolve22(data);
|
|
30069
30893
|
}
|
|
30070
30894
|
});
|
|
30071
30895
|
req.on("error", () => {
|
|
@@ -30116,7 +30940,7 @@ async function findStaleWorktrees(worktrees, cutoff) {
|
|
|
30116
30940
|
cwd: worktree.path
|
|
30117
30941
|
});
|
|
30118
30942
|
if (status.trim()) return null;
|
|
30119
|
-
const worktreeStat = await
|
|
30943
|
+
const worktreeStat = await stat21(worktree.path);
|
|
30120
30944
|
return worktreeStat.birthtime.getTime() < cutoff ? worktree : null;
|
|
30121
30945
|
} catch {
|
|
30122
30946
|
return null;
|
|
@@ -30357,6 +31181,8 @@ var init_api_routes = __esm({
|
|
|
30357
31181
|
init_files();
|
|
30358
31182
|
init_git_diff();
|
|
30359
31183
|
init_git_status();
|
|
31184
|
+
init_github_actions();
|
|
31185
|
+
init_vercel_deployments();
|
|
30360
31186
|
init_project_icon();
|
|
30361
31187
|
init_hello();
|
|
30362
31188
|
init_local_file();
|
|
@@ -30371,6 +31197,7 @@ var init_api_routes = __esm({
|
|
|
30371
31197
|
init_project_files();
|
|
30372
31198
|
init_projects2();
|
|
30373
31199
|
init_provider_updates();
|
|
31200
|
+
init_agent_executable();
|
|
30374
31201
|
init_scripts();
|
|
30375
31202
|
init_session_config();
|
|
30376
31203
|
init_session_context();
|
|
@@ -30425,6 +31252,8 @@ var init_api_routes = __esm({
|
|
|
30425
31252
|
apiRoute("project-files", registerProjectFileRoutes),
|
|
30426
31253
|
apiRoute("project-file", registerProjectFileContentRoutes),
|
|
30427
31254
|
apiRoute("git-status", registerGitStatusRoutes),
|
|
31255
|
+
apiRoute("github-actions", registerGitHubActionsRoutes),
|
|
31256
|
+
apiRoute("vercel-deployments", registerVercelDeploymentRoutes),
|
|
30428
31257
|
apiRoute("project-icon", registerProjectIconRoutes),
|
|
30429
31258
|
apiRoute("git-diff", registerGitDiffRoutes),
|
|
30430
31259
|
apiRoute("mcp", registerMcpRoutes),
|
|
@@ -30438,7 +31267,8 @@ var init_api_routes = __esm({
|
|
|
30438
31267
|
apiRoute("models", registerModelRoutes),
|
|
30439
31268
|
apiRoute("codex-threads", registerCodexThreadRoutes),
|
|
30440
31269
|
apiRoute("agent-runtime", registerAgentRuntimeRoutes),
|
|
30441
|
-
apiRoute("provider-updates", registerProviderUpdateRoutes)
|
|
31270
|
+
apiRoute("provider-updates", registerProviderUpdateRoutes),
|
|
31271
|
+
apiRoute("agent-executable", registerAgentExecutableRoutes)
|
|
30442
31272
|
];
|
|
30443
31273
|
}
|
|
30444
31274
|
});
|
|
@@ -30854,18 +31684,18 @@ var init_pty_authorization = __esm({
|
|
|
30854
31684
|
// ../../server/app-server.ts
|
|
30855
31685
|
import express from "express";
|
|
30856
31686
|
import { createServer, request as httpRequest2 } from "node:http";
|
|
30857
|
-
import { join as
|
|
31687
|
+
import { join as join30 } from "node:path";
|
|
30858
31688
|
import { WebSocketServer as WebSocketServer2 } from "ws";
|
|
30859
31689
|
async function createServerComposition(staticDir, userDataDir, environment) {
|
|
30860
31690
|
setDataRoot(userDataDir);
|
|
30861
|
-
setConfigPath(
|
|
31691
|
+
setConfigPath(join30(userDataDir, "config.local.json"));
|
|
30862
31692
|
await loadConfig();
|
|
30863
31693
|
const configEdition = getConfiguredEditionValue();
|
|
30864
31694
|
initEdition({ shell: environment.mode, configEdition });
|
|
30865
31695
|
const suppression = describeEditionSuppression(process.env, configEdition, environment.mode);
|
|
30866
31696
|
if (suppression) console.warn(suppression);
|
|
30867
31697
|
if (isTeamEdition()) {
|
|
30868
|
-
const teamDir =
|
|
31698
|
+
const teamDir = join30(getDataRoot(), "team");
|
|
30869
31699
|
await initUsersStore(teamDir);
|
|
30870
31700
|
await initSessionPersistence(teamDir);
|
|
30871
31701
|
initializeBootstrapToken(userCount());
|
|
@@ -30976,7 +31806,7 @@ async function createServerComposition(staticDir, userDataDir, environment) {
|
|
|
30976
31806
|
for (const socket of upgradedSockets) socket.destroy();
|
|
30977
31807
|
upgradedSockets.clear();
|
|
30978
31808
|
await Promise.all([
|
|
30979
|
-
new Promise((
|
|
31809
|
+
new Promise((resolve22) => wss.close(() => resolve22())),
|
|
30980
31810
|
cleanupProcesses(),
|
|
30981
31811
|
...allRuntimes().map((runtime) => runtime.shutdown()),
|
|
30982
31812
|
flushSessionPersistence()
|
|
@@ -30988,8 +31818,8 @@ async function createServerComposition(staticDir, userDataDir, environment) {
|
|
|
30988
31818
|
void cleanupRuntime();
|
|
30989
31819
|
});
|
|
30990
31820
|
const dispose = async () => {
|
|
30991
|
-
const serverClosed = httpServer.listening ? new Promise((
|
|
30992
|
-
httpServer.close((error) => error ? reject(error) :
|
|
31821
|
+
const serverClosed = httpServer.listening ? new Promise((resolve22, reject) => {
|
|
31822
|
+
httpServer.close((error) => error ? reject(error) : resolve22());
|
|
30993
31823
|
}) : Promise.resolve();
|
|
30994
31824
|
await cleanupRuntime();
|
|
30995
31825
|
await serverClosed;
|
|
@@ -31036,7 +31866,7 @@ var init_standalone_app_server = __esm({
|
|
|
31036
31866
|
// ../../server/lib/portFile.ts
|
|
31037
31867
|
import { mkdirSync as mkdirSync2, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
31038
31868
|
import { homedir as homedir12 } from "node:os";
|
|
31039
|
-
import { dirname as dirname15, join as
|
|
31869
|
+
import { dirname as dirname15, join as join31 } from "node:path";
|
|
31040
31870
|
function writePortFile(port) {
|
|
31041
31871
|
try {
|
|
31042
31872
|
mkdirSync2(dirname15(PORT_FILE), { recursive: true });
|
|
@@ -31056,7 +31886,7 @@ function removePortFile() {
|
|
|
31056
31886
|
var PORT_FILE;
|
|
31057
31887
|
var init_portFile = __esm({
|
|
31058
31888
|
"../../server/lib/portFile.ts"() {
|
|
31059
|
-
PORT_FILE =
|
|
31889
|
+
PORT_FILE = join31(homedir12(), ".cogpit", "port");
|
|
31060
31890
|
}
|
|
31061
31891
|
});
|
|
31062
31892
|
|
|
@@ -31266,8 +32096,8 @@ var init_sessionActivityMonitor = __esm({
|
|
|
31266
32096
|
});
|
|
31267
32097
|
|
|
31268
32098
|
// ../../server/lib/standalone-bootstrap.ts
|
|
31269
|
-
import { readFileSync as
|
|
31270
|
-
function resolveEnvPassword(env = process.env, readFileFn = (p) =>
|
|
32099
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
32100
|
+
function resolveEnvPassword(env = process.env, readFileFn = (p) => readFileSync4(p, "utf-8")) {
|
|
31271
32101
|
const file = env.COGPIT_NETWORK_PASSWORD_FILE;
|
|
31272
32102
|
if (file && file.length > 0) {
|
|
31273
32103
|
const trimmed = readFileFn(file).replace(/\r?\n$/, "");
|
|
@@ -31305,9 +32135,9 @@ __export(standalone_runtime_exports, {
|
|
|
31305
32135
|
});
|
|
31306
32136
|
import { existsSync, mkdirSync as mkdirSync3 } from "node:fs";
|
|
31307
32137
|
import { homedir as homedir13 } from "node:os";
|
|
31308
|
-
import { join as
|
|
32138
|
+
import { join as join32 } from "node:path";
|
|
31309
32139
|
function listen(server, port, host) {
|
|
31310
|
-
return new Promise((
|
|
32140
|
+
return new Promise((resolve22, reject) => {
|
|
31311
32141
|
const onError = (error) => reject(error);
|
|
31312
32142
|
server.once("error", onError);
|
|
31313
32143
|
server.listen(port, host, () => {
|
|
@@ -31317,27 +32147,27 @@ function listen(server, port, host) {
|
|
|
31317
32147
|
reject(new Error("Cogpit started without a listening address."));
|
|
31318
32148
|
return;
|
|
31319
32149
|
}
|
|
31320
|
-
|
|
32150
|
+
resolve22(address.port);
|
|
31321
32151
|
});
|
|
31322
32152
|
});
|
|
31323
32153
|
}
|
|
31324
32154
|
async function startStandaloneServer({
|
|
31325
32155
|
staticDir,
|
|
31326
|
-
dataDir =
|
|
32156
|
+
dataDir = join32(homedir13(), ".config", "cogpit"),
|
|
31327
32157
|
host = "127.0.0.1",
|
|
31328
32158
|
port = 19384,
|
|
31329
32159
|
env = process.env,
|
|
31330
32160
|
publishPort = false
|
|
31331
32161
|
}) {
|
|
31332
32162
|
mkdirSync3(dataDir, { recursive: true });
|
|
31333
|
-
const configPath =
|
|
32163
|
+
const configPath = join32(dataDir, "config.local.json");
|
|
31334
32164
|
setConfigPath(configPath);
|
|
31335
32165
|
const configExisted = existsSync(configPath);
|
|
31336
32166
|
await loadConfig();
|
|
31337
32167
|
let createdConfig;
|
|
31338
32168
|
if (!configExisted) {
|
|
31339
|
-
const claudeDir =
|
|
31340
|
-
if (existsSync(
|
|
32169
|
+
const claudeDir = join32(homedir13(), ".claude");
|
|
32170
|
+
if (existsSync(join32(claudeDir, "projects"))) {
|
|
31341
32171
|
await saveConfig({ claudeDir });
|
|
31342
32172
|
createdConfig = `${configPath} for ${claudeDir}`;
|
|
31343
32173
|
}
|
|
@@ -31410,7 +32240,7 @@ var init_standalone_runtime = __esm({
|
|
|
31410
32240
|
// src/index.ts
|
|
31411
32241
|
import { spawn as spawn4 } from "node:child_process";
|
|
31412
32242
|
import { homedir as homedir14 } from "node:os";
|
|
31413
|
-
import { join as
|
|
32243
|
+
import { join as join33, resolve as resolve21 } from "node:path";
|
|
31414
32244
|
var SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/;
|
|
31415
32245
|
var USAGE = `Cogpit
|
|
31416
32246
|
|
|
@@ -31477,7 +32307,7 @@ function parseArgs(argv) {
|
|
|
31477
32307
|
if (value === "--data-dir") {
|
|
31478
32308
|
const path = argv[index + 1];
|
|
31479
32309
|
if (!path) throw new Error("--data-dir requires a directory.");
|
|
31480
|
-
dataDir =
|
|
32310
|
+
dataDir = resolve21(path);
|
|
31481
32311
|
index += 1;
|
|
31482
32312
|
continue;
|
|
31483
32313
|
}
|
|
@@ -31519,8 +32349,8 @@ async function openExternalUrl(url) {
|
|
|
31519
32349
|
async function startPackagedServer(options) {
|
|
31520
32350
|
const { startStandaloneServer: startStandaloneServer2 } = await Promise.resolve().then(() => (init_standalone_runtime(), standalone_runtime_exports));
|
|
31521
32351
|
return startStandaloneServer2({
|
|
31522
|
-
staticDir:
|
|
31523
|
-
dataDir: options.dataDir ??
|
|
32352
|
+
staticDir: join33(import.meta.dirname, "web"),
|
|
32353
|
+
dataDir: options.dataDir ?? join33(homedir14(), ".config", "cogpit"),
|
|
31524
32354
|
host: "127.0.0.1",
|
|
31525
32355
|
port: options.port,
|
|
31526
32356
|
publishPort: false
|
|
@@ -31536,7 +32366,7 @@ async function waitForShutdownSignal() {
|
|
|
31536
32366
|
for (const signal of signals) process.once(signal, done);
|
|
31537
32367
|
});
|
|
31538
32368
|
}
|
|
31539
|
-
var
|
|
32369
|
+
var defaultDependencies3 = {
|
|
31540
32370
|
fetch,
|
|
31541
32371
|
openUrl: openExternalUrl,
|
|
31542
32372
|
startServer: startPackagedServer,
|
|
@@ -31563,7 +32393,7 @@ async function verifyServer(server, command, deps) {
|
|
|
31563
32393
|
}
|
|
31564
32394
|
}
|
|
31565
32395
|
async function run(argv, overrides = {}) {
|
|
31566
|
-
const deps = { ...
|
|
32396
|
+
const deps = { ...defaultDependencies3, ...overrides };
|
|
31567
32397
|
let command;
|
|
31568
32398
|
try {
|
|
31569
32399
|
command = parseArgs(argv);
|