cogpit 2.2.1 → 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 +938 -585
- package/dist/web/assets/{CommandPaletteHost--_g3tlgk.js → CommandPaletteHost-D-VvT_HL.js} +1 -1
- package/dist/web/assets/ConfigBrowser-Cc2lrh85.js +1 -0
- package/dist/web/assets/{HighlightedEditor-Byq8pOUC.js → HighlightedEditor-DWNz1Jcz.js} +2 -2
- package/dist/web/assets/{KeyboardShortcutsDialog-CFhdeGBw.js → KeyboardShortcutsDialog-yOs1u5D6.js} +1 -1
- package/dist/web/assets/{MobileFileChanges-uxpxh1W6.js → MobileFileChanges-B1dtcdSZ.js} +1 -1
- package/dist/web/assets/PreviewPanel-BJwfunf9.js +1 -0
- package/dist/web/assets/{ProjectFilesPanel-ByyaiSGy.js → ProjectFilesPanel-DppuIFEt.js} +3 -3
- package/dist/web/assets/{ProjectSwitcherModal-BRbFj3Dd.js → ProjectSwitcherModal-DgsuH5CY.js} +1 -1
- package/dist/web/assets/{TerminalOutput-Aavw8QCx.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-C-5Kgwol.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/{vendor-ui-CyII6N5s.js → vendor-ui-CdA11Wfh.js} +158 -148
- package/dist/web/index.html +3 -3
- package/package.json +1 -1
- package/dist/web/assets/ConfigBrowser-DrAZQBx8.js +0 -1
- package/dist/web/assets/PreviewPanel-DC6OTZfZ.js +0 -1
- package/dist/web/assets/ThemeSelectorModal-CxGMhlkF.js +0 -1
- package/dist/web/assets/WorkflowsPanel-Beg1AAtq.js +0 -1
- package/dist/web/assets/WorktreePanel-B17_SlFC.js +0 -1
- package/dist/web/assets/index-CJcccHRp.js +0 -1
- package/dist/web/assets/index-CTpAqQye.js +0 -1
- package/dist/web/assets/index-DB1wEO_I.js +0 -148
- package/dist/web/assets/index-DU9XxwBy.css +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
|
}
|
|
@@ -1164,7 +1164,7 @@ function verifyPassword(password, stored) {
|
|
|
1164
1164
|
async function verifyPasswordAsync(password, stored) {
|
|
1165
1165
|
const scryptHash = parseScryptHash(stored);
|
|
1166
1166
|
if (!scryptHash) return verifyPassword(password, stored);
|
|
1167
|
-
const candidate = await new Promise((
|
|
1167
|
+
const candidate = await new Promise((resolve22, reject) => {
|
|
1168
1168
|
scrypt(
|
|
1169
1169
|
password,
|
|
1170
1170
|
Buffer.from(scryptHash.salt, "hex"),
|
|
@@ -1175,7 +1175,7 @@ async function verifyPasswordAsync(password, stored) {
|
|
|
1175
1175
|
p: SCRYPT_PARALLELISM,
|
|
1176
1176
|
maxmem: SCRYPT_MAX_MEMORY
|
|
1177
1177
|
},
|
|
1178
|
-
(error, derivedKey) => error ? reject(error) :
|
|
1178
|
+
(error, derivedKey) => error ? reject(error) : resolve22(derivedKey)
|
|
1179
1179
|
);
|
|
1180
1180
|
});
|
|
1181
1181
|
return safeCompareBuffers(candidate, Buffer.from(scryptHash.hash, "hex"));
|
|
@@ -3999,7 +3999,7 @@ async function createShare(input) {
|
|
|
3999
3999
|
const passwordHash = hashPassword(passphrase);
|
|
4000
4000
|
const share = await commitShareMutation((draft) => {
|
|
4001
4001
|
const existing = draft.get(input.sessionId);
|
|
4002
|
-
const
|
|
4002
|
+
const record4 = {
|
|
4003
4003
|
sessionId: input.sessionId,
|
|
4004
4004
|
dirName: input.dirName,
|
|
4005
4005
|
fileName: input.fileName,
|
|
@@ -4008,8 +4008,8 @@ async function createShare(input) {
|
|
|
4008
4008
|
// No guest has ever used this passphrase; the UI renders 0 as "never".
|
|
4009
4009
|
lastAccessAt: 0
|
|
4010
4010
|
};
|
|
4011
|
-
draft.set(
|
|
4012
|
-
return { changed: true, value: toPublicShare(
|
|
4011
|
+
draft.set(record4.sessionId, record4);
|
|
4012
|
+
return { changed: true, value: toPublicShare(record4) };
|
|
4013
4013
|
});
|
|
4014
4014
|
return { share, passphrase };
|
|
4015
4015
|
}
|
|
@@ -4860,6 +4860,7 @@ var init_policy = __esm({
|
|
|
4860
4860
|
"project-file": admin("/api/project-file"),
|
|
4861
4861
|
"git-status": admin("/api/git-status"),
|
|
4862
4862
|
"github-actions": admin("/api/github-actions"),
|
|
4863
|
+
"vercel-deployments": admin("/api/vercel-deployments"),
|
|
4863
4864
|
"project-icon": admin("/api/project-icon"),
|
|
4864
4865
|
"git-diff": admin("/api/git-diff"),
|
|
4865
4866
|
mcp: admin("/api/mcp-servers"),
|
|
@@ -5714,7 +5715,7 @@ var init_versions = __esm({
|
|
|
5714
5715
|
// ../../server/lib/cliProcess.ts
|
|
5715
5716
|
import { spawn } from "node:child_process";
|
|
5716
5717
|
function runCli(executable, args, timeoutMs) {
|
|
5717
|
-
return new Promise((
|
|
5718
|
+
return new Promise((resolve22) => {
|
|
5718
5719
|
const resolved = resolveAgentCommand(executable, [...args]);
|
|
5719
5720
|
const child = spawn(resolved.command, resolved.args, {
|
|
5720
5721
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -5736,11 +5737,11 @@ function runCli(executable, args, timeoutMs) {
|
|
|
5736
5737
|
});
|
|
5737
5738
|
child.on("error", () => {
|
|
5738
5739
|
clearTimeout(timer);
|
|
5739
|
-
|
|
5740
|
+
resolve22({ code: null, stdout, stderr, timedOut });
|
|
5740
5741
|
});
|
|
5741
5742
|
child.on("close", (code) => {
|
|
5742
5743
|
clearTimeout(timer);
|
|
5743
|
-
|
|
5744
|
+
resolve22({ code, stdout, stderr, timedOut });
|
|
5744
5745
|
});
|
|
5745
5746
|
});
|
|
5746
5747
|
}
|
|
@@ -5795,7 +5796,7 @@ function findNpmClaude(options = {}) {
|
|
|
5795
5796
|
const windows = platform2 === "win32";
|
|
5796
5797
|
const path = windows ? win322 : posix2;
|
|
5797
5798
|
const isFile = options.isFile ?? realIsFile;
|
|
5798
|
-
const
|
|
5799
|
+
const readFile22 = options.readFile ?? realReadFile;
|
|
5799
5800
|
const shim = findExecutableOnPath(BIN_NAME, { platform: platform2, env: options.env, isExecutable: isFile });
|
|
5800
5801
|
if (!shim) return void 0;
|
|
5801
5802
|
const shimDir = path.dirname(shim);
|
|
@@ -5804,7 +5805,7 @@ function findNpmClaude(options = {}) {
|
|
|
5804
5805
|
path.join(shimDir, "..", "lib", "node_modules", NPM_PACKAGE)
|
|
5805
5806
|
];
|
|
5806
5807
|
for (const packageDir of packageDirs) {
|
|
5807
|
-
const manifest =
|
|
5808
|
+
const manifest = readFile22(path.join(packageDir, "package.json"));
|
|
5808
5809
|
if (!manifest) continue;
|
|
5809
5810
|
const relative11 = binField(manifest);
|
|
5810
5811
|
if (!relative11) continue;
|
|
@@ -6217,16 +6218,16 @@ function makeCanUseTool(state) {
|
|
|
6217
6218
|
return (toolName, input, options) => {
|
|
6218
6219
|
if (toolName === "AskUserQuestion") {
|
|
6219
6220
|
const toolUseId = options.toolUseID;
|
|
6220
|
-
return new Promise((
|
|
6221
|
+
return new Promise((resolve22) => {
|
|
6221
6222
|
const pending = {
|
|
6222
6223
|
input,
|
|
6223
6224
|
askedAt: Date.now(),
|
|
6224
|
-
resolve:
|
|
6225
|
+
resolve: resolve22
|
|
6225
6226
|
};
|
|
6226
6227
|
state.pendingUserQuestions.set(toolUseId, pending);
|
|
6227
6228
|
const onAbort = () => {
|
|
6228
6229
|
if (state.pendingUserQuestions.delete(toolUseId)) {
|
|
6229
|
-
|
|
6230
|
+
resolve22({ behavior: "deny", message: "Session aborted", interrupt: true });
|
|
6230
6231
|
}
|
|
6231
6232
|
};
|
|
6232
6233
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -6239,7 +6240,7 @@ function makeCanUseTool(state) {
|
|
|
6239
6240
|
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
6240
6241
|
}
|
|
6241
6242
|
const requestId = options.toolUseID;
|
|
6242
|
-
return new Promise((
|
|
6243
|
+
return new Promise((resolve22) => {
|
|
6243
6244
|
const pending = {
|
|
6244
6245
|
requestId,
|
|
6245
6246
|
toolName,
|
|
@@ -6252,12 +6253,12 @@ function makeCanUseTool(state) {
|
|
|
6252
6253
|
blockedPath: options.blockedPath,
|
|
6253
6254
|
suggestions: options.suggestions,
|
|
6254
6255
|
timestamp: Date.now(),
|
|
6255
|
-
resolve:
|
|
6256
|
+
resolve: resolve22
|
|
6256
6257
|
};
|
|
6257
6258
|
state.pendingPermissions.set(requestId, pending);
|
|
6258
6259
|
const onAbort = () => {
|
|
6259
6260
|
if (state.pendingPermissions.delete(requestId)) {
|
|
6260
|
-
|
|
6261
|
+
resolve22({ behavior: "deny", message: "Session aborted", interrupt: true });
|
|
6261
6262
|
}
|
|
6262
6263
|
};
|
|
6263
6264
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -6334,16 +6335,16 @@ function makeOnElicitation(state) {
|
|
|
6334
6335
|
);
|
|
6335
6336
|
return Promise.resolve({ action: "decline" });
|
|
6336
6337
|
}
|
|
6337
|
-
return new Promise((
|
|
6338
|
+
return new Promise((resolve22) => {
|
|
6338
6339
|
const requestId = options.requestId;
|
|
6339
6340
|
state.pendingElicitations.set(requestId, {
|
|
6340
6341
|
request,
|
|
6341
6342
|
fields: projection.fields,
|
|
6342
6343
|
askedAt: Date.now(),
|
|
6343
|
-
resolve:
|
|
6344
|
+
resolve: resolve22
|
|
6344
6345
|
});
|
|
6345
6346
|
const onAbort = () => {
|
|
6346
|
-
if (state.pendingElicitations.delete(requestId))
|
|
6347
|
+
if (state.pendingElicitations.delete(requestId)) resolve22({ action: "decline" });
|
|
6347
6348
|
};
|
|
6348
6349
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
6349
6350
|
});
|
|
@@ -6367,14 +6368,14 @@ function makeOnUserDialog(state) {
|
|
|
6367
6368
|
if (!(request.dialogKind in DIALOG_CHOICES)) return Promise.resolve(null);
|
|
6368
6369
|
const projected = projectUserDialog(request);
|
|
6369
6370
|
if (!projected) return Promise.resolve({ behavior: "cancelled" });
|
|
6370
|
-
return new Promise((
|
|
6371
|
+
return new Promise((resolve22) => {
|
|
6371
6372
|
const requestId = options.requestId;
|
|
6372
6373
|
state.pendingUserDialogs.set(requestId, {
|
|
6373
6374
|
dialog: { ...projected, requestId, askedAt: Date.now() },
|
|
6374
|
-
resolve:
|
|
6375
|
+
resolve: resolve22
|
|
6375
6376
|
});
|
|
6376
6377
|
const onAbort = () => {
|
|
6377
|
-
if (state.pendingUserDialogs.delete(requestId))
|
|
6378
|
+
if (state.pendingUserDialogs.delete(requestId)) resolve22({ behavior: "cancelled" });
|
|
6378
6379
|
};
|
|
6379
6380
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
6380
6381
|
});
|
|
@@ -7103,8 +7104,8 @@ var init_sdk_session = __esm({
|
|
|
7103
7104
|
closed = false;
|
|
7104
7105
|
enqueue(message) {
|
|
7105
7106
|
if (this.closed) return false;
|
|
7106
|
-
const
|
|
7107
|
-
if (
|
|
7107
|
+
const resolve22 = this.waiting.shift();
|
|
7108
|
+
if (resolve22) resolve22({ value: message, done: false });
|
|
7108
7109
|
else this.queued.push(message);
|
|
7109
7110
|
return true;
|
|
7110
7111
|
}
|
|
@@ -7112,15 +7113,15 @@ var init_sdk_session = __esm({
|
|
|
7112
7113
|
if (this.closed) return;
|
|
7113
7114
|
this.closed = true;
|
|
7114
7115
|
this.queued.length = 0;
|
|
7115
|
-
for (const
|
|
7116
|
-
|
|
7116
|
+
for (const resolve22 of this.waiting.splice(0)) {
|
|
7117
|
+
resolve22({ value: void 0, done: true });
|
|
7117
7118
|
}
|
|
7118
7119
|
}
|
|
7119
7120
|
next() {
|
|
7120
7121
|
const message = this.queued.shift();
|
|
7121
7122
|
if (message) return Promise.resolve({ value: message, done: false });
|
|
7122
7123
|
if (this.closed) return Promise.resolve({ value: void 0, done: true });
|
|
7123
|
-
return new Promise((
|
|
7124
|
+
return new Promise((resolve22) => this.waiting.push(resolve22));
|
|
7124
7125
|
}
|
|
7125
7126
|
return() {
|
|
7126
7127
|
this.close();
|
|
@@ -7256,8 +7257,8 @@ var init_agent_prompts = __esm({
|
|
|
7256
7257
|
function observeExit(proc) {
|
|
7257
7258
|
let didExit = proc.exitCode !== null && proc.exitCode !== void 0 || proc.signalCode !== null && proc.signalCode !== void 0;
|
|
7258
7259
|
let resolveExit = () => void 0;
|
|
7259
|
-
const exited = new Promise((
|
|
7260
|
-
resolveExit =
|
|
7260
|
+
const exited = new Promise((resolve22) => {
|
|
7261
|
+
resolveExit = resolve22;
|
|
7261
7262
|
});
|
|
7262
7263
|
if (didExit) resolveExit();
|
|
7263
7264
|
const markExited = () => {
|
|
@@ -7283,14 +7284,14 @@ function observeExit(proc) {
|
|
|
7283
7284
|
async function waitForExit(observers, timeoutMs, onTimeout = () => void 0) {
|
|
7284
7285
|
const pending = observers.filter((observer) => !observer.hasExited());
|
|
7285
7286
|
if (pending.length === 0) return;
|
|
7286
|
-
await new Promise((
|
|
7287
|
+
await new Promise((resolve22) => {
|
|
7287
7288
|
const timer = setTimeout(() => {
|
|
7288
7289
|
onTimeout();
|
|
7289
|
-
|
|
7290
|
+
resolve22();
|
|
7290
7291
|
}, timeoutMs);
|
|
7291
7292
|
void Promise.all(pending.map((observer) => observer.exited)).then(() => {
|
|
7292
7293
|
clearTimeout(timer);
|
|
7293
|
-
|
|
7294
|
+
resolve22();
|
|
7294
7295
|
});
|
|
7295
7296
|
});
|
|
7296
7297
|
}
|
|
@@ -7573,7 +7574,7 @@ async function readClaudeSessionMeta(filePath, head) {
|
|
|
7573
7574
|
let cwd = "";
|
|
7574
7575
|
let firstUserMessage = "";
|
|
7575
7576
|
let lastUserMessage = "";
|
|
7576
|
-
let
|
|
7577
|
+
let timestamp2 = "";
|
|
7577
7578
|
let lastTimestamp = "";
|
|
7578
7579
|
let turnCount = 0;
|
|
7579
7580
|
let aiTitle = "";
|
|
@@ -7612,8 +7613,8 @@ async function readClaudeSessionMeta(filePath, head) {
|
|
|
7612
7613
|
if (obj.type === "assistant" && obj.message?.model && !model) {
|
|
7613
7614
|
model = obj.message.model;
|
|
7614
7615
|
}
|
|
7615
|
-
if (obj.type === "user" && !obj.isMeta && !
|
|
7616
|
-
|
|
7616
|
+
if (obj.type === "user" && !obj.isMeta && !timestamp2) {
|
|
7617
|
+
timestamp2 = obj.timestamp || "";
|
|
7617
7618
|
}
|
|
7618
7619
|
if (obj.type === "user" && !obj.isMeta) {
|
|
7619
7620
|
if (obj.timestamp) lastTimestamp = obj.timestamp;
|
|
@@ -7708,8 +7709,8 @@ async function readClaudeSessionMeta(filePath, head) {
|
|
|
7708
7709
|
cwd,
|
|
7709
7710
|
firstUserMessage,
|
|
7710
7711
|
lastUserMessage,
|
|
7711
|
-
timestamp,
|
|
7712
|
-
lastTimestamp: lastTimestamp ||
|
|
7712
|
+
timestamp: timestamp2,
|
|
7713
|
+
lastTimestamp: lastTimestamp || timestamp2,
|
|
7713
7714
|
turnCount,
|
|
7714
7715
|
lineCount: isPartialRead ? Math.round(head.size / (HEAD_BYTES / lines.length)) : lines.length,
|
|
7715
7716
|
branchedFrom,
|
|
@@ -7998,7 +7999,7 @@ var init_sessionStats = __esm({
|
|
|
7998
7999
|
});
|
|
7999
8000
|
|
|
8000
8001
|
// ../../shared/session/turnContent.ts
|
|
8001
|
-
function appendAssistantText(turn, text,
|
|
8002
|
+
function appendAssistantText(turn, text, timestamp2) {
|
|
8002
8003
|
if (!text) return;
|
|
8003
8004
|
turn.assistantText.push(text);
|
|
8004
8005
|
const last = turn.contentBlocks[turn.contentBlocks.length - 1];
|
|
@@ -8006,7 +8007,7 @@ function appendAssistantText(turn, text, timestamp) {
|
|
|
8006
8007
|
last.text.push(text);
|
|
8007
8008
|
return;
|
|
8008
8009
|
}
|
|
8009
|
-
turn.contentBlocks.push({ kind: "text", text: [text], timestamp });
|
|
8010
|
+
turn.contentBlocks.push({ kind: "text", text: [text], timestamp: timestamp2 });
|
|
8010
8011
|
}
|
|
8011
8012
|
var init_turnContent = __esm({
|
|
8012
8013
|
"../../shared/session/turnContent.ts"() {
|
|
@@ -8376,7 +8377,7 @@ function resolveCodexPatchPath(filePath, cwd) {
|
|
|
8376
8377
|
const relative11 = filePath.replace(/^\.[\\/]/, "");
|
|
8377
8378
|
return /^[A-Za-z]:[\\/]/.test(cwd) ? `${base}\\${relative11.replace(/\//g, "\\")}` : `${base}/${relative11}`;
|
|
8378
8379
|
}
|
|
8379
|
-
function parseApplyPatch(patchText, callId,
|
|
8380
|
+
function parseApplyPatch(patchText, callId, timestamp2, cwd = "") {
|
|
8380
8381
|
const toolCalls = [];
|
|
8381
8382
|
const filePattern = /^\*\*\*\s+(Update File|Add File|Delete File):\s*(.+)$/gm;
|
|
8382
8383
|
const sections = [];
|
|
@@ -8419,7 +8420,7 @@ function parseApplyPatch(patchText, callId, timestamp, cwd = "") {
|
|
|
8419
8420
|
input: { file_path: filePath, content: newLines.join("\n") },
|
|
8420
8421
|
result: null,
|
|
8421
8422
|
isError: false,
|
|
8422
|
-
timestamp
|
|
8423
|
+
timestamp: timestamp2
|
|
8423
8424
|
});
|
|
8424
8425
|
} else if (section.action === "Delete File") {
|
|
8425
8426
|
toolCalls.push({
|
|
@@ -8428,7 +8429,7 @@ function parseApplyPatch(patchText, callId, timestamp, cwd = "") {
|
|
|
8428
8429
|
input: { file_path: filePath, old_string: oldLines.join("\n"), new_string: "" },
|
|
8429
8430
|
result: null,
|
|
8430
8431
|
isError: false,
|
|
8431
|
-
timestamp
|
|
8432
|
+
timestamp: timestamp2
|
|
8432
8433
|
});
|
|
8433
8434
|
} else {
|
|
8434
8435
|
toolCalls.push({
|
|
@@ -8442,18 +8443,18 @@ function parseApplyPatch(patchText, callId, timestamp, cwd = "") {
|
|
|
8442
8443
|
},
|
|
8443
8444
|
result: null,
|
|
8444
8445
|
isError: false,
|
|
8445
|
-
timestamp
|
|
8446
|
+
timestamp: timestamp2
|
|
8446
8447
|
});
|
|
8447
8448
|
}
|
|
8448
8449
|
}
|
|
8449
8450
|
return toolCalls;
|
|
8450
8451
|
}
|
|
8451
|
-
function parseCodexToolPatches(toolName, rawInput, callId,
|
|
8452
|
+
function parseCodexToolPatches(toolName, rawInput, callId, timestamp2, cwd = "") {
|
|
8452
8453
|
if (toolName === "apply_patch") {
|
|
8453
|
-
return parseApplyPatch(rawInput, callId,
|
|
8454
|
+
return parseApplyPatch(rawInput, callId, timestamp2, cwd);
|
|
8454
8455
|
}
|
|
8455
8456
|
return extractApplyPatchInputs(rawInput).flatMap(
|
|
8456
|
-
(patch, patchIndex) => parseApplyPatch(patch, `${callId}:patch-${patchIndex}`,
|
|
8457
|
+
(patch, patchIndex) => parseApplyPatch(patch, `${callId}:patch-${patchIndex}`, timestamp2, cwd)
|
|
8457
8458
|
);
|
|
8458
8459
|
}
|
|
8459
8460
|
function findFailedNestedPatchCallIds(output, wrapperIsError, calls) {
|
|
@@ -8578,9 +8579,9 @@ function safeParseLine(line) {
|
|
|
8578
8579
|
function isObject2(value) {
|
|
8579
8580
|
return typeof value === "object" && value !== null;
|
|
8580
8581
|
}
|
|
8581
|
-
function isCodexRecord(
|
|
8582
|
-
if (!
|
|
8583
|
-
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";
|
|
8584
8585
|
}
|
|
8585
8586
|
function extractMessageText(payload, blockType) {
|
|
8586
8587
|
const content = payload?.content;
|
|
@@ -8697,7 +8698,7 @@ function parseTokenUsage(value) {
|
|
|
8697
8698
|
cache_read_input_tokens: cacheRead
|
|
8698
8699
|
};
|
|
8699
8700
|
}
|
|
8700
|
-
function appendThinking(turn, text,
|
|
8701
|
+
function appendThinking(turn, text, timestamp2) {
|
|
8701
8702
|
if (!text) return;
|
|
8702
8703
|
const block = { type: "thinking", thinking: text, signature: "" };
|
|
8703
8704
|
turn.thinking.push(block);
|
|
@@ -8706,16 +8707,16 @@ function appendThinking(turn, text, timestamp) {
|
|
|
8706
8707
|
last.blocks.push(block);
|
|
8707
8708
|
return;
|
|
8708
8709
|
}
|
|
8709
|
-
turn.contentBlocks.push({ kind: "thinking", blocks: [block], timestamp });
|
|
8710
|
+
turn.contentBlocks.push({ kind: "thinking", blocks: [block], timestamp: timestamp2 });
|
|
8710
8711
|
}
|
|
8711
|
-
function appendToolCall(turn, toolCall,
|
|
8712
|
+
function appendToolCall(turn, toolCall, timestamp2) {
|
|
8712
8713
|
turn.toolCalls.push(toolCall);
|
|
8713
8714
|
const last = turn.contentBlocks[turn.contentBlocks.length - 1];
|
|
8714
|
-
if (last && last.kind === "tool_calls" && last.timestamp ===
|
|
8715
|
+
if (last && last.kind === "tool_calls" && last.timestamp === timestamp2) {
|
|
8715
8716
|
last.toolCalls.push(toolCall);
|
|
8716
8717
|
return;
|
|
8717
8718
|
}
|
|
8718
|
-
turn.contentBlocks.push({ kind: "tool_calls", toolCalls: [toolCall], timestamp });
|
|
8719
|
+
turn.contentBlocks.push({ kind: "tool_calls", toolCalls: [toolCall], timestamp: timestamp2 });
|
|
8719
8720
|
}
|
|
8720
8721
|
function finalizeTurn(turns, current, lastTimestamp) {
|
|
8721
8722
|
if (!current) return null;
|
|
@@ -8766,37 +8767,37 @@ function parseMcpEventResult(value) {
|
|
|
8766
8767
|
isError: ok.isError === true || parsedContent.isError
|
|
8767
8768
|
};
|
|
8768
8769
|
}
|
|
8769
|
-
function createTurn(turnId,
|
|
8770
|
+
function createTurn(turnId, timestamp2, model) {
|
|
8770
8771
|
return {
|
|
8771
|
-
id: turnId ? `${turnId}@${
|
|
8772
|
+
id: turnId ? `${turnId}@${timestamp2}` : randomTurnId("codex-turn"),
|
|
8772
8773
|
userMessage: null,
|
|
8773
8774
|
contentBlocks: [],
|
|
8774
8775
|
thinking: [],
|
|
8775
8776
|
assistantText: [],
|
|
8776
8777
|
toolCalls: [],
|
|
8777
8778
|
subAgentActivity: [],
|
|
8778
|
-
timestamp,
|
|
8779
|
+
timestamp: timestamp2,
|
|
8779
8780
|
durationMs: null,
|
|
8780
8781
|
tokenUsage: null,
|
|
8781
8782
|
model
|
|
8782
8783
|
};
|
|
8783
8784
|
}
|
|
8784
|
-
function extractPromptFromRecord(
|
|
8785
|
-
if (
|
|
8786
|
-
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);
|
|
8787
8788
|
}
|
|
8788
|
-
if (
|
|
8789
|
-
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"));
|
|
8790
8791
|
}
|
|
8791
8792
|
return "";
|
|
8792
8793
|
}
|
|
8793
|
-
function recordOpensTurn(
|
|
8794
|
-
if (
|
|
8795
|
-
if (
|
|
8796
|
-
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") {
|
|
8797
8798
|
if (payload.role === "developer" || payload.role === "system") return false;
|
|
8798
8799
|
if (payload.role === "user") {
|
|
8799
|
-
return extractPromptFromRecord(
|
|
8800
|
+
return extractPromptFromRecord(record4) !== "" || extractResponseMessageImages(payload).length > 0 || extractResponseMessageAudio(payload).length > 0;
|
|
8800
8801
|
}
|
|
8801
8802
|
}
|
|
8802
8803
|
return true;
|
|
@@ -8810,29 +8811,29 @@ function extractMetadataFromRecords(records) {
|
|
|
8810
8811
|
let branchedFrom;
|
|
8811
8812
|
let firstUserMessage = "";
|
|
8812
8813
|
let lastUserMessage = "";
|
|
8813
|
-
let
|
|
8814
|
+
let timestamp2 = "";
|
|
8814
8815
|
let lastTimestamp = "";
|
|
8815
8816
|
let turnCount = 0;
|
|
8816
8817
|
let isSubagent = false;
|
|
8817
8818
|
let parentSessionId = null;
|
|
8818
8819
|
let agentPath = "/root";
|
|
8819
8820
|
let previousPrompt = "";
|
|
8820
|
-
for (const
|
|
8821
|
-
if (!isObject2(
|
|
8822
|
-
if (
|
|
8823
|
-
sessionId ||= typeof
|
|
8824
|
-
version ||= typeof
|
|
8825
|
-
cwd ||= typeof
|
|
8826
|
-
if (!branchedFrom && isObject2(
|
|
8827
|
-
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 : "";
|
|
8828
8829
|
if (sourceId) {
|
|
8829
8830
|
branchedFrom = {
|
|
8830
8831
|
sessionId: sourceId,
|
|
8831
|
-
turnIndex: typeof
|
|
8832
|
+
turnIndex: typeof record4.payload.branchedFrom.turnIndex === "number" ? record4.payload.branchedFrom.turnIndex : null
|
|
8832
8833
|
};
|
|
8833
8834
|
}
|
|
8834
8835
|
}
|
|
8835
|
-
const source = isObject2(
|
|
8836
|
+
const source = isObject2(record4.payload.source) ? record4.payload.source : null;
|
|
8836
8837
|
if (source && isObject2(source.subagent)) {
|
|
8837
8838
|
isSubagent = true;
|
|
8838
8839
|
const threadSpawn = isObject2(source.subagent.thread_spawn) ? source.subagent.thread_spawn : null;
|
|
@@ -8840,27 +8841,27 @@ function extractMetadataFromRecords(records) {
|
|
|
8840
8841
|
agentPath = threadSpawn.agent_path;
|
|
8841
8842
|
}
|
|
8842
8843
|
}
|
|
8843
|
-
if (typeof
|
|
8844
|
-
parentSessionId =
|
|
8844
|
+
if (typeof record4.payload.forked_from_id === "string" && record4.payload.forked_from_id) {
|
|
8845
|
+
parentSessionId = record4.payload.forked_from_id;
|
|
8845
8846
|
}
|
|
8846
|
-
const git = isObject2(
|
|
8847
|
+
const git = isObject2(record4.payload.git) ? record4.payload.git : null;
|
|
8847
8848
|
gitBranch ||= git && typeof git.branch === "string" ? git.branch : "";
|
|
8848
8849
|
}
|
|
8849
|
-
if (
|
|
8850
|
-
model ||= typeof
|
|
8851
|
-
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 : "";
|
|
8852
8853
|
}
|
|
8853
|
-
const prompt = extractPromptFromRecord(
|
|
8854
|
+
const prompt = extractPromptFromRecord(record4);
|
|
8854
8855
|
if (!prompt) continue;
|
|
8855
8856
|
if (prompt === previousPrompt) continue;
|
|
8856
8857
|
if (!firstUserMessage) firstUserMessage = prompt;
|
|
8857
8858
|
lastUserMessage = prompt;
|
|
8858
8859
|
previousPrompt = prompt;
|
|
8859
8860
|
turnCount++;
|
|
8860
|
-
if (!
|
|
8861
|
-
lastTimestamp =
|
|
8861
|
+
if (!timestamp2) timestamp2 = record4.timestamp ?? "";
|
|
8862
|
+
lastTimestamp = record4.timestamp ?? lastTimestamp;
|
|
8862
8863
|
}
|
|
8863
|
-
if (lastTimestamp === "") lastTimestamp =
|
|
8864
|
+
if (lastTimestamp === "") lastTimestamp = timestamp2;
|
|
8864
8865
|
return {
|
|
8865
8866
|
sessionId,
|
|
8866
8867
|
version,
|
|
@@ -8872,7 +8873,7 @@ function extractMetadataFromRecords(records) {
|
|
|
8872
8873
|
branchedFrom,
|
|
8873
8874
|
firstUserMessage,
|
|
8874
8875
|
lastUserMessage,
|
|
8875
|
-
timestamp,
|
|
8876
|
+
timestamp: timestamp2,
|
|
8876
8877
|
lastTimestamp,
|
|
8877
8878
|
turnCount,
|
|
8878
8879
|
isSubagent,
|
|
@@ -8985,8 +8986,8 @@ function walkCodexRecords(records, options) {
|
|
|
8985
8986
|
pendingTurnStart = null;
|
|
8986
8987
|
return result;
|
|
8987
8988
|
}
|
|
8988
|
-
function createActiveTurn(turnId,
|
|
8989
|
-
const turn = createTurn(turnId,
|
|
8989
|
+
function createActiveTurn(turnId, timestamp2, model) {
|
|
8990
|
+
const turn = createTurn(turnId, timestamp2, model);
|
|
8990
8991
|
pendingTurnStart = pendingContextIndex ?? recordIndex;
|
|
8991
8992
|
pendingContextIndex = null;
|
|
8992
8993
|
if (!sawTurnStart) turn.isFragment = true;
|
|
@@ -8996,7 +8997,7 @@ function walkCodexRecords(records, options) {
|
|
|
8996
8997
|
}
|
|
8997
8998
|
return turn;
|
|
8998
8999
|
}
|
|
8999
|
-
function upsertWebSearchCall(targetTurn, id, input, status,
|
|
9000
|
+
function upsertWebSearchCall(targetTurn, id, input, status, timestamp2) {
|
|
9000
9001
|
const existing = webSearchCalls.get(id);
|
|
9001
9002
|
if (existing) {
|
|
9002
9003
|
existing.input = { ...existing.input, ...input };
|
|
@@ -9010,39 +9011,39 @@ function walkCodexRecords(records, options) {
|
|
|
9010
9011
|
input,
|
|
9011
9012
|
result: status,
|
|
9012
9013
|
isError: status === "failed",
|
|
9013
|
-
timestamp
|
|
9014
|
+
timestamp: timestamp2
|
|
9014
9015
|
};
|
|
9015
9016
|
webSearchCalls.set(id, toolCall);
|
|
9016
|
-
appendToolCall(targetTurn, toolCall,
|
|
9017
|
+
appendToolCall(targetTurn, toolCall, timestamp2);
|
|
9017
9018
|
}
|
|
9018
9019
|
for (let index = 0; index < records.length; index++) {
|
|
9019
|
-
const
|
|
9020
|
-
if (!isCodexRecord(
|
|
9020
|
+
const record4 = records[index];
|
|
9021
|
+
if (!isCodexRecord(record4)) continue;
|
|
9021
9022
|
recordIndex = index;
|
|
9022
|
-
const payload = isObject2(
|
|
9023
|
-
const
|
|
9024
|
-
if (
|
|
9023
|
+
const payload = isObject2(record4.payload) ? record4.payload : void 0;
|
|
9024
|
+
const timestamp2 = record4.timestamp ?? "";
|
|
9025
|
+
if (record4.type === "compacted") {
|
|
9025
9026
|
current = commitTurn(current);
|
|
9026
9027
|
pendingCompaction = "Conversation compacted";
|
|
9027
|
-
lastTurnTimestamp =
|
|
9028
|
+
lastTurnTimestamp = timestamp2;
|
|
9028
9029
|
continue;
|
|
9029
9030
|
}
|
|
9030
|
-
if (
|
|
9031
|
-
if (
|
|
9031
|
+
if (record4.type === "world_state") continue;
|
|
9032
|
+
if (record4.type === "turn_context") {
|
|
9032
9033
|
current = commitTurn(current);
|
|
9033
9034
|
pendingContextIndex = index;
|
|
9034
9035
|
currentTurnId = typeof payload?.turn_id === "string" ? payload.turn_id : null;
|
|
9035
9036
|
currentModel = typeof payload?.model === "string" ? payload.model : currentModel;
|
|
9036
|
-
lastTurnTimestamp =
|
|
9037
|
+
lastTurnTimestamp = timestamp2;
|
|
9037
9038
|
sawTurnStart = true;
|
|
9038
9039
|
continue;
|
|
9039
9040
|
}
|
|
9040
|
-
if (
|
|
9041
|
+
if (record4.type === "event_msg" && payload?.type === "user_message" && typeof payload.message === "string") {
|
|
9041
9042
|
if (current && (current.assistantText.length > 0 || current.toolCalls.length > 0 || current.thinking.length > 0)) {
|
|
9042
9043
|
current = commitTurn(current);
|
|
9043
9044
|
}
|
|
9044
9045
|
sawTurnStart = true;
|
|
9045
|
-
current ??= createActiveTurn(currentTurnId,
|
|
9046
|
+
current ??= createActiveTurn(currentTurnId, timestamp2, currentModel);
|
|
9046
9047
|
const localImages = (Array.isArray(payload.local_images) ? payload.local_images : []).filter(
|
|
9047
9048
|
(p) => typeof p === "string" && p.length > 0
|
|
9048
9049
|
);
|
|
@@ -9057,16 +9058,16 @@ function walkCodexRecords(records, options) {
|
|
|
9057
9058
|
localAudio
|
|
9058
9059
|
);
|
|
9059
9060
|
current.isFragment = false;
|
|
9060
|
-
current.timestamp = current.timestamp ||
|
|
9061
|
-
lastTurnTimestamp =
|
|
9061
|
+
current.timestamp = current.timestamp || timestamp2;
|
|
9062
|
+
lastTurnTimestamp = timestamp2;
|
|
9062
9063
|
continue;
|
|
9063
9064
|
}
|
|
9064
|
-
if (!current && !recordOpensTurn(
|
|
9065
|
-
current ??= createActiveTurn(currentTurnId,
|
|
9065
|
+
if (!current && !recordOpensTurn(record4, payload)) continue;
|
|
9066
|
+
current ??= createActiveTurn(currentTurnId, timestamp2, currentModel);
|
|
9066
9067
|
if (!current.model && currentModel) current.model = currentModel;
|
|
9067
|
-
if (!current.timestamp) current.timestamp =
|
|
9068
|
-
if (
|
|
9069
|
-
if (
|
|
9068
|
+
if (!current.timestamp) current.timestamp = timestamp2;
|
|
9069
|
+
if (timestamp2) lastTurnTimestamp = timestamp2;
|
|
9070
|
+
if (record4.type === "event_msg" && payload?.type === "token_count") {
|
|
9070
9071
|
const info = isObject2(payload.info) ? payload.info : null;
|
|
9071
9072
|
const lastUsage = info ? parseTokenUsage(info.last_token_usage) : null;
|
|
9072
9073
|
if (lastUsage) {
|
|
@@ -9074,14 +9075,14 @@ function walkCodexRecords(records, options) {
|
|
|
9074
9075
|
}
|
|
9075
9076
|
continue;
|
|
9076
9077
|
}
|
|
9077
|
-
if (
|
|
9078
|
+
if (record4.type === "event_msg" && payload?.type === "web_search_end" && typeof payload.call_id === "string") {
|
|
9078
9079
|
const input = {};
|
|
9079
9080
|
if (typeof payload.query === "string" && payload.query) input.query = payload.query;
|
|
9080
9081
|
if (isObject2(payload.action)) input.action = payload.action;
|
|
9081
|
-
upsertWebSearchCall(current, payload.call_id, input, "completed",
|
|
9082
|
+
upsertWebSearchCall(current, payload.call_id, input, "completed", timestamp2);
|
|
9082
9083
|
continue;
|
|
9083
9084
|
}
|
|
9084
|
-
if (
|
|
9085
|
+
if (record4.type === "event_msg" && payload?.type === "mcp_tool_call_end" && typeof payload.call_id === "string" && isObject2(payload.invocation)) {
|
|
9085
9086
|
const invocation = payload.invocation;
|
|
9086
9087
|
const server = typeof invocation.server === "string" ? invocation.server : "mcp";
|
|
9087
9088
|
const tool = typeof invocation.tool === "string" ? invocation.tool : "tool";
|
|
@@ -9099,12 +9100,12 @@ function walkCodexRecords(records, options) {
|
|
|
9099
9100
|
input,
|
|
9100
9101
|
result: result.text,
|
|
9101
9102
|
isError: result.isError,
|
|
9102
|
-
timestamp
|
|
9103
|
-
},
|
|
9103
|
+
timestamp: timestamp2
|
|
9104
|
+
}, timestamp2);
|
|
9104
9105
|
}
|
|
9105
9106
|
continue;
|
|
9106
9107
|
}
|
|
9107
|
-
if (
|
|
9108
|
+
if (record4.type === "event_msg" && payload?.type === "sub_agent_activity" && typeof payload.agent_thread_id === "string" && typeof payload.agent_path === "string") {
|
|
9108
9109
|
const agentId = payload.agent_thread_id;
|
|
9109
9110
|
const eventId2 = typeof payload.event_id === "string" ? payload.event_id : "";
|
|
9110
9111
|
const kind = typeof payload.kind === "string" ? payload.kind : "started";
|
|
@@ -9128,24 +9129,24 @@ function walkCodexRecords(records, options) {
|
|
|
9128
9129
|
message: existing?.message ?? spawnInfo?.message ?? "",
|
|
9129
9130
|
model: existing?.model ?? spawnInfo?.model ?? null,
|
|
9130
9131
|
agentType: existing?.agentType ?? spawnInfo?.agentType ?? null,
|
|
9131
|
-
timestamp: existing?.timestamp ?? (
|
|
9132
|
+
timestamp: existing?.timestamp ?? (timestamp2 || spawnInfo?.timestamp || ""),
|
|
9132
9133
|
parentToolCallId: existing?.parentToolCallId ?? eventId2
|
|
9133
9134
|
};
|
|
9134
9135
|
agentRegistry.set(agentId, info);
|
|
9135
9136
|
agentIdByPath.set(payload.agent_path, agentId);
|
|
9136
9137
|
if (eventId2 && (kind === "started" || spawnInfo)) agentIdBySpawnCall.set(eventId2, agentId);
|
|
9137
9138
|
const status = kind === "interrupted" ? "interrupted" : "running";
|
|
9138
|
-
upsertAgentMessage(agentId, current,
|
|
9139
|
+
upsertAgentMessage(agentId, current, timestamp2, { status });
|
|
9139
9140
|
continue;
|
|
9140
9141
|
}
|
|
9141
|
-
if (
|
|
9142
|
+
if (record4.type !== "response_item" || !payload) continue;
|
|
9142
9143
|
if (payload.type === "reasoning") {
|
|
9143
9144
|
const summary = Array.isArray(payload.summary) ? payload.summary.filter((item) => typeof item === "string").join("\n") : "";
|
|
9144
|
-
appendThinking(current, summary.trim(),
|
|
9145
|
+
appendThinking(current, summary.trim(), timestamp2);
|
|
9145
9146
|
continue;
|
|
9146
9147
|
}
|
|
9147
9148
|
if (payload.type === "message" && payload.role === "assistant") {
|
|
9148
|
-
appendAssistantText(current, extractMessageText(payload, "output_text"),
|
|
9149
|
+
appendAssistantText(current, extractMessageText(payload, "output_text"), timestamp2);
|
|
9149
9150
|
continue;
|
|
9150
9151
|
}
|
|
9151
9152
|
if (payload.type === "message" && payload.role === "user" && current.userMessage === null) {
|
|
@@ -9163,7 +9164,7 @@ function walkCodexRecords(records, options) {
|
|
|
9163
9164
|
const input = {};
|
|
9164
9165
|
if (isObject2(payload.action)) input.action = payload.action;
|
|
9165
9166
|
const status = typeof payload.status === "string" ? payload.status : "completed";
|
|
9166
|
-
upsertWebSearchCall(current, payload.id, input, status,
|
|
9167
|
+
upsertWebSearchCall(current, payload.id, input, status, timestamp2);
|
|
9167
9168
|
continue;
|
|
9168
9169
|
}
|
|
9169
9170
|
if (payload.type === "tool_search_call") {
|
|
@@ -9175,10 +9176,10 @@ function walkCodexRecords(records, options) {
|
|
|
9175
9176
|
input: isObject2(payload.arguments) ? payload.arguments : {},
|
|
9176
9177
|
result: null,
|
|
9177
9178
|
isError: false,
|
|
9178
|
-
timestamp
|
|
9179
|
+
timestamp: timestamp2
|
|
9179
9180
|
};
|
|
9180
9181
|
pendingToolCalls.set(callId, toolCall);
|
|
9181
|
-
appendToolCall(current, toolCall,
|
|
9182
|
+
appendToolCall(current, toolCall, timestamp2);
|
|
9182
9183
|
}
|
|
9183
9184
|
continue;
|
|
9184
9185
|
}
|
|
@@ -9212,7 +9213,7 @@ function walkCodexRecords(records, options) {
|
|
|
9212
9213
|
message: "",
|
|
9213
9214
|
model: null,
|
|
9214
9215
|
agentType: null,
|
|
9215
|
-
timestamp,
|
|
9216
|
+
timestamp: timestamp2,
|
|
9216
9217
|
parentToolCallId: ""
|
|
9217
9218
|
});
|
|
9218
9219
|
agentIdByPath.set(author, agentId);
|
|
@@ -9222,7 +9223,7 @@ function walkCodexRecords(records, options) {
|
|
|
9222
9223
|
else if (interAgentMessage.messageType === "ERROR" || interAgentMessage.messageType === "FAILED") status = "failed";
|
|
9223
9224
|
else if (interAgentMessage.messageType === "INTERRUPTED") status = "interrupted";
|
|
9224
9225
|
else if (interAgentMessage.messageType === "MESSAGE") status = "running";
|
|
9225
|
-
upsertAgentMessage(agentId, current,
|
|
9226
|
+
upsertAgentMessage(agentId, current, timestamp2, {
|
|
9226
9227
|
status,
|
|
9227
9228
|
text: interAgentMessage.text || void 0
|
|
9228
9229
|
});
|
|
@@ -9247,7 +9248,7 @@ function walkCodexRecords(records, options) {
|
|
|
9247
9248
|
taskName: typeof parsedInput.task_name === "string" ? parsedInput.task_name : null,
|
|
9248
9249
|
model: typeof parsedInput.model === "string" ? parsedInput.model : null,
|
|
9249
9250
|
agentType: typeof parsedInput.agent_type === "string" ? parsedInput.agent_type : null,
|
|
9250
|
-
timestamp
|
|
9251
|
+
timestamp: timestamp2
|
|
9251
9252
|
});
|
|
9252
9253
|
}
|
|
9253
9254
|
const toolCall = {
|
|
@@ -9256,10 +9257,10 @@ function walkCodexRecords(records, options) {
|
|
|
9256
9257
|
input,
|
|
9257
9258
|
result: null,
|
|
9258
9259
|
isError: false,
|
|
9259
|
-
timestamp
|
|
9260
|
+
timestamp: timestamp2
|
|
9260
9261
|
};
|
|
9261
9262
|
pendingToolCalls.set(toolCall.id, toolCall);
|
|
9262
|
-
appendToolCall(current, toolCall,
|
|
9263
|
+
appendToolCall(current, toolCall, timestamp2);
|
|
9263
9264
|
continue;
|
|
9264
9265
|
}
|
|
9265
9266
|
if (payload.type === "function_call_output" && typeof payload.call_id === "string") {
|
|
@@ -9285,13 +9286,13 @@ function walkCodexRecords(records, options) {
|
|
|
9285
9286
|
message: existing?.message ?? spawnInfo?.message ?? "",
|
|
9286
9287
|
model: existing?.model ?? spawnInfo?.model ?? null,
|
|
9287
9288
|
agentType: existing?.agentType ?? spawnInfo?.agentType ?? null,
|
|
9288
|
-
timestamp: existing?.timestamp ?? spawnInfo?.timestamp ??
|
|
9289
|
+
timestamp: existing?.timestamp ?? spawnInfo?.timestamp ?? timestamp2,
|
|
9289
9290
|
parentToolCallId: existing?.parentToolCallId ?? toolCall.id
|
|
9290
9291
|
};
|
|
9291
9292
|
agentRegistry.set(agentId, info);
|
|
9292
9293
|
agentIdBySpawnCall.set(toolCall.id, agentId);
|
|
9293
9294
|
if (info.agentPath) agentIdByPath.set(info.agentPath, agentId);
|
|
9294
|
-
upsertAgentMessage(agentId, current,
|
|
9295
|
+
upsertAgentMessage(agentId, current, timestamp2, { status: "running" });
|
|
9295
9296
|
}
|
|
9296
9297
|
} catch {
|
|
9297
9298
|
}
|
|
@@ -9314,11 +9315,11 @@ function walkCodexRecords(records, options) {
|
|
|
9314
9315
|
message: "",
|
|
9315
9316
|
model: null,
|
|
9316
9317
|
agentType: null,
|
|
9317
|
-
timestamp,
|
|
9318
|
+
timestamp: timestamp2,
|
|
9318
9319
|
parentToolCallId: ""
|
|
9319
9320
|
});
|
|
9320
9321
|
}
|
|
9321
|
-
upsertAgentMessage(agentId, current,
|
|
9322
|
+
upsertAgentMessage(agentId, current, timestamp2, {
|
|
9322
9323
|
status: lifecycle,
|
|
9323
9324
|
text: completedText || failedText || interruptedText || void 0
|
|
9324
9325
|
});
|
|
@@ -9332,7 +9333,7 @@ function walkCodexRecords(records, options) {
|
|
|
9332
9333
|
const name = typeof payload.name === "string" ? payload.name : "tool";
|
|
9333
9334
|
const rawInput = typeof payload.input === "string" ? payload.input : "";
|
|
9334
9335
|
const callId = payload.call_id;
|
|
9335
|
-
const perFileCalls = rawInput ? parseCodexToolPatches(name, rawInput, callId,
|
|
9336
|
+
const perFileCalls = rawInput ? parseCodexToolPatches(name, rawInput, callId, timestamp2, metadata.cwd) : [];
|
|
9336
9337
|
if (name !== "apply_patch") {
|
|
9337
9338
|
const toolCall = {
|
|
9338
9339
|
id: callId,
|
|
@@ -9340,14 +9341,14 @@ function walkCodexRecords(records, options) {
|
|
|
9340
9341
|
input: parseToolInput(rawInput),
|
|
9341
9342
|
result: null,
|
|
9342
9343
|
isError: false,
|
|
9343
|
-
timestamp
|
|
9344
|
+
timestamp: timestamp2
|
|
9344
9345
|
};
|
|
9345
9346
|
pendingToolCalls.set(toolCall.id, toolCall);
|
|
9346
|
-
appendToolCall(current, toolCall,
|
|
9347
|
+
appendToolCall(current, toolCall, timestamp2);
|
|
9347
9348
|
}
|
|
9348
9349
|
for (const tc of perFileCalls) {
|
|
9349
9350
|
pendingToolCalls.set(tc.id, tc);
|
|
9350
|
-
appendToolCall(current, tc,
|
|
9351
|
+
appendToolCall(current, tc, timestamp2);
|
|
9351
9352
|
}
|
|
9352
9353
|
if (perFileCalls.length > 0) {
|
|
9353
9354
|
patchCallIds.set(callId, {
|
|
@@ -9408,7 +9409,7 @@ function parseCodexSession(jsonlText, options) {
|
|
|
9408
9409
|
return session;
|
|
9409
9410
|
}
|
|
9410
9411
|
function appendCodexSession(existing, newJsonlText) {
|
|
9411
|
-
const prefix = existing.rawMessages.map((
|
|
9412
|
+
const prefix = existing.rawMessages.map((record4) => JSON.stringify(record4)).join("\n");
|
|
9412
9413
|
return parseCodexSession(prefix ? `${prefix}
|
|
9413
9414
|
${newJsonlText}` : newJsonlText);
|
|
9414
9415
|
}
|
|
@@ -9603,16 +9604,16 @@ async function readCodexSessionIdentity(filePath) {
|
|
|
9603
9604
|
let parentSessionId = null;
|
|
9604
9605
|
let sawSessionMeta = false;
|
|
9605
9606
|
for (const line of await readHeadLines(filePath, HEAD_BYTES)) {
|
|
9606
|
-
let
|
|
9607
|
+
let record4;
|
|
9607
9608
|
try {
|
|
9608
|
-
|
|
9609
|
+
record4 = JSON.parse(line);
|
|
9609
9610
|
} catch {
|
|
9610
9611
|
continue;
|
|
9611
9612
|
}
|
|
9612
|
-
if (!isRecord2(
|
|
9613
|
-
if (
|
|
9613
|
+
if (!isRecord2(record4) || !isRecord2(record4.payload)) continue;
|
|
9614
|
+
if (record4.type === "session_meta") {
|
|
9614
9615
|
sawSessionMeta = true;
|
|
9615
|
-
const payload =
|
|
9616
|
+
const payload = record4.payload;
|
|
9616
9617
|
if (!sessionId && typeof payload.id === "string") sessionId = payload.id;
|
|
9617
9618
|
if (!cwd && typeof payload.cwd === "string") cwd = payload.cwd;
|
|
9618
9619
|
if (!parentSessionId && typeof payload.forked_from_id === "string") {
|
|
@@ -9622,8 +9623,8 @@ async function readCodexSessionIdentity(filePath) {
|
|
|
9622
9623
|
if (source && isRecord2(source.subagent)) isSubagent = true;
|
|
9623
9624
|
const git = isRecord2(payload.git) ? payload.git : null;
|
|
9624
9625
|
if (!gitBranch && git && typeof git.branch === "string") gitBranch = git.branch;
|
|
9625
|
-
} else if (
|
|
9626
|
-
if (!cwd && typeof
|
|
9626
|
+
} else if (record4.type === "turn_context") {
|
|
9627
|
+
if (!cwd && typeof record4.payload.cwd === "string") cwd = record4.payload.cwd;
|
|
9627
9628
|
}
|
|
9628
9629
|
}
|
|
9629
9630
|
if (!sawSessionMeta || !cwd) return null;
|
|
@@ -9946,8 +9947,8 @@ function extractMetadata(events) {
|
|
|
9946
9947
|
for (const event of events) {
|
|
9947
9948
|
if (!isRootEvent(event)) continue;
|
|
9948
9949
|
const { data } = event;
|
|
9949
|
-
const
|
|
9950
|
-
if (
|
|
9950
|
+
const timestamp2 = eventTimestamp(event);
|
|
9951
|
+
if (timestamp2) metadata.lastTimestamp = timestamp2;
|
|
9951
9952
|
if (event.type === "session.start") {
|
|
9952
9953
|
metadata.sessionId ||= readString(data.sessionId);
|
|
9953
9954
|
metadata.version ||= readString(data.copilotVersion) || (typeof data.version === "number" ? String(data.version) : readString(data.version));
|
|
@@ -9985,7 +9986,7 @@ function extractMetadata(events) {
|
|
|
9985
9986
|
}
|
|
9986
9987
|
if (event.type !== "user.message") continue;
|
|
9987
9988
|
metadata.turnCount++;
|
|
9988
|
-
metadata.timestamp ||=
|
|
9989
|
+
metadata.timestamp ||= timestamp2;
|
|
9989
9990
|
const content = readString(data.content).trim();
|
|
9990
9991
|
if (!content) continue;
|
|
9991
9992
|
metadata.firstUserMessage ||= content;
|
|
@@ -10209,7 +10210,7 @@ function extractToolResult(data) {
|
|
|
10209
10210
|
if (result.structuredContent !== void 0) return safeStringify2(result.structuredContent);
|
|
10210
10211
|
return safeStringify2(result);
|
|
10211
10212
|
}
|
|
10212
|
-
function appendThinking2(turn, text,
|
|
10213
|
+
function appendThinking2(turn, text, timestamp2, signature) {
|
|
10213
10214
|
if (!text || turn.thinking.some((block2) => block2.thinking === text)) return;
|
|
10214
10215
|
const block = { type: "thinking", thinking: text, signature };
|
|
10215
10216
|
turn.thinking.push(block);
|
|
@@ -10218,21 +10219,21 @@ function appendThinking2(turn, text, timestamp, signature) {
|
|
|
10218
10219
|
last.blocks.push(block);
|
|
10219
10220
|
return;
|
|
10220
10221
|
}
|
|
10221
|
-
turn.contentBlocks.push({ kind: "thinking", blocks: [block], timestamp });
|
|
10222
|
+
turn.contentBlocks.push({ kind: "thinking", blocks: [block], timestamp: timestamp2 });
|
|
10222
10223
|
}
|
|
10223
|
-
function appendToolCall2(turn, call,
|
|
10224
|
+
function appendToolCall2(turn, call, timestamp2) {
|
|
10224
10225
|
turn.toolCalls.push(call);
|
|
10225
10226
|
const last = turn.contentBlocks[turn.contentBlocks.length - 1];
|
|
10226
10227
|
if (last?.kind === "tool_calls") {
|
|
10227
10228
|
last.toolCalls.push(call);
|
|
10228
10229
|
return;
|
|
10229
10230
|
}
|
|
10230
|
-
turn.contentBlocks.push({ kind: "tool_calls", toolCalls: [call], timestamp });
|
|
10231
|
+
turn.contentBlocks.push({ kind: "tool_calls", toolCalls: [call], timestamp: timestamp2 });
|
|
10231
10232
|
}
|
|
10232
|
-
function newToolCall(id, name, input,
|
|
10233
|
-
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 };
|
|
10234
10235
|
}
|
|
10235
|
-
function toolCallsFromRequests(value,
|
|
10236
|
+
function toolCallsFromRequests(value, timestamp2, isPending) {
|
|
10236
10237
|
if (!Array.isArray(value)) return [];
|
|
10237
10238
|
const calls = [];
|
|
10238
10239
|
for (const request of value) {
|
|
@@ -10241,14 +10242,14 @@ function toolCallsFromRequests(value, timestamp, isPending) {
|
|
|
10241
10242
|
const rawName = readString(request.name);
|
|
10242
10243
|
if (!id || !rawName || isPending(id)) continue;
|
|
10243
10244
|
const name = normalizeToolName(rawName);
|
|
10244
|
-
calls.push(newToolCall(id, name, normalizeToolInput(name, request.arguments),
|
|
10245
|
+
calls.push(newToolCall(id, name, normalizeToolInput(name, request.arguments), timestamp2));
|
|
10245
10246
|
}
|
|
10246
10247
|
return calls;
|
|
10247
10248
|
}
|
|
10248
|
-
function updateToolCallStart(call, name, input,
|
|
10249
|
+
function updateToolCallStart(call, name, input, timestamp2) {
|
|
10249
10250
|
call.name = name;
|
|
10250
10251
|
call.input = normalizeToolInput(name, input);
|
|
10251
|
-
call.timestamp =
|
|
10252
|
+
call.timestamp = timestamp2 || call.timestamp;
|
|
10252
10253
|
}
|
|
10253
10254
|
function updateToolCallResult(call, data, binaryAssets) {
|
|
10254
10255
|
call.result = extractToolResult(data);
|
|
@@ -10256,7 +10257,7 @@ function updateToolCallResult(call, data, binaryAssets) {
|
|
|
10256
10257
|
if (resultImages.length > 0) call.resultImages = resultImages;
|
|
10257
10258
|
call.isError = data.success === false || data.error !== void 0 && data.error !== null;
|
|
10258
10259
|
}
|
|
10259
|
-
function createTurn2(id,
|
|
10260
|
+
function createTurn2(id, timestamp2, userMessage, model, effort, isFragment) {
|
|
10260
10261
|
return {
|
|
10261
10262
|
id,
|
|
10262
10263
|
userMessage,
|
|
@@ -10265,7 +10266,7 @@ function createTurn2(id, timestamp, userMessage, model, effort, isFragment) {
|
|
|
10265
10266
|
assistantText: [],
|
|
10266
10267
|
toolCalls: [],
|
|
10267
10268
|
subAgentActivity: [],
|
|
10268
|
-
timestamp,
|
|
10269
|
+
timestamp: timestamp2,
|
|
10269
10270
|
durationMs: null,
|
|
10270
10271
|
tokenUsage: null,
|
|
10271
10272
|
model,
|
|
@@ -10292,8 +10293,8 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10292
10293
|
let sawAssistantUsage = false;
|
|
10293
10294
|
let sawAssistantDuration = false;
|
|
10294
10295
|
let shutdownUsage = null;
|
|
10295
|
-
function noteTimestamp(turn,
|
|
10296
|
-
if (
|
|
10296
|
+
function noteTimestamp(turn, timestamp2) {
|
|
10297
|
+
if (timestamp2) endTimestamps.set(turn, timestamp2);
|
|
10297
10298
|
}
|
|
10298
10299
|
function ensureTurn(event) {
|
|
10299
10300
|
if (!current) {
|
|
@@ -10354,7 +10355,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10354
10355
|
const message = ensureAgent(event);
|
|
10355
10356
|
if (!message) return true;
|
|
10356
10357
|
const { data } = event;
|
|
10357
|
-
const
|
|
10358
|
+
const timestamp2 = eventTimestamp(event);
|
|
10358
10359
|
if (event.type === "subagent.started" || event.type === "subagent.configured") {
|
|
10359
10360
|
message.parentToolUseId ||= readString(data.toolCallId) || void 0;
|
|
10360
10361
|
message.agentName = readString(data.agentDisplayName, data.agentName) || message.agentName;
|
|
@@ -10393,7 +10394,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10393
10394
|
if (text && !message.text.includes(text)) message.text.push(text);
|
|
10394
10395
|
for (const call of toolCallsFromRequests(
|
|
10395
10396
|
data.toolRequests,
|
|
10396
|
-
|
|
10397
|
+
timestamp2,
|
|
10397
10398
|
(id) => pendingAgentToolCalls.has(id)
|
|
10398
10399
|
)) {
|
|
10399
10400
|
message.toolCalls.push(call);
|
|
@@ -10413,13 +10414,13 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10413
10414
|
const name = normalizeToolName(rawName);
|
|
10414
10415
|
const existing = pendingAgentToolCalls.get(callId);
|
|
10415
10416
|
if (existing) {
|
|
10416
|
-
updateToolCallStart(existing.call, name, data.arguments,
|
|
10417
|
+
updateToolCallStart(existing.call, name, data.arguments, timestamp2);
|
|
10417
10418
|
} else {
|
|
10418
10419
|
const call = newToolCall(
|
|
10419
10420
|
callId,
|
|
10420
10421
|
name,
|
|
10421
10422
|
normalizeToolInput(name, data.arguments),
|
|
10422
|
-
|
|
10423
|
+
timestamp2
|
|
10423
10424
|
);
|
|
10424
10425
|
message.toolCalls.push(call);
|
|
10425
10426
|
pendingAgentToolCalls.set(callId, { call, message });
|
|
@@ -10432,7 +10433,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10432
10433
|
if (!pending) {
|
|
10433
10434
|
const rawName = readString(data.toolName) || "Tool";
|
|
10434
10435
|
const name = normalizeToolName(rawName);
|
|
10435
|
-
const call = newToolCall(callId, name, {},
|
|
10436
|
+
const call = newToolCall(callId, name, {}, timestamp2);
|
|
10436
10437
|
message.toolCalls.push(call);
|
|
10437
10438
|
pending = { call, message };
|
|
10438
10439
|
}
|
|
@@ -10445,7 +10446,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10445
10446
|
for (const event of events) {
|
|
10446
10447
|
if (applyAgentEvent(event)) continue;
|
|
10447
10448
|
const { data } = event;
|
|
10448
|
-
const
|
|
10449
|
+
const timestamp2 = eventTimestamp(event);
|
|
10449
10450
|
if (event.type === "session.start" || event.type === "session.resume") {
|
|
10450
10451
|
currentModel = readString(data.selectedModel) || currentModel;
|
|
10451
10452
|
currentEffort = readString(data.reasoningEffort) || currentEffort;
|
|
@@ -10478,13 +10479,13 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10478
10479
|
finalizeCurrent();
|
|
10479
10480
|
current = createTurn2(
|
|
10480
10481
|
turnEventId(event),
|
|
10481
|
-
|
|
10482
|
+
timestamp2,
|
|
10482
10483
|
buildUserContent(data, binaryAssets),
|
|
10483
10484
|
currentModel,
|
|
10484
10485
|
currentEffort,
|
|
10485
10486
|
false
|
|
10486
10487
|
);
|
|
10487
|
-
noteTimestamp(current,
|
|
10488
|
+
noteTimestamp(current, timestamp2);
|
|
10488
10489
|
continue;
|
|
10489
10490
|
}
|
|
10490
10491
|
if (event.type === "assistant.turn_start") {
|
|
@@ -10492,7 +10493,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10492
10493
|
const turn = ensureTurn(event);
|
|
10493
10494
|
turn.model = currentModel;
|
|
10494
10495
|
if (currentEffort) turn.effort = currentEffort;
|
|
10495
|
-
noteTimestamp(turn,
|
|
10496
|
+
noteTimestamp(turn, timestamp2);
|
|
10496
10497
|
continue;
|
|
10497
10498
|
}
|
|
10498
10499
|
if (event.type === "assistant.reasoning") {
|
|
@@ -10500,10 +10501,10 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10500
10501
|
appendThinking2(
|
|
10501
10502
|
turn,
|
|
10502
10503
|
readString(data.content),
|
|
10503
|
-
|
|
10504
|
+
timestamp2,
|
|
10504
10505
|
readString(data.reasoningId) || eventId(event, "copilot-thinking")
|
|
10505
10506
|
);
|
|
10506
|
-
noteTimestamp(turn,
|
|
10507
|
+
noteTimestamp(turn, timestamp2);
|
|
10507
10508
|
continue;
|
|
10508
10509
|
}
|
|
10509
10510
|
if (event.type === "assistant.message") {
|
|
@@ -10514,19 +10515,19 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10514
10515
|
appendThinking2(
|
|
10515
10516
|
turn,
|
|
10516
10517
|
readString(data.reasoningText),
|
|
10517
|
-
|
|
10518
|
+
timestamp2,
|
|
10518
10519
|
eventId(event, "copilot-thinking")
|
|
10519
10520
|
);
|
|
10520
|
-
appendAssistantText(turn, textFromValue(data.content),
|
|
10521
|
+
appendAssistantText(turn, textFromValue(data.content), timestamp2);
|
|
10521
10522
|
for (const call of toolCallsFromRequests(
|
|
10522
10523
|
data.toolRequests,
|
|
10523
|
-
|
|
10524
|
+
timestamp2,
|
|
10524
10525
|
(id) => pendingToolCalls.has(id)
|
|
10525
10526
|
)) {
|
|
10526
|
-
appendToolCall2(turn, call,
|
|
10527
|
+
appendToolCall2(turn, call, timestamp2);
|
|
10527
10528
|
pendingToolCalls.set(call.id, { call, turn });
|
|
10528
10529
|
}
|
|
10529
|
-
noteTimestamp(turn,
|
|
10530
|
+
noteTimestamp(turn, timestamp2);
|
|
10530
10531
|
continue;
|
|
10531
10532
|
}
|
|
10532
10533
|
if (event.type === "assistant.usage") {
|
|
@@ -10541,7 +10542,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10541
10542
|
if (currentEffort) turn.effort = currentEffort;
|
|
10542
10543
|
if (usage) turn.tokenUsage = mergeTokenUsage2(turn.tokenUsage, usage);
|
|
10543
10544
|
if (duration) apiDurationMs.set(turn, (apiDurationMs.get(turn) ?? 0) + duration);
|
|
10544
|
-
noteTimestamp(turn,
|
|
10545
|
+
noteTimestamp(turn, timestamp2);
|
|
10545
10546
|
continue;
|
|
10546
10547
|
}
|
|
10547
10548
|
if (event.type === "tool.execution_start") {
|
|
@@ -10553,18 +10554,18 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10553
10554
|
const name = normalizeToolName(rawName);
|
|
10554
10555
|
const existing = pendingToolCalls.get(callId);
|
|
10555
10556
|
if (existing) {
|
|
10556
|
-
updateToolCallStart(existing.call, name, data.arguments,
|
|
10557
|
+
updateToolCallStart(existing.call, name, data.arguments, timestamp2);
|
|
10557
10558
|
} else {
|
|
10558
10559
|
const call = newToolCall(
|
|
10559
10560
|
callId,
|
|
10560
10561
|
name,
|
|
10561
10562
|
normalizeToolInput(name, data.arguments),
|
|
10562
|
-
|
|
10563
|
+
timestamp2
|
|
10563
10564
|
);
|
|
10564
|
-
appendToolCall2(turn, call,
|
|
10565
|
+
appendToolCall2(turn, call, timestamp2);
|
|
10565
10566
|
pendingToolCalls.set(callId, { call, turn });
|
|
10566
10567
|
}
|
|
10567
|
-
noteTimestamp(turn,
|
|
10568
|
+
noteTimestamp(turn, timestamp2);
|
|
10568
10569
|
continue;
|
|
10569
10570
|
}
|
|
10570
10571
|
if (event.type === "tool.execution_complete") {
|
|
@@ -10575,13 +10576,13 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10575
10576
|
const turn = ensureTurn(event);
|
|
10576
10577
|
const rawName = readString(data.toolName) || "Tool";
|
|
10577
10578
|
const name = normalizeToolName(rawName);
|
|
10578
|
-
const call = newToolCall(callId, name, {},
|
|
10579
|
-
appendToolCall2(turn, call,
|
|
10579
|
+
const call = newToolCall(callId, name, {}, timestamp2);
|
|
10580
|
+
appendToolCall2(turn, call, timestamp2);
|
|
10580
10581
|
pending = { call, turn };
|
|
10581
10582
|
}
|
|
10582
10583
|
updateToolCallResult(pending.call, data, binaryAssets);
|
|
10583
10584
|
pendingToolCalls.delete(callId);
|
|
10584
|
-
noteTimestamp(pending.turn,
|
|
10585
|
+
noteTimestamp(pending.turn, timestamp2);
|
|
10585
10586
|
continue;
|
|
10586
10587
|
}
|
|
10587
10588
|
if (event.type === "session.error") {
|
|
@@ -10596,13 +10597,13 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10596
10597
|
input,
|
|
10597
10598
|
result: readString(data.message) || "Copilot session error",
|
|
10598
10599
|
isError: true,
|
|
10599
|
-
timestamp
|
|
10600
|
-
},
|
|
10601
|
-
noteTimestamp(turn,
|
|
10600
|
+
timestamp: timestamp2
|
|
10601
|
+
}, timestamp2);
|
|
10602
|
+
noteTimestamp(turn, timestamp2);
|
|
10602
10603
|
continue;
|
|
10603
10604
|
}
|
|
10604
10605
|
if (event.type === "assistant.turn_end" || event.type === "assistant.idle" || event.type === "session.idle") {
|
|
10605
|
-
if (current) noteTimestamp(current,
|
|
10606
|
+
if (current) noteTimestamp(current, timestamp2);
|
|
10606
10607
|
}
|
|
10607
10608
|
}
|
|
10608
10609
|
finalizeCurrent();
|
|
@@ -10645,7 +10646,7 @@ function parseCopilotSession(jsonlText, options) {
|
|
|
10645
10646
|
};
|
|
10646
10647
|
}
|
|
10647
10648
|
function appendCopilotSession(existing, newJsonlText) {
|
|
10648
|
-
const prefix = existing.rawMessages.map((
|
|
10649
|
+
const prefix = existing.rawMessages.map((record4) => JSON.stringify(record4)).join("\n");
|
|
10649
10650
|
return parseCopilotSession(prefix ? `${prefix}
|
|
10650
10651
|
${newJsonlText}` : newJsonlText);
|
|
10651
10652
|
}
|
|
@@ -10753,11 +10754,11 @@ function brandCopilotBranch() {
|
|
|
10753
10754
|
function copilotTurnBoundaries(records) {
|
|
10754
10755
|
const boundaries = [];
|
|
10755
10756
|
for (let index = 0; index < records.length; index++) {
|
|
10756
|
-
const
|
|
10757
|
-
if (
|
|
10758
|
-
const data =
|
|
10757
|
+
const record4 = records[index];
|
|
10758
|
+
if (record4.type !== "user.message" || typeof record4.agentId === "string") continue;
|
|
10759
|
+
const data = record4.data;
|
|
10759
10760
|
if (!data || typeof data !== "object" || Array.isArray(data)) continue;
|
|
10760
|
-
if (typeof
|
|
10761
|
+
if (typeof record4.id !== "string" || !record4.id) continue;
|
|
10761
10762
|
boundaries.push(index);
|
|
10762
10763
|
}
|
|
10763
10764
|
return boundaries;
|
|
@@ -10814,14 +10815,14 @@ async function readCopilotSessionIdentity(filePath) {
|
|
|
10814
10815
|
let cwd = "";
|
|
10815
10816
|
let gitBranch = "";
|
|
10816
10817
|
for (const line of await readHeadLines(filePath, HEAD_BYTES)) {
|
|
10817
|
-
let
|
|
10818
|
+
let record4;
|
|
10818
10819
|
try {
|
|
10819
|
-
|
|
10820
|
+
record4 = JSON.parse(line);
|
|
10820
10821
|
} catch {
|
|
10821
10822
|
continue;
|
|
10822
10823
|
}
|
|
10823
|
-
if (!isRecord3(
|
|
10824
|
-
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;
|
|
10825
10826
|
if (!data) continue;
|
|
10826
10827
|
if (typeof data.sessionId === "string" && data.sessionId) sessionId = data.sessionId;
|
|
10827
10828
|
const context = isRecord3(data.context) ? data.context : null;
|
|
@@ -11141,7 +11142,7 @@ function groupPlanModeBlocks(blocks) {
|
|
|
11141
11142
|
if (enterIdx !== -1) {
|
|
11142
11143
|
const enterCall = block.toolCalls[enterIdx];
|
|
11143
11144
|
const plan = String(enterCall.input.plan ?? "");
|
|
11144
|
-
const
|
|
11145
|
+
const timestamp2 = block.timestamp;
|
|
11145
11146
|
const before = block.toolCalls.slice(0, enterIdx);
|
|
11146
11147
|
if (before.length > 0) {
|
|
11147
11148
|
result.push({ kind: "tool_calls", toolCalls: before, timestamp: block.timestamp });
|
|
@@ -11157,7 +11158,7 @@ function groupPlanModeBlocks(blocks) {
|
|
|
11157
11158
|
if (exitCall.result !== null) {
|
|
11158
11159
|
status = exitCall.isError ? "rejected" : "approved";
|
|
11159
11160
|
}
|
|
11160
|
-
result.push({ kind: "plan_mode", plan, planFilePath, status, toolCalls: embedded, timestamp });
|
|
11161
|
+
result.push({ kind: "plan_mode", plan, planFilePath, status, toolCalls: embedded, timestamp: timestamp2 });
|
|
11161
11162
|
const after = afterEnterInSameBlock.slice(exitInSameBlock + 1);
|
|
11162
11163
|
if (after.length > 0) {
|
|
11163
11164
|
result.push({ kind: "tool_calls", toolCalls: after, timestamp: block.timestamp });
|
|
@@ -11183,7 +11184,7 @@ function groupPlanModeBlocks(blocks) {
|
|
|
11183
11184
|
status = exitCall.isError ? "rejected" : "approved";
|
|
11184
11185
|
}
|
|
11185
11186
|
const tail = next.toolCalls.slice(exitIdx + 1);
|
|
11186
|
-
result.push({ kind: "plan_mode", plan, planFilePath, status, toolCalls: embedded, timestamp });
|
|
11187
|
+
result.push({ kind: "plan_mode", plan, planFilePath, status, toolCalls: embedded, timestamp: timestamp2 });
|
|
11187
11188
|
result.push(...passthroughBlocks);
|
|
11188
11189
|
if (tail.length > 0) {
|
|
11189
11190
|
result.push({ kind: "tool_calls", toolCalls: tail, timestamp: next.timestamp });
|
|
@@ -11202,7 +11203,7 @@ function groupPlanModeBlocks(blocks) {
|
|
|
11202
11203
|
}
|
|
11203
11204
|
}
|
|
11204
11205
|
if (!exitCall) {
|
|
11205
|
-
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 });
|
|
11206
11207
|
result.push(...passthroughBlocks);
|
|
11207
11208
|
i = j;
|
|
11208
11209
|
}
|
|
@@ -12184,9 +12185,9 @@ function nonEmpty(value) {
|
|
|
12184
12185
|
function stripTaggedBlocks(text) {
|
|
12185
12186
|
return text.replace(/<[^>]+>[\s\S]*?<\/[^>]+>/g, "").trim();
|
|
12186
12187
|
}
|
|
12187
|
-
function effortFromRecord(
|
|
12188
|
+
function effortFromRecord(record4) {
|
|
12188
12189
|
for (const kind of AGENT_KINDS) {
|
|
12189
|
-
const effort = READERS[kind].effort(
|
|
12190
|
+
const effort = READERS[kind].effort(record4);
|
|
12190
12191
|
if (effort) return effort;
|
|
12191
12192
|
}
|
|
12192
12193
|
return null;
|
|
@@ -12196,15 +12197,15 @@ function userMessageTextFromLine(line) {
|
|
|
12196
12197
|
(kind) => READERS[kind].userMessageMarkers.some((marker) => line.includes(marker))
|
|
12197
12198
|
);
|
|
12198
12199
|
if (candidates.length === 0) return null;
|
|
12199
|
-
let
|
|
12200
|
+
let record4;
|
|
12200
12201
|
try {
|
|
12201
|
-
|
|
12202
|
+
record4 = JSON.parse(line);
|
|
12202
12203
|
} catch {
|
|
12203
12204
|
return null;
|
|
12204
12205
|
}
|
|
12205
|
-
if (!isRecord4(
|
|
12206
|
+
if (!isRecord4(record4)) return null;
|
|
12206
12207
|
for (const kind of candidates) {
|
|
12207
|
-
const text = READERS[kind].userMessageText(
|
|
12208
|
+
const text = READERS[kind].userMessageText(record4);
|
|
12208
12209
|
if (text !== null) return text;
|
|
12209
12210
|
}
|
|
12210
12211
|
return null;
|
|
@@ -12216,11 +12217,11 @@ var init_recordReaders = __esm({
|
|
|
12216
12217
|
claudeReader = {
|
|
12217
12218
|
kind: "claude",
|
|
12218
12219
|
// Every assistant record is tagged with the effort that turn ran at.
|
|
12219
|
-
effort: (
|
|
12220
|
+
effort: (record4) => record4.type === "assistant" ? nonEmpty(record4.effort) : null,
|
|
12220
12221
|
userMessageMarkers: ['"user"'],
|
|
12221
|
-
userMessageText(
|
|
12222
|
-
if (
|
|
12223
|
-
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;
|
|
12224
12225
|
if (typeof content === "string") return stripTaggedBlocks(content);
|
|
12225
12226
|
if (!Array.isArray(content)) return "";
|
|
12226
12227
|
let text = "";
|
|
@@ -12235,32 +12236,32 @@ var init_recordReaders = __esm({
|
|
|
12235
12236
|
codexReader = {
|
|
12236
12237
|
kind: "codex",
|
|
12237
12238
|
// Effort is recorded per turn; newer CLI versions moved it under `thread_settings`.
|
|
12238
|
-
effort(
|
|
12239
|
-
if (
|
|
12240
|
-
const { payload } =
|
|
12239
|
+
effort(record4) {
|
|
12240
|
+
if (record4.type !== "turn_context" || !isRecord4(record4.payload)) return null;
|
|
12241
|
+
const { payload } = record4;
|
|
12241
12242
|
const direct = nonEmpty(payload.effort);
|
|
12242
12243
|
if (direct) return direct;
|
|
12243
12244
|
const settings = isRecord4(payload.thread_settings) ? payload.thread_settings : null;
|
|
12244
12245
|
return nonEmpty(settings?.reasoning_effort);
|
|
12245
12246
|
},
|
|
12246
12247
|
userMessageMarkers: ['"event_msg"'],
|
|
12247
|
-
userMessageText(
|
|
12248
|
-
if (
|
|
12249
|
-
const { payload } =
|
|
12248
|
+
userMessageText(record4) {
|
|
12249
|
+
if (record4.type !== "event_msg" || !isRecord4(record4.payload)) return null;
|
|
12250
|
+
const { payload } = record4;
|
|
12250
12251
|
return payload.type === "user_message" && typeof payload.message === "string" ? payload.message.trim() : null;
|
|
12251
12252
|
}
|
|
12252
12253
|
};
|
|
12253
12254
|
copilotReader = {
|
|
12254
12255
|
kind: "copilot",
|
|
12255
|
-
effort(
|
|
12256
|
-
if (
|
|
12257
|
-
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);
|
|
12258
12259
|
},
|
|
12259
12260
|
userMessageMarkers: ['"user.message"'],
|
|
12260
|
-
userMessageText(
|
|
12261
|
-
if (
|
|
12262
|
-
if (typeof
|
|
12263
|
-
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;
|
|
12264
12265
|
return typeof data?.content === "string" ? data.content.trim() : "";
|
|
12265
12266
|
}
|
|
12266
12267
|
};
|
|
@@ -12273,16 +12274,16 @@ var init_recordReaders = __esm({
|
|
|
12273
12274
|
});
|
|
12274
12275
|
|
|
12275
12276
|
// ../../server/agents/tailRecords.ts
|
|
12276
|
-
function isSubagentLifecycle(
|
|
12277
|
-
return
|
|
12277
|
+
function isSubagentLifecycle(record4) {
|
|
12278
|
+
return record4.type.startsWith("subagent.") && typeof record4.agentId === "string" && record4.agentId.length > 0;
|
|
12278
12279
|
}
|
|
12279
|
-
function isSubagentNoise(
|
|
12280
|
-
return typeof
|
|
12280
|
+
function isSubagentNoise(record4) {
|
|
12281
|
+
return typeof record4.agentId === "string" && record4.agentId.length > 0;
|
|
12281
12282
|
}
|
|
12282
|
-
function classifyTailRecord(
|
|
12283
|
+
function classifyTailRecord(record4) {
|
|
12283
12284
|
for (const kind of AGENT_KINDS) {
|
|
12284
12285
|
const format = TAIL_FORMATS[kind];
|
|
12285
|
-
const verdict = format.classify(
|
|
12286
|
+
const verdict = format.classify(record4);
|
|
12286
12287
|
if (verdict.kind !== "ignore") return { format, verdict };
|
|
12287
12288
|
}
|
|
12288
12289
|
return null;
|
|
@@ -12299,31 +12300,31 @@ var init_tailRecords = __esm({
|
|
|
12299
12300
|
// Background agent/workflow launches, task notifications and TaskStop calls
|
|
12300
12301
|
// can all still change a verdict that a turn-ending line looked to settle.
|
|
12301
12302
|
markers: ["async_launched", "task-notification", '"TaskStop"'],
|
|
12302
|
-
classify(
|
|
12303
|
-
if (
|
|
12304
|
-
const reason =
|
|
12303
|
+
classify(record4) {
|
|
12304
|
+
if (record4.type === "system" && record4.subtype === "terminal_reason") {
|
|
12305
|
+
const reason = record4.reason;
|
|
12305
12306
|
return reason ? { kind: "final", status: { status: "completed", terminalReason: reason } } : IGNORE;
|
|
12306
12307
|
}
|
|
12307
|
-
if (
|
|
12308
|
-
const data =
|
|
12308
|
+
if (record4.type === "progress") {
|
|
12309
|
+
const data = record4.data;
|
|
12309
12310
|
if (data?.type !== "hook_progress") return IGNORE;
|
|
12310
12311
|
const decision = data.decision ?? data.hookSpecificOutput?.permissionDecision;
|
|
12311
12312
|
return decision === "defer" ? ANSWER : IGNORE;
|
|
12312
12313
|
}
|
|
12313
|
-
if (
|
|
12314
|
-
if (
|
|
12315
|
-
const stopReason =
|
|
12316
|
-
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") {
|
|
12317
12318
|
return { kind: "turn-end", awaitUserActivity: true };
|
|
12318
12319
|
}
|
|
12319
|
-
const canDerive =
|
|
12320
|
+
const canDerive = record4.type === "assistant" || record4.type === "user" && !record4.isMeta;
|
|
12320
12321
|
return canDerive ? ANSWER : KEEP;
|
|
12321
12322
|
}
|
|
12322
12323
|
return IGNORE;
|
|
12323
12324
|
},
|
|
12324
|
-
classifyAfterTurnEnd(
|
|
12325
|
-
if (
|
|
12326
|
-
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;
|
|
12327
12328
|
return { kind: "keep", sawUserActivity: isRealUserTurn };
|
|
12328
12329
|
}
|
|
12329
12330
|
};
|
|
@@ -12342,9 +12343,9 @@ var init_tailRecords = __esm({
|
|
|
12342
12343
|
"agent_message",
|
|
12343
12344
|
"function_call_output"
|
|
12344
12345
|
],
|
|
12345
|
-
classify(
|
|
12346
|
-
if (
|
|
12347
|
-
const payload =
|
|
12346
|
+
classify(record4) {
|
|
12347
|
+
if (record4.type === "event_msg") {
|
|
12348
|
+
const payload = record4.payload;
|
|
12348
12349
|
switch (payload?.type) {
|
|
12349
12350
|
case "task_complete":
|
|
12350
12351
|
return { kind: "turn-end" };
|
|
@@ -12356,32 +12357,32 @@ var init_tailRecords = __esm({
|
|
|
12356
12357
|
return IGNORE;
|
|
12357
12358
|
}
|
|
12358
12359
|
}
|
|
12359
|
-
if (
|
|
12360
|
-
const payload =
|
|
12360
|
+
if (record4.type === "response_item") {
|
|
12361
|
+
const payload = record4.payload;
|
|
12361
12362
|
const decides = payload?.type === "function_call" || payload?.type === "message" && (payload.role === "assistant" || payload.role === "user");
|
|
12362
12363
|
return decides ? ANSWER : IGNORE;
|
|
12363
12364
|
}
|
|
12364
12365
|
return IGNORE;
|
|
12365
12366
|
},
|
|
12366
|
-
classifyAfterTurnEnd(
|
|
12367
|
-
return
|
|
12367
|
+
classifyAfterTurnEnd(record4) {
|
|
12368
|
+
return record4.type === "event_msg" || record4.type === "response_item" ? KEEP : IGNORE;
|
|
12368
12369
|
}
|
|
12369
12370
|
};
|
|
12370
12371
|
copilotTail = {
|
|
12371
12372
|
kind: "copilot",
|
|
12372
12373
|
markers: ['"abort"', '"assistant.message"', '"user.message"', '"subagent.'],
|
|
12373
|
-
classify(
|
|
12374
|
-
if (isSubagentLifecycle(
|
|
12375
|
-
const decidable =
|
|
12376
|
-
if (!decidable || isSubagentNoise(
|
|
12377
|
-
if (
|
|
12378
|
-
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;
|
|
12379
12380
|
return { kind: "answer-if-active" };
|
|
12380
12381
|
},
|
|
12381
|
-
classifyAfterTurnEnd(
|
|
12382
|
-
if (isSubagentLifecycle(
|
|
12383
|
-
if (isSubagentNoise(
|
|
12384
|
-
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";
|
|
12385
12386
|
return decides ? ANSWER : IGNORE;
|
|
12386
12387
|
}
|
|
12387
12388
|
};
|
|
@@ -12436,14 +12437,14 @@ async function readTranscriptEffort(filePath) {
|
|
|
12436
12437
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
12437
12438
|
const line = lines[i];
|
|
12438
12439
|
if (!line || !line.includes("effort") && !line.includes("Effort")) continue;
|
|
12439
|
-
let
|
|
12440
|
+
let record4;
|
|
12440
12441
|
try {
|
|
12441
|
-
|
|
12442
|
+
record4 = JSON.parse(line);
|
|
12442
12443
|
} catch {
|
|
12443
12444
|
continue;
|
|
12444
12445
|
}
|
|
12445
|
-
if (typeof
|
|
12446
|
-
const effort = effortFromRecord(
|
|
12446
|
+
if (typeof record4 !== "object" || record4 === null) continue;
|
|
12447
|
+
const effort = effortFromRecord(record4);
|
|
12447
12448
|
if (effort) return effort;
|
|
12448
12449
|
}
|
|
12449
12450
|
}
|
|
@@ -12479,14 +12480,14 @@ async function getSessionStatus(filePath) {
|
|
|
12479
12480
|
const line = lines[i];
|
|
12480
12481
|
if (!line) continue;
|
|
12481
12482
|
if (turnEnded && !isTailCandidate(line, turnEnded)) continue;
|
|
12482
|
-
let
|
|
12483
|
+
let record4;
|
|
12483
12484
|
try {
|
|
12484
|
-
|
|
12485
|
+
record4 = JSON.parse(line);
|
|
12485
12486
|
} catch {
|
|
12486
12487
|
continue;
|
|
12487
12488
|
}
|
|
12488
|
-
if (typeof
|
|
12489
|
-
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);
|
|
12490
12491
|
if (!match) continue;
|
|
12491
12492
|
const { verdict } = match;
|
|
12492
12493
|
switch (verdict.kind) {
|
|
@@ -12495,20 +12496,20 @@ async function getSessionStatus(filePath) {
|
|
|
12495
12496
|
case "final":
|
|
12496
12497
|
return verdict.status;
|
|
12497
12498
|
case "keep":
|
|
12498
|
-
meaningful.unshift(
|
|
12499
|
+
meaningful.unshift(record4);
|
|
12499
12500
|
if (verdict.sawUserActivity) needUserActivity = false;
|
|
12500
12501
|
continue;
|
|
12501
12502
|
case "answer":
|
|
12502
|
-
meaningful.unshift(
|
|
12503
|
+
meaningful.unshift(record4);
|
|
12503
12504
|
return deriveSessionStatus(meaningful);
|
|
12504
12505
|
case "answer-if-active": {
|
|
12505
|
-
meaningful.unshift(
|
|
12506
|
+
meaningful.unshift(record4);
|
|
12506
12507
|
const status = deriveSessionStatus(meaningful);
|
|
12507
12508
|
if (status.status !== "idle") return status;
|
|
12508
12509
|
continue;
|
|
12509
12510
|
}
|
|
12510
12511
|
case "turn-end":
|
|
12511
|
-
meaningful.unshift(
|
|
12512
|
+
meaningful.unshift(record4);
|
|
12512
12513
|
turnEnded = match.format;
|
|
12513
12514
|
needUserActivity = verdict.awaitUserActivity === true;
|
|
12514
12515
|
continue;
|
|
@@ -12653,12 +12654,12 @@ var init_modelCatalog = __esm({
|
|
|
12653
12654
|
|
|
12654
12655
|
// ../../server/agents/timeout.ts
|
|
12655
12656
|
function withTimeout(promise, ms, label) {
|
|
12656
|
-
return new Promise((
|
|
12657
|
+
return new Promise((resolve22, reject) => {
|
|
12657
12658
|
const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
12658
12659
|
promise.then(
|
|
12659
12660
|
(value) => {
|
|
12660
12661
|
clearTimeout(timer);
|
|
12661
|
-
|
|
12662
|
+
resolve22(value);
|
|
12662
12663
|
},
|
|
12663
12664
|
(error) => {
|
|
12664
12665
|
clearTimeout(timer);
|
|
@@ -12861,7 +12862,7 @@ async function awaitTranscript(filePath, isSettled) {
|
|
|
12861
12862
|
return true;
|
|
12862
12863
|
} catch {
|
|
12863
12864
|
}
|
|
12864
|
-
await new Promise((
|
|
12865
|
+
await new Promise((resolve22) => setTimeout(resolve22, TRANSCRIPT_POLL_INTERVAL_MS));
|
|
12865
12866
|
}
|
|
12866
12867
|
return false;
|
|
12867
12868
|
}
|
|
@@ -12908,7 +12909,7 @@ function startOneShot(req) {
|
|
|
12908
12909
|
child.on("close", () => {
|
|
12909
12910
|
activeProcesses.delete(sessionId);
|
|
12910
12911
|
});
|
|
12911
|
-
return new Promise((
|
|
12912
|
+
return new Promise((resolve22, reject) => {
|
|
12912
12913
|
let settled = false;
|
|
12913
12914
|
const fail = (message) => {
|
|
12914
12915
|
if (settled) return;
|
|
@@ -12930,7 +12931,7 @@ function startOneShot(req) {
|
|
|
12930
12931
|
await stat7(filePath);
|
|
12931
12932
|
settled = true;
|
|
12932
12933
|
clearTimeout(timer);
|
|
12933
|
-
|
|
12934
|
+
resolve22({ sessionId, dirName: req.dirName, fileName, filePath });
|
|
12934
12935
|
} catch {
|
|
12935
12936
|
fail(
|
|
12936
12937
|
stderr.trim() || `${descriptor4.binName} exited with code ${code} before creating session`
|
|
@@ -12960,7 +12961,7 @@ function startInteractive(req) {
|
|
|
12960
12961
|
worktreeName: req.worktreeName,
|
|
12961
12962
|
mcpConfig: req.mcpConfig
|
|
12962
12963
|
});
|
|
12963
|
-
return new Promise((
|
|
12964
|
+
return new Promise((resolve22, reject) => {
|
|
12964
12965
|
let settled = false;
|
|
12965
12966
|
const succeed = async () => {
|
|
12966
12967
|
if (settled) return;
|
|
@@ -12970,7 +12971,7 @@ function startInteractive(req) {
|
|
|
12970
12971
|
initialContent = await readFile9(filePath, "utf-8");
|
|
12971
12972
|
} catch {
|
|
12972
12973
|
}
|
|
12973
|
-
|
|
12974
|
+
resolve22({ sessionId, dirName: req.dirName, fileName, filePath, initialContent });
|
|
12974
12975
|
};
|
|
12975
12976
|
const fail = (message) => {
|
|
12976
12977
|
if (settled) return;
|
|
@@ -13111,10 +13112,10 @@ var init_claudeRuntime = __esm({
|
|
|
13111
13112
|
mcpConfig: req.mcpConfig
|
|
13112
13113
|
});
|
|
13113
13114
|
watchSubagentsFor(state, req.filePath ?? null);
|
|
13114
|
-
const completion = new Promise((
|
|
13115
|
+
const completion = new Promise((resolve22) => {
|
|
13115
13116
|
state.onResult = (result) => {
|
|
13116
13117
|
state.onResult = null;
|
|
13117
|
-
|
|
13118
|
+
resolve22(turnResultFrom(result));
|
|
13118
13119
|
};
|
|
13119
13120
|
});
|
|
13120
13121
|
return { delivery: "started", completion };
|
|
@@ -13200,7 +13201,7 @@ var init_package = __esm({
|
|
|
13200
13201
|
package_default = {
|
|
13201
13202
|
name: "cogpit",
|
|
13202
13203
|
private: true,
|
|
13203
|
-
version: "2.
|
|
13204
|
+
version: "2.3.0",
|
|
13204
13205
|
description: "Control center for Claude Code, OpenAI Codex, and GitHub Copilot CLI sessions",
|
|
13205
13206
|
license: "MIT",
|
|
13206
13207
|
author: {
|
|
@@ -14072,7 +14073,7 @@ var init_codexAppServer = __esm({
|
|
|
14072
14073
|
);
|
|
14073
14074
|
}
|
|
14074
14075
|
const id = this.nextRequestId++;
|
|
14075
|
-
return new Promise((
|
|
14076
|
+
return new Promise((resolve22, reject) => {
|
|
14076
14077
|
const timer = timeoutMs > 0 ? this.setTimer(() => {
|
|
14077
14078
|
const pending = this.pendingRequests.get(id);
|
|
14078
14079
|
if (!pending) return;
|
|
@@ -14085,7 +14086,7 @@ var init_codexAppServer = __esm({
|
|
|
14085
14086
|
}, timeoutMs) : null;
|
|
14086
14087
|
this.pendingRequests.set(id, {
|
|
14087
14088
|
method,
|
|
14088
|
-
resolve: (result) =>
|
|
14089
|
+
resolve: (result) => resolve22(result),
|
|
14089
14090
|
reject,
|
|
14090
14091
|
timer
|
|
14091
14092
|
});
|
|
@@ -14111,12 +14112,12 @@ var init_codexAppServer = __esm({
|
|
|
14111
14112
|
new CodexAppServerError("Codex app-server stdin is not writable")
|
|
14112
14113
|
);
|
|
14113
14114
|
}
|
|
14114
|
-
return new Promise((
|
|
14115
|
+
return new Promise((resolve22, reject) => {
|
|
14115
14116
|
try {
|
|
14116
14117
|
child.stdin.write(`${JSON.stringify(message)}
|
|
14117
14118
|
`, (error) => {
|
|
14118
14119
|
if (error) reject(error);
|
|
14119
|
-
else
|
|
14120
|
+
else resolve22();
|
|
14120
14121
|
});
|
|
14121
14122
|
} catch (error) {
|
|
14122
14123
|
reject(error);
|
|
@@ -14217,13 +14218,13 @@ var init_codexAppServer = __esm({
|
|
|
14217
14218
|
}
|
|
14218
14219
|
}
|
|
14219
14220
|
waitForChildClose(closed, timeoutMs) {
|
|
14220
|
-
return new Promise((
|
|
14221
|
+
return new Promise((resolve22) => {
|
|
14221
14222
|
let settled = false;
|
|
14222
14223
|
const finish = (didClose) => {
|
|
14223
14224
|
if (settled) return;
|
|
14224
14225
|
settled = true;
|
|
14225
14226
|
this.clearTimer(timer);
|
|
14226
|
-
|
|
14227
|
+
resolve22(didClose);
|
|
14227
14228
|
};
|
|
14228
14229
|
const timer = this.setTimer(() => finish(false), timeoutMs);
|
|
14229
14230
|
void closed.then(() => finish(true));
|
|
@@ -14232,8 +14233,8 @@ var init_codexAppServer = __esm({
|
|
|
14232
14233
|
async terminateChild(child, error) {
|
|
14233
14234
|
let didClose = false;
|
|
14234
14235
|
let resolveClose = () => void 0;
|
|
14235
|
-
const closed = new Promise((
|
|
14236
|
-
resolveClose =
|
|
14236
|
+
const closed = new Promise((resolve22) => {
|
|
14237
|
+
resolveClose = resolve22;
|
|
14237
14238
|
});
|
|
14238
14239
|
child.on("close", () => {
|
|
14239
14240
|
didClose = true;
|
|
@@ -14593,7 +14594,7 @@ async function waitForNewSession(cwd, knownPaths, startedAt2, timeoutMs = SESSIO
|
|
|
14593
14594
|
while (Date.now() < deadline) {
|
|
14594
14595
|
const match = await findNewestCodexSessionForCwd(cwd, knownPaths, startedAt2);
|
|
14595
14596
|
if (match) return match;
|
|
14596
|
-
await new Promise((
|
|
14597
|
+
await new Promise((resolve22) => setTimeout(resolve22, SESSION_DISCOVERY_INTERVAL_MS));
|
|
14597
14598
|
}
|
|
14598
14599
|
return null;
|
|
14599
14600
|
}
|
|
@@ -14607,9 +14608,9 @@ function identityFromMetaLine(line) {
|
|
|
14607
14608
|
const sessionId = typeof payload.id === "string" ? payload.id : "";
|
|
14608
14609
|
const timestampText = typeof payload.timestamp === "string" ? payload.timestamp : typeof parsed.timestamp === "string" ? parsed.timestamp : "";
|
|
14609
14610
|
if (!sessionId || !timestampText) return null;
|
|
14610
|
-
const
|
|
14611
|
-
if (Number.isNaN(
|
|
14612
|
-
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);
|
|
14613
14614
|
return { sessionId, fileName, filePath: join11(sessionsRoot2(), fileName) };
|
|
14614
14615
|
} catch {
|
|
14615
14616
|
return null;
|
|
@@ -14680,7 +14681,7 @@ async function startLegacy(req, knownPaths) {
|
|
|
14680
14681
|
child.stderr?.on("data", (data) => {
|
|
14681
14682
|
stderr += data.toString();
|
|
14682
14683
|
});
|
|
14683
|
-
return new Promise((
|
|
14684
|
+
return new Promise((resolve22, reject) => {
|
|
14684
14685
|
let settled = false;
|
|
14685
14686
|
let sessionId = null;
|
|
14686
14687
|
const discovery = waitForNewSession(req.cwd, knownPaths, startedAt2);
|
|
@@ -14698,7 +14699,7 @@ async function startLegacy(req, knownPaths) {
|
|
|
14698
14699
|
} catch {
|
|
14699
14700
|
}
|
|
14700
14701
|
}
|
|
14701
|
-
|
|
14702
|
+
resolve22({
|
|
14702
14703
|
sessionId: identity.sessionId,
|
|
14703
14704
|
dirName: req.dirName,
|
|
14704
14705
|
fileName: identity.fileName,
|
|
@@ -14775,10 +14776,10 @@ async function sendLegacy(sessionId, req) {
|
|
|
14775
14776
|
child.stderr?.on("data", (data) => {
|
|
14776
14777
|
stderr += data.toString();
|
|
14777
14778
|
});
|
|
14778
|
-
const completion = new Promise((
|
|
14779
|
+
const completion = new Promise((resolve22) => {
|
|
14779
14780
|
session.onResult = (result) => {
|
|
14780
14781
|
session.onResult = null;
|
|
14781
|
-
|
|
14782
|
+
resolve22({
|
|
14782
14783
|
isError: result.is_error === true,
|
|
14783
14784
|
message: result.result
|
|
14784
14785
|
});
|
|
@@ -15816,7 +15817,7 @@ var init_copilotTransport = __esm({
|
|
|
15816
15817
|
}
|
|
15817
15818
|
waitForRequest(request, method, timeoutMs = this.transportTimeoutMs, onTimeout) {
|
|
15818
15819
|
if (timeoutMs <= 0) return request;
|
|
15819
|
-
return new Promise((
|
|
15820
|
+
return new Promise((resolve22, reject) => {
|
|
15820
15821
|
const timer = setTimeout(() => {
|
|
15821
15822
|
try {
|
|
15822
15823
|
onTimeout?.();
|
|
@@ -15827,7 +15828,7 @@ var init_copilotTransport = __esm({
|
|
|
15827
15828
|
request.then(
|
|
15828
15829
|
(value) => {
|
|
15829
15830
|
clearTimeout(timer);
|
|
15830
|
-
|
|
15831
|
+
resolve22(value);
|
|
15831
15832
|
},
|
|
15832
15833
|
(error) => {
|
|
15833
15834
|
clearTimeout(timer);
|
|
@@ -15953,10 +15954,10 @@ var init_copilotTransport = __esm({
|
|
|
15953
15954
|
...typeof params.allowFreeform === "boolean" ? { allowFreeform: params.allowFreeform } : {},
|
|
15954
15955
|
askedAt: Date.now()
|
|
15955
15956
|
};
|
|
15956
|
-
return new Promise((
|
|
15957
|
+
return new Promise((resolve22, reject) => {
|
|
15957
15958
|
this.pendingUserInputs.set(
|
|
15958
15959
|
this.pendingInteractionKey(sessionId, requestId),
|
|
15959
|
-
{ value, resolve:
|
|
15960
|
+
{ value, resolve: resolve22, reject }
|
|
15960
15961
|
);
|
|
15961
15962
|
});
|
|
15962
15963
|
}
|
|
@@ -15976,10 +15977,10 @@ var init_copilotTransport = __esm({
|
|
|
15976
15977
|
recommendedAction: typeof params.recommendedAction === "string" ? params.recommendedAction : actions[0] ?? "interactive",
|
|
15977
15978
|
askedAt: Date.now()
|
|
15978
15979
|
};
|
|
15979
|
-
return new Promise((
|
|
15980
|
+
return new Promise((resolve22, reject) => {
|
|
15980
15981
|
this.pendingExitPlans.set(
|
|
15981
15982
|
this.pendingInteractionKey(sessionId, requestId),
|
|
15982
|
-
{ value, resolve:
|
|
15983
|
+
{ value, resolve: resolve22, reject }
|
|
15983
15984
|
);
|
|
15984
15985
|
});
|
|
15985
15986
|
}
|
|
@@ -16204,17 +16205,17 @@ function parseJsonRecord(line) {
|
|
|
16204
16205
|
}
|
|
16205
16206
|
}
|
|
16206
16207
|
function parseClaudeUsageLine(line) {
|
|
16207
|
-
const
|
|
16208
|
-
if (!
|
|
16209
|
-
const message = asRecord3(
|
|
16208
|
+
const record4 = parseJsonRecord(line);
|
|
16209
|
+
if (!record4 || record4.type !== "assistant") return null;
|
|
16210
|
+
const message = asRecord3(record4.message);
|
|
16210
16211
|
const usage = message ? asRecord3(message.usage) : null;
|
|
16211
16212
|
if (!message || !usage) return null;
|
|
16212
|
-
const timestampMs = parseTimestampMs(
|
|
16213
|
+
const timestampMs = parseTimestampMs(record4.timestamp);
|
|
16213
16214
|
if (timestampMs === null) return null;
|
|
16214
16215
|
const model = typeof message.model === "string" ? message.model : "";
|
|
16215
16216
|
if (model.length === 0) return null;
|
|
16216
16217
|
const messageId = typeof message.id === "string" ? message.id : null;
|
|
16217
|
-
const requestId = typeof
|
|
16218
|
+
const requestId = typeof record4.requestId === "string" ? record4.requestId : null;
|
|
16218
16219
|
const dedupeKey = messageId === null && requestId === null ? null : `${messageId ?? ""}:${requestId ?? ""}`;
|
|
16219
16220
|
const cacheCreationTokens = int(usage.cache_creation_input_tokens);
|
|
16220
16221
|
const byTtl = asRecord3(usage.cache_creation);
|
|
@@ -16233,12 +16234,12 @@ function parseClaudeUsageLine(line) {
|
|
|
16233
16234
|
reasoningTokens: 0
|
|
16234
16235
|
};
|
|
16235
16236
|
if (totalUsageCostTokens(totals) === 0) return null;
|
|
16236
|
-
const cost =
|
|
16237
|
+
const cost = record4.costUSD;
|
|
16237
16238
|
return {
|
|
16238
16239
|
provider: "claude",
|
|
16239
16240
|
timestampMs,
|
|
16240
16241
|
model,
|
|
16241
|
-
sessionId: typeof
|
|
16242
|
+
sessionId: typeof record4.sessionId === "string" ? record4.sessionId : "",
|
|
16242
16243
|
totals,
|
|
16243
16244
|
reportedCostUsd: typeof cost === "number" && Number.isFinite(cost) ? cost : null,
|
|
16244
16245
|
dedupeKey
|
|
@@ -16260,30 +16261,30 @@ function isForkedSessionMeta(payload) {
|
|
|
16260
16261
|
return typeof spawn5?.parent_thread_id === "string";
|
|
16261
16262
|
}
|
|
16262
16263
|
function parseCodexUsageLine(line, state) {
|
|
16263
|
-
const
|
|
16264
|
-
if (!
|
|
16265
|
-
const payload = asRecord3(
|
|
16264
|
+
const record4 = parseJsonRecord(line);
|
|
16265
|
+
if (!record4) return null;
|
|
16266
|
+
const payload = asRecord3(record4.payload);
|
|
16266
16267
|
if (!payload) return null;
|
|
16267
|
-
if (
|
|
16268
|
+
if (record4.type === "session_meta") {
|
|
16268
16269
|
if (state.sawSessionMeta) return null;
|
|
16269
16270
|
state.sawSessionMeta = true;
|
|
16270
16271
|
const id = payload.id ?? payload.session_id;
|
|
16271
16272
|
if (typeof id === "string") state.sessionId = id;
|
|
16272
|
-
const metaTimestampMs = parseTimestampMs(
|
|
16273
|
+
const metaTimestampMs = parseTimestampMs(record4.timestamp);
|
|
16273
16274
|
if (metaTimestampMs !== null && isForkedSessionMeta(payload)) {
|
|
16274
16275
|
state.suppressingForkCopies = true;
|
|
16275
16276
|
state.forkCopyAnchorMs = metaTimestampMs;
|
|
16276
16277
|
}
|
|
16277
16278
|
return null;
|
|
16278
16279
|
}
|
|
16279
|
-
if (
|
|
16280
|
+
if (record4.type === "turn_context") {
|
|
16280
16281
|
if (typeof payload.model === "string") state.model = payload.model;
|
|
16281
16282
|
return null;
|
|
16282
16283
|
}
|
|
16283
16284
|
if (payload.type !== "token_count") return null;
|
|
16284
16285
|
const last = asRecord3(asRecord3(payload.info)?.last_token_usage);
|
|
16285
16286
|
if (!last) return null;
|
|
16286
|
-
const timestampMs = parseTimestampMs(
|
|
16287
|
+
const timestampMs = parseTimestampMs(record4.timestamp);
|
|
16287
16288
|
if (timestampMs === null) return null;
|
|
16288
16289
|
if (state.model.length === 0) return null;
|
|
16289
16290
|
const signature = JSON.stringify(last);
|
|
@@ -16382,17 +16383,17 @@ function parseCopilotUsageMetrics(value, state, timestampMs) {
|
|
|
16382
16383
|
return records;
|
|
16383
16384
|
}
|
|
16384
16385
|
function parseCopilotUsageLine(line, state) {
|
|
16385
|
-
const
|
|
16386
|
-
if (!
|
|
16387
|
-
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);
|
|
16388
16389
|
if (!data) return [];
|
|
16389
|
-
if (
|
|
16390
|
+
if (record4.type === "session.start") {
|
|
16390
16391
|
const sessionId = data.sessionId;
|
|
16391
16392
|
if (typeof sessionId === "string" && sessionId.length > 0) state.sessionId = sessionId;
|
|
16392
16393
|
return [];
|
|
16393
16394
|
}
|
|
16394
|
-
if (
|
|
16395
|
-
const timestampMs = parseTimestampMs(
|
|
16395
|
+
if (record4.type !== "session.shutdown") return [];
|
|
16396
|
+
const timestampMs = parseTimestampMs(record4.timestamp);
|
|
16396
16397
|
return timestampMs === null ? [] : parseCopilotUsageMetrics(data, state, timestampMs);
|
|
16397
16398
|
}
|
|
16398
16399
|
function createUsageScanner(provider, filePath) {
|
|
@@ -16409,8 +16410,8 @@ var init_usageScanners = __esm({
|
|
|
16409
16410
|
// object, so a line is either self-contained or of no interest.
|
|
16410
16411
|
wantsLine: (line) => line.includes('"usage"'),
|
|
16411
16412
|
accept: (line) => {
|
|
16412
|
-
const
|
|
16413
|
-
return
|
|
16413
|
+
const record4 = parseClaudeUsageLine(line);
|
|
16414
|
+
return record4 === null ? [] : [record4];
|
|
16414
16415
|
}
|
|
16415
16416
|
}),
|
|
16416
16417
|
codex: () => {
|
|
@@ -16421,8 +16422,8 @@ var init_usageScanners = __esm({
|
|
|
16421
16422
|
// at all but still have to reach the reducer.
|
|
16422
16423
|
wantsLine: (line) => line.includes('"token_count"') || line.includes('"turn_context"') || line.includes('"session_meta"'),
|
|
16423
16424
|
accept: (line) => {
|
|
16424
|
-
const
|
|
16425
|
-
return
|
|
16425
|
+
const record4 = parseCodexUsageLine(line, state);
|
|
16426
|
+
return record4 === null ? [] : [record4];
|
|
16426
16427
|
}
|
|
16427
16428
|
};
|
|
16428
16429
|
},
|
|
@@ -16668,7 +16669,7 @@ var init_copilotRuntime = __esm({
|
|
|
16668
16669
|
initialContent = await readFile9(filePath, "utf-8");
|
|
16669
16670
|
break;
|
|
16670
16671
|
} catch {
|
|
16671
|
-
await new Promise((
|
|
16672
|
+
await new Promise((resolve22) => setTimeout(resolve22, TRANSCRIPT_POLL_INTERVAL_MS2));
|
|
16672
16673
|
}
|
|
16673
16674
|
}
|
|
16674
16675
|
return { sessionId, dirName: req.dirName, fileName, filePath, initialContent };
|
|
@@ -17671,12 +17672,12 @@ function registerBranchSessionRoute(use) {
|
|
|
17671
17672
|
}
|
|
17672
17673
|
}
|
|
17673
17674
|
const newSessionId = randomUUID2();
|
|
17674
|
-
const { record:
|
|
17675
|
+
const { record: record4, originalId } = format.brandBranch(
|
|
17675
17676
|
JSON.parse(lines[0]),
|
|
17676
17677
|
newSessionId,
|
|
17677
17678
|
turnIndex ?? null
|
|
17678
17679
|
);
|
|
17679
|
-
lines[0] = JSON.stringify(
|
|
17680
|
+
lines[0] = JSON.stringify(record4);
|
|
17680
17681
|
const target = storeForDirName(dirName).transcriptPath(dirName, newSessionId);
|
|
17681
17682
|
if (!target) {
|
|
17682
17683
|
res.statusCode = 500;
|
|
@@ -19843,21 +19844,21 @@ function toPublic(device) {
|
|
|
19843
19844
|
return rest;
|
|
19844
19845
|
}
|
|
19845
19846
|
function readJsonBody2(req) {
|
|
19846
|
-
return new Promise((
|
|
19847
|
+
return new Promise((resolve22) => {
|
|
19847
19848
|
let raw = "";
|
|
19848
19849
|
req.on("data", (chunk) => {
|
|
19849
19850
|
raw += chunk.toString();
|
|
19850
19851
|
});
|
|
19851
19852
|
req.on("end", () => {
|
|
19852
|
-
if (!raw.trim()) return
|
|
19853
|
+
if (!raw.trim()) return resolve22({});
|
|
19853
19854
|
try {
|
|
19854
19855
|
const parsed = JSON.parse(raw);
|
|
19855
|
-
|
|
19856
|
+
resolve22(parsed && typeof parsed === "object" ? parsed : null);
|
|
19856
19857
|
} catch {
|
|
19857
|
-
|
|
19858
|
+
resolve22(null);
|
|
19858
19859
|
}
|
|
19859
19860
|
});
|
|
19860
|
-
req.on("error", () =>
|
|
19861
|
+
req.on("error", () => resolve22(null));
|
|
19861
19862
|
});
|
|
19862
19863
|
}
|
|
19863
19864
|
function handleList(res) {
|
|
@@ -20245,9 +20246,9 @@ function terminalCommand(terminal, dirPath) {
|
|
|
20245
20246
|
return { cmd: terminal, args: ["--working-directory", dirPath] };
|
|
20246
20247
|
}
|
|
20247
20248
|
function whichEditor(name) {
|
|
20248
|
-
return new Promise((
|
|
20249
|
+
return new Promise((resolve22) => {
|
|
20249
20250
|
const cmd = platform() === "win32" ? "where" : "which";
|
|
20250
|
-
execFile(cmd, [name], (err) =>
|
|
20251
|
+
execFile(cmd, [name], (err) => resolve22(err ? null : name));
|
|
20251
20252
|
});
|
|
20252
20253
|
}
|
|
20253
20254
|
async function resolveEditor(configuredEditor) {
|
|
@@ -20261,10 +20262,10 @@ async function resolveEditor(configuredEditor) {
|
|
|
20261
20262
|
return null;
|
|
20262
20263
|
}
|
|
20263
20264
|
function openWithEditor(editor, args) {
|
|
20264
|
-
return new Promise((
|
|
20265
|
+
return new Promise((resolve22, reject) => {
|
|
20265
20266
|
execFile(editor, args, (err) => {
|
|
20266
20267
|
if (err) reject(err);
|
|
20267
|
-
else
|
|
20268
|
+
else resolve22();
|
|
20268
20269
|
});
|
|
20269
20270
|
});
|
|
20270
20271
|
}
|
|
@@ -20277,14 +20278,14 @@ function editorOpenArgs(editor, filePath, line, column) {
|
|
|
20277
20278
|
return [filePath];
|
|
20278
20279
|
}
|
|
20279
20280
|
function getGitHeadContent(filePath) {
|
|
20280
|
-
return new Promise((
|
|
20281
|
+
return new Promise((resolve22, reject) => {
|
|
20281
20282
|
execFile(
|
|
20282
20283
|
"git",
|
|
20283
20284
|
["-C", dirname7(filePath), "show", `HEAD:./${basename7(filePath)}`],
|
|
20284
20285
|
{ maxBuffer: 10 * 1024 * 1024 },
|
|
20285
20286
|
(err, stdout) => {
|
|
20286
20287
|
if (err) reject(err);
|
|
20287
|
-
else
|
|
20288
|
+
else resolve22(stdout);
|
|
20288
20289
|
}
|
|
20289
20290
|
);
|
|
20290
20291
|
});
|
|
@@ -20960,23 +20961,23 @@ function registerFileRoutes(use) {
|
|
|
20960
20961
|
req.on("end", async () => {
|
|
20961
20962
|
try {
|
|
20962
20963
|
let spawnLines = function(args, cwd) {
|
|
20963
|
-
return new Promise((
|
|
20964
|
+
return new Promise((resolve22) => {
|
|
20964
20965
|
const proc = spawn2("git", args, { cwd });
|
|
20965
20966
|
let out = "";
|
|
20966
20967
|
proc.stdout.on("data", (d) => out += d.toString());
|
|
20967
20968
|
proc.on("close", (code) => {
|
|
20968
|
-
if (code !== 0 || !out) return
|
|
20969
|
-
|
|
20969
|
+
if (code !== 0 || !out) return resolve22(0);
|
|
20970
|
+
resolve22(out.split("\n").length);
|
|
20970
20971
|
});
|
|
20971
|
-
proc.on("error", () =>
|
|
20972
|
+
proc.on("error", () => resolve22(0));
|
|
20972
20973
|
});
|
|
20973
20974
|
}, spawnOutput = function(args, cwd) {
|
|
20974
|
-
return new Promise((
|
|
20975
|
+
return new Promise((resolve22) => {
|
|
20975
20976
|
const proc = spawn2("git", args, { cwd });
|
|
20976
20977
|
let out = "";
|
|
20977
20978
|
proc.stdout.on("data", (d) => out += d.toString());
|
|
20978
|
-
proc.on("close", () =>
|
|
20979
|
-
proc.on("error", () =>
|
|
20979
|
+
proc.on("close", () => resolve22(out.trim()));
|
|
20980
|
+
proc.on("error", () => resolve22(""));
|
|
20980
20981
|
});
|
|
20981
20982
|
};
|
|
20982
20983
|
const { files, dirs: dirs2 } = JSON.parse(body);
|
|
@@ -21000,18 +21001,18 @@ function registerFileRoutes(use) {
|
|
|
21000
21001
|
cwd = cwd.substring(0, cwd.lastIndexOf("/")) || "/";
|
|
21001
21002
|
}
|
|
21002
21003
|
}
|
|
21003
|
-
return new Promise((
|
|
21004
|
+
return new Promise((resolve22) => {
|
|
21004
21005
|
const proc = spawn2("git", ["rev-parse", "--show-toplevel"], { cwd });
|
|
21005
21006
|
let out = "";
|
|
21006
21007
|
proc.stdout.on("data", (d) => out += d.toString());
|
|
21007
21008
|
proc.on("close", (code) => {
|
|
21008
21009
|
const root = code === 0 ? out.trim() : null;
|
|
21009
21010
|
gitRootCache.set(dir, root);
|
|
21010
|
-
|
|
21011
|
+
resolve22(root);
|
|
21011
21012
|
});
|
|
21012
21013
|
proc.on("error", () => {
|
|
21013
21014
|
gitRootCache.set(dir, null);
|
|
21014
|
-
|
|
21015
|
+
resolve22(null);
|
|
21015
21016
|
});
|
|
21016
21017
|
});
|
|
21017
21018
|
}
|
|
@@ -21246,11 +21247,11 @@ function parseGitStatus(output) {
|
|
|
21246
21247
|
const branch = parseBranchHeader(header);
|
|
21247
21248
|
const files = [];
|
|
21248
21249
|
for (let index = 0; index < records.length; index += 1) {
|
|
21249
|
-
const
|
|
21250
|
-
if (!
|
|
21251
|
-
const indexStatus =
|
|
21252
|
-
const workTreeStatus =
|
|
21253
|
-
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);
|
|
21254
21255
|
const renamedOrCopied = /[RC]/.test(`${indexStatus}${workTreeStatus}`);
|
|
21255
21256
|
const originalPath = renamedOrCopied ? records[index += 1] || void 0 : void 0;
|
|
21256
21257
|
files.push({ path, originalPath, indexStatus, workTreeStatus });
|
|
@@ -21571,14 +21572,364 @@ var init_github_actions = __esm({
|
|
|
21571
21572
|
}
|
|
21572
21573
|
});
|
|
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
|
+
|
|
21574
21925
|
// ../../server/lib/projectIcon.ts
|
|
21575
|
-
import { realpath as
|
|
21576
|
-
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";
|
|
21577
21928
|
function namedIconCandidates(root) {
|
|
21578
21929
|
const name = basename9(root);
|
|
21579
21930
|
if (!name || name.startsWith(".")) return [];
|
|
21580
21931
|
return ["public", "assets", "static", "."].flatMap(
|
|
21581
|
-
(dir) => NAMED_ICON_EXTENSIONS.map((ext) =>
|
|
21932
|
+
(dir) => NAMED_ICON_EXTENSIONS.map((ext) => join21(dir, `${name}${ext}`))
|
|
21582
21933
|
);
|
|
21583
21934
|
}
|
|
21584
21935
|
function iconContentType(path) {
|
|
@@ -21591,7 +21942,7 @@ function isInside(root, candidate) {
|
|
|
21591
21942
|
async function resolveProjectIcon(projectPath) {
|
|
21592
21943
|
let root;
|
|
21593
21944
|
try {
|
|
21594
|
-
root = await
|
|
21945
|
+
root = await realpath9(projectPath);
|
|
21595
21946
|
} catch {
|
|
21596
21947
|
return null;
|
|
21597
21948
|
}
|
|
@@ -21601,11 +21952,11 @@ async function resolveProjectIcon(projectPath) {
|
|
|
21601
21952
|
...PROJECT_ICON_CANDIDATES.slice(6)
|
|
21602
21953
|
];
|
|
21603
21954
|
for (const candidate of candidates) {
|
|
21604
|
-
const guess =
|
|
21955
|
+
const guess = join21(root, candidate);
|
|
21605
21956
|
try {
|
|
21606
|
-
const resolved = await
|
|
21957
|
+
const resolved = await realpath9(guess);
|
|
21607
21958
|
if (!isInside(root, resolved)) continue;
|
|
21608
|
-
const info = await
|
|
21959
|
+
const info = await stat14(resolved);
|
|
21609
21960
|
if (!info.isFile() || info.size === 0 || info.size > MAX_ICON_BYTES) continue;
|
|
21610
21961
|
if (!iconContentType(resolved)) continue;
|
|
21611
21962
|
return resolved;
|
|
@@ -21663,13 +22014,13 @@ var init_projectIcon = __esm({
|
|
|
21663
22014
|
|
|
21664
22015
|
// ../../server/routes/project-icon.ts
|
|
21665
22016
|
import { createReadStream } from "node:fs";
|
|
21666
|
-
import { isAbsolute as
|
|
22017
|
+
import { isAbsolute as isAbsolute9 } from "node:path";
|
|
21667
22018
|
function registerProjectIconRoutes(use) {
|
|
21668
22019
|
use("/api/project-icon", async (req, res, next) => {
|
|
21669
22020
|
if (req.method !== "GET") return next();
|
|
21670
22021
|
const url = new URL(req.url || "", "http://localhost");
|
|
21671
22022
|
const cwd = url.searchParams.get("cwd") ?? "";
|
|
21672
|
-
if (!
|
|
22023
|
+
if (!isAbsolute9(cwd)) {
|
|
21673
22024
|
return sendJson(res, 400, { error: "cwd must be an absolute path" });
|
|
21674
22025
|
}
|
|
21675
22026
|
const icon = await resolveProjectIcon(cwd);
|
|
@@ -21754,14 +22105,14 @@ var init_local_file = __esm({
|
|
|
21754
22105
|
});
|
|
21755
22106
|
|
|
21756
22107
|
// ../../server/routes/mcp.ts
|
|
21757
|
-
import { execFile as
|
|
21758
|
-
import { isAbsolute as
|
|
21759
|
-
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";
|
|
21760
22111
|
import { homedir as homedir7 } from "node:os";
|
|
21761
22112
|
async function readMcpConfigs(cwd) {
|
|
21762
22113
|
const configs = {};
|
|
21763
22114
|
try {
|
|
21764
|
-
const raw = await
|
|
22115
|
+
const raw = await readFile16(join22(homedir7(), ".claude.json"), "utf-8");
|
|
21765
22116
|
const parsed = JSON.parse(raw);
|
|
21766
22117
|
if (parsed.mcpServers && typeof parsed.mcpServers === "object") {
|
|
21767
22118
|
Object.assign(configs, parsed.mcpServers);
|
|
@@ -21779,16 +22130,16 @@ async function readMcpConfigs(cwd) {
|
|
|
21779
22130
|
} catch {
|
|
21780
22131
|
}
|
|
21781
22132
|
const otherSources = [
|
|
21782
|
-
|
|
22133
|
+
join22(homedir7(), ".claude", "settings.json"),
|
|
21783
22134
|
// global settings
|
|
21784
|
-
|
|
22135
|
+
join22(cwd, ".mcp.json"),
|
|
21785
22136
|
// project
|
|
21786
|
-
|
|
22137
|
+
join22(cwd, ".claude", "settings.local.json")
|
|
21787
22138
|
// project local
|
|
21788
22139
|
];
|
|
21789
22140
|
for (const path of otherSources) {
|
|
21790
22141
|
try {
|
|
21791
|
-
const raw = await
|
|
22142
|
+
const raw = await readFile16(path, "utf-8");
|
|
21792
22143
|
const parsed = JSON.parse(raw);
|
|
21793
22144
|
if (parsed.mcpServers && typeof parsed.mcpServers === "object") {
|
|
21794
22145
|
Object.assign(configs, parsed.mcpServers);
|
|
@@ -21831,18 +22182,18 @@ async function getMcpServers(cwd) {
|
|
|
21831
22182
|
return { servers: cached.servers, configs: cached.configs };
|
|
21832
22183
|
}
|
|
21833
22184
|
const configs = await readMcpConfigs(cwd);
|
|
21834
|
-
return new Promise((
|
|
22185
|
+
return new Promise((resolve22) => {
|
|
21835
22186
|
const env = { ...process.env };
|
|
21836
22187
|
delete env.CLAUDECODE;
|
|
21837
22188
|
const cli = resolveAgentCommand("claude", ["mcp", "list"]);
|
|
21838
|
-
|
|
22189
|
+
execFile5(cli.command, cli.args, { cwd, env, timeout: 15e3, ...cli.spawnOptions }, (err, stdout) => {
|
|
21839
22190
|
if (err) {
|
|
21840
|
-
|
|
22191
|
+
resolve22({ servers: cached?.servers ?? [], configs });
|
|
21841
22192
|
return;
|
|
21842
22193
|
}
|
|
21843
22194
|
const servers = parseMcpListOutput(stdout);
|
|
21844
22195
|
cache.set(cwd, { servers, configs, timestamp: Date.now() });
|
|
21845
|
-
|
|
22196
|
+
resolve22({ servers, configs });
|
|
21846
22197
|
});
|
|
21847
22198
|
});
|
|
21848
22199
|
}
|
|
@@ -21852,7 +22203,7 @@ function registerMcpRoutes(use) {
|
|
|
21852
22203
|
const url = new URL(req.url || "", `http://${req.headers.host}`);
|
|
21853
22204
|
const cwd = url.searchParams.get("cwd");
|
|
21854
22205
|
const refresh = url.searchParams.get("refresh") === "1";
|
|
21855
|
-
if (!cwd || !
|
|
22206
|
+
if (!cwd || !isAbsolute10(cwd)) {
|
|
21856
22207
|
return sendJson(res, 400, { error: "cwd must be an absolute path" });
|
|
21857
22208
|
}
|
|
21858
22209
|
if (refresh) clearMcpCache(cwd);
|
|
@@ -21964,7 +22315,7 @@ var init_diff_utils = __esm({
|
|
|
21964
22315
|
function isObject9(value) {
|
|
21965
22316
|
return typeof value === "object" && value !== null;
|
|
21966
22317
|
}
|
|
21967
|
-
function
|
|
22318
|
+
function firstString3(...values) {
|
|
21968
22319
|
return values.find((value) => typeof value === "string") ?? "";
|
|
21969
22320
|
}
|
|
21970
22321
|
function truncate(value, length = 140) {
|
|
@@ -22211,19 +22562,19 @@ function nativeWebPresentation(input) {
|
|
|
22211
22562
|
if (type === "open_page" || type === "openPage") {
|
|
22212
22563
|
return {
|
|
22213
22564
|
label: "Open page",
|
|
22214
|
-
summary:
|
|
22565
|
+
summary: firstString3(action?.url, input.query),
|
|
22215
22566
|
styleName: "WebSearch"
|
|
22216
22567
|
};
|
|
22217
22568
|
}
|
|
22218
22569
|
if (type === "find_in_page" || type === "findInPage") {
|
|
22219
22570
|
return {
|
|
22220
22571
|
label: "Find on page",
|
|
22221
|
-
summary: [
|
|
22572
|
+
summary: [firstString3(action?.pattern), firstString3(action?.url)].filter(Boolean).join(" \xB7 "),
|
|
22222
22573
|
styleName: "WebSearch"
|
|
22223
22574
|
};
|
|
22224
22575
|
}
|
|
22225
22576
|
const queries = Array.isArray(action?.queries) ? action.queries.filter((query5) => typeof query5 === "string") : [];
|
|
22226
|
-
const query4 =
|
|
22577
|
+
const query4 = firstString3(action?.query, input.query);
|
|
22227
22578
|
return {
|
|
22228
22579
|
label: "Search web",
|
|
22229
22580
|
summary: compactValues([query4, ...queries]),
|
|
@@ -22231,7 +22582,7 @@ function nativeWebPresentation(input) {
|
|
|
22231
22582
|
};
|
|
22232
22583
|
}
|
|
22233
22584
|
function schemaFreeSummary(input) {
|
|
22234
|
-
const gist =
|
|
22585
|
+
const gist = firstString3(...SCHEMA_FREE_GIST_KEYS.map((key2) => input[key2]));
|
|
22235
22586
|
if (gist) return truncate(gist);
|
|
22236
22587
|
for (const [key2, value] of Object.entries(input)) {
|
|
22237
22588
|
if (!Array.isArray(value)) continue;
|
|
@@ -22241,11 +22592,11 @@ function schemaFreeSummary(input) {
|
|
|
22241
22592
|
return "";
|
|
22242
22593
|
}
|
|
22243
22594
|
function workflowSummary(input) {
|
|
22244
|
-
const description =
|
|
22595
|
+
const description = firstString3(input.description);
|
|
22245
22596
|
if (description) return truncate(description);
|
|
22246
|
-
const script =
|
|
22597
|
+
const script = firstString3(input.script);
|
|
22247
22598
|
const metaName = script ? extractJsStringPropertyValues(script, "name")[0] ?? "" : "";
|
|
22248
|
-
return metaName ||
|
|
22599
|
+
return metaName || firstString3(input.scriptPath);
|
|
22249
22600
|
}
|
|
22250
22601
|
function firstStringValue(input) {
|
|
22251
22602
|
const keys = Object.keys(input);
|
|
@@ -22322,19 +22673,19 @@ function defaultToolSummary(tc) {
|
|
|
22322
22673
|
case "ToolSearch":
|
|
22323
22674
|
return String(input.query ?? "");
|
|
22324
22675
|
case "SendMessage": {
|
|
22325
|
-
const recipient =
|
|
22326
|
-
const gist = truncate(
|
|
22676
|
+
const recipient = firstString3(input.to, input.recipient);
|
|
22677
|
+
const gist = truncate(firstString3(input.summary, input.message, input.content));
|
|
22327
22678
|
return [recipient, gist].filter(Boolean).join(" \xB7 ");
|
|
22328
22679
|
}
|
|
22329
22680
|
case "ListAgents":
|
|
22330
22681
|
case "TaskList":
|
|
22331
22682
|
return "";
|
|
22332
22683
|
case "TaskCreate":
|
|
22333
|
-
return truncate(
|
|
22684
|
+
return truncate(firstString3(input.subject, input.description));
|
|
22334
22685
|
case "TaskUpdate": {
|
|
22335
22686
|
const taskId = String(input.taskId ?? "");
|
|
22336
22687
|
const blockers = Array.isArray(input.addBlockedBy) ? input.addBlockedBy.filter((id) => typeof id === "string") : [];
|
|
22337
|
-
const change =
|
|
22688
|
+
const change = firstString3(input.status) || (blockers.length > 0 ? `blocked by ${blockers.join(", ")}` : "");
|
|
22338
22689
|
return change ? `${taskId} \u2192 ${change}` : taskId;
|
|
22339
22690
|
}
|
|
22340
22691
|
case "TaskOutput":
|
|
@@ -22634,8 +22985,8 @@ function copilotText(value) {
|
|
|
22634
22985
|
if (!Array.isArray(value)) return "";
|
|
22635
22986
|
return value.flatMap((part) => {
|
|
22636
22987
|
if (typeof part === "string") return part ? [part] : [];
|
|
22637
|
-
const
|
|
22638
|
-
const text = str(
|
|
22988
|
+
const record4 = asRecord5(part);
|
|
22989
|
+
const text = str(record4.text) || str(record4.content);
|
|
22639
22990
|
return text ? [text] : [];
|
|
22640
22991
|
}).join("\n");
|
|
22641
22992
|
}
|
|
@@ -22967,7 +23318,7 @@ var init_summaryFolds = __esm({
|
|
|
22967
23318
|
});
|
|
22968
23319
|
|
|
22969
23320
|
// ../../server/lib/missionControlSummary.ts
|
|
22970
|
-
import { open as open7, stat as
|
|
23321
|
+
import { open as open7, stat as stat15 } from "node:fs/promises";
|
|
22971
23322
|
function foldLine(acc, line) {
|
|
22972
23323
|
const trimmed = line.trim();
|
|
22973
23324
|
if (!trimmed) return;
|
|
@@ -22977,10 +23328,10 @@ function foldLine(acc, line) {
|
|
|
22977
23328
|
} catch {
|
|
22978
23329
|
return;
|
|
22979
23330
|
}
|
|
22980
|
-
const
|
|
22981
|
-
if (
|
|
22982
|
-
acc.startedAt ??=
|
|
22983
|
-
acc.lastEventAt =
|
|
23331
|
+
const timestamp2 = str(entry.timestamp);
|
|
23332
|
+
if (timestamp2) {
|
|
23333
|
+
acc.startedAt ??= timestamp2;
|
|
23334
|
+
acc.lastEventAt = timestamp2;
|
|
22984
23335
|
}
|
|
22985
23336
|
foldSummaryEntry(acc, entry);
|
|
22986
23337
|
}
|
|
@@ -23042,7 +23393,7 @@ async function readSince(filePath, from, to) {
|
|
|
23042
23393
|
async function summarizeSession(sessionId, filePath) {
|
|
23043
23394
|
let size;
|
|
23044
23395
|
try {
|
|
23045
|
-
size = (await
|
|
23396
|
+
size = (await stat15(filePath)).size;
|
|
23046
23397
|
} catch {
|
|
23047
23398
|
return null;
|
|
23048
23399
|
}
|
|
@@ -23199,14 +23550,14 @@ var init_models = __esm({
|
|
|
23199
23550
|
});
|
|
23200
23551
|
|
|
23201
23552
|
// ../../server/lib/notificationHistory.ts
|
|
23202
|
-
import { mkdir as mkdir5, readFile as
|
|
23553
|
+
import { mkdir as mkdir5, readFile as readFile17 } from "node:fs/promises";
|
|
23203
23554
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
23204
23555
|
import { homedir as homedir8 } from "node:os";
|
|
23205
|
-
import { dirname as dirname9, join as
|
|
23556
|
+
import { dirname as dirname9, join as join23 } from "node:path";
|
|
23206
23557
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
23207
23558
|
async function load() {
|
|
23208
23559
|
if (entries) return entries;
|
|
23209
|
-
loadPromise ??=
|
|
23560
|
+
loadPromise ??= readFile17(NOTIFICATION_HISTORY_FILE, "utf-8").then((raw) => {
|
|
23210
23561
|
const parsed = JSON.parse(raw);
|
|
23211
23562
|
return Array.isArray(parsed) ? parsed.filter(isEntry) : [];
|
|
23212
23563
|
}).catch(() => []).then((loaded2) => {
|
|
@@ -23290,7 +23641,7 @@ var NOTIFICATION_HISTORY_FILE, MAX_ENTRIES, PERSIST_DEBOUNCE_MS, entries, loadPr
|
|
|
23290
23641
|
var init_notificationHistory = __esm({
|
|
23291
23642
|
"../../server/lib/notificationHistory.ts"() {
|
|
23292
23643
|
init_atomicJsonFile();
|
|
23293
|
-
NOTIFICATION_HISTORY_FILE =
|
|
23644
|
+
NOTIFICATION_HISTORY_FILE = join23(homedir8(), ".cogpit", "notifications.json");
|
|
23294
23645
|
MAX_ENTRIES = 200;
|
|
23295
23646
|
PERSIST_DEBOUNCE_MS = 500;
|
|
23296
23647
|
entries = null;
|
|
@@ -23338,7 +23689,7 @@ var init_notifications = __esm({
|
|
|
23338
23689
|
});
|
|
23339
23690
|
|
|
23340
23691
|
// ../../server/lib/systemProcesses.ts
|
|
23341
|
-
import { execFile as
|
|
23692
|
+
import { execFile as execFile6 } from "node:child_process";
|
|
23342
23693
|
function parseEtimeSeconds(etime) {
|
|
23343
23694
|
const match = /^(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+)$/.exec(etime.trim());
|
|
23344
23695
|
if (!match) return 0;
|
|
@@ -23459,12 +23810,12 @@ function classifyProcesses(rows, selfPid) {
|
|
|
23459
23810
|
}).slice(0, MAX_LISTED_PROCESSES);
|
|
23460
23811
|
}
|
|
23461
23812
|
function listSystemProcesses() {
|
|
23462
|
-
return new Promise((
|
|
23463
|
-
|
|
23813
|
+
return new Promise((resolve22, reject) => {
|
|
23814
|
+
execFile6(
|
|
23464
23815
|
"ps",
|
|
23465
23816
|
["-axo", "pid=,ppid=,pcpu=,rss=,etime=,args="],
|
|
23466
23817
|
{ maxBuffer: 8 * 1024 * 1024 },
|
|
23467
|
-
(error, stdout) => error ? reject(error) :
|
|
23818
|
+
(error, stdout) => error ? reject(error) : resolve22(stdout)
|
|
23468
23819
|
);
|
|
23469
23820
|
});
|
|
23470
23821
|
}
|
|
@@ -23498,7 +23849,7 @@ var init_systemProcesses = __esm({
|
|
|
23498
23849
|
});
|
|
23499
23850
|
|
|
23500
23851
|
// ../../server/lib/desktopNotify.ts
|
|
23501
|
-
import { execFile as
|
|
23852
|
+
import { execFile as execFile7 } from "node:child_process";
|
|
23502
23853
|
function parentMessagePort() {
|
|
23503
23854
|
const { parentPort } = process;
|
|
23504
23855
|
return parentPort && typeof parentPort.postMessage === "function" ? parentPort : null;
|
|
@@ -23511,7 +23862,7 @@ function showNotification(title, body, nav, historyId) {
|
|
|
23511
23862
|
return;
|
|
23512
23863
|
}
|
|
23513
23864
|
if (process.platform === "darwin") {
|
|
23514
|
-
|
|
23865
|
+
execFile7(
|
|
23515
23866
|
"osascript",
|
|
23516
23867
|
["-e", `display notification "${escapeAppleScript(body)}" with title "${escapeAppleScript(title)}"`],
|
|
23517
23868
|
// This is the standalone server's only desktop channel, so a silent
|
|
@@ -23554,7 +23905,7 @@ var init_notifications2 = __esm({
|
|
|
23554
23905
|
// ../../server/lib/pushConfig.ts
|
|
23555
23906
|
import { readFileSync as readFileSync3, statSync as statSync3 } from "node:fs";
|
|
23556
23907
|
import { homedir as homedir9 } from "node:os";
|
|
23557
|
-
import { join as
|
|
23908
|
+
import { join as join24 } from "node:path";
|
|
23558
23909
|
function warnOnce(message) {
|
|
23559
23910
|
if (lastWarning === message) return;
|
|
23560
23911
|
lastWarning = message;
|
|
@@ -23614,7 +23965,7 @@ function normalizeBaseUrl(value, label) {
|
|
|
23614
23965
|
}
|
|
23615
23966
|
return parsed.toString().replace(/\/+$/, "");
|
|
23616
23967
|
}
|
|
23617
|
-
function
|
|
23968
|
+
function resolve16(path) {
|
|
23618
23969
|
const file = readConfigFile(path);
|
|
23619
23970
|
const topic = asString(process.env.COGPIT_NTFY_TOPIC) ?? asString(file.topic);
|
|
23620
23971
|
if (!topic) return null;
|
|
@@ -23642,14 +23993,14 @@ function getPushConfig(path = PUSH_CONFIG_FILE) {
|
|
|
23642
23993
|
process.env.COGPIT_PUBLIC_URL
|
|
23643
23994
|
].join("\0");
|
|
23644
23995
|
if (cache3?.key === key2) return cache3.config;
|
|
23645
|
-
const config =
|
|
23996
|
+
const config = resolve16(path);
|
|
23646
23997
|
cache3 = { key: key2, config };
|
|
23647
23998
|
return config;
|
|
23648
23999
|
}
|
|
23649
24000
|
var PUSH_CONFIG_FILE, DEFAULT_NTFY_URL, TOPIC_PATTERN, cache3, lastWarning;
|
|
23650
24001
|
var init_pushConfig = __esm({
|
|
23651
24002
|
"../../server/lib/pushConfig.ts"() {
|
|
23652
|
-
PUSH_CONFIG_FILE =
|
|
24003
|
+
PUSH_CONFIG_FILE = join24(homedir9(), ".cogpit", "push.json");
|
|
23653
24004
|
DEFAULT_NTFY_URL = "https://ntfy.sh";
|
|
23654
24005
|
TOPIC_PATTERN = /^[-_A-Za-z0-9]{1,64}$/;
|
|
23655
24006
|
cache3 = null;
|
|
@@ -24264,22 +24615,22 @@ async function handleBackgroundTasks(req, res, next) {
|
|
|
24264
24615
|
const portAlive = {};
|
|
24265
24616
|
await Promise.all(
|
|
24266
24617
|
allPorts.map(
|
|
24267
|
-
(port) => new Promise((
|
|
24618
|
+
(port) => new Promise((resolve22) => {
|
|
24268
24619
|
const socket = createConnection({ port, host: "127.0.0.1" });
|
|
24269
24620
|
socket.setTimeout(500);
|
|
24270
24621
|
socket.on("connect", () => {
|
|
24271
24622
|
portAlive[port] = true;
|
|
24272
24623
|
socket.destroy();
|
|
24273
|
-
|
|
24624
|
+
resolve22();
|
|
24274
24625
|
});
|
|
24275
24626
|
socket.on("timeout", () => {
|
|
24276
24627
|
portAlive[port] = false;
|
|
24277
24628
|
socket.destroy();
|
|
24278
|
-
|
|
24629
|
+
resolve22();
|
|
24279
24630
|
});
|
|
24280
24631
|
socket.on("error", () => {
|
|
24281
24632
|
portAlive[port] = false;
|
|
24282
|
-
|
|
24633
|
+
resolve22();
|
|
24283
24634
|
});
|
|
24284
24635
|
})
|
|
24285
24636
|
)
|
|
@@ -24383,14 +24734,14 @@ var init_backgroundAgents = __esm({
|
|
|
24383
24734
|
|
|
24384
24735
|
// ../../server/routes/ports/listeningProcesses.ts
|
|
24385
24736
|
function runCapture(command, args) {
|
|
24386
|
-
return new Promise((
|
|
24737
|
+
return new Promise((resolve22, reject) => {
|
|
24387
24738
|
const child = spawn2(command, args);
|
|
24388
24739
|
let stdout = "";
|
|
24389
24740
|
child.stdout?.on("data", (data) => {
|
|
24390
24741
|
stdout += data.toString();
|
|
24391
24742
|
});
|
|
24392
24743
|
child.on("error", reject);
|
|
24393
|
-
child.on("close", () =>
|
|
24744
|
+
child.on("close", () => resolve22(stdout));
|
|
24394
24745
|
});
|
|
24395
24746
|
}
|
|
24396
24747
|
async function findListeningPids(port) {
|
|
@@ -24430,22 +24781,22 @@ function registerPortRoutes(use) {
|
|
|
24430
24781
|
const results = {};
|
|
24431
24782
|
await Promise.all(
|
|
24432
24783
|
ports.map(
|
|
24433
|
-
(port) => new Promise((
|
|
24784
|
+
(port) => new Promise((resolve22) => {
|
|
24434
24785
|
const socket = createConnection({ port, host: "127.0.0.1" });
|
|
24435
24786
|
socket.setTimeout(500);
|
|
24436
24787
|
socket.on("connect", () => {
|
|
24437
24788
|
results[port] = true;
|
|
24438
24789
|
socket.destroy();
|
|
24439
|
-
|
|
24790
|
+
resolve22();
|
|
24440
24791
|
});
|
|
24441
24792
|
socket.on("timeout", () => {
|
|
24442
24793
|
results[port] = false;
|
|
24443
24794
|
socket.destroy();
|
|
24444
|
-
|
|
24795
|
+
resolve22();
|
|
24445
24796
|
});
|
|
24446
24797
|
socket.on("error", () => {
|
|
24447
24798
|
results[port] = false;
|
|
24448
|
-
|
|
24799
|
+
resolve22();
|
|
24449
24800
|
});
|
|
24450
24801
|
})
|
|
24451
24802
|
)
|
|
@@ -24515,8 +24866,8 @@ var init_ports2 = __esm({
|
|
|
24515
24866
|
|
|
24516
24867
|
// ../../server/routes/project-file.ts
|
|
24517
24868
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
24518
|
-
import { readFile as
|
|
24519
|
-
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";
|
|
24520
24871
|
function readBody(req) {
|
|
24521
24872
|
return new Promise((resolveBody, reject) => {
|
|
24522
24873
|
let body = "";
|
|
@@ -24534,26 +24885,26 @@ function readBody(req) {
|
|
|
24534
24885
|
});
|
|
24535
24886
|
}
|
|
24536
24887
|
async function resolveProjectFile(cwd, filePath) {
|
|
24537
|
-
if (!
|
|
24538
|
-
if (!filePath ||
|
|
24888
|
+
if (!isAbsolute11(cwd)) throw new ProjectFileError(400, "cwd must be an absolute path");
|
|
24889
|
+
if (!filePath || isAbsolute11(filePath) || filePath.includes("\0")) {
|
|
24539
24890
|
throw new ProjectFileError(400, "path must be a relative project file");
|
|
24540
24891
|
}
|
|
24541
24892
|
let root;
|
|
24542
24893
|
try {
|
|
24543
|
-
root = await
|
|
24894
|
+
root = await realpath10(resolve17(cwd));
|
|
24544
24895
|
} catch {
|
|
24545
24896
|
throw new ProjectFileError(404, "Project directory not found");
|
|
24546
24897
|
}
|
|
24547
|
-
const candidate =
|
|
24898
|
+
const candidate = resolve17(root, filePath);
|
|
24548
24899
|
if (!isWithinDir(root, candidate)) throw new ProjectFileError(403, "File is outside the project");
|
|
24549
24900
|
let absolutePath;
|
|
24550
24901
|
try {
|
|
24551
|
-
absolutePath = await
|
|
24902
|
+
absolutePath = await realpath10(candidate);
|
|
24552
24903
|
} catch {
|
|
24553
24904
|
throw new ProjectFileError(404, "File not found");
|
|
24554
24905
|
}
|
|
24555
24906
|
if (!isWithinDir(root, absolutePath)) throw new ProjectFileError(403, "File is outside the project");
|
|
24556
|
-
const info = await
|
|
24907
|
+
const info = await stat16(absolutePath);
|
|
24557
24908
|
if (!info.isFile()) throw new ProjectFileError(400, "Path must point to a file");
|
|
24558
24909
|
if (info.size > MAX_FILE_BYTES) throw new ProjectFileError(413, "File is larger than 2 MB");
|
|
24559
24910
|
return { absolutePath, info };
|
|
@@ -24573,14 +24924,14 @@ function decodeTextFile(buffer) {
|
|
|
24573
24924
|
}
|
|
24574
24925
|
}
|
|
24575
24926
|
async function writeAtomically(absolutePath, content, mode, expectedMtimeMs) {
|
|
24576
|
-
const latest = await
|
|
24927
|
+
const latest = await stat16(absolutePath);
|
|
24577
24928
|
if (latest.mtimeMs !== expectedMtimeMs) {
|
|
24578
24929
|
throw new ProjectFileError(409, "File changed on disk. Reload it before saving.");
|
|
24579
24930
|
}
|
|
24580
|
-
const temporaryPath =
|
|
24931
|
+
const temporaryPath = resolve17(dirname10(absolutePath), `.${randomUUID5()}.cogpit-save`);
|
|
24581
24932
|
try {
|
|
24582
24933
|
await writeFile6(temporaryPath, content, { encoding: "utf-8", mode });
|
|
24583
|
-
const beforeRename = await
|
|
24934
|
+
const beforeRename = await stat16(absolutePath);
|
|
24584
24935
|
if (beforeRename.mtimeMs !== expectedMtimeMs) {
|
|
24585
24936
|
throw new ProjectFileError(409, "File changed on disk. Reload it before saving.");
|
|
24586
24937
|
}
|
|
@@ -24597,7 +24948,7 @@ function registerProjectFileContentRoutes(use) {
|
|
|
24597
24948
|
const filePath = url.searchParams.get("path") ?? "";
|
|
24598
24949
|
try {
|
|
24599
24950
|
const file = await resolveProjectFile(cwd, filePath);
|
|
24600
|
-
const buffer = await
|
|
24951
|
+
const buffer = await readFile18(file.absolutePath);
|
|
24601
24952
|
return sendJson(res, 200, {
|
|
24602
24953
|
content: decodeTextFile(buffer),
|
|
24603
24954
|
mtimeMs: file.info.mtimeMs,
|
|
@@ -24621,7 +24972,7 @@ function registerProjectFileContentRoutes(use) {
|
|
|
24621
24972
|
throw new ProjectFileError(409, "File changed on disk. Reload it before saving.");
|
|
24622
24973
|
}
|
|
24623
24974
|
await writeAtomically(file.absolutePath, body.content, file.info.mode, body.expectedMtimeMs);
|
|
24624
|
-
const saved = await
|
|
24975
|
+
const saved = await stat16(file.absolutePath);
|
|
24625
24976
|
return sendJson(res, 200, { ok: true, mtimeMs: saved.mtimeMs, size: saved.size });
|
|
24626
24977
|
} catch (error) {
|
|
24627
24978
|
return respondWithError(res, error);
|
|
@@ -24671,13 +25022,13 @@ var init_project_files_ranking = __esm({
|
|
|
24671
25022
|
});
|
|
24672
25023
|
|
|
24673
25024
|
// ../../server/routes/project-files.ts
|
|
24674
|
-
import { execFile as
|
|
24675
|
-
import { readdir as readdir11, realpath as
|
|
24676
|
-
import { isAbsolute as
|
|
24677
|
-
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";
|
|
24678
25029
|
async function listGitProjectFiles(root) {
|
|
24679
25030
|
try {
|
|
24680
|
-
const result = await
|
|
25031
|
+
const result = await execFile8(
|
|
24681
25032
|
"git",
|
|
24682
25033
|
["ls-files", "--cached", "--others", "--exclude-standard", "-z", "--", "."],
|
|
24683
25034
|
{
|
|
@@ -24713,7 +25064,7 @@ async function listProjectFiles(root, { skipCache = false } = {}) {
|
|
|
24713
25064
|
}
|
|
24714
25065
|
for (const entry of entries3) {
|
|
24715
25066
|
if (entry.isSymbolicLink()) continue;
|
|
24716
|
-
const absolutePath =
|
|
25067
|
+
const absolutePath = resolve18(directory, entry.name);
|
|
24717
25068
|
if (entry.isDirectory()) {
|
|
24718
25069
|
if (!IGNORED_DIRECTORIES.has(entry.name)) pending.push(absolutePath);
|
|
24719
25070
|
continue;
|
|
@@ -24735,12 +25086,12 @@ function registerProjectFileRoutes(use) {
|
|
|
24735
25086
|
const query4 = url.searchParams.get("q") ?? "";
|
|
24736
25087
|
const limit = Math.min(Math.max(Number(url.searchParams.get("limit")) || 30, 1), 100);
|
|
24737
25088
|
const skipCache = url.searchParams.get("refresh") === "1";
|
|
24738
|
-
if (!
|
|
24739
|
-
let root =
|
|
25089
|
+
if (!isAbsolute12(cwd)) return sendJson(res, 400, { error: "cwd must be an absolute path" });
|
|
25090
|
+
let root = resolve18(cwd);
|
|
24740
25091
|
try {
|
|
24741
|
-
const info = await
|
|
25092
|
+
const info = await stat17(root);
|
|
24742
25093
|
if (!info.isDirectory()) return sendJson(res, 400, { error: "cwd must be a directory" });
|
|
24743
|
-
root = await
|
|
25094
|
+
root = await realpath11(root);
|
|
24744
25095
|
const files = await listProjectFiles(root, { skipCache });
|
|
24745
25096
|
const ranked = rankProjectFiles(files, query4, limit);
|
|
24746
25097
|
return sendJson(res, 200, {
|
|
@@ -24753,7 +25104,7 @@ function registerProjectFileRoutes(use) {
|
|
|
24753
25104
|
}
|
|
24754
25105
|
});
|
|
24755
25106
|
}
|
|
24756
|
-
var MAX_FILES, CACHE_TTL_MS3, IGNORED_DIRECTORIES, fileCache,
|
|
25107
|
+
var MAX_FILES, CACHE_TTL_MS3, IGNORED_DIRECTORIES, fileCache, execFile8;
|
|
24757
25108
|
var init_project_files = __esm({
|
|
24758
25109
|
"../../server/routes/project-files.ts"() {
|
|
24759
25110
|
init_http();
|
|
@@ -24774,7 +25125,7 @@ var init_project_files = __esm({
|
|
|
24774
25125
|
"target"
|
|
24775
25126
|
]);
|
|
24776
25127
|
fileCache = /* @__PURE__ */ new Map();
|
|
24777
|
-
|
|
25128
|
+
execFile8 = promisify4(execFileCallback4);
|
|
24778
25129
|
}
|
|
24779
25130
|
});
|
|
24780
25131
|
|
|
@@ -24988,7 +25339,7 @@ function createCollector() {
|
|
|
24988
25339
|
return {
|
|
24989
25340
|
pullRequests,
|
|
24990
25341
|
add,
|
|
24991
|
-
record(output, command, toolCallId,
|
|
25342
|
+
record(output, command, toolCallId, timestamp2) {
|
|
24992
25343
|
const match = PR_URL.exec(output);
|
|
24993
25344
|
if (!match) return;
|
|
24994
25345
|
add({
|
|
@@ -24998,7 +25349,7 @@ function createCollector() {
|
|
|
24998
25349
|
title: extractTitle(command),
|
|
24999
25350
|
isDraft: /(?:^|\s)--draft(?:\s|$)/.test(command),
|
|
25000
25351
|
toolCallId,
|
|
25001
|
-
timestamp
|
|
25352
|
+
timestamp: timestamp2
|
|
25002
25353
|
});
|
|
25003
25354
|
}
|
|
25004
25355
|
};
|
|
@@ -25027,22 +25378,22 @@ function createPullRequestScanner() {
|
|
|
25027
25378
|
seenReferences.add(key2);
|
|
25028
25379
|
references.push(reference);
|
|
25029
25380
|
}
|
|
25030
|
-
function recordToolCall(id, input,
|
|
25381
|
+
function recordToolCall(id, input, timestamp2) {
|
|
25031
25382
|
const reference = findPullRequestReference(input);
|
|
25032
25383
|
if (reference) recordReference(reference);
|
|
25033
|
-
recordCreate(id, input,
|
|
25384
|
+
recordCreate(id, input, timestamp2);
|
|
25034
25385
|
}
|
|
25035
|
-
function recordCreate(id, input,
|
|
25386
|
+
function recordCreate(id, input, timestamp2) {
|
|
25036
25387
|
if (typeof id !== "string" || !id) return;
|
|
25037
25388
|
const command = findCreateCommand(input);
|
|
25038
|
-
if (command) openCreates.set(id, { command, timestamp });
|
|
25389
|
+
if (command) openCreates.set(id, { command, timestamp: timestamp2 });
|
|
25039
25390
|
}
|
|
25040
|
-
function recordPrLink(
|
|
25041
|
-
const url =
|
|
25042
|
-
const number =
|
|
25391
|
+
function recordPrLink(record4, timestamp2) {
|
|
25392
|
+
const url = record4.prUrl;
|
|
25393
|
+
const number = record4.prNumber;
|
|
25043
25394
|
if (typeof url !== "string" || !url) return;
|
|
25044
25395
|
if (typeof number !== "number" || !Number.isInteger(number) || number <= 0) return;
|
|
25045
|
-
const repo = typeof
|
|
25396
|
+
const repo = typeof record4.prRepository === "string" ? record4.prRepository : "";
|
|
25046
25397
|
collector.add({
|
|
25047
25398
|
url,
|
|
25048
25399
|
number,
|
|
@@ -25050,7 +25401,7 @@ function createPullRequestScanner() {
|
|
|
25050
25401
|
title: null,
|
|
25051
25402
|
isDraft: false,
|
|
25052
25403
|
toolCallId: "",
|
|
25053
|
-
timestamp
|
|
25404
|
+
timestamp: timestamp2
|
|
25054
25405
|
});
|
|
25055
25406
|
recordReference({ number, repo });
|
|
25056
25407
|
}
|
|
@@ -25077,37 +25428,37 @@ function createPullRequestScanner() {
|
|
|
25077
25428
|
if (!line.includes(GH_PR_HINT) && !line.includes(URL_HINT) && !line.includes(PR_LINK_HINT)) {
|
|
25078
25429
|
return;
|
|
25079
25430
|
}
|
|
25080
|
-
let
|
|
25431
|
+
let record4;
|
|
25081
25432
|
try {
|
|
25082
|
-
|
|
25433
|
+
record4 = JSON.parse(line);
|
|
25083
25434
|
} catch {
|
|
25084
25435
|
return;
|
|
25085
25436
|
}
|
|
25086
|
-
if (!isRecord5(
|
|
25087
|
-
const
|
|
25088
|
-
if (
|
|
25089
|
-
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);
|
|
25090
25441
|
return;
|
|
25091
25442
|
}
|
|
25092
|
-
const payload =
|
|
25443
|
+
const payload = record4.payload;
|
|
25093
25444
|
if (isRecord5(payload)) {
|
|
25094
25445
|
const type = payload.type;
|
|
25095
25446
|
if (type === "function_call" || type === "custom_tool_call") {
|
|
25096
|
-
recordToolCall(payload.call_id, parseArgs2(payload.arguments ?? payload.input),
|
|
25447
|
+
recordToolCall(payload.call_id, parseArgs2(payload.arguments ?? payload.input), timestamp2);
|
|
25097
25448
|
} else if (type === "function_call_output" || type === "custom_tool_call_output") {
|
|
25098
25449
|
recordResult(payload.call_id, payload.output, false);
|
|
25099
25450
|
}
|
|
25100
25451
|
return;
|
|
25101
25452
|
}
|
|
25102
|
-
const data =
|
|
25453
|
+
const data = record4.data;
|
|
25103
25454
|
if (isRecord5(data)) {
|
|
25104
|
-
if (
|
|
25455
|
+
if (record4.type === "tool.execution_start") {
|
|
25105
25456
|
recordToolCall(
|
|
25106
25457
|
data.toolCallId,
|
|
25107
25458
|
parseArgs2(data.arguments ?? data.input),
|
|
25108
|
-
|
|
25459
|
+
timestamp2
|
|
25109
25460
|
);
|
|
25110
|
-
} else if (
|
|
25461
|
+
} else if (record4.type === "tool.execution_complete") {
|
|
25111
25462
|
recordResult(
|
|
25112
25463
|
data.toolCallId,
|
|
25113
25464
|
data.result ?? data.output ?? data.error,
|
|
@@ -25116,12 +25467,12 @@ function createPullRequestScanner() {
|
|
|
25116
25467
|
}
|
|
25117
25468
|
return;
|
|
25118
25469
|
}
|
|
25119
|
-
const message =
|
|
25470
|
+
const message = record4.message;
|
|
25120
25471
|
if (!isRecord5(message) || !Array.isArray(message.content)) return;
|
|
25121
25472
|
for (const block of message.content) {
|
|
25122
25473
|
if (!isRecord5(block)) continue;
|
|
25123
25474
|
if (block.type === "tool_use" && isRecord5(block.input)) {
|
|
25124
|
-
recordToolCall(block.id, block.input,
|
|
25475
|
+
recordToolCall(block.id, block.input, timestamp2);
|
|
25125
25476
|
} else if (block.type === "tool_result") {
|
|
25126
25477
|
recordResult(block.tool_use_id, block.content, block.is_error === true);
|
|
25127
25478
|
}
|
|
@@ -25226,15 +25577,15 @@ var init_sessionPrIndex = __esm({
|
|
|
25226
25577
|
});
|
|
25227
25578
|
|
|
25228
25579
|
// ../../server/lib/sessionPrSearchIndex.ts
|
|
25229
|
-
import { mkdir as mkdir6, readFile as
|
|
25230
|
-
import { join as
|
|
25580
|
+
import { mkdir as mkdir6, readFile as readFile19 } from "node:fs/promises";
|
|
25581
|
+
import { join as join25 } from "node:path";
|
|
25231
25582
|
function isIndexEntry(value) {
|
|
25232
25583
|
if (typeof value !== "object" || value === null) return false;
|
|
25233
25584
|
const entry = value;
|
|
25234
25585
|
return typeof entry.size === "number" && typeof entry.mtimeMs === "number" && Array.isArray(entry.pullRequests) && Array.isArray(entry.references);
|
|
25235
25586
|
}
|
|
25236
25587
|
function currentIndexPath() {
|
|
25237
|
-
return
|
|
25588
|
+
return join25(dirs.SESSION_CONFIG_DIR, INDEX_FILE);
|
|
25238
25589
|
}
|
|
25239
25590
|
function resetForPath(indexPath) {
|
|
25240
25591
|
activeIndexPath = indexPath;
|
|
@@ -25251,7 +25602,7 @@ async function loadIndex() {
|
|
|
25251
25602
|
if (loaded) return;
|
|
25252
25603
|
if (loading) return loading;
|
|
25253
25604
|
const expectedGeneration = generation;
|
|
25254
|
-
const pendingLoad =
|
|
25605
|
+
const pendingLoad = readFile19(indexPath, "utf-8").then((raw) => {
|
|
25255
25606
|
if (expectedGeneration !== generation) return;
|
|
25256
25607
|
const parsed = JSON.parse(raw);
|
|
25257
25608
|
if (typeof parsed !== "object" || parsed === null) return;
|
|
@@ -25295,7 +25646,7 @@ async function runQueue(expectedGeneration) {
|
|
|
25295
25646
|
await persistIndex(expectedGeneration).catch(() => void 0);
|
|
25296
25647
|
sincePersist = 0;
|
|
25297
25648
|
}
|
|
25298
|
-
await new Promise((
|
|
25649
|
+
await new Promise((resolve22) => setImmediate(resolve22));
|
|
25299
25650
|
}
|
|
25300
25651
|
if (sincePersist > 0) await persistIndex(expectedGeneration).catch(() => void 0);
|
|
25301
25652
|
} finally {
|
|
@@ -26338,11 +26689,11 @@ var init_agent_executable = __esm({
|
|
|
26338
26689
|
});
|
|
26339
26690
|
|
|
26340
26691
|
// ../../server/routes/scripts/discovery.ts
|
|
26341
|
-
import { readdir as readdir12, readFile as
|
|
26342
|
-
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";
|
|
26343
26694
|
async function extractScripts(dir, dirLabel) {
|
|
26344
26695
|
try {
|
|
26345
|
-
const raw = await
|
|
26696
|
+
const raw = await readFile20(join26(dir, "package.json"), "utf-8");
|
|
26346
26697
|
const pkg = JSON.parse(raw);
|
|
26347
26698
|
const scripts = pkg.scripts;
|
|
26348
26699
|
if (!scripts || typeof scripts !== "object") return [];
|
|
@@ -26368,7 +26719,7 @@ async function discoverScripts(projectDir) {
|
|
|
26368
26719
|
);
|
|
26369
26720
|
const childResults = await Promise.all(
|
|
26370
26721
|
childDirs.map(async (entry) => {
|
|
26371
|
-
const childPath =
|
|
26722
|
+
const childPath = join26(projectDir, entry.name);
|
|
26372
26723
|
const label = relative10(projectDir, childPath) + "/";
|
|
26373
26724
|
return extractScripts(childPath, label);
|
|
26374
26725
|
})
|
|
@@ -26415,12 +26766,12 @@ var init_discovery = __esm({
|
|
|
26415
26766
|
});
|
|
26416
26767
|
|
|
26417
26768
|
// ../../server/routes/scripts/index.ts
|
|
26418
|
-
import { stat as
|
|
26419
|
-
import { resolve as
|
|
26769
|
+
import { stat as stat18 } from "node:fs/promises";
|
|
26770
|
+
import { resolve as resolve19 } from "node:path";
|
|
26420
26771
|
async function validateDir(dir) {
|
|
26421
26772
|
try {
|
|
26422
|
-
const resolved =
|
|
26423
|
-
const info = await
|
|
26773
|
+
const resolved = resolve19(dir);
|
|
26774
|
+
const info = await stat18(resolved);
|
|
26424
26775
|
return info.isDirectory() ? resolved : null;
|
|
26425
26776
|
} catch {
|
|
26426
26777
|
return null;
|
|
@@ -26485,7 +26836,7 @@ async function withTranscriptEffort(key2, stored) {
|
|
|
26485
26836
|
}
|
|
26486
26837
|
}
|
|
26487
26838
|
function collectBody(req) {
|
|
26488
|
-
return new Promise((
|
|
26839
|
+
return new Promise((resolve22, reject) => {
|
|
26489
26840
|
let body = "";
|
|
26490
26841
|
req.on("data", (chunk) => {
|
|
26491
26842
|
body += chunk.toString();
|
|
@@ -26494,7 +26845,7 @@ function collectBody(req) {
|
|
|
26494
26845
|
req.destroy();
|
|
26495
26846
|
}
|
|
26496
26847
|
});
|
|
26497
|
-
req.on("end", () =>
|
|
26848
|
+
req.on("end", () => resolve22(body));
|
|
26498
26849
|
req.on("error", reject);
|
|
26499
26850
|
});
|
|
26500
26851
|
}
|
|
@@ -26554,12 +26905,12 @@ var init_session_config = __esm({
|
|
|
26554
26905
|
|
|
26555
26906
|
// ../../server/lib/agentTeamIdentity.ts
|
|
26556
26907
|
import { open as open9, readdir as readdir13 } from "node:fs/promises";
|
|
26557
|
-
import { join as
|
|
26908
|
+
import { join as join27 } from "node:path";
|
|
26558
26909
|
async function matchSubagentToMember(leadSessionId, subagentFileName, members) {
|
|
26559
26910
|
const entries3 = await readdir13(dirs.PROJECTS_DIR, { withFileTypes: true });
|
|
26560
26911
|
for (const entry of entries3) {
|
|
26561
26912
|
if (!entry.isDirectory() || entry.name === "memory") continue;
|
|
26562
|
-
const filePath =
|
|
26913
|
+
const filePath = join27(
|
|
26563
26914
|
dirs.PROJECTS_DIR,
|
|
26564
26915
|
entry.name,
|
|
26565
26916
|
leadSessionId,
|
|
@@ -27252,7 +27603,7 @@ function normalizeCopilotFileChangeEvents(jsonlContent) {
|
|
|
27252
27603
|
}
|
|
27253
27604
|
});
|
|
27254
27605
|
}
|
|
27255
|
-
return records.map((
|
|
27606
|
+
return records.map((record4) => JSON.stringify(record4)).join("\n");
|
|
27256
27607
|
}
|
|
27257
27608
|
async function parseSessionFileChanges(jsonlContent, includeContent) {
|
|
27258
27609
|
if (formatForText(jsonlContent).kind === "copilot") {
|
|
@@ -28672,8 +29023,8 @@ var init_paths = __esm({
|
|
|
28672
29023
|
});
|
|
28673
29024
|
|
|
28674
29025
|
// ../../server/routes/undo/fileOperations.ts
|
|
28675
|
-
import { basename as basename12, dirname as dirname13, isAbsolute as
|
|
28676
|
-
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";
|
|
28677
29028
|
function hasTraversalSegment(filePath) {
|
|
28678
29029
|
return filePath.split(/[\\/]+/).includes("..");
|
|
28679
29030
|
}
|
|
@@ -28684,7 +29035,7 @@ function isForbiddenPath(filePath) {
|
|
|
28684
29035
|
return FORBIDDEN_PREFIXES.some((prefix) => isWithinDir(prefix, filePath));
|
|
28685
29036
|
}
|
|
28686
29037
|
async function resolveSafeOperationPath(filePath, home, canonicalHome) {
|
|
28687
|
-
if (typeof filePath !== "string" || !
|
|
29038
|
+
if (typeof filePath !== "string" || !isAbsolute13(filePath) || hasTraversalSegment(filePath)) {
|
|
28688
29039
|
return null;
|
|
28689
29040
|
}
|
|
28690
29041
|
const resolved = resolve7(filePath);
|
|
@@ -28692,12 +29043,12 @@ async function resolveSafeOperationPath(filePath, home, canonicalHome) {
|
|
|
28692
29043
|
try {
|
|
28693
29044
|
const stats = await lstat6(resolved);
|
|
28694
29045
|
if (stats.isSymbolicLink()) return null;
|
|
28695
|
-
const canonicalTarget = await
|
|
29046
|
+
const canonicalTarget = await realpath12(resolved);
|
|
28696
29047
|
return isWithinDir(canonicalHome, canonicalTarget) && !isForbiddenPath(canonicalTarget) ? canonicalTarget : null;
|
|
28697
29048
|
} catch (error) {
|
|
28698
29049
|
if (!isMissingPathError(error)) return null;
|
|
28699
29050
|
try {
|
|
28700
|
-
const canonicalParent = await
|
|
29051
|
+
const canonicalParent = await realpath12(dirname13(resolved));
|
|
28701
29052
|
const canonicalTarget = join11(canonicalParent, basename12(resolved));
|
|
28702
29053
|
return isWithinDir(canonicalHome, canonicalTarget) && !isForbiddenPath(canonicalTarget) ? canonicalTarget : null;
|
|
28703
29054
|
} catch {
|
|
@@ -28745,7 +29096,7 @@ async function prepareFileOperations(operationValues, options = {}) {
|
|
|
28745
29096
|
const home = resolve7(homedir4());
|
|
28746
29097
|
let canonicalHome;
|
|
28747
29098
|
try {
|
|
28748
|
-
canonicalHome = await
|
|
29099
|
+
canonicalHome = await realpath12(home);
|
|
28749
29100
|
} catch {
|
|
28750
29101
|
throw new UndoOperationError(403, "File operations restricted to home directory");
|
|
28751
29102
|
}
|
|
@@ -28949,7 +29300,7 @@ function applySessionMutation(content, mutation) {
|
|
|
28949
29300
|
` : "";
|
|
28950
29301
|
}
|
|
28951
29302
|
async function readBody2(req) {
|
|
28952
|
-
return await new Promise((
|
|
29303
|
+
return await new Promise((resolve22, reject) => {
|
|
28953
29304
|
let body = "";
|
|
28954
29305
|
let bytes = 0;
|
|
28955
29306
|
let settled = false;
|
|
@@ -28968,7 +29319,7 @@ async function readBody2(req) {
|
|
|
28968
29319
|
req.on("end", () => {
|
|
28969
29320
|
if (!settled) {
|
|
28970
29321
|
settled = true;
|
|
28971
|
-
|
|
29322
|
+
resolve22(body);
|
|
28972
29323
|
}
|
|
28973
29324
|
});
|
|
28974
29325
|
req.on("error", (error) => {
|
|
@@ -29221,20 +29572,20 @@ var init_aggregate = __esm({
|
|
|
29221
29572
|
this.#toDay = makeDayFormatter(options.timeZone);
|
|
29222
29573
|
}
|
|
29223
29574
|
/** Folds one record in; returns whether it actually contributed. */
|
|
29224
|
-
add(
|
|
29225
|
-
if (
|
|
29226
|
-
if (this.#seen.has(
|
|
29227
|
-
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);
|
|
29228
29579
|
}
|
|
29229
|
-
const day = this.#toDay(
|
|
29580
|
+
const day = this.#toDay(record4.timestampMs);
|
|
29230
29581
|
if (day < this.#options.sinceDay || day > this.#options.untilDay) return false;
|
|
29231
|
-
const key2 = [day,
|
|
29582
|
+
const key2 = [day, record4.provider, record4.model].join(KEY_SEPARATOR);
|
|
29232
29583
|
let bucket = this.#buckets.get(key2);
|
|
29233
29584
|
if (bucket === void 0) {
|
|
29234
29585
|
bucket = {
|
|
29235
29586
|
day,
|
|
29236
|
-
provider:
|
|
29237
|
-
model:
|
|
29587
|
+
provider: record4.provider,
|
|
29588
|
+
model: record4.model,
|
|
29238
29589
|
totals: emptyUsageCostTotals(),
|
|
29239
29590
|
costUsd: 0,
|
|
29240
29591
|
cacheSavingsUsd: 0,
|
|
@@ -29247,19 +29598,19 @@ var init_aggregate = __esm({
|
|
|
29247
29598
|
}
|
|
29248
29599
|
const priced = priceUsage(
|
|
29249
29600
|
this.#options.rates,
|
|
29250
|
-
|
|
29251
|
-
|
|
29252
|
-
|
|
29601
|
+
record4.model,
|
|
29602
|
+
record4.totals,
|
|
29603
|
+
record4.reportedCostUsd
|
|
29253
29604
|
);
|
|
29254
|
-
bucket.totals = addUsageCostTotals(bucket.totals,
|
|
29605
|
+
bucket.totals = addUsageCostTotals(bucket.totals, record4.totals);
|
|
29255
29606
|
bucket.costUsd += priced.costUsd;
|
|
29256
|
-
bucket.cacheSavingsUsd += cacheSavingsUsd(this.#options.rates,
|
|
29607
|
+
bucket.cacheSavingsUsd += cacheSavingsUsd(this.#options.rates, record4.model, record4.totals);
|
|
29257
29608
|
bucket.records += 1;
|
|
29258
29609
|
if (priced.costSource === "unpriced") bucket.unpricedRecords += 1;
|
|
29259
29610
|
if (priced.costSource === "providerReported") bucket.providerReportedRecords += 1;
|
|
29260
|
-
if (
|
|
29261
|
-
bucket.sessions.add(
|
|
29262
|
-
this.#sessions.add(
|
|
29611
|
+
if (record4.sessionId.length > 0) {
|
|
29612
|
+
bucket.sessions.add(record4.sessionId);
|
|
29613
|
+
this.#sessions.add(record4.sessionId);
|
|
29263
29614
|
}
|
|
29264
29615
|
return true;
|
|
29265
29616
|
}
|
|
@@ -29289,8 +29640,8 @@ var init_aggregate = __esm({
|
|
|
29289
29640
|
|
|
29290
29641
|
// ../../server/lib/usageCost/reader.ts
|
|
29291
29642
|
import { createReadStream as createReadStream3 } from "node:fs";
|
|
29292
|
-
import { readdir as readdir14, stat as
|
|
29293
|
-
import { join as
|
|
29643
|
+
import { readdir as readdir14, stat as stat19 } from "node:fs/promises";
|
|
29644
|
+
import { join as join28 } from "node:path";
|
|
29294
29645
|
import { createInterface as createInterface3 } from "node:readline";
|
|
29295
29646
|
async function listTranscriptFiles(root, sinceMs) {
|
|
29296
29647
|
const found = [];
|
|
@@ -29302,14 +29653,14 @@ async function listTranscriptFiles(root, sinceMs) {
|
|
|
29302
29653
|
return;
|
|
29303
29654
|
}
|
|
29304
29655
|
for (const entry of entries3) {
|
|
29305
|
-
const child =
|
|
29656
|
+
const child = join28(dir, entry.name);
|
|
29306
29657
|
if (entry.isDirectory()) {
|
|
29307
29658
|
await walk2(child);
|
|
29308
29659
|
continue;
|
|
29309
29660
|
}
|
|
29310
29661
|
if (!entry.name.endsWith(".jsonl")) continue;
|
|
29311
29662
|
try {
|
|
29312
|
-
const stats = await
|
|
29663
|
+
const stats = await stat19(child);
|
|
29313
29664
|
if (stats.mtimeMs >= sinceMs) {
|
|
29314
29665
|
found.push({ path: child, size: stats.size, mtimeMs: stats.mtimeMs });
|
|
29315
29666
|
}
|
|
@@ -29340,17 +29691,17 @@ async function readTranscriptRecords(filePath, provider) {
|
|
|
29340
29691
|
function dedupeWithinFile(records) {
|
|
29341
29692
|
const slotByKey = /* @__PURE__ */ new Map();
|
|
29342
29693
|
const kept = [];
|
|
29343
|
-
for (const
|
|
29344
|
-
if (
|
|
29345
|
-
kept.push(
|
|
29694
|
+
for (const record4 of records) {
|
|
29695
|
+
if (record4.dedupeKey === null) {
|
|
29696
|
+
kept.push(record4);
|
|
29346
29697
|
continue;
|
|
29347
29698
|
}
|
|
29348
|
-
const slot = slotByKey.get(
|
|
29699
|
+
const slot = slotByKey.get(record4.dedupeKey);
|
|
29349
29700
|
if (slot === void 0) {
|
|
29350
|
-
slotByKey.set(
|
|
29701
|
+
slotByKey.set(record4.dedupeKey, kept.push(record4) - 1);
|
|
29351
29702
|
continue;
|
|
29352
29703
|
}
|
|
29353
|
-
if (
|
|
29704
|
+
if (record4.totals.outputTokens > kept[slot].totals.outputTokens) kept[slot] = record4;
|
|
29354
29705
|
}
|
|
29355
29706
|
return kept;
|
|
29356
29707
|
}
|
|
@@ -29361,10 +29712,10 @@ var init_reader = __esm({
|
|
|
29361
29712
|
});
|
|
29362
29713
|
|
|
29363
29714
|
// ../../server/lib/usageCost/service.ts
|
|
29364
|
-
import { readFile as
|
|
29365
|
-
import { join as
|
|
29715
|
+
import { readFile as readFile21, writeFile as writeFile7 } from "node:fs/promises";
|
|
29716
|
+
import { join as join29 } from "node:path";
|
|
29366
29717
|
function ratesCachePath() {
|
|
29367
|
-
return
|
|
29718
|
+
return join29(getDataRoot(), "usage-model-rates.json");
|
|
29368
29719
|
}
|
|
29369
29720
|
function ratesFetchedAt() {
|
|
29370
29721
|
return ratesFetchedAtMs === null ? null : new Date(ratesFetchedAtMs).toISOString();
|
|
@@ -29374,7 +29725,7 @@ async function ensureRatesInner() {
|
|
|
29374
29725
|
if (ratesFetchedAtMs !== null && now - ratesFetchedAtMs < RATES_TTL_MS) return;
|
|
29375
29726
|
if (ratesFetchedAtMs === null) {
|
|
29376
29727
|
try {
|
|
29377
|
-
const raw = JSON.parse(await
|
|
29728
|
+
const raw = JSON.parse(await readFile21(ratesCachePath(), "utf8"));
|
|
29378
29729
|
if (typeof raw.fetchedAtMs === "number") {
|
|
29379
29730
|
const parsed2 = parseRateTable(raw.document);
|
|
29380
29731
|
if (parsed2.size > 0) {
|
|
@@ -29459,23 +29810,23 @@ async function readUsageCostSummary(input) {
|
|
|
29459
29810
|
for (const file of files) {
|
|
29460
29811
|
const records = await readFileRecords(file, provider);
|
|
29461
29812
|
scannedFiles += 1;
|
|
29462
|
-
for (const
|
|
29463
|
-
aggregator.add(
|
|
29464
|
-
if (!liveSessionIds.has(
|
|
29465
|
-
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();
|
|
29466
29817
|
byModel.set(
|
|
29467
|
-
|
|
29818
|
+
record4.model,
|
|
29468
29819
|
addUsageCostTotals(
|
|
29469
|
-
byModel.get(
|
|
29470
|
-
|
|
29820
|
+
byModel.get(record4.model) ?? emptyUsageCostTotals(),
|
|
29821
|
+
record4.totals
|
|
29471
29822
|
)
|
|
29472
29823
|
);
|
|
29473
|
-
durableTotals.set(
|
|
29824
|
+
durableTotals.set(record4.sessionId, byModel);
|
|
29474
29825
|
}
|
|
29475
29826
|
}
|
|
29476
29827
|
}
|
|
29477
29828
|
for (const runtime of runtimes2) {
|
|
29478
|
-
for (const
|
|
29829
|
+
for (const record4 of await runtime.liveUsageRecords(durableTotals)) aggregator.add(record4);
|
|
29479
29830
|
}
|
|
29480
29831
|
const retentionCutoffMs = startedAtMs - 90 * 24 * 60 * 60 * 1e3;
|
|
29481
29832
|
for (const [path, entry] of fileCache2) {
|
|
@@ -29561,12 +29912,12 @@ async function readKeychainCredentials() {
|
|
|
29561
29912
|
if (process.platform !== "darwin") {
|
|
29562
29913
|
return null;
|
|
29563
29914
|
}
|
|
29564
|
-
return new Promise((
|
|
29915
|
+
return new Promise((resolve22) => {
|
|
29565
29916
|
let resolved = false;
|
|
29566
29917
|
const done = (value) => {
|
|
29567
29918
|
if (resolved) return;
|
|
29568
29919
|
resolved = true;
|
|
29569
|
-
|
|
29920
|
+
resolve22(value);
|
|
29570
29921
|
};
|
|
29571
29922
|
const child = spawn3("/usr/bin/security", [
|
|
29572
29923
|
"find-generic-password",
|
|
@@ -30202,8 +30553,8 @@ var init_workflows2 = __esm({
|
|
|
30202
30553
|
});
|
|
30203
30554
|
|
|
30204
30555
|
// ../../server/routes/worktrees/worktreeIo.ts
|
|
30205
|
-
import { execFile as
|
|
30206
|
-
import { promisify as
|
|
30556
|
+
import { execFile as execFile9 } from "node:child_process";
|
|
30557
|
+
import { promisify as promisify5 } from "node:util";
|
|
30207
30558
|
async function runWorktreeCommand(file, args, { cwd, timeoutMs = WORKTREE_COMMAND_TIMEOUT_MS }) {
|
|
30208
30559
|
const result = await execFileAsync(file, [...args], {
|
|
30209
30560
|
cwd,
|
|
@@ -30242,7 +30593,7 @@ var init_worktreeIo = __esm({
|
|
|
30242
30593
|
WORKTREE_COMMAND_MAX_BUFFER = 4 * 1024 * 1024;
|
|
30243
30594
|
WORKTREE_SCAN_CONCURRENCY = 4;
|
|
30244
30595
|
SESSION_HEADER_CONCURRENCY = 8;
|
|
30245
|
-
execFileAsync =
|
|
30596
|
+
execFileAsync = promisify5(execFile9);
|
|
30246
30597
|
NONINTERACTIVE_ENV = {
|
|
30247
30598
|
...process.env,
|
|
30248
30599
|
GCM_INTERACTIVE: "Never",
|
|
@@ -30255,7 +30606,7 @@ var init_worktreeIo = __esm({
|
|
|
30255
30606
|
});
|
|
30256
30607
|
|
|
30257
30608
|
// ../../server/routes/worktrees/worktreeUtils.ts
|
|
30258
|
-
import { resolve as
|
|
30609
|
+
import { resolve as resolve20, dirname as dirname14 } from "node:path";
|
|
30259
30610
|
function isValidWorktreeName(name) {
|
|
30260
30611
|
return /^[a-zA-Z0-9._-]+$/.test(name) && name.length <= 40;
|
|
30261
30612
|
}
|
|
@@ -30318,7 +30669,7 @@ async function getMainWorktreeRoot(projectPath) {
|
|
|
30318
30669
|
const commonDir = (await runWorktreeCommand("git", ["rev-parse", "--git-common-dir"], {
|
|
30319
30670
|
cwd: projectPath
|
|
30320
30671
|
})).trim();
|
|
30321
|
-
return dirname14(
|
|
30672
|
+
return dirname14(resolve20(projectPath, commonDir));
|
|
30322
30673
|
} catch {
|
|
30323
30674
|
return null;
|
|
30324
30675
|
}
|
|
@@ -30343,7 +30694,7 @@ var init_worktreeUtils = __esm({
|
|
|
30343
30694
|
});
|
|
30344
30695
|
|
|
30345
30696
|
// ../../server/routes/worktrees/worktreeListRoute.ts
|
|
30346
|
-
import { stat as
|
|
30697
|
+
import { stat as stat20 } from "node:fs/promises";
|
|
30347
30698
|
async function loadSessionBranches(projectDir) {
|
|
30348
30699
|
const sessionBranches = /* @__PURE__ */ new Map();
|
|
30349
30700
|
try {
|
|
@@ -30458,7 +30809,7 @@ async function buildWorktreeInfo(worktree, defaultBranch, sessionBranches) {
|
|
|
30458
30809
|
}
|
|
30459
30810
|
let createdAt = "";
|
|
30460
30811
|
try {
|
|
30461
|
-
createdAt = (await
|
|
30812
|
+
createdAt = (await stat20(worktree.path)).birthtime.toISOString();
|
|
30462
30813
|
} catch {
|
|
30463
30814
|
}
|
|
30464
30815
|
return {
|
|
@@ -30519,9 +30870,9 @@ var init_worktreeListRoute = __esm({
|
|
|
30519
30870
|
});
|
|
30520
30871
|
|
|
30521
30872
|
// ../../server/routes/worktrees/index.ts
|
|
30522
|
-
import { stat as
|
|
30873
|
+
import { stat as stat21 } from "node:fs/promises";
|
|
30523
30874
|
async function readJsonRequestBody(req) {
|
|
30524
|
-
const body = await new Promise((
|
|
30875
|
+
const body = await new Promise((resolve22, reject) => {
|
|
30525
30876
|
let data = "";
|
|
30526
30877
|
let bytesRead = 0;
|
|
30527
30878
|
let settled = false;
|
|
@@ -30538,7 +30889,7 @@ async function readJsonRequestBody(req) {
|
|
|
30538
30889
|
req.on("end", () => {
|
|
30539
30890
|
if (!settled) {
|
|
30540
30891
|
settled = true;
|
|
30541
|
-
|
|
30892
|
+
resolve22(data);
|
|
30542
30893
|
}
|
|
30543
30894
|
});
|
|
30544
30895
|
req.on("error", () => {
|
|
@@ -30589,7 +30940,7 @@ async function findStaleWorktrees(worktrees, cutoff) {
|
|
|
30589
30940
|
cwd: worktree.path
|
|
30590
30941
|
});
|
|
30591
30942
|
if (status.trim()) return null;
|
|
30592
|
-
const worktreeStat = await
|
|
30943
|
+
const worktreeStat = await stat21(worktree.path);
|
|
30593
30944
|
return worktreeStat.birthtime.getTime() < cutoff ? worktree : null;
|
|
30594
30945
|
} catch {
|
|
30595
30946
|
return null;
|
|
@@ -30831,6 +31182,7 @@ var init_api_routes = __esm({
|
|
|
30831
31182
|
init_git_diff();
|
|
30832
31183
|
init_git_status();
|
|
30833
31184
|
init_github_actions();
|
|
31185
|
+
init_vercel_deployments();
|
|
30834
31186
|
init_project_icon();
|
|
30835
31187
|
init_hello();
|
|
30836
31188
|
init_local_file();
|
|
@@ -30901,6 +31253,7 @@ var init_api_routes = __esm({
|
|
|
30901
31253
|
apiRoute("project-file", registerProjectFileContentRoutes),
|
|
30902
31254
|
apiRoute("git-status", registerGitStatusRoutes),
|
|
30903
31255
|
apiRoute("github-actions", registerGitHubActionsRoutes),
|
|
31256
|
+
apiRoute("vercel-deployments", registerVercelDeploymentRoutes),
|
|
30904
31257
|
apiRoute("project-icon", registerProjectIconRoutes),
|
|
30905
31258
|
apiRoute("git-diff", registerGitDiffRoutes),
|
|
30906
31259
|
apiRoute("mcp", registerMcpRoutes),
|
|
@@ -31331,18 +31684,18 @@ var init_pty_authorization = __esm({
|
|
|
31331
31684
|
// ../../server/app-server.ts
|
|
31332
31685
|
import express from "express";
|
|
31333
31686
|
import { createServer, request as httpRequest2 } from "node:http";
|
|
31334
|
-
import { join as
|
|
31687
|
+
import { join as join30 } from "node:path";
|
|
31335
31688
|
import { WebSocketServer as WebSocketServer2 } from "ws";
|
|
31336
31689
|
async function createServerComposition(staticDir, userDataDir, environment) {
|
|
31337
31690
|
setDataRoot(userDataDir);
|
|
31338
|
-
setConfigPath(
|
|
31691
|
+
setConfigPath(join30(userDataDir, "config.local.json"));
|
|
31339
31692
|
await loadConfig();
|
|
31340
31693
|
const configEdition = getConfiguredEditionValue();
|
|
31341
31694
|
initEdition({ shell: environment.mode, configEdition });
|
|
31342
31695
|
const suppression = describeEditionSuppression(process.env, configEdition, environment.mode);
|
|
31343
31696
|
if (suppression) console.warn(suppression);
|
|
31344
31697
|
if (isTeamEdition()) {
|
|
31345
|
-
const teamDir =
|
|
31698
|
+
const teamDir = join30(getDataRoot(), "team");
|
|
31346
31699
|
await initUsersStore(teamDir);
|
|
31347
31700
|
await initSessionPersistence(teamDir);
|
|
31348
31701
|
initializeBootstrapToken(userCount());
|
|
@@ -31453,7 +31806,7 @@ async function createServerComposition(staticDir, userDataDir, environment) {
|
|
|
31453
31806
|
for (const socket of upgradedSockets) socket.destroy();
|
|
31454
31807
|
upgradedSockets.clear();
|
|
31455
31808
|
await Promise.all([
|
|
31456
|
-
new Promise((
|
|
31809
|
+
new Promise((resolve22) => wss.close(() => resolve22())),
|
|
31457
31810
|
cleanupProcesses(),
|
|
31458
31811
|
...allRuntimes().map((runtime) => runtime.shutdown()),
|
|
31459
31812
|
flushSessionPersistence()
|
|
@@ -31465,8 +31818,8 @@ async function createServerComposition(staticDir, userDataDir, environment) {
|
|
|
31465
31818
|
void cleanupRuntime();
|
|
31466
31819
|
});
|
|
31467
31820
|
const dispose = async () => {
|
|
31468
|
-
const serverClosed = httpServer.listening ? new Promise((
|
|
31469
|
-
httpServer.close((error) => error ? reject(error) :
|
|
31821
|
+
const serverClosed = httpServer.listening ? new Promise((resolve22, reject) => {
|
|
31822
|
+
httpServer.close((error) => error ? reject(error) : resolve22());
|
|
31470
31823
|
}) : Promise.resolve();
|
|
31471
31824
|
await cleanupRuntime();
|
|
31472
31825
|
await serverClosed;
|
|
@@ -31513,7 +31866,7 @@ var init_standalone_app_server = __esm({
|
|
|
31513
31866
|
// ../../server/lib/portFile.ts
|
|
31514
31867
|
import { mkdirSync as mkdirSync2, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
31515
31868
|
import { homedir as homedir12 } from "node:os";
|
|
31516
|
-
import { dirname as dirname15, join as
|
|
31869
|
+
import { dirname as dirname15, join as join31 } from "node:path";
|
|
31517
31870
|
function writePortFile(port) {
|
|
31518
31871
|
try {
|
|
31519
31872
|
mkdirSync2(dirname15(PORT_FILE), { recursive: true });
|
|
@@ -31533,7 +31886,7 @@ function removePortFile() {
|
|
|
31533
31886
|
var PORT_FILE;
|
|
31534
31887
|
var init_portFile = __esm({
|
|
31535
31888
|
"../../server/lib/portFile.ts"() {
|
|
31536
|
-
PORT_FILE =
|
|
31889
|
+
PORT_FILE = join31(homedir12(), ".cogpit", "port");
|
|
31537
31890
|
}
|
|
31538
31891
|
});
|
|
31539
31892
|
|
|
@@ -31782,9 +32135,9 @@ __export(standalone_runtime_exports, {
|
|
|
31782
32135
|
});
|
|
31783
32136
|
import { existsSync, mkdirSync as mkdirSync3 } from "node:fs";
|
|
31784
32137
|
import { homedir as homedir13 } from "node:os";
|
|
31785
|
-
import { join as
|
|
32138
|
+
import { join as join32 } from "node:path";
|
|
31786
32139
|
function listen(server, port, host) {
|
|
31787
|
-
return new Promise((
|
|
32140
|
+
return new Promise((resolve22, reject) => {
|
|
31788
32141
|
const onError = (error) => reject(error);
|
|
31789
32142
|
server.once("error", onError);
|
|
31790
32143
|
server.listen(port, host, () => {
|
|
@@ -31794,27 +32147,27 @@ function listen(server, port, host) {
|
|
|
31794
32147
|
reject(new Error("Cogpit started without a listening address."));
|
|
31795
32148
|
return;
|
|
31796
32149
|
}
|
|
31797
|
-
|
|
32150
|
+
resolve22(address.port);
|
|
31798
32151
|
});
|
|
31799
32152
|
});
|
|
31800
32153
|
}
|
|
31801
32154
|
async function startStandaloneServer({
|
|
31802
32155
|
staticDir,
|
|
31803
|
-
dataDir =
|
|
32156
|
+
dataDir = join32(homedir13(), ".config", "cogpit"),
|
|
31804
32157
|
host = "127.0.0.1",
|
|
31805
32158
|
port = 19384,
|
|
31806
32159
|
env = process.env,
|
|
31807
32160
|
publishPort = false
|
|
31808
32161
|
}) {
|
|
31809
32162
|
mkdirSync3(dataDir, { recursive: true });
|
|
31810
|
-
const configPath =
|
|
32163
|
+
const configPath = join32(dataDir, "config.local.json");
|
|
31811
32164
|
setConfigPath(configPath);
|
|
31812
32165
|
const configExisted = existsSync(configPath);
|
|
31813
32166
|
await loadConfig();
|
|
31814
32167
|
let createdConfig;
|
|
31815
32168
|
if (!configExisted) {
|
|
31816
|
-
const claudeDir =
|
|
31817
|
-
if (existsSync(
|
|
32169
|
+
const claudeDir = join32(homedir13(), ".claude");
|
|
32170
|
+
if (existsSync(join32(claudeDir, "projects"))) {
|
|
31818
32171
|
await saveConfig({ claudeDir });
|
|
31819
32172
|
createdConfig = `${configPath} for ${claudeDir}`;
|
|
31820
32173
|
}
|
|
@@ -31887,7 +32240,7 @@ var init_standalone_runtime = __esm({
|
|
|
31887
32240
|
// src/index.ts
|
|
31888
32241
|
import { spawn as spawn4 } from "node:child_process";
|
|
31889
32242
|
import { homedir as homedir14 } from "node:os";
|
|
31890
|
-
import { join as
|
|
32243
|
+
import { join as join33, resolve as resolve21 } from "node:path";
|
|
31891
32244
|
var SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/;
|
|
31892
32245
|
var USAGE = `Cogpit
|
|
31893
32246
|
|
|
@@ -31954,7 +32307,7 @@ function parseArgs(argv) {
|
|
|
31954
32307
|
if (value === "--data-dir") {
|
|
31955
32308
|
const path = argv[index + 1];
|
|
31956
32309
|
if (!path) throw new Error("--data-dir requires a directory.");
|
|
31957
|
-
dataDir =
|
|
32310
|
+
dataDir = resolve21(path);
|
|
31958
32311
|
index += 1;
|
|
31959
32312
|
continue;
|
|
31960
32313
|
}
|
|
@@ -31996,8 +32349,8 @@ async function openExternalUrl(url) {
|
|
|
31996
32349
|
async function startPackagedServer(options) {
|
|
31997
32350
|
const { startStandaloneServer: startStandaloneServer2 } = await Promise.resolve().then(() => (init_standalone_runtime(), standalone_runtime_exports));
|
|
31998
32351
|
return startStandaloneServer2({
|
|
31999
|
-
staticDir:
|
|
32000
|
-
dataDir: options.dataDir ??
|
|
32352
|
+
staticDir: join33(import.meta.dirname, "web"),
|
|
32353
|
+
dataDir: options.dataDir ?? join33(homedir14(), ".config", "cogpit"),
|
|
32001
32354
|
host: "127.0.0.1",
|
|
32002
32355
|
port: options.port,
|
|
32003
32356
|
publishPort: false
|
|
@@ -32013,7 +32366,7 @@ async function waitForShutdownSignal() {
|
|
|
32013
32366
|
for (const signal of signals) process.once(signal, done);
|
|
32014
32367
|
});
|
|
32015
32368
|
}
|
|
32016
|
-
var
|
|
32369
|
+
var defaultDependencies3 = {
|
|
32017
32370
|
fetch,
|
|
32018
32371
|
openUrl: openExternalUrl,
|
|
32019
32372
|
startServer: startPackagedServer,
|
|
@@ -32040,7 +32393,7 @@ async function verifyServer(server, command, deps) {
|
|
|
32040
32393
|
}
|
|
32041
32394
|
}
|
|
32042
32395
|
async function run(argv, overrides = {}) {
|
|
32043
|
-
const deps = { ...
|
|
32396
|
+
const deps = { ...defaultDependencies3, ...overrides };
|
|
32044
32397
|
let command;
|
|
32045
32398
|
try {
|
|
32046
32399
|
command = parseArgs(argv);
|