jinzd-ai-cli 0.4.191 → 0.4.193

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
@@ -15,11 +15,12 @@ import {
15
15
  saveDevState,
16
16
  sessionHasMeaningfulContent,
17
17
  setupProxy
18
- } from "./chunk-IMSENBJ6.js";
18
+ } from "./chunk-MI23I43Y.js";
19
19
  import {
20
20
  ToolExecutor,
21
21
  ToolRegistry,
22
22
  askUserContext,
23
+ cleanupRejectedTeeFile,
23
24
  estimateTokens,
24
25
  googleSearchContext,
25
26
  initTheme,
@@ -34,10 +35,10 @@ import {
34
35
  spawnAgentContext,
35
36
  theme,
36
37
  undoStack
37
- } from "./chunk-RQ7JVLFM.js";
38
+ } from "./chunk-SI5EO3NJ.js";
38
39
  import "./chunk-T2NL5ZIA.js";
39
40
  import "./chunk-BXP6YZ2P.js";
40
- import "./chunk-HSQAKOYX.js";
41
+ import "./chunk-7PX3ZX4G.js";
41
42
  import {
42
43
  SessionManager,
43
44
  getContentText
@@ -54,10 +55,18 @@ import {
54
55
  getConfigDirUsage,
55
56
  listRecentCrashes,
56
57
  writeCrashLog
57
- } from "./chunk-TRV47UK4.js";
58
+ } from "./chunk-PO3ZY3PN.js";
59
+ import {
60
+ ProviderRegistry
61
+ } from "./chunk-BGXQGCEO.js";
62
+ import {
63
+ getStatsSnapshot,
64
+ getTopFailingTools,
65
+ getTopUsedTools,
66
+ installFlushOnExit
67
+ } from "./chunk-SHI5UFUH.js";
58
68
  import {
59
69
  CONTENT_ONLY_STREAM_REMINDER,
60
- ProviderRegistry,
61
70
  TEE_FINAL_USER_NUDGE,
62
71
  TOOL_CALL_REMINDER,
63
72
  ThinkTagFilter,
@@ -70,17 +79,10 @@ import {
70
79
  runAgentLoop,
71
80
  stripToolCallReminder,
72
81
  teeStreamErrorSummary
73
- } from "./chunk-JTLPYPT3.js";
74
- import {
75
- getStatsSnapshot,
76
- getTopFailingTools,
77
- getTopUsedTools,
78
- installFlushOnExit
79
- } from "./chunk-Y3PNCW7A.js";
80
- import "./chunk-HIU2SH4V.js";
82
+ } from "./chunk-JOR572WG.js";
81
83
  import {
82
84
  ConfigManager
83
- } from "./chunk-XDH5EFWC.js";
85
+ } from "./chunk-VQT27CZK.js";
84
86
  import {
85
87
  AuthError,
86
88
  ProviderError,
@@ -107,7 +109,7 @@ import {
107
109
  SKILLS_DIR_NAME,
108
110
  VERSION,
109
111
  buildUserIdentityPrompt
110
- } from "./chunk-ASVBZIUE.js";
112
+ } from "./chunk-P3PTUSP4.js";
111
113
  import {
112
114
  formatGitContextForPrompt,
113
115
  getGitContext,
@@ -136,7 +138,7 @@ import { program } from "commander";
136
138
 
137
139
  // src/repl/repl.ts
138
140
  import * as readline from "readline";
139
- import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
141
+ import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync2 } from "fs";
140
142
  import { join as join4, resolve as resolve2, extname as extname2, dirname as dirname3, basename as basename2 } from "path";
141
143
  import chalk4 from "chalk";
142
144
 
@@ -1822,7 +1824,7 @@ No tools match "${filter}".
1822
1824
  const { join: join5 } = await import("path");
1823
1825
  const { existsSync: existsSync5 } = await import("fs");
1824
1826
  const { getGitRoot: getGitRoot2 } = await import("./git-context-EXOEHQSF.js");
1825
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-3T5G34S5.js");
1827
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-LEU54VQQ.js");
1826
1828
  const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
1827
1829
  const cwd = process.cwd();
