jinzd-ai-cli 0.4.2 → 0.4.4
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/{chunk-LP2ZH4HH.js → chunk-DGH7SQCZ.js} +2 -2
- package/dist/{chunk-E2HVDEWW.js → chunk-FUPDFYHI.js} +1 -1
- package/dist/{chunk-54EGIKT5.js → chunk-GGIRUPT6.js} +3 -3
- package/dist/{chunk-UB6BRUQ4.js → chunk-QAYMV7WE.js} +3 -3
- package/dist/{hub-OXZNGBAY.js → hub-ZP7OZJMH.js} +2 -2
- package/dist/index.js +6 -6
- package/dist/{run-tests-DRN42YLI.js → run-tests-IABMLZG5.js} +1 -1
- package/dist/{run-tests-4WOG5THP.js → run-tests-KPWEEJKA.js} +1 -1
- package/dist/{server-JNWKHPBS.js → server-USQZD3PU.js} +4 -4
- package/dist/{task-orchestrator-GONUQ6TN.js → task-orchestrator-XUMAUKLC.js} +103 -20
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
EnvLoader,
|
|
4
4
|
schemaToJsonSchema
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-FUPDFYHI.js";
|
|
6
6
|
import {
|
|
7
7
|
APP_NAME,
|
|
8
8
|
CONFIG_DIR_NAME,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
MCP_TOOL_PREFIX,
|
|
16
16
|
PLUGINS_DIR_NAME,
|
|
17
17
|
VERSION
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-QAYMV7WE.js";
|
|
19
19
|
|
|
20
20
|
// src/config/config-manager.ts
|
|
21
21
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
@@ -6,7 +6,7 @@ import { platform } from "os";
|
|
|
6
6
|
import chalk from "chalk";
|
|
7
7
|
|
|
8
8
|
// src/core/constants.ts
|
|
9
|
-
var VERSION = "0.4.
|
|
9
|
+
var VERSION = "0.4.4";
|
|
10
10
|
var APP_NAME = "ai-cli";
|
|
11
11
|
var CONFIG_DIR_NAME = ".aicli";
|
|
12
12
|
var CONFIG_FILE_NAME = "config.json";
|
|
@@ -59,8 +59,8 @@ You are currently in read-only planning (Plan) mode.
|
|
|
59
59
|
- Focus your analysis on reading files and producing actionable plans.
|
|
60
60
|
|
|
61
61
|
Once planning is complete, clearly inform the user: type \`/plan execute\` to begin executing the plan, or \`/plan exit\` to discard it.`;
|
|
62
|
-
var SUBAGENT_DEFAULT_MAX_ROUNDS =
|
|
63
|
-
var SUBAGENT_MAX_ROUNDS_LIMIT =
|
|
62
|
+
var SUBAGENT_DEFAULT_MAX_ROUNDS = 15;
|
|
63
|
+
var SUBAGENT_MAX_ROUNDS_LIMIT = 30;
|
|
64
64
|
var SUBAGENT_ALLOWED_TOOLS = /* @__PURE__ */ new Set([
|
|
65
65
|
"bash",
|
|
66
66
|
"read_file",
|
|
@@ -8,7 +8,7 @@ import { platform } from "os";
|
|
|
8
8
|
import chalk from "chalk";
|
|
9
9
|
|
|
10
10
|
// src/core/constants.ts
|
|
11
|
-
var VERSION = "0.4.
|
|
11
|
+
var VERSION = "0.4.4";
|
|
12
12
|
var APP_NAME = "ai-cli";
|
|
13
13
|
var CONFIG_DIR_NAME = ".aicli";
|
|
14
14
|
var CONFIG_FILE_NAME = "config.json";
|
|
@@ -62,8 +62,8 @@ You are currently in read-only planning (Plan) mode.
|
|
|
62
62
|
- Focus your analysis on reading files and producing actionable plans.
|
|
63
63
|
|
|
64
64
|
Once planning is complete, clearly inform the user: type \`/plan execute\` to begin executing the plan, or \`/plan exit\` to discard it.`;
|
|
65
|
-
var SUBAGENT_DEFAULT_MAX_ROUNDS =
|
|
66
|
-
var SUBAGENT_MAX_ROUNDS_LIMIT =
|
|
65
|
+
var SUBAGENT_DEFAULT_MAX_ROUNDS = 15;
|
|
66
|
+
var SUBAGENT_MAX_ROUNDS_LIMIT = 30;
|
|
67
67
|
var SUBAGENT_ALLOWED_TOOLS = /* @__PURE__ */ new Set([
|
|
68
68
|
"bash",
|
|
69
69
|
"read_file",
|
|
@@ -366,7 +366,7 @@ ${content}`);
|
|
|
366
366
|
defaultModel,
|
|
367
367
|
maxRounds: options.maxRounds ?? (mode === "task" ? 15 : 10),
|
|
368
368
|
enableTools: mode === "task",
|
|
369
|
-
maxToolRoundsPerTurn: mode === "task" ?
|
|
369
|
+
maxToolRoundsPerTurn: mode === "task" ? 30 : void 0,
|
|
370
370
|
context,
|
|
371
371
|
contextFiles: contextFileNames.length > 0 ? contextFileNames : void 0
|
|
372
372
|
};
|
|
@@ -381,7 +381,7 @@ ${content}`);
|
|
|
381
381
|
}
|
|
382
382
|
}
|
|
383
383
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
384
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
384
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-XUMAUKLC.js");
|
|
385
385
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
386
386
|
let interrupted = false;
|
|
387
387
|
const onSigint = () => {
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
saveDevState,
|
|
24
24
|
sessionHasMeaningfulContent,
|
|
25
25
|
setupProxy
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-DGH7SQCZ.js";
|
|
27
27
|
import {
|
|
28
28
|
ToolRegistry,
|
|
29
29
|
askUserContext,
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
theme,
|
|
39
39
|
truncateOutput,
|
|
40
40
|
undoStack
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-FUPDFYHI.js";
|
|
42
42
|
import {
|
|
43
43
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
44
44
|
AUTHOR,
|
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
REPO_URL,
|
|
59
59
|
SKILLS_DIR_NAME,
|
|
60
60
|
VERSION
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-QAYMV7WE.js";
|
|
62
62
|
|
|
63
63
|
// src/index.ts
|
|
64
64
|
import { program } from "commander";
|
|
@@ -1914,7 +1914,7 @@ ${hint}` : "")
|
|
|
1914
1914
|
description: "Run project tests and show structured report",
|
|
1915
1915
|
usage: "/test [command|filter]",
|
|
1916
1916
|
async execute(args, _ctx) {
|
|
1917
|
-
const { executeTests } = await import("./run-tests-
|
|
1917
|
+
const { executeTests } = await import("./run-tests-KPWEEJKA.js");
|
|
1918
1918
|
const argStr = args.join(" ").trim();
|
|
1919
1919
|
let testArgs = {};
|
|
1920
1920
|
if (argStr) {
|
|
@@ -5524,7 +5524,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
5524
5524
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
5525
5525
|
process.exit(1);
|
|
5526
5526
|
}
|
|
5527
|
-
const { startWebServer } = await import("./server-
|
|
5527
|
+
const { startWebServer } = await import("./server-USQZD3PU.js");
|
|
5528
5528
|
await startWebServer({ port, host: options.host });
|
|
5529
5529
|
});
|
|
5530
5530
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -5757,7 +5757,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
5757
5757
|
}),
|
|
5758
5758
|
config.get("customProviders")
|
|
5759
5759
|
);
|
|
5760
|
-
const { startHub } = await import("./hub-
|
|
5760
|
+
const { startHub } = await import("./hub-ZP7OZJMH.js");
|
|
5761
5761
|
await startHub(
|
|
5762
5762
|
{
|
|
5763
5763
|
topic: topic ?? "",
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
renderDiff,
|
|
19
19
|
runHook,
|
|
20
20
|
setupProxy
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-DGH7SQCZ.js";
|
|
22
22
|
import {
|
|
23
23
|
AuthManager
|
|
24
24
|
} from "./chunk-CPLT6CD3.js";
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
spawnAgentContext,
|
|
33
33
|
truncateOutput,
|
|
34
34
|
undoStack
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-FUPDFYHI.js";
|
|
36
36
|
import {
|
|
37
37
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
38
38
|
CONTEXT_FILE_CANDIDATES,
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
PLAN_MODE_SYSTEM_ADDON,
|
|
45
45
|
SKILLS_DIR_NAME,
|
|
46
46
|
VERSION
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-QAYMV7WE.js";
|
|
48
48
|
|
|
49
49
|
// src/web/server.ts
|
|
50
50
|
import express from "express";
|
|
@@ -1440,7 +1440,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1440
1440
|
case "test": {
|
|
1441
1441
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
1442
1442
|
try {
|
|
1443
|
-
const { executeTests } = await import("./run-tests-
|
|
1443
|
+
const { executeTests } = await import("./run-tests-KPWEEJKA.js");
|
|
1444
1444
|
const argStr = args.join(" ").trim();
|
|
1445
1445
|
let testArgs = {};
|
|
1446
1446
|
if (argStr) {
|
|
@@ -4,13 +4,15 @@ import {
|
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
googleSearchContext,
|
|
6
6
|
truncateOutput
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-FUPDFYHI.js";
|
|
8
8
|
import {
|
|
9
9
|
SUBAGENT_ALLOWED_TOOLS
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QAYMV7WE.js";
|
|
11
11
|
|
|
12
12
|
// src/hub/task-orchestrator.ts
|
|
13
13
|
import { createInterface } from "readline";
|
|
14
|
+
import { existsSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
15
|
+
import { join } from "path";
|
|
14
16
|
import chalk from "chalk";
|
|
15
17
|
|
|
16
18
|
// src/hub/task-executor.ts
|
|
@@ -63,6 +65,7 @@ ${task}`, timestamp: /* @__PURE__ */ new Date() }
|
|
|
63
65
|
let finalContent = "";
|
|
64
66
|
let roundsUsed = 0;
|
|
65
67
|
const executor = new TaskToolExecutor(registry, onToolCall, onToolResult);
|
|
68
|
+
let toolCallCount = 0;
|
|
66
69
|
try {
|
|
67
70
|
for (let round = 0; round < maxRounds; round++) {
|
|
68
71
|
roundsUsed = round + 1;
|
|
@@ -71,17 +74,24 @@ ${task}`, timestamp: /* @__PURE__ */ new Date() }
|
|
|
71
74
|
if (configManager) {
|
|
72
75
|
googleSearchContext.configManager = configManager;
|
|
73
76
|
}
|
|
77
|
+
let activeSystemPrompt = systemPrompt;
|
|
78
|
+
if (round === maxRounds - 2) {
|
|
79
|
+
activeSystemPrompt += "\n\n\u26A0\uFE0F You have 2 rounds remaining. Start wrapping up \u2014 finish current work and prepare your summary.";
|
|
80
|
+
} else if (round === maxRounds - 1) {
|
|
81
|
+
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.";
|
|
82
|
+
}
|
|
74
83
|
const result = await provider.chatWithTools(
|
|
75
84
|
{
|
|
76
85
|
messages,
|
|
77
86
|
model,
|
|
78
|
-
systemPrompt,
|
|
87
|
+
systemPrompt: activeSystemPrompt,
|
|
79
88
|
stream: false,
|
|
80
89
|
temperature: 0.3,
|
|
81
90
|
maxTokens: 8192,
|
|
82
91
|
...extraMessages.length > 0 ? { _extraMessages: extraMessages } : {}
|
|
83
92
|
},
|
|
84
|
-
|
|
93
|
+
// On the very last round, send empty tools to force text response
|
|
94
|
+
round === maxRounds - 1 ? [] : toolDefs
|
|
85
95
|
);
|
|
86
96
|
if (result.usage) {
|
|
87
97
|
totalUsage.inputTokens += result.usage.inputTokens;
|
|
@@ -91,13 +101,18 @@ ${task}`, timestamp: /* @__PURE__ */ new Date() }
|
|
|
91
101
|
finalContent = result.content;
|
|
92
102
|
break;
|
|
93
103
|
}
|
|
104
|
+
toolCallCount += result.toolCalls.length;
|
|
94
105
|
const toolResults = await executor.executeAll(result.toolCalls);
|
|
95
106
|
const reasoningContent = "reasoningContent" in result ? result.reasoningContent : void 0;
|
|
96
107
|
const newMsgs = provider.buildToolResultMessages(result.toolCalls, toolResults, reasoningContent);
|
|
97
108
|
extraMessages.push(...newMsgs);
|
|
98
109
|
}
|
|
99
110
|
if (!finalContent) {
|
|
100
|
-
|
|
111
|
+
if (toolCallCount > 0) {
|
|
112
|
+
finalContent = `(Task completed work using ${toolCallCount} tool calls across ${maxRounds} rounds, but did not produce a final summary)`;
|
|
113
|
+
} else {
|
|
114
|
+
finalContent = `(Task agent reached maximum rounds (${maxRounds}) without producing output)`;
|
|
115
|
+
}
|
|
101
116
|
}
|
|
102
117
|
} catch (err) {
|
|
103
118
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -105,7 +120,8 @@ ${task}`, timestamp: /* @__PURE__ */ new Date() }
|
|
|
105
120
|
}
|
|
106
121
|
return {
|
|
107
122
|
content: finalContent,
|
|
108
|
-
|
|
123
|
+
// Success if: got a real response, OR did useful tool work (soft success)
|
|
124
|
+
success: !finalContent.startsWith("(Task") || toolCallCount > 0,
|
|
109
125
|
roundsUsed,
|
|
110
126
|
usage: totalUsage
|
|
111
127
|
};
|
|
@@ -158,6 +174,7 @@ var TaskToolExecutor = class {
|
|
|
158
174
|
};
|
|
159
175
|
|
|
160
176
|
// src/hub/task-orchestrator.ts
|
|
177
|
+
var TASK_STATE_FILE = ".aicli-task.json";
|
|
161
178
|
var TaskOrchestrator = class {
|
|
162
179
|
constructor(config, providers, configManager) {
|
|
163
180
|
this.config = config;
|
|
@@ -169,7 +186,7 @@ var TaskOrchestrator = class {
|
|
|
169
186
|
this.aborted = true;
|
|
170
187
|
}
|
|
171
188
|
/**
|
|
172
|
-
* Run the full task mode workflow.
|
|
189
|
+
* Run the full task mode workflow, with resume support.
|
|
173
190
|
*/
|
|
174
191
|
async run(goal) {
|
|
175
192
|
const provider = this.providers.get(this.config.defaultProvider);
|
|
@@ -177,23 +194,85 @@ var TaskOrchestrator = class {
|
|
|
177
194
|
console.error(chalk.red(` \u2717 Provider "${this.config.defaultProvider}" not available.`));
|
|
178
195
|
return;
|
|
179
196
|
}
|
|
180
|
-
this.
|
|
181
|
-
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
|
|
197
|
+
const saved = this.loadState();
|
|
198
|
+
let plan = null;
|
|
199
|
+
if (saved && saved.tasks.some((t) => t.status === "pending" || t.status === "failed")) {
|
|
200
|
+
const doneCount = saved.tasks.filter((t) => t.status === "done").length;
|
|
201
|
+
const totalCount = saved.tasks.length;
|
|
202
|
+
console.log();
|
|
203
|
+
console.log(chalk.bold.yellow(` \u26A1 Found saved task plan (${doneCount}/${totalCount} completed)`));
|
|
204
|
+
console.log(chalk.dim(` Goal: ${saved.goal}`));
|
|
205
|
+
console.log();
|
|
206
|
+
const resume = await this.askResume();
|
|
207
|
+
if (resume) {
|
|
208
|
+
plan = saved;
|
|
209
|
+
for (const t of plan.tasks) {
|
|
210
|
+
if (t.status === "failed") t.status = "pending";
|
|
211
|
+
}
|
|
212
|
+
this.renderPlan(plan);
|
|
213
|
+
}
|
|
185
214
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
215
|
+
if (!plan) {
|
|
216
|
+
this.renderPhaseHeader("PLAN", "Architect is decomposing the goal into tasks...");
|
|
217
|
+
plan = await this.generatePlan(goal, provider);
|
|
218
|
+
if (!plan || plan.tasks.length === 0) {
|
|
219
|
+
console.log(chalk.red(" \u2717 Failed to generate a task plan."));
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
this.renderPlan(plan);
|
|
223
|
+
this.renderPhaseHeader("APPROVE", "Review the task plan");
|
|
224
|
+
const approved = await this.waitForApproval(plan);
|
|
225
|
+
if (!approved) {
|
|
226
|
+
console.log(chalk.yellow(" \u26A0 Task plan rejected. Exiting."));
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
192
229
|
}
|
|
193
230
|
this.renderPhaseHeader("EXECUTE", "Agents are executing tasks...");
|
|
194
231
|
await this.executePlan(plan, provider);
|
|
195
232
|
this.renderPhaseHeader("REVIEW", "Generating project summary...");
|
|
196
233
|
await this.generateReview(plan, provider);
|
|
234
|
+
const allDone = plan.tasks.every((t) => t.status === "done");
|
|
235
|
+
if (allDone) {
|
|
236
|
+
this.deleteState();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// ── State Persistence ────────────────────────────────────────────
|
|
240
|
+
get stateFilePath() {
|
|
241
|
+
return join(process.cwd(), TASK_STATE_FILE);
|
|
242
|
+
}
|
|
243
|
+
saveState(plan) {
|
|
244
|
+
try {
|
|
245
|
+
writeFileSync(this.stateFilePath, JSON.stringify(plan, null, 2), "utf-8");
|
|
246
|
+
} catch {
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
loadState() {
|
|
250
|
+
try {
|
|
251
|
+
if (!existsSync(this.stateFilePath)) return null;
|
|
252
|
+
const raw = readFileSync(this.stateFilePath, "utf-8");
|
|
253
|
+
const parsed = JSON.parse(raw);
|
|
254
|
+
if (!parsed.goal || !Array.isArray(parsed.tasks)) return null;
|
|
255
|
+
return parsed;
|
|
256
|
+
} catch {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
deleteState() {
|
|
261
|
+
try {
|
|
262
|
+
if (existsSync(this.stateFilePath)) unlinkSync(this.stateFilePath);
|
|
263
|
+
} catch {
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
async askResume() {
|
|
267
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
268
|
+
try {
|
|
269
|
+
const answer = await new Promise((resolve) => {
|
|
270
|
+
rl.question(chalk.green(" Resume from saved state? (y/n) > "), resolve);
|
|
271
|
+
});
|
|
272
|
+
return answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes";
|
|
273
|
+
} finally {
|
|
274
|
+
rl.close();
|
|
275
|
+
}
|
|
197
276
|
}
|
|
198
277
|
// ── Phase 1: Plan Generation ──────────────────────────────────────
|
|
199
278
|
async generatePlan(goal, provider) {
|
|
@@ -305,9 +384,12 @@ Example:
|
|
|
305
384
|
}
|
|
306
385
|
// ── Phase 3: Task Execution ───────────────────────────────────────
|
|
307
386
|
async executePlan(plan, provider) {
|
|
308
|
-
const maxRoundsPerTask = this.config.maxToolRoundsPerTurn ??
|
|
387
|
+
const maxRoundsPerTask = this.config.maxToolRoundsPerTurn ?? 30;
|
|
309
388
|
const roleMap = new Map(this.config.roles.map((r) => [r.id, r]));
|
|
310
|
-
const completedIds =
|
|
389
|
+
const completedIds = new Set(
|
|
390
|
+
plan.tasks.filter((t) => t.status === "done").map((t) => t.id)
|
|
391
|
+
);
|
|
392
|
+
this.saveState(plan);
|
|
311
393
|
while (!this.aborted) {
|
|
312
394
|
const nextTask = plan.tasks.find(
|
|
313
395
|
(t) => t.status === "pending" && t.dependencies.every((d) => completedIds.has(d))
|
|
@@ -354,6 +436,7 @@ Example:
|
|
|
354
436
|
if (result.success) {
|
|
355
437
|
completedIds.add(nextTask.id);
|
|
356
438
|
}
|
|
439
|
+
this.saveState(plan);
|
|
357
440
|
this.renderTaskEnd(nextTask, result);
|
|
358
441
|
if (this.aborted) {
|
|
359
442
|
console.log(chalk.yellow("\n \u26A0 Execution interrupted by user."));
|