jinzd-ai-cli 0.4.190 → 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.
@@ -3,20 +3,21 @@ import {
3
3
  ToolRegistry,
4
4
  googleSearchContext,
5
5
  truncateOutput
6
- } from "./chunk-5CLH6XAW.js";
6
+ } from "./chunk-SI5EO3NJ.js";
7
7
  import "./chunk-T2NL5ZIA.js";
8
8
  import "./chunk-BXP6YZ2P.js";
9
- import "./chunk-NV6W7TZW.js";
9
+ import "./chunk-7PX3ZX4G.js";
10
10
  import {
11
11
  runTool
12
- } from "./chunk-KHS7RSGR.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-4KMDKDAK.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-X4J2DZB5.js";
11
+ } from "./chunk-VQT27CZK.js";
12
12
  import "./chunk-TZQHYZKT.js";
13
- import "./chunk-4KMDKDAK.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.190",
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
- };