jinzd-ai-cli 0.2.28 → 0.3.1

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.
@@ -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.2.28";
9
+ var VERSION = "0.3.1";
10
10
  var APP_NAME = "ai-cli";
11
11
  var CONFIG_DIR_NAME = ".aicli";
12
12
  var CONFIG_FILE_NAME = "config.json";
@@ -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.2.28";
11
+ var VERSION = "0.3.1";
12
12
  var APP_NAME = "ai-cli";
13
13
  var CONFIG_DIR_NAME = ".aicli";
14
14
  var CONFIG_FILE_NAME = "config.json";
@@ -16,7 +16,7 @@ import {
16
16
  SUBAGENT_MAX_ROUNDS_LIMIT,
17
17
  VERSION,
18
18
  runTestsTool
19
- } from "./chunk-STOS2HXS.js";
19
+ } from "./chunk-QVUOF3DK.js";
20
20
 
21
21
  // src/config/config-manager.ts
22
22
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
@@ -0,0 +1,646 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/hub/agent.ts
4
+ var PASS_MARKER = "[PASS]";
5
+ var HubAgent = class {
6
+ role;
7
+ providers;
8
+ defaultProvider;
9
+ defaultModel;
10
+ constructor(role, providers, defaultProvider, defaultModel) {
11
+ this.role = role;
12
+ this.providers = providers;
13
+ this.defaultProvider = defaultProvider;
14
+ this.defaultModel = defaultModel;
15
+ }
16
+ get providerId() {
17
+ return this.role.provider ?? this.defaultProvider;
18
+ }
19
+ get modelId() {
20
+ return this.role.model ?? this.defaultModel;
21
+ }
22
+ /**
23
+ * Generate this agent's response given the full discussion history.
24
+ *
25
+ * Returns a DiscussionMessage, with `passed: true` if the agent outputs [PASS].
26
+ */
27
+ async speak(topic, history, round, maxRounds) {
28
+ const provider = this.providers.get(this.providerId);
29
+ if (!provider) {
30
+ throw new Error(`Provider "${this.providerId}" not available for agent "${this.role.id}"`);
31
+ }
32
+ const systemPrompt = this.buildSystemPrompt(topic, round, maxRounds);
33
+ const messages = this.buildMessages(history);
34
+ const response = await provider.chat({
35
+ messages,
36
+ model: this.modelId,
37
+ systemPrompt,
38
+ stream: false,
39
+ temperature: 0.7,
40
+ maxTokens: 4096
41
+ });
42
+ const content = response.content.trim();
43
+ const passed = content.toUpperCase().startsWith(PASS_MARKER) || content.toUpperCase() === PASS_MARKER;
44
+ return {
45
+ speaker: this.role.id,
46
+ speakerName: this.role.name,
47
+ content: passed ? "" : content,
48
+ timestamp: /* @__PURE__ */ new Date(),
49
+ passed
50
+ };
51
+ }
52
+ /**
53
+ * Generate a summary of the entire discussion from this agent's perspective.
54
+ */
55
+ async summarize(topic, history) {
56
+ const provider = this.providers.get(this.providerId);
57
+ if (!provider) {
58
+ throw new Error(`Provider "${this.providerId}" not available`);
59
+ }
60
+ const messages = [
61
+ {
62
+ role: "user",
63
+ content: this.buildSummaryPrompt(topic, history),
64
+ timestamp: /* @__PURE__ */ new Date()
65
+ }
66
+ ];
67
+ const response = await provider.chat({
68
+ messages,
69
+ model: this.modelId,
70
+ stream: false,
71
+ temperature: 0.3,
72
+ maxTokens: 4096
73
+ });
74
+ return response.content.trim();
75
+ }
76
+ // ── Private ──────────────────────────────────────────────────────
77
+ buildSystemPrompt(topic, round, maxRounds) {
78
+ return `# Multi-Agent Discussion \u2014 Role: ${this.role.name}
79
+
80
+ ${this.role.persona}
81
+
82
+ ## Discussion Rules
83
+ - You are participating in a multi-agent discussion about the topic below.
84
+ - You can see what other participants have said. Build on their ideas, challenge them, or add your own perspective.
85
+ - Stay in character as ${this.role.name}. Respond from your role's expertise and viewpoint.
86
+ - Keep responses concise and focused (2-6 paragraphs). Do not repeat what others have already said.
87
+ - If you have nothing meaningful to add (others have covered your points), respond with exactly: [PASS]
88
+ - This is round ${round} of ${maxRounds}. ${round >= maxRounds - 1 ? "This is one of the final rounds \u2014 try to converge on conclusions." : ""}
89
+ - Use the language that the topic is written in (if the topic is in Chinese, respond in Chinese).
90
+
91
+ ## Topic
92
+ ${topic}`;
93
+ }
94
+ buildMessages(history) {
95
+ const messages = [];
96
+ for (const msg of history) {
97
+ if (msg.passed) continue;
98
+ if (msg.speaker === this.role.id) {
99
+ messages.push({
100
+ role: "assistant",
101
+ content: msg.content,
102
+ timestamp: msg.timestamp
103
+ });
104
+ } else {
105
+ const prefix = `[${msg.speakerName} (${msg.speaker})]:`;
106
+ messages.push({
107
+ role: "user",
108
+ content: `${prefix}
109
+ ${msg.content}`,
110
+ timestamp: msg.timestamp
111
+ });
112
+ }
113
+ }
114
+ if (messages.length === 0) {
115
+ messages.push({
116
+ role: "user",
117
+ content: "Please share your initial thoughts on the topic described in the system prompt. You are the first to speak.",
118
+ timestamp: /* @__PURE__ */ new Date()
119
+ });
120
+ } else {
121
+ messages.push({
122
+ role: "user",
123
+ content: "It is now your turn to respond. Consider what the other participants have said and share your perspective. If you have nothing to add, respond with [PASS].",
124
+ timestamp: /* @__PURE__ */ new Date()
125
+ });
126
+ }
127
+ return messages;
128
+ }
129
+ buildSummaryPrompt(topic, history) {
130
+ const transcript = history.filter((m) => !m.passed).map((m) => `**${m.speakerName}** (${m.speaker}):
131
+ ${m.content}`).join("\n\n---\n\n");
132
+ return `Please synthesize the following multi-agent discussion into a clear, structured summary.
133
+
134
+ ## Discussion Topic
135
+ ${topic}
136
+
137
+ ## Full Transcript
138
+ ${transcript}
139
+
140
+ ## Instructions
141
+ Produce a summary that includes:
142
+ 1. **Key Points of Agreement** \u2014 what all participants agreed on
143
+ 2. **Points of Debate** \u2014 where participants disagreed and the different perspectives
144
+ 3. **Conclusions & Recommendations** \u2014 actionable takeaways
145
+ 4. **Open Questions** \u2014 unresolved issues that need further discussion
146
+
147
+ Keep the summary concise (within 500 words). Use the same language as the discussion.`;
148
+ }
149
+ };
150
+
151
+ // src/hub/discuss.ts
152
+ var DiscussionOrchestrator = class {
153
+ constructor(config, providers) {
154
+ this.config = config;
155
+ this.providers = providers;
156
+ this.agents = config.roles.map(
157
+ (role) => new HubAgent(role, providers, config.defaultProvider, config.defaultModel)
158
+ );
159
+ this.state = {
160
+ topic: "",
161
+ messages: [],
162
+ round: 0,
163
+ maxRounds: config.maxRounds ?? 10,
164
+ finished: false
165
+ };
166
+ }
167
+ agents = [];
168
+ state;
169
+ aborted = false;
170
+ /** Callback for rendering events */
171
+ onEvent;
172
+ /** Get all agents */
173
+ getAgents() {
174
+ return this.agents;
175
+ }
176
+ /** Signal the orchestrator to stop after current turn */
177
+ abort() {
178
+ this.aborted = true;
179
+ }
180
+ /**
181
+ * Run the full discussion on a given topic.
182
+ * Returns the final DiscussionState including summary.
183
+ */
184
+ async run(topic) {
185
+ this.state.topic = topic;
186
+ this.state.round = 0;
187
+ this.state.finished = false;
188
+ this.aborted = false;
189
+ try {
190
+ for (let round = 1; round <= this.state.maxRounds; round++) {
191
+ if (this.aborted) {
192
+ this.emit({ type: "discussion_end", reason: "user_interrupt" });
193
+ break;
194
+ }
195
+ this.state.round = round;
196
+ this.emit({ type: "round_start", round, maxRounds: this.state.maxRounds });
197
+ let allPassed = true;
198
+ for (const agent of this.agents) {
199
+ if (this.aborted) break;
200
+ this.emit({ type: "agent_speaking", roleId: agent.role.id, roleName: agent.role.name });
201
+ try {
202
+ const message = await agent.speak(topic, this.state.messages, round, this.state.maxRounds);
203
+ this.state.messages.push(message);
204
+ if (message.passed) {
205
+ this.emit({ type: "agent_passed", roleId: agent.role.id });
206
+ this.emit({ type: "agent_spoke", roleId: agent.role.id, message });
207
+ } else {
208
+ allPassed = false;
209
+ this.emit({ type: "agent_spoke", roleId: agent.role.id, message });
210
+ }
211
+ } catch (err) {
212
+ const errMsg = err instanceof Error ? err.message : String(err);
213
+ this.emit({ type: "error", roleId: agent.role.id, message: errMsg });
214
+ this.state.messages.push({
215
+ speaker: "system",
216
+ speakerName: "System",
217
+ content: `[${agent.role.name} encountered an error: ${errMsg}]`,
218
+ timestamp: /* @__PURE__ */ new Date()
219
+ });
220
+ }
221
+ }
222
+ this.emit({ type: "round_end", round });
223
+ if (allPassed && round > 1) {
224
+ this.emit({ type: "discussion_end", reason: "consensus" });
225
+ break;
226
+ }
227
+ if (round === this.state.maxRounds) {
228
+ this.emit({ type: "discussion_end", reason: "max_rounds" });
229
+ }
230
+ }
231
+ } catch (err) {
232
+ const errMsg = err instanceof Error ? err.message : String(err);
233
+ this.emit({ type: "error", message: errMsg });
234
+ }
235
+ await this.generateSummary();
236
+ this.state.finished = true;
237
+ return this.state;
238
+ }
239
+ // ── Private ──────────────────────────────────────────────────────
240
+ async generateSummary() {
241
+ if (this.state.messages.filter((m) => !m.passed && m.speaker !== "system").length === 0) {
242
+ this.state.summary = "(No substantive discussion occurred.)";
243
+ this.emit({ type: "summary", content: this.state.summary });
244
+ return;
245
+ }
246
+ const summarizer = this.agents[0];
247
+ if (!summarizer) {
248
+ this.state.summary = "(No agents available to summarize.)";
249
+ this.emit({ type: "summary", content: this.state.summary });
250
+ return;
251
+ }
252
+ try {
253
+ this.state.summary = await summarizer.summarize(this.state.topic, this.state.messages);
254
+ this.emit({ type: "summary", content: this.state.summary });
255
+ } catch (err) {
256
+ const errMsg = err instanceof Error ? err.message : String(err);
257
+ this.state.summary = `(Summary generation failed: ${errMsg})`;
258
+ this.emit({ type: "summary", content: this.state.summary });
259
+ }
260
+ }
261
+ emit(event) {
262
+ this.onEvent?.(event);
263
+ }
264
+ };
265
+
266
+ // src/hub/presets.ts
267
+ var PRESETS = [
268
+ {
269
+ id: "tech-review",
270
+ name: "Tech Review Panel",
271
+ description: "\u67B6\u6784\u5E08 + \u5F00\u53D1\u8005 + \u5B89\u5168\u4E13\u5BB6 \u8BA8\u8BBA\u6280\u672F\u65B9\u6848",
272
+ roles: [
273
+ {
274
+ id: "architect",
275
+ name: "\u67B6\u6784\u5E08",
276
+ persona: `\u4F60\u662F\u4E00\u4F4D\u8D44\u6DF1\u8F6F\u4EF6\u67B6\u6784\u5E08\uFF0C\u6709 15 \u5E74\u4EE5\u4E0A\u7684\u7CFB\u7EDF\u8BBE\u8BA1\u7ECF\u9A8C\u3002
277
+ \u4F60\u7684\u4E13\u957F\uFF1A\u7CFB\u7EDF\u67B6\u6784\u3001\u53EF\u6269\u5C55\u6027\u3001\u6280\u672F\u9009\u578B\u3001\u8BBE\u8BA1\u6A21\u5F0F\u3002
278
+ \u4F60\u5173\u6CE8\u7684\u7EF4\u5EA6\uFF1A\u7CFB\u7EDF\u6574\u4F53\u7ED3\u6784\u3001\u6A21\u5757\u89E3\u8026\u3001\u957F\u671F\u53EF\u7EF4\u62A4\u6027\u3001\u6280\u672F\u503A\u52A1\u3002
279
+ \u98CE\u683C\uFF1A\u5168\u5C40\u89C6\u89D2\uFF0C\u5584\u4E8E\u6743\u8861 trade-off\uFF0C\u7528\u56FE\u8868\u548C\u7C7B\u6BD4\u89E3\u91CA\u590D\u6742\u6982\u5FF5\u3002`,
280
+ color: "cyan"
281
+ },
282
+ {
283
+ id: "developer",
284
+ name: "\u5168\u6808\u5F00\u53D1\u8005",
285
+ persona: `\u4F60\u662F\u4E00\u4F4D\u7ECF\u9A8C\u4E30\u5BCC\u7684\u5168\u6808\u5F00\u53D1\u8005\uFF0C\u7CBE\u901A\u524D\u7AEF\u548C\u540E\u7AEF\u6280\u672F\u6808\u3002
286
+ \u4F60\u7684\u4E13\u957F\uFF1A\u4EE3\u7801\u5B9E\u73B0\u3001\u6027\u80FD\u4F18\u5316\u3001API \u8BBE\u8BA1\u3001\u5F00\u53D1\u6548\u7387\u3002
287
+ \u4F60\u5173\u6CE8\u7684\u7EF4\u5EA6\uFF1A\u4EE3\u7801\u53EF\u8BFB\u6027\u3001\u5B9E\u73B0\u590D\u6742\u5EA6\u3001DX(\u5F00\u53D1\u8005\u4F53\u9A8C)\u3001\u5177\u4F53\u6280\u672F\u7EC6\u8282\u3002
288
+ \u98CE\u683C\uFF1A\u52A1\u5B9E\u3001\u6CE8\u91CD\u7EC6\u8282\uFF0C\u559C\u6B22\u7ED9\u51FA\u5177\u4F53\u7684\u4EE3\u7801\u793A\u4F8B\u548C\u5B9E\u73B0\u5EFA\u8BAE\u3002`,
289
+ color: "green"
290
+ },
291
+ {
292
+ id: "security",
293
+ name: "\u5B89\u5168\u4E13\u5BB6",
294
+ persona: `\u4F60\u662F\u4E00\u4F4D\u7F51\u7EDC\u5B89\u5168\u4E13\u5BB6\uFF0C\u4E13\u6CE8\u4E8E\u5E94\u7528\u5B89\u5168\u548C\u5B89\u5168\u67B6\u6784\u8BBE\u8BA1\u3002
295
+ \u4F60\u7684\u4E13\u957F\uFF1A\u5A01\u80C1\u5EFA\u6A21\u3001\u6F0F\u6D1E\u5206\u6790\u3001\u5B89\u5168\u6700\u4F73\u5B9E\u8DF5\u3001\u5408\u89C4\u8981\u6C42\u3002
296
+ \u4F60\u5173\u6CE8\u7684\u7EF4\u5EA6\uFF1A\u653B\u51FB\u9762\u3001\u6570\u636E\u4FDD\u62A4\u3001\u8BA4\u8BC1\u6388\u6743\u3001\u5B89\u5168\u7F16\u7801\u5B9E\u8DF5\u3002
297
+ \u98CE\u683C\uFF1A\u8C28\u614E\u3001\u4E25\u8C28\uFF0C\u5584\u4E8E\u53D1\u73B0\u6F5C\u5728\u98CE\u9669\uFF0C\u540C\u65F6\u4E5F\u4F1A\u63D0\u51FA\u5B9E\u7528\u7684\u5B89\u5168\u65B9\u6848\u800C\u4E0D\u662F\u4E00\u5473\u5426\u5B9A\u3002`,
298
+ color: "red"
299
+ }
300
+ ]
301
+ },
302
+ {
303
+ id: "brainstorm",
304
+ name: "Brainstorm Team",
305
+ description: "\u521B\u610F\u8005 + \u5206\u6790\u5E08 + \u6267\u884C\u8005 \u5934\u8111\u98CE\u66B4",
306
+ roles: [
307
+ {
308
+ id: "creative",
309
+ name: "\u521B\u610F\u8005",
310
+ persona: `\u4F60\u662F\u4E00\u4F4D\u5145\u6EE1\u521B\u610F\u7684\u4EA7\u54C1\u601D\u8003\u8005\uFF0C\u5584\u4E8E\u8DF3\u51FA\u6846\u67B6\u601D\u8003\u3002
311
+ \u4F60\u7684\u4E13\u957F\uFF1A\u521B\u65B0\u601D\u7EF4\u3001\u7528\u6237\u4F53\u9A8C\u3001\u4EA7\u54C1\u613F\u666F\u3001\u8BBE\u8BA1\u601D\u7EF4\u3002
312
+ \u4F60\u5173\u6CE8\u7684\u7EF4\u5EA6\uFF1A\u7528\u6237\u9700\u6C42\u3001\u521B\u65B0\u6027\u3001\u5DEE\u5F02\u5316\u3001\u60C5\u611F\u4EF7\u503C\u3002
313
+ \u98CE\u683C\uFF1A\u53D1\u6563\u6027\u601D\u7EF4\uFF0C\u5927\u80C6\u63D0\u51FA\u65B0\u60F3\u6CD5\uFF0C\u4E0D\u6015\u5929\u9A6C\u884C\u7A7A\u3002\u5584\u4E8E\u7528\u6545\u4E8B\u548C\u573A\u666F\u6765\u63CF\u8FF0\u6784\u60F3\u3002`,
314
+ color: "magenta"
315
+ },
316
+ {
317
+ id: "analyst",
318
+ name: "\u5206\u6790\u5E08",
319
+ persona: `\u4F60\u662F\u4E00\u4F4D\u7406\u6027\u7684\u6570\u636E\u5206\u6790\u5E08\uFF0C\u5584\u4E8E\u7528\u6570\u636E\u548C\u903B\u8F91\u8BC4\u4F30\u65B9\u6848\u3002
320
+ \u4F60\u7684\u4E13\u957F\uFF1A\u6570\u636E\u5206\u6790\u3001\u5E02\u573A\u7814\u7A76\u3001\u53EF\u884C\u6027\u8BC4\u4F30\u3001ROI \u5206\u6790\u3002
321
+ \u4F60\u5173\u6CE8\u7684\u7EF4\u5EA6\uFF1A\u6570\u636E\u652F\u6491\u3001\u6210\u672C\u6536\u76CA\u3001\u98CE\u9669\u8BC4\u4F30\u3001\u5E02\u573A\u53EF\u884C\u6027\u3002
322
+ \u98CE\u683C\uFF1A\u4E25\u8C28\u5BA2\u89C2\uFF0C\u5584\u4E8E\u63D0\u51FA\u5173\u952E\u95EE\u9898\uFF0C\u7528\u6570\u636E\u8BF4\u8BDD\u3002\u4E0D\u8F7B\u6613\u5426\u5B9A\u4F46\u4F1A\u6307\u51FA\u903B\u8F91\u6F0F\u6D1E\u3002`,
323
+ color: "yellow"
324
+ },
325
+ {
326
+ id: "executor",
327
+ name: "\u6267\u884C\u8005",
328
+ persona: `\u4F60\u662F\u4E00\u4F4D\u9AD8\u6548\u7684\u9879\u76EE\u6267\u884C\u8005\uFF0C\u5584\u4E8E\u5C06\u60F3\u6CD5\u8F6C\u5316\u4E3A\u53EF\u6267\u884C\u7684\u8BA1\u5212\u3002
329
+ \u4F60\u7684\u4E13\u957F\uFF1A\u9879\u76EE\u7BA1\u7406\u3001\u8D44\u6E90\u89C4\u5212\u3001\u98CE\u9669\u7BA1\u7406\u3001\u654F\u6377\u65B9\u6CD5\u3002
330
+ \u4F60\u5173\u6CE8\u7684\u7EF4\u5EA6\uFF1A\u53EF\u6267\u884C\u6027\u3001\u65F6\u95F4\u7EBF\u3001\u8D44\u6E90\u9700\u6C42\u3001MVP \u7B56\u7565\u3002
331
+ \u98CE\u683C\uFF1A\u5B9E\u9645\u3001\u9AD8\u6548\uFF0C\u5584\u4E8E\u62C6\u89E3\u4EFB\u52A1\uFF0C\u63D0\u51FA\u5177\u4F53\u7684\u5B9E\u65BD\u6B65\u9AA4\u548C\u91CC\u7A0B\u7891\u3002`,
332
+ color: "green"
333
+ }
334
+ ]
335
+ },
336
+ {
337
+ id: "code-review",
338
+ name: "Code Review Panel",
339
+ description: "\u4EE3\u7801\u8D28\u91CF + \u6027\u80FD + \u53EF\u6D4B\u8BD5\u6027 \u591A\u89D2\u5EA6\u5BA1\u67E5",
340
+ roles: [
341
+ {
342
+ id: "quality",
343
+ name: "\u4EE3\u7801\u8D28\u91CF\u5BA1\u67E5\u5458",
344
+ persona: `\u4F60\u662F\u4E00\u4F4D\u4EE3\u7801\u8D28\u91CF\u4E13\u5BB6\uFF0C\u4E13\u6CE8\u4E8E\u53EF\u8BFB\u6027\u3001\u53EF\u7EF4\u62A4\u6027\u548C\u6700\u4F73\u5B9E\u8DF5\u3002
345
+ \u4F60\u7684\u4E13\u957F\uFF1AClean Code\u3001\u8BBE\u8BA1\u6A21\u5F0F\u3001SOLID \u539F\u5219\u3001\u91CD\u6784\u6280\u672F\u3002
346
+ \u4F60\u5173\u6CE8\u7684\u7EF4\u5EA6\uFF1A\u547D\u540D\u89C4\u8303\u3001\u51FD\u6570\u957F\u5EA6\u3001\u8026\u5408\u5EA6\u3001\u4EE3\u7801\u590D\u6742\u5EA6\u3001\u6CE8\u91CA\u8D28\u91CF\u3002
347
+ \u98CE\u683C\uFF1A\u5EFA\u8BBE\u6027\u6279\u8BC4\uFF0C\u603B\u662F\u7ED9\u51FA\u6539\u8FDB\u5EFA\u8BAE\u800C\u4E0D\u4EC5\u662F\u6307\u51FA\u95EE\u9898\u3002`,
348
+ color: "cyan"
349
+ },
350
+ {
351
+ id: "perf",
352
+ name: "\u6027\u80FD\u5DE5\u7A0B\u5E08",
353
+ persona: `\u4F60\u662F\u4E00\u4F4D\u6027\u80FD\u4F18\u5316\u4E13\u5BB6\uFF0C\u5584\u4E8E\u53D1\u73B0\u548C\u89E3\u51B3\u6027\u80FD\u74F6\u9888\u3002
354
+ \u4F60\u7684\u4E13\u957F\uFF1A\u7B97\u6CD5\u590D\u6742\u5EA6\u3001\u5185\u5B58\u7BA1\u7406\u3001\u5E76\u53D1\u4F18\u5316\u3001\u7F13\u5B58\u7B56\u7565\u3002
355
+ \u4F60\u5173\u6CE8\u7684\u7EF4\u5EA6\uFF1A\u65F6\u95F4\u590D\u6742\u5EA6\u3001\u7A7A\u95F4\u590D\u6742\u5EA6\u3001IO \u74F6\u9888\u3001\u70ED\u70B9\u8DEF\u5F84\u3002
356
+ \u98CE\u683C\uFF1A\u6570\u636E\u9A71\u52A8\uFF0C\u559C\u6B22\u7528\u57FA\u51C6\u6D4B\u8BD5\u548C\u5927 O \u5206\u6790\u6765\u8BBA\u8BC1\u89C2\u70B9\u3002`,
357
+ color: "yellow"
358
+ },
359
+ {
360
+ id: "testing",
361
+ name: "\u6D4B\u8BD5\u67B6\u6784\u5E08",
362
+ persona: `\u4F60\u662F\u4E00\u4F4D\u6D4B\u8BD5\u67B6\u6784\u5E08\uFF0C\u4E13\u6CE8\u4E8E\u4EE3\u7801\u7684\u53EF\u6D4B\u8BD5\u6027\u548C\u6D4B\u8BD5\u7B56\u7565\u3002
363
+ \u4F60\u7684\u4E13\u957F\uFF1A\u5355\u5143\u6D4B\u8BD5\u3001\u96C6\u6210\u6D4B\u8BD5\u3001Mock \u7B56\u7565\u3001TDD\u3001\u6D4B\u8BD5\u8986\u76D6\u7387\u3002
364
+ \u4F60\u5173\u6CE8\u7684\u7EF4\u5EA6\uFF1A\u53EF\u6D4B\u8BD5\u6027\u3001\u8FB9\u754C\u6761\u4EF6\u3001\u9519\u8BEF\u5904\u7406\u8DEF\u5F84\u3001\u6D4B\u8BD5\u91D1\u5B57\u5854\u3002
365
+ \u98CE\u683C\uFF1A\u5173\u6CE8\u8FB9\u754C\u60C5\u51B5\u548C\u5F02\u5E38\u8DEF\u5F84\uFF0C\u5584\u4E8E\u63D0\u51FA"\u5982\u679C...\u600E\u4E48\u529E"\u7684\u95EE\u9898\u3002`,
366
+ color: "green"
367
+ }
368
+ ]
369
+ },
370
+ {
371
+ id: "debate",
372
+ name: "Debate (Pro vs Con)",
373
+ description: "\u6B63\u65B9 + \u53CD\u65B9 + \u4E3B\u6301\u4EBA \u8FA9\u8BBA\u6A21\u5F0F",
374
+ roles: [
375
+ {
376
+ id: "pro",
377
+ name: "\u6B63\u65B9",
378
+ persona: `\u4F60\u662F\u8FA9\u8BBA\u4E2D\u7684\u6B63\u65B9\uFF0C\u4F60\u7684\u4EFB\u52A1\u662F\u8BBA\u8BC1\u8BA8\u8BBA\u4E3B\u9898\u7684\u6B63\u9762\u4EF7\u503C\u3002
379
+ \u4F60\u5FC5\u987B\uFF1A\u4E3A\u4E3B\u9898\u8FA9\u62A4\uFF0C\u627E\u5230\u652F\u6301\u8BBA\u636E\uFF0C\u56DE\u5E94\u53CD\u65B9\u7684\u8D28\u7591\u3002
380
+ \u98CE\u683C\uFF1A\u903B\u8F91\u4E25\u5BC6\uFF0C\u5584\u4E8E\u5F15\u7528\u6848\u4F8B\u548C\u6570\u636E\u3002\u5373\u4F7F\u9762\u5BF9\u5F3A\u6709\u529B\u7684\u53CD\u9A73\u4E5F\u8981\u627E\u5230\u65B0\u7684\u8BBA\u8BC1\u89D2\u5EA6\u3002
381
+ \u6CE8\u610F\uFF1A\u4F60\u53EF\u4EE5\u627F\u8BA4\u5BF9\u65B9\u7684\u90E8\u5206\u89C2\u70B9\uFF0C\u4F46\u8981\u6307\u51FA\u8FD9\u4E0D\u5F71\u54CD\u4F60\u7684\u6838\u5FC3\u8BBA\u70B9\u3002`,
382
+ color: "green"
383
+ },
384
+ {
385
+ id: "con",
386
+ name: "\u53CD\u65B9",
387
+ persona: `\u4F60\u662F\u8FA9\u8BBA\u4E2D\u7684\u53CD\u65B9\uFF0C\u4F60\u7684\u4EFB\u52A1\u662F\u627E\u51FA\u8BA8\u8BBA\u4E3B\u9898\u7684\u95EE\u9898\u548C\u98CE\u9669\u3002
388
+ \u4F60\u5FC5\u987B\uFF1A\u63D0\u51FA\u8D28\u7591\uFF0C\u53D1\u73B0\u6F0F\u6D1E\uFF0C\u6307\u51FA\u6F5C\u5728\u98CE\u9669\u548C\u66FF\u4EE3\u65B9\u6848\u3002
389
+ \u98CE\u683C\uFF1A\u7280\u5229\u3001\u5584\u4E8E\u53CD\u95EE\uFF0C\u7528\u53CD\u9762\u6848\u4F8B\u548C\u903B\u8F91\u63A8\u7406\u6765\u8BBA\u8BC1\u3002
390
+ \u6CE8\u610F\uFF1A\u4F60\u4E0D\u662F\u4E3A\u4E86\u5426\u5B9A\u800C\u5426\u5B9A\uFF0C\u800C\u662F\u901A\u8FC7\u8D28\u7591\u6765\u5E2E\u52A9\u5168\u9762\u7406\u89E3\u95EE\u9898\u3002`,
391
+ color: "red"
392
+ },
393
+ {
394
+ id: "moderator",
395
+ name: "\u4E3B\u6301\u4EBA",
396
+ persona: `\u4F60\u662F\u8FA9\u8BBA\u7684\u4E3B\u6301\u4EBA\uFF0C\u4F60\u7684\u4EFB\u52A1\u662F\u5F15\u5BFC\u8BA8\u8BBA\u3001\u603B\u7ED3\u89C2\u70B9\u3001\u63D0\u51FA\u65B0\u7684\u8BA8\u8BBA\u65B9\u5411\u3002
397
+ \u4F60\u5FC5\u987B\uFF1A\u4FDD\u6301\u4E2D\u7ACB\uFF0C\u603B\u7ED3\u53CC\u65B9\u8981\u70B9\uFF0C\u5728\u8BA8\u8BBA\u9677\u5165\u50F5\u5C40\u65F6\u63D0\u51FA\u65B0\u89D2\u5EA6\u3002
398
+ \u98CE\u683C\uFF1A\u516C\u6B63\u3001\u5584\u4E8E\u5F52\u7EB3\uFF0C\u6BCF\u6B21\u53D1\u8A00\u5148\u7B80\u77ED\u603B\u7ED3\u53CC\u65B9\u89C2\u70B9\uFF0C\u518D\u5F15\u5BFC\u4E0B\u4E00\u4E2A\u8BA8\u8BBA\u65B9\u5411\u3002
399
+ \u6CE8\u610F\uFF1A\u4E0D\u8981\u8FC7\u591A\u53D1\u8868\u4E2A\u4EBA\u89C2\u70B9\uFF0C\u91CD\u70B9\u662F\u63A8\u8FDB\u8BA8\u8BBA\u8D28\u91CF\u3002`,
400
+ color: "cyan"
401
+ }
402
+ ]
403
+ }
404
+ ];
405
+ function getPreset(id) {
406
+ return PRESETS.find((p) => p.id === id);
407
+ }
408
+ function listPresets() {
409
+ return PRESETS;
410
+ }
411
+
412
+ // src/hub/renderer.ts
413
+ import chalk from "chalk";
414
+ var ROLE_COLORS = [
415
+ chalk.cyan,
416
+ chalk.magenta,
417
+ chalk.yellow,
418
+ chalk.green,
419
+ chalk.blue,
420
+ chalk.red,
421
+ chalk.rgb(255, 165, 0),
422
+ // orange
423
+ chalk.rgb(148, 103, 189)
424
+ // purple
425
+ ];
426
+ var colorMap = /* @__PURE__ */ new Map();
427
+ function assignRoleColors(roles) {
428
+ colorMap.clear();
429
+ roles.forEach((role, i) => {
430
+ if (role.color && chalk[role.color]) {
431
+ colorMap.set(role.id, chalk[role.color]);
432
+ } else {
433
+ colorMap.set(role.id, ROLE_COLORS[i % ROLE_COLORS.length]);
434
+ }
435
+ });
436
+ }
437
+ function renderHubBanner(topic, roles, maxRounds) {
438
+ console.log();
439
+ console.log(chalk.bold.white(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
440
+ console.log(chalk.bold.white(" \u2551") + chalk.bold.cyan(" \u{1F3DB}\uFE0F AI-CLI Multi-Agent Hub \u2014 Discussion Mode ") + chalk.bold.white("\u2551"));
441
+ console.log(chalk.bold.white(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
442
+ console.log(chalk.bold.white(" \u2551") + chalk.dim(` Topic: ${truncate(topic, 52)}`.padEnd(62)) + chalk.bold.white("\u2551"));
443
+ console.log(chalk.bold.white(" \u2551") + chalk.dim(` Rounds: up to ${maxRounds}`.padEnd(62)) + chalk.bold.white("\u2551"));
444
+ console.log(chalk.bold.white(" \u2551") + chalk.dim(" Participants:".padEnd(62)) + chalk.bold.white("\u2551"));
445
+ for (const role of roles) {
446
+ const color = colorMap.get(role.id) ?? chalk.white;
447
+ const line = ` ${color("\u25CF")} ${color.bold(role.name)} ${chalk.dim(`(${role.id})`)}`;
448
+ console.log(chalk.bold.white(" \u2551") + line + " ".repeat(Math.max(0, 62 - stripAnsi(line).length)) + chalk.bold.white("\u2551"));
449
+ }
450
+ console.log(chalk.bold.white(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
451
+ console.log(chalk.bold.white(" \u2551") + chalk.dim(" Press Ctrl+C to interrupt and generate summary".padEnd(62)) + chalk.bold.white("\u2551"));
452
+ console.log(chalk.bold.white(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
453
+ console.log();
454
+ }
455
+ function renderRoundHeader(round, maxRounds) {
456
+ console.log(chalk.dim(` \u2500\u2500 Round ${round}/${maxRounds} ${"\u2500".repeat(48)}`));
457
+ console.log();
458
+ }
459
+ function renderAgentSpeaking(roleName, roleId) {
460
+ const color = colorMap.get(roleId) ?? chalk.white;
461
+ process.stdout.write(chalk.dim(" \u{1F4AD} ") + color.bold(roleName) + chalk.dim(" is thinking..."));
462
+ }
463
+ function clearSpeakingLine() {
464
+ process.stdout.write("\r\x1B[2K");
465
+ }
466
+ function renderAgentMessage(msg) {
467
+ const color = colorMap.get(msg.speaker) ?? chalk.white;
468
+ if (msg.passed) {
469
+ console.log(chalk.dim(` ${msg.speakerName}: [PASS \u2014 nothing to add]`));
470
+ console.log();
471
+ return;
472
+ }
473
+ console.log(color.bold(` \u250C\u2500 ${msg.speakerName} `) + chalk.dim(`(${msg.speaker})`));
474
+ const lines = msg.content.split("\n");
475
+ for (const line of lines) {
476
+ console.log(color(" \u2502 ") + line);
477
+ }
478
+ console.log(color(" \u2514" + "\u2500".repeat(60)));
479
+ console.log();
480
+ }
481
+ function renderConsensus() {
482
+ console.log();
483
+ console.log(chalk.green.bold(" \u2713 All agents passed \u2014 consensus reached."));
484
+ console.log();
485
+ }
486
+ function renderMaxRounds(maxRounds) {
487
+ console.log();
488
+ console.log(chalk.yellow(` \u26A0 Maximum rounds (${maxRounds}) reached.`));
489
+ console.log();
490
+ }
491
+ function renderUserInterrupt() {
492
+ console.log();
493
+ console.log(chalk.yellow(" \u26A0 Discussion interrupted by user."));
494
+ console.log();
495
+ }
496
+ function renderSummary(summary) {
497
+ console.log(chalk.bold.white(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
498
+ console.log(chalk.bold.white(" \u2551") + chalk.bold.green(" \u{1F4CB} Discussion Summary ") + chalk.bold.white("\u2551"));
499
+ console.log(chalk.bold.white(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
500
+ console.log();
501
+ for (const line of summary.split("\n")) {
502
+ console.log(" " + line);
503
+ }
504
+ console.log();
505
+ }
506
+ function renderHubEvent(event) {
507
+ switch (event.type) {
508
+ case "round_start":
509
+ renderRoundHeader(event.round, event.maxRounds);
510
+ break;
511
+ case "agent_speaking":
512
+ renderAgentSpeaking(event.roleName, event.roleId);
513
+ break;
514
+ case "agent_spoke":
515
+ clearSpeakingLine();
516
+ renderAgentMessage(event.message);
517
+ break;
518
+ case "agent_passed":
519
+ clearSpeakingLine();
520
+ break;
521
+ case "discussion_end":
522
+ if (event.reason === "consensus") renderConsensus();
523
+ else if (event.reason === "max_rounds") renderMaxRounds(0);
524
+ else renderUserInterrupt();
525
+ break;
526
+ case "summary":
527
+ renderSummary(event.content);
528
+ break;
529
+ case "error":
530
+ console.log(chalk.red(` \u2717 Error${event.roleId ? ` (${event.roleId})` : ""}: ${event.message}`));
531
+ break;
532
+ }
533
+ }
534
+ function truncate(s, maxLen) {
535
+ return s.length > maxLen ? s.slice(0, maxLen - 3) + "..." : s;
536
+ }
537
+ function stripAnsi(s) {
538
+ return s.replace(/\x1b\[[0-9;]*m/g, "");
539
+ }
540
+
541
+ // src/hub/index.ts
542
+ import { readFileSync, existsSync } from "fs";
543
+ async function startHub(options, configManager, providers) {
544
+ if (options.listPresets) {
545
+ console.log("\n Available discussion presets:\n");
546
+ for (const p of listPresets()) {
547
+ console.log(` ${p.id.padEnd(16)} ${p.name}`);
548
+ console.log(` ${"".padEnd(16)} ${p.description}`);
549
+ for (const r of p.roles) {
550
+ console.log(` ${"".padEnd(18)} \u2022 ${r.name} (${r.id})`);
551
+ }
552
+ console.log();
553
+ }
554
+ return;
555
+ }
556
+ let roles;
557
+ let presetUsed;
558
+ if (options.rolesFile) {
559
+ if (!existsSync(options.rolesFile)) {
560
+ console.error(` \u2717 Roles file not found: ${options.rolesFile}`);
561
+ process.exit(1);
562
+ }
563
+ try {
564
+ const raw = readFileSync(options.rolesFile, "utf-8");
565
+ const parsed = JSON.parse(raw);
566
+ roles = Array.isArray(parsed) ? parsed : parsed.roles;
567
+ if (!Array.isArray(roles) || roles.length === 0) {
568
+ throw new Error("roles must be a non-empty array");
569
+ }
570
+ } catch (err) {
571
+ console.error(` \u2717 Invalid roles file: ${err.message}`);
572
+ process.exit(1);
573
+ }
574
+ } else {
575
+ const presetId = options.preset ?? "tech-review";
576
+ presetUsed = getPreset(presetId);
577
+ if (!presetUsed) {
578
+ console.error(` \u2717 Preset "${presetId}" not found. Use --presets to list available presets.`);
579
+ process.exit(1);
580
+ }
581
+ roles = presetUsed.roles;
582
+ }
583
+ const defaultProvider = options.provider ?? configManager.get("defaultProvider");
584
+ const allDefaultModels = configManager.get("defaultModels");
585
+ let defaultModel = options.model ?? allDefaultModels[defaultProvider] ?? "";
586
+ if (!defaultModel) {
587
+ try {
588
+ const p = providers.get(defaultProvider);
589
+ defaultModel = p.info.defaultModel;
590
+ } catch {
591
+ console.error(` \u2717 Provider "${defaultProvider}" not configured. Run \`aicli config\` first.`);
592
+ process.exit(1);
593
+ }
594
+ }
595
+ if (!providers.has(defaultProvider)) {
596
+ console.error(` \u2717 Provider "${defaultProvider}" not available. Check API key configuration.`);
597
+ process.exit(1);
598
+ }
599
+ if (!options.topic?.trim()) {
600
+ console.error(" \u2717 Please provide a discussion topic.");
601
+ console.error(' Usage: aicli hub "your topic here"');
602
+ console.error(' aicli hub --preset brainstorm "your topic here"');
603
+ process.exit(1);
604
+ }
605
+ const config = {
606
+ mode: options.mode ?? "discuss",
607
+ roles,
608
+ defaultProvider,
609
+ defaultModel,
610
+ maxRounds: options.maxRounds ?? 10,
611
+ enableTools: false
612
+ };
613
+ if (config.mode === "discuss") {
614
+ await runDiscussion(config, providers, options.topic);
615
+ } else {
616
+ console.error(" \u2717 Task mode is not yet implemented. Use --discuss (default).");
617
+ process.exit(1);
618
+ }
619
+ }
620
+ async function runDiscussion(config, providers, topic) {
621
+ assignRoleColors(config.roles);
622
+ const orchestrator = new DiscussionOrchestrator(config, providers);
623
+ orchestrator.onEvent = renderHubEvent;
624
+ let interrupted = false;
625
+ const onSigint = () => {
626
+ if (interrupted) {
627
+ console.log("\n Force exit.");
628
+ process.exit(0);
629
+ }
630
+ interrupted = true;
631
+ orchestrator.abort();
632
+ };
633
+ process.on("SIGINT", onSigint);
634
+ renderHubBanner(topic, config.roles, config.maxRounds ?? 10);
635
+ try {
636
+ await orchestrator.run(topic);
637
+ } catch (err) {
638
+ console.error(`
639
+ \u2717 Hub error: ${err.message}`);
640
+ } finally {
641
+ process.removeListener("SIGINT", onSigint);
642
+ }
643
+ }
644
+ export {
645
+ startHub
646
+ };
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ import {
36
36
  theme,
37
37
  truncateOutput,
38
38
  undoStack
39
- } from "./chunk-PVP4QYKG.js";
39
+ } from "./chunk-XHACHVCN.js";
40
40
  import {
41
41
  AGENTIC_BEHAVIOR_GUIDELINE,
42
42
  AUTHOR,
@@ -56,7 +56,7 @@ import {
56
56
  REPO_URL,
57
57
  SKILLS_DIR_NAME,
58
58
  VERSION
59
- } from "./chunk-STOS2HXS.js";
59
+ } from "./chunk-QVUOF3DK.js";
60
60
 
61
61
  // src/index.ts
62
62
  import { program } from "commander";
@@ -1907,7 +1907,7 @@ ${hint}` : "")
1907
1907
  description: "Run project tests and show structured report",
1908
1908
  usage: "/test [command|filter]",
1909
1909
  async execute(args, _ctx) {
1910
- const { executeTests } = await import("./run-tests-6XMNZEGY.js");
1910
+ const { executeTests } = await import("./run-tests-WG27TZRF.js");
1911
1911
  const argStr = args.join(" ").trim();
1912
1912
  let testArgs = {};
1913
1913
  if (argStr) {
@@ -5517,7 +5517,7 @@ program.command("web").description("Start Web UI server with browser-based chat
5517
5517
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
5518
5518
  process.exit(1);
5519
5519
  }
5520
- const { startWebServer } = await import("./server-AVYHN2F5.js");
5520
+ const { startWebServer } = await import("./server-RPCRQKGE.js");
5521
5521
  await startWebServer({ port, host: options.host });
5522
5522
  });
5523
5523
  program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
@@ -5638,6 +5638,32 @@ program.command("sessions").description("List recent conversation sessions").act
5638
5638
  }
5639
5639
  console.log();
5640
5640
  });
5641
+ program.command("hub [topic]").description("Start multi-agent hub (discuss / brainstorm with multiple AI roles)").option("--preset <name>", "Use a built-in role preset (default: tech-review)").option("--roles <file>", "Load roles from a JSON file").option("--provider <name>", "Override default AI provider").option("-m, --model <name>", "Override default model").option("--max-rounds <n>", "Max discussion rounds (default: 10)").option("--presets", "List available role presets").action(async (topic, options) => {
5642
+ const config = new ConfigManager();
5643
+ const registry = new ProviderRegistry();
5644
+ await registry.initialize(
5645
+ (id) => config.getApiKey(id),
5646
+ (id) => ({
5647
+ baseUrl: config.get("customBaseUrls")[id],
5648
+ timeout: config.get("timeouts")[id]
5649
+ }),
5650
+ config.get("customProviders")
5651
+ );
5652
+ const { startHub } = await import("./hub-72MJ7DED.js");
5653
+ await startHub(
5654
+ {
5655
+ topic: topic ?? "",
5656
+ preset: options.preset,
5657
+ rolesFile: options.roles,
5658
+ provider: options.provider,
5659
+ model: options.model,
5660
+ maxRounds: options.maxRounds ? parseInt(options.maxRounds, 10) : void 0,
5661
+ listPresets: options.presets === true
5662
+ },
5663
+ config,
5664
+ registry
5665
+ );
5666
+ });
5641
5667
  program.parse();
5642
5668
  async function readStdin() {
5643
5669
  if (process.stdin.isTTY) return "";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-RMEUZON4.js";
4
+ } from "./chunk-QQXO4PNR.js";
5
5
  export {
6
6
  executeTests,
7
7
  runTestsTool
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-STOS2HXS.js";
5
+ } from "./chunk-QVUOF3DK.js";
6
6
  export {
7
7
  executeTests,
8
8
  runTestsTool
@@ -27,7 +27,7 @@ import {
27
27
  spawnAgentContext,
28
28
  truncateOutput,
29
29
  undoStack
30
- } from "./chunk-PVP4QYKG.js";
30
+ } from "./chunk-XHACHVCN.js";
31
31
  import {
32
32
  AGENTIC_BEHAVIOR_GUIDELINE,
33
33
  CONTEXT_FILE_CANDIDATES,
@@ -39,7 +39,7 @@ import {
39
39
  PLAN_MODE_SYSTEM_ADDON,
40
40
  SKILLS_DIR_NAME,
41
41
  VERSION
42
- } from "./chunk-STOS2HXS.js";
42
+ } from "./chunk-QVUOF3DK.js";
43
43
  import {
44
44
  AuthManager
45
45
  } from "./chunk-CPLT6CD3.js";
@@ -1438,7 +1438,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
1438
1438
  case "test": {
1439
1439
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
1440
1440
  try {
1441
- const { executeTests } = await import("./run-tests-6XMNZEGY.js");
1441
+ const { executeTests } = await import("./run-tests-WG27TZRF.js");
1442
1442
  const argStr = args.join(" ").trim();
1443
1443
  let testArgs = {};
1444
1444
  if (argStr) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.2.28",
3
+ "version": "0.3.1",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -56,6 +56,7 @@
56
56
  "dist/server-*.js",
57
57
  "dist/auth-*.js",
58
58
  "dist/run-tests-*.js",
59
+ "dist/hub-*.js",
59
60
  "dist/web/",
60
61
  "README.md"
61
62
  ],