jinzd-ai-cli 0.4.204 → 0.4.206

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 (26) hide show
  1. package/README.md +1 -1
  2. package/dist/{batch-ZP52GVVD.js → batch-6PORMJWT.js} +2 -2
  3. package/dist/{chunk-JLZ5QA2I.js → chunk-2WV6AGHM.js} +1 -1
  4. package/dist/{chunk-26YWVRLT.js → chunk-BQIV4ZQT.js} +1 -1
  5. package/dist/{chunk-T5RTPF2Q.js → chunk-KJHMRAJU.js} +1 -1
  6. package/dist/{chunk-PIZWD5JN.js → chunk-KOU4KX7J.js} +2 -2
  7. package/dist/{chunk-UZISJ3KZ.js → chunk-QMXC327F.js} +3 -3
  8. package/dist/{chunk-SCQOEDVL.js → chunk-QNUVZO5X.js} +1 -1
  9. package/dist/{chunk-B75A6AG4.js → chunk-QQYSZMET.js} +108 -64
  10. package/dist/{chunk-GYN2PTY2.js → chunk-SFCNFX42.js} +1 -1
  11. package/dist/{chunk-BENRC3OO.js → chunk-TW47X5AO.js} +1 -1
  12. package/dist/{chunk-SMFRJCXB.js → chunk-XPBEJB27.js} +8 -1
  13. package/dist/{ci-LWE2I5QW.js → ci-AYMV66P3.js} +9 -9
  14. package/dist/{constants-JRY7PDEY.js → constants-NHGTSHKT.js} +1 -1
  15. package/dist/{doctor-cli-KPUULUPS.js → doctor-cli-WKH7T4AW.js} +6 -6
  16. package/dist/electron-server.js +131 -82
  17. package/dist/{hub-4CDJPNIM.js → hub-6R3M3NTC.js} +1 -1
  18. package/dist/index.js +29 -27
  19. package/dist/{run-tests-RQWSG25U.js → run-tests-5F2OBWIK.js} +2 -2
  20. package/dist/{run-tests-6G2F7OSC.js → run-tests-NBCA4KEG.js} +1 -1
  21. package/dist/{server-XNB76DRR.js → server-37EXC4EB.js} +5 -5
  22. package/dist/{server-MF6UDMBZ.js → server-LDPQ3DLK.js} +23 -20
  23. package/dist/{task-orchestrator-PKZ2UTOK.js → task-orchestrator-2DTDVCMR.js} +5 -5
  24. package/dist/{usage-Z64KJASD.js → usage-SZWZFX3T.js} +2 -2
  25. package/dist/web/client/app.js +2 -2
  26. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  saveDevState,
16
16
  sessionHasMeaningfulContent,
17
17
  setupProxy
18
- } from "./chunk-PIZWD5JN.js";
18
+ } from "./chunk-KOU4KX7J.js";
19
19
  import {
20
20
  ToolExecutor,
21
21
  ToolRegistry,
@@ -35,10 +35,10 @@ import {
35
35
  spawnAgentContext,
36
36
  theme,
37
37
  undoStack
38
- } from "./chunk-B75A6AG4.js";
38
+ } from "./chunk-QQYSZMET.js";
39
39
  import "./chunk-T2NL5ZIA.js";
40
40
  import "./chunk-BXP6YZ2P.js";
