jinzd-ai-cli 0.4.114 → 0.4.116

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  buildWriteRoundReminder,
15
15
  clearDevState,
16
16
  computeCost,
17
+ detectMetaNarration,
17
18
  detectPseudoToolCalls,
18
19
  detectsHallucinatedFileOp,
19
20
  extractWrittenFilePaths,
@@ -31,10 +32,10 @@ import {
31
32
  setupProxy,
32
33
  stripPseudoToolCalls,
33
34
  stripToolCallReminder
34
- } from "./chunk-E24HT62E.js";
35
+ } from "./chunk-QMT4T4PH.js";
35
36
  import {
36
37
  ConfigManager
37
- } from "./chunk-CP6PALA4.js";
38
+ } from "./chunk-KRTQDZMY.js";
38
39
  import {
39
40
  ToolExecutor,
40
41
  ToolRegistry,
@@ -53,10 +54,10 @@ import {
53
54
  spawnAgentContext,
54
55
  theme,
55
56
  undoStack
56
- } from "./chunk-XXKWSBRC.js";
57
+ } from "./chunk-YTP26DOV.js";
57
58
  import "./chunk-3BICTI5M.js";
58
59
  import "./chunk-2DXY7UGF.js";
59
- import "./chunk-2WAF7FOX.js";
60
+ import "./chunk-VJE5V4H2.js";
60
61
  import "./chunk-2ZD3YTVM.js";
