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.
- package/dist/{batch-W57MV5OT.js → batch-DBOCPVH5.js} +2 -2
- package/dist/{chat-index-LUQWWLKO.js → chat-index-2I7ZHRE5.js} +2 -1
- package/dist/{chunk-SH7NTECG.js → chunk-3DCAQKVZ.js} +1 -1
- package/dist/{chunk-HVNEBTSF.js → chunk-3SQMKA4I.js} +1 -1
- package/dist/{chunk-UE26B3RO.js → chunk-3WLEDKOW.js} +1 -1
- package/dist/{chunk-2IODI5TI.js → chunk-7OCOFVQP.js} +1 -1
- package/dist/{chunk-NP7WOVIH.js → chunk-AACNCJMD.js} +1 -1
- package/dist/{chunk-ZAYDVWY4.js → chunk-GQ647SF3.js} +23 -787
- package/dist/{chunk-RXM76HB7.js → chunk-MM3F43H6.js} +3 -117
- package/dist/chunk-NZ4X6GUC.js +230 -0
- package/dist/{chunk-O6MLS5QO.js → chunk-OJL3PY36.js} +0 -226
- package/dist/{hub-OP7EWTQQ.js → chunk-Q3ZUDA6S.js} +10 -237
- package/dist/chunk-RUJQ5OUB.js +51 -0
- package/dist/chunk-SLSWPBK3.js +120 -0
- package/dist/chunk-TOTEUETI.js +768 -0
- package/dist/{chunk-OSTMMSOV.js → chunk-UAPNBQLU.js} +1 -1
- package/dist/{chunk-XWYWASPT.js → chunk-Z2UJDFJK.js} +4 -4
- package/dist/{ci-JYZGZSMP.js → ci-AWA6KC3X.js} +3 -3
- package/dist/{constants-S4Y6A25E.js → constants-QDTWBWWC.js} +1 -1
- package/dist/{doctor-cli-FMTMDO2Z.js → doctor-cli-4MTG6SFH.js} +6 -6
- package/dist/electron-server.js +740 -44
- package/dist/hub-QRDXG527.js +260 -0
- package/dist/{hub-server-OH7AYQIW.js → hub-server-GSTG5MNE.js} +4 -2
- package/dist/index.js +50 -44
- package/dist/persist-UI6WRBGB.js +12 -0
- package/dist/{run-tests-3QAZGHP2.js → run-tests-CNURD2ST.js} +2 -2
- package/dist/{run-tests-4XNY7QB4.js → run-tests-NPWSCWP5.js} +1 -1
- package/dist/{server-W4TBZN6I.js → server-HFG2SM3Y.js} +6 -5
- package/dist/{server-UL42EXOA.js → server-RRUCZMMM.js} +124 -29
- package/dist/{task-orchestrator-RLAZK5EB.js → task-orchestrator-GF6ZMNUK.js} +6 -5
- package/dist/web/client/app.js +138 -0
- package/dist/web/client/index.html +28 -0
- 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-
|
|
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-
|
|
42
|
+
} from "./chunk-Z2UJDFJK.js";
|
|
53
43
|
import "./chunk-HDSKW7Q3.js";
|
|
54
44
|
import "./chunk-ZWVIDFGY.js";
|
|
55
|
-
import "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
6
|
+
} from "./chunk-Z2UJDFJK.js";
|
|
7
7
|
import "./chunk-HDSKW7Q3.js";
|
|
8
8
|
import "./chunk-ZWVIDFGY.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-AACNCJMD.js";
|
|
10
10
|
import {
|
|
11
11
|
runTool
|
|
12
|
-
} from "./chunk-
|
|
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-
|
|
19
|
+
} from "./chunk-3WLEDKOW.js";
|
|
20
20
|
import "./chunk-4BKXL7SM.js";
|
|
21
|
-
import "./chunk-
|
|
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";
|
package/dist/web/client/app.js
CHANGED
|
@@ -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>
|