cogpit 2.4.0 → 2.4.2

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.
Files changed (25) hide show
  1. package/dist/cli.js +1104 -489
  2. package/dist/web/assets/{CommandPaletteHost-DU1jhhYG.js → CommandPaletteHost-DJghey7B.js} +1 -1
  3. package/dist/web/assets/{ConfigBrowser-CTZR8nw6.js → ConfigBrowser-x0UdXG0K.js} +1 -1
  4. package/dist/web/assets/{HighlightedEditor-CNTtimUO.js → HighlightedEditor-D0TDZx8S.js} +1 -1
  5. package/dist/web/assets/{KeyboardShortcutsDialog-DtTE4xjZ.js → KeyboardShortcutsDialog-2606YXAx.js} +1 -1
  6. package/dist/web/assets/{MobileFileChanges-DaJh6sQ7.js → MobileFileChanges-B4dwGXMS.js} +1 -1
  7. package/dist/web/assets/{PreviewPanel-BOL9gNaQ.js → PreviewPanel-CJdf-VLC.js} +1 -1
  8. package/dist/web/assets/{ProjectFilesPanel-CBFFT9qJ.js → ProjectFilesPanel-3GzuQyp3.js} +1 -1
  9. package/dist/web/assets/{ProjectSwitcherModal-UUQMoktd.js → ProjectSwitcherModal-D8boI2Qx.js} +1 -1
  10. package/dist/web/assets/{TerminalOutput-T82q4Tf9.js → TerminalOutput-C-6RWc6C.js} +1 -1
  11. package/dist/web/assets/{ThemeSelectorModal-rFVnzZuC.js → ThemeSelectorModal-DZ9JuT6j.js} +1 -1
  12. package/dist/web/assets/{WorkflowsPanel-COZwo8h-.js → WorkflowsPanel-i3GanFyN.js} +1 -1
  13. package/dist/web/assets/{WorktreePanel-DvZNvNhH.js → WorktreePanel-D-BUTFL2.js} +1 -1
  14. package/dist/web/assets/{index-CpHg1sRc.js → index-BBKPLXTq.js} +1 -1
  15. package/dist/web/assets/index-CMQcske6.js +1 -0
  16. package/dist/web/assets/index-C_0XOtqJ.css +1 -0
  17. package/dist/web/assets/index-D6p4gVB_.js +154 -0
  18. package/dist/web/assets/{index-BhjwMUil.js → index-ztb2qsgi.js} +1 -1
  19. package/dist/web/assets/{session-parser.worker-QY58jiXs.js → session-parser.worker-D3MwyNH5.js} +1 -1
  20. package/dist/web/assets/{vendor-ui-B9m2oOMV.js → vendor-ui-RwWl1mlR.js} +175 -160
  21. package/dist/web/index.html +3 -3
  22. package/package.json +1 -1
  23. package/dist/web/assets/index-CghBqEmp.js +0 -153
  24. package/dist/web/assets/index-XlQRZ_Un.js +0 -1
  25. package/dist/web/assets/index-f2DFkgKZ.css +0 -1
package/dist/cli.js CHANGED
@@ -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 record4 = { at: Date.now(), generation: generation2 };
490
- lastAttempt.set(id, record4);
489
+ const record5 = { at: Date.now(), generation: generation2 };
490
+ lastAttempt.set(id, record5);
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
- record4.error = error;
506
+ record5.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
- record4.error = error;
514
+ record5.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
- record4.error = error;
525
+ record5.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
- record4.error = error;
539
+ record5.error = error;
540
540
  if (generationIsCurrent(id, generation2)) {
541
541
  setDeviceRuntime(id, { authState: "bad-password", lastProbe: Date.now() });
542
542
  }