61
62
  import {
62
63
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -79,7 +80,7 @@ import {
79
80
  SKILLS_DIR_NAME,
80
81
  VERSION,
81
82
  buildUserIdentityPrompt
82
- } from "./chunk-UF62SHR7.js";
83
+ } from "./chunk-H3F2E4MD.js";
83
84
  import {
84
85
  formatGitContextForPrompt,
85
86
  getGitContext,
@@ -411,6 +412,7 @@ var Renderer = class {
411
412
  buf = "";
412
413
  };
413
414
  let interrupted = false;
415
+ let streamErr = null;
414
416
  try {
415
417
  for await (const chunk of stream) {
416
418
  if (options?.signal?.aborted) {
@@ -435,41 +437,51 @@ var Renderer = class {
435
437
  interrupted = true;
436
438
  if (!inThinking) flushBuf();
437
439
  } else {
438
- throw err;
440
+ streamErr = err;
439
441
  }
440
442
  }
441
443
  if (interrupted) {
442
444
  process.stdout.write(theme.dim(" [interrupted]\n"));
443
445
  }
444
446
  let tokensShown = false;
445
- if (options?.showTokens) {
446
- process.stdout.write("\n");
447
- if (usage) {
448
- const sessionTotal = options.sessionTotal;
449
- const updatedTotal = sessionTotal ? { inputTokens: sessionTotal.inputTokens + usage.inputTokens, outputTokens: sessionTotal.outputTokens + usage.outputTokens } : void 0;
450
- this.renderUsage(usage, updatedTotal);
451
- tokensShown = true;
452
- } else if (fullContent.length > 0) {
453
- const est = Math.ceil(fullContent.length / 2.5);
454
- process.stdout.write(theme.dim(`\u{1F4CA} ~${est.toLocaleString()} output tokens (estimated)
447
+ if (!streamErr) {
448
+ if (options?.showTokens) {
449
+ process.stdout.write("\n");
450
+ if (usage) {
451
+ const sessionTotal = options.sessionTotal;
452
+ const updatedTotal = sessionTotal ? { inputTokens: sessionTotal.inputTokens + usage.inputTokens, outputTokens: sessionTotal.outputTokens + usage.outputTokens } : void 0;
453
+ this.renderUsage(usage, updatedTotal);
454
+ tokensShown = true;
455
+ } else if (fullContent.length > 0) {
456
+ const est = Math.ceil(fullContent.length / 2.5);
457
+ process.stdout.write(theme.dim(`\u{1F4CA} ~${est.toLocaleString()} output tokens (estimated)
455
458
 
456
459
  `));
457
- tokensShown = true;
460
+ tokensShown = true;
461
+ } else {
462
+ process.stdout.write("\n");
463
+ }
458
464
  } else {
459
- process.stdout.write("\n");
465
+ process.stdout.write("\n\n");
460
466
  }
461
467
  } else {
462
- process.stdout.write("\n\n");
468
+ process.stdout.write("\n");
463
469
  }
464
470
  if (fileStream) {
465
- await new Promise((resolve3, reject) => {
466
- fileStream.end((err) => err ? reject(err) : resolve3());
467
- });
468
- const kb = (Buffer.byteLength(fullContent, "utf-8") / 1024).toFixed(1);
469
- process.stdout.write(theme.success(` \u2705 Saved: ${options.saveToFile} (${kb} KB)
471
+ try {
472
+ await new Promise((resolve3) => {
473
+ fileStream.end(() => resolve3());
474
+ });
475
+ } catch {
476
+ }
477
+ if (!streamErr) {
478
+ const kb = (Buffer.byteLength(fullContent, "utf-8") / 1024).toFixed(1);
479
+ process.stdout.write(theme.success(` \u2705 Saved: ${options.saveToFile} (${kb} KB)
470
480
 
471
481
  `));
482
+ }
472
483
  }
484
+ if (streamErr) throw streamErr;
473
485
  return { content: fullContent, usage, tokensShown };
474
486
  }
475
487
  renderResponse(content) {
@@ -964,6 +976,42 @@ var CommandRegistry = class {
964
976
  return [...this.commands.values()];
965
977
  }
966
978
  };
979
+ async function promptSkillHistoryAction(ctx, fromLabel, toLabel) {
980
+ const session = ctx.sessions.current;
981
+ const msgCount = session?.messages.length ?? 0;
982
+ if (msgCount === 0 || !session) return true;
983
+ const choice = await ctx.select(
984
+ `Switching skill: ${fromLabel} \u2192 ${toLabel} (${msgCount} message(s) in context)`,
985
+ [
986
+ { value: "clear", label: "Clear history", hint: "recommended \u2014 fresh start under new skill" },
987
+ { value: "fork", label: "Fork to new branch", hint: "preserve old branch, start fresh on new one" },
988
+ { value: "keep", label: "Keep history", hint: "old skill actions may bias new skill" },
989
+ { value: "cancel", label: "Cancel", hint: "do not switch skill" }
990
+ ],
991
+ 0
992
+ );
993
+ if (!choice || choice === "cancel") return false;
994
+ if (choice === "clear") {
995
+ session.clear();
996
+ ctx.resetSessionTokenUsage();
997
+ ctx.clearDevState();
998
+ ctx.renderer.printInfo(` History cleared (${msgCount} message(s) removed).`);
999
+ } else if (choice === "fork") {
1000
+ try {
1001
+ const branchTitle = toLabel === "(none)" ? `pre-deactivate-${fromLabel}` : `skill-${toLabel}`;
1002
+ const newId = session.createBranch(0, branchTitle);
1003
+ await ctx.sessions.save();
1004
+ ctx.renderer.printInfo(` Forked to fresh branch "${newId}" (old branch preserved).`);
1005
+ } catch (err) {
1006
+ ctx.renderer.renderError(`Fork failed: ${err.message}`);
1007
+ return false;
1008
+ }
1009
+ }
1010
+ if (choice === "keep") {
1011
+ ctx.renderer.printInfo(" Keeping history. Use /clear later if the new skill misbehaves.");
1012
+ }
1013
+ return true;
1014
+ }
967
1015
  function createDefaultCommands() {
968
1016
  return [
969
1017
  {
@@ -1600,7 +1648,7 @@ ${text}
1600
1648
  const { join: join6 } = await import("path");
1601
1649
  const { existsSync: existsSync6 } = await import("fs");
1602
1650
  const { getGitRoot: getGitRoot2 } = await import("./git-context-7KIP4X2V.js");
1603
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-YEBRZDBP.js");
1651
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-NWATGC4A.js");
1604
1652
  const { approveProject, hashMcpFile } = await import("./project-trust-IFM7FXEV.js");
1605
1653
  const cwd = process.cwd();
1606
1654
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -1863,7 +1911,7 @@ ${text}
1863
1911
  name: "skill",
1864
1912
  description: "Manage agent skills (reusable prompt packs)",
1865
1913
  usage: "/skill [name|off|list|reload]",
1866
- execute(args, ctx) {
1914
+ async execute(args, ctx) {
1867
1915
  const sub = args[0]?.toLowerCase();
1868
1916
  const manager = ctx.getSkillManager();
1869
1917
  if (!manager) {
@@ -1896,10 +1944,13 @@ ${text}
1896
1944
  return;
1897
1945
  }
1898
1946
  if (sub === "off" || sub === "none" || sub === "deactivate") {
1899
- if (!manager.getActive()) {
1947
+ const prev2 = manager.getActive();
1948
+ if (!prev2) {
1900
1949
  ctx.renderer.printInfo("No skill is currently active.");
1901
1950
  return;
1902
1951
  }
1952
+ const proceed2 = await promptSkillHistoryAction(ctx, prev2.meta.name, "(none)");
1953
+ if (!proceed2) return;
1903
1954
  manager.deactivate();
1904
1955
  ctx.refreshPrompt();
1905
1956
  ctx.renderer.printSuccess("Skill deactivated.");
@@ -1910,11 +1961,19 @@ ${text}
1910
1961
  ctx.renderer.printSuccess(`Reloaded: ${count} skill(s) found.`);
1911
1962
  return;
1912
1963
  }
1913
- const skill = manager.activate(sub);
1914
- if (!skill) {
1964
+ const target = manager.listSkills().find((s) => s.meta.name === sub);
1965
+ if (!target) {
1915
1966
  ctx.renderer.renderError(`Skill '${sub}' not found. Use /skill list to see available skills.`);
1916
1967
  return;
1917
1968
  }
1969
+ const prev = manager.getActive();
1970
+ if (prev?.meta.name === sub) {
1971
+ ctx.renderer.printInfo(`Skill '${sub}' is already active.`);
1972
+ return;
1973
+ }
1974
+ const proceed = await promptSkillHistoryAction(ctx, prev?.meta.name ?? "(none)", sub);
1975
+ if (!proceed) return;
1976
+ const skill = manager.activate(sub);
1918
1977
  ctx.refreshPrompt();
1919
1978
  ctx.renderer.printSuccess(`Skill activated: ${skill.meta.name} \u2014 ${skill.meta.description}`);
1920
1979
  if (skill.meta.tools) {
@@ -2650,7 +2709,7 @@ ${hint}` : "")
2650
2709
  usage: "/test [command|filter]",
2651
2710
  async execute(args, ctx) {
2652
2711
  try {
2653
- const { executeTests } = await import("./run-tests-7WN5Q7YV.js");
2712
+ const { executeTests } = await import("./run-tests-QOZZHW4L.js");
2654
2713
  const argStr = args.join(" ").trim();
2655
2714
  let testArgs = {};
2656
2715
  if (argStr) {
@@ -6260,10 +6319,71 @@ ${mcpBudgetNote}` : "");
6260
6319
  _extraMessages: teeExtraMessages
6261
6320
  });
6262
6321
  const teeShowTokens = this.shouldShowTokens();
6263
- const { content: genContent, usage: genUsage, tokensShown: teeTokShown } = await this.renderer.renderStream(
6264
- genStream,
6265
- { saveToFile, showTokens: teeShowTokens, sessionTotal: teeShowTokens ? { ...this.sessionTokenUsage } : void 0, signal: teeAc.signal }
6266
- );
6322
+ let genContent;
6323
+ let genUsage;
6324
+ let teeTokShown = false;
6325
+ try {
6326
+ const teeResult = await this.renderer.renderStream(
6327
+ genStream,
6328
+ { saveToFile, showTokens: teeShowTokens, sessionTotal: teeShowTokens ? { ...this.sessionTokenUsage } : void 0, signal: teeAc.signal }
6329
+ );
6330
+ genContent = teeResult.content;
6331
+ genUsage = teeResult.usage;
6332
+ teeTokShown = teeResult.tokensShown;
6333
+ } catch (teeErr) {
6334
+ try {
6335
+ unlinkSync2(saveToFile);
6336
+ } catch {
6337
+ }
6338
+ const errMsg = teeErr instanceof Error ? teeErr.message : String(teeErr);
6339
+ process.stdout.write(theme.error(
6340
+ `
6341
+ \u2717 tee stream failed: ${errMsg}
6342
+ ${saveToFile} (partial) was deleted. Asking model to retry.
6343
+
6344
+ `
6345
+ ));
6346
+ const errorResults = result.toolCalls.map((tc) => ({
6347
+ callId: tc.id,
6348
+ content: tc.name === "save_last_response" ? `[save_last_response failed] streaming was interrupted: ${errMsg}. ${saveToFile} was NOT saved. Retry \u2014 and consider producing a more compact output (split very large reports across multiple save_last_response calls if the previous attempt timed out).` : `[skipped: save_last_response failed]`,
6349
+ isError: tc.name === "save_last_response"
6350
+ }));
6351
+ const reasoningContent3 = "reasoningContent" in result ? result.reasoningContent : void 0;
6352
+ const newMsgs3 = provider.buildToolResultMessages(result.toolCalls, errorResults, reasoningContent3);
6353
+ extraMessages.push(...newMsgs3);
6354
+ continue;
6355
+ }
6356
+ const metaMatch = detectMetaNarration(genContent);
6357
+ if (metaMatch) {
6358
+ try {
6359
+ unlinkSync2(saveToFile);
6360
+ } catch {
6361
+ }
6362
+ process.stdout.write(theme.error(
6363
+ `
6364
+ \u2717 Rejected save: response was meta-narration / leaked reasoning, not document body (matched: ${metaMatch})
6365
+ ${saveToFile} was deleted; asking model to retry.
6366
+
6367
+ `
6368
+ ));
6369
+ const errorResults = result.toolCalls.map((tc) => ({
6370
+ callId: tc.id,
6371
+ content: tc.name === "save_last_response" ? `[save_last_response REJECTED] Your output was internal reasoning / meta-narration about the task (e.g. "Let me re-read\u2026", "the user is asking me to\u2026") instead of the requested document body. ${saveToFile} was NOT saved.
6372
+
6373
+ This fresh stream has NO tools. Produce ONLY the document body: start with a markdown heading like "# \u5BA1\u8BA1\u62A5\u544A" / "# Audit Report" and write the full content. Do NOT narrate that you will produce the document \u2014 produce it.` : `[skipped: save_last_response was rejected and other parallel calls are abandoned]`,
6374
+ isError: tc.name === "save_last_response"
6375
+ }));
6376
+ const reasoningContent3 = "reasoningContent" in result ? result.reasoningContent : void 0;
6377
+ const newMsgs3 = provider.buildToolResultMessages(result.toolCalls, errorResults, reasoningContent3);
6378
+ extraMessages.push(...newMsgs3);
6379
+ if (genUsage) {
6380
+ roundUsage.inputTokens += genUsage.inputTokens;
6381
+ roundUsage.outputTokens += genUsage.outputTokens;
6382
+ roundUsage.cacheCreationTokens += genUsage.cacheCreationTokens ?? 0;
6383
+ roundUsage.cacheReadTokens += genUsage.cacheReadTokens ?? 0;
6384
+ }
6385
+ continue;
6386
+ }
6267
6387
  const pseudoMatch = detectPseudoToolCalls(genContent);
6268
6388
  if (pseudoMatch) {
6269
6389
  const cleaned = stripPseudoToolCalls(genContent);
@@ -6882,11 +7002,11 @@ program.command("web").description("Start Web UI server with browser-based chat
6882
7002
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
6883
7003
  process.exit(1);
6884
7004
  }
6885
- const { startWebServer } = await import("./server-AKG7HG36.js");
7005
+ const { startWebServer } = await import("./server-IX6L4W2L.js");
6886
7006
  await startWebServer({ port, host: options.host });
6887
7007
  });
6888
7008
  program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | logout-all <name> | migrate <name>)").action(async (action, username) => {
6889
- const { AuthManager } = await import("./auth-VBV7HTLQ.js");
7009
+ const { AuthManager } = await import("./auth-7KK5BOCA.js");
6890
7010
  const config = new ConfigManager();
6891
7011
  const auth = new AuthManager(config.getConfigDir());
6892
7012
  if (!action || action === "list") {
@@ -7018,7 +7138,7 @@ program.command("sessions").description("List recent conversation sessions").act
7018
7138
  });
7019
7139
  program.command("batch <action> [arg] [arg2]").description("Anthropic Message Batches: submit | list | status <id> | results <id> [out] | cancel <id>").option("--dry-run", "Parse and validate input without submitting (submit only)").action(async (action, arg, arg2, options) => {
7020
7140
  try {
7021
- const batch = await import("./batch-Q5NQCXKN.js");
7141
+ const batch = await import("./batch-GRHEH3JF.js");
7022
7142
  switch (action) {
7023
7143
  case "submit":
7024
7144
  if (!arg) {
@@ -7061,7 +7181,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
7061
7181
  }
7062
7182
  });
7063
7183
  program.command("mcp-serve").description("Start an MCP server over STDIO, exposing aicli's built-in tools to Claude Desktop / Cursor / other MCP clients").option("--allow-destructive", "Allow bash / run_interactive / task_create (always destructive in MCP mode)").option("--allow-outside-cwd", "Allow tool path arguments to escape the sandbox root \u2014 disabled by default").option("--tools <list>", "Comma-separated whitelist of tools to expose (default: all eligible tools)").option("--cwd <path>", "Working directory AND sandbox root (default: current directory)").action(async (options) => {
7064
- const { startMcpServer } = await import("./server-NQ5J6FAL.js");
7184
+ const { startMcpServer } = await import("./server-HI6GVBD3.js");
7065
7185
  await startMcpServer({
7066
7186
  allowDestructive: !!options.allowDestructive,
7067
7187
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -7188,7 +7308,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
7188
7308
  }),
7189
7309
  config.get("customProviders")
7190
7310
  );
7191
- const { startHub } = await import("./hub-DGJC2RRF.js");
7311
+ const { startHub } = await import("./hub-YNP5HCTT.js");
7192
7312
  await startHub(
7193
7313
  {
7194
7314
  topic: topic ?? "",
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-W45U3KQE.js";
4
+ } from "./chunk-BXDHW7JO.js";
5
5
  import "./chunk-3RG5ZIWI.js";
6
6
  export {
7
7
  executeTests,
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-2WAF7FOX.js";
6
- import "./chunk-UF62SHR7.js";
5
+ } from "./chunk-VJE5V4H2.js";
6
+ import "./chunk-H3F2E4MD.js";
7
7
  import "./chunk-PDX44BCA.js";
8
8
  export {
9
9
  executeTests,
@@ -3,14 +3,14 @@ import {
3
3
  ToolRegistry,
4
4
  getDangerLevel,
5
5
  schemaToJsonSchema
6
- } from "./chunk-XXKWSBRC.js";
6
+ } from "./chunk-YTP26DOV.js";
7
7
  import "./chunk-3BICTI5M.js";
8
8
  import "./chunk-2DXY7UGF.js";
9
- import "./chunk-2WAF7FOX.js";
9
+ import "./chunk-VJE5V4H2.js";
10
10
  import "./chunk-2ZD3YTVM.js";
11
11
  import {
12
12
  VERSION
13
- } from "./chunk-UF62SHR7.js";
13
+ } from "./chunk-H3F2E4MD.js";
14
14
  import "./chunk-4BKXL7SM.js";
15
15
  import "./chunk-7ZJN4KLV.js";
16
16
  import "./chunk-KHYD3WXE.js";
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- AuthManager
4
- } from "./chunk-5UPFMM2A.js";
3
+ AuthManager,
4
+ TOKEN_EXPIRY_MS
5
+ } from "./chunk-O7NM4WTS.js";
5
6
  import {
6
7
  CONTENT_ONLY_STREAM_REMINDER,
7
8
  HALLUCINATION_CORRECTION_MESSAGE,
@@ -13,6 +14,7 @@ import {
13
14
  TOOL_CALL_REMINDER,
14
15
  autoTrimSessionIfNeeded,
15
16
  computeCost,
17
+ detectMetaNarration,
16
18
  detectPseudoToolCalls,
17
19
  detectsHallucinatedFileOp,
18
20
  formatCost,
@@ -24,10 +26,10 @@ import {
24
26
  setupProxy,
25
27
  stripPseudoToolCalls,
26
28
  stripToolCallReminder
27
- } from "./chunk-E24HT62E.js";
29
+ } from "./chunk-QMT4T4PH.js";
28
30
  import {
29
31
  ConfigManager
30
- } from "./chunk-CP6PALA4.js";
32
+ } from "./chunk-KRTQDZMY.js";
31
33
  import {
32
34
  ToolExecutor,
33
35
  ToolRegistry,
@@ -45,10 +47,10 @@ import {
45
47
  spawnAgentContext,
46
48
  truncateOutput,
47
49
  undoStack
48
- } from "./chunk-XXKWSBRC.js";
50
+ } from "./chunk-YTP26DOV.js";
49
51
  import "./chunk-3BICTI5M.js";
50
52
  import "./chunk-2DXY7UGF.js";
51
- import "./chunk-2WAF7FOX.js";
53
+ import "./chunk-VJE5V4H2.js";
52
54
  import "./chunk-2ZD3YTVM.js";
53
55
  import {
54
56
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -68,7 +70,7 @@ import {
68
70
  SKILLS_DIR_NAME,
69
71
  VERSION,
70
72
  buildUserIdentityPrompt
71
- } from "./chunk-UF62SHR7.js";
73
+ } from "./chunk-H3F2E4MD.js";
72
74
  import {
73
75
  formatGitContextForPrompt,
74
76
  getGitContext,
@@ -1294,6 +1296,31 @@ ${summaryResult.content}`,
1294
1296
  await new Promise((resolve3, reject) => {
1295
1297
  fileStream.end((err) => err ? reject(err) : resolve3());
1296
1298
  });
1299
+ const metaMatch = detectMetaNarration(fullContent);
1300
+ if (metaMatch) {
1301
+ try {
1302
+ unlinkSync(saveToFile);
1303
+ } catch {
1304
+ }
1305
+ isError = true;
1306
+ summary = `[save_last_response REJECTED] Your output was internal reasoning / meta-narration (e.g. "Let me re-read\u2026", "the user is asking me to\u2026") instead of the requested document body (matched: ${metaMatch}). ${saveToFile} was NOT saved.
1307
+
1308
+ This fresh stream has NO tools. Produce ONLY the document body: start with a markdown heading and write the full content. Do NOT narrate that you will produce the document \u2014 produce it.`;
1309
+ if (teeUsage) {
1310
+ roundUsage.inputTokens += teeUsage.inputTokens;
1311
+ roundUsage.outputTokens += teeUsage.outputTokens;
1312
+ roundUsage.cacheCreationTokens += teeUsage.cacheCreationTokens ?? 0;
1313
+ roundUsage.cacheReadTokens += teeUsage.cacheReadTokens ?? 0;
1314
+ }
1315
+ this.send({
1316
+ type: "tool_call_result",
1317
+ callId: call.id,
1318
+ result: summary,
1319
+ isError: true,
1320
+ endTime: Date.now()
1321
+ });
1322
+ return { content: "", summary, isError: true };
1323
+ }
1297
1324
  const pseudoMatch = detectPseudoToolCalls(fullContent);
1298
1325
  if (pseudoMatch) {
1299
1326
  const cleaned = stripPseudoToolCalls(fullContent);
@@ -1331,9 +1358,13 @@ ${summaryResult.content}`,
1331
1358
  } catch {
1332
1359
  }
1333
1360
  }
1361
+ try {
1362
+ unlinkSync(saveToFile);
1363
+ } catch {
1364
+ }
1334
1365
  isError = true;
1335
1366
  const msg = err instanceof Error ? err.message : String(err);
1336
- summary = `[save_last_response failed] ${msg}`;
1367
+ summary = `[save_last_response failed] streaming was interrupted: ${msg}. ${saveToFile} (partial) was deleted. Retry \u2014 and consider producing a more compact output (split very large reports across multiple save_last_response calls if the previous attempt timed out).`;
1337
1368
  }
1338
1369
  this.send({
1339
1370
  type: "tool_call_result",
@@ -2412,7 +2443,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
2412
2443
  case "test": {
2413
2444
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
2414
2445
  try {
2415
- const { executeTests } = await import("./run-tests-7WN5Q7YV.js");
2446
+ const { executeTests } = await import("./run-tests-QOZZHW4L.js");
2416
2447
  const argStr = args.join(" ").trim();
2417
2448
  let testArgs = {};
2418
2449
  if (argStr) {
@@ -3573,7 +3604,7 @@ async function startWebServer(options = {}) {
3573
3604
  }
3574
3605
  const token = authManager.login(username, password);
3575
3606
  console.log(` \u2713 User registered via API: ${username}${firstRun ? " (first-run)" : ""}`);
3576
- res.cookie("aicli_token", token, { httpOnly: true, sameSite: "strict", maxAge: 7 * 24 * 3600 * 1e3 });
3607
+ res.cookie("aicli_token", token, { httpOnly: true, sameSite: "strict", maxAge: TOKEN_EXPIRY_MS });
3577
3608
  res.json({ success: true, username });
3578
3609
  });
3579
3610
  app.post("/api/auth/login", (req, res) => {
@@ -3587,7 +3618,7 @@ async function startWebServer(options = {}) {
3587
3618
  res.status(401).json({ error: "Invalid username or password" });
3588
3619
  return;
3589
3620
  }
3590
- res.cookie("aicli_token", token, { httpOnly: true, sameSite: "strict", maxAge: 7 * 24 * 3600 * 1e3 });
3621
+ res.cookie("aicli_token", token, { httpOnly: true, sameSite: "strict", maxAge: TOKEN_EXPIRY_MS });
3591
3622
  res.json({ success: true, username });
3592
3623
  });
3593
3624
  app.post("/api/auth/logout", (_req, res) => {
@@ -4,14 +4,14 @@ import {
4
4
  getDangerLevel,
5
5
  googleSearchContext,
6
6
  truncateOutput
7
- } from "./chunk-XXKWSBRC.js";
7
+ } from "./chunk-YTP26DOV.js";
8
8
  import "./chunk-3BICTI5M.js";
9
9
  import "./chunk-2DXY7UGF.js";
10
- import "./chunk-2WAF7FOX.js";
10
+ import "./chunk-VJE5V4H2.js";
11
11
  import "./chunk-2ZD3YTVM.js";
12
12
  import {
13
13
  SUBAGENT_ALLOWED_TOOLS
14
- } from "./chunk-UF62SHR7.js";
14
+ } from "./chunk-H3F2E4MD.js";
15
15
  import "./chunk-4BKXL7SM.js";
16
16
  import "./chunk-7ZJN4KLV.js";
17
17
  import "./chunk-KHYD3WXE.js";