jinzd-ai-cli 0.4.154 → 0.4.156

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/{batch-W57MV5OT.js → batch-DBOCPVH5.js} +2 -2
  2. package/dist/{chat-index-LUQWWLKO.js → chat-index-2I7ZHRE5.js} +2 -1
  3. package/dist/{chunk-SH7NTECG.js → chunk-3DCAQKVZ.js} +1 -1
  4. package/dist/{chunk-HVNEBTSF.js → chunk-3SQMKA4I.js} +1 -1
  5. package/dist/{chunk-UE26B3RO.js → chunk-3WLEDKOW.js} +1 -1
  6. package/dist/{chunk-2IODI5TI.js → chunk-7OCOFVQP.js} +1 -1
  7. package/dist/{chunk-NP7WOVIH.js → chunk-AACNCJMD.js} +1 -1
  8. package/dist/{chunk-ZAYDVWY4.js → chunk-GQ647SF3.js} +23 -787
  9. package/dist/{chunk-RXM76HB7.js → chunk-MM3F43H6.js} +3 -117
  10. package/dist/chunk-NZ4X6GUC.js +230 -0
  11. package/dist/{chunk-O6MLS5QO.js → chunk-OJL3PY36.js} +0 -226
  12. package/dist/{hub-OP7EWTQQ.js → chunk-Q3ZUDA6S.js} +10 -237
  13. package/dist/chunk-RUJQ5OUB.js +51 -0
  14. package/dist/chunk-SLSWPBK3.js +120 -0
  15. package/dist/chunk-TOTEUETI.js +768 -0
  16. package/dist/{chunk-OSTMMSOV.js → chunk-UAPNBQLU.js} +1 -1
  17. package/dist/{chunk-XWYWASPT.js → chunk-Z2UJDFJK.js} +4 -4
  18. package/dist/{ci-JYZGZSMP.js → ci-AWA6KC3X.js} +3 -3
  19. package/dist/{constants-S4Y6A25E.js → constants-QDTWBWWC.js} +1 -1
  20. package/dist/{doctor-cli-FMTMDO2Z.js → doctor-cli-4MTG6SFH.js} +6 -6
  21. package/dist/electron-server.js +740 -44
  22. package/dist/hub-QRDXG527.js +260 -0
  23. package/dist/{hub-server-OH7AYQIW.js → hub-server-GSTG5MNE.js} +4 -2
  24. package/dist/index.js +50 -44
  25. package/dist/persist-UI6WRBGB.js +12 -0
  26. package/dist/{run-tests-3QAZGHP2.js → run-tests-CNURD2ST.js} +2 -2
  27. package/dist/{run-tests-4XNY7QB4.js → run-tests-NPWSCWP5.js} +1 -1
  28. package/dist/{server-W4TBZN6I.js → server-HFG2SM3Y.js} +6 -5
  29. package/dist/{server-UL42EXOA.js → server-RRUCZMMM.js} +124 -29
  30. package/dist/{task-orchestrator-RLAZK5EB.js → task-orchestrator-GF6ZMNUK.js} +6 -5
  31. package/dist/web/client/app.js +138 -0
  32. package/dist/web/client/index.html +28 -0
  33. package/package.json +1 -1
@@ -1,37 +1,27 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ DiscussionOrchestrator,
4
+ getPreset,
5
+ resolveRoleProviders
6
+ } from "./chunk-Q3ZUDA6S.js";
7
+ import "./chunk-NZ4X6GUC.js";
8
+ import {
9
+ persistDiscussion
10
+ } from "./chunk-RUJQ5OUB.js";
2
11
  import {
3
12
  AuthManager,
4
13
  TOKEN_EXPIRY_MS
5
14
  } from "./chunk-GXB7YKF2.js";