1828
1830
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -2883,7 +2885,7 @@ ${hint}` : "")
2883
2885
  usage: "/test [command|filter]",
2884
2886
  async execute(args, ctx) {
2885
2887
  try {
2886
- const { executeTests } = await import("./run-tests-X2MCBIKN.js");
2888
+ const { executeTests } = await import("./run-tests-IL4342SV.js");
2887
2889
  const argStr = args.join(" ").trim();
2888
2890
  let testArgs = {};
2889
2891
  if (argStr) {
@@ -6811,10 +6813,7 @@ Tip: You can continue the conversation by asking the AI to proceed.`
6811
6813
  genUsage = teeResult.usage;
6812
6814
  teeTokShown = teeResult.tokensShown;
6813
6815
  } catch (teeErr) {
6814
- try {
6815
- unlinkSync2(saveToFile);
6816
- } catch {
6817
- }
6816
+ cleanupRejectedTeeFile(saveToFile);
6818
6817
  const errMsg = teeErr instanceof Error ? teeErr.message : String(teeErr);
6819
6818
  process.stdout.write(theme.error(
6820
6819
  `
@@ -6833,12 +6832,9 @@ Tip: You can continue the conversation by asking the AI to proceed.`
6833
6832
  return "continue";
6834
6833
  }
6835
6834
  if (genUsage) accumulateUsage(usage, genUsage);
6836
- const verdict = evaluateTeeContent(genContent, saveToFile);
6835
+ const verdict = evaluateTeeContent(genContent, saveToFile, lastResponseStore.content);
6837
6836
  if (verdict.kind === "reject") {
6838
- try {
6839
- unlinkSync2(saveToFile);
6840
- } catch {
6841
- }
6837
+ cleanupRejectedTeeFile(saveToFile);
6842
6838
  const label = verdict.reason === "meta-narration" ? "meta-narration / leaked reasoning, not document body" : "pseudo-tool-call markup with no usable document body";
6843
6839
  process.stdout.write(theme.error(
6844
6840
  `
@@ -6855,21 +6851,21 @@ Tip: You can continue the conversation by asking the AI to proceed.`
6855
6851
  extraMessages.push(...provider.buildToolResultMessages(toolCalls, errorResults, reasoningContent));
6856
6852
  return "continue";
6857
6853
  }
6858
- if (verdict.kind === "salvaged") {
6854
+ if (verdict.kind === "salvaged" || verdict.kind === "fallback") {
6859
6855
  try {
6860
6856
  writeFileSync2(saveToFile, verdict.content, "utf-8");
6861
- process.stdout.write(theme.warning(
6862
- `
6857
+ const banner = verdict.kind === "fallback" ? `
6858
+ \u26A0 Fallback save: fresh stream had no usable body (matched: ${verdict.matched})
6859
+ ${saveToFile} now holds the response you previously saw (${verdict.content.length} chars).
6860
+
6861
+ ` : `
6863
6862
  \u26A0 Salvaged save: stripped pseudo-tool-call markup (matched: ${verdict.matched})
6864
6863
  ${saveToFile} now contains the cleaned document (${verdict.content.length} chars; was ${genContent.length}).
6865
6864
 
6866
- `
6867
- ));
6865
+ `;
6866
+ process.stdout.write(theme.warning(banner));
6868
6867
  } catch (writeErr) {
6869
- try {
6870
- unlinkSync2(saveToFile);
6871
- } catch {
6872
- }
6868
+ cleanupRejectedTeeFile(saveToFile);
6873
6869
  process.stderr.write(`[tee] salvage write failed: ${writeErr.message ?? writeErr}
6874
6870
  `);
6875
6871
  const errorResults = toolCalls.map((tc) => ({
@@ -7213,7 +7209,7 @@ program.command("web").description("Start Web UI server with browser-based chat
7213
7209
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
7214
7210
  process.exit(1);
7215
7211
  }
7216
- const { startWebServer } = await import("./server-TJDKEECG.js");
7212
+ const { startWebServer } = await import("./server-KE7X3BHW.js");
7217
7213
  await startWebServer({ port, host: options.host });
7218
7214
  });
7219
7215
  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) => {
@@ -7380,16 +7376,16 @@ program.command("sessions").description("List recent conversation sessions").opt
7380
7376
  console.log(footer + "\n");
7381
7377
  });
7382
7378
  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) => {
7383
- const { runUsageCli } = await import("./usage-FYKIOPJI.js");
7379
+ const { runUsageCli } = await import("./usage-CG7PJ3AB.js");
7384
7380
  await runUsageCli(options);
7385
7381
  });
7386
7382
  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) => {
7387
- const { runDoctorCli } = await import("./doctor-cli-3QE7FZKB.js");
7383
+ const { runDoctorCli } = await import("./doctor-cli-4RKSIH7N.js");
7388
7384
  await runDoctorCli({ json: !!options.json, resetStats: !!options.resetStats });
7389
7385
  });
7390
7386
  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) => {
7391
7387
  try {
7392
- const batch = await import("./batch-4XSN4VF7.js");
7388
+ const batch = await import("./batch-M6367YB4.js");
7393
7389
  switch (action) {
7394
7390
  case "submit":
7395
7391
  if (!arg) {
@@ -7432,7 +7428,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
7432
7428
  }
7433
7429
  });
7434
7430
  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) => {
7435
- const { startMcpServer } = await import("./server-FE7XTYVC.js");
7431
+ const { startMcpServer } = await import("./server-Y7TCCIGA.js");
7436
7432
  await startMcpServer({
7437
7433
  allowDestructive: !!options.allowDestructive,
7438
7434
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -7441,7 +7437,7 @@ program.command("mcp-serve").description("Start an MCP server over STDIO, exposi
7441
7437
  });
7442
7438
  });
7443
7439
  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) => {
7444
- const { runCi } = await import("./ci-USJCTRP7.js");
7440
+ const { runCi } = await import("./ci-4MJ4EGKQ.js");
7445
7441
  const result = await runCi({
7446
7442
  pr: options.pr,
7447
7443
  base: options.base,
@@ -7587,7 +7583,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
7587
7583
  }),
7588
7584
  config.get("customProviders")
7589
7585
  );
7590
- const { startHub } = await import("./hub-LABDYMAE.js");
7586
+ const { startHub } = await import("./hub-XMUI5HMK.js");
7591
7587
  await startHub(
7592
7588
  {
7593
7589
  topic: topic ?? "",
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-6Z42O3DN.js";
4
+ } from "./chunk-IFETB4PY.js";
5
5
  export {
6
6
  executeTests,
7
7
  runTestsTool
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-HSQAKOYX.js";
6
- import "./chunk-ASVBZIUE.js";
5
+ } from "./chunk-7PX3ZX4G.js";
6
+ import "./chunk-P3PTUSP4.js";
7
7
  export {
8
8
  executeTests,
9
9
  runTestsTool
@@ -19,12 +19,13 @@ import {
19
19
  loadDevState,
20
20
  persistToolRound,
21
21
  setupProxy
22
- } from "./chunk-IMSENBJ6.js";
22
+ } from "./chunk-MI23I43Y.js";
23
23
  import {
24
24
  ToolExecutor,
25
25
  ToolRegistry,
26
26
  askUserContext,
27
27
  checkPermission,
28
+ cleanupRejectedTeeFile,
28
29
  estimateTokens,
29
30
  googleSearchContext,
30
31
  groupCallsByPhase,
@@ -37,10 +38,10 @@ import {
37
38
  spawnAgentContext,
38
39
  truncateOutput,
39
40
  undoStack
40
- } from "./chunk-RQ7JVLFM.js";
41
+ } from "./chunk-SI5EO3NJ.js";
41
42
  import "./chunk-T2NL5ZIA.js";
42
43
  import "./chunk-BXP6YZ2P.js";
43
- import "./chunk-HSQAKOYX.js";
44
+ import "./chunk-7PX3ZX4G.js";
44
45
  import {
45
46
  SessionManager,
46
47
  getContentText
@@ -49,27 +50,27 @@ import {
49
50
  computeCost,
50
51
  formatCost
51
52
  } from "./chunk-V37XOYOE.js";
53
+ import {
54
+ ProviderRegistry
55
+ } from "./chunk-BGXQGCEO.js";
56
+ import {
57
+ runTool
58
+ } from "./chunk-SHI5UFUH.js";
52
59
  import {
53
60
  CONTENT_ONLY_STREAM_REMINDER,
54
- ProviderRegistry,
55
61
  TEE_FINAL_USER_NUDGE,
56
62
  TOOL_CALL_REMINDER,
57
63
  buildRoundBudgetHint,
58
64
  consumeToolCallStream,
59
65
  evaluateTeeContent,
66
+ getDangerLevel,
60
67
  runAgentLoop,
61
68
  stripToolCallReminder,
62
69
  teeStreamErrorSummary
63
- } from "./chunk-JTLPYPT3.js";
64
- import {
65
- runTool
66
- } from "./chunk-Y3PNCW7A.js";
67
- import {
68
- getDangerLevel
69
- } from "./chunk-HIU2SH4V.js";
70
+ } from "./chunk-JOR572WG.js";
70
71
  import {
71
72
  ConfigManager
72
- } from "./chunk-XDH5EFWC.js";
73
+ } from "./chunk-VQT27CZK.js";
73
74
  import "./chunk-TZQHYZKT.js";
74
75
  import {
75
76
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -89,7 +90,7 @@ import {
89
90
  SKILLS_DIR_NAME,
90
91
  VERSION,
91
92
  buildUserIdentityPrompt
92
- } from "./chunk-ASVBZIUE.js";
93
+ } from "./chunk-P3PTUSP4.js";
93
94
  import {
94
95
  formatGitContextForPrompt,
95
96
  getGitContext,
@@ -512,9 +513,23 @@ function loadMemoryContent(configDir) {
512
513
  }
513
514
 
514
515
  // src/web/session-handler.ts
515
- import { existsSync as existsSync3, readFileSync as readFileSync3, appendFileSync, writeFileSync, mkdirSync, readdirSync, statSync, createWriteStream, unlinkSync } from "fs";
516
+ import { existsSync as existsSync3, readFileSync as readFileSync3, appendFileSync, writeFileSync, mkdirSync, readdirSync, statSync, createWriteStream } from "fs";
516
517
  import { join as join2, resolve, dirname } from "path";
517
518
  import { execSync } from "child_process";
519
+ function lastAssistantText(messages) {
520
+ for (let i = messages.length - 1; i >= 0; i--) {
521
+ const m = messages[i];
522
+ if (!m || m.role !== "assistant") continue;
523
+ const c = m.content;
524
+ if (typeof c === "string") return c;
525
+ if (Array.isArray(c)) {
526
+ const text = c.filter((p) => p && p.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
527
+ if (text) return text;
528
+ }
529
+ return void 0;
530
+ }
531
+ return void 0;
532
+ }
518
533
  var SessionHandler = class _SessionHandler {
519
534
  ws;
520
535
  config;
@@ -1324,17 +1339,14 @@ ${summaryContent}`,
1324
1339
  await new Promise((resolve3, reject) => {
1325
1340
  fileStream.end((err) => err ? reject(err) : resolve3());
1326
1341
  });
1327
- const verdict = evaluateTeeContent(fullContent, saveToFile);
1342
+ const verdict = evaluateTeeContent(fullContent, saveToFile, lastAssistantText(apiMessages));
1328
1343
  if (verdict.kind === "reject") {
1329
- try {
1330
- unlinkSync(saveToFile);
1331
- } catch {
1332
- }
1344
+ cleanupRejectedTeeFile(saveToFile);
1333
1345
  isError = true;
1334
1346
  summary = verdict.summary;
1335
1347
  fullContent = "";
1336
1348
  } else {
1337
- if (verdict.kind === "salvaged") {
1349
+ if (verdict.kind === "salvaged" || verdict.kind === "fallback") {
1338
1350
  writeFileSync(saveToFile, verdict.content, "utf-8");
1339
1351
  fullContent = verdict.content;
1340
1352
  }
@@ -1354,10 +1366,7 @@ ${summaryContent}`,
1354
1366
  } catch {
1355
1367
  }
1356
1368
  }
1357
- try {
1358
- unlinkSync(saveToFile);
1359
- } catch {
1360
- }
1369
+ cleanupRejectedTeeFile(saveToFile);
1361
1370
  isError = true;
1362
1371
  const msg = err instanceof Error ? err.message : String(err);
1363
1372
  summary = teeStreamErrorSummary(saveToFile, msg);
@@ -2403,7 +2412,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
2403
2412
  case "test": {
2404
2413
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
2405
2414
  try {
2406
- const { executeTests } = await import("./run-tests-X2MCBIKN.js");
2415
+ const { executeTests } = await import("./run-tests-IL4342SV.js");
2407
2416
  const argStr = args.join(" ").trim();
2408
2417
  let testArgs = {};
2409
2418
  if (argStr) {
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ToolRegistry
4
- } from "./chunk-RQ7JVLFM.js";
4
+ } from "./chunk-SI5EO3NJ.js";
5
5
  import "./chunk-T2NL5ZIA.js";
6
6
  import "./chunk-BXP6YZ2P.js";
7
- import "./chunk-HSQAKOYX.js";
7
+ import "./chunk-7PX3ZX4G.js";
8
8
  import {
9
9
  runTool
10
- } from "./chunk-Y3PNCW7A.js";
10
+ } from "./chunk-SHI5UFUH.js";
11
11
  import {
12
12
  getDangerLevel,
13
13
  schemaToJsonSchema
14
- } from "./chunk-HIU2SH4V.js";
14
+ } from "./chunk-JOR572WG.js";
15
15
  import "./chunk-TZQHYZKT.js";
16
16
  import {
17
17
  VERSION
18
- } from "./chunk-ASVBZIUE.js";
18
+ } from "./chunk-P3PTUSP4.js";
19
19
  import "./chunk-4BKXL7SM.js";
20
20
  import "./chunk-TB4W4Y4T.js";
21
21
  import "./chunk-KHYD3WXE.js";
@@ -3,20 +3,21 @@ import {
3
3
  ToolRegistry,
4
4
  googleSearchContext,
5
5
  truncateOutput
6
- } from "./chunk-RQ7JVLFM.js";
6
+ } from "./chunk-SI5EO3NJ.js";
7
7
  import "./chunk-T2NL5ZIA.js";