41
- import "./chunk-GYN2PTY2.js";
41
+ import "./chunk-SFCNFX42.js";
42
42
  import {
43
43
  SessionManager,
44
44
  getContentText
@@ -55,16 +55,16 @@ import {
55
55
  getConfigDirUsage,
56
56
  listRecentCrashes,
57
57
  writeCrashLog
58
- } from "./chunk-T5RTPF2Q.js";
58
+ } from "./chunk-KJHMRAJU.js";
59
59
  import {
60
60
  ProviderRegistry
61
- } from "./chunk-UZISJ3KZ.js";
61
+ } from "./chunk-QMXC327F.js";
62
62
  import {
63
63
  getStatsSnapshot,
64
64
  getTopFailingTools,
65
65
  getTopUsedTools,
66
66
  installFlushOnExit
67
- } from "./chunk-JLZ5QA2I.js";
67
+ } from "./chunk-2WV6AGHM.js";
68
68
  import {
69
69
  CONTENT_ONLY_STREAM_REMINDER,
70
70
  TEE_FINAL_USER_NUDGE,
@@ -83,10 +83,10 @@ import {
83
83
  stripOuterCodeFence,
84
84
  stripToolCallReminder,
85
85
  teeStreamErrorSummary
86
- } from "./chunk-SMFRJCXB.js";
86
+ } from "./chunk-XPBEJB27.js";
87
87
  import {
88
88
  ConfigManager
89
- } from "./chunk-BENRC3OO.js";
89
+ } from "./chunk-TW47X5AO.js";
90
90
  import {
91
91
  AuthError,
92
92
  ProviderError,
@@ -113,7 +113,7 @@ import {
113
113
  SKILLS_DIR_NAME,
114
114
  VERSION,
115
115
  buildUserIdentityPrompt
116
- } from "./chunk-SCQOEDVL.js";
116
+ } from "./chunk-QNUVZO5X.js";
117
117
  import {
118
118
  formatGitContextForPrompt,
119
119
  getGitContext,
@@ -135,14 +135,16 @@ import {
135
135
  } from "./chunk-SLSWPBK3.js";
136
136
  import "./chunk-O6UFCEUZ.js";
137
137
  import "./chunk-CKH4KQ4E.js";
138
- import "./chunk-IW3Q7AE5.js";
138
+ import {
139
+ atomicWriteFileSync
140
+ } from "./chunk-IW3Q7AE5.js";
139
141
 
140
142
  // src/index.ts
141
143
  import { program } from "commander";
142
144
 
143
145
  // src/repl/repl.ts
144
146
  import * as readline from "readline";
145
- import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync4 } from "fs";
147
+ import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync3, mkdirSync as mkdirSync4 } from "fs";
146
148
  import { join as join4, resolve as resolve2, extname as extname2, dirname as dirname3, basename as basename2 } from "path";
147
149
  import chalk4 from "chalk";
148
150
 
@@ -1828,7 +1830,7 @@ No tools match "${filter}".
1828
1830
  const { join: join5 } = await import("path");
1829
1831
  const { existsSync: existsSync5 } = await import("fs");
1830
1832
  const { getGitRoot: getGitRoot2 } = await import("./git-context-EXOEHQSF.js");
1831
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-JRY7PDEY.js");
1833
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-NHGTSHKT.js");
1832
1834
  const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
1833
1835
  const cwd = process.cwd();
1834
1836
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -2889,7 +2891,7 @@ ${hint}` : "")
2889
2891
  usage: "/test [command|filter]",
2890
2892
  async execute(args, ctx) {
2891
2893
  try {
2892
- const { executeTests } = await import("./run-tests-RQWSG25U.js");
2894
+ const { executeTests } = await import("./run-tests-5F2OBWIK.js");
2893
2895
  const argStr = args.join(" ").trim();
2894
2896
  let testArgs = {};
2895
2897
  if (argStr) {
@@ -3567,7 +3569,7 @@ Summary: ${fileMap.size} file(s) \u2014 ${newFiles} new, ${modifiedFiles} modifi
3567
3569
  console.log(theme.info(" \u{1F512} Auto-approve disabled \u2014 confirmations restored for this session."));
3568
3570
  } else {
3569
3571
  executor.sessionAutoApprove = true;
3570
- console.log(theme.warning(" \u26A1 YOLO mode ON \u2014 all write/destructive tools auto-approved for this session."));
3572
+ console.log(theme.warning(" \u26A1 YOLO mode ON \u2014 write tools auto-approved; destructive tools still require confirmation."));
3571
3573
  console.log(theme.dim(" Use /yolo off to re-enable confirmations."));
3572
3574
  }
3573
3575
  console.log();
@@ -4047,11 +4049,11 @@ Managing ${displayName} API Key`);
4047
4049
  console.log(" alwaysYolo: " + (current ? theme.warning("ON") : theme.dim("off")));
4048
4050
  console.log(
4049
4051
  theme.dim(
4050
- " When ON, REPL starts with sessionAutoApprove enabled \u2014 all write/destructive\n tools (edit_file, bash, etc.) run without confirmation prompts. Only enable this\n if you fully trust the working directory you run aicli in.\n"
4052
+ " When ON, REPL starts with sessionAutoApprove enabled \u2014 write\n tools (write_file/edit_file, etc.) run without confirmation prompts. Destructive tools still require confirmation. Only enable this\n if you fully trust the working directory you run aicli in.\n"
4051
4053
  )
4052
4054
  );