6
15
  import {
7
16
  McpManager,
8
- SessionManager,
9
17
  SkillManager,
10
18
  autoTrimSessionIfNeeded,
11
19
  computeCost,
12
20
  formatCost,
13
- getContentText,
14
21
  loadDevState,
15
22
  persistToolRound,
16
23
  setupProxy
17
- } from "./chunk-ZAYDVWY4.js";
18
- import {
19
- CONTENT_ONLY_STREAM_REMINDER,
20
- HALLUCINATION_CORRECTION_MESSAGE,
21
- ProviderRegistry,
22
- TEE_FINAL_USER_NUDGE,
23
- TOOL_CALL_REMINDER,
24
- detectMetaNarration,
25
- detectPseudoToolCalls,
26
- detectsHallucinatedFileOp,
27
- hadPreviousWriteToolCalls,
28
- looksLikeDocumentBody,
29
- stripPseudoToolCalls,
30
- stripToolCallReminder
31
- } from "./chunk-AIZOARZY.js";
32
- import {
33
- ConfigManager
34
- } from "./chunk-OSTMMSOV.js";
24
+ } from "./chunk-GQ647SF3.js";
35
25
  import {
36
26
  ToolExecutor,
37
27
  ToolRegistry,
@@ -49,16 +39,37 @@ import {
49
39
  spawnAgentContext,
50
40
  truncateOutput,
51
41
  undoStack
52
- } from "./chunk-XWYWASPT.js";
42
+ } from "./chunk-Z2UJDFJK.js";
53
43
  import "./chunk-HDSKW7Q3.js";
54
44
  import "./chunk-ZWVIDFGY.js";
55
- import "./chunk-NP7WOVIH.js";
45
+ import "./chunk-AACNCJMD.js";
46
+ import {
47
+ SessionManager,
48
+ getContentText
49
+ } from "./chunk-TOTEUETI.js";
50
+ import {
51
+ CONTENT_ONLY_STREAM_REMINDER,
52
+ HALLUCINATION_CORRECTION_MESSAGE,
53
+ ProviderRegistry,
54
+ TEE_FINAL_USER_NUDGE,
55
+ TOOL_CALL_REMINDER,
56
+ detectMetaNarration,
57
+ detectPseudoToolCalls,
58
+ detectsHallucinatedFileOp,
59
+ hadPreviousWriteToolCalls,
60
+ looksLikeDocumentBody,
61
+ stripPseudoToolCalls,
62
+ stripToolCallReminder
63
+ } from "./chunk-AIZOARZY.js";
56
64
  import {
57
65
  runTool
58
- } from "./chunk-HVNEBTSF.js";
66
+ } from "./chunk-3SQMKA4I.js";
59
67
  import {
60
68
  getDangerLevel
61
69
  } from "./chunk-NXXNLLSG.js";
70
+ import {
71
+ ConfigManager
72
+ } from "./chunk-UAPNBQLU.js";
62
73
  import "./chunk-2ZD3YTVM.js";
63
74
  import {
64
75
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -78,15 +89,16 @@ import {
78
89
  SKILLS_DIR_NAME,
79
90
  VERSION,
80
91
  buildUserIdentityPrompt
81
- } from "./chunk-UE26B3RO.js";
92
+ } from "./chunk-3WLEDKOW.js";
82
93
  import {
83
94
  formatGitContextForPrompt,
84
95
  getGitContext,
85
96
  getGitRoot
86
97
  } from "./chunk-HOSJZMQS.js";
87
98
  import "./chunk-4BKXL7SM.js";
88
- import "./chunk-RXM76HB7.js";
99
+ import "./chunk-MM3F43H6.js";
89
100
  import "./chunk-KHYD3WXE.js";
101
+ import "./chunk-SLSWPBK3.js";
90
102
  import "./chunk-VNNYHW6N.js";
91
103
  import "./chunk-OVWE4E46.js";
92
104
  import "./chunk-PDX44BCA.js";