8
8
  import "./chunk-BXP6YZ2P.js";
9
- import "./chunk-HSQAKOYX.js";
9
+ import "./chunk-7PX3ZX4G.js";
10
10
  import {
11
11
  runTool
12
- } from "./chunk-Y3PNCW7A.js";
12
+ } from "./chunk-SHI5UFUH.js";
13
13
  import {
14
- getDangerLevel
15
- } from "./chunk-HIU2SH4V.js";
14
+ getDangerLevel,
15
+ runLeanAgentLoop
16
+ } from "./chunk-JOR572WG.js";
16
17
  import "./chunk-TZQHYZKT.js";
17
18
  import {
18
19
  SUBAGENT_ALLOWED_TOOLS
19
- } from "./chunk-ASVBZIUE.js";
20
+ } from "./chunk-P3PTUSP4.js";
20
21
  import "./chunk-4BKXL7SM.js";
21
22
  import "./chunk-TB4W4Y4T.js";
22
23
  import "./chunk-KHYD3WXE.js";
@@ -99,73 +100,44 @@ If you keep calling tools after the task is done, you are wasting rounds. STOP a
99
100
 
100
101
  ${task}`, timestamp: /* @__PURE__ */ new Date() }
101
102
  ];
102
- const extraMessages = [];
103
- const totalUsage = { inputTokens: 0, outputTokens: 0 };
104
- let finalContent = "";
105
- let roundsUsed = 0;
106
103
  const executor = new TaskToolExecutor(registry, onToolCall, onToolResult);
107
- let toolCallCount = 0;
108
- try {
109
- for (let round = 0; round < maxRounds; round++) {
110
- roundsUsed = round + 1;
111
- executor.setRoundInfo(round + 1, maxRounds);
112
- onRound?.(round + 1, maxRounds);
113
- if (configManager) {
114
- googleSearchContext.configManager = configManager;
115
- }
116
- let activeSystemPrompt = systemPrompt;
117
- const remaining = maxRounds - round;
104
+ const loop = await runLeanAgentLoop({
105
+ provider,
106
+ messages,
107
+ model,
108
+ maxRounds,
109
+ chatParams: { temperature: 0.3, maxTokens: 8192 },
110
+ executeTools: (calls) => executor.executeAll(calls),
111
+ systemPromptForRound: (_round, remaining) => {
118
112
  if (remaining <= 3 && remaining > 1) {
119
- activeSystemPrompt += `
113
+ return systemPrompt + `
120
114
 
121
115
  \u26A0\uFE0F You have ${remaining} rounds remaining. Finish your current work NOW and respond with a text summary on the next turn. Do NOT start new sub-tasks.`;