@@ -845,6 +845,7 @@ var init_agent_descriptors = __esm({
845
845
  ultracode: true,
846
846
  contextWindow: true,
847
847
  externalProcesses: false,
848
+ accountSwitching: true,
848
849
  modelFallbackNotices: true,
849
850
  autoPermissionMode: "per-model",
850
851
  settingsApply: "live",
@@ -972,6 +973,7 @@ var init_agent_descriptors = __esm({
972
973
  ultracode: false,
973
974
  contextWindow: false,
974
975
  externalProcesses: false,
976
+ accountSwitching: false,
975
977
  modelFallbackNotices: false,
976
978
  autoPermissionMode: "never",
977
979
  settingsApply: "next-turn",
@@ -1088,6 +1090,7 @@ var init_agent_descriptors = __esm({
1088
1090
  ultracode: false,
1089
1091
  contextWindow: false,
1090
1092
  externalProcesses: true,
1093
+ accountSwitching: false,
1091
1094
  modelFallbackNotices: false,
1092
1095
  autoPermissionMode: "always",
1093
1096
  settingsApply: "next-turn",
@@ -1271,8 +1274,8 @@ function quoteArgument(arg) {
1271
1274
  const escaped = arg.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/, "$1$1");
1272
1275
  return `"${escaped}"`;
1273
1276
  }
1274
- function escapeForCmd(text) {
1275
- return text.replace(CMD_META_CHARS, "^$1");
1277
+ function escapeForCmd(text2) {
1278
+ return text2.replace(CMD_META_CHARS, "^$1");
1276
1279
  }
1277
1280
  function throughCmdExe(executable, args, options) {
1278
1281
  const line = [
@@ -1980,17 +1983,17 @@ function shareRequestAllowed(method, rawUrl, share) {
1980
1983
  const path = parseRequestPath(rawUrl);
1981
1984
  if (path === null) return false;
1982
1985
  const verb = method.toUpperCase();
1983
- const route = path.raw[1];
1986
+ const route2 = path.raw[1];
1984
1987
  const identity = path.decoded.slice(2);
1985
1988
  const routePath = `/${path.raw.join("/")}`;
1986
1989
  if (SHARE_NAMESPACE.some(([allowedVerb, allowedPath]) => allowedVerb === verb && allowedPath === routePath)) return true;
1987
- if (verb === "GET" && (route === "sessions" || route === "watch")) {
1990
+ if (verb === "GET" && (route2 === "sessions" || route2 === "watch")) {
1988
1991
  return identity.length === 2 && identity[0] === share.dirName && identity[1] === share.fileName;
1989
1992
  }
1990
- if (verb === "GET" && (route === "session-status" || route === "session-file-changes")) {
1993
+ if (verb === "GET" && (route2 === "session-status" || route2 === "session-file-changes")) {
1991
1994
  return identity.length === 1 && identity[0] === share.sessionId;
1992
1995
  }
1993
- if (verb === "GET" && route === "session-config") {
1996
+ if (verb === "GET" && route2 === "session-config") {
1994
1997
  return identity.length === 1 && identity[0] === share.fileName;
1995
1998
  }
1996
1999
  return false;
@@ -4002,7 +4005,7 @@ async function createShare(input) {
4002
4005
  const passwordHash = hashPassword(passphrase);
4003
4006
  const share = await commitShareMutation((draft) => {
4004
4007
  const existing = draft.get(input.sessionId);
4005
- const record4 = {
4008
+ const record5 = {
4006
4009
  sessionId: input.sessionId,
4007
4010
  dirName: input.dirName,
4008
4011
  fileName: input.fileName,
@@ -4011,8 +4014,8 @@ async function createShare(input) {
4011
4014
  // No guest has ever used this passphrase; the UI renders 0 as "never".
4012
4015
  lastAccessAt: 0
4013
4016
  };
4014
- draft.set(record4.sessionId, record4);
4015
- return { changed: true, value: toPublicShare(record4) };
4017
+ draft.set(record5.sessionId, record5);
4018
+ return { changed: true, value: toPublicShare(record5) };
4016
4019
  });
4017
4020
  return { share, passphrase };
4018
4021
  }
@@ -4865,6 +4868,7 @@ var init_policy = __esm({
4865
4868
  "git-status": admin("/api/git-status"),
4866
4869
  github: admin("/api/github"),
4867
4870
  "vercel-deployments": admin("/api/vercel-deployments"),
4871
+ clickup: admin("/api/clickup"),
4868
4872
  "project-icon": admin("/api/project-icon"),
4869
4873
  "git-diff": admin("/api/git-diff"),
4870
4874
  mcp: admin("/api/mcp-servers"),
@@ -4897,6 +4901,10 @@ var init_policy = __esm({
4897
4901
  // Reports which binary the server spawns; the choice itself is saved through /api/config.
4898
4902
  "agent-executable": [
4899
4903
  { prefix: "/api/agent-executable", methods: ["GET"], requires: "authed" }
4904
+ ],
4905
+ "agent-accounts": [
4906
+ { prefix: "/api/agent-accounts", methods: ["GET"], requires: "authed" },
4907
+ { prefix: "/api/agent-accounts", requires: "admin" }
4900
4908
  ]
4901
4909
  };
4902
4910
  ALL_RULES = Object.values(ROUTE_POLICIES).flat();
@@ -5800,7 +5808,7 @@ function findNpmClaude(options = {}) {
5800
5808
  const windows = platform2 === "win32";
5801
5809
  const path = windows ? win322 : posix2;
5802
5810
  const isFile = options.isFile ?? realIsFile;
5803
- const readFile22 = options.readFile ?? realReadFile;
5811
+ const readFile23 = options.readFile ?? realReadFile;
5804
5812
  const shim = findExecutableOnPath(BIN_NAME, { platform: platform2, env: options.env, isExecutable: isFile });
5805
5813
  if (!shim) return void 0;
5806
5814
  const shimDir = path.dirname(shim);
@@ -5809,7 +5817,7 @@ function findNpmClaude(options = {}) {
5809
5817
  path.join(shimDir, "..", "lib", "node_modules", NPM_PACKAGE)
5810
5818
  ];
5811
5819
  for (const packageDir of packageDirs) {
5812
- const manifest = readFile22(path.join(packageDir, "package.json"));
5820
+ const manifest = readFile23(path.join(packageDir, "package.json"));
5813
5821
  if (!manifest) continue;
5814
5822
  const relative11 = binField(manifest);
5815
5823
  if (!relative11) continue;
@@ -6039,8 +6047,8 @@ function publish(sessionId, ev, parentToolUseId) {
6039
6047
  const msg = messageId ? state.messages.get(messageId) : void 0;
6040
6048
  if (!messageId || !msg || ev.index === void 0) return;
6041
6049
  const d = ev.delta;
6042
- const text = d?.type === "text_delta" ? d.text : d?.type === "thinking_delta" ? d.thinking : d?.type === "input_json_delta" ? d.partial_json : void 0;
6043
- if (!text) return;
6050
+ const text2 = d?.type === "text_delta" ? d.text : d?.type === "thinking_delta" ? d.thinking : d?.type === "input_json_delta" ? d.partial_json : void 0;
6051
+ if (!text2) return;
6044
6052
  let block = msg.blocks.find((b) => b.index === ev.index);
6045
6053
  if (!block) {
6046
6054
  const inferred = d?.type === "thinking_delta" ? "thinking" : d?.type === "input_json_delta" ? "tool_use" : "text";
@@ -6048,7 +6056,7 @@ function publish(sessionId, ev, parentToolUseId) {
6048
6056
  msg.blocks.push(block);
6049
6057
  }
6050
6058
  if (block.text.length < MAX_BLOCK_TEXT) {
6051
- block.text += text;
6059
+ block.text += text2;
6052
6060
  }
6053
6061
  queueDelta(state, {
6054
6062
  messageId,
@@ -6056,7 +6064,7 @@ function publish(sessionId, ev, parentToolUseId) {
6056
6064
  blockIndex: ev.index,
6057
6065
  blockType: block.blockType,
6058
6066
  ...block.toolName ? { toolName: block.toolName } : {},
6059
- delta: text
6067
+ delta: text2
6060
6068
  });
6061
6069
  return;
6062
6070
  }
@@ -6080,8 +6088,8 @@ function publish(sessionId, ev, parentToolUseId) {
6080
6088
  return;
6081
6089
  }
6082
6090
  }
6083
- function publishTextDelta(sessionId, messageId, text, parentToolUseId = null) {
6084
- if (!sessionId || !messageId || !text) return;
6091
+ function publishTextDelta(sessionId, messageId, text2, parentToolUseId = null) {
6092
+ if (!sessionId || !messageId || !text2) return;
6085
6093
  const state = getOrCreate(sessionId);
6086
6094
  let msg = state.messages.get(messageId);
6087
6095
  if (!msg) {
@@ -6094,13 +6102,13 @@ function publishTextDelta(sessionId, messageId, text, parentToolUseId = null) {
6094
6102
  block = { index: 0, blockType: "text", text: "" };
6095
6103
  msg.blocks.push(block);
6096
6104
  }
6097
- if (block.text.length < MAX_BLOCK_TEXT) block.text += text;
6105
+ if (block.text.length < MAX_BLOCK_TEXT) block.text += text2;
6098
6106
  queueDelta(state, {
6099
6107
  messageId,
6100
6108
  parentToolUseId,
6101
6109
  blockIndex: 0,
6102
6110
  blockType: "text",
6103
- delta: text
6111
+ delta: text2
6104
6112
  });
6105
6113
  }
6106
6114
  function publishCompleteMessage(sessionId, msg) {
@@ -7486,12 +7494,12 @@ async function readHeadLines(filePath, byteLimit) {
7486
7494
  try {
7487
7495
  const buf = Buffer.allocUnsafe(byteLimit);
7488
7496
  const { bytesRead } = await fh.read(buf, 0, byteLimit, 0);
7489
- let text = buf.subarray(0, bytesRead).toString("utf-8");
7497
+ let text2 = buf.subarray(0, bytesRead).toString("utf-8");
7490
7498
  if (bytesRead === byteLimit) {
7491
- const lastNewline = text.lastIndexOf("\n");
7492
- if (lastNewline >= 0) text = text.slice(0, lastNewline);
7499
+ const lastNewline = text2.lastIndexOf("\n");
7500
+ if (lastNewline >= 0) text2 = text2.slice(0, lastNewline);
7493
7501
  }
7494
- return text.split("\n").filter(Boolean);
7502
+ return text2.split("\n").filter(Boolean);
7495
7503
  } finally {
7496
7504
  await fh.close();
7497
7505
  }
@@ -7529,9 +7537,9 @@ var init_transcriptHead = __esm({
7529
7537
 
7530
7538
  // ../../server/agents/claudeMetadata.ts
7531
7539
  import { open as open3 } from "node:fs/promises";
7532
- function lastRealModel(text) {
7540
+ function lastRealModel(text2) {
7533
7541
  let found = null;
7534
- for (const match of text.matchAll(MODEL_RE)) {
7542
+ for (const match of text2.matchAll(MODEL_RE)) {
7535
7543
  if (!match[1].startsWith("<")) found = match[1];
7536
7544
  }
7537
7545
  return found;
@@ -7650,15 +7658,15 @@ async function readClaudeSessionMeta(filePath, head) {
7650
7658
  cursor -= readSize;
7651
7659
  const buf = Buffer.alloc(readSize);
7652
7660
  const { bytesRead } = await fh.read(buf, 0, readSize, cursor);
7653
- const text = buf.subarray(0, bytesRead).toString("utf-8") + leftover;
7661
+ const text2 = buf.subarray(0, bytesRead).toString("utf-8") + leftover;
7654
7662
  if (!foundModel) {
7655
- const found = lastRealModel(text);
7663
+ const found = lastRealModel(text2);
7656
7664
  if (found) {
7657
7665
  model = found;
7658
7666
  foundModel = true;
7659
7667
  }
7660
7668
  }
7661
- const splitLines = text.split("\n");
7669
+ const splitLines = text2.split("\n");
7662
7670
  leftover = cursor > 0 ? splitLines[0] : "";
7663
7671
  const startIdx = cursor > 0 ? 1 : 0;
7664
7672
  for (let j = splitLines.length - 1; j >= startIdx; j--) {
@@ -8003,15 +8011,15 @@ var init_sessionStats = __esm({
8003
8011
  });
8004
8012
 
8005
8013
  // ../../shared/session/turnContent.ts
8006
- function appendAssistantText(turn, text, timestamp2) {
8007
- if (!text) return;
8008
- turn.assistantText.push(text);
8014
+ function appendAssistantText(turn, text2, timestamp2) {
8015
+ if (!text2) return;
8016
+ turn.assistantText.push(text2);
8009
8017
  const last = turn.contentBlocks[turn.contentBlocks.length - 1];
8010
8018
  if (last?.kind === "text") {
8011
- last.text.push(text);
8019
+ last.text.push(text2);
8012
8020
  return;
8013
8021
  }
8014
- turn.contentBlocks.push({ kind: "text", text: [text], timestamp: timestamp2 });
8022
+ turn.contentBlocks.push({ kind: "text", text: [text2], timestamp: timestamp2 });
8015
8023
  }
8016
8024
  var init_turnContent = __esm({
8017
8025
  "../../shared/session/turnContent.ts"() {
@@ -8541,10 +8549,10 @@ function parseCustomToolOutput(output) {
8541
8549
  if (!rawOutput) return { text: "", isError: false };
8542
8550
  try {
8543
8551
  const parsed = JSON.parse(rawOutput);
8544
- const text = typeof parsed.output === "string" ? parsed.output : rawOutput;
8552
+ const text2 = typeof parsed.output === "string" ? parsed.output : rawOutput;
8545
8553
  const meta = isObject(parsed.metadata) ? parsed.metadata : null;
8546
- const isError = meta ? meta.exit_code !== 0 && meta.exit_code !== void 0 : inferToolError(text);
8547
- return { text, isError };
8554
+ const isError = meta ? meta.exit_code !== 0 && meta.exit_code !== void 0 : inferToolError(text2);
8555
+ return { text: text2, isError };
8548
8556
  } catch {
8549
8557
  return { text: rawOutput, isError: inferToolError(rawOutput) };
8550
8558
  }
@@ -8583,9 +8591,9 @@ function safeParseLine(line) {
8583
8591
  function isObject2(value) {
8584
8592
  return typeof value === "object" && value !== null;
8585
8593
  }
8586
- function isCodexRecord(record4) {
8587
- if (!record4 || typeof record4.type !== "string") return false;
8588
- 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";
8594
+ function isCodexRecord(record5) {
8595
+ if (!record5 || typeof record5.type !== "string") return false;
8596
+ return record5.type === "session_meta" || record5.type === "turn_context" || record5.type === "event_msg" || record5.type === "response_item" || record5.type === "inter_agent_communication_metadata" || record5.type === "compacted" || record5.type === "world_state";
8589
8597
  }
8590
8598
  function extractMessageText(payload, blockType) {
8591
8599
  const content = payload?.content;
@@ -8641,12 +8649,12 @@ function buildCodexUserContent(message, images, audio = [], localImages = [], lo
8641
8649
  ...localAudio.map((path) => `
8642
8650
  [audio attachment](<${path}>)`)
8643
8651
  ].join("");
8644
- const text = message + attachmentSuffix;
8645
- if (images.length === 0 && audio.length === 0) return text;
8652
+ const text2 = message + attachmentSuffix;
8653
+ if (images.length === 0 && audio.length === 0) return text2;
8646
8654
  return [
8647
8655
  ...images,
8648
8656
  ...audio,
8649
- ...text ? [{ type: "text", text }] : []
8657
+ ...text2 ? [{ type: "text", text: text2 }] : []
8650
8658
  ];
8651
8659
  }
8652
8660
  function extractInterAgentMessage(payload) {
@@ -8658,8 +8666,8 @@ function extractInterAgentMessage(payload) {
8658
8666
  }
8659
8667
  const header = rawText.slice(0, headerEnd.index);
8660
8668
  const messageType = header.match(/^Message Type:\s*([^\r\n]+)/)?.[1]?.trim().toUpperCase() ?? null;
8661
- const text = rawText.slice(headerEnd.index + headerEnd[0].length).trim();
8662
- return { messageType, text };
8669
+ const text2 = rawText.slice(headerEnd.index + headerEnd[0].length).trim();
8670
+ return { messageType, text: text2 };
8663
8671
  }
8664
8672
  function agentNameFromPath(agentPath) {
8665
8673
  const segments2 = agentPath.split(/[\\/]/).filter(Boolean);
@@ -8671,8 +8679,8 @@ function readableAgentPrompt(value) {
8671
8679
  if (/^gAAAAA[A-Za-z0-9_-]+$/.test(prompt)) return "";
8672
8680
  return prompt;
8673
8681
  }
8674
- function normalizePromptText(text) {
8675
- const trimmed = text.trim();
8682
+ function normalizePromptText(text2) {
8683
+ const trimmed = text2.trim();
8676
8684
  if (!trimmed) return "";
8677
8685
  if (SKIP_PROMPT_PREFIXES.some((prefix) => trimmed.startsWith(prefix))) return "";
8678
8686
  return trimmed;
@@ -8702,9 +8710,9 @@ function parseTokenUsage(value) {
8702
8710
  cache_read_input_tokens: cacheRead
8703
8711
  };
8704
8712
  }
8705
- function appendThinking(turn, text, timestamp2) {
8706
- if (!text) return;
8707
- const block = { type: "thinking", thinking: text, signature: "" };
8713
+ function appendThinking(turn, text2, timestamp2) {
8714
+ if (!text2) return;
8715
+ const block = { type: "thinking", thinking: text2, signature: "" };
8708
8716
  turn.thinking.push(block);
8709
8717
  const last = turn.contentBlocks[turn.contentBlocks.length - 1];
8710
8718
  if (last && last.kind === "thinking") {
@@ -8765,9 +8773,9 @@ function parseMcpEventResult(value) {
8765
8773
  const ok = isObject2(value.Ok) ? value.Ok : null;
8766
8774
  if (!ok) return { text: safeStringify(value), isError: false };
8767
8775
  const parsedContent = parseCustomToolOutput(ok.content);
8768
- const text = parsedContent.text || (ok.structuredContent !== void 0 ? safeStringify(ok.structuredContent) : safeStringify(ok));
8776
+ const text2 = parsedContent.text || (ok.structuredContent !== void 0 ? safeStringify(ok.structuredContent) : safeStringify(ok));
8769
8777
  return {
8770
- text,
8778
+ text: text2,
8771
8779
  isError: ok.isError === true || parsedContent.isError
8772
8780
  };
8773
8781
  }
@@ -8786,22 +8794,22 @@ function createTurn(turnId, timestamp2, model) {
8786
8794
  model
8787
8795
  };
8788
8796
  }
8789
- function extractPromptFromRecord(record4) {
8790
- if (record4.type === "event_msg" && isObject2(record4.payload) && record4.payload.type === "user_message" && typeof record4.payload.message === "string") {
8791
- return normalizePromptText(record4.payload.message);
8797
+ function extractPromptFromRecord(record5) {
8798
+ if (record5.type === "event_msg" && isObject2(record5.payload) && record5.payload.type === "user_message" && typeof record5.payload.message === "string") {
8799
+ return normalizePromptText(record5.payload.message);
8792
8800
  }
8793
- if (record4.type === "response_item" && isObject2(record4.payload) && record4.payload.type === "message" && record4.payload.role === "user") {
8794
- return normalizePromptText(extractMessageText(record4.payload, "input_text"));
8801
+ if (record5.type === "response_item" && isObject2(record5.payload) && record5.payload.type === "message" && record5.payload.role === "user") {
8802
+ return normalizePromptText(extractMessageText(record5.payload, "input_text"));
8795
8803
  }
8796
8804
  return "";
8797
8805
  }
8798
- function recordOpensTurn(record4, payload) {
8799
- if (record4.type === "session_meta") return false;
8800
- if (record4.type === "event_msg" && payload?.type === "task_started") return false;
8801
- if (record4.type === "response_item" && payload?.type === "message") {
8806
+ function recordOpensTurn(record5, payload) {
8807
+ if (record5.type === "session_meta") return false;
8808
+ if (record5.type === "event_msg" && payload?.type === "task_started") return false;
8809
+ if (record5.type === "response_item" && payload?.type === "message") {
8802
8810
  if (payload.role === "developer" || payload.role === "system") return false;
8803
8811
  if (payload.role === "user") {
8804
- return extractPromptFromRecord(record4) !== "" || extractResponseMessageImages(payload).length > 0 || extractResponseMessageAudio(payload).length > 0;
8812
+ return extractPromptFromRecord(record5) !== "" || extractResponseMessageImages(payload).length > 0 || extractResponseMessageAudio(payload).length > 0;
8805
8813
  }
8806
8814
  }
8807
8815
  return true;
@@ -8822,22 +8830,22 @@ function extractMetadataFromRecords(records) {
8822
8830
  let parentSessionId = null;
8823
8831
  let agentPath = "/root";
8824
8832
  let previousPrompt = "";
8825
- for (const record4 of records) {
8826
- if (!isObject2(record4.payload)) continue;
8827
- if (record4.type === "session_meta") {
8828
- sessionId ||= typeof record4.payload.id === "string" ? record4.payload.id : "";
8829
- version ||= typeof record4.payload.cli_version === "string" ? record4.payload.cli_version : "";
8830
- cwd ||= typeof record4.payload.cwd === "string" ? record4.payload.cwd : "";
8831
- if (!branchedFrom && isObject2(record4.payload.branchedFrom)) {
8832
- const sourceId = typeof record4.payload.branchedFrom.sessionId === "string" ? record4.payload.branchedFrom.sessionId : "";
8833
+ for (const record5 of records) {
8834
+ if (!isObject2(record5.payload)) continue;
8835
+ if (record5.type === "session_meta") {
8836
+ sessionId ||= typeof record5.payload.id === "string" ? record5.payload.id : "";
8837
+ version ||= typeof record5.payload.cli_version === "string" ? record5.payload.cli_version : "";
8838
+ cwd ||= typeof record5.payload.cwd === "string" ? record5.payload.cwd : "";
8839
+ if (!branchedFrom && isObject2(record5.payload.branchedFrom)) {
8840
+ const sourceId = typeof record5.payload.branchedFrom.sessionId === "string" ? record5.payload.branchedFrom.sessionId : "";
8833
8841
  if (sourceId) {
8834
8842
  branchedFrom = {
8835
8843
  sessionId: sourceId,
8836
- turnIndex: typeof record4.payload.branchedFrom.turnIndex === "number" ? record4.payload.branchedFrom.turnIndex : null
8844
+ turnIndex: typeof record5.payload.branchedFrom.turnIndex === "number" ? record5.payload.branchedFrom.turnIndex : null
8837
8845
  };
8838
8846
  }
8839
8847
  }
8840
- const source = isObject2(record4.payload.source) ? record4.payload.source : null;
8848
+ const source = isObject2(record5.payload.source) ? record5.payload.source : null;
8841
8849
  if (source && isObject2(source.subagent)) {
8842
8850
  isSubagent = true;
8843
8851
  const threadSpawn = isObject2(source.subagent.thread_spawn) ? source.subagent.thread_spawn : null;
@@ -8845,25 +8853,25 @@ function extractMetadataFromRecords(records) {
8845
8853
  agentPath = threadSpawn.agent_path;
8846
8854
  }
8847
8855
  }
8848
- if (typeof record4.payload.forked_from_id === "string" && record4.payload.forked_from_id) {
8849
- parentSessionId = record4.payload.forked_from_id;
8856
+ if (typeof record5.payload.forked_from_id === "string" && record5.payload.forked_from_id) {
8857
+ parentSessionId = record5.payload.forked_from_id;
8850
8858
  }
8851
- const git = isObject2(record4.payload.git) ? record4.payload.git : null;
8859
+ const git = isObject2(record5.payload.git) ? record5.payload.git : null;
8852
8860
  gitBranch ||= git && typeof git.branch === "string" ? git.branch : "";
8853
8861
  }
8854
- if (record4.type === "turn_context") {
8855
- model ||= typeof record4.payload.model === "string" ? record4.payload.model : "";
8856
- cwd ||= typeof record4.payload.cwd === "string" ? record4.payload.cwd : "";
8862
+ if (record5.type === "turn_context") {
8863
+ model ||= typeof record5.payload.model === "string" ? record5.payload.model : "";
8864
+ cwd ||= typeof record5.payload.cwd === "string" ? record5.payload.cwd : "";
8857
8865
  }
8858
- const prompt = extractPromptFromRecord(record4);
8866
+ const prompt = extractPromptFromRecord(record5);
8859
8867
  if (!prompt) continue;
8860
8868
  if (prompt === previousPrompt) continue;
8861
8869
  if (!firstUserMessage) firstUserMessage = prompt;
8862
8870
  lastUserMessage = prompt;
8863
8871
  previousPrompt = prompt;
8864
8872
  turnCount++;
8865
- if (!timestamp2) timestamp2 = record4.timestamp ?? "";
8866
- lastTimestamp = record4.timestamp ?? lastTimestamp;
8873
+ if (!timestamp2) timestamp2 = record5.timestamp ?? "";
8874
+ lastTimestamp = record5.timestamp ?? lastTimestamp;
8867
8875
  }
8868
8876
  if (lastTimestamp === "") lastTimestamp = timestamp2;
8869
8877
  return {
@@ -9021,19 +9029,19 @@ function walkCodexRecords(records, options) {
9021
9029
  appendToolCall(targetTurn, toolCall, timestamp2);
9022
9030
  }
9023
9031
  for (let index = 0; index < records.length; index++) {
9024
- const record4 = records[index];
9025
- if (!isCodexRecord(record4)) continue;
9032
+ const record5 = records[index];
9033
+ if (!isCodexRecord(record5)) continue;
9026
9034
  recordIndex = index;
9027
- const payload = isObject2(record4.payload) ? record4.payload : void 0;
9028
- const timestamp2 = record4.timestamp ?? "";
9029
- if (record4.type === "compacted") {
9035
+ const payload = isObject2(record5.payload) ? record5.payload : void 0;
9036
+ const timestamp2 = record5.timestamp ?? "";
9037
+ if (record5.type === "compacted") {
9030
9038
  current = commitTurn(current);
9031
9039
  pendingCompaction = "Conversation compacted";
9032
9040
  lastTurnTimestamp = timestamp2;
9033
9041
  continue;
9034
9042
  }
9035
- if (record4.type === "world_state") continue;
9036
- if (record4.type === "turn_context") {
9043
+ if (record5.type === "world_state") continue;
9044
+ if (record5.type === "turn_context") {
9037
9045
  current = commitTurn(current);
9038
9046
  pendingContextIndex = index;
9039
9047
  currentTurnId = typeof payload?.turn_id === "string" ? payload.turn_id : null;
@@ -9042,7 +9050,7 @@ function walkCodexRecords(records, options) {
9042
9050
  sawTurnStart = true;
9043
9051
  continue;
9044
9052
  }
9045
- if (record4.type === "event_msg" && payload?.type === "user_message" && typeof payload.message === "string") {
9053
+ if (record5.type === "event_msg" && payload?.type === "user_message" && typeof payload.message === "string") {
9046
9054
  if (current && (current.assistantText.length > 0 || current.toolCalls.length > 0 || current.thinking.length > 0)) {
9047
9055
  current = commitTurn(current);
9048
9056
  }
@@ -9066,12 +9074,12 @@ function walkCodexRecords(records, options) {
9066
9074
  lastTurnTimestamp = timestamp2;
9067
9075
  continue;
9068
9076
  }
9069
- if (!current && !recordOpensTurn(record4, payload)) continue;
9077
+ if (!current && !recordOpensTurn(record5, payload)) continue;
9070
9078
  current ??= createActiveTurn(currentTurnId, timestamp2, currentModel);
9071
9079
  if (!current.model && currentModel) current.model = currentModel;
9072
9080
  if (!current.timestamp) current.timestamp = timestamp2;
9073
9081
  if (timestamp2) lastTurnTimestamp = timestamp2;
9074
- if (record4.type === "event_msg" && payload?.type === "token_count") {
9082
+ if (record5.type === "event_msg" && payload?.type === "token_count") {
9075
9083
  const info = isObject2(payload.info) ? payload.info : null;
9076
9084
  const lastUsage = info ? parseTokenUsage(info.last_token_usage) : null;
9077
9085
  if (lastUsage) {
@@ -9079,14 +9087,14 @@ function walkCodexRecords(records, options) {
9079
9087
  }
9080
9088
  continue;
9081
9089
  }
9082
- if (record4.type === "event_msg" && payload?.type === "web_search_end" && typeof payload.call_id === "string") {
9090
+ if (record5.type === "event_msg" && payload?.type === "web_search_end" && typeof payload.call_id === "string") {
9083
9091
  const input = {};
9084
9092
  if (typeof payload.query === "string" && payload.query) input.query = payload.query;
9085
9093
  if (isObject2(payload.action)) input.action = payload.action;
9086
9094
  upsertWebSearchCall(current, payload.call_id, input, "completed", timestamp2);
9087
9095
  continue;
9088
9096
  }
9089
- if (record4.type === "event_msg" && payload?.type === "mcp_tool_call_end" && typeof payload.call_id === "string" && isObject2(payload.invocation)) {
9097
+ if (record5.type === "event_msg" && payload?.type === "mcp_tool_call_end" && typeof payload.call_id === "string" && isObject2(payload.invocation)) {
9090
9098
  const invocation = payload.invocation;
9091
9099
  const server = typeof invocation.server === "string" ? invocation.server : "mcp";
9092
9100
  const tool = typeof invocation.tool === "string" ? invocation.tool : "tool";
@@ -9109,7 +9117,7 @@ function walkCodexRecords(records, options) {
9109
9117
  }
9110
9118
  continue;
9111
9119
  }
9112
- if (record4.type === "event_msg" && payload?.type === "sub_agent_activity" && typeof payload.agent_thread_id === "string" && typeof payload.agent_path === "string") {
9120
+ if (record5.type === "event_msg" && payload?.type === "sub_agent_activity" && typeof payload.agent_thread_id === "string" && typeof payload.agent_path === "string") {
9113
9121
  const agentId = payload.agent_thread_id;
9114
9122
  const eventId2 = typeof payload.event_id === "string" ? payload.event_id : "";
9115
9123
  const kind = typeof payload.kind === "string" ? payload.kind : "started";
@@ -9143,7 +9151,7 @@ function walkCodexRecords(records, options) {
9143
9151
  upsertAgentMessage(agentId, current, timestamp2, { status });
9144
9152
  continue;
9145
9153
  }
9146
- if (record4.type !== "response_item" || !payload) continue;
9154
+ if (record5.type !== "response_item" || !payload) continue;
9147
9155
  if (payload.type === "reasoning") {
9148
9156
  const summary = Array.isArray(payload.summary) ? payload.summary.filter((item) => typeof item === "string").join("\n") : "";
9149
9157
  appendThinking(current, summary.trim(), timestamp2);
@@ -9154,11 +9162,11 @@ function walkCodexRecords(records, options) {
9154
9162
  continue;
9155
9163
  }
9156
9164
  if (payload.type === "message" && payload.role === "user" && current.userMessage === null) {
9157
- const text = normalizePromptText(extractMessageText(payload, "input_text"));
9165
+ const text2 = normalizePromptText(extractMessageText(payload, "input_text"));
9158
9166
  const images = extractResponseMessageImages(payload);
9159
9167
  const audio = extractResponseMessageAudio(payload);
9160
- if (text || images.length > 0 || audio.length > 0) {
9161
- current.userMessage = buildCodexUserContent(text, images, audio);
9168
+ if (text2 || images.length > 0 || audio.length > 0) {
9169
+ current.userMessage = buildCodexUserContent(text2, images, audio);
9162
9170
  current.isFragment = false;
9163
9171
  sawTurnStart = true;
9164
9172
  }
@@ -9364,14 +9372,14 @@ function walkCodexRecords(records, options) {
9364
9372
  }
9365
9373
  if (payload.type === "custom_tool_call_output" && typeof payload.call_id === "string") {
9366
9374
  const callId = payload.call_id;
9367
- const { text, isError } = parseCustomToolOutput(payload.output);
9375
+ const { text: text2, isError } = parseCustomToolOutput(payload.output);
9368
9376
  const patchCalls = patchCallIds.get(callId);
9369
9377
  if (patchCalls) {
9370
- const failedIds = patchCalls.direct && isError ? new Set(patchCalls.calls.map((call) => call.id)) : findFailedNestedPatchCallIds(text, isError, patchCalls.calls);
9378
+ const failedIds = patchCalls.direct && isError ? new Set(patchCalls.calls.map((call) => call.id)) : findFailedNestedPatchCallIds(text2, isError, patchCalls.calls);
9371
9379
  for (const patchCall of patchCalls.calls) {
9372
9380
  const tc = pendingToolCalls.get(patchCall.id);
9373
9381
  if (tc) {
9374
- tc.result = text;
9382
+ tc.result = text2;
9375
9383
  tc.isError = failedIds.has(tc.id);
9376
9384
  pendingToolCalls.delete(tc.id);
9377
9385
  }
@@ -9380,7 +9388,7 @@ function walkCodexRecords(records, options) {
9380
9388
  }
9381
9389
  const toolCall = pendingToolCalls.get(callId);
9382
9390
  if (toolCall) {
9383
- toolCall.result = text;
9391
+ toolCall.result = text2;
9384
9392
  toolCall.isError = isError;
9385
9393
  pendingToolCalls.delete(callId);
9386
9394
  }
@@ -9413,7 +9421,7 @@ function parseCodexSession(jsonlText, options) {
9413
9421
  return session;
9414
9422
  }
9415
9423
  function appendCodexSession(existing, newJsonlText) {
9416
- const prefix = existing.rawMessages.map((record4) => JSON.stringify(record4)).join("\n");
9424
+ const prefix = existing.rawMessages.map((record5) => JSON.stringify(record5)).join("\n");
9417
9425
  return parseCodexSession(prefix ? `${prefix}
9418
9426
  ${newJsonlText}` : newJsonlText);
9419
9427
  }
@@ -9513,8 +9521,8 @@ function collectCodexPendingAgents(rawMessages) {
9513
9521
  continue;
9514
9522
  }
9515
9523
  if (payload.type === "agent_message" && typeof payload.author === "string") {
9516
- const text = codexPayloadText(payload);
9517
- const messageType = text.match(/^Message Type:\s*([^\r\n]+)/)?.[1]?.trim().toUpperCase() ?? "";
9524
+ const text2 = codexPayloadText(payload);
9525
+ const messageType = text2.match(/^Message Type:\s*([^\r\n]+)/)?.[1]?.trim().toUpperCase() ?? "";
9518
9526
  if (!TERMINAL_INTER_AGENT_TYPES.has(messageType)) continue;
9519
9527
  const agentId = agentIdByPath.get(payload.author) ?? payload.author;
9520
9528
  done.add(agentId);
@@ -9608,16 +9616,16 @@ async function readCodexSessionIdentity(filePath) {
9608
9616
  let parentSessionId = null;
9609
9617
  let sawSessionMeta = false;
9610
9618
  for (const line of await readHeadLines(filePath, HEAD_BYTES)) {
9611
- let record4;
9619
+ let record5;
9612
9620
  try {
9613
- record4 = JSON.parse(line);
9621
+ record5 = JSON.parse(line);
9614
9622
  } catch {
9615
9623
  continue;
9616
9624
  }
9617
- if (!isRecord2(record4) || !isRecord2(record4.payload)) continue;
9618
- if (record4.type === "session_meta") {
9625
+ if (!isRecord2(record5) || !isRecord2(record5.payload)) continue;
9626
+ if (record5.type === "session_meta") {
9619
9627
  sawSessionMeta = true;
9620
- const payload = record4.payload;
9628
+ const payload = record5.payload;
9621
9629
  if (!sessionId && typeof payload.id === "string") sessionId = payload.id;
9622
9630
  if (!cwd && typeof payload.cwd === "string") cwd = payload.cwd;
9623
9631
  if (!parentSessionId && typeof payload.forked_from_id === "string") {
@@ -9627,8 +9635,8 @@ async function readCodexSessionIdentity(filePath) {
9627
9635
  if (source && isRecord2(source.subagent)) isSubagent = true;
9628
9636
  const git = isRecord2(payload.git) ? payload.git : null;
9629
9637
  if (!gitBranch && git && typeof git.branch === "string") gitBranch = git.branch;
9630
- } else if (record4.type === "turn_context") {
9631
- if (!cwd && typeof record4.payload.cwd === "string") cwd = record4.payload.cwd;
9638
+ } else if (record5.type === "turn_context") {
9639
+ if (!cwd && typeof record5.payload.cwd === "string") cwd = record5.payload.cwd;
9632
9640
  }
9633
9641
  }
9634
9642
  if (!sawSessionMeta || !cwd) return null;
@@ -10028,8 +10036,8 @@ function textFromValue(value) {
10028
10036
  if (typeof value === "string") return value;
10029
10037
  if (!Array.isArray(value)) return "";
10030
10038
  return value.flatMap((part) => {
10031
- const text = typeof part === "string" ? part : isObject3(part) ? readString(part.text, part.content) : "";
10032
- return text ? [text] : [];
10039
+ const text2 = typeof part === "string" ? part : isObject3(part) ? readString(part.text, part.content) : "";
10040
+ return text2 ? [text2] : [];
10033
10041
  }).join("\n");
10034
10042
  }
10035
10043
  function collectBinaryAssets(events) {
@@ -10069,10 +10077,10 @@ function extractImages(values, assets) {
10069
10077
  return images;
10070
10078
  }
10071
10079
  function buildUserContent(data, assets) {
10072
- const text = readString(data.content);
10080
+ const text2 = readString(data.content);
10073
10081
  const images = extractImages(data.attachments, assets);
10074
- if (images.length === 0) return text;
10075
- return [...images, ...text ? [{ type: "text", text }] : []];
10082
+ if (images.length === 0) return text2;
10083
+ return [...images, ...text2 ? [{ type: "text", text: text2 }] : []];
10076
10084
  }
10077
10085
  function extractToolResultImages(data, assets) {
10078
10086
  if (!isObject3(data.result)) return [];
@@ -10201,17 +10209,17 @@ function extractToolResult(data) {
10201
10209
  if (typeof result.content === "string") return result.content;
10202
10210
  if (Array.isArray(result.contents)) {
10203
10211
  const content = result.contents.flatMap((part) => {
10204
- const text = typeof part === "string" ? part : isObject3(part) ? readString(part.text, part.content, part.output) : "";
10205
- return text ? [text] : [];
10212
+ const text2 = typeof part === "string" ? part : isObject3(part) ? readString(part.text, part.content, part.output) : "";
10213
+ return text2 ? [text2] : [];
10206
10214
  }).join("\n");
10207
10215
  if (content) return content;
10208
10216
  }
10209
10217
  if (result.structuredContent !== void 0) return safeStringify2(result.structuredContent);
10210
10218
  return safeStringify2(result);
10211
10219
  }
10212
- function appendThinking2(turn, text, timestamp2, signature) {
10213
- if (!text || turn.thinking.some((block2) => block2.thinking === text)) return;
10214
- const block = { type: "thinking", thinking: text, signature };
10220
+ function appendThinking2(turn, text2, timestamp2, signature) {
10221
+ if (!text2 || turn.thinking.some((block2) => block2.thinking === text2)) return;
10222
+ const block = { type: "thinking", thinking: text2, signature };
10215
10223
  turn.thinking.push(block);
10216
10224
  const last = turn.contentBlocks[turn.contentBlocks.length - 1];
10217
10225
  if (last?.kind === "thinking") {
@@ -10389,8 +10397,8 @@ function parseCopilotSession(jsonlText, options) {
10389
10397
  message.model = readString(data.model) || message.model;
10390
10398
  const reasoning = readString(data.reasoningText);
10391
10399
  if (reasoning && !message.thinking.includes(reasoning)) message.thinking.push(reasoning);
10392
- const text = textFromValue(data.content);
10393
- if (text && !message.text.includes(text)) message.text.push(text);
10400
+ const text2 = textFromValue(data.content);
10401
+ if (text2 && !message.text.includes(text2)) message.text.push(text2);
10394
10402
  for (const call of toolCallsFromRequests(
10395
10403
  data.toolRequests,
10396
10404
  timestamp2,
@@ -10645,7 +10653,7 @@ function parseCopilotSession(jsonlText, options) {
10645
10653
  };
10646
10654
  }
10647
10655
  function appendCopilotSession(existing, newJsonlText) {
10648
- const prefix = existing.rawMessages.map((record4) => JSON.stringify(record4)).join("\n");
10656
+ const prefix = existing.rawMessages.map((record5) => JSON.stringify(record5)).join("\n");
10649
10657
  return parseCopilotSession(prefix ? `${prefix}
10650
10658
  ${newJsonlText}` : newJsonlText);
10651
10659
  }
@@ -10753,11 +10761,11 @@ function brandCopilotBranch() {
10753
10761
  function copilotTurnBoundaries(records) {
10754
10762
  const boundaries = [];
10755
10763
  for (let index = 0; index < records.length; index++) {
10756
- const record4 = records[index];
10757
- if (record4.type !== "user.message" || typeof record4.agentId === "string") continue;
10758
- const data = record4.data;
10764
+ const record5 = records[index];
10765
+ if (record5.type !== "user.message" || typeof record5.agentId === "string") continue;
10766
+ const data = record5.data;
10759
10767
  if (!data || typeof data !== "object" || Array.isArray(data)) continue;
10760
- if (typeof record4.id !== "string" || !record4.id) continue;
10768
+ if (typeof record5.id !== "string" || !record5.id) continue;
10761
10769
  boundaries.push(index);
10762
10770
  }
10763
10771
  return boundaries;
@@ -10814,14 +10822,14 @@ async function readCopilotSessionIdentity(filePath) {
10814
10822
  let cwd = "";
10815
10823
  let gitBranch = "";
10816
10824
  for (const line of await readHeadLines(filePath, HEAD_BYTES)) {
10817
- let record4;
10825
+ let record5;
10818
10826
  try {
10819
- record4 = JSON.parse(line);
10827
+ record5 = JSON.parse(line);
10820
10828
  } catch {
10821
10829
  continue;
10822
10830
  }
10823
- if (!isRecord3(record4) || record4.type !== "session.start" && record4.type !== "session.resume") continue;
10824
- const data = isRecord3(record4.data) ? record4.data : null;
10831
+ if (!isRecord3(record5) || record5.type !== "session.start" && record5.type !== "session.resume") continue;
10832
+ const data = isRecord3(record5.data) ? record5.data : null;
10825
10833
  if (!data) continue;
10826
10834
  if (typeof data.sessionId === "string" && data.sessionId) sessionId = data.sessionId;
10827
10835
  const context = isRecord3(data.context) ? data.context : null;
@@ -11013,15 +11021,15 @@ function readSender(attrs) {
11013
11021
  }
11014
11022
  return null;
11015
11023
  }
11016
- function parseAgentEnvelope(text) {
11024
+ function parseAgentEnvelope(text2) {
11017
11025
  let sender = null;
11018
11026
  let matched = false;
11019
- const unwrapped = text.replace(ENVELOPE_RE, (_full, _tag, attrs, inner) => {
11027
+ const unwrapped = text2.replace(ENVELOPE_RE, (_full, _tag, attrs, inner) => {
11020
11028
  matched = true;
11021
11029
  if (sender === null) sender = readSender(attrs);
11022
11030
  return inner.trim();
11023
11031
  });
11024
- return { sender, matched, body: matched ? unwrapped.trim() : text };
11032
+ return { sender, matched, body: matched ? unwrapped.trim() : text2 };
11025
11033
  }
11026
11034
  var ENVELOPE_RE, SENDER_PATTERNS;
11027
11035
  var init_agentEnvelope = __esm({
@@ -11055,9 +11063,9 @@ function isVisibleQueuedPrompt(content) {
11055
11063
  }
11056
11064
  function isTaskNotificationRecord(msg) {
11057
11065
  if (msg.origin?.kind === "task-notification") return true;
11058
- const text = extractTextFromContent(msg.message.content);
11059
- if (!text.includes("<task-notification>")) return false;
11060
- return text.replace(TASK_NOTIFICATION_BLOCK_RE, "").replace(ANY_TAG_RE, "").trim() === "";
11066
+ const text2 = extractTextFromContent(msg.message.content);
11067
+ if (!text2.includes("<task-notification>")) return false;
11068
+ return text2.replace(TASK_NOTIFICATION_BLOCK_RE, "").replace(ANY_TAG_RE, "").trim() === "";
11061
11069
  }
11062
11070
  function queuedCommandPrompt(msg) {
11063
11071
  if (!isAttachmentMessage(msg)) return null;
@@ -11109,8 +11117,8 @@ function mergeTokenUsage3(existing, incoming) {
11109
11117
  };
11110
11118
  }
11111
11119
  function extractCompactionSummary(content) {
11112
- const text = extractTextFromContent(content).trim();
11113
- return text.replace(RESUME_PREAMBLE_RE, "").replace(RESUME_INSTRUCTIONS_RE, "").trim();
11120
+ const text2 = extractTextFromContent(content).trim();
11121
+ return text2.replace(RESUME_PREAMBLE_RE, "").replace(RESUME_INSTRUCTIONS_RE, "").trim();
11114
11122
  }
11115
11123
  function normalizeCompactionMeta(meta) {
11116
11124
  if (!meta) return void 0;
@@ -11891,13 +11899,13 @@ function collectClaudeBackgroundWork(rawMessages) {
11891
11899
  const resolved = /* @__PURE__ */ new Set();
11892
11900
  const queuedIds = /* @__PURE__ */ new Set();
11893
11901
  const deliveredIds = /* @__PURE__ */ new Set();
11894
- function noteNotifications(text, sink) {
11895
- if (!text.includes(TASK_NOTIFICATION_MARKER)) return;
11896
- for (const match of text.matchAll(TASK_ID_RE)) {
11902
+ function noteNotifications(text2, sink) {
11903
+ if (!text2.includes(TASK_NOTIFICATION_MARKER)) return;
11904
+ for (const match of text2.matchAll(TASK_ID_RE)) {
11897
11905
  resolved.add(match[1]);
11898
11906
  sink?.add(match[1]);
11899
11907
  }
11900
- for (const match of text.matchAll(TOOL_USE_ID_RE)) {
11908
+ for (const match of text2.matchAll(TOOL_USE_ID_RE)) {
11901
11909
  resolved.add(match[1]);
11902
11910
  sink?.add(match[1]);
11903
11911
  }
@@ -11913,7 +11921,7 @@ function collectClaudeBackgroundWork(rawMessages) {
11913
11921
  const description = [toolUseResult.description, toolUseResult.workflowName, toolUseResult.summary].find((value) => typeof value === "string" && value.length > 0) ?? "";
11914
11922
  if (ids.length > 0) launches.push({ ids, description });
11915
11923
  }
11916
- for (const text of userMessageTexts(msg)) noteNotifications(text, deliveredIds);
11924
+ for (const text2 of userMessageTexts(msg)) noteNotifications(text2, deliveredIds);
11917
11925
  continue;
11918
11926
  }
11919
11927
  if (msg.type === "assistant") {
@@ -12181,12 +12189,12 @@ function isRecord4(value) {
12181
12189
  function nonEmpty(value) {
12182
12190
  return typeof value === "string" && value ? value : null;
12183
12191
  }
12184
- function stripTaggedBlocks(text) {
12185
- return text.replace(/<[^>]+>[\s\S]*?<\/[^>]+>/g, "").trim();
12192
+ function stripTaggedBlocks(text2) {
12193
+ return text2.replace(/<[^>]+>[\s\S]*?<\/[^>]+>/g, "").trim();
12186
12194
  }
12187
- function effortFromRecord(record4) {
12195
+ function effortFromRecord(record5) {
12188
12196
  for (const kind of AGENT_KINDS) {
12189
- const effort = READERS[kind].effort(record4);
12197
+ const effort = READERS[kind].effort(record5);
12190
12198
  if (effort) return effort;
12191
12199
  }
12192
12200
  return null;
@@ -12196,16 +12204,16 @@ function userMessageTextFromLine(line) {
12196
12204
  (kind) => READERS[kind].userMessageMarkers.some((marker) => line.includes(marker))
12197
12205
  );
12198
12206
  if (candidates.length === 0) return null;
12199
- let record4;
12207
+ let record5;
12200
12208
  try {
12201
- record4 = JSON.parse(line);
12209
+ record5 = JSON.parse(line);
12202
12210
  } catch {
12203
12211
  return null;
12204
12212
  }
12205
- if (!isRecord4(record4)) return null;
12213
+ if (!isRecord4(record5)) return null;
12206
12214
  for (const kind of candidates) {
12207
- const text = READERS[kind].userMessageText(record4);
12208
- if (text !== null) return text;
12215
+ const text2 = READERS[kind].userMessageText(record5);
12216
+ if (text2 !== null) return text2;
12209
12217
  }
12210
12218
  return null;
12211
12219
  }
@@ -12216,51 +12224,51 @@ var init_recordReaders = __esm({
12216
12224
  claudeReader = {
12217
12225
  kind: "claude",
12218
12226
  // Every assistant record is tagged with the effort that turn ran at.
12219
- effort: (record4) => record4.type === "assistant" ? nonEmpty(record4.effort) : null,
12227
+ effort: (record5) => record5.type === "assistant" ? nonEmpty(record5.effort) : null,
12220
12228
  userMessageMarkers: ['"user"'],
12221
- userMessageText(record4) {
12222
- if (record4.type !== "user" || record4.isMeta) return null;
12223
- const content = isRecord4(record4.message) ? record4.message.content : void 0;
12229
+ userMessageText(record5) {
12230
+ if (record5.type !== "user" || record5.isMeta) return null;
12231
+ const content = isRecord4(record5.message) ? record5.message.content : void 0;
12224
12232
  if (typeof content === "string") return stripTaggedBlocks(content);
12225
12233
  if (!Array.isArray(content)) return "";
12226
- let text = "";
12234
+ let text2 = "";
12227
12235
  for (const block of content) {
12228
12236
  if (isRecord4(block) && block.type === "text" && typeof block.text === "string") {
12229
- text += stripTaggedBlocks(block.text) + " ";
12237
+ text2 += stripTaggedBlocks(block.text) + " ";
12230
12238
  }
12231
12239
  }
12232
- return text.trim();
12240
+ return text2.trim();
12233
12241
  }
12234
12242
  };
12235
12243
  codexReader = {
12236
12244
  kind: "codex",
12237
12245
  // Effort is recorded per turn; newer CLI versions moved it under `thread_settings`.
12238
- effort(record4) {
12239
- if (record4.type !== "turn_context" || !isRecord4(record4.payload)) return null;
12240
- const { payload } = record4;
12246
+ effort(record5) {
12247
+ if (record5.type !== "turn_context" || !isRecord4(record5.payload)) return null;
12248
+ const { payload } = record5;
12241
12249
  const direct = nonEmpty(payload.effort);
12242
12250
  if (direct) return direct;
12243
12251
  const settings = isRecord4(payload.thread_settings) ? payload.thread_settings : null;
12244
12252
  return nonEmpty(settings?.reasoning_effort);
12245
12253
  },
12246
12254
  userMessageMarkers: ['"event_msg"'],
12247
- userMessageText(record4) {
12248
- if (record4.type !== "event_msg" || !isRecord4(record4.payload)) return null;
12249
- const { payload } = record4;
12255
+ userMessageText(record5) {
12256
+ if (record5.type !== "event_msg" || !isRecord4(record5.payload)) return null;
12257
+ const { payload } = record5;
12250
12258
  return payload.type === "user_message" && typeof payload.message === "string" ? payload.message.trim() : null;
12251
12259
  }
12252
12260
  };
12253
12261
  copilotReader = {
12254
12262
  kind: "copilot",
12255
- effort(record4) {
12256
- if (record4.type !== "session.start" && record4.type !== "session.resume" && record4.type !== "session.model_change" || !isRecord4(record4.data)) return null;
12257
- return nonEmpty(record4.data.reasoningEffort ?? record4.data.effort);
12263
+ effort(record5) {
12264
+ if (record5.type !== "session.start" && record5.type !== "session.resume" && record5.type !== "session.model_change" || !isRecord4(record5.data)) return null;
12265
+ return nonEmpty(record5.data.reasoningEffort ?? record5.data.effort);
12258
12266
  },
12259
12267
  userMessageMarkers: ['"user.message"'],
12260
- userMessageText(record4) {
12261
- if (record4.type !== "user.message") return null;
12262
- if (typeof record4.agentId === "string" && record4.agentId) return null;
12263
- const data = isRecord4(record4.data) ? record4.data : null;
12268
+ userMessageText(record5) {
12269
+ if (record5.type !== "user.message") return null;
12270
+ if (typeof record5.agentId === "string" && record5.agentId) return null;
12271
+ const data = isRecord4(record5.data) ? record5.data : null;
12264
12272
  return typeof data?.content === "string" ? data.content.trim() : "";
12265
12273
  }
12266
12274
  };
@@ -12273,16 +12281,16 @@ var init_recordReaders = __esm({
12273
12281
  });
12274
12282
 
12275
12283
  // ../../server/agents/tailRecords.ts
12276
- function isSubagentLifecycle(record4) {
12277
- return record4.type.startsWith("subagent.") && typeof record4.agentId === "string" && record4.agentId.length > 0;
12284
+ function isSubagentLifecycle(record5) {
12285
+ return record5.type.startsWith("subagent.") && typeof record5.agentId === "string" && record5.agentId.length > 0;
12278
12286
  }
12279
- function isSubagentNoise(record4) {
12280
- return typeof record4.agentId === "string" && record4.agentId.length > 0;
12287
+ function isSubagentNoise(record5) {
12288
+ return typeof record5.agentId === "string" && record5.agentId.length > 0;
12281
12289
  }
12282
- function classifyTailRecord(record4) {
12290
+ function classifyTailRecord(record5) {
12283
12291
  for (const kind of AGENT_KINDS) {
12284
12292
  const format = TAIL_FORMATS[kind];
12285
- const verdict = format.classify(record4);
12293
+ const verdict = format.classify(record5);
12286
12294
  if (verdict.kind !== "ignore") return { format, verdict };
12287
12295
  }
12288
12296
  return null;
@@ -12299,31 +12307,31 @@ var init_tailRecords = __esm({
12299
12307
  // Background agent/workflow launches, task notifications and TaskStop calls
12300
12308
  // can all still change a verdict that a turn-ending line looked to settle.
12301
12309
  markers: ["async_launched", "task-notification", '"TaskStop"'],
12302
- classify(record4) {
12303
- if (record4.type === "system" && record4.subtype === "terminal_reason") {
12304
- const reason = record4.reason;
12310
+ classify(record5) {
12311
+ if (record5.type === "system" && record5.subtype === "terminal_reason") {
12312
+ const reason = record5.reason;
12305
12313
  return reason ? { kind: "final", status: { status: "completed", terminalReason: reason } } : IGNORE;
12306
12314
  }
12307
- if (record4.type === "progress") {
12308
- const data = record4.data;
12315
+ if (record5.type === "progress") {
12316
+ const data = record5.data;
12309
12317
  if (data?.type !== "hook_progress") return IGNORE;
12310
12318
  const decision = data.decision ?? data.hookSpecificOutput?.permissionDecision;
12311
12319
  return decision === "defer" ? ANSWER : IGNORE;
12312
12320
  }
12313
- if (record4.type === "attachment") return KEEP;
12314
- if (record4.type === "assistant" || record4.type === "user" || record4.type === "queue-operation") {
12315
- const stopReason = record4.message?.stop_reason;
12316
- if (record4.type === "assistant" && stopReason === "end_turn") {
12321
+ if (record5.type === "attachment") return KEEP;
12322
+ if (record5.type === "assistant" || record5.type === "user" || record5.type === "queue-operation") {
12323
+ const stopReason = record5.message?.stop_reason;
12324
+ if (record5.type === "assistant" && stopReason === "end_turn") {
12317
12325
  return { kind: "turn-end", awaitUserActivity: true };
12318
12326
  }
12319
- const canDerive = record4.type === "assistant" || record4.type === "user" && !record4.isMeta;
12327
+ const canDerive = record5.type === "assistant" || record5.type === "user" && !record5.isMeta;
12320
12328
  return canDerive ? ANSWER : KEEP;
12321
12329
  }
12322
12330
  return IGNORE;
12323
12331
  },
12324
- classifyAfterTurnEnd(record4) {
12325
- if (record4.type !== "user" && record4.type !== "assistant" && record4.type !== "queue-operation" && record4.type !== "attachment") return IGNORE;
12326
- const isRealUserTurn = record4.type === "user" && !record4.isMeta;
12332
+ classifyAfterTurnEnd(record5) {
12333
+ if (record5.type !== "user" && record5.type !== "assistant" && record5.type !== "queue-operation" && record5.type !== "attachment") return IGNORE;
12334
+ const isRealUserTurn = record5.type === "user" && !record5.isMeta;
12327
12335
  return { kind: "keep", sawUserActivity: isRealUserTurn };
12328
12336
  }
12329
12337
  };
@@ -12342,9 +12350,9 @@ var init_tailRecords = __esm({
12342
12350
  "agent_message",
12343
12351
  "function_call_output"
12344
12352
  ],
12345
- classify(record4) {
12346
- if (record4.type === "event_msg") {
12347
- const payload = record4.payload;
12353
+ classify(record5) {
12354
+ if (record5.type === "event_msg") {
12355
+ const payload = record5.payload;
12348
12356
  switch (payload?.type) {
12349
12357
  case "task_complete":
12350
12358
  return { kind: "turn-end" };
@@ -12356,32 +12364,32 @@ var init_tailRecords = __esm({
12356
12364
  return IGNORE;
12357
12365
  }
12358
12366
  }
12359
- if (record4.type === "response_item") {
12360
- const payload = record4.payload;
12367
+ if (record5.type === "response_item") {
12368
+ const payload = record5.payload;
12361
12369
  const decides = payload?.type === "function_call" || payload?.type === "message" && (payload.role === "assistant" || payload.role === "user");
12362
12370
  return decides ? ANSWER : IGNORE;
12363
12371
  }
12364
12372
  return IGNORE;
12365
12373
  },
12366
- classifyAfterTurnEnd(record4) {
12367
- return record4.type === "event_msg" || record4.type === "response_item" ? KEEP : IGNORE;
12374
+ classifyAfterTurnEnd(record5) {
12375
+ return record5.type === "event_msg" || record5.type === "response_item" ? KEEP : IGNORE;
12368
12376
  }
12369
12377
  };
12370
12378
  copilotTail = {
12371
12379
  kind: "copilot",
12372
12380
  markers: ['"abort"', '"assistant.message"', '"user.message"', '"subagent.'],
12373
- classify(record4) {
12374
- if (isSubagentLifecycle(record4)) return KEEP;
12375
- 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.");
12376
- if (!decidable || isSubagentNoise(record4)) return IGNORE;
12377
- if (record4.type === "assistant.turn_end") return { kind: "turn-end" };
12378
- if (record4.type === "session.start" || record4.type === "session.resume") return ANSWER;
12381
+ classify(record5) {
12382
+ if (isSubagentLifecycle(record5)) return KEEP;
12383
+ const decidable = record5.type === "abort" || record5.type === "user.message" || record5.type.startsWith("assistant.") || record5.type.startsWith("permission.") || record5.type.startsWith("session.") || record5.type.startsWith("tool.") || record5.type.startsWith("user_input.");
12384
+ if (!decidable || isSubagentNoise(record5)) return IGNORE;
12385
+ if (record5.type === "assistant.turn_end") return { kind: "turn-end" };
12386
+ if (record5.type === "session.start" || record5.type === "session.resume") return ANSWER;
12379
12387
  return { kind: "answer-if-active" };
12380
12388
  },
12381
- classifyAfterTurnEnd(record4) {
12382
- if (isSubagentLifecycle(record4)) return KEEP;
12383
- if (isSubagentNoise(record4)) return IGNORE;
12384
- const decides = record4.type === "abort" || record4.type === "assistant.message" || record4.type === "user.message";
12389
+ classifyAfterTurnEnd(record5) {
12390
+ if (isSubagentLifecycle(record5)) return KEEP;
12391
+ if (isSubagentNoise(record5)) return IGNORE;
12392
+ const decides = record5.type === "abort" || record5.type === "assistant.message" || record5.type === "user.message";
12385
12393
  return decides ? ANSWER : IGNORE;
12386
12394
  }
12387
12395
  };
@@ -12436,14 +12444,14 @@ async function readTranscriptEffort(filePath) {
12436
12444
  for (let i = lines.length - 1; i >= 0; i--) {
12437
12445
  const line = lines[i];
12438
12446
  if (!line || !line.includes("effort") && !line.includes("Effort")) continue;
12439
- let record4;
12447
+ let record5;
12440
12448
  try {
12441
- record4 = JSON.parse(line);
12449
+ record5 = JSON.parse(line);
12442
12450
  } catch {
12443
12451
  continue;
12444
12452
  }
12445
- if (typeof record4 !== "object" || record4 === null) continue;
12446
- const effort = effortFromRecord(record4);
12453
+ if (typeof record5 !== "object" || record5 === null) continue;
12454
+ const effort = effortFromRecord(record5);
12447
12455
  if (effort) return effort;
12448
12456
  }
12449
12457
  }
@@ -12471,22 +12479,22 @@ async function getSessionStatus(filePath) {
12471
12479
  cursor -= readSize;
12472
12480
  const buf = Buffer.alloc(readSize);
12473
12481
  const { bytesRead } = await fh.read(buf, 0, readSize, cursor);
12474
- const text = buf.subarray(0, bytesRead).toString("utf-8") + leftover;
12475
- const lines = text.split("\n");
12482
+ const text2 = buf.subarray(0, bytesRead).toString("utf-8") + leftover;
12483
+ const lines = text2.split("\n");
12476
12484
  leftover = cursor > 0 ? lines[0] : "";
12477
12485
  const startIdx = cursor > 0 ? 1 : 0;
12478
12486
  for (let i = lines.length - 1; i >= startIdx; i--) {
12479
12487
  const line = lines[i];
12480
12488
  if (!line) continue;
12481
12489
  if (turnEnded && !isTailCandidate(line, turnEnded)) continue;
12482
- let record4;
12490
+ let record5;
12483
12491
  try {
12484
- record4 = JSON.parse(line);
12492
+ record5 = JSON.parse(line);
12485
12493
  } catch {
12486
12494
  continue;
12487
12495
  }
12488
- if (typeof record4?.type !== "string") continue;
12489
- const match = turnEnded ? { format: turnEnded, verdict: turnEnded.classifyAfterTurnEnd(record4) } : classifyTailRecord(record4);
12496
+ if (typeof record5?.type !== "string") continue;
12497
+ const match = turnEnded ? { format: turnEnded, verdict: turnEnded.classifyAfterTurnEnd(record5) } : classifyTailRecord(record5);
12490
12498
  if (!match) continue;
12491
12499
  const { verdict } = match;
12492
12500
  switch (verdict.kind) {
@@ -12495,20 +12503,20 @@ async function getSessionStatus(filePath) {
12495
12503
  case "final":
12496
12504
  return verdict.status;
12497
12505
  case "keep":
12498
- meaningful.unshift(record4);
12506
+ meaningful.unshift(record5);
12499
12507
  if (verdict.sawUserActivity) needUserActivity = false;
12500
12508
  continue;
12501
12509
  case "answer":
12502
- meaningful.unshift(record4);
12510
+ meaningful.unshift(record5);
12503
12511
  return deriveSessionStatus(meaningful);
12504
12512
  case "answer-if-active": {
12505
- meaningful.unshift(record4);
12513
+ meaningful.unshift(record5);
12506
12514
  const status = deriveSessionStatus(meaningful);
12507
12515
  if (status.status !== "idle") return status;
12508
12516
  continue;
12509
12517
  }
12510
12518
  case "turn-end":
12511
- meaningful.unshift(record4);
12519
+ meaningful.unshift(record5);
12512
12520
  turnEnded = match.format;
12513
12521
  needUserActivity = verdict.awaitUserActivity === true;
12514
12522
  continue;
@@ -12523,12 +12531,12 @@ async function getSessionStatus(filePath) {
12523
12531
  return { status: "idle" };
12524
12532
  }
12525
12533
  }
12526
- function snippetAround(text, query4) {
12527
- const lower = text.toLowerCase();
12534
+ function snippetAround(text2, query4) {
12535
+ const lower = text2.toLowerCase();
12528
12536
  const idx = lower.indexOf(query4.toLowerCase());
12529
12537
  const start = Math.max(0, idx - 30);
12530
- const end = Math.min(text.length, idx + query4.length + 70);
12531
- const snippet = (start > 0 ? "..." : "") + text.slice(start, end).trim() + (end < text.length ? "..." : "");
12538
+ const end = Math.min(text2.length, idx + query4.length + 70);
12539
+ const snippet = (start > 0 ? "..." : "") + text2.slice(start, end).trim() + (end < text2.length ? "..." : "");
12532
12540
  return snippet.slice(0, 150);
12533
12541
  }
12534
12542
  async function searchSessionMessages(filePath, query4) {
@@ -12540,8 +12548,8 @@ async function searchSessionMessages(filePath, query4) {
12540
12548
  return null;
12541
12549
  }
12542
12550
  for (const line of content.split("\n")) {
12543
- const text = userMessageTextFromLine(line);
12544
- if (text !== null && text.toLowerCase().includes(q)) return snippetAround(text, query4);
12551
+ const text2 = userMessageTextFromLine(line);
12552
+ if (text2 !== null && text2.toLowerCase().includes(q)) return snippetAround(text2, query4);
12545
12553
  }
12546
12554
  return null;
12547
12555
  }
@@ -12847,10 +12855,10 @@ function transcriptPath2(dirName, sessionId) {
12847
12855
  }
12848
12856
  function turnResultFrom(result) {
12849
12857
  if (!result.is_error) return { isError: false };
12850
- const { result: text, subtype } = result;
12858
+ const { result: text2, subtype } = result;
12851
12859
  return {
12852
12860
  isError: true,
12853
- message: text != null ? String(text) : `Claude returned an error${subtype ? ` (${subtype})` : ""}`
12861
+ message: text2 != null ? String(text2) : `Claude returned an error${subtype ? ` (${subtype})` : ""}`
12854
12862
  };
12855
12863
  }
12856
12864
  async function awaitTranscript(filePath, isSettled) {
@@ -13200,7 +13208,7 @@ var init_package = __esm({
13200
13208
  package_default = {
13201
13209
  name: "cogpit",
13202
13210
  private: true,
13203
- version: "2.4.0",
13211
+ version: "2.4.2",
13204
13212
  description: "Control center for Claude Code, OpenAI Codex, and GitHub Copilot CLI sessions",
13205
13213
  license: "MIT",
13206
13214
  author: {
@@ -16209,17 +16217,17 @@ function parseJsonRecord(line) {
16209
16217
  }
16210
16218
  }
16211
16219
  function parseClaudeUsageLine(line) {
16212
- const record4 = parseJsonRecord(line);
16213
- if (!record4 || record4.type !== "assistant") return null;
16214
- const message = asRecord3(record4.message);
16220
+ const record5 = parseJsonRecord(line);
16221
+ if (!record5 || record5.type !== "assistant") return null;
16222
+ const message = asRecord3(record5.message);
16215
16223
  const usage = message ? asRecord3(message.usage) : null;
16216
16224
  if (!message || !usage) return null;
16217
- const timestampMs = parseTimestampMs(record4.timestamp);
16225
+ const timestampMs = parseTimestampMs(record5.timestamp);
16218
16226
  if (timestampMs === null) return null;
16219
16227
  const model = typeof message.model === "string" ? message.model : "";
16220
16228
  if (model.length === 0) return null;
16221
16229
  const messageId = typeof message.id === "string" ? message.id : null;
16222
- const requestId = typeof record4.requestId === "string" ? record4.requestId : null;
16230
+ const requestId = typeof record5.requestId === "string" ? record5.requestId : null;
16223
16231
  const dedupeKey = messageId === null && requestId === null ? null : `${messageId ?? ""}:${requestId ?? ""}`;
16224
16232
  const cacheCreationTokens = int(usage.cache_creation_input_tokens);
16225
16233
  const byTtl = asRecord3(usage.cache_creation);
@@ -16238,12 +16246,12 @@ function parseClaudeUsageLine(line) {
16238
16246
  reasoningTokens: 0
16239
16247
  };
16240
16248
  if (totalUsageCostTokens(totals) === 0) return null;
16241
- const cost = record4.costUSD;
16249
+ const cost = record5.costUSD;
16242
16250
  return {
16243
16251
  provider: "claude",
16244
16252
  timestampMs,
16245
16253
  model,
16246
- sessionId: typeof record4.sessionId === "string" ? record4.sessionId : "",
16254
+ sessionId: typeof record5.sessionId === "string" ? record5.sessionId : "",
16247
16255
  totals,
16248
16256
  reportedCostUsd: typeof cost === "number" && Number.isFinite(cost) ? cost : null,
16249
16257
  speed: requestSpeed(usage.speed ?? usage.service_tier),
@@ -16267,23 +16275,23 @@ function isForkedSessionMeta(payload) {
16267
16275
  return typeof spawn5?.parent_thread_id === "string";
16268
16276
  }
16269
16277
  function parseCodexUsageLine(line, state) {
16270
- const record4 = parseJsonRecord(line);
16271
- if (!record4) return null;
16272
- const payload = asRecord3(record4.payload);
16278
+ const record5 = parseJsonRecord(line);
16279
+ if (!record5) return null;
16280
+ const payload = asRecord3(record5.payload);
16273
16281
  if (!payload) return null;
16274
- if (record4.type === "session_meta") {
16282
+ if (record5.type === "session_meta") {
16275
16283
  if (state.sawSessionMeta) return null;
16276
16284
  state.sawSessionMeta = true;
16277
16285
  const id = payload.id ?? payload.session_id;
16278
16286
  if (typeof id === "string") state.sessionId = id;
16279
- const metaTimestampMs = parseTimestampMs(record4.timestamp);
16287
+ const metaTimestampMs = parseTimestampMs(record5.timestamp);
16280
16288
  if (metaTimestampMs !== null && isForkedSessionMeta(payload)) {
16281
16289
  state.suppressingForkCopies = true;
16282
16290
  state.forkCopyAnchorMs = metaTimestampMs;
16283
16291
  }
16284
16292
  return null;
16285
16293
  }
16286
- if (record4.type === "turn_context") {
16294
+ if (record5.type === "turn_context") {
16287
16295
  if (typeof payload.model === "string") state.model = payload.model;
16288
16296
  return null;
16289
16297
  }
@@ -16297,7 +16305,7 @@ function parseCodexUsageLine(line, state) {
16297
16305
  if (payload.type !== "token_count") return null;
16298
16306
  const last = asRecord3(asRecord3(payload.info)?.last_token_usage);
16299
16307
  if (!last) return null;
16300
- const timestampMs = parseTimestampMs(record4.timestamp);
16308
+ const timestampMs = parseTimestampMs(record5.timestamp);
16301
16309
  if (timestampMs === null) return null;
16302
16310
  if (state.model.length === 0) return null;
16303
16311
  const signature = JSON.stringify(last);
@@ -16398,17 +16406,17 @@ function parseCopilotUsageMetrics(value, state, timestampMs) {
16398
16406
  return records;
16399
16407
  }
16400
16408
  function parseCopilotUsageLine(line, state) {
16401
- const record4 = parseJsonRecord(line);
16402
- if (!record4 || typeof record4.agentId === "string" && record4.agentId.length > 0) return [];
16403
- const data = asRecord3(record4.data);
16409
+ const record5 = parseJsonRecord(line);
16410
+ if (!record5 || typeof record5.agentId === "string" && record5.agentId.length > 0) return [];
16411
+ const data = asRecord3(record5.data);
16404
16412
  if (!data) return [];
16405
- if (record4.type === "session.start") {
16413
+ if (record5.type === "session.start") {
16406
16414
  const sessionId = data.sessionId;
16407
16415
  if (typeof sessionId === "string" && sessionId.length > 0) state.sessionId = sessionId;
16408
16416
  return [];
16409
16417
  }
16410
- if (record4.type !== "session.shutdown") return [];
16411
- const timestampMs = parseTimestampMs(record4.timestamp);
16418
+ if (record5.type !== "session.shutdown") return [];
16419
+ const timestampMs = parseTimestampMs(record5.timestamp);
16412
16420
  return timestampMs === null ? [] : parseCopilotUsageMetrics(data, state, timestampMs);
16413
16421
  }
16414
16422
  function createUsageScanner(provider, filePath) {
@@ -16425,8 +16433,8 @@ var init_usageScanners = __esm({
16425
16433
  // object, so a line is either self-contained or of no interest.
16426
16434
  wantsLine: (line) => line.includes('"usage"'),
16427
16435
  accept: (line) => {
16428
- const record4 = parseClaudeUsageLine(line);
16429
- return record4 === null ? [] : [record4];
16436
+ const record5 = parseClaudeUsageLine(line);
16437
+ return record5 === null ? [] : [record5];
16430
16438
  }
16431
16439
  }),
16432
16440
  codex: () => {
@@ -16437,8 +16445,8 @@ var init_usageScanners = __esm({
16437
16445
  // at all but still have to reach the reducer.
16438
16446
  wantsLine: (line) => line.includes('"token_count"') || line.includes('"turn_context"') || line.includes('"session_meta"') || line.includes('"thread_settings_applied"'),
16439
16447
  accept: (line) => {
16440
- const record4 = parseCodexUsageLine(line, state);
16441
- return record4 === null ? [] : [record4];
16448
+ const record5 = parseCodexUsageLine(line, state);
16449
+ return record5 === null ? [] : [record5];
16442
16450
  }
16443
16451
  };
16444
16452
  },
@@ -17161,7 +17169,7 @@ async function releaseInspectedSession(sessionId, state, runtime) {
17161
17169
  });
17162
17170
  }
17163
17171
  }
17164
- async function respondFromInspectedSession(res, sessionId, runtime, failureMessage, operation) {
17172
+ async function respondFromInspectedSession(res, sessionId, runtime, failureMessage2, operation) {
17165
17173
  let state = null;
17166
17174
  try {
17167
17175
  state = await ensureCopilotSession(sessionId, runtime);
@@ -17172,7 +17180,7 @@ async function respondFromInspectedSession(res, sessionId, runtime, failureMessa
17172
17180
  sendJson(res, 200, await operation());
17173
17181
  } catch (error) {
17174
17182
  sendJson(res, 502, {
17175
- error: error instanceof Error ? error.message : failureMessage
17183
+ error: error instanceof Error ? error.message : failureMessage2
17176
17184
  });
17177
17185
  } finally {
17178
17186
  await releaseInspectedSession(sessionId, state, runtime);
@@ -17687,12 +17695,12 @@ function registerBranchSessionRoute(use) {
17687
17695
  }
17688
17696
  }
17689
17697
  const newSessionId = randomUUID2();
17690
- const { record: record4, originalId } = format.brandBranch(
17698
+ const { record: record5, originalId } = format.brandBranch(
17691
17699
  JSON.parse(lines[0]),
17692
17700
  newSessionId,
17693
17701
  turnIndex ?? null
17694
17702
  );
17695
- lines[0] = JSON.stringify(record4);
17703
+ lines[0] = JSON.stringify(record5);
17696
17704
  const target = storeForDirName(dirName).transcriptPath(dirName, newSessionId);
17697
17705
  if (!target) {
17698
17706
  res.statusCode = 500;
@@ -20656,9 +20664,9 @@ function registerFileWatchRoutes(use) {
20656
20664
  if (bytesRead <= 0) return;
20657
20665
  offset += bytesRead;
20658
20666
  recordActivity("Task output reads", { bytes: bytesRead });
20659
- const text = decoder.write(buf.subarray(0, bytesRead));
20660
- if (text) {
20661
- res.write(`data: ${JSON.stringify({ type: "output", text })}
20667
+ const text2 = decoder.write(buf.subarray(0, bytesRead));
20668
+ if (text2) {
20669
+ res.write(`data: ${JSON.stringify({ type: "output", text: text2 })}
20662
20670
 
20663
20671
  `);
20664
20672
  }
@@ -21262,11 +21270,11 @@ function parseGitStatus(output) {
21262
21270
  const branch = parseBranchHeader(header);
21263
21271
  const files = [];
21264
21272
  for (let index = 0; index < records.length; index += 1) {
21265
- const record4 = records[index];
21266
- if (!record4 || record4.length < 3) continue;
21267
- const indexStatus = record4[0];
21268
- const workTreeStatus = record4[1];
21269
- const path = record4.slice(3);
21273
+ const record5 = records[index];
21274
+ if (!record5 || record5.length < 3) continue;
21275
+ const indexStatus = record5[0];
21276
+ const workTreeStatus = record5[1];
21277
+ const path = record5.slice(3);
21270
21278
  const renamedOrCopied = /[RC]/.test(`${indexStatus}${workTreeStatus}`);
21271
21279
  const originalPath = renamedOrCopied ? records[index += 1] || void 0 : void 0;
21272
21280
  files.push({ path, originalPath, indexStatus, workTreeStatus });
@@ -21482,12 +21490,12 @@ function createPullRequestScanner() {
21482
21490
  const command = findCreateCommand(input);
21483
21491
  if (command) openCreates.set(id, { command, timestamp: timestamp2 });
21484
21492
  }
21485
- function recordPrLink(record4, timestamp2) {
21486
- const url = record4.prUrl;
21487
- const number = record4.prNumber;
21493
+ function recordPrLink(record5, timestamp2) {
21494
+ const url = record5.prUrl;
21495
+ const number = record5.prNumber;
21488
21496
  if (typeof url !== "string" || !url) return;
21489
21497
  if (typeof number !== "number" || !Number.isInteger(number) || number <= 0) return;
21490
- const repo = typeof record4.prRepository === "string" ? record4.prRepository : "";
21498
+ const repo = typeof record5.prRepository === "string" ? record5.prRepository : "";
21491
21499
  collector.add({
21492
21500
  url,
21493
21501
  number,
@@ -21503,9 +21511,9 @@ function createPullRequestScanner() {
21503
21511
  if (typeof id !== "string") return;
21504
21512
  const create = openCreates.get(id);
21505
21513
  if (!create || isError) return;
21506
- const text = resultText(output);
21507
- collector.record(text, create.command, id, create.timestamp);
21508
- const match = PR_URL.exec(text);
21514
+ const text2 = resultText(output);
21515
+ collector.record(text2, create.command, id, create.timestamp);
21516
+ const match = PR_URL.exec(text2);
21509
21517
  if (match) recordReference({ number: Number(match[3]), repo: `${match[1]}/${match[2]}` });
21510
21518
  }
21511
21519
  function parseArgs2(raw) {
@@ -21522,19 +21530,19 @@ function createPullRequestScanner() {
21522
21530
  if (!line.includes(GH_PR_HINT) && !line.includes(URL_HINT) && !line.includes(PR_LINK_HINT)) {
21523
21531
  return;
21524
21532
  }
21525
- let record4;
21533
+ let record5;
21526
21534
  try {
21527
- record4 = JSON.parse(line);
21535
+ record5 = JSON.parse(line);
21528
21536
  } catch {
21529
21537
  return;
21530
21538
  }
21531
- if (!isRecord5(record4)) return;
21532
- const timestamp2 = typeof record4.timestamp === "string" ? record4.timestamp : "";
21533
- if (record4.type === "pr-link") {
21534
- recordPrLink(record4, timestamp2);
21539
+ if (!isRecord5(record5)) return;
21540
+ const timestamp2 = typeof record5.timestamp === "string" ? record5.timestamp : "";
21541
+ if (record5.type === "pr-link") {
21542
+ recordPrLink(record5, timestamp2);
21535
21543
  return;
21536
21544
  }
21537
- const payload = record4.payload;
21545
+ const payload = record5.payload;
21538
21546
  if (isRecord5(payload)) {
21539
21547
  const type = payload.type;
21540
21548
  if (type === "function_call" || type === "custom_tool_call") {
@@ -21544,15 +21552,15 @@ function createPullRequestScanner() {
21544
21552
  }
21545
21553
  return;
21546
21554
  }
21547
- const data = record4.data;
21555
+ const data = record5.data;
21548
21556
  if (isRecord5(data)) {
21549
- if (record4.type === "tool.execution_start") {
21557
+ if (record5.type === "tool.execution_start") {
21550
21558
  recordToolCall(
21551
21559
  data.toolCallId,
21552
21560
  parseArgs2(data.arguments ?? data.input),
21553
21561
  timestamp2
21554
21562
  );
21555
- } else if (record4.type === "tool.execution_complete") {
21563
+ } else if (record5.type === "tool.execution_complete") {
21556
21564
  recordResult(
21557
21565
  data.toolCallId,
21558
21566
  data.result ?? data.output ?? data.error,
@@ -21561,7 +21569,7 @@ function createPullRequestScanner() {
21561
21569
  }
21562
21570
  return;
21563
21571
  }
21564
- const message = record4.message;
21572
+ const message = record5.message;
21565
21573
  if (!isRecord5(message) || !Array.isArray(message.content)) return;
21566
21574
  for (const block of message.content) {
21567
21575
  if (!isRecord5(block)) continue;
@@ -22438,9 +22446,9 @@ function deploymentState(value) {
22438
22446
  return typeof value === "string" && DEPLOYMENT_STATES.has(value) ? value : "QUEUED";
22439
22447
  }
22440
22448
  function httpsUrl(value, hostnameOnly = false) {
22441
- const text = stringValue2(value);
22442
- if (!text) return null;
22443
- const candidate = hostnameOnly && !text.includes("://") ? `https://${text}` : text;
22449
+ const text2 = stringValue2(value);
22450
+ if (!text2) return null;
22451
+ const candidate = hostnameOnly && !text2.includes("://") ? `https://${text2}` : text2;
22444
22452
  try {
22445
22453
  const url = new URL(candidate);
22446
22454
  return url.protocol === "https:" ? url.toString().replace(/\/$/, "") : null;
@@ -22516,13 +22524,13 @@ function parseBuildLog(value) {
22516
22524
  const source = record3(value);
22517
22525
  if (!source) return null;
22518
22526
  const createdAt = timestamp(source.created) ?? timestamp(source.date);
22519
- const text = stringValue2(source.text);
22520
- if (createdAt === null || !text) return null;
22527
+ const text2 = stringValue2(source.text);
22528
+ if (createdAt === null || !text2) return null;
22521
22529
  return {
22522
- id: stringValue2(source.id, `${createdAt}-${text}`),
22530
+ id: stringValue2(source.id, `${createdAt}-${text2}`),
22523
22531
  createdAt,
22524
22532
  type: stringValue2(source.type, "stdout"),
22525
- text
22533
+ text: text2
22526
22534
  };
22527
22535
  }
22528
22536
  function parseBuildLogsResponse(value) {
@@ -22759,14 +22767,440 @@ var init_vercel_deployments = __esm({
22759
22767
  }
22760
22768
  });
22761
22769
 
22770
+ // ../../server/lib/clickupConfig.ts
22771
+ import { mkdir as mkdir6, readFile as readFile17 } from "node:fs/promises";
22772
+ import { homedir as homedir7 } from "node:os";
22773
+ import { dirname as dirname9, join as join22 } from "node:path";
22774
+ function isClickUpToken(value) {
22775
+ return typeof value === "string" && TOKEN_PATTERN.test(value);
22776
+ }
22777
+ async function readStored() {
22778
+ let raw;
22779
+ try {
22780
+ raw = await readFile17(configPath, "utf8");
22781
+ } catch {
22782
+ return {};
22783
+ }
22784
+ try {
22785
+ const parsed = JSON.parse(raw);
22786
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
22787
+ const source = parsed;
22788
+ const projects = {};
22789
+ const storedProjects = source.projects;
22790
+ if (typeof storedProjects === "object" && storedProjects !== null) {
22791
+ for (const [path, listId] of Object.entries(storedProjects)) {
22792
+ if (typeof listId === "string" && /^\d+$/.test(listId)) projects[path] = listId;
22793
+ }
22794
+ }
22795
+ return { token: isClickUpToken(source.token) ? source.token : void 0, projects };
22796
+ } catch {
22797
+ return {};
22798
+ }
22799
+ }
22800
+ async function loadClickUpConfig() {
22801
+ const stored = await readStored();
22802
+ const envToken = TOKEN_ENV_VARS.map((name) => process.env[name]?.trim()).find(isClickUpToken);
22803
+ if (envToken) {
22804
+ return { token: envToken, tokenFromEnv: true, projects: stored.projects ?? {} };
22805
+ }
22806
+ return { token: stored.token ?? null, tokenFromEnv: false, projects: stored.projects ?? {} };
22807
+ }
22808
+ async function writeStored(next) {
22809
+ await mkdir6(dirname9(configPath), { recursive: true });
22810
+ const file = { projects: next.projects ?? {} };
22811
+ if (next.token) file.token = next.token;
22812
+ await writeOwnerOnlyJson(configPath, file);
22813
+ }
22814
+ async function saveClickUpToken(token) {
22815
+ const stored = await readStored();
22816
+ await writeStored({ ...stored, token: token ?? void 0 });
22817
+ }
22818
+ async function saveClickUpProjectLink(projectPath, listId) {
22819
+ const stored = await readStored();
22820
+ const projects = { ...stored.projects };
22821
+ if (listId === null) delete projects[projectPath];
22822
+ else projects[projectPath] = listId;
22823
+ await writeStored({ ...stored, projects });
22824
+ }
22825
+ var CLICKUP_CONFIG_FILE, TOKEN_PATTERN, configPath, TOKEN_ENV_VARS;
22826
+ var init_clickupConfig = __esm({
22827
+ "../../server/lib/clickupConfig.ts"() {
22828
+ init_atomicJsonFile();
22829
+ CLICKUP_CONFIG_FILE = join22(homedir7(), ".cogpit", "clickup.json");
22830
+ TOKEN_PATTERN = /^pk_[A-Za-z0-9_]{8,}$/;
22831
+ configPath = CLICKUP_CONFIG_FILE;
22832
+ TOKEN_ENV_VARS = ["COGPIT_CLICKUP_TOKEN", "CLICKUP_API_TOKEN"];
22833
+ }
22834
+ });
22835
+
22836
+ // ../../server/routes/clickup.ts
22837
+ function record4(value) {
22838
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
22839
+ }
22840
+ function text(value, fallback = "") {
22841
+ return typeof value === "string" ? value : fallback;
22842
+ }
22843
+ function idText(value) {
22844
+ if (typeof value === "number") return String(value);
22845
+ return text(value);
22846
+ }
22847
+ function epoch(value) {
22848
+ const parsed = typeof value === "string" ? Number(value) : value;
22849
+ return typeof parsed === "number" && Number.isFinite(parsed) && parsed > 0 ? parsed : null;
22850
+ }
22851
+ function folderNameOf(value) {
22852
+ const folder = record4(value);
22853
+ return folder && folder.hidden !== true ? text(folder.name) || null : null;
22854
+ }
22855
+ function invalid(what) {
22856
+ return new ClickUpRouteError(502, "invalid_response", `ClickUp returned an invalid ${what} response`);
22857
+ }
22858
+ function parseUser(value) {
22859
+ const source = record4(value);
22860
+ if (!source || typeof source.id !== "number") return null;
22861
+ const username = text(source.username) || text(source.email);
22862
+ return {
22863
+ id: source.id,
22864
+ username,
22865
+ initials: text(source.initials) || username.slice(0, 2).toUpperCase(),
22866
+ color: text(source.color) || null
22867
+ };
22868
+ }
22869
+ function parseViewerResponse(value) {
22870
+ const viewer = parseUser(record4(value)?.user);
22871
+ if (!viewer) throw invalid("user");
22872
+ return viewer;
22873
+ }
22874
+ function parseNamedEntities(entries3, fallbackName) {
22875
+ return entries3.flatMap((entry) => {
22876
+ const source = record4(entry);
22877
+ const id = idText(source?.id);
22878
+ return source && NUMERIC_ID.test(id) ? [{ id, name: text(source.name, fallbackName) }] : [];
22879
+ });
22880
+ }
22881
+ function parseWorkspacesResponse(value) {
22882
+ const teams = record4(value)?.teams;
22883
+ if (!Array.isArray(teams)) throw invalid("workspace");
22884
+ return parseNamedEntities(teams, "Workspace");
22885
+ }
22886
+ function parseStatus(value) {
22887
+ const source = record4(value);
22888
+ if (!source) return null;
22889
+ const name = text(source.status);
22890
+ if (!name) return null;
22891
+ const type = text(source.type);
22892
+ return {
22893
+ name,
22894
+ type: STATUS_TYPES.has(type) ? type : "custom",
22895
+ color: text(source.color, "#d3d3d3"),
22896
+ order: typeof source.orderindex === "number" ? source.orderindex : 0
22897
+ };
22898
+ }
22899
+ function parseTag(value) {
22900
+ const source = record4(value);
22901
+ const name = text(source?.name);
22902
+ return name ? { name, background: text(source?.tag_bg) || null } : null;
22903
+ }
22904
+ function parsePriority(value) {
22905
+ const name = text(record4(value)?.priority);
22906
+ return PRIORITIES.has(name) ? name : null;
22907
+ }
22908
+ function parseTask(value) {
22909
+ const source = record4(value);
22910
+ if (!source) return null;
22911
+ const id = text(source.id);
22912
+ const status = parseStatus(source.status);
22913
+ const list = record4(source.list);
22914
+ if (!id || !status || !list) return null;
22915
+ const customId = text(source.custom_id);
22916
+ return {
22917
+ id,
22918
+ customId: customId || null,
22919
+ name: text(source.name, "Untitled task"),
22920
+ description: text(source.markdown_description) || text(source.description),
22921
+ status,
22922
+ priority: parsePriority(source.priority),
22923
+ url: text(source.url) || `https://app.clickup.com/t/${id}`,
22924
+ assignees: Array.isArray(source.assignees) ? source.assignees.map(parseUser).filter((user) => user !== null) : [],
22925
+ tags: Array.isArray(source.tags) ? source.tags.map(parseTag).filter((tag) => tag !== null) : [],
22926
+ parentId: text(source.parent) || null,
22927
+ listId: idText(list.id),
22928
+ listName: text(list.name, "List"),
22929
+ folderName: folderNameOf(source.folder),
22930
+ spaceId: idText(record4(source.space)?.id),
22931
+ createdAt: epoch(source.date_created) ?? 0,
22932
+ updatedAt: epoch(source.date_updated) ?? epoch(source.date_created) ?? 0,
22933
+ dueAt: epoch(source.due_date),
22934
+ startAt: epoch(source.start_date),
22935
+ closedAt: epoch(source.date_closed) ?? epoch(source.date_done)
22936
+ };
22937
+ }
22938
+ function parseTasksPage(value) {
22939
+ const source = record4(value);
22940
+ if (!source || !Array.isArray(source.tasks)) throw invalid("task list");
22941
+ return {
22942
+ tasks: source.tasks.map(parseTask).filter((task) => task !== null),
22943
+ lastPage: source.last_page !== false
22944
+ };
22945
+ }
22946
+ function parseListResponse(value) {
22947
+ const source = record4(value);
22948
+ const id = idText(source?.id);
22949
+ if (!source || !NUMERIC_ID.test(id)) throw invalid("list");
22950
+ const statuses = Array.isArray(source.statuses) ? source.statuses.map(parseStatus).filter((status) => status !== null) : [];
22951
+ return {
22952
+ id,
22953
+ name: text(source.name, "List"),
22954
+ folderName: folderNameOf(source.folder),
22955
+ spaceId: idText(record4(source.space)?.id),
22956
+ statuses: statuses.sort((left, right) => left.order - right.order),
22957
+ url: `https://app.clickup.com/v/li/${id}`
22958
+ };
22959
+ }
22960
+ function parseSpacesResponse(value) {
22961
+ const spaces = record4(value)?.spaces;
22962
+ if (!Array.isArray(spaces)) throw invalid("space");
22963
+ return parseNamedEntities(spaces, "Space");
22964
+ }
22965
+ function parseListOptions(value, folderName) {
22966
+ if (!Array.isArray(value)) return [];
22967
+ return parseNamedEntities(value, "List").map((list) => ({ ...list, folderName }));
22968
+ }
22969
+ function parseFoldersResponse(value) {
22970
+ const folders = record4(value)?.folders;
22971
+ if (!Array.isArray(folders)) throw invalid("folder");
22972
+ return folders.flatMap((folder) => {
22973
+ const source = record4(folder);
22974
+ return source ? parseListOptions(source.lists, text(source.name) || null) : [];
22975
+ });
22976
+ }
22977
+ function parseFolderlessListsResponse(value) {
22978
+ const source = record4(value);
22979
+ if (!source || !Array.isArray(source.lists)) throw invalid("list");
22980
+ return parseListOptions(source.lists, null);
22981
+ }
22982
+ async function runClickUpApi(token, path) {
22983
+ let response;
22984
+ try {
22985
+ response = await fetch(`${API_BASE}${path}`, {
22986
+ headers: { Authorization: token, Accept: "application/json" },
22987
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
22988
+ });
22989
+ } catch {
22990
+ throw new ClickUpRouteError(502, "clickup_api_failed", "ClickUp is unreachable");
22991
+ }
22992
+ if (response.status === 401) {
22993
+ throw new ClickUpRouteError(401, "clickup_auth_failed", "ClickUp rejected the API token");
22994
+ }
22995
+ if (response.status === 429) {
22996
+ throw new ClickUpRouteError(429, "clickup_rate_limited", "ClickUp rate limit reached; try again in a minute");
22997
+ }
22998
+ if (!response.ok) {
22999
+ throw new ClickUpRouteError(502, "clickup_api_failed", `ClickUp request failed (${response.status})`);
23000
+ }
23001
+ try {
23002
+ return await response.json();
23003
+ } catch {
23004
+ throw invalid("JSON");
23005
+ }
23006
+ }
23007
+ function identityFor(token, deps) {
23008
+ let cached = identityCache.get(token);
23009
+ if (!cached) {
23010
+ cached = (async () => {
23011
+ const [viewer, workspaces] = await Promise.all([
23012
+ deps.api(token, "/user").then(parseViewerResponse),
23013
+ deps.api(token, "/team").then(parseWorkspacesResponse)
23014
+ ]);
23015
+ const workspace = workspaces[0];
23016
+ if (!workspace) throw new ClickUpRouteError(502, "clickup_api_failed", "The token belongs to no ClickUp workspace");
23017
+ return { token, viewer, workspace };
23018
+ })();
23019
+ identityCache.set(token, cached);
23020
+ cached.catch(() => identityCache.delete(token));
23021
+ }
23022
+ return cached;
23023
+ }
23024
+ async function requireIdentity(deps) {
23025
+ const config = await deps.loadConfig();
23026
+ if (!config.token) {
23027
+ throw new ClickUpRouteError(503, "clickup_not_configured", "Add a ClickUp API token to view your tasks");
23028
+ }
23029
+ return { ...await identityFor(config.token, deps), config };
23030
+ }
23031
+ async function statusFor(config, deps) {
23032
+ if (!config.token) return { configured: false, tokenFromEnv: false, viewer: null, workspace: null };
23033
+ const identity = await identityFor(config.token, deps);
23034
+ return { configured: true, tokenFromEnv: config.tokenFromEnv, viewer: identity.viewer, workspace: identity.workspace };
23035
+ }
23036
+ async function fetchTaskPages(token, path, deps, maxPages = MAX_TASK_PAGES) {
23037
+ const tasks = [];
23038
+ for (let page = 0; page < maxPages; page += 1) {
23039
+ const result = parseTasksPage(await deps.api(token, `${path}&page=${page}`));
23040
+ tasks.push(...result.tasks);
23041
+ if (result.lastPage) return { tasks, truncated: false };
23042
+ }
23043
+ return { tasks, truncated: true };
23044
+ }
23045
+ async function resolveProjectPath2(cwd, deps) {
23046
+ const project = await deps.resolveProject(cwd);
23047
+ if (!project.ok) throw new ClickUpRouteError(project.status, "clickup_api_failed", project.error);
23048
+ return project.projectPath;
23049
+ }
23050
+ function sendRouteError4(res, error) {
23051
+ if (error instanceof ClickUpRouteError) {
23052
+ sendJson(res, error.status, { error: error.message, code: error.code });
23053
+ return;
23054
+ }
23055
+ sendJson(res, 500, { error: "Unable to load ClickUp data", code: "clickup_api_failed" });
23056
+ }
23057
+ function route(use, path, methods, handler) {
23058
+ use(path, async (req, res, next) => {
23059
+ if (!methods.includes(req.method ?? "")) return next();
23060
+ const url = new URL(req.url || "", "http://localhost");
23061
+ if (url.pathname !== "/" && url.pathname !== "") return next();
23062
+ try {
23063
+ const result = await handler(req, url);
23064
+ sendJson(res, result.status, result.body);
23065
+ } catch (error) {
23066
+ sendRouteError4(res, error);
23067
+ }
23068
+ });
23069
+ }
23070
+ function registerClickUpRoutes(use, deps = defaultDependencies3) {
23071
+ route(use, "/api/clickup/status", ["GET"], async () => ({
23072
+ status: 200,
23073
+ body: await statusFor(await deps.loadConfig(), deps)
23074
+ }));
23075
+ route(use, "/api/clickup/token", ["POST", "DELETE"], async (req) => {
23076
+ const current = await deps.loadConfig();
23077
+ if (current.tokenFromEnv) {
23078
+ throw new ClickUpRouteError(409, "clickup_api_failed", "The ClickUp token comes from the server environment; change it there");
23079
+ }
23080
+ if (current.token) identityCache.delete(current.token);
23081
+ if (req.method === "DELETE") {
23082
+ await deps.saveToken(null);
23083
+ return { status: 200, body: await statusFor({ ...current, token: null }, deps) };
23084
+ }
23085
+ const { token } = await readJsonBody(req);
23086
+ const candidate = typeof token === "string" ? token.trim() : "";
23087
+ if (!isClickUpToken(candidate)) {
23088
+ throw new ClickUpRouteError(400, "clickup_auth_failed", "That does not look like a ClickUp personal API token (pk_\u2026)");
23089
+ }
23090
+ await identityFor(candidate, deps);
23091
+ await deps.saveToken(candidate);
23092
+ return { status: 200, body: await statusFor({ ...current, token: candidate }, deps) };
23093
+ });
23094
+ route(use, "/api/clickup/tasks/mine", ["GET"], async () => {
23095
+ const { token, viewer, workspace } = await requireIdentity(deps);
23096
+ const path = `/team/${workspace.id}/task?assignees[]=${viewer.id}&include_closed=false&subtasks=true&order_by=due_date&reverse=true`;
23097
+ const { tasks, truncated } = await fetchTaskPages(token, path, deps);
23098
+ const body = { workspace, viewer, tasks, truncated };
23099
+ return { status: 200, body };
23100
+ });
23101
+ route(use, "/api/clickup/tasks/list", ["GET"], async (_req, url) => {
23102
+ const projectPath = await resolveProjectPath2(url.searchParams.get("cwd") ?? "", deps);
23103
+ const { token, viewer, workspace, config } = await requireIdentity(deps);
23104
+ const listId = config.projects[projectPath];
23105
+ if (!listId) throw new ClickUpRouteError(404, "project_unlinked", "This project is not linked to a ClickUp list");
23106
+ const since = deps.now() - CLOSED_WINDOW_MS;
23107
+ const [list, open10, closed] = await Promise.all([
23108
+ deps.api(token, `/list/${listId}`).then(parseListResponse),
23109
+ fetchTaskPages(token, `/list/${listId}/task?include_closed=false&subtasks=true&order_by=updated`, deps),
23110
+ fetchTaskPages(token, `/list/${listId}/task?include_closed=true&subtasks=true&order_by=updated&date_updated_gt=${since}`, deps, 1)
23111
+ ]);
23112
+ const seen = new Set(open10.tasks.map((task) => task.id));
23113
+ const recentlyClosed = closed.tasks.filter((task) => !seen.has(task.id) && task.status.type === "closed");
23114
+ const body = {
23115
+ workspace,
23116
+ viewer,
23117
+ list,
23118
+ tasks: [...open10.tasks, ...recentlyClosed],
23119
+ truncated: open10.truncated
23120
+ };
23121
+ return { status: 200, body };
23122
+ });
23123
+ route(use, "/api/clickup/spaces", ["GET"], async () => {
23124
+ const { token, workspace } = await requireIdentity(deps);
23125
+ const spaces = parseSpacesResponse(await deps.api(token, `/team/${workspace.id}/space?archived=false`));
23126
+ const body = { workspace, spaces };
23127
+ return { status: 200, body };
23128
+ });
23129
+ route(use, "/api/clickup/lists", ["GET"], async (_req, url) => {
23130
+ const spaceId = url.searchParams.get("spaceId") ?? "";
23131
+ if (!NUMERIC_ID.test(spaceId)) {
23132
+ throw new ClickUpRouteError(400, "clickup_api_failed", "spaceId must be a ClickUp space id");
23133
+ }
23134
+ const { token } = await requireIdentity(deps);
23135
+ const [inFolders, folderless] = await Promise.all([
23136
+ deps.api(token, `/space/${spaceId}/folder?archived=false`).then(parseFoldersResponse),
23137
+ deps.api(token, `/space/${spaceId}/list?archived=false`).then(parseFolderlessListsResponse)
23138
+ ]);
23139
+ const body = { spaceId, lists: [...folderless, ...inFolders] };
23140
+ return { status: 200, body };
23141
+ });
23142
+ route(use, "/api/clickup/project-list", ["GET", "PUT"], async (req, url) => {
23143
+ if (req.method === "GET") {
23144
+ const projectPath2 = await resolveProjectPath2(url.searchParams.get("cwd") ?? "", deps);
23145
+ const config = await deps.loadConfig();
23146
+ const body2 = { cwd: projectPath2, listId: config.projects[projectPath2] ?? null };
23147
+ return { status: 200, body: body2 };
23148
+ }
23149
+ const request = await readJsonBody(req);
23150
+ const projectPath = await resolveProjectPath2(typeof request.cwd === "string" ? request.cwd : "", deps);
23151
+ const listId = request.listId === null || request.listId === void 0 ? null : String(request.listId);
23152
+ if (listId !== null && !NUMERIC_ID.test(listId)) {
23153
+ throw new ClickUpRouteError(400, "clickup_api_failed", "listId must be a ClickUp list id");
23154
+ }
23155
+ if (listId !== null) {
23156
+ const { token } = await requireIdentity(deps);
23157
+ parseListResponse(await deps.api(token, `/list/${listId}`));
23158
+ }
23159
+ await deps.saveProjectLink(projectPath, listId);
23160
+ const body = { cwd: projectPath, listId };
23161
+ return { status: 200, body };
23162
+ });
23163
+ }
23164
+ var API_BASE, REQUEST_TIMEOUT_MS, MAX_TASK_PAGES, CLOSED_WINDOW_MS, NUMERIC_ID, STATUS_TYPES, PRIORITIES, ClickUpRouteError, defaultDependencies3, identityCache;
23165
+ var init_clickup = __esm({
23166
+ "../../server/routes/clickup.ts"() {
23167
+ init_http();
23168
+ init_clickupConfig();
23169
+ init_gitProject();
23170
+ API_BASE = "https://api.clickup.com/api/v2";
23171
+ REQUEST_TIMEOUT_MS = 2e4;
23172
+ MAX_TASK_PAGES = 3;
23173
+ CLOSED_WINDOW_MS = 14 * 24 * 60 * 60 * 1e3;
23174
+ NUMERIC_ID = /^\d+$/;
23175
+ STATUS_TYPES = /* @__PURE__ */ new Set(["open", "custom", "closed", "done"]);
23176
+ PRIORITIES = /* @__PURE__ */ new Set(["urgent", "high", "normal", "low"]);
23177
+ ClickUpRouteError = class extends Error {
23178
+ constructor(status, code, message) {
23179
+ super(message);
23180
+ this.status = status;
23181
+ this.code = code;
23182
+ }
23183
+ };
23184
+ defaultDependencies3 = {
23185
+ api: runClickUpApi,
23186
+ loadConfig: loadClickUpConfig,
23187
+ saveToken: saveClickUpToken,
23188
+ saveProjectLink: saveClickUpProjectLink,
23189
+ resolveProject: resolveGitProject,
23190
+ now: () => Date.now()
23191
+ };
23192
+ identityCache = /* @__PURE__ */ new Map();
23193
+ }
23194
+ });
23195
+
22762
23196
  // ../../server/lib/projectIcon.ts
22763
23197
  import { realpath as realpath10, stat as stat14 } from "node:fs/promises";
22764
- import { basename as basename9, extname, join as join22, relative as relative8, sep as sep10 } from "node:path";
23198
+ import { basename as basename9, extname, join as join23, relative as relative8, sep as sep10 } from "node:path";
22765
23199
  function namedIconCandidates(root) {
22766
23200
  const name = basename9(root);
22767
23201
  if (!name || name.startsWith(".")) return [];
22768
23202
  return ["public", "assets", "static", "."].flatMap(
22769
- (dir) => NAMED_ICON_EXTENSIONS.map((ext) => join22(dir, `${name}${ext}`))
23203
+ (dir) => NAMED_ICON_EXTENSIONS.map((ext) => join23(dir, `${name}${ext}`))
22770
23204
  );
22771
23205
  }
22772
23206
  function iconContentType(path) {
@@ -22789,7 +23223,7 @@ async function resolveProjectIcon(projectPath) {
22789
23223
  ...PROJECT_ICON_CANDIDATES.slice(6)
22790
23224
  ];
22791
23225
  for (const candidate of candidates) {
22792
- const guess = join22(root, candidate);
23226
+ const guess = join23(root, candidate);
22793
23227
  try {
22794
23228
  const resolved = await realpath10(guess);
22795
23229
  if (!isInside(root, resolved)) continue;
@@ -22943,13 +23377,13 @@ var init_local_file = __esm({
22943
23377
 
22944
23378
  // ../../server/routes/mcp.ts
22945
23379
  import { execFile as execFile5 } from "node:child_process";
22946
- import { isAbsolute as isAbsolute10, join as join23 } from "node:path";
22947
- import { readFile as readFile17 } from "node:fs/promises";
22948
- import { homedir as homedir7 } from "node:os";
23380
+ import { isAbsolute as isAbsolute10, join as join24 } from "node:path";
23381
+ import { readFile as readFile18 } from "node:fs/promises";
23382
+ import { homedir as homedir8 } from "node:os";
22949
23383
  async function readMcpConfigs(cwd) {
22950
23384
  const configs = {};
22951
23385
  try {
22952
- const raw = await readFile17(join23(homedir7(), ".claude.json"), "utf-8");
23386
+ const raw = await readFile18(join24(homedir8(), ".claude.json"), "utf-8");
22953
23387
  const parsed = JSON.parse(raw);
22954
23388
  if (parsed.mcpServers && typeof parsed.mcpServers === "object") {
22955
23389
  Object.assign(configs, parsed.mcpServers);
@@ -22967,16 +23401,16 @@ async function readMcpConfigs(cwd) {
22967
23401
  } catch {
22968
23402
  }
22969
23403
  const otherSources = [
22970
- join23(homedir7(), ".claude", "settings.json"),
23404
+ join24(homedir8(), ".claude", "settings.json"),
22971
23405
  // global settings
22972
- join23(cwd, ".mcp.json"),
23406
+ join24(cwd, ".mcp.json"),
22973
23407
  // project
22974
- join23(cwd, ".claude", "settings.local.json")
23408
+ join24(cwd, ".claude", "settings.local.json")
22975
23409
  // project local
22976
23410
  ];
22977
23411
  for (const path of otherSources) {
22978
23412
  try {
22979
- const raw = await readFile17(path, "utf-8");
23413
+ const raw = await readFile18(path, "utf-8");
22980
23414
  const parsed = JSON.parse(raw);
22981
23415
  if (parsed.mcpServers && typeof parsed.mcpServers === "object") {
22982
23416
  Object.assign(configs, parsed.mcpServers);
@@ -23187,8 +23621,8 @@ function humanizeIdentifier(value, titleCase = false) {
23187
23621
  return titleCase ? lower[0].toUpperCase() + lower.slice(1) : lower;
23188
23622
  });
23189
23623
  if (words.length === 0) return "Tool";
23190
- const text = words.join(" ");
23191
- return text[0].toUpperCase() + text.slice(1);
23624
+ const text2 = words.join(" ");
23625
+ return text2[0].toUpperCase() + text2.slice(1);
23192
23626
  }
23193
23627
  function stringExpression(source) {
23194
23628
  if (!source) return null;
@@ -23718,8 +24152,8 @@ function foldFileEdit(acc, name, input) {
23718
24152
  }
23719
24153
  return true;
23720
24154
  }
23721
- function notePreview(acc, text) {
23722
- const trimmed = text.trim();
24155
+ function notePreview(acc, text2) {
24156
+ const trimmed = text2.trim();
23723
24157
  if (trimmed) acc.lastAssistantText = trimmed.slice(0, PREVIEW_LIMIT);
23724
24158
  }
23725
24159
  var TRAIL_LENGTH, PREVIEW_LIMIT;
@@ -23822,9 +24256,9 @@ function copilotText(value) {
23822
24256
  if (!Array.isArray(value)) return "";
23823
24257
  return value.flatMap((part) => {
23824
24258
  if (typeof part === "string") return part ? [part] : [];
23825
- const record4 = asRecord5(part);
23826
- const text = str(record4.text) || str(record4.content);
23827
- return text ? [text] : [];
24259
+ const record5 = asRecord5(part);
24260
+ const text2 = str(record5.text) || str(record5.content);
24261
+ return text2 ? [text2] : [];
23828
24262
  }).join("\n");
23829
24263
  }
23830
24264
  function normalizeCopilotToolName(name) {
@@ -24387,14 +24821,14 @@ var init_models = __esm({
24387
24821
  });
24388
24822
 
24389
24823
  // ../../server/lib/notificationHistory.ts
24390
- import { mkdir as mkdir6, readFile as readFile18 } from "node:fs/promises";
24824
+ import { mkdir as mkdir7, readFile as readFile19 } from "node:fs/promises";
24391
24825
  import { mkdirSync, writeFileSync } from "node:fs";
24392
- import { homedir as homedir8 } from "node:os";
24393
- import { dirname as dirname9, join as join24 } from "node:path";
24826
+ import { homedir as homedir9 } from "node:os";
24827
+ import { dirname as dirname10, join as join25 } from "node:path";
24394
24828
  import { randomUUID as randomUUID4 } from "node:crypto";
24395
24829
  async function load() {
24396
24830
  if (entries2) return entries2;
24397
- loadPromise ??= readFile18(NOTIFICATION_HISTORY_FILE, "utf-8").then((raw) => {
24831
+ loadPromise ??= readFile19(NOTIFICATION_HISTORY_FILE, "utf-8").then((raw) => {
24398
24832
  const parsed = JSON.parse(raw);
24399
24833
  return Array.isArray(parsed) ? parsed.filter(isEntry) : [];
24400
24834
  }).catch(() => []).then((loaded2) => {
@@ -24420,7 +24854,7 @@ function schedulePersist2() {
24420
24854
  const snapshot = entries2;
24421
24855
  if (!snapshot) return;
24422
24856
  dirty = false;
24423
- void mkdir6(dirname9(NOTIFICATION_HISTORY_FILE), { recursive: true }).then(() => writeOwnerOnlyJson(NOTIFICATION_HISTORY_FILE, snapshot)).catch((err) => console.error("[notify] Failed to persist history:", err));
24857
+ void mkdir7(dirname10(NOTIFICATION_HISTORY_FILE), { recursive: true }).then(() => writeOwnerOnlyJson(NOTIFICATION_HISTORY_FILE, snapshot)).catch((err) => console.error("[notify] Failed to persist history:", err));
24424
24858
  }, PERSIST_DEBOUNCE_MS);
24425
24859
  persistTimer.unref?.();
24426
24860
  }
@@ -24428,7 +24862,7 @@ function flushSync() {
24428
24862
  if (!dirty || !entries2) return;
24429
24863
  dirty = false;
24430
24864
  try {
24431
- mkdirSync(dirname9(NOTIFICATION_HISTORY_FILE), { recursive: true });
24865
+ mkdirSync(dirname10(NOTIFICATION_HISTORY_FILE), { recursive: true });
24432
24866
  writeFileSync(NOTIFICATION_HISTORY_FILE, JSON.stringify(entries2, null, 2), { mode: 384 });
24433
24867
  } catch {
24434
24868
  }
@@ -24478,7 +24912,7 @@ var NOTIFICATION_HISTORY_FILE, MAX_ENTRIES3, PERSIST_DEBOUNCE_MS, entries2, load
24478
24912
  var init_notificationHistory = __esm({
24479
24913
  "../../server/lib/notificationHistory.ts"() {
24480
24914
  init_atomicJsonFile();
24481
- NOTIFICATION_HISTORY_FILE = join24(homedir8(), ".cogpit", "notifications.json");
24915
+ NOTIFICATION_HISTORY_FILE = join25(homedir9(), ".cogpit", "notifications.json");
24482
24916
  MAX_ENTRIES3 = 200;
24483
24917
  PERSIST_DEBOUNCE_MS = 500;
24484
24918
  entries2 = null;
@@ -24533,9 +24967,9 @@ function parseEtimeSeconds(etime) {
24533
24967
  const [, days, hours, minutes, seconds] = match;
24534
24968
  return Number(days ?? 0) * 86400 + Number(hours ?? 0) * 3600 + Number(minutes) * 60 + Number(seconds);
24535
24969
  }
24536
- function parsePsOutput(text) {
24970
+ function parsePsOutput(text2) {
24537
24971
  const rows = [];
24538
- for (const line of text.split("\n")) {
24972
+ for (const line of text2.split("\n")) {
24539
24973
  const match = /^\s*(\d+)\s+(\d+)\s+([\d.]+)\s+(\d+)\s+(\S+)\s+(.*\S)/.exec(line);
24540
24974
  if (!match) continue;
24541
24975
  rows.push({
@@ -24741,8 +25175,8 @@ var init_notifications2 = __esm({
24741
25175
 
24742
25176
  // ../../server/lib/pushConfig.ts
24743
25177
  import { readFileSync as readFileSync3, statSync as statSync3 } from "node:fs";
24744
- import { homedir as homedir9 } from "node:os";
24745
- import { join as join25 } from "node:path";
25178
+ import { homedir as homedir10 } from "node:os";
25179
+ import { join as join26 } from "node:path";
24746
25180
  function warnOnce(message) {
24747
25181
  if (lastWarning === message) return;
24748
25182
  lastWarning = message;
@@ -24837,7 +25271,7 @@ function getPushConfig(path = PUSH_CONFIG_FILE) {
24837
25271
  var PUSH_CONFIG_FILE, DEFAULT_NTFY_URL, TOPIC_PATTERN, cache5, lastWarning;
24838
25272
  var init_pushConfig = __esm({
24839
25273
  "../../server/lib/pushConfig.ts"() {
24840
- PUSH_CONFIG_FILE = join25(homedir9(), ".cogpit", "push.json");
25274
+ PUSH_CONFIG_FILE = join26(homedir10(), ".cogpit", "push.json");
24841
25275
  DEFAULT_NTFY_URL = "https://ntfy.sh";
24842
25276
  TOPIC_PATTERN = /^[-_A-Za-z0-9]{1,64}$/;
24843
25277
  cache5 = null;
@@ -24846,12 +25280,12 @@ var init_pushConfig = __esm({
24846
25280
  });
24847
25281
 
24848
25282
  // ../../server/lib/pushNotify.ts
24849
- function truncateBytes(text, maxBytes) {
24850
- if (encoder.encode(text).length <= maxBytes) return text;
25283
+ function truncateBytes(text2, maxBytes) {
25284
+ if (encoder.encode(text2).length <= maxBytes) return text2;
24851
25285
  const budget = maxBytes - 3;
24852
25286
  let out = "";
24853
25287
  let used = 0;
24854
- for (const char of text) {
25288
+ for (const char of text2) {
24855
25289
  const size = encoder.encode(char).length;
24856
25290
  if (used + size > budget) break;
24857
25291
  out += char;
@@ -24859,8 +25293,8 @@ function truncateBytes(text, maxBytes) {
24859
25293
  }
24860
25294
  return `${out}\u2026`;
24861
25295
  }
24862
- function stripControls(text) {
24863
- return text.replace(/[\u0000-\u001f\u007f-\u009f]+/g, " ").trim();
25296
+ function stripControls(text2) {
25297
+ return text2.replace(/[\u0000-\u001f\u007f-\u009f]+/g, " ").trim();
24864
25298
  }
24865
25299
  function buildNtfyPayload(notification, config) {
24866
25300
  const title = truncateBytes(stripControls(notification.title), TITLE_MAX_BYTES) || "Cogpit";
@@ -24879,7 +25313,7 @@ async function sendPushNotification(notification, config = getPushConfig()) {
24879
25313
  method: "POST",
24880
25314
  headers,
24881
25315
  body: JSON.stringify(buildNtfyPayload(notification, config)),
24882
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
25316
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2),
24883
25317
  redirect: "error"
24884
25318
  });
24885
25319
  if (!response.ok) {
@@ -24893,14 +25327,14 @@ async function sendPushNotification(notification, config = getPushConfig()) {
24893
25327
  return false;
24894
25328
  }
24895
25329
  }
24896
- var MESSAGE_MAX_BYTES, TITLE_MAX_BYTES, REQUEST_TIMEOUT_MS, encoder;
25330
+ var MESSAGE_MAX_BYTES, TITLE_MAX_BYTES, REQUEST_TIMEOUT_MS2, encoder;
24897
25331
  var init_pushNotify = __esm({
24898
25332
  "../../server/lib/pushNotify.ts"() {
24899
25333
  init_notifications2();
24900
25334
  init_pushConfig();
24901
25335
  MESSAGE_MAX_BYTES = 1024;
24902
25336
  TITLE_MAX_BYTES = 256;
24903
- REQUEST_TIMEOUT_MS = 5e3;
25337
+ REQUEST_TIMEOUT_MS2 = 5e3;
24904
25338
  encoder = new TextEncoder();
24905
25339
  }
24906
25340
  });
@@ -25703,8 +26137,8 @@ var init_ports2 = __esm({
25703
26137
 
25704
26138
  // ../../server/routes/project-file.ts
25705
26139
  import { randomUUID as randomUUID5 } from "node:crypto";
25706
- import { readFile as readFile19, realpath as realpath11, rename as rename3, stat as stat16, unlink as unlink6, writeFile as writeFile6 } from "node:fs/promises";
25707
- import { dirname as dirname10, isAbsolute as isAbsolute11, resolve as resolve17 } from "node:path";
26140
+ import { readFile as readFile20, realpath as realpath11, rename as rename3, stat as stat16, unlink as unlink6, writeFile as writeFile6 } from "node:fs/promises";
26141
+ import { dirname as dirname11, isAbsolute as isAbsolute11, resolve as resolve17 } from "node:path";
25708
26142
  function readBody(req) {
25709
26143
  return new Promise((resolveBody, reject) => {
25710
26144
  let body = "";
@@ -25765,7 +26199,7 @@ async function writeAtomically(absolutePath, content, mode, expectedMtimeMs) {
25765
26199
  if (latest.mtimeMs !== expectedMtimeMs) {
25766
26200
  throw new ProjectFileError(409, "File changed on disk. Reload it before saving.");
25767
26201
  }
25768
- const temporaryPath = resolve17(dirname10(absolutePath), `.${randomUUID5()}.cogpit-save`);
26202
+ const temporaryPath = resolve17(dirname11(absolutePath), `.${randomUUID5()}.cogpit-save`);
25769
26203
  try {
25770
26204
  await writeFile6(temporaryPath, content, { encoding: "utf-8", mode });
25771
26205
  const beforeRename = await stat16(absolutePath);
@@ -25785,7 +26219,7 @@ function registerProjectFileContentRoutes(use) {
25785
26219
  const filePath = url.searchParams.get("path") ?? "";
25786
26220
  try {
25787
26221
  const file = await resolveProjectFile(cwd, filePath);
25788
- const buffer = await readFile19(file.absolutePath);
26222
+ const buffer = await readFile20(file.absolutePath);
25789
26223
  return sendJson(res, 200, {
25790
26224
  content: decodeTextFile(buffer),
25791
26225
  mtimeMs: file.info.mtimeMs,
@@ -26066,7 +26500,7 @@ var init_sessionSearch = __esm({
26066
26500
 
26067
26501
  // ../../server/lib/projectNames.ts
26068
26502
  import { basename as basename10 } from "node:path";
26069
- import { homedir as homedir10 } from "node:os";
26503
+ import { homedir as homedir11 } from "node:os";
26070
26504
  function shortNameFromPath(path) {
26071
26505
  const trimmed = path.replace(/[\\/]+$/, "");
26072
26506
  return basename10(trimmed) || trimmed || path;
@@ -26102,7 +26536,7 @@ var HOME_PREFIX;
26102
26536
  var init_projectNames = __esm({
26103
26537
  "../../server/lib/projectNames.ts"() {
26104
26538
  init_agent_descriptors();
26105
- HOME_PREFIX = descriptorFor("claude").dirName.encode(homedir10()).replace(/^-/, "").toLowerCase();
26539
+ HOME_PREFIX = descriptorFor("claude").dirName.encode(homedir11()).replace(/^-/, "").toLowerCase();
26106
26540
  }
26107
26541
  });
26108
26542
 
@@ -26214,8 +26648,8 @@ async function handleActiveSessions(req, res, next) {
26214
26648
  const resolveTeamLead = (teamName) => {
26215
26649
  let cached = teamLeadCache.get(teamName);
26216
26650
  if (!cached) {
26217
- const configPath = join11(dirs.TEAMS_DIR, teamName, "config.json");
26218
- cached = isWithinDir(dirs.TEAMS_DIR, configPath) ? readFile9(configPath, "utf-8").then((raw) => {
26651
+ const configPath2 = join11(dirs.TEAMS_DIR, teamName, "config.json");
26652
+ cached = isWithinDir(dirs.TEAMS_DIR, configPath2) ? readFile9(configPath2, "utf-8").then((raw) => {
26219
26653
  const lead = JSON.parse(String(raw)).leadSessionId;
26220
26654
  return typeof lead === "string" && lead ? lead : null;
26221
26655
  }).catch(() => null) : Promise.resolve(null);
@@ -26425,18 +26859,18 @@ async function readSessionHeader(filePath) {
26425
26859
  try {
26426
26860
  const fileStat = await fh.stat();
26427
26861
  let readLen = Math.min(HEADER_BYTES, fileStat.size);
26428
- let text = "";
26862
+ let text2 = "";
26429
26863
  let bytesRead = 0;
26430
26864
  for (; ; ) {
26431
26865
  const buf = Buffer.allocUnsafe(readLen);
26432
26866
  const result = await fh.read(buf, 0, readLen, 0);
26433
26867
  bytesRead = result.bytesRead;
26434
- text = buf.subarray(0, bytesRead).toString("utf-8");
26868
+ text2 = buf.subarray(0, bytesRead).toString("utf-8");
26435
26869
  const isWholeFile = bytesRead >= fileStat.size;
26436
- if (isWholeFile || text.includes("\n") || readLen >= MAX_HEADER_BYTES) break;
26870
+ if (isWholeFile || text2.includes("\n") || readLen >= MAX_HEADER_BYTES) break;
26437
26871
  readLen = Math.min(readLen * 4, Math.min(fileStat.size, MAX_HEADER_BYTES));
26438
26872
  }
26439
- const parts = text.split("\n").filter((l) => l.trim().length > 0);
26873
+ const parts = text2.split("\n").filter((l) => l.trim().length > 0);
26440
26874
  if (bytesRead < fileStat.size && parts.length > 0) {
26441
26875
  parts.pop();
26442
26876
  }
@@ -26900,8 +27334,8 @@ function getProviderUpdates() {
26900
27334
  function isProviderUpdateId(value) {
26901
27335
  return typeof value === "string" && AGENT_KINDS.includes(value);
26902
27336
  }
26903
- function truncate2(text) {
26904
- const trimmed = text.trim();
27337
+ function truncate2(text2) {
27338
+ const trimmed = text2.trim();
26905
27339
  if (!trimmed) return null;
26906
27340
  return trimmed.length <= CLI_OUTPUT_MAX_CHARS ? trimmed : trimmed.slice(0, CLI_OUTPUT_MAX_CHARS);
26907
27341
  }
@@ -27049,12 +27483,189 @@ var init_agent_executable = __esm({
27049
27483
  }
27050
27484
  });
27051
27485
 
27486
+ // ../../server/agents/claudeSwap.ts
27487
+ function asRow(value) {
27488
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
27489
+ }
27490
+ function asString2(value) {
27491
+ return typeof value === "string" && value.trim() ? value : null;
27492
+ }
27493
+ function asSlot(value) {
27494
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : null;
27495
+ }
27496
+ function parseWindow(value) {
27497
+ const row = asRow(value);
27498
+ if (!row || typeof row.pct !== "number" || !Number.isFinite(row.pct)) return null;
27499
+ return {
27500
+ pct: Math.min(100, Math.max(0, row.pct)),
27501
+ resetsIn: asString2(row.countdown),
27502
+ resetsAt: asString2(row.resetsAt)
27503
+ };
27504
+ }
27505
+ function parseUsage2(value) {
27506
+ const row = asRow(value);
27507
+ if (!row) return null;
27508
+ return { fiveHour: parseWindow(row.fiveHour), sevenDay: parseWindow(row.sevenDay) };
27509
+ }
27510
+ function parseAccount(value) {
27511
+ const row = asRow(value);
27512
+ if (!row) return null;
27513
+ const slot = asSlot(row.number);
27514
+ const email = asString2(row.email);
27515
+ if (slot === null || email === null) return null;
27516
+ return {
27517
+ slot,
27518
+ alias: asString2(row.alias),
27519
+ email,
27520
+ organization: asString2(row.organizationName),
27521
+ active: row.active === true,
27522
+ disabled: row.disabled === true,
27523
+ usageStatus: asString2(row.usageStatus) ?? "unavailable",
27524
+ usage: parseUsage2(row.usage)
27525
+ };
27526
+ }
27527
+ function parseJson(stdout) {
27528
+ try {
27529
+ return asRow(JSON.parse(stdout));
27530
+ } catch {
27531
+ return null;
27532
+ }
27533
+ }
27534
+ function parseAccountList(stdout) {
27535
+ const payload = parseJson(stdout);
27536
+ if (!payload || !Array.isArray(payload.accounts)) return null;
27537
+ return {
27538
+ activeSlot: asSlot(payload.activeAccountNumber),
27539
+ accounts: payload.accounts.map(parseAccount).filter((account) => account !== null)
27540
+ };
27541
+ }
27542
+ function parseSwitchResult(stdout) {
27543
+ const payload = parseJson(stdout);
27544
+ if (!payload) return null;
27545
+ const error = switcherError(payload);
27546
+ if (error) return { error };
27547
+ if (typeof payload.switched !== "boolean") return null;
27548
+ return {
27549
+ switched: payload.switched,
27550
+ message: asString2(payload.message) ?? (payload.switched ? "Switched account." : "Account unchanged."),
27551
+ warnings: Array.isArray(payload.warnings) ? payload.warnings.filter((w) => typeof w === "string") : []
27552
+ };
27553
+ }
27554
+ function switcherError(payload) {
27555
+ return asString2(asRow(payload.error)?.message);
27556
+ }
27557
+ function failureMessage(run2, fallback) {
27558
+ if (run2.timedOut) return `${CSWAP_BIN} timed out`;
27559
+ const envelope = parseJson(run2.stdout);
27560
+ return envelope && switcherError(envelope) || run2.stderr.trim() || fallback;
27561
+ }
27562
+ function isClaudeSwapInstalled() {
27563
+ return findExecutableOnPath(CSWAP_BIN) !== void 0;
27564
+ }
27565
+ async function describeClaudeAccounts() {
27566
+ if (!isClaudeSwapInstalled()) return { status: "missing" };
27567
+ const [version, list] = await Promise.all([
27568
+ runCli(CSWAP_BIN, ["--version"], DEFAULT_PROBE_TIMEOUT_MS),
27569
+ runCli(CSWAP_BIN, ["list", "--json"], LIST_TIMEOUT_MS)
27570
+ ]);
27571
+ if (list.code !== 0) {
27572
+ return { status: "error", error: failureMessage(list, `${CSWAP_BIN} list failed`) };
27573
+ }
27574
+ const parsed = parseAccountList(list.stdout);
27575
+ if (!parsed) return { status: "error", error: `${CSWAP_BIN} list returned unexpected output` };
27576
+ return { status: "ok", tool: TOOL_NAME, version: extractVersion(version.stdout), ...parsed };
27577
+ }
27578
+ async function switchClaudeAccount(slot) {
27579
+ if (asSlot(slot) === null) throw new Error("slot must be a positive integer");
27580
+ const run2 = await runCli(CSWAP_BIN, ["switch", String(slot), "--json"], SWITCH_TIMEOUT_MS);
27581
+ const parsed = run2.code === 0 ? parseSwitchResult(run2.stdout) : null;
27582
+ if (!parsed) throw new Error(failureMessage(run2, `${CSWAP_BIN} switch failed`));
27583
+ if ("error" in parsed) throw new Error(parsed.error);
27584
+ return { ...parsed, credentialStore: process.platform === "darwin" ? "keychain" : "file" };
27585
+ }
27586
+ var CSWAP_BIN, TOOL_NAME, LIST_TIMEOUT_MS, SWITCH_TIMEOUT_MS;
27587
+ var init_claudeSwap = __esm({
27588
+ "../../server/agents/claudeSwap.ts"() {
27589
+ init_versions();
27590
+ init_binaryResolver();
27591
+ init_cliProcess();
27592
+ CSWAP_BIN = "cswap";
27593
+ TOOL_NAME = "claude-swap";
27594
+ LIST_TIMEOUT_MS = 3e4;
27595
+ SWITCH_TIMEOUT_MS = 3e4;
27596
+ }
27597
+ });
27598
+
27599
+ // ../../server/agents/accounts.ts
27600
+ function accountSwitcherFor(kind) {
27601
+ return kind === "claude" ? claudeAccounts : null;
27602
+ }
27603
+ var claudeAccounts;
27604
+ var init_accounts = __esm({
27605
+ "../../server/agents/accounts.ts"() {
27606
+ init_claudeSwap();
27607
+ claudeAccounts = {
27608
+ describe: describeClaudeAccounts,
27609
+ switchTo: switchClaudeAccount
27610
+ };
27611
+ }
27612
+ });
27613
+
27614
+ // ../../server/routes/agent-accounts.ts
27615
+ function registerAgentAccountRoutes(use) {
27616
+ use("/api/agent-accounts", async (req, res, next) => {
27617
+ const segments2 = new URL(req.url || "/", "http://localhost").pathname.split("/").filter(Boolean);
27618
+ const [kind, action, ...rest] = segments2;
27619
+ if (!AGENT_KINDS.includes(kind ?? "") || rest.length > 0) return next();
27620
+ const switcher = accountSwitcherFor(kind);
27621
+ if (action === void 0 && req.method === "GET") {
27622
+ if (!switcher) {
27623
+ sendJson(res, 404, { error: `${kind} has no account switcher` });
27624
+ return;
27625
+ }
27626
+ try {
27627
+ sendJson(res, 200, await switcher.describe());
27628
+ } catch (err) {
27629
+ sendJson(res, 500, { error: String(err) });
27630
+ }
27631
+ return;
27632
+ }
27633
+ if (action === "switch" && req.method === "POST") {
27634
+ if (!switcher) {
27635
+ sendJson(res, 404, { error: `${kind} has no account switcher` });
27636
+ return;
27637
+ }
27638
+ withJsonBody(req, res, async (body) => {
27639
+ const slot = body?.slot;
27640
+ if (typeof slot !== "number" || !Number.isInteger(slot) || slot <= 0) {
27641
+ sendJson(res, 400, { error: "slot must be a positive integer" });
27642
+ return;
27643
+ }
27644
+ try {
27645
+ sendJson(res, 200, await switcher.switchTo(slot));
27646
+ } catch (err) {
27647
+ sendJson(res, 500, { error: err instanceof Error ? err.message : String(err) });
27648
+ }
27649
+ });
27650
+ return;
27651
+ }
27652
+ next();
27653
+ });
27654
+ }
27655
+ var init_agent_accounts = __esm({
27656
+ "../../server/routes/agent-accounts.ts"() {
27657
+ init_agent_descriptors();
27658
+ init_accounts();
27659
+ init_http();
27660
+ }
27661
+ });
27662
+
27052
27663
  // ../../server/routes/scripts/discovery.ts
27053
- import { readdir as readdir12, readFile as readFile20 } from "node:fs/promises";
27054
- import { join as join26, relative as relative10 } from "node:path";
27664
+ import { readdir as readdir12, readFile as readFile21 } from "node:fs/promises";
27665
+ import { join as join27, relative as relative10 } from "node:path";
27055
27666
  async function extractScripts(dir, dirLabel) {
27056
27667
  try {
27057
- const raw = await readFile20(join26(dir, "package.json"), "utf-8");
27668
+ const raw = await readFile21(join27(dir, "package.json"), "utf-8");
27058
27669
  const pkg = JSON.parse(raw);
27059
27670
  const scripts = pkg.scripts;
27060
27671
  if (!scripts || typeof scripts !== "object") return [];
@@ -27080,7 +27691,7 @@ async function discoverScripts(projectDir) {
27080
27691
  );
27081
27692
  const childResults = await Promise.all(
27082
27693
  childDirs.map(async (entry) => {
27083
- const childPath = join26(projectDir, entry.name);
27694
+ const childPath = join27(projectDir, entry.name);
27084
27695
  const label = relative10(projectDir, childPath) + "/";
27085
27696
  return extractScripts(childPath, label);
27086
27697
  })
@@ -27266,12 +27877,12 @@ var init_session_config = __esm({
27266
27877
 
27267
27878
  // ../../server/lib/agentTeamIdentity.ts
27268
27879
  import { open as open9, readdir as readdir13 } from "node:fs/promises";
27269
- import { join as join27 } from "node:path";
27880
+ import { join as join28 } from "node:path";
27270
27881
  async function matchSubagentToMember(leadSessionId, subagentFileName, members) {
27271
27882
  const entries3 = await readdir13(dirs.PROJECTS_DIR, { withFileTypes: true });
27272
27883
  for (const entry of entries3) {
27273
27884
  if (!entry.isDirectory() || entry.name === "memory") continue;
27274
- const filePath = join27(
27885
+ const filePath = join28(
27275
27886
  dirs.PROJECTS_DIR,
27276
27887
  entry.name,
27277
27888
  leadSessionId,
@@ -27312,8 +27923,8 @@ async function readSessionTeamTags(filePath) {
27312
27923
  try {
27313
27924
  const buf = Buffer.alloc(32768);
27314
27925
  const { bytesRead } = await fh.read(buf, 0, 32768, 0);
27315
- const text = buf.subarray(0, bytesRead).toString("utf-8");
27316
- const lines = text.split("\n");
27926
+ const text2 = buf.subarray(0, bytesRead).toString("utf-8");
27927
+ const lines = text2.split("\n");
27317
27928
  const complete = bytesRead === 32768 ? lines.slice(0, -1) : lines;
27318
27929
  for (const line of complete.slice(0, 40)) {
27319
27930
  if (!line || !line.includes('"teamName"')) continue;
@@ -27479,8 +28090,8 @@ function mapToolCall(tc) {
27479
28090
  function mapContentBlock(block) {
27480
28091
  switch (block.kind) {
27481
28092
  case "thinking": {
27482
- const text = block.blocks.filter((b) => b.thinking.length > 0).map((b) => b.thinking).join("\n\n");
27483
- return { kind: "thinking", text, timestamp: block.timestamp ?? null };
28093
+ const text2 = block.blocks.filter((b) => b.thinking.length > 0).map((b) => b.thinking).join("\n\n");
28094
+ return { kind: "thinking", text: text2, timestamp: block.timestamp ?? null };
27484
28095
  }
27485
28096
  case "text":
27486
28097
  return { kind: "text", text: block.text.join("\n\n"), timestamp: block.timestamp ?? null };
@@ -27548,9 +28159,9 @@ async function findTeamContext(sessionId, subagentFileName) {
27548
28159
  const teamEntries = await readdir6(dirs.TEAMS_DIR, { withFileTypes: true });
27549
28160
  for (const entry of teamEntries) {
27550
28161
  if (!entry.isDirectory()) continue;
27551
- const configPath = join11(dirs.TEAMS_DIR, entry.name, "config.json");
28162
+ const configPath2 = join11(dirs.TEAMS_DIR, entry.name, "config.json");
27552
28163
  try {
27553
- const raw = await readFile9(configPath, "utf-8");
28164
+ const raw = await readFile9(configPath2, "utf-8");
27554
28165
  const config = JSON.parse(raw);
27555
28166
  if (config.leadSessionId !== sessionId) continue;
27556
28167
  const members = config.members ?? [];
@@ -27786,14 +28397,14 @@ function cdTarget(segment, cwd) {
27786
28397
  if (!m) return null;
27787
28398
  return resolvePath(m[1] ?? m[2] ?? m[3] ?? "", cwd);
27788
28399
  }
27789
- function writeTarget(text) {
27790
- const tee = text.match(/^tee\s+(?:(-a)\s+)?(?:"([^"]+)"|'([^']+)'|([^\s<>|;&]+))/);
28400
+ function writeTarget(text2) {
28401
+ const tee = text2.match(/^tee\s+(?:(-a)\s+)?(?:"([^"]+)"|'([^']+)'|([^\s<>|;&]+))/);
27791
28402
  if (tee) {
27792
28403
  if (tee[1]) return null;
27793
28404
  return tee[2] ?? tee[3] ?? tee[4] ?? null;
27794
28405
  }
27795
- if (!/^cat\b/.test(text)) return null;
27796
- const redirect = text.match(/(>>?)\s*(?:"([^"]+)"|'([^']+)'|([^\s<>|;&]+))/);
28406
+ if (!/^cat\b/.test(text2)) return null;
28407
+ const redirect = text2.match(/(>>?)\s*(?:"([^"]+)"|'([^']+)'|([^\s<>|;&]+))/);
27797
28408
  if (!redirect || redirect[1] === ">>") return null;
27798
28409
  return redirect[2] ?? redirect[3] ?? redirect[4] ?? null;
27799
28410
  }
@@ -27964,7 +28575,7 @@ function normalizeCopilotFileChangeEvents(jsonlContent) {
27964
28575
  }
27965
28576
  });
27966
28577
  }
27967
- return records.map((record4) => JSON.stringify(record4)).join("\n");
28578
+ return records.map((record5) => JSON.stringify(record5)).join("\n");
27968
28579
  }
27969
28580
  async function parseSessionFileChanges(jsonlContent, includeContent) {
27970
28581
  if (formatForText(jsonlContent).kind === "copilot") {
@@ -28034,8 +28645,8 @@ async function parseSessionFileChanges(jsonlContent, includeContent) {
28034
28645
  if (payload.type === "custom_tool_call_output" && typeof payload.call_id === "string") {
28035
28646
  const patchCalls = patchCallIds.get(payload.call_id);
28036
28647
  if (patchCalls) {
28037
- const { text, isError: wrapperIsError } = parseCustomToolOutput(payload.output);
28038
- const failedIds = patchCalls.direct && wrapperIsError ? new Set(patchCalls.calls.map((call) => call.id)) : findFailedNestedPatchCallIds(text, wrapperIsError, patchCalls.calls);
28648
+ const { text: text2, isError: wrapperIsError } = parseCustomToolOutput(payload.output);
28649
+ const failedIds = patchCalls.direct && wrapperIsError ? new Set(patchCalls.calls.map((call) => call.id)) : findFailedNestedPatchCallIds(text2, wrapperIsError, patchCalls.calls);
28039
28650
  for (const call of patchCalls.calls) resultMap.set(call.id, failedIds.has(call.id));
28040
28651
  }
28041
28652
  }
@@ -28272,7 +28883,7 @@ var init_session_status = __esm({
28272
28883
  });
28273
28884
 
28274
28885
  // ../../server/routes/shares.ts
28275
- import { basename as basename11, dirname as dirname11 } from "node:path";
28886
+ import { basename as basename11, dirname as dirname12 } from "node:path";
28276
28887
  function remoteAccessEnabled() {
28277
28888
  return isTeamEdition() || getConfig()?.networkAccess === true;
28278
28889
  }
@@ -28287,7 +28898,7 @@ async function resolveShareTarget(sessionId) {
28287
28898
  if (agentKind === "codex" || agentKind === "copilot") {
28288
28899
  return { shareable: false, reason: agentKind };
28289
28900
  }
28290
- const dirName = basename11(dirname11(filePath));
28901
+ const dirName = basename11(dirname12(filePath));
28291
28902
  const fileName = basename11(filePath);
28292
28903
  const resolved = await resolveSessionFilePath(dirName, fileName);
28293
28904
  if (resolved !== filePath) return { shareable: false, reason: "not-found" };
@@ -28693,7 +29304,7 @@ async function readBodyOrRespond(req, res) {
28693
29304
  return null;
28694
29305
  }
28695
29306
  }
28696
- function asString2(value) {
29307
+ function asString3(value) {
28697
29308
  return typeof value === "string" ? value : "";
28698
29309
  }
28699
29310
  function enqueueBootstrap(operation) {
@@ -28754,8 +29365,8 @@ function registerTeamAdminRoutes(use) {
28754
29365
  }
28755
29366
  try {
28756
29367
  const user = await createUser({
28757
- username: asString2(body.username),
28758
- password: asString2(body.password),
29368
+ username: asString3(body.username),
29369
+ password: asString3(body.password),
28759
29370
  displayName: typeof body.displayName === "string" ? body.displayName : void 0,
28760
29371
  role: "admin"
28761
29372
  });
@@ -28787,10 +29398,10 @@ function registerTeamAdminRoutes(use) {
28787
29398
  if (body === null) return;
28788
29399
  try {
28789
29400
  const user = await createUser({
28790
- username: asString2(body.username),
28791
- password: asString2(body.password),
29401
+ username: asString3(body.username),
29402
+ password: asString3(body.password),
28792
29403
  displayName: typeof body.displayName === "string" ? body.displayName : void 0,
28793
- role: asString2(body.role)
29404
+ role: asString3(body.role)
28794
29405
  });
28795
29406
  return sendJson(res, 200, { user });
28796
29407
  } catch (error) {
@@ -28883,10 +29494,10 @@ async function detectTeamFromSessionFile(sessionId, dirNameHint) {
28883
29494
  if (!isWithinDir(dirs.PROJECTS_DIR, filePath)) continue;
28884
29495
  const tags = await readSessionTeamTags(filePath);
28885
29496
  if (!tags.teamName) continue;
28886
- const configPath = join11(dirs.TEAMS_DIR, tags.teamName, "config.json");
28887
- if (!isWithinDir(dirs.TEAMS_DIR, configPath)) continue;
29497
+ const configPath2 = join11(dirs.TEAMS_DIR, tags.teamName, "config.json");
29498
+ if (!isWithinDir(dirs.TEAMS_DIR, configPath2)) continue;
28888
29499
  try {
28889
- const config = JSON.parse(await readFile9(configPath, "utf-8"));
29500
+ const config = JSON.parse(await readFile9(configPath2, "utf-8"));
28890
29501
  return {
28891
29502
  teamName: tags.teamName,
28892
29503
  config,
@@ -28965,8 +29576,8 @@ function registerTeamSessionRoutes(use) {
28965
29576
  let bestMatch = null;
28966
29577
  for (const teamName of teamDirs) {
28967
29578
  try {
28968
- const configPath = join11(dirs.TEAMS_DIR, teamName, "config.json");
28969
- const configRaw = await readFile9(configPath, "utf-8");
29579
+ const configPath2 = join11(dirs.TEAMS_DIR, teamName, "config.json");
29580
+ const configRaw = await readFile9(configPath2, "utf-8");
28970
29581
  const config = JSON.parse(configRaw);
28971
29582
  if (config.leadSessionId !== leadSessionId) continue;
28972
29583
  const createdAt = config.createdAt ?? 0;
@@ -29020,8 +29631,8 @@ function registerTeamSessionRoutes(use) {
29020
29631
  const teamName = decodeURIComponent(parts[0]);
29021
29632
  const memberName = decodeURIComponent(parts[1]);
29022
29633
  try {
29023
- const configPath = join11(dirs.TEAMS_DIR, teamName, "config.json");
29024
- const configRaw = await readFile9(configPath, "utf-8");
29634
+ const configPath2 = join11(dirs.TEAMS_DIR, teamName, "config.json");
29635
+ const configRaw = await readFile9(configPath2, "utf-8");
29025
29636
  const config = JSON.parse(configRaw);
29026
29637
  const leadSessionId = config.leadSessionId;
29027
29638
  if (!leadSessionId) {
@@ -29152,8 +29763,8 @@ function registerTeamRoutes(use) {
29152
29763
  const teams = [];
29153
29764
  for (const teamName of teamDirs) {
29154
29765
  try {
29155
- const configPath = join11(dirs.TEAMS_DIR, teamName, "config.json");
29156
- const configRaw = await readFile9(configPath, "utf-8");
29766
+ const configPath2 = join11(dirs.TEAMS_DIR, teamName, "config.json");
29767
+ const configRaw = await readFile9(configPath2, "utf-8");
29157
29768
  const config = JSON.parse(configRaw);
29158
29769
  const taskSummary = { total: 0, completed: 0, inProgress: 0, pending: 0 };
29159
29770
  try {
@@ -29352,7 +29963,7 @@ var init_teams = __esm({
29352
29963
  });
29353
29964
 
29354
29965
  // ../../server/routes/undo/paths.ts
29355
- import { dirname as dirname12 } from "node:path";
29966
+ import { dirname as dirname13 } from "node:path";
29356
29967
  function isOpaqueFileName(value) {
29357
29968
  return value.length > 0 && !value.includes("/") && !value.includes("\\") && !value.includes("\0");
29358
29969
  }
@@ -29360,7 +29971,7 @@ function resolveUndoStatePath(sessionId) {
29360
29971
  if (!isOpaqueFileName(sessionId)) return null;
29361
29972
  const undoRoot = resolve7(dirs.UNDO_DIR);
29362
29973
  const filePath = resolve7(undoRoot, `${sessionId}.json`);
29363
- return isWithinDir(undoRoot, filePath) && dirname12(filePath) === undoRoot ? filePath : null;
29974
+ return isWithinDir(undoRoot, filePath) && dirname13(filePath) === undoRoot ? filePath : null;
29364
29975
  }
29365
29976
  function resolveEncodedUndoStatePath(encodedSessionId) {
29366
29977
  try {
@@ -29384,7 +29995,7 @@ var init_paths = __esm({
29384
29995
  });
29385
29996
 
29386
29997
  // ../../server/routes/undo/fileOperations.ts
29387
- import { basename as basename12, dirname as dirname13, isAbsolute as isAbsolute13 } from "node:path";
29998
+ import { basename as basename12, dirname as dirname14, isAbsolute as isAbsolute13 } from "node:path";
29388
29999
  import { lstat as lstat6, realpath as realpath13 } from "node:fs/promises";
29389
30000
  function hasTraversalSegment(filePath) {
29390
30001
  return filePath.split(/[\\/]+/).includes("..");
@@ -29409,7 +30020,7 @@ async function resolveSafeOperationPath(filePath, home, canonicalHome) {
29409
30020
  } catch (error) {
29410
30021
  if (!isMissingPathError(error)) return null;
29411
30022
  try {
29412
- const canonicalParent = await realpath13(dirname13(resolved));
30023
+ const canonicalParent = await realpath13(dirname14(resolved));
29413
30024
  const canonicalTarget = join11(canonicalParent, basename12(resolved));
29414
30025
  return isWithinDir(canonicalHome, canonicalTarget) && !isForbiddenPath(canonicalTarget) ? canonicalTarget : null;
29415
30026
  } catch {
@@ -30044,25 +30655,25 @@ function aggregateSessionUsage(scopedRecords, rates2) {
30044
30655
  let providerReportedRecords = 0;
30045
30656
  let modelPricedRecords = 0;
30046
30657
  let unpricedRecords = 0;
30047
- for (const { record: record4, isSubagent } of scopedRecords) {
30048
- if (record4.dedupeKey !== null) {
30049
- if (seen.has(record4.dedupeKey)) continue;
30050
- seen.add(record4.dedupeKey);
30051
- }
30052
- const priced = priceUsage(rates2, record4.model, record4.totals, record4.reportedCostUsd, record4.speed);
30053
- const recordSavings = cacheSavingsUsd(rates2, record4.model, record4.totals, record4.speed);
30054
- const calculated = usageCostBreakdown(rates2, record4.model, record4.totals, record4.speed);
30055
- totals = addUsageCostTotals(totals, record4.totals);
30658
+ for (const { record: record5, isSubagent } of scopedRecords) {
30659
+ if (record5.dedupeKey !== null) {
30660
+ if (seen.has(record5.dedupeKey)) continue;
30661
+ seen.add(record5.dedupeKey);
30662
+ }
30663
+ const priced = priceUsage(rates2, record5.model, record5.totals, record5.reportedCostUsd, record5.speed);
30664
+ const recordSavings = cacheSavingsUsd(rates2, record5.model, record5.totals, record5.speed);
30665
+ const calculated = usageCostBreakdown(rates2, record5.model, record5.totals, record5.speed);
30666
+ totals = addUsageCostTotals(totals, record5.totals);
30056
30667
  costUsd += priced.costUsd;
30057
30668
  cacheSavings += recordSavings;
30058
30669
  addRecordCostBreakdown(breakdown, calculated, priced.costUsd);
30059
30670
  if (priced.costSource === "providerReported") providerReportedRecords += 1;
30060
30671
  else if (priced.costSource === "modelPriced") modelPricedRecords += 1;
30061
30672
  else unpricedRecords += 1;
30062
- let model = models.get(record4.model);
30673
+ let model = models.get(record5.model);
30063
30674
  if (!model) {
30064
30675
  model = {
30065
- model: record4.model,
30676
+ model: record5.model,
30066
30677
  totals: emptyUsageCostTotals(),
30067
30678
  costUsd: 0,
30068
30679
  cacheSavingsUsd: 0,
@@ -30070,18 +30681,18 @@ function aggregateSessionUsage(scopedRecords, rates2) {
30070
30681
  providerReportedRecords: 0,
30071
30682
  unpricedRecords: 0
30072
30683
  };
30073
- models.set(record4.model, model);
30684
+ models.set(record5.model, model);
30074
30685
  }
30075
- model.totals = addUsageCostTotals(model.totals, record4.totals);
30686
+ model.totals = addUsageCostTotals(model.totals, record5.totals);
30076
30687
  model.costUsd += priced.costUsd;
30077
30688
  model.cacheSavingsUsd += recordSavings;
30078
30689
  model.records += 1;
30079
30690
  if (priced.costSource === "providerReported") model.providerReportedRecords += 1;
30080
30691
  if (priced.costSource === "unpriced") model.unpricedRecords += 1;
30081
30692
  calls.push({
30082
- timestamp: new Date(record4.timestampMs).toISOString(),
30083
- model: record4.model,
30084
- totals: record4.totals,
30693
+ timestamp: new Date(record5.timestampMs).toISOString(),
30694
+ model: record5.model,
30695
+ totals: record5.totals,
30085
30696
  costUsd: priced.costUsd,
30086
30697
  costSource: priced.costSource,
30087
30698
  isSubagent
@@ -30126,20 +30737,20 @@ var init_aggregate = __esm({
30126
30737
  this.#toDay = makeDayFormatter(options.timeZone);
30127
30738
  }
30128
30739
  /** Folds one record in; returns whether it actually contributed. */
30129
- add(record4) {
30130
- if (record4.dedupeKey !== null) {
30131
- if (this.#seen.has(record4.dedupeKey)) return false;
30132
- this.#seen.add(record4.dedupeKey);
30740
+ add(record5) {
30741
+ if (record5.dedupeKey !== null) {
30742
+ if (this.#seen.has(record5.dedupeKey)) return false;
30743
+ this.#seen.add(record5.dedupeKey);
30133
30744
  }
30134
- const day = this.#toDay(record4.timestampMs);
30745
+ const day = this.#toDay(record5.timestampMs);
30135
30746
  if (day < this.#options.sinceDay || day > this.#options.untilDay) return false;
30136
- const key2 = [day, record4.provider, record4.model].join(KEY_SEPARATOR);
30747
+ const key2 = [day, record5.provider, record5.model].join(KEY_SEPARATOR);
30137
30748
  let bucket = this.#buckets.get(key2);
30138
30749
  if (bucket === void 0) {
30139
30750
  bucket = {
30140
30751
  day,
30141
- provider: record4.provider,
30142
- model: record4.model,
30752
+ provider: record5.provider,
30753
+ model: record5.model,
30143
30754
  totals: emptyUsageCostTotals(),
30144
30755
  costUsd: 0,
30145
30756
  cacheSavingsUsd: 0,
@@ -30152,25 +30763,25 @@ var init_aggregate = __esm({
30152
30763
  }
30153
30764
  const priced = priceUsage(
30154
30765
  this.#options.rates,
30155
- record4.model,
30156
- record4.totals,
30157
- record4.reportedCostUsd,
30158
- record4.speed
30766
+ record5.model,
30767
+ record5.totals,
30768
+ record5.reportedCostUsd,
30769
+ record5.speed
30159
30770
  );
30160
- bucket.totals = addUsageCostTotals(bucket.totals, record4.totals);
30771
+ bucket.totals = addUsageCostTotals(bucket.totals, record5.totals);
30161
30772
  bucket.costUsd += priced.costUsd;
30162
30773
  bucket.cacheSavingsUsd += cacheSavingsUsd(
30163
30774
  this.#options.rates,
30164
- record4.model,
30165
- record4.totals,
30166
- record4.speed
30775
+ record5.model,
30776
+ record5.totals,
30777
+ record5.speed
30167
30778
  );
30168
30779
  bucket.records += 1;
30169
30780
  if (priced.costSource === "unpriced") bucket.unpricedRecords += 1;
30170
30781
  if (priced.costSource === "providerReported") bucket.providerReportedRecords += 1;
30171
- if (record4.sessionId.length > 0) {
30172
- bucket.sessions.add(record4.sessionId);
30173
- this.#sessions.add(record4.sessionId);
30782
+ if (record5.sessionId.length > 0) {
30783
+ bucket.sessions.add(record5.sessionId);
30784
+ this.#sessions.add(record5.sessionId);
30174
30785
  }
30175
30786
  return true;
30176
30787
  }
@@ -30201,7 +30812,7 @@ var init_aggregate = __esm({
30201
30812
  // ../../server/lib/usageCost/reader.ts
30202
30813
  import { createReadStream as createReadStream3 } from "node:fs";
30203
30814
  import { readdir as readdir14, stat as stat19 } from "node:fs/promises";
30204
- import { join as join28 } from "node:path";
30815
+ import { join as join29 } from "node:path";
30205
30816
  import { createInterface as createInterface3 } from "node:readline";
30206
30817
  async function listTranscriptFiles(root, sinceMs) {
30207
30818
  const found = [];
@@ -30213,7 +30824,7 @@ async function listTranscriptFiles(root, sinceMs) {
30213
30824
  return;
30214
30825
  }
30215
30826
  for (const entry of entries3) {
30216
- const child = join28(dir, entry.name);
30827
+ const child = join29(dir, entry.name);
30217
30828
  if (entry.isDirectory()) {
30218
30829
  await walk2(child);
30219
30830
  continue;
@@ -30251,17 +30862,17 @@ async function readTranscriptRecords(filePath, provider) {
30251
30862
  function dedupeWithinFile(records) {
30252
30863
  const slotByKey = /* @__PURE__ */ new Map();
30253
30864
  const kept = [];
30254
- for (const record4 of records) {
30255
- if (record4.dedupeKey === null) {
30256
- kept.push(record4);
30865
+ for (const record5 of records) {
30866
+ if (record5.dedupeKey === null) {
30867
+ kept.push(record5);
30257
30868
  continue;
30258
30869
  }
30259
- const slot = slotByKey.get(record4.dedupeKey);
30870
+ const slot = slotByKey.get(record5.dedupeKey);
30260
30871
  if (slot === void 0) {
30261
- slotByKey.set(record4.dedupeKey, kept.push(record4) - 1);
30872
+ slotByKey.set(record5.dedupeKey, kept.push(record5) - 1);
30262
30873
  continue;
30263
30874
  }
30264
- if (record4.totals.outputTokens > kept[slot].totals.outputTokens) kept[slot] = record4;
30875
+ if (record5.totals.outputTokens > kept[slot].totals.outputTokens) kept[slot] = record5;
30265
30876
  }
30266
30877
  return kept;
30267
30878
  }
@@ -30272,10 +30883,10 @@ var init_reader = __esm({
30272
30883
  });
30273
30884
 
30274
30885
  // ../../server/lib/usageCost/service.ts
30275
- import { readFile as readFile21, stat as stat20, writeFile as writeFile7 } from "node:fs/promises";
30276
- import { join as join29 } from "node:path";
30886
+ import { readFile as readFile22, stat as stat20, writeFile as writeFile7 } from "node:fs/promises";
30887
+ import { join as join30 } from "node:path";
30277
30888
  function ratesCachePath() {
30278
- return join29(getDataRoot(), "usage-model-rates.json");
30889
+ return join30(getDataRoot(), "usage-model-rates.json");
30279
30890
  }
30280
30891
  function ratesFetchedAt() {
30281
30892
  return ratesFetchedAtMs === null ? null : new Date(ratesFetchedAtMs).toISOString();
@@ -30285,7 +30896,7 @@ async function ensureRatesInner() {
30285
30896
  if (ratesFetchedAtMs !== null && now - ratesFetchedAtMs < RATES_TTL_MS) return;
30286
30897
  if (ratesFetchedAtMs === null) {
30287
30898
  try {
30288
- const raw = JSON.parse(await readFile21(ratesCachePath(), "utf8"));
30899
+ const raw = JSON.parse(await readFile22(ratesCachePath(), "utf8"));
30289
30900
  if (typeof raw.fetchedAtMs === "number") {
30290
30901
  const parsed2 = parseRateTable(raw.document);
30291
30902
  if (parsed2.size > 0) {
@@ -30341,13 +30952,13 @@ async function readFileRecords(file, provider) {
30341
30952
  fileCache2.set(file.path, { size: file.size, mtimeMs: file.mtimeMs, provider, records });
30342
30953
  return records;
30343
30954
  }
30344
- function addCountedUsage(counted, record4) {
30345
- const byModel = counted.get(record4.sessionId) ?? /* @__PURE__ */ new Map();
30955
+ function addCountedUsage(counted, record5) {
30956
+ const byModel = counted.get(record5.sessionId) ?? /* @__PURE__ */ new Map();
30346
30957
  byModel.set(
30347
- record4.model,
30348
- addUsageCostTotals(byModel.get(record4.model) ?? emptyUsageCostTotals(), record4.totals)
30958
+ record5.model,
30959
+ addUsageCostTotals(byModel.get(record5.model) ?? emptyUsageCostTotals(), record5.totals)
30349
30960
  );
30350
- counted.set(record4.sessionId, byModel);
30961
+ counted.set(record5.sessionId, byModel);
30351
30962
  }
30352
30963
  function makeWindow(days, timeZone, nowMs = Date.now()) {
30353
30964
  const toDay = makeDayFormatter(timeZone);
@@ -30378,14 +30989,14 @@ async function readUsageCostSummary(input) {
30378
30989
  for (const file of files) {
30379
30990
  const records = await readFileRecords(file, provider);
30380
30991
  scannedFiles += 1;
30381
- for (const record4 of records) {
30382
- aggregator.add(record4);
30383
- if (liveSessionIds.has(record4.sessionId)) addCountedUsage(durableTotals, record4);
30992
+ for (const record5 of records) {
30993
+ aggregator.add(record5);
30994
+ if (liveSessionIds.has(record5.sessionId)) addCountedUsage(durableTotals, record5);
30384
30995
  }
30385
30996
  }
30386
30997
  }
30387
30998
  for (const runtime of runtimes2) {
30388
- for (const record4 of await runtime.liveUsageRecords(durableTotals)) aggregator.add(record4);
30999
+ for (const record5 of await runtime.liveUsageRecords(durableTotals)) aggregator.add(record5);
30389
31000
  }
30390
31001
  const retentionCutoffMs = startedAtMs - 90 * 24 * 60 * 60 * 1e3;
30391
31002
  for (const [path, entry] of fileCache2) {
@@ -30450,8 +31061,8 @@ async function childTranscripts(dirName, rootSessionId, provider) {
30450
31061
  }
30451
31062
  function countedUsageBySession(scopedRecords) {
30452
31063
  const counted = /* @__PURE__ */ new Map();
30453
- for (const { record: record4 } of scopedRecords) {
30454
- if (record4.sessionId) addCountedUsage(counted, record4);
31064
+ for (const { record: record5 } of scopedRecords) {
31065
+ if (record5.sessionId) addCountedUsage(counted, record5);
30455
31066
  }
30456
31067
  return counted;
30457
31068
  }
@@ -30465,7 +31076,7 @@ async function readSessionUsageCostSummary(input) {
30465
31076
  const store = storeForDirName(input.dirName);
30466
31077
  const provider = store.kind;
30467
31078
  const directRecords = await readFileRecords(directFile, provider);
30468
- const sessionId = store.descriptor.sessionFile.sessionId(input.fileName) ?? directRecords.find((record4) => record4.sessionId.length > 0)?.sessionId ?? "";
31079
+ const sessionId = store.descriptor.sessionFile.sessionId(input.fileName) ?? directRecords.find((record5) => record5.sessionId.length > 0)?.sessionId ?? "";
30469
31080
  const files = [
30470
31081
  { file: directFile, isSubagent: isSubagentAddress(input.fileName) }
30471
31082
  ];
@@ -30479,19 +31090,19 @@ async function readSessionUsageCostSummary(input) {
30479
31090
  records: await readFileRecords(file, provider)
30480
31091
  })));
30481
31092
  const scopedRecords = recordsByFile.flatMap(
30482
- ({ records, isSubagent }) => records.map((record4) => ({ record: record4, isSubagent }))
31093
+ ({ records, isSubagent }) => records.map((record5) => ({ record: record5, isSubagent }))
30483
31094
  );
30484
31095
  const sessionIds = /* @__PURE__ */ new Set();
30485
- for (const { record: record4 } of scopedRecords) {
30486
- if (record4.sessionId) sessionIds.add(record4.sessionId);
31096
+ for (const { record: record5 } of scopedRecords) {
31097
+ if (record5.sessionId) sessionIds.add(record5.sessionId);
30487
31098
  }
30488
31099
  if (sessionId) sessionIds.add(sessionId);
30489
31100
  const runtime = runtimeFor(provider);
30490
31101
  if ([...sessionIds].some((id) => runtime.hasSession(id))) {
30491
31102
  const liveRecords = await runtime.liveUsageRecords(countedUsageBySession(scopedRecords));
30492
- for (const record4 of liveRecords) {
30493
- if (!sessionIds.has(record4.sessionId)) continue;
30494
- scopedRecords.push({ record: record4, isSubagent: record4.sessionId !== sessionId });
31103
+ for (const record5 of liveRecords) {
31104
+ if (!sessionIds.has(record5.sessionId)) continue;
31105
+ scopedRecords.push({ record: record5, isSubagent: record5.sessionId !== sessionId });
30495
31106
  }
30496
31107
  }
30497
31108
  const aggregated = aggregateSessionUsage(scopedRecords, rates);
@@ -31286,7 +31897,7 @@ var init_worktreeIo = __esm({
31286
31897
  });
31287
31898
 
31288
31899
  // ../../server/routes/worktrees/worktreeUtils.ts
31289
- import { resolve as resolve20, dirname as dirname14 } from "node:path";
31900
+ import { resolve as resolve20, dirname as dirname15 } from "node:path";
31290
31901
  function isValidWorktreeName(name) {
31291
31902
  return /^[a-zA-Z0-9._-]+$/.test(name) && name.length <= 40;
31292
31903
  }
@@ -31322,7 +31933,7 @@ async function readFirstJsonLine(filePath) {
31322
31933
  await fileHandle.close();
31323
31934
  }
31324
31935
  }
31325
- async function resolveProjectPath2(projectDir, dirName) {
31936
+ async function resolveProjectPath3(projectDir, dirName) {
31326
31937
  try {
31327
31938
  const files = await readdir6(projectDir);
31328
31939
  const sessionFiles = files.filter((file) => file.endsWith(".jsonl"));
@@ -31349,7 +31960,7 @@ async function getMainWorktreeRoot(projectPath) {
31349
31960
  const commonDir = (await runWorktreeCommand("git", ["rev-parse", "--git-common-dir"], {
31350
31961
  cwd: projectPath
31351
31962
  })).trim();
31352
- return dirname14(resolve20(projectPath, commonDir));
31963
+ return dirname15(resolve20(projectPath, commonDir));
31353
31964
  } catch {
31354
31965
  return null;
31355
31966
  }
@@ -31512,7 +32123,7 @@ async function handleWorktreeList(dirName, res) {
31512
32123
  res.end(JSON.stringify({ error: "Access denied" }));
31513
32124
  return;
31514
32125
  }
31515
- const projectPath = await resolveProjectPath2(projectDir, dirName);
32126
+ const projectPath = await resolveProjectPath3(projectDir, dirName);
31516
32127
  const gitRoot = await getMainWorktreeRoot(projectPath);
31517
32128
  if (!gitRoot) {
31518
32129
  res.setHeader("Content-Type", "application/json");
@@ -31601,7 +32212,7 @@ function requireProjectDir(dirName, res) {
31601
32212
  return projectDir;
31602
32213
  }
31603
32214
  async function requireGitRoot(projectDir, dirName, res) {
31604
- const projectPath = await resolveProjectPath2(projectDir, dirName);
32215
+ const projectPath = await resolveProjectPath3(projectDir, dirName);
31605
32216
  const gitRoot = await getMainWorktreeRoot(projectPath);
31606
32217
  if (!gitRoot) {
31607
32218
  res.statusCode = 400;
@@ -31834,8 +32445,8 @@ function apiRoute(id, register) {
31834
32445
  function registerApiRoutes(use, context) {
31835
32446
  const safeUse = (path, handler) => use(path, catchAsyncErrors(handler));
31836
32447
  safeUse("/api", compressionMiddleware);
31837
- for (const route of API_ROUTE_REGISTRY) {
31838
- route.register(safeUse, context);
32448
+ for (const route2 of API_ROUTE_REGISTRY) {
32449
+ route2.register(safeUse, context);
31839
32450
  }
31840
32451
  }
31841
32452
  var API_ROUTE_REGISTRY;
@@ -31863,6 +32474,7 @@ var init_api_routes = __esm({
31863
32474
  init_git_status();
31864
32475
  init_github();
31865
32476
  init_vercel_deployments();
32477
+ init_clickup();
31866
32478
  init_project_icon();
31867
32479
  init_hello();
31868
32480
  init_local_file();
@@ -31878,6 +32490,7 @@ var init_api_routes = __esm({
31878
32490
  init_projects2();
31879
32491
  init_provider_updates();
31880
32492
  init_agent_executable();
32493
+ init_agent_accounts();
31881
32494
  init_scripts();
31882
32495
  init_session_config();
31883
32496
  init_session_context();
@@ -31934,6 +32547,7 @@ var init_api_routes = __esm({
31934
32547
  apiRoute("git-status", registerGitStatusRoutes),
31935
32548
  apiRoute("github", registerGitHubRoutes),
31936
32549
  apiRoute("vercel-deployments", registerVercelDeploymentRoutes),
32550
+ apiRoute("clickup", registerClickUpRoutes),
31937
32551
  apiRoute("project-icon", registerProjectIconRoutes),
31938
32552
  apiRoute("git-diff", registerGitDiffRoutes),
31939
32553
  apiRoute("mcp", registerMcpRoutes),
@@ -31948,7 +32562,8 @@ var init_api_routes = __esm({
31948
32562
  apiRoute("codex-threads", registerCodexThreadRoutes),
31949
32563
  apiRoute("agent-runtime", registerAgentRuntimeRoutes),
31950
32564
  apiRoute("provider-updates", registerProviderUpdateRoutes),
31951
- apiRoute("agent-executable", registerAgentExecutableRoutes)
32565
+ apiRoute("agent-executable", registerAgentExecutableRoutes),
32566
+ apiRoute("agent-accounts", registerAgentAccountRoutes)
31952
32567
  ];
31953
32568
  }
31954
32569
  });
@@ -31992,7 +32607,7 @@ import { WebSocket } from "ws";
31992
32607
  import { spawn as ptySpawn } from "node-pty";
31993
32608
  import { execFileSync as execFileSync2 } from "node:child_process";
31994
32609
  import { randomUUID as randomUUID6 } from "node:crypto";
31995
- import { homedir as homedir11 } from "node:os";
32610
+ import { homedir as homedir12 } from "node:os";
31996
32611
  function defaultShell() {
31997
32612
  if (process.platform === "win32") return process.env.COMSPEC ?? "powershell.exe";
31998
32613
  return process.env.SHELL ?? "/bin/zsh";
@@ -32106,7 +32721,7 @@ var init_pty_server = __esm({
32106
32721
  return;
32107
32722
  }
32108
32723
  const name = msg.name || `Terminal ${this.sessions.size + 1}`;
32109
- const cwd = msg.cwd || homedir11();
32724
+ const cwd = msg.cwd || homedir12();
32110
32725
  const cols = msg.cols || 80;
32111
32726
  const rows = msg.rows || 24;
32112
32727
  const command = msg.command || defaultShell();
@@ -32364,18 +32979,18 @@ var init_pty_authorization = __esm({
32364
32979
  // ../../server/app-server.ts
32365
32980
  import express from "express";
32366
32981
  import { createServer, request as httpRequest2 } from "node:http";
32367
- import { join as join30 } from "node:path";
32982
+ import { join as join31 } from "node:path";
32368
32983
  import { WebSocketServer as WebSocketServer2 } from "ws";
32369
32984
  async function createServerComposition(staticDir, userDataDir, environment) {
32370
32985
  setDataRoot(userDataDir);
32371
- setConfigPath(join30(userDataDir, "config.local.json"));
32986
+ setConfigPath(join31(userDataDir, "config.local.json"));
32372
32987
  await loadConfig();
32373
32988
  const configEdition = getConfiguredEditionValue();
32374
32989
  initEdition({ shell: environment.mode, configEdition });
32375
32990
  const suppression = describeEditionSuppression(process.env, configEdition, environment.mode);
32376
32991
  if (suppression) console.warn(suppression);
32377
32992
  if (isTeamEdition()) {
32378
- const teamDir = join30(getDataRoot(), "team");
32993
+ const teamDir = join31(getDataRoot(), "team");
32379
32994
  await initUsersStore(teamDir);
32380
32995
  await initSessionPersistence(teamDir);
32381
32996
  initializeBootstrapToken(userCount());
@@ -32545,11 +33160,11 @@ var init_standalone_app_server = __esm({
32545
33160
 
32546
33161
  // ../../server/lib/portFile.ts
32547
33162
  import { mkdirSync as mkdirSync2, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
32548
- import { homedir as homedir12 } from "node:os";
32549
- import { dirname as dirname15, join as join31 } from "node:path";
33163
+ import { homedir as homedir13 } from "node:os";
33164
+ import { dirname as dirname16, join as join32 } from "node:path";
32550
33165
  function writePortFile(port) {
32551
33166
  try {
32552
- mkdirSync2(dirname15(PORT_FILE), { recursive: true });
33167
+ mkdirSync2(dirname16(PORT_FILE), { recursive: true });
32553
33168
  writeFileSync2(PORT_FILE, `${port}
32554
33169
  `, { mode: 384 });
32555
33170
  } catch (err) {
@@ -32566,7 +33181,7 @@ function removePortFile() {
32566
33181
  var PORT_FILE;
32567
33182
  var init_portFile = __esm({
32568
33183
  "../../server/lib/portFile.ts"() {
32569
- PORT_FILE = join31(homedir12(), ".cogpit", "port");
33184
+ PORT_FILE = join32(homedir13(), ".cogpit", "port");
32570
33185
  }
32571
33186
  });
32572
33187
 
@@ -32814,8 +33429,8 @@ __export(standalone_runtime_exports, {
32814
33429
  startStandaloneServer: () => startStandaloneServer
32815
33430
  });
32816
33431
  import { existsSync, mkdirSync as mkdirSync3 } from "node:fs";
32817
- import { homedir as homedir13 } from "node:os";
32818
- import { join as join32 } from "node:path";
33432
+ import { homedir as homedir14 } from "node:os";
33433
+ import { join as join33 } from "node:path";
32819
33434
  function listen(server, port, host) {
32820
33435
  return new Promise((resolve22, reject) => {
32821
33436
  const onError = (error) => reject(error);
@@ -32833,23 +33448,23 @@ function listen(server, port, host) {
32833
33448
  }
32834
33449
  async function startStandaloneServer({
32835
33450
  staticDir,
32836
- dataDir = join32(homedir13(), ".config", "cogpit"),
33451
+ dataDir = join33(homedir14(), ".config", "cogpit"),
32837
33452
  host = "127.0.0.1",
32838
33453
  port = 19384,
32839
33454
  env = process.env,
32840
33455
  publishPort = false
32841
33456
  }) {
32842
33457
  mkdirSync3(dataDir, { recursive: true });
32843
- const configPath = join32(dataDir, "config.local.json");
32844
- setConfigPath(configPath);
32845
- const configExisted = existsSync(configPath);
33458
+ const configPath2 = join33(dataDir, "config.local.json");
33459
+ setConfigPath(configPath2);
33460
+ const configExisted = existsSync(configPath2);
32846
33461
  await loadConfig();
32847
33462
  let createdConfig;
32848
33463
  if (!configExisted) {
32849
- const claudeDir = join32(homedir13(), ".claude");
32850
- if (existsSync(join32(claudeDir, "projects"))) {
33464
+ const claudeDir = join33(homedir14(), ".claude");
33465
+ if (existsSync(join33(claudeDir, "projects"))) {
32851
33466
  await saveConfig({ claudeDir });
32852
- createdConfig = `${configPath} for ${claudeDir}`;
33467
+ createdConfig = `${configPath2} for ${claudeDir}`;
32853
33468
  }
32854
33469
  }
32855
33470
  initEdition({ shell: "standalone", configEdition: getConfiguredEditionValue() });
@@ -32919,8 +33534,8 @@ var init_standalone_runtime = __esm({
32919
33534
 
32920
33535
  // src/index.ts
32921
33536
  import { spawn as spawn4 } from "node:child_process";
32922
- import { homedir as homedir14 } from "node:os";
32923
- import { join as join33, resolve as resolve21 } from "node:path";
33537
+ import { homedir as homedir15 } from "node:os";
33538
+ import { join as join34, resolve as resolve21 } from "node:path";
32924
33539
  var SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/;
32925
33540
  var USAGE = `Cogpit
32926
33541
 
@@ -33029,8 +33644,8 @@ async function openExternalUrl(url) {
33029
33644
  async function startPackagedServer(options) {
33030
33645
  const { startStandaloneServer: startStandaloneServer2 } = await Promise.resolve().then(() => (init_standalone_runtime(), standalone_runtime_exports));
33031
33646
  return startStandaloneServer2({
33032
- staticDir: join33(import.meta.dirname, "web"),
33033
- dataDir: options.dataDir ?? join33(homedir14(), ".config", "cogpit"),
33647
+ staticDir: join34(import.meta.dirname, "web"),
33648
+ dataDir: options.dataDir ?? join34(homedir15(), ".config", "cogpit"),
33034
33649
  host: "127.0.0.1",
33035
33650
  port: options.port,
33036
33651
  publishPort: false
@@ -33046,7 +33661,7 @@ async function waitForShutdownSignal() {
33046
33661
  for (const signal of signals) process.once(signal, done);
33047
33662
  });
33048
33663
  }
33049
- var defaultDependencies3 = {
33664
+ var defaultDependencies4 = {
33050
33665
  fetch,
33051
33666
  openUrl: openExternalUrl,
33052
33667
  startServer: startPackagedServer,
@@ -33073,7 +33688,7 @@ async function verifyServer(server, command, deps) {
33073
33688
  }
33074
33689
  }
33075
33690
  async function run(argv, overrides = {}) {
33076
- const deps = { ...defaultDependencies3, ...overrides };
33691
+ const deps = { ...defaultDependencies4, ...overrides };
33077
33692
  let command;
33078
33693
  try {
33079
33694
  command = parseArgs(argv);