jinzd-ai-cli 0.4.155 → 0.4.157
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-LS3IJVBK.js → batch-ATL6V3UE.js} +2 -2
- package/dist/{chat-index-IF4EINLQ.js → chat-index-2I7ZHRE5.js} +2 -2
- package/dist/{chunk-E5ICQT3P.js → chunk-3HJW556L.js} +4 -4
- package/dist/{chunk-JOJRBV2K.js → chunk-62CD2T5F.js} +1 -1
- package/dist/{chunk-D6GJTJQH.js → chunk-77DDRYFM.js} +1 -1
- package/dist/{chunk-CIZQZ7CC.js → chunk-A4JROOGF.js} +2 -2
- package/dist/{chunk-NFRTSL3N.js → chunk-GRFQ2QD5.js} +1 -1
- package/dist/{chunk-JXSWY54M.js → chunk-LLQMVGNP.js} +1 -1
- package/dist/{chunk-B3LFGPU2.js → chunk-N3VGZTEJ.js} +1 -1
- package/dist/chunk-NZ4X6GUC.js +230 -0
- package/dist/{chunk-O6MLS5QO.js → chunk-OJL3PY36.js} +0 -226
- package/dist/{hub-ZILVZWI2.js → chunk-Q3ZUDA6S.js} +6 -249
- package/dist/{persist-3EBOLHFZ.js → chunk-RUJQ5OUB.js} +1 -2
- package/dist/{chunk-IBBYW6PM.js → chunk-V5OQOKU3.js} +1 -1
- package/dist/{ci-34ZQH43L.js → ci-E7MDZSB6.js} +3 -3
- package/dist/{constants-DQ5VJOGS.js → constants-NL5ETRA5.js} +1 -1
- package/dist/{doctor-cli-TSCI4ORL.js → doctor-cli-XJNT745O.js} +6 -6
- package/dist/electron-server.js +758 -44
- package/dist/hub-RXZ5IDBY.js +260 -0
- package/dist/{hub-server-OH7AYQIW.js → hub-server-GSTG5MNE.js} +4 -2
- package/dist/index.js +40 -40
- package/dist/persist-UI6WRBGB.js +12 -0
- package/dist/{run-tests-5KWCHBQS.js → run-tests-I3EBH7O6.js} +2 -2
- package/dist/{run-tests-5CJRMOMI.js → run-tests-O46AI32W.js} +1 -1
- package/dist/{server-35OQV62B.js → server-4PJJHZWM.js} +142 -32
- package/dist/{server-DVIP7NLW.js → server-SVBHOHTC.js} +6 -6
- package/dist/{task-orchestrator-AXSS7ROD.js → task-orchestrator-NMX3CYW2.js} +6 -6
- package/dist/web/client/app.js +173 -0
- package/dist/web/client/index.html +31 -0
- package/package.json +1 -1
- package/dist/{chunk-U5MY24UZ.js → chunk-MM3F43H6.js} +3 -3
|
@@ -1,4 +1,13 @@
|
|
|
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
|
|
@@ -12,28 +21,7 @@ import {
|
|
|
12
21
|
loadDevState,
|
|
13
22
|
persistToolRound,
|
|
14
23
|
setupProxy
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import {
|
|
17
|
-
SessionManager,
|
|
18
|
-
getContentText
|
|
19
|
-
} from "./chunk-TOTEUETI.js";
|
|
20
|
-
import {
|
|
21
|
-
CONTENT_ONLY_STREAM_REMINDER,
|
|
22
|
-
HALLUCINATION_CORRECTION_MESSAGE,
|
|
23
|
-
ProviderRegistry,
|
|
24
|
-
TEE_FINAL_USER_NUDGE,
|
|
25
|
-
TOOL_CALL_REMINDER,
|
|
26
|
-
detectMetaNarration,
|
|
27
|
-
detectPseudoToolCalls,
|
|
28
|
-
detectsHallucinatedFileOp,
|
|
29
|
-
hadPreviousWriteToolCalls,
|
|
30
|
-
looksLikeDocumentBody,
|
|
31
|
-
stripPseudoToolCalls,
|
|
32
|
-
stripToolCallReminder
|
|
33
|
-
} from "./chunk-AIZOARZY.js";
|
|
34
|
-
import {
|
|
35
|
-
ConfigManager
|
|
36
|
-
} from "./chunk-IBBYW6PM.js";
|
|
24
|
+
} from "./chunk-A4JROOGF.js";
|
|
37
25
|
import {
|
|
38
26
|
ToolExecutor,
|
|
39
27
|
ToolRegistry,
|
|
@@ -51,16 +39,37 @@ import {
|
|
|
51
39
|
spawnAgentContext,
|
|
52
40
|
truncateOutput,
|
|
53
41
|
undoStack
|
|
54
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-3HJW556L.js";
|
|
55
43
|
import "./chunk-HDSKW7Q3.js";
|
|
56
44
|
import "./chunk-ZWVIDFGY.js";
|
|
57
|
-
import "./chunk-
|
|
45
|
+
import "./chunk-62CD2T5F.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";
|
|
58
64
|
import {
|
|
59
65
|
runTool
|
|
60
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-GRFQ2QD5.js";
|
|
61
67
|
import {
|
|
62
68
|
getDangerLevel
|
|
63
69
|
} from "./chunk-NXXNLLSG.js";
|
|
70
|
+
import {
|
|
71
|
+
ConfigManager
|
|
72
|
+
} from "./chunk-V5OQOKU3.js";
|
|
64
73
|
import "./chunk-2ZD3YTVM.js";
|
|
65
74
|
import {
|
|
66
75
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
@@ -80,16 +89,16 @@ import {
|
|
|
80
89
|
SKILLS_DIR_NAME,
|
|
81
90
|
VERSION,
|
|
82
91
|
buildUserIdentityPrompt
|
|
83
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-N3VGZTEJ.js";
|
|
84
93
|
import {
|
|
85
94
|
formatGitContextForPrompt,
|
|
86
95
|
getGitContext,
|
|
87
96
|
getGitRoot
|
|
88
97
|
} from "./chunk-HOSJZMQS.js";
|
|
89
98
|
import "./chunk-4BKXL7SM.js";
|
|
90
|
-
import "./chunk-
|
|
91
|
-
import "./chunk-SLSWPBK3.js";
|
|
99
|
+
import "./chunk-MM3F43H6.js";
|
|
92
100
|
import "./chunk-KHYD3WXE.js";
|
|
101
|
+
import "./chunk-SLSWPBK3.js";
|
|
93
102
|
import "./chunk-VNNYHW6N.js";
|
|
94
103
|
import "./chunk-OVWE4E46.js";
|
|
95
104
|
import "./chunk-PDX44BCA.js";
|
|
@@ -535,6 +544,10 @@ var SessionHandler = class _SessionHandler {
|
|
|
535
544
|
abortController = null;
|
|
536
545
|
userInterjection = null;
|
|
537
546
|
processing = false;
|
|
547
|
+
/** P4: active hub discussion orchestrator (web room), if any. */
|
|
548
|
+
hubOrchestrator = null;
|
|
549
|
+
/** P4b: pending between-rounds human-steer prompts (requestId → resolver). */
|
|
550
|
+
pendingHubReview = /* @__PURE__ */ new Map();
|
|
538
551
|
/** Pending ask_user promises */
|
|
539
552
|
pendingAskUser = /* @__PURE__ */ new Map();
|
|
540
553
|
/** Pending auto-pause promises */
|
|
@@ -673,6 +686,19 @@ var SessionHandler = class _SessionHandler {
|
|
|
673
686
|
this.abortController.abort();
|
|
674
687
|
}
|
|
675
688
|
return;
|
|
689
|
+
case "hub_start":
|
|
690
|
+
return this.handleHubStart(msg);
|
|
691
|
+
case "hub_abort":
|
|
692
|
+
this.hubOrchestrator?.abort();
|
|
693
|
+
return;
|
|
694
|
+
case "hub_steer": {
|
|
695
|
+
const resolve3 = this.pendingHubReview.get(msg.requestId);
|
|
696
|
+
if (resolve3) {
|
|
697
|
+
this.pendingHubReview.delete(msg.requestId);
|
|
698
|
+
resolve3({ action: msg.action, message: msg.message });
|
|
699
|
+
}
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
676
702
|
case "interjection":
|
|
677
703
|
this.userInterjection = msg.content;
|
|
678
704
|
return;
|
|
@@ -763,6 +789,90 @@ var SessionHandler = class _SessionHandler {
|
|
|
763
789
|
}
|
|
764
790
|
}
|
|
765
791
|
// ── Chat handling ────────────────────────────────────────────────
|
|
792
|
+
/**
|
|
793
|
+
* P4: run a multi-agent hub discussion in the browser room. Bridges the
|
|
794
|
+
* UI-agnostic DiscussionOrchestrator (onEvent) to WebSocket hub_event
|
|
795
|
+
* messages, then persists the result (P3) so it can be replayed.
|
|
796
|
+
*/
|
|
797
|
+
async handleHubStart(msg) {
|
|
798
|
+
if (this.processing || this.hubOrchestrator) {
|
|
799
|
+
this.send({ type: "error", message: "Already running a request. Abort first." });
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
const topic = (msg.topic ?? "").trim();
|
|
803
|
+
if (!topic) {
|
|
804
|
+
this.send({ type: "error", message: "Hub topic is required." });
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
const preset = getPreset(msg.preset ?? "brainstorm");
|
|
808
|
+
if (!preset) {
|
|
809
|
+
this.send({ type: "error", message: `Unknown preset "${msg.preset}".` });
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
const defaultProvider = this.currentProvider;
|
|
813
|
+
const defaultModel = this.currentModel;
|
|
814
|
+
const resolution = resolveRoleProviders(
|
|
815
|
+
preset.roles,
|
|
816
|
+
{
|
|
817
|
+
has: (id) => this.providers.has(id),
|
|
818
|
+
defaultModelFor: (id) => this.providers.has(id) ? this.providers.get(id).info.defaultModel : void 0
|
|
819
|
+
},
|
|
820
|
+
defaultProvider,
|
|
821
|
+
defaultModel,
|
|
822
|
+
this.providers.listAvailable().map((p) => p.info.id),
|
|
823
|
+
msg.mix
|
|
824
|
+
);
|
|
825
|
+
const roles = resolution.roles;
|
|
826
|
+
for (const w of resolution.warnings) this.send({ type: "info", message: w });
|
|
827
|
+
const config = {
|
|
828
|
+
mode: "discuss",
|
|
829
|
+
roles,
|
|
830
|
+
defaultProvider,
|
|
831
|
+
defaultModel,
|
|
832
|
+
maxRounds: msg.maxRounds && msg.maxRounds > 0 ? Math.min(msg.maxRounds, 20) : 6,
|
|
833
|
+
voteConverge: msg.vote === true,
|
|
834
|
+
humanSteer: msg.steer === true
|
|
835
|
+
};
|
|
836
|
+
this.send({
|
|
837
|
+
type: "hub_started",
|
|
838
|
+
topic,
|
|
839
|
+
maxRounds: config.maxRounds,
|
|
840
|
+
roles: roles.map((r) => ({ id: r.id, name: r.name, color: r.color, provider: r.provider, model: r.model }))
|
|
841
|
+
});
|
|
842
|
+
const orchestrator = new DiscussionOrchestrator(config, this.providers);
|
|
843
|
+
this.hubOrchestrator = orchestrator;
|
|
844
|
+
orchestrator.onEvent = (event) => this.send({ type: "hub_event", event });
|
|
845
|
+
if (config.humanSteer) {
|
|
846
|
+
orchestrator.onRoundReview = ({ round, maxRounds }) => new Promise((resolve3) => {
|
|
847
|
+
const requestId = `hubrev_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
848
|
+
this.pendingHubReview.set(requestId, resolve3);
|
|
849
|
+
this.send({ type: "hub_review", requestId, round, maxRounds });
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
this.processing = true;
|
|
853
|
+
try {
|
|
854
|
+
const state = await orchestrator.run(topic);
|
|
855
|
+
let sessionId;
|
|
856
|
+
let saved = false;
|
|
857
|
+
if (state.messages.length > 0) {
|
|
858
|
+
try {
|
|
859
|
+
const res = await persistDiscussion(state, this.config, defaultProvider, defaultModel);
|
|
860
|
+
sessionId = res.id;
|
|
861
|
+
saved = true;
|
|
862
|
+
} catch (err) {
|
|
863
|
+
this.send({ type: "info", message: `Could not save discussion: ${err.message}` });
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
this.send({ type: "hub_done", sessionId, saved });
|
|
867
|
+
if (saved) this.sendSessionList();
|
|
868
|
+
} catch (err) {
|
|
869
|
+
this.send({ type: "error", message: `Hub error: ${err.message}` });
|
|
870
|
+
this.send({ type: "hub_done", saved: false });
|
|
871
|
+
} finally {
|
|
872
|
+
this.processing = false;
|
|
873
|
+
this.hubOrchestrator = null;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
766
876
|
async handleChat(content, images) {
|
|
767
877
|
if (this.processing) {
|
|
768
878
|
this.send({ type: "error", message: "Already processing a request. Use abort first." });
|
|
@@ -2465,7 +2575,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2465
2575
|
case "test": {
|
|
2466
2576
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
2467
2577
|
try {
|
|
2468
|
-
const { executeTests } = await import("./run-tests-
|
|
2578
|
+
const { executeTests } = await import("./run-tests-I3EBH7O6.js");
|
|
2469
2579
|
const argStr = args.join(" ").trim();
|
|
2470
2580
|
let testArgs = {};
|
|
2471
2581
|
if (argStr) {
|
|
@@ -2989,7 +3099,7 @@ Add .md files to create commands.` });
|
|
|
2989
3099
|
return;
|
|
2990
3100
|
}
|
|
2991
3101
|
try {
|
|
2992
|
-
const { searchChatMemory, loadChatIndex } = await import("./chat-index-
|
|
3102
|
+
const { searchChatMemory, loadChatIndex } = await import("./chat-index-2I7ZHRE5.js");
|
|
2993
3103
|
const loaded = loadChatIndex();
|
|
2994
3104
|
if (!loaded || loaded.idx.chunks.length === 0) {
|
|
2995
3105
|
this.send({ type: "memory_hits", query: q, hits: [], indexMissing: true });
|
|
@@ -3025,7 +3135,7 @@ Add .md files to create commands.` });
|
|
|
3025
3135
|
}
|
|
3026
3136
|
async handleMemoryStatus() {
|
|
3027
3137
|
try {
|
|
3028
|
-
const { getChatIndexStatus } = await import("./chat-index-
|
|
3138
|
+
const { getChatIndexStatus } = await import("./chat-index-2I7ZHRE5.js");
|
|
3029
3139
|
const s = getChatIndexStatus();
|
|
3030
3140
|
this.send({
|
|
3031
3141
|
type: "memory_status",
|
|
@@ -3050,7 +3160,7 @@ Add .md files to create commands.` });
|
|
|
3050
3160
|
type: "info",
|
|
3051
3161
|
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"
|
|
3052
3162
|
});
|
|
3053
|
-
const { buildChatIndex } = await import("./chat-index-
|
|
3163
|
+
const { buildChatIndex } = await import("./chat-index-2I7ZHRE5.js");
|
|
3054
3164
|
const stats = await buildChatIndex({
|
|
3055
3165
|
full,
|
|
3056
3166
|
onProgress: (p) => {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ToolRegistry
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3HJW556L.js";
|
|
5
5
|
import "./chunk-HDSKW7Q3.js";
|
|
6
6
|
import "./chunk-ZWVIDFGY.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-62CD2T5F.js";
|
|
8
8
|
import {
|
|
9
9
|
runTool
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GRFQ2QD5.js";
|
|
11
11
|
import {
|
|
12
12
|
getDangerLevel,
|
|
13
13
|
schemaToJsonSchema
|
|
@@ -15,11 +15,11 @@ import {
|
|
|
15
15
|
import "./chunk-2ZD3YTVM.js";
|
|
16
16
|
import {
|
|
17
17
|
VERSION
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-N3VGZTEJ.js";
|
|
19
19
|
import "./chunk-4BKXL7SM.js";
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-SLSWPBK3.js";
|
|
20
|
+
import "./chunk-MM3F43H6.js";
|
|
22
21
|
import "./chunk-KHYD3WXE.js";
|
|
22
|
+
import "./chunk-SLSWPBK3.js";
|
|
23
23
|
import "./chunk-VNNYHW6N.js";
|
|
24
24
|
import "./chunk-OVWE4E46.js";
|
|
25
25
|
import "./chunk-PDX44BCA.js";
|
|
@@ -3,24 +3,24 @@ import {
|
|
|
3
3
|
ToolRegistry,
|
|
4
4
|
googleSearchContext,
|
|
5
5
|
truncateOutput
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-3HJW556L.js";
|
|
7
7
|
import "./chunk-HDSKW7Q3.js";
|
|
8
8
|
import "./chunk-ZWVIDFGY.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-62CD2T5F.js";
|
|
10
10
|
import {
|
|
11
11
|
runTool
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GRFQ2QD5.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-N3VGZTEJ.js";
|
|
20
20
|
import "./chunk-4BKXL7SM.js";
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-SLSWPBK3.js";
|
|
21
|
+
import "./chunk-MM3F43H6.js";
|
|
23
22
|
import "./chunk-KHYD3WXE.js";
|
|
23
|
+
import "./chunk-SLSWPBK3.js";
|
|
24
24
|
import "./chunk-VNNYHW6N.js";
|
|
25
25
|
import "./chunk-OVWE4E46.js";
|
|
26
26
|
import "./chunk-PDX44BCA.js";
|
package/dist/web/client/app.js
CHANGED
|
@@ -199,6 +199,10 @@ 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;
|
|
205
|
+
case 'hub_review': hubReview(msg); break;
|
|
202
206
|
case 'info': addInfoMessage(msg.message); break;
|
|
203
207
|
case 'error': addErrorMessage(msg.message); hideRoundProgress(); clearAllToolTimers(); setProcessing(false); break;
|
|
204
208
|
case 'round_progress': handleRoundProgress(msg); break;
|
|
@@ -3109,3 +3113,172 @@ document.querySelectorAll('.sidebar-tab').forEach(btn => {
|
|
|
3109
3113
|
btn.addEventListener('click', () => initMemoryPanel());
|
|
3110
3114
|
}
|
|
3111
3115
|
});
|
|
3116
|
+
|
|
3117
|
+
// ── Hub multi-agent room (P4) ─────────────────────────────────────
|
|
3118
|
+
// DaisyUI semantic colors map for role legend dots / borders.
|
|
3119
|
+
const HUB_COLORS = { cyan: '#22d3ee', green: '#4ade80', red: '#f87171', magenta: '#e879f9', yellow: '#facc15', blue: '#60a5fa', white: '#e5e7eb' };
|
|
3120
|
+
let hubRoles = {}; // roleId → { name, color, provider, model }
|
|
3121
|
+
let hubStreamEl = null; // current streaming agent message element
|
|
3122
|
+
let hubStreamRoleId = null;
|
|
3123
|
+
|
|
3124
|
+
function hubColor(c) { return HUB_COLORS[c] || '#9ca3af'; }
|
|
3125
|
+
|
|
3126
|
+
window.startHub = function () {
|
|
3127
|
+
const topic = (document.getElementById('hub-topic').value || '').trim();
|
|
3128
|
+
if (!topic) { document.getElementById('hub-status').textContent = 'Enter a topic first.'; return; }
|
|
3129
|
+
send({
|
|
3130
|
+
type: 'hub_start',
|
|
3131
|
+
topic,
|
|
3132
|
+
preset: document.getElementById('hub-preset').value,
|
|
3133
|
+
maxRounds: parseInt(document.getElementById('hub-rounds').value, 10) || 6,
|
|
3134
|
+
mix: document.getElementById('hub-mix').checked,
|
|
3135
|
+
vote: document.getElementById('hub-vote').checked,
|
|
3136
|
+
steer: document.getElementById('hub-steer').checked,
|
|
3137
|
+
});
|
|
3138
|
+
document.getElementById('hub-start-btn').classList.add('hidden');
|
|
3139
|
+
document.getElementById('hub-abort-btn').classList.remove('hidden');
|
|
3140
|
+
document.getElementById('hub-status').textContent = 'Starting…';
|
|
3141
|
+
};
|
|
3142
|
+
|
|
3143
|
+
window.abortHub = function () {
|
|
3144
|
+
send({ type: 'hub_abort' });
|
|
3145
|
+
document.getElementById('hub-status').textContent = 'Stopping after current turn…';
|
|
3146
|
+
};
|
|
3147
|
+
|
|
3148
|
+
function hubStarted(msg) {
|
|
3149
|
+
hubRoles = {};
|
|
3150
|
+
for (const r of msg.roles) hubRoles[r.id] = r;
|
|
3151
|
+
hubStreamEl = null; hubStreamRoleId = null;
|
|
3152
|
+
|
|
3153
|
+
const legend = msg.roles.map(r => {
|
|
3154
|
+
const backend = r.provider ? `${r.provider}${r.model ? ':' + r.model : ''}` : '';
|
|
3155
|
+
return `<span class="inline-flex items-center gap-1 mr-2">
|
|
3156
|
+
<span style="width:.6rem;height:.6rem;border-radius:9999px;background:${hubColor(r.color)};display:inline-block"></span>
|
|
3157
|
+
<b>${escapeHtml(r.name)}</b><span class="opacity-50">${backend ? ' · ' + escapeHtml(backend) : ''}</span></span>`;
|
|
3158
|
+
}).join('');
|
|
3159
|
+
|
|
3160
|
+
const el = document.createElement('div');
|
|
3161
|
+
el.className = 'hub-banner border border-base-content/10 rounded-lg p-3 my-2 bg-base-200';
|
|
3162
|
+
el.innerHTML = `<div class="font-bold mb-1">🏛 ${escapeHtml(msg.topic)}</div>
|
|
3163
|
+
<div class="text-xs opacity-70 mb-1">up to ${msg.maxRounds} rounds</div>
|
|
3164
|
+
<div class="text-xs">${legend}</div>`;
|
|
3165
|
+
messagesEl.appendChild(el);
|
|
3166
|
+
scrollToBottom();
|
|
3167
|
+
}
|
|
3168
|
+
|
|
3169
|
+
function hubEvent(ev) {
|
|
3170
|
+
switch (ev.type) {
|
|
3171
|
+
case 'round_start': {
|
|
3172
|
+
const el = document.createElement('div');
|
|
3173
|
+
el.className = 'hub-round text-xs opacity-50 text-center my-2';
|
|
3174
|
+
el.textContent = `── Round ${ev.round}/${ev.maxRounds} ──`;
|
|
3175
|
+
messagesEl.appendChild(el);
|
|
3176
|
+
scrollToBottom();
|
|
3177
|
+
break;
|
|
3178
|
+
}
|
|
3179
|
+
case 'agent_token': {
|
|
3180
|
+
if (hubStreamRoleId !== ev.roleId || !hubStreamEl) {
|
|
3181
|
+
const role = hubRoles[ev.roleId] || { name: ev.roleId, color: 'white' };
|
|
3182
|
+
hubStreamEl = document.createElement('div');
|
|
3183
|
+
hubStreamEl.className = 'hub-msg border-l-2 pl-2 my-2';
|
|
3184
|
+
hubStreamEl.style.borderColor = hubColor(role.color);
|
|
3185
|
+
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>`;
|
|
3186
|
+
messagesEl.appendChild(hubStreamEl);
|
|
3187
|
+
hubStreamRoleId = ev.roleId;
|
|
3188
|
+
hubStreamEl._raw = '';
|
|
3189
|
+
}
|
|
3190
|
+
hubStreamEl._raw += ev.token;
|
|
3191
|
+
renderMarkdown(hubStreamEl.querySelector('.hub-body'), hubStreamEl._raw);
|
|
3192
|
+
scrollToBottom();
|
|
3193
|
+
break;
|
|
3194
|
+
}
|
|
3195
|
+
case 'agent_spoke':
|
|
3196
|
+
// Streaming already rendered the body; finalize the stream slot.
|
|
3197
|
+
hubStreamEl = null; hubStreamRoleId = null;
|
|
3198
|
+
break;
|
|
3199
|
+
case 'agent_passed': {
|
|
3200
|
+
const role = hubRoles[ev.roleId] || { name: ev.roleId };
|
|
3201
|
+
const el = document.createElement('div');
|
|
3202
|
+
el.className = 'text-xs opacity-40 italic pl-2 my-1';
|
|
3203
|
+
el.textContent = `${role.name} passed`;
|
|
3204
|
+
messagesEl.appendChild(el);
|
|
3205
|
+
hubStreamEl = null; hubStreamRoleId = null;
|
|
3206
|
+
break;
|
|
3207
|
+
}
|
|
3208
|
+
case 'converge_vote': {
|
|
3209
|
+
const el = document.createElement('div');
|
|
3210
|
+
el.className = 'text-xs text-center opacity-60 my-1';
|
|
3211
|
+
el.textContent = `🗳 Convergence vote: ${ev.converged}/${ev.total} marked [CONVERGED]`;
|
|
3212
|
+
messagesEl.appendChild(el);
|
|
3213
|
+
break;
|
|
3214
|
+
}
|
|
3215
|
+
case 'discussion_end': {
|
|
3216
|
+
const labels = { consensus: 'Consensus reached', vote_converged: '✓ Converged by vote', max_rounds: 'Max rounds reached', human_stop: 'Stopped', user_interrupt: 'Interrupted' };
|
|
3217
|
+
const el = document.createElement('div');
|
|
3218
|
+
el.className = 'text-xs text-center font-semibold my-2 text-success';
|
|
3219
|
+
el.textContent = labels[ev.reason] || ev.reason;
|
|
3220
|
+
messagesEl.appendChild(el);
|
|
3221
|
+
break;
|
|
3222
|
+
}
|
|
3223
|
+
case 'summary': {
|
|
3224
|
+
const el = document.createElement('div');
|
|
3225
|
+
el.className = 'hub-summary border border-success/40 rounded-lg p-3 my-2 bg-success/5';
|
|
3226
|
+
el.innerHTML = `<div class="font-bold mb-1">📋 Summary</div><div class="hub-body text-sm"></div>`;
|
|
3227
|
+
messagesEl.appendChild(el);
|
|
3228
|
+
renderMarkdown(el.querySelector('.hub-body'), ev.content);
|
|
3229
|
+
scrollToBottom();
|
|
3230
|
+
break;
|
|
3231
|
+
}
|
|
3232
|
+
case 'error': {
|
|
3233
|
+
addErrorMessage(`Hub${ev.roleId ? ' (' + ev.roleId + ')' : ''}: ${ev.message}`);
|
|
3234
|
+
hubStreamEl = null; hubStreamRoleId = null;
|
|
3235
|
+
break;
|
|
3236
|
+
}
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
|
|
3240
|
+
function hubDone(msg) {
|
|
3241
|
+
document.getElementById('hub-start-btn').classList.remove('hidden');
|
|
3242
|
+
document.getElementById('hub-abort-btn').classList.add('hidden');
|
|
3243
|
+
const status = document.getElementById('hub-status');
|
|
3244
|
+
if (msg.saved && msg.sessionId) {
|
|
3245
|
+
status.innerHTML = `Saved. <a class="link link-primary" onclick="send({type:'command',name:'session',args:['load','${msg.sessionId}']})">Open session</a>`;
|
|
3246
|
+
} else {
|
|
3247
|
+
status.textContent = msg.saved ? 'Saved to history.' : 'Done (not saved).';
|
|
3248
|
+
}
|
|
3249
|
+
hubStreamEl = null; hubStreamRoleId = null;
|
|
3250
|
+
scrollToBottom();
|
|
3251
|
+
}
|
|
3252
|
+
|
|
3253
|
+
function hubReview(msg) {
|
|
3254
|
+
// Inline between-rounds steering card. Submitting guidance continues with it
|
|
3255
|
+
// injected; Continue (empty) proceeds; Stop ends early and jumps to summary.
|
|
3256
|
+
const card = document.createElement('div');
|
|
3257
|
+
card.className = 'hub-review border border-info/40 rounded-lg p-3 my-2 bg-info/5';
|
|
3258
|
+
card.innerHTML = `
|
|
3259
|
+
<div class="text-sm font-semibold mb-2">🧭 Round ${msg.round}/${msg.maxRounds} done — steer the next round?</div>
|
|
3260
|
+
<input type="text" class="input input-bordered input-sm w-full mb-2" placeholder="Optional guidance for all agents…">
|
|
3261
|
+
<div class="flex gap-2">
|
|
3262
|
+
<button class="btn btn-primary btn-sm flex-1">Continue ▶</button>
|
|
3263
|
+
<button class="btn btn-error btn-outline btn-sm">Stop ⏹</button>
|
|
3264
|
+
</div>`;
|
|
3265
|
+
const input = card.querySelector('input');
|
|
3266
|
+
const [contBtn, stopBtn] = card.querySelectorAll('button');
|
|
3267
|
+
let answered = false;
|
|
3268
|
+
const finish = (action) => {
|
|
3269
|
+
if (answered) return;
|
|
3270
|
+
answered = true;
|
|
3271
|
+
const message = input.value.trim();
|
|
3272
|
+
send({ type: 'hub_steer', requestId: msg.requestId, action, message: message || undefined });
|
|
3273
|
+
card.querySelectorAll('input,button').forEach(e => e.disabled = true);
|
|
3274
|
+
card.querySelector('.text-sm').textContent = action === 'stop'
|
|
3275
|
+
? '🧭 Stopping…'
|
|
3276
|
+
: (message ? `🧭 Steered: ${message}` : '🧭 Continuing…');
|
|
3277
|
+
};
|
|
3278
|
+
contBtn.addEventListener('click', () => finish('continue'));
|
|
3279
|
+
stopBtn.addEventListener('click', () => finish('stop'));
|
|
3280
|
+
input.addEventListener('keydown', (e) => { if (e.key === 'Enter') finish('continue'); });
|
|
3281
|
+
messagesEl.appendChild(card);
|
|
3282
|
+
scrollToBottom();
|
|
3283
|
+
setTimeout(() => input.focus(), 50);
|
|
3284
|
+
}
|
|
@@ -186,6 +186,37 @@
|
|
|
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
|
+
<label class="flex items-center gap-2 text-xs cursor-pointer">
|
|
213
|
+
<input id="hub-steer" type="checkbox" class="checkbox checkbox-xs"> Human steering (pause each round to guide/stop)
|
|
214
|
+
</label>
|
|
215
|
+
<button id="hub-start-btn" class="btn btn-primary btn-sm w-full" onclick="startHub()">🏛 Start discussion</button>
|
|
216
|
+
<button id="hub-abort-btn" class="btn btn-error btn-outline btn-xs w-full hidden" onclick="abortHub()">⏹ Stop</button>
|
|
217
|
+
<div id="hub-status" class="text-xs opacity-60"></div>
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
189
220
|
</aside>
|
|
190
221
|
<!-- Sidebar resize handle -->
|
|
191
222
|
<div id="sidebar-resize" class="sidebar-resize-handle" title="Drag to resize sidebar"></div>
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
redactString
|
|
4
|
-
} from "./chunk-SLSWPBK3.js";
|
|
5
2
|
import {
|
|
6
3
|
EMBEDDING_DIM,
|
|
7
4
|
embed,
|
|
8
5
|
embedOne
|
|
9
6
|
} from "./chunk-KHYD3WXE.js";
|
|
7
|
+
import {
|
|
8
|
+
redactString
|
|
9
|
+
} from "./chunk-SLSWPBK3.js";
|
|
10
10
|
|
|
11
11
|
// src/memory/chat-index.ts
|
|
12
12
|
import fs from "fs";
|