122
- } else if (remaining === 1) {
123
- activeSystemPrompt += "\n\n\u{1F6D1} LAST ROUND. Do NOT call any more tools. You MUST respond with a text summary of what you accomplished. List files created/modified and the current state.";
124
- }
125
- const result = await provider.chatWithTools(
126
- {
127
- messages,
128
- model,
129
- systemPrompt: activeSystemPrompt,
130
- stream: false,
131
- temperature: 0.3,
132
- maxTokens: 8192,
133
- ...extraMessages.length > 0 ? { _extraMessages: extraMessages } : {}
134
- },
135
- // On the very last round, send empty tools to force text response
136
- round === maxRounds - 1 ? [] : toolDefs
137
- );
138
- if (result.usage) {
139
- totalUsage.inputTokens += result.usage.inputTokens;
140
- totalUsage.outputTokens += result.usage.outputTokens;
141
- }
142
- if ("content" in result) {
143
- finalContent = result.content;
144
- break;
145
116
  }
146
- toolCallCount += result.toolCalls.length;
147
- const toolResults = await executor.executeAll(result.toolCalls);
148
- const reasoningContent = "reasoningContent" in result ? result.reasoningContent : void 0;
149
- const newMsgs = provider.buildToolResultMessages(result.toolCalls, toolResults, reasoningContent);
150
- extraMessages.push(...newMsgs);
151
- }
152
- if (!finalContent) {
153
- if (toolCallCount > 0) {
154
- finalContent = `(Task completed work using ${toolCallCount} tool calls across ${maxRounds} rounds, but did not produce a final summary)`;
155
- } else {
156
- finalContent = `(Task agent reached maximum rounds (${maxRounds}) without producing output)`;
117
+ if (remaining === 1) {
118
+ return systemPrompt + "\n\n\u{1F6D1} LAST ROUND. Do NOT call any more tools. You MUST respond with a text summary of what you accomplished. List files created/modified and the current state.";
157
119
  }
158
- }
159
- } catch (err) {
160
- const errMsg = err instanceof Error ? err.message : String(err);
161
- finalContent = `(Task execution error: ${errMsg})`;
162
- }
120
+ return systemPrompt;
121
+ },
122
+ // On the very last round, send empty tools to force a text response
123
+ toolDefsForRound: (round) => round === maxRounds - 1 ? [] : toolDefs,
124
+ onRoundStart: (round) => {
125
+ executor.setRoundInfo(round + 1, maxRounds);
126
+ onRound?.(round + 1, maxRounds);
127
+ if (configManager) googleSearchContext.configManager = configManager;
128
+ },
129
+ onRoundsExhausted: (toolCallCount) => (
130
+ // If agent did useful work (tool calls) but ran out of rounds, treat as soft success
131
+ toolCallCount > 0 ? `(Task completed work using ${toolCallCount} tool calls across ${maxRounds} rounds, but did not produce a final summary)` : `(Task agent reached maximum rounds (${maxRounds}) without producing output)`
132
+ ),
133
+ onError: (errMsg) => `(Task execution error: ${errMsg})`
134
+ });
163
135
  return {
164
- content: finalContent,
136
+ content: loop.content,
165
137
  // Success if: got a real response, OR did useful tool work (soft success)
166
- success: !finalContent.startsWith("(Task") || toolCallCount > 0,
167
- roundsUsed,
168
- usage: totalUsage
138
+ success: !loop.content.startsWith("(Task") || loop.toolCallCount > 0,
139
+ roundsUsed: loop.roundsUsed,
140
+ usage: loop.usage
169
141
  };