4053
4055
  const next = await confirm({
4054
- message: current ? "Keep alwaysYolo enabled?" : "Enable alwaysYolo (skip ALL write/destructive confirmations)?",
4056
+ message: current ? "Keep alwaysYolo enabled?" : "Enable alwaysYolo (skip write confirmations; destructive still confirms)?",
4055
4057
  default: current
4056
4058
  });
4057
4059
  if (next === current) {
@@ -5391,7 +5393,7 @@ Session '${this.resumeSessionId}' not found.
5391
5393
  this.renderer.printWelcome(this.currentProvider, this.currentModel, welcomeModelInfo?.contextWindow, profileNickname);
5392
5394
  if (this.toolExecutor.sessionAutoApprove && this.config.get("alwaysYolo") === true) {
5393
5395
  process.stdout.write(
5394
- theme.warning(" \u26A1 YOLO mode ON (alwaysYolo=true in config) \u2014 all write/destructive tools auto-approved.\n")
5396
+ theme.warning(" \u26A1 YOLO mode ON (alwaysYolo=true in config) \u2014 write tools auto-approved; destructive tools still require confirmation.\n")
5395
5397
  );
5396
5398
  }
5397
5399
  const cfgOutputCap = this.config.get("maxToolOutputChars");
@@ -6642,7 +6644,7 @@ ${decision.displayMessage}
6642
6644
  try {
6643
6645
  mkdirSync4(dirname3(pendingTeeSave), { recursive: true });
6644
6646
  const bodyToSave = stripOuterCodeFence(content);
6645
- writeFileSync2(pendingTeeSave, bodyToSave, "utf-8");
6647
+ atomicWriteFileSync(pendingTeeSave, bodyToSave);
6646
6648
  undoStack.push(pendingTeeSave, `save_last_response (deferred): ${pendingTeeSave}`);
6647
6649
  const lines = bodyToSave.split("\n").length;
6648
6650
  process.stdout.write(theme.success(
@@ -6911,7 +6913,7 @@ Tip: You can continue the conversation by asking the AI to proceed.`
6911
6913
  }
6912
6914
  if (verdict.kind === "salvaged" || verdict.kind === "fallback") {
6913
6915
  try {
6914
- writeFileSync2(saveToFile, verdict.content, "utf-8");
6916
+ atomicWriteFileSync(saveToFile, verdict.content);
6915
6917
  const banner = verdict.kind === "fallback" ? `
6916
6918
  \u26A0 Fallback save: fresh stream had no usable body (matched: ${verdict.matched})
6917
6919
  ${saveToFile} now holds the response you previously saw (${verdict.content.length} chars).
@@ -7267,7 +7269,7 @@ program.command("web").description("Start Web UI server with browser-based chat
7267
7269
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
7268
7270
  process.exit(1);
7269
7271
  }
7270
- const { startWebServer } = await import("./server-MF6UDMBZ.js");
7272
+ const { startWebServer } = await import("./server-LDPQ3DLK.js");
7271
7273
  await startWebServer({ port, host: options.host });
7272
7274
  });
7273
7275
  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) => {
@@ -7434,16 +7436,16 @@ program.command("sessions").description("List recent conversation sessions").opt
7434
7436
  console.log(footer + "\n");
7435
7437
  });
7436
7438
  program.command("usage").description("Show token + cost usage grouped by provider/model (cross-session)").option("--days <n>", "Only the last N days (inclusive of today)").option("--month <ym>", "Only a specific month, format YYYY-MM (e.g. 2026-06)").option("--json", "Output as JSON (for scripting)").action(async (options) => {
7437
- const { runUsageCli } = await import("./usage-Z64KJASD.js");
7439
+ const { runUsageCli } = await import("./usage-SZWZFX3T.js");
7438
7440
  await runUsageCli(options);
7439
7441
  });