@@ -532,6 +544,8 @@ var SessionHandler = class _SessionHandler {
532
544
  abortController = null;
533
545
  userInterjection = null;
534
546
  processing = false;
547
+ /** P4: active hub discussion orchestrator (web room), if any. */
548
+ hubOrchestrator = null;
535
549
  /** Pending ask_user promises */
536
550
  pendingAskUser = /* @__PURE__ */ new Map();
537
551
  /** Pending auto-pause promises */
@@ -670,6 +684,11 @@ var SessionHandler = class _SessionHandler {
670
684
  this.abortController.abort();
671
685
  }
672
686
  return;
687
+ case "hub_start":
688
+ return this.handleHubStart(msg);
689
+ case "hub_abort":
690
+ this.hubOrchestrator?.abort();
691
+ return;
673
692
  case "interjection":
674
693
  this.userInterjection = msg.content;
675
694
  return;
@@ -760,6 +779,82 @@ var SessionHandler = class _SessionHandler {
760
779
  }
761
780
  }
762
781
  // ── Chat handling ────────────────────────────────────────────────
782
+ /**
783
+ * P4: run a multi-agent hub discussion in the browser room. Bridges the
784
+ * UI-agnostic DiscussionOrchestrator (onEvent) to WebSocket hub_event
785
+ * messages, then persists the result (P3) so it can be replayed.
786
+ */
787
+ async handleHubStart(msg) {
788
+ if (this.processing || this.hubOrchestrator) {
789
+ this.send({ type: "error", message: "Already running a request. Abort first." });
790
+ return;
791
+ }
792
+ const topic = (msg.topic ?? "").trim();
793
+ if (!topic) {
794
+ this.send({ type: "error", message: "Hub topic is required." });
795
+ return;
796
+ }
797
+ const preset = getPreset(msg.preset ?? "brainstorm");
798
+ if (!preset) {
799
+ this.send({ type: "error", message: `Unknown preset "${msg.preset}".` });
800
+ return;
801
+ }
802
+ const defaultProvider = this.currentProvider;
803
+ const defaultModel = this.currentModel;
804
+ const resolution = resolveRoleProviders(
805
+ preset.roles,
806
+ {
807
+ has: (id) => this.providers.has(id),
808
+ defaultModelFor: (id) => this.providers.has(id) ? this.providers.get(id).info.defaultModel : void 0
809
+ },
810
+ defaultProvider,
811
+ defaultModel,
812
+ this.providers.listAvailable().map((p) => p.info.id),
813
+ msg.mix
814
+ );
815
+ const roles = resolution.roles;
816
+ for (const w of resolution.warnings) this.send({ type: "info", message: w });
817
+ const config = {
818
+ mode: "discuss",
819
+ roles,
820
+ defaultProvider,
821
+ defaultModel,
822
+ maxRounds: msg.maxRounds && msg.maxRounds > 0 ? Math.min(msg.maxRounds, 20) : 6,
823
+ voteConverge: msg.vote === true
824
+ };
825
+ this.send({
826
+ type: "hub_started",
827
+ topic,
828
+ maxRounds: config.maxRounds,
829
+ roles: roles.map((r) => ({ id: r.id, name: r.name, color: r.color, provider: r.provider, model: r.model }))
830
+ });
831
+ const orchestrator = new DiscussionOrchestrator(config, this.providers);
832
+ this.hubOrchestrator = orchestrator;
833
+ orchestrator.onEvent = (event) => this.send({ type: "hub_event", event });
834
+ this.processing = true;
835
+ try {
836
+ const state = await orchestrator.run(topic);
837
+ let sessionId;
838
+ let saved = false;
839
+ if (state.messages.length > 0) {
840
+ try {
841
+ const res = await persistDiscussion(state, this.config, defaultProvider, defaultModel);
842
+ sessionId = res.id;
843
+ saved = true;
844
+ } catch (err) {
845
+ this.send({ type: "info", message: `Could not save discussion: ${err.message}` });
846
+ }
847
+ }
848
+ this.send({ type: "hub_done", sessionId, saved });
849
+ if (saved) this.sendSessionList();
850
+ } catch (err) {
851
+ this.send({ type: "error", message: `Hub error: ${err.message}` });
852
+ this.send({ type: "hub_done", saved: false });
853
+ } finally {
854
+ this.processing = false;
855
+ this.hubOrchestrator = null;
856
+ }
857
+ }
763
858
  async handleChat(content, images) {
764
859
  if (this.processing) {
765
860
  this.send({ type: "error", message: "Already processing a request. Use abort first." });
@@ -2462,7 +2557,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
2462
2557
  case "test": {
2463
2558
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
2464
2559
  try {
2465
- const { executeTests } = await import("./run-tests-3QAZGHP2.js");
2560
+ const { executeTests } = await import("./run-tests-CNURD2ST.js");
2466
2561
  const argStr = args.join(" ").trim();
2467
2562
  let testArgs = {};
2468
2563
  if (argStr) {
@@ -2986,7 +3081,7 @@ Add .md files to create commands.` });
2986
3081
  return;
2987
3082
  }
2988
3083
  try {
2989
- const { searchChatMemory, loadChatIndex } = await import("./chat-index-LUQWWLKO.js");
3084
+ const { searchChatMemory, loadChatIndex } = await import("./chat-index-2I7ZHRE5.js");
2990
3085
  const loaded = loadChatIndex();
2991
3086
  if (!loaded || loaded.idx.chunks.length === 0) {
2992
3087
  this.send({ type: "memory_hits", query: q, hits: [], indexMissing: true });
@@ -3022,7 +3117,7 @@ Add .md files to create commands.` });
3022
3117
  }
3023
3118
  async handleMemoryStatus() {
3024
3119
  try {
3025
- const { getChatIndexStatus } = await import("./chat-index-LUQWWLKO.js");
3120
+ const { getChatIndexStatus } = await import("./chat-index-2I7ZHRE5.js");
3026
3121
  const s = getChatIndexStatus();
3027
3122
  this.send({
3028
3123
  type: "memory_status",
@@ -3047,7 +3142,7 @@ Add .md files to create commands.` });
3047
3142
  type: "info",
3048
3143
  message: full ? "\u{1F9E0} Rebuilding chat memory index (this may take a while on first run \u2014 ~117 MB embedder)." : "\u{1F9E0} Refreshing chat memory index (incremental)\u2026"
3049
3144
  });
3050
- const { buildChatIndex } = await import("./chat-index-LUQWWLKO.js");
3145
+ const { buildChatIndex } = await import("./chat-index-2I7ZHRE5.js");
3051
3146
  const stats = await buildChatIndex({
3052
3147
  full,
3053
3148
  onProgress: (p) => {
@@ -3,23 +3,24 @@ import {
3
3
  ToolRegistry,
4
4
  googleSearchContext,
5
5
  truncateOutput
6
- } from "./chunk-XWYWASPT.js";
6
+ } from "./chunk-Z2UJDFJK.js";
7
7
  import "./chunk-HDSKW7Q3.js";
8
8
  import "./chunk-ZWVIDFGY.js";
9
- import "./chunk-NP7WOVIH.js";
9
+ import "./chunk-AACNCJMD.js";
10
10
  import {
11
11
  runTool
12
- } from "./chunk-HVNEBTSF.js";
12
+ } from "./chunk-3SQMKA4I.js";
13
13
  import {
14
14
  getDangerLevel
15
15
  } from "./chunk-NXXNLLSG.js";
16
16
  import "./chunk-2ZD3YTVM.js";
17
17
  import {
18
18
  SUBAGENT_ALLOWED_TOOLS
19
- } from "./chunk-UE26B3RO.js";
19
+ } from "./chunk-3WLEDKOW.js";
20
20
  import "./chunk-4BKXL7SM.js";
21
- import "./chunk-RXM76HB7.js";
21
+ import "./chunk-MM3F43H6.js";
22
22
  import "./chunk-KHYD3WXE.js";
23
+ import "./chunk-SLSWPBK3.js";
23
24
  import "./chunk-VNNYHW6N.js";
24
25
  import "./chunk-OVWE4E46.js";
25
26
  import "./chunk-PDX44BCA.js";
@@ -199,6 +199,9 @@ function handleServerMessage(msg) {
199
199
  case 'memory_rebuild_done': renderMemoryRebuildDone(msg); break;
200
200
  case 'auth_required': showAuthScreen(msg.hasUsers); break;
201
201
  case 'auth_result': handleAuthResult(msg); break;
202
+ case 'hub_started': hubStarted(msg); break;
203
+ case 'hub_event': hubEvent(msg.event); break;
204
+ case 'hub_done': hubDone(msg); break;
202
205
  case 'info': addInfoMessage(msg.message); break;
203
206
  case 'error': addErrorMessage(msg.message); hideRoundProgress(); clearAllToolTimers(); setProcessing(false); break;
204
207
  case 'round_progress': handleRoundProgress(msg); break;
@@ -3109,3 +3112,138 @@ document.querySelectorAll('.sidebar-tab').forEach(btn => {
3109
3112
  btn.addEventListener('click', () => initMemoryPanel());
3110
3113
  }
3111
3114
  });
3115
+
3116
+ // ── Hub multi-agent room (P4) ─────────────────────────────────────
3117
+ // DaisyUI semantic colors map for role legend dots / borders.
3118
+ const HUB_COLORS = { cyan: '#22d3ee', green: '#4ade80', red: '#f87171', magenta: '#e879f9', yellow: '#facc15', blue: '#60a5fa', white: '#e5e7eb' };
3119
+ let hubRoles = {}; // roleId → { name, color, provider, model }
3120
+ let hubStreamEl = null; // current streaming agent message element
3121
+ let hubStreamRoleId = null;
3122
+
3123
+ function hubColor(c) { return HUB_COLORS[c] || '#9ca3af'; }
3124
+
3125
+ window.startHub = function () {
3126
+ const topic = (document.getElementById('hub-topic').value || '').trim();
3127
+ if (!topic) { document.getElementById('hub-status').textContent = 'Enter a topic first.'; return; }
3128
+ send({
3129
+ type: 'hub_start',
3130
+ topic,
3131
+ preset: document.getElementById('hub-preset').value,
3132
+ maxRounds: parseInt(document.getElementById('hub-rounds').value, 10) || 6,
3133
+ mix: document.getElementById('hub-mix').checked,
3134
+ vote: document.getElementById('hub-vote').checked,
3135
+ });
3136
+ document.getElementById('hub-start-btn').classList.add('hidden');
3137
+ document.getElementById('hub-abort-btn').classList.remove('hidden');
3138
+ document.getElementById('hub-status').textContent = 'Starting…';
3139
+ };
3140
+
3141
+ window.abortHub = function () {
3142
+ send({ type: 'hub_abort' });
3143
+ document.getElementById('hub-status').textContent = 'Stopping after current turn…';
3144
+ };
3145
+
3146
+ function hubStarted(msg) {
3147
+ hubRoles = {};
3148
+ for (const r of msg.roles) hubRoles[r.id] = r;
3149
+ hubStreamEl = null; hubStreamRoleId = null;
3150
+
3151
+ const legend = msg.roles.map(r => {
3152
+ const backend = r.provider ? `${r.provider}${r.model ? ':' + r.model : ''}` : '';
3153
+ return `<span class="inline-flex items-center gap-1 mr-2">
3154
+ <span style="width:.6rem;height:.6rem;border-radius:9999px;background:${hubColor(r.color)};display:inline-block"></span>
3155
+ <b>${escapeHtml(r.name)}</b><span class="opacity-50">${backend ? ' · ' + escapeHtml(backend) : ''}</span></span>`;
3156
+ }).join('');
3157
+
3158
+ const el = document.createElement('div');
3159
+ el.className = 'hub-banner border border-base-content/10 rounded-lg p-3 my-2 bg-base-200';
3160
+ el.innerHTML = `<div class="font-bold mb-1">🏛 ${escapeHtml(msg.topic)}</div>
3161
+ <div class="text-xs opacity-70 mb-1">up to ${msg.maxRounds} rounds</div>
3162
+ <div class="text-xs">${legend}</div>`;
3163
+ messagesEl.appendChild(el);
3164
+ scrollToBottom();
3165
+ }
3166
+
3167
+ function hubEvent(ev) {
3168
+ switch (ev.type) {
3169
+ case 'round_start': {
3170
+ const el = document.createElement('div');
3171
+ el.className = 'hub-round text-xs opacity-50 text-center my-2';
3172
+ el.textContent = `── Round ${ev.round}/${ev.maxRounds} ──`;
3173
+ messagesEl.appendChild(el);
3174
+ scrollToBottom();
3175
+ break;
3176
+ }
3177
+ case 'agent_token': {
3178
+ if (hubStreamRoleId !== ev.roleId || !hubStreamEl) {
3179
+ const role = hubRoles[ev.roleId] || { name: ev.roleId, color: 'white' };
3180
+ hubStreamEl = document.createElement('div');
3181
+ hubStreamEl.className = 'hub-msg border-l-2 pl-2 my-2';
3182
+ hubStreamEl.style.borderColor = hubColor(role.color);
3183
+ hubStreamEl.innerHTML = `<div class="text-xs font-bold mb-1" style="color:${hubColor(role.color)}">${escapeHtml(role.name)}</div><div class="hub-body text-sm"></div>`;
3184
+ messagesEl.appendChild(hubStreamEl);
3185
+ hubStreamRoleId = ev.roleId;
3186
+ hubStreamEl._raw = '';
3187
+ }
3188
+ hubStreamEl._raw += ev.token;
3189
+ renderMarkdown(hubStreamEl.querySelector('.hub-body'), hubStreamEl._raw);
3190
+ scrollToBottom();
3191
+ break;
3192
+ }
3193
+ case 'agent_spoke':
3194
+ // Streaming already rendered the body; finalize the stream slot.
3195
+ hubStreamEl = null; hubStreamRoleId = null;
3196
+ break;
3197
+ case 'agent_passed': {
3198
+ const role = hubRoles[ev.roleId] || { name: ev.roleId };
3199
+ const el = document.createElement('div');
3200
+ el.className = 'text-xs opacity-40 italic pl-2 my-1';
3201
+ el.textContent = `${role.name} passed`;
3202
+ messagesEl.appendChild(el);
3203
+ hubStreamEl = null; hubStreamRoleId = null;
3204
+ break;
3205
+ }
3206
+ case 'converge_vote': {
3207
+ const el = document.createElement('div');
3208
+ el.className = 'text-xs text-center opacity-60 my-1';
3209
+ el.textContent = `🗳 Convergence vote: ${ev.converged}/${ev.total} marked [CONVERGED]`;
3210
+ messagesEl.appendChild(el);
3211
+ break;
3212
+ }
3213
+ case 'discussion_end': {
3214
+ const labels = { consensus: 'Consensus reached', vote_converged: '✓ Converged by vote', max_rounds: 'Max rounds reached', human_stop: 'Stopped', user_interrupt: 'Interrupted' };
3215
+ const el = document.createElement('div');
3216
+ el.className = 'text-xs text-center font-semibold my-2 text-success';
3217
+ el.textContent = labels[ev.reason] || ev.reason;
3218
+ messagesEl.appendChild(el);
3219
+ break;
3220
+ }
3221
+ case 'summary': {
3222
+ const el = document.createElement('div');
3223
+ el.className = 'hub-summary border border-success/40 rounded-lg p-3 my-2 bg-success/5';
3224
+ el.innerHTML = `<div class="font-bold mb-1">📋 Summary</div><div class="hub-body text-sm"></div>`;
3225
+ messagesEl.appendChild(el);
3226
+ renderMarkdown(el.querySelector('.hub-body'), ev.content);
3227
+ scrollToBottom();
3228
+ break;
3229
+ }
3230
+ case 'error': {
3231
+ addErrorMessage(`Hub${ev.roleId ? ' (' + ev.roleId + ')' : ''}: ${ev.message}`);
3232
+ hubStreamEl = null; hubStreamRoleId = null;
3233
+ break;
3234
+ }
3235
+ }
3236
+ }
3237
+
3238
+ function hubDone(msg) {
3239
+ document.getElementById('hub-start-btn').classList.remove('hidden');
3240
+ document.getElementById('hub-abort-btn').classList.add('hidden');
3241
+ const status = document.getElementById('hub-status');
3242
+ if (msg.saved && msg.sessionId) {
3243
+ status.innerHTML = `Saved. <a class="link link-primary" onclick="send({type:'command',name:'session',args:['load','${msg.sessionId}']})">Open session</a>`;
3244
+ } else {
3245
+ status.textContent = msg.saved ? 'Saved to history.' : 'Done (not saved).';
3246
+ }
3247
+ hubStreamEl = null; hubStreamRoleId = null;
3248
+ scrollToBottom();
3249
+ }
@@ -186,6 +186,34 @@
186
186
  <div class="text-xs opacity-40 text-center py-4">Type a query above to recall past chats.</div>
187
187
  </div>
188
188
  </div>
189
+
190
+ <!-- Hub tab (P4) — multi-agent brainstorm room -->
191
+ <div id="tab-hub" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
192
+ <div class="p-2 flex flex-col gap-2 overflow-y-auto">
193
+ <p class="text-xs opacity-60 leading-snug">Several AI agents discuss a topic in the chat area, then a structured summary is saved to history (open it and hit 🎬 to replay).</p>
194
+ <textarea id="hub-topic" class="textarea textarea-bordered textarea-sm w-full" rows="2" placeholder="Discussion topic…"></textarea>
195
+ <label class="text-xs opacity-70">Preset
196
+ <select id="hub-preset" class="select select-bordered select-xs w-full mt-1">
197
+ <option value="brainstorm">brainstorm — 创意者·分析师·执行者</option>
198
+ <option value="tech-review">tech-review — 架构师·开发者·安全</option>
199
+ <option value="code-review">code-review — 质量·性能·测试</option>
200
+ <option value="debate">debate — 正方·反方·主持人</option>
201
+ </select>
202
+ </label>
203
+ <label class="text-xs opacity-70">Max rounds
204
+ <input id="hub-rounds" type="number" min="1" max="20" value="6" class="input input-bordered input-xs w-full mt-1">
205
+ </label>
206
+ <label class="flex items-center gap-2 text-xs cursor-pointer">
207
+ <input id="hub-mix" type="checkbox" class="checkbox checkbox-xs"> Mix providers (Claude vs GPT vs DeepSeek…)
208
+ </label>
209
+ <label class="flex items-center gap-2 text-xs cursor-pointer">
210
+ <input id="hub-vote" type="checkbox" class="checkbox checkbox-xs" checked> Convergence voting (2/3 ends early)
211
+ </label>
212
+ <button id="hub-start-btn" class="btn btn-primary btn-sm w-full" onclick="startHub()">🏛 Start discussion</button>
213
+ <button id="hub-abort-btn" class="btn btn-error btn-outline btn-xs w-full hidden" onclick="abortHub()">⏹ Stop</button>
214
+ <div id="hub-status" class="text-xs opacity-60"></div>
215
+ </div>
216
+ </div>
189
217
  </aside>
190
218
  <!-- Sidebar resize handle -->
191
219
  <div id="sidebar-resize" class="sidebar-resize-handle" title="Drag to resize sidebar"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.154",
3
+ "version": "0.4.156",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",