170
142
  }
171
143
  var TaskToolExecutor = class {
@@ -8,9 +8,9 @@ import {
8
8
  } from "./chunk-V37XOYOE.js";
9
9
  import {
10
10
  ConfigManager
11
- } from "./chunk-XDH5EFWC.js";
11
+ } from "./chunk-VQT27CZK.js";
12
12
  import "./chunk-TZQHYZKT.js";
13
- import "./chunk-ASVBZIUE.js";
13
+ import "./chunk-P3PTUSP4.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
15
 
16
16
  // src/cli/usage.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.191",
3
+ "version": "0.4.193",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,64 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/tools/types.ts
4
- function isFileWriteTool(name) {
5
- return name === "write_file" || name === "edit_file" || name === "notebook_edit";
6
- }
7
- function getDangerLevel(toolName, args) {
8
- if (toolName.startsWith("mcp__")) return "safe";
9
- if (toolName === "bash") {
10
- const cmd = String(args["command"] ?? "");
11
- if (/\brm\s+[^\n]*(?:-\w*[rRfF]\w*|--recursive|--force)\b/.test(cmd)) return "destructive";
12
- if (/\brm\s+\S/.test(cmd)) return "destructive";
13
- if (/\brmdir\b|\bformat\b|\bmkfs\b|\bdd\s+if=|\bshred\b|\bfdisk\b|\bparted\b/.test(cmd)) return "destructive";
14
- if (/\bshutdown\b|\breboot\b|\bhalt\b|\bpoweroff\b/.test(cmd)) return "destructive";
15
- if (/\bkill\s+-9\b|\bkillall\b/.test(cmd)) return "destructive";
16
- if (/\bRemove-Item\b|\bri\s+\S/i.test(cmd)) return "destructive";
17
- if (/\brd\s+\/s\b|\brmdir\s+\/s\b/i.test(cmd)) return "destructive";
18
- if (/\bdel\s+\S/.test(cmd)) return "destructive";
19
- if (/\bShutdown(-Computer)?\b|\bRestart-Computer\b/i.test(cmd)) return "destructive";
20
- if (/(?:^|[\s|;&])>>?\s*\S/.test(cmd)) return "write";
21
- if (/\btee\b|\bcp\b|\bmv\b|\bln\s+-s/.test(cmd)) return "write";
22
- if (/\bchmod\b|\bchown\b/.test(cmd)) return "write";
23
- if (/\bSet-Content\b|\bOut-File\b|\bAdd-Content\b|\bCopy-Item\b|\bMove-Item\b|\bSet-ItemProperty\b|\bNew-ItemProperty\b/i.test(cmd)) return "write";
24
- if (/\b(python3?|node|deno|bun|perl|ruby|php|bash|sh|zsh|pwsh|powershell)(\.exe)?\b[^\n]*?\s-(?:Command|EncodedCommand|c|e|p|r)\b/i.test(cmd)) return "write";
25
- if (/\bcmd(\.exe)?\s+\/[ck]\b/i.test(cmd)) return "write";
26
- return "safe";
27
- }
28
- if (toolName === "write_file") return "write";
29
- if (toolName === "edit_file") return "write";
30
- if (toolName === "save_last_response") return "write";
31
- if (toolName === "run_interactive") {
32
- const exe = String(args["executable"] ?? "").toLowerCase();
33
- if (/\b(rm|rmdir|del|format|mkfs|Remove-Item)\b/i.test(exe)) return "destructive";
34
- if (/\b(bash|sh|zsh|cmd|powershell|pwsh|python|node|ruby|perl)\b/i.test(exe)) return "write";
35
- return "write";
36
- }
37
- if (toolName === "task_create" || toolName === "task_stop") return "write";
38
- if (toolName === "task_list") return "safe";
39
- if (toolName === "git_commit") return "write";
40
- if (toolName === "git_status" || toolName === "git_diff" || toolName === "git_log") return "safe";
41
- if (toolName === "notebook_edit") return "write";
42
- if (toolName === "read_file" || toolName === "list_dir" || toolName === "grep_files" || toolName === "glob_files" || toolName === "web_fetch" || toolName === "save_memory" || toolName === "ask_user" || toolName === "write_todos" || toolName === "google_search" || toolName === "spawn_agent" || toolName === "run_tests") return "safe";
43
- return "write";
44
- }
45
- function schemaToJsonSchema(schema) {
46
- const result = {
47
- type: schema.type,
48
- description: schema.description
49
- };
50
- if (schema.enum) result["enum"] = schema.enum;
51
- if (schema.items) result["items"] = schemaToJsonSchema(schema.items);
52
- if (schema.properties) {
53
- result["properties"] = Object.fromEntries(
54
- Object.entries(schema.properties).map(([k, v]) => [k, schemaToJsonSchema(v)])
55
- );
56
- }
57
- return result;
58
- }
59
-
60
- export {
61
- isFileWriteTool,
62
- getDangerLevel,
63
- schemaToJsonSchema
64
- };