7440
7442
  program.command("doctor").description("Health check: API keys, config, MCP, recent crashes, tool usage, disk usage").option("--json", "Output as JSON (for scripting)").option("--reset-stats", "Reset accumulated tool usage statistics").action(async (options) => {
7441
- const { runDoctorCli } = await import("./doctor-cli-KPUULUPS.js");
7443
+ const { runDoctorCli } = await import("./doctor-cli-WKH7T4AW.js");
7442
7444
  await runDoctorCli({ json: !!options.json, resetStats: !!options.resetStats });
7443
7445
  });
7444
7446
  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) => {
7445
7447
  try {
7446
- const batch = await import("./batch-ZP52GVVD.js");
7448
+ const batch = await import("./batch-6PORMJWT.js");
7447
7449
  switch (action) {
7448
7450
  case "submit":
7449
7451
  if (!arg) {
@@ -7486,7 +7488,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
7486
7488
  }
7487
7489
  });
7488
7490
  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) => {
7489
- const { startMcpServer } = await import("./server-XNB76DRR.js");
7491
+ const { startMcpServer } = await import("./server-37EXC4EB.js");
7490
7492
  await startMcpServer({
7491
7493
  allowDestructive: !!options.allowDestructive,
7492
7494
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -7495,7 +7497,7 @@ program.command("mcp-serve").description("Start an MCP server over STDIO, exposi
7495
7497
  });
7496
7498
  });
7497
7499
  program.command("ci").description("Headless PR review (code + security) \u2014 reads git/gh diff, optionally posts to PR. Designed for GitHub Actions.").option("--pr <num>", "PR number; diff fetched via `gh pr diff <num>`", (v) => parseInt(v, 10)).option("--base <ref>", "Base ref for `git diff <ref>...HEAD` (ignored when --pr set)").option("--post", "Post review as a PR comment (requires gh CLI + GH_TOKEN, needs --pr)").option("--no-update", "Always create a new comment instead of updating the previous aicli review").option("--skip-code", "Skip the code review section").option("--skip-security", "Skip the security review section").option("--detailed", "Use the detailed code-review prompt").option("--max-diff <n>", "Max diff chars sent to the model (default 30000)", (v) => parseInt(v, 10)).option("--provider <id>", "Override provider (default: config.defaultProvider)").option("--model <id>", "Override model").option("--dry-run", "Print result to stdout instead of posting (overrides --post)").action(async (options) => {
7498
- const { runCi } = await import("./ci-LWE2I5QW.js");
7500
+ const { runCi } = await import("./ci-AYMV66P3.js");
7499
7501
  const result = await runCi({
7500
7502
  pr: options.pr,
7501
7503
  base: options.base,
@@ -7593,7 +7595,7 @@ program.command("help").description("Show a comprehensive guide to all aicli fea
7593
7595
  ` ${M}/checkpoint${R} ${M}/fork${R} Save/restore/fork session state`,
7594
7596
  ` ${M}/branch${R} List/create/switch/delete conversation branches (B2)`,
7595
7597
  ` ${M}/undo${R} Undo file operations`,
7596
- ` ${M}/yolo${R} Skip all tool confirmations`,
7598
+ ` ${M}/yolo${R} Skip write confirmations`,
7597
7599
  ` ${M}/mcp${R} Manage MCP server connections`,
7598
7600
  ` ${M}/skill${R} Manage agent skills`,
7599
7601
  ` ${M}/memory${R} View/edit persistent memory`,
@@ -7641,7 +7643,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
7641
7643
  }),
7642
7644
  config.get("customProviders")
7643
7645
  );
7644
- const { startHub } = await import("./hub-4CDJPNIM.js");
7646
+ const { startHub } = await import("./hub-6R3M3NTC.js");
7645
7647
  await startHub(
7646
7648
  {
7647
7649
  topic: topic ?? "",
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-GYN2PTY2.js";
6
- import "./chunk-SCQOEDVL.js";
5
+ } from "./chunk-SFCNFX42.js";
6
+ import "./chunk-QNUVZO5X.js";
7
7
  export {
8
8
  executeTests,
9
9
  runTestsTool
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-26YWVRLT.js";
4
+ } from "./chunk-BQIV4ZQT.js";
5
5
  export {
6
6
  executeTests,
7
7
  runTestsTool
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ToolRegistry
4
- } from "./chunk-B75A6AG4.js";
4
+ } from "./chunk-QQYSZMET.js";
5
5
  import "./chunk-T2NL5ZIA.js";
6
6
  import "./chunk-BXP6YZ2P.js";
7
- import "./chunk-GYN2PTY2.js";
7
+ import "./chunk-SFCNFX42.js";
8
8
  import {
9
9
  runTool
10
- } from "./chunk-JLZ5QA2I.js";
10
+ } from "./chunk-2WV6AGHM.js";
11
11
  import {
12
12
  getDangerLevel,
13
13
  schemaToJsonSchema
14
- } from "./chunk-SMFRJCXB.js";
14
+ } from "./chunk-XPBEJB27.js";
15
15
  import "./chunk-TZQHYZKT.js";
16
16
  import {
17
17
  VERSION
18
- } from "./chunk-SCQOEDVL.js";
18
+ } from "./chunk-QNUVZO5X.js";
19
19
  import "./chunk-4BKXL7SM.js";
20
20
  import "./chunk-TB4W4Y4T.js";
21
21
  import "./chunk-KHYD3WXE.js";
@@ -19,7 +19,7 @@ import {
19
19
  loadDevState,
20
20
  persistToolRound,
21
21
  setupProxy
22
- } from "./chunk-PIZWD5JN.js";
22
+ } from "./chunk-KOU4KX7J.js";
23
23
  import {
24
24
  ToolExecutor,
25
25
  ToolRegistry,
@@ -38,10 +38,10 @@ import {
38
38
  spawnAgentContext,
39
39
  truncateOutput,
40
40
  undoStack
41
- } from "./chunk-B75A6AG4.js";
41
+ } from "./chunk-QQYSZMET.js";
42
42
  import "./chunk-T2NL5ZIA.js";
43
43
  import "./chunk-BXP6YZ2P.js";
44
- import "./chunk-GYN2PTY2.js";
44
+ import "./chunk-SFCNFX42.js";
45
45
  import {
46
46
  SessionManager,
47
47
  getContentText
@@ -52,10 +52,10 @@ import {
52
52
  } from "./chunk-E44DTERW.js";
53
53
  import {
54
54
  ProviderRegistry
55
- } from "./chunk-UZISJ3KZ.js";
55
+ } from "./chunk-QMXC327F.js";
56
56
  import {
57
57
  runTool
58
- } from "./chunk-JLZ5QA2I.js";
58
+ } from "./chunk-2WV6AGHM.js";
59
59
  import {
60
60
  CONTENT_ONLY_STREAM_REMINDER,
61
61
  TEE_FINAL_USER_NUDGE,
@@ -71,10 +71,10 @@ import {
71
71
  stripOuterCodeFence,
72
72
  stripToolCallReminder,
73
73
  teeStreamErrorSummary
74
- } from "./chunk-SMFRJCXB.js";
74
+ } from "./chunk-XPBEJB27.js";
75
75
  import {
76
76
  ConfigManager
77
- } from "./chunk-BENRC3OO.js";
77
+ } from "./chunk-TW47X5AO.js";
78
78
  import "./chunk-TZQHYZKT.js";
79
79
  import {
80
80
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -94,7 +94,7 @@ import {
94
94
  SKILLS_DIR_NAME,
95
95
  VERSION,
96
96
  buildUserIdentityPrompt
97
- } from "./chunk-SCQOEDVL.js";
97
+ } from "./chunk-QNUVZO5X.js";
98
98
  import {
99
99
  formatGitContextForPrompt,
100
100
  getGitContext,
@@ -106,7 +106,9 @@ import "./chunk-KHYD3WXE.js";
106
106
  import "./chunk-SLSWPBK3.js";
107
107
  import "./chunk-O6UFCEUZ.js";
108
108
  import "./chunk-CKH4KQ4E.js";
109
- import "./chunk-IW3Q7AE5.js";
109
+ import {
110
+ atomicWriteFileSync
111
+ } from "./chunk-IW3Q7AE5.js";
110
112
 
111
113
  // src/web/server.ts
112
114
  import express from "express";
@@ -346,7 +348,7 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
346
348
  }
347
349
  }
348
350
  this.sendToolCallStart(call);
349
- if (this.sessionAutoApprove && (dangerLevel === "write" || dangerLevel === "destructive")) {
351
+ if (this.sessionAutoApprove && dangerLevel === "write") {
350
352
  try {
351
353
  const rawContent = await runTool(tool, call.arguments, call.name);
352
354
  const content = truncateOutput(rawContent, call.name);
@@ -1176,7 +1178,7 @@ Try: /compact to reduce context, /clear to reset, or switch to a larger-context
1176
1178
  try {
1177
1179
  mkdirSync(dirname(pendingTeeSave), { recursive: true });
1178
1180
  const bodyToSave = stripOuterCodeFence(content);
1179
- writeFileSync(pendingTeeSave, bodyToSave, "utf-8");
1181
+ atomicWriteFileSync(pendingTeeSave, bodyToSave);
1180
1182
  undoStack.push(pendingTeeSave, `save_last_response (deferred): ${pendingTeeSave}`);
1181
1183
  const lines = bodyToSave.split("\n").length;
1182
1184
  this.send({ type: "info", message: `\u2705 Saved (from reply): ${pendingTeeSave} (${lines} lines, ${bodyToSave.length} chars)` });
@@ -1351,7 +1353,7 @@ ${summaryContent}`,
1351
1353
  let summary;
1352
1354
  try {
1353
1355
  mkdirSync(dirname(saveToFile), { recursive: true });
1354
- fileStream = createWriteStream(saveToFile, { encoding: "utf-8" });
1356
+ fileStream = createWriteStream(saveToFile);
1355
1357
  const teeSystemPrompt = stripToolCallReminder(systemPrompt ?? "") + CONTENT_ONLY_STREAM_REMINDER;
1356
1358
  const teeExtraMessages = extraMessages.length > 0 ? [...extraMessages, { role: "user", content: TEE_FINAL_USER_NUDGE }] : [{ role: "user", content: TEE_FINAL_USER_NUDGE }];
1357
1359
  const chatRequest = {
@@ -1391,7 +1393,7 @@ ${summaryContent}`,
1391
1393
  fullContent = "";
1392
1394
  } else {
1393
1395
  if (verdict.kind === "salvaged" || verdict.kind === "fallback") {
1394
- writeFileSync(saveToFile, verdict.content, "utf-8");
1396
+ atomicWriteFileSync(saveToFile, verdict.content);
1395
1397
  fullContent = verdict.content;
1396
1398
  }
1397
1399
  summary = verdict.summary;
@@ -1843,7 +1845,7 @@ ${activated.meta.description || ""}` });
1843
1845
  this.send({ type: "info", message: "\u{1F512} Auto-approve disabled \u2014 confirmations restored for this session." });
1844
1846
  } else {
1845
1847
  this.toolExecutor.sessionAutoApprove = true;
1846
- this.send({ type: "info", message: "\u26A1 YOLO mode ON \u2014 all write/destructive tools auto-approved for this session.\nUse /yolo off to re-enable confirmations." });
1848
+ this.send({ type: "info", message: "\u26A1 YOLO mode ON \u2014 write tools auto-approved; destructive tools still require confirmation.\nUse /yolo off to re-enable write confirmations." });
1847
1849
  }
1848
1850
  break;
1849
1851
  }
@@ -2456,7 +2458,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
2456
2458
  case "test": {
2457
2459
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
2458
2460
  try {
2459
- const { executeTests } = await import("./run-tests-RQWSG25U.js");
2461
+ const { executeTests } = await import("./run-tests-5F2OBWIK.js");
2460
2462
  const argStr = args.join(" ").trim();
2461
2463
  let testArgs = {};
2462
2464
  if (argStr) {
@@ -3891,7 +3893,7 @@ async function startWebServer(options = {}) {
3891
3893
  handlers.set(tabId, handler);
3892
3894
  clearPreAuthTimer();
3893
3895
  console.log(` \u2713 User registered & connected: ${username} (tab: ${tabId.slice(0, 12)})`);
3894
- ws.send(JSON.stringify({ type: "auth_result", success: true, token: newToken, username }));
3896
+ ws.send(JSON.stringify({ type: "auth_result", success: true, username }));
3895
3897
  return;
3896
3898
  }
3897
3899
  if (action === "token") {
@@ -3907,7 +3909,7 @@ async function startWebServer(options = {}) {
3907
3909
  handlers.set(tabId, handler);
3908
3910
  clearPreAuthTimer();
3909
3911
  console.log(` \u2713 Token auth: ${verifiedUser} (tab: ${tabId.slice(0, 12)})`);
3910
- ws.send(JSON.stringify({ type: "auth_result", success: true, token: clientToken, username: verifiedUser }));
3912
+ ws.send(JSON.stringify({ type: "auth_result", success: true, username: verifiedUser }));
3911
3913
  return;
3912
3914
  }
3913
3915
  if (action === "login") {
@@ -3922,7 +3924,7 @@ async function startWebServer(options = {}) {
3922
3924
  handlers.set(tabId, handler);
3923
3925
  clearPreAuthTimer();
3924
3926
  console.log(` \u2713 User logged in: ${username} (tab: ${tabId.slice(0, 12)})`);
3925
- ws.send(JSON.stringify({ type: "auth_result", success: true, token: loginToken, username }));
3927
+ ws.send(JSON.stringify({ type: "auth_result", success: true, username }));
3926
3928
  return;
3927
3929
  }
3928
3930
  ws.send(JSON.stringify({ type: "auth_result", success: false, error: "Unknown auth action" }));
@@ -3948,9 +3950,10 @@ async function startWebServer(options = {}) {
3948
3950
  });
3949
3951
  ws.on("close", () => {
3950
3952
  clearPreAuthTimer();
3951
- console.log(` \u2717 Tab disconnected: ${tabId.slice(0, 12)} (total: ${handlers.size - 1})`);
3953
+ const wasTracked = handlers.has(tabId);
3952
3954
  if (handler) handler.onDisconnect();
3953
- handlers.delete(tabId);
3955
+ if (wasTracked) handlers.delete(tabId);
3956
+ console.log(` \u2717 Tab disconnected: ${tabId.slice(0, 12)} (total: ${handlers.size})`);
3954
3957
  });
3955
3958
  ws.on("error", (err) => {
3956
3959
  console.error(` WebSocket error: ${err.message}`);
@@ -3,21 +3,21 @@ import {
3
3
  ToolRegistry,
4
4
  googleSearchContext,
5
5
  truncateOutput
6
- } from "./chunk-B75A6AG4.js";
6
+ } from "./chunk-QQYSZMET.js";
7
7
  import "./chunk-T2NL5ZIA.js";
8
8
  import "./chunk-BXP6YZ2P.js";
9
- import "./chunk-GYN2PTY2.js";
9
+ import "./chunk-SFCNFX42.js";
10
10
  import {
11
11
  runTool
12
- } from "./chunk-JLZ5QA2I.js";
12
+ } from "./chunk-2WV6AGHM.js";
13
13
  import {
14
14
  getDangerLevel,
15
15
  runLeanAgentLoop
16
- } from "./chunk-SMFRJCXB.js";
16
+ } from "./chunk-XPBEJB27.js";
17
17
  import "./chunk-TZQHYZKT.js";
18
18
  import {
19
19
  SUBAGENT_ALLOWED_TOOLS
20
- } from "./chunk-SCQOEDVL.js";
20
+ } from "./chunk-QNUVZO5X.js";
21
21
  import "./chunk-4BKXL7SM.js";
22
22
  import "./chunk-TB4W4Y4T.js";
23
23
  import "./chunk-KHYD3WXE.js";
@@ -8,9 +8,9 @@ import {
8
8
  } from "./chunk-E44DTERW.js";
9
9
  import {
10
10
  ConfigManager
11
- } from "./chunk-BENRC3OO.js";
11
+ } from "./chunk-TW47X5AO.js";
12
12
  import "./chunk-TZQHYZKT.js";
13
- import "./chunk-SCQOEDVL.js";
13
+ import "./chunk-QNUVZO5X.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
15
 
16
16
  // src/cli/usage.ts
@@ -2805,8 +2805,8 @@ async function handleAuth(event) {
2805
2805
  }
2806
2806
  }
2807
2807
 
2808
- // Legacy WS auth_result handler — kept for backwards-compat with clients/
2809
- // flows that still hit the WS auth path. Token field, if present, is ignored.
2808
+ // Legacy WS auth_result handler — kept for flows that still hit the WS auth path.
2809
+ // The server no longer echoes tokens; auth state is carried by httpOnly cookie.
2810
2810
  function handleAuthResult(msg) {
2811
2811
  const errorEl = document.getElementById('auth-error');
2812
2812
  const submitBtn = document.getElementById('auth-submit');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.204",
3
+ "version": "0.4.206",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",