jinzd-ai-cli 0.4.153 → 0.4.155
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-DBRN4MCC.js → batch-LS3IJVBK.js} +2 -2
- package/dist/{chat-index-LUQWWLKO.js → chat-index-IF4EINLQ.js} +2 -1
- package/dist/{chunk-D62BVFP7.js → chunk-B3LFGPU2.js} +1 -1
- package/dist/{chunk-EIIMBVXN.js → chunk-CIZQZ7CC.js} +23 -787
- package/dist/{chunk-TURORFH2.js → chunk-D6GJTJQH.js} +1 -1
- package/dist/{chunk-OP3I24WL.js → chunk-E5ICQT3P.js} +4 -4
- package/dist/{chunk-UWW3EWER.js → chunk-IBBYW6PM.js} +1 -1
- package/dist/{chunk-OT2HLGSO.js → chunk-JOJRBV2K.js} +1 -1
- package/dist/{chunk-LJPB4ZER.js → chunk-JXSWY54M.js} +1 -1
- package/dist/{chunk-EYJQJZJ6.js → chunk-NFRTSL3N.js} +1 -1
- package/dist/{chunk-M4GJOBWN.js → chunk-O6MLS5QO.js} +63 -23
- package/dist/chunk-SLSWPBK3.js +120 -0
- package/dist/chunk-TOTEUETI.js +768 -0
- package/dist/{chunk-RXM76HB7.js → chunk-U5MY24UZ.js} +3 -117
- package/dist/{ci-UEEUSELV.js → ci-34ZQH43L.js} +2 -2
- package/dist/{constants-43EVHE2E.js → constants-DQ5VJOGS.js} +1 -1
- package/dist/{doctor-cli-ZT674MCQ.js → doctor-cli-TSCI4ORL.js} +4 -4
- package/dist/electron-server.js +2 -2
- package/dist/{hub-MDQNJOMV.js → hub-ZILVZWI2.js} +81 -7
- package/dist/{hub-server-VPXCBWLA.js → hub-server-OH7AYQIW.js} +1 -1
- package/dist/index.js +32 -22
- package/dist/persist-3EBOLHFZ.js +52 -0
- package/dist/{run-tests-DCT5LWBB.js → run-tests-5CJRMOMI.js} +1 -1
- package/dist/{run-tests-EYZ2JZ4X.js → run-tests-5KWCHBQS.js} +2 -2
- package/dist/{server-OIYBFKS2.js → server-35OQV62B.js} +16 -13
- package/dist/{server-MQWFO2GJ.js → server-DVIP7NLW.js} +6 -5
- package/dist/{task-orchestrator-BGQBNKAI.js → task-orchestrator-AXSS7ROD.js} +6 -5
- package/package.json +1 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
redactString
|
|
4
|
+
} from "./chunk-SLSWPBK3.js";
|
|
2
5
|
import {
|
|
3
6
|
EMBEDDING_DIM,
|
|
4
7
|
embed,
|
|
@@ -10,120 +13,6 @@ import fs from "fs";
|
|
|
10
13
|
import path from "path";
|
|
11
14
|
import os from "os";
|
|
12
15
|
import crypto from "crypto";
|
|
13
|
-
|
|
14
|
-
// src/security/redactor.ts
|
|
15
|
-
var DEFAULT_PATTERNS = [
|
|
16
|
-
// password: xxx / password = xxx / password="xxx"
|
|
17
|
-
// Covers YAML / JSON / shell-ish / env-file forms.
|
|
18
|
-
{ kind: "password", regex: /\b(password|passwd|pwd)\s*[:=]\s*["']?([^\s"',;{}]{4,200})["']?/gi },
|
|
19
|
-
// PGPASSWORD=xxx (explicit bash env-var form, separate rule because no quotes usually)
|
|
20
|
-
{ kind: "pgpassword-env", regex: /\b(PGPASSWORD)=([^\s"']{4,200})/g },
|
|
21
|
-
// JDBC/PG/MySQL/Mongo connection strings with inline credentials
|
|
22
|
-
// postgresql://user:pass@host/db → redact pass
|
|
23
|
-
{ kind: "db-uri-password", regex: /(\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis|amqp|mssql):\/\/[^:\s]+:)([^@\s]+)(@)/gi },
|
|
24
|
-
// Anthropic API keys
|
|
25
|
-
{ kind: "anthropic-key", regex: /(sk-ant-[a-zA-Z0-9_-]{90,})/g },
|
|
26
|
-
// L6 (v0.4.108): Zhipu / GLM API keys — `<24+ hex/base64-ish>.<32+>`
|
|
27
|
-
// Two segments separated by a dot, each safely identifiable by length
|
|
28
|
-
// and char class. Conservative on the lower bound so we don't eat
|
|
29
|
-
// version strings like `1.0.0` or filenames.
|
|
30
|
-
{ kind: "zhipu-key", regex: /\b([a-zA-Z0-9]{24,}\.[a-zA-Z0-9]{32,})\b/g },
|
|
31
|
-
// OpenAI / generic sk- keys — requires length ≥32 to avoid eating short identifiers
|
|
32
|
-
{ kind: "openai-key", regex: /(sk-(?:proj-)?[a-zA-Z0-9_-]{32,})/g },
|
|
33
|
-
// GitHub personal access tokens
|
|
34
|
-
{ kind: "github-pat", regex: /\b(ghp_[a-zA-Z0-9]{36})\b/g },
|
|
35
|
-
{ kind: "github-oauth", regex: /\b(gho_[a-zA-Z0-9]{36})\b/g },
|
|
36
|
-
{ kind: "github-install", regex: /\b(ghs_[a-zA-Z0-9]{36})\b/g },
|
|
37
|
-
// Slack tokens
|
|
38
|
-
{ kind: "slack-bot", regex: /\b(xoxb-\d+-\d+-[a-zA-Z0-9]+)\b/g },
|
|
39
|
-
{ kind: "slack-user", regex: /\b(xoxp-\d+-\d+-\d+-[a-zA-Z0-9]+)\b/g },
|
|
40
|
-
// AWS access key IDs (AKIA...) and secret access keys are context-dependent;
|
|
41
|
-
// we only catch the ID because secret key alone is indistinguishable from random base64.
|
|
42
|
-
{ kind: "aws-access-key-id", regex: /\b(AKIA[0-9A-Z]{16})\b/g },
|
|
43
|
-
// Google API keys
|
|
44
|
-
{ kind: "google-api-key", regex: /\b(AIza[0-9A-Za-z_-]{35})\b/g },
|
|
45
|
-
// Generic "api_key": "..." / "apiKey": "..." / api-key=xxx
|
|
46
|
-
{ kind: "api-key", regex: /\b(api[_-]?key)\s*[:=]\s*["']?([a-zA-Z0-9_\-.]{16,200})["']?/gi },
|
|
47
|
-
// Generic token: xxx (only when value looks token-shaped; avoids eating human prose)
|
|
48
|
-
{ kind: "token", regex: /\b(token|access[_-]?token|bearer[_-]?token)\s*[:=]\s*["']?([a-zA-Z0-9_\-.]{20,300})["']?/gi },
|
|
49
|
-
// Bearer <token> in Authorization headers
|
|
50
|
-
{ kind: "bearer", regex: /\b(Authorization:\s*Bearer\s+)([a-zA-Z0-9_\-.=]{20,500})/g },
|
|
51
|
-
// Private key PEM blocks — catch the header+footer together
|
|
52
|
-
{ kind: "private-key", regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g }
|
|
53
|
-
];
|
|
54
|
-
var MAX_CUSTOM = 32;
|
|
55
|
-
var MAX_PATTERN_LEN = 500;
|
|
56
|
-
var SUSPICIOUS_REDOS = /\([^)]*[+*][^)]*\)\s*[+*{]/;
|
|
57
|
-
function render(placeholder, kind) {
|
|
58
|
-
return placeholder.replace("{kind}", kind);
|
|
59
|
-
}
|
|
60
|
-
function redactString(input, options) {
|
|
61
|
-
if (!options.enabled || !input) return { redacted: input, hits: [] };
|
|
62
|
-
const placeholder = options.placeholder ?? "[REDACTED:{kind}]";
|
|
63
|
-
const customSrcs = (options.customRegexes ?? []).slice(0, MAX_CUSTOM);
|
|
64
|
-
const patterns = [
|
|
65
|
-
...options.patterns ?? DEFAULT_PATTERNS,
|
|
66
|
-
...customSrcs.flatMap((src, i) => {
|
|
67
|
-
if (typeof src !== "string" || src.length === 0 || src.length > MAX_PATTERN_LEN) return [];
|
|
68
|
-
try {
|
|
69
|
-
const flags = src.match(/^\/.*\/([gimsuy]*)$/)?.[1] ?? "";
|
|
70
|
-
const body = src.replace(/^\/(.*)\/[gimsuy]*$/, "$1");
|
|
71
|
-
if (SUSPICIOUS_REDOS.test(body)) return [];
|
|
72
|
-
const regex = new RegExp(body, flags.includes("g") ? flags : flags + "g");
|
|
73
|
-
return [{ kind: `custom-${i}`, regex }];
|
|
74
|
-
} catch {
|
|
75
|
-
return [];
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
];
|
|
79
|
-
let redacted = input;
|
|
80
|
-
const hits = [];
|
|
81
|
-
for (const { kind, regex } of patterns) {
|
|
82
|
-
const rx = new RegExp(regex.source, regex.flags);
|
|
83
|
-
const captureCount = new RegExp(rx.source + "|").exec("").length - 1;
|
|
84
|
-
redacted = redacted.replace(rx, (...args) => {
|
|
85
|
-
const match = args[0];
|
|
86
|
-
const g1 = captureCount >= 1 ? args[1] : void 0;
|
|
87
|
-
const g2 = captureCount >= 2 ? args[2] : void 0;
|
|
88
|
-
const offset = args[1 + captureCount];
|
|
89
|
-
if (captureCount >= 2 && typeof g2 === "string") {
|
|
90
|
-
hits.push({ kind, start: offset + (g1?.length ?? 0), length: g2.length, secret: g2 });
|
|
91
|
-
return `${g1}${render(placeholder, kind)}`;
|
|
92
|
-
}
|
|
93
|
-
hits.push({ kind, start: offset, length: match.length, secret: g1 ?? match });
|
|
94
|
-
return render(placeholder, kind);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
return { redacted, hits };
|
|
98
|
-
}
|
|
99
|
-
function redactJson(value, options) {
|
|
100
|
-
if (!options.enabled) return { value, hits: [] };
|
|
101
|
-
const allHits = [];
|
|
102
|
-
function walk(v) {
|
|
103
|
-
if (typeof v === "string") {
|
|
104
|
-
const r = redactString(v, options);
|
|
105
|
-
allHits.push(...r.hits);
|
|
106
|
-
return r.redacted;
|
|
107
|
-
}
|
|
108
|
-
if (Array.isArray(v)) return v.map(walk);
|
|
109
|
-
if (v && typeof v === "object") {
|
|
110
|
-
const out = {};
|
|
111
|
-
for (const [k, vv] of Object.entries(v)) {
|
|
112
|
-
out[k] = walk(vv);
|
|
113
|
-
}
|
|
114
|
-
return out;
|
|
115
|
-
}
|
|
116
|
-
return v;
|
|
117
|
-
}
|
|
118
|
-
const redacted = walk(value);
|
|
119
|
-
return { value: redacted, hits: allHits };
|
|
120
|
-
}
|
|
121
|
-
function scanString(input, options) {
|
|
122
|
-
const { hits } = redactString(input, { ...options, enabled: true });
|
|
123
|
-
return hits;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// src/memory/chat-index.ts
|
|
127
16
|
var MEMORY_DIR_NAME = "memory-index";
|
|
128
17
|
var CHUNKS_FILE = "chunks.json";
|
|
129
18
|
var VECTORS_FILE = "vectors.vec";
|
|
@@ -458,9 +347,6 @@ function getChatIndexStatus() {
|
|
|
458
347
|
}
|
|
459
348
|
|
|
460
349
|
export {
|
|
461
|
-
DEFAULT_PATTERNS,
|
|
462
|
-
redactJson,
|
|
463
|
-
scanString,
|
|
464
350
|
chunkSession,
|
|
465
351
|
loadChatIndex,
|
|
466
352
|
clearChatIndex,
|
|
@@ -9,12 +9,12 @@ import {
|
|
|
9
9
|
} from "./chunk-AIZOARZY.js";
|
|
10
10
|
import {
|
|
11
11
|
ConfigManager
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IBBYW6PM.js";
|
|
13
13
|
import "./chunk-NXXNLLSG.js";
|
|
14
14
|
import "./chunk-2ZD3YTVM.js";
|
|
15
15
|
import {
|
|
16
16
|
VERSION
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-B3LFGPU2.js";
|
|
18
18
|
import "./chunk-PDX44BCA.js";
|
|
19
19
|
|
|
20
20
|
// src/cli/ci.ts
|
|
@@ -2,26 +2,26 @@
|
|
|
2
2
|
import {
|
|
3
3
|
getConfigDirUsage,
|
|
4
4
|
listRecentCrashes
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-D6GJTJQH.js";
|
|
6
6
|
import {
|
|
7
7
|
ProviderRegistry
|
|
8
8
|
} from "./chunk-AIZOARZY.js";
|
|
9
9
|
import {
|
|
10
10
|
ConfigManager
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-IBBYW6PM.js";
|
|
12
12
|
import {
|
|
13
13
|
getStatsSnapshot,
|
|
14
14
|
getTopFailingTools,
|
|
15
15
|
getTopUsedTools,
|
|
16
16
|
resetStats
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-NFRTSL3N.js";
|
|
18
18
|
import "./chunk-NXXNLLSG.js";
|
|
19
19
|
import "./chunk-2ZD3YTVM.js";
|
|
20
20
|
import {
|
|
21
21
|
DEV_STATE_FILE_NAME,
|
|
22
22
|
MEMORY_FILE_NAME,
|
|
23
23
|
VERSION
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-B3LFGPU2.js";
|
|
25
25
|
import "./chunk-PDX44BCA.js";
|
|
26
26
|
|
|
27
27
|
// src/diagnostics/doctor-cli.ts
|
package/dist/electron-server.js
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
VERSION,
|
|
37
37
|
buildUserIdentityPrompt,
|
|
38
38
|
runTestsTool
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-JXSWY54M.js";
|
|
40
40
|
import {
|
|
41
41
|
hasSemanticIndex,
|
|
42
42
|
semanticSearch
|
|
@@ -12715,7 +12715,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
12715
12715
|
case "test": {
|
|
12716
12716
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
12717
12717
|
try {
|
|
12718
|
-
const { executeTests } = await import("./run-tests-
|
|
12718
|
+
const { executeTests } = await import("./run-tests-5CJRMOMI.js");
|
|
12719
12719
|
const argStr = args.join(" ").trim();
|
|
12720
12720
|
let testArgs = {};
|
|
12721
12721
|
if (argStr) {
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
HubAgent,
|
|
4
4
|
assignRoleColors,
|
|
5
|
+
isConverged,
|
|
5
6
|
renderHubBanner,
|
|
6
7
|
renderHubEvent
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-O6MLS5QO.js";
|
|
8
9
|
import "./chunk-PDX44BCA.js";
|
|
9
10
|
|
|
10
11
|
// src/hub/discuss.ts
|
|
@@ -12,12 +13,22 @@ var DiscussionOrchestrator = class {
|
|
|
12
13
|
agents = [];
|
|
13
14
|
state;
|
|
14
15
|
aborted = false;
|
|
16
|
+
humanSteer;
|
|
17
|
+
voteConverge;
|
|
15
18
|
/** Callback for rendering events */
|
|
16
19
|
onEvent;
|
|
20
|
+
/**
|
|
21
|
+
* P2: human-in-the-loop. When `config.humanSteer` is on, the orchestrator
|
|
22
|
+
* awaits this between rounds so a person can inject guidance or stop. The
|
|
23
|
+
* CLI layer supplies the actual prompt; the orchestrator stays UI-agnostic.
|
|
24
|
+
*/
|
|
25
|
+
onRoundReview;
|
|
17
26
|
constructor(config, providers) {
|
|
18
27
|
this.agents = config.roles.map(
|
|
19
28
|
(role) => new HubAgent(role, providers, config.defaultProvider, config.defaultModel, config.context)
|
|
20
29
|
);
|
|
30
|
+
this.humanSteer = config.humanSteer ?? false;
|
|
31
|
+
this.voteConverge = config.voteConverge ?? false;
|
|
21
32
|
this.state = {
|
|
22
33
|
topic: "",
|
|
23
34
|
messages: [],
|
|
@@ -30,6 +41,10 @@ var DiscussionOrchestrator = class {
|
|
|
30
41
|
getAgents() {
|
|
31
42
|
return this.agents;
|
|
32
43
|
}
|
|
44
|
+
/** Current discussion state (used to persist even after an error). */
|
|
45
|
+
getState() {
|
|
46
|
+
return this.state;
|
|
47
|
+
}
|
|
33
48
|
/** Signal the orchestrator to stop after current turn */
|
|
34
49
|
abort() {
|
|
35
50
|
this.aborted = true;
|
|
@@ -52,6 +67,7 @@ var DiscussionOrchestrator = class {
|
|
|
52
67
|
this.state.round = round;
|
|
53
68
|
this.emit({ type: "round_start", round, maxRounds: this.state.maxRounds });
|
|
54
69
|
let allPassed = true;
|
|
70
|
+
let convergedCount = 0;
|
|
55
71
|
for (const agent of this.agents) {
|
|
56
72
|
if (this.aborted) break;
|
|
57
73
|
this.emit({ type: "agent_speaking", roleId: agent.role.id, roleName: agent.role.name });
|
|
@@ -61,9 +77,11 @@ var DiscussionOrchestrator = class {
|
|
|
61
77
|
this.state.messages,
|
|
62
78
|
round,
|
|
63
79
|
this.state.maxRounds,
|
|
64
|
-
(token) => this.emit({ type: "agent_token", roleId: agent.role.id, token })
|
|
80
|
+
(token) => this.emit({ type: "agent_token", roleId: agent.role.id, token }),
|
|
81
|
+
{ voteConverge: this.voteConverge }
|
|
65
82
|
);
|
|
66
83
|
this.state.messages.push(message);
|
|
84
|
+
if (message.converged) convergedCount++;
|
|
67
85
|
if (message.passed) {
|
|
68
86
|
this.emit({ type: "agent_passed", roleId: agent.role.id });
|
|
69
87
|
this.emit({ type: "agent_spoke", roleId: agent.role.id, message });
|
|
@@ -87,8 +105,33 @@ var DiscussionOrchestrator = class {
|
|
|
87
105
|
this.emit({ type: "discussion_end", reason: "consensus" });
|
|
88
106
|
break;
|
|
89
107
|
}
|
|
108
|
+
if (this.voteConverge && convergedCount > 0) {
|
|
109
|
+
this.emit({ type: "converge_vote", converged: convergedCount, total: this.agents.length });
|
|
110
|
+
if (isConverged(convergedCount, this.agents.length)) {
|
|
111
|
+
this.emit({ type: "discussion_end", reason: "vote_converged" });
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
90
115
|
if (round === this.state.maxRounds) {
|
|
91
116
|
this.emit({ type: "discussion_end", reason: "max_rounds", maxRounds: this.state.maxRounds });
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
if (this.humanSteer && this.onRoundReview && !this.aborted) {
|
|
120
|
+
const steer = await this.onRoundReview({ round, maxRounds: this.state.maxRounds, state: this.state });
|
|
121
|
+
if (steer.action === "stop") {
|
|
122
|
+
this.emit({ type: "discussion_end", reason: "human_stop" });
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
const guidance = steer.message?.trim();
|
|
126
|
+
if (guidance) {
|
|
127
|
+
this.state.messages.push({
|
|
128
|
+
speaker: "human",
|
|
129
|
+
speakerName: "\u4E3B\u6301\u4EBA (You)",
|
|
130
|
+
content: guidance,
|
|
131
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
132
|
+
});
|
|
133
|
+
this.emit({ type: "human_steer", message: guidance });
|
|
134
|
+
}
|
|
92
135
|
}
|
|
93
136
|
}
|
|
94
137
|
} catch (err) {
|
|
@@ -431,20 +474,33 @@ ${content}`);
|
|
|
431
474
|
enableTools: mode === "task",
|
|
432
475
|
maxToolRoundsPerTurn: mode === "task" ? options.taskRounds ?? 30 : void 0,
|
|
433
476
|
context,
|
|
434
|
-
contextFiles: contextFileNames.length > 0 ? contextFileNames : void 0
|
|
477
|
+
contextFiles: contextFileNames.length > 0 ? contextFileNames : void 0,
|
|
478
|
+
humanSteer: options.steer === true,
|
|
479
|
+
voteConverge: options.vote === true
|
|
435
480
|
};
|
|
436
481
|
if (mode === "discuss") {
|
|
437
482
|
if (options.distributed) {
|
|
438
483
|
await runDistributedDiscussion(config, providers, options.topic, options.port ?? 9527);
|
|
439
484
|
} else {
|
|
440
|
-
await runDiscussion(config, providers, options.topic);
|
|
485
|
+
const state = await runDiscussion(config, providers, options.topic);
|
|
486
|
+
if (options.save !== false && state.messages.length > 0) {
|
|
487
|
+
try {
|
|
488
|
+
const { persistDiscussion } = await import("./persist-3EBOLHFZ.js");
|
|
489
|
+
const { path } = await persistDiscussion(state, configManager, defaultProvider, defaultModel);
|
|
490
|
+
console.log(chalk.dim(`
|
|
491
|
+
\u{1F4BE} Saved to history \u2014 open it in the Web UI and hit \u{1F3AC} to replay.
|
|
492
|
+
${path}`));
|
|
493
|
+
} catch (err) {
|
|
494
|
+
console.error(chalk.yellow(` \u26A0 Could not save discussion: ${err.message}`));
|
|
495
|
+
}
|
|
496
|
+
}
|
|
441
497
|
}
|
|
442
498
|
} else if (mode === "task") {
|
|
443
499
|
await runTaskMode(config, providers, configManager, options.topic);
|
|
444
500
|
}
|
|
445
501
|
}
|
|
446
502
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
447
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
503
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-AXSS7ROD.js");
|
|
448
504
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
449
505
|
let interrupted = false;
|
|
450
506
|
const onSigint = () => {
|
|
@@ -480,7 +536,7 @@ async function runTaskMode(config, providers, configManager, topic) {
|
|
|
480
536
|
}
|
|
481
537
|
}
|
|
482
538
|
async function runDistributedDiscussion(config, providers, topic, port) {
|
|
483
|
-
const { HubServer } = await import("./hub-server-
|
|
539
|
+
const { HubServer } = await import("./hub-server-OH7AYQIW.js");
|
|
484
540
|
const hub = new HubServer(config, providers, port);
|
|
485
541
|
let interrupted = false;
|
|
486
542
|
const onSigint = () => {
|
|
@@ -506,6 +562,23 @@ async function runDiscussion(config, providers, topic) {
|
|
|
506
562
|
assignRoleColors(config.roles);
|
|
507
563
|
const orchestrator = new DiscussionOrchestrator(config, providers);
|
|
508
564
|
orchestrator.onEvent = renderHubEvent;
|
|
565
|
+
if (config.humanSteer) {
|
|
566
|
+
const { createInterface } = await import("readline");
|
|
567
|
+
orchestrator.onRoundReview = async ({ round, maxRounds }) => {
|
|
568
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
569
|
+
const answer = await new Promise((resolve) => {
|
|
570
|
+
rl.question(
|
|
571
|
+
chalk.cyan(`
|
|
572
|
+
\u{1F9ED} Round ${round}/${maxRounds} done. Steer next round? `) + chalk.dim("[Enter=continue \xB7 type guidance \xB7 /stop=end] "),
|
|
573
|
+
resolve
|
|
574
|
+
);
|
|
575
|
+
});
|
|
576
|
+
rl.close();
|
|
577
|
+
const t = answer.trim();
|
|
578
|
+
if (t === "/stop" || t.toLowerCase() === "stop") return { action: "stop" };
|
|
579
|
+
return { action: "continue", message: t || void 0 };
|
|
580
|
+
};
|
|
581
|
+
}
|
|
509
582
|
let interrupted = false;
|
|
510
583
|
const onSigint = () => {
|
|
511
584
|
if (interrupted) {
|
|
@@ -518,10 +591,11 @@ async function runDiscussion(config, providers, topic) {
|
|
|
518
591
|
process.on("SIGINT", onSigint);
|
|
519
592
|
renderHubBanner(topic, config.roles, config.maxRounds ?? 10, config.contextFiles);
|
|
520
593
|
try {
|
|
521
|
-
await orchestrator.run(topic);
|
|
594
|
+
return await orchestrator.run(topic);
|
|
522
595
|
} catch (err) {
|
|
523
596
|
console.error(`
|
|
524
597
|
\u2717 Hub error: ${err.message}`);
|
|
598
|
+
return orchestrator.getState();
|
|
525
599
|
} finally {
|
|
526
600
|
process.removeListener("SIGINT", onSigint);
|
|
527
601
|
}
|
package/dist/index.js
CHANGED
|
@@ -6,13 +6,11 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
McpManager,
|
|
8
8
|
SNAPSHOT_PROMPT,
|
|
9
|
-
SessionManager,
|
|
10
9
|
SkillManager,
|
|
11
10
|
autoTrimSessionIfNeeded,
|
|
12
11
|
clearDevState,
|
|
13
12
|
computeCost,
|
|
14
13
|
formatCost,
|
|
15
|
-
getContentText,
|
|
16
14
|
getPricing,
|
|
17
15
|
loadDevState,
|
|
18
16
|
parseSimpleYaml,
|
|
@@ -20,12 +18,16 @@ import {
|
|
|
20
18
|
saveDevState,
|
|
21
19
|
sessionHasMeaningfulContent,
|
|
22
20
|
setupProxy
|
|
23
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-CIZQZ7CC.js";
|
|
22
|
+
import {
|
|
23
|
+
SessionManager,
|
|
24
|
+
getContentText
|
|
25
|
+
} from "./chunk-TOTEUETI.js";
|
|
24
26
|
import {
|
|
25
27
|
getConfigDirUsage,
|
|
26
28
|
listRecentCrashes,
|
|
27
29
|
writeCrashLog
|
|
28
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-D6GJTJQH.js";
|
|
29
31
|
import {
|
|
30
32
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
31
33
|
HALLUCINATION_CORRECTION_MESSAGE,
|
|
@@ -46,7 +48,7 @@ import {
|
|
|
46
48
|
} from "./chunk-AIZOARZY.js";
|
|
47
49
|
import {
|
|
48
50
|
ConfigManager
|
|
49
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-IBBYW6PM.js";
|
|
50
52
|
import {
|
|
51
53
|
ToolExecutor,
|
|
52
54
|
ToolRegistry,
|
|
@@ -65,16 +67,16 @@ import {
|
|
|
65
67
|
spawnAgentContext,
|
|
66
68
|
theme,
|
|
67
69
|
undoStack
|
|
68
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-E5ICQT3P.js";
|
|
69
71
|
import "./chunk-HDSKW7Q3.js";
|
|
70
72
|
import "./chunk-ZWVIDFGY.js";
|
|
71
|
-
import "./chunk-
|
|
73
|
+
import "./chunk-JOJRBV2K.js";
|
|
72
74
|
import {
|
|
73
75
|
getStatsSnapshot,
|
|
74
76
|
getTopFailingTools,
|
|
75
77
|
getTopUsedTools,
|
|
76
78
|
installFlushOnExit
|
|
77
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-NFRTSL3N.js";
|
|
78
80
|
import "./chunk-NXXNLLSG.js";
|
|
79
81
|
import {
|
|
80
82
|
AuthError,
|
|
@@ -102,7 +104,7 @@ import {
|
|
|
102
104
|
SKILLS_DIR_NAME,
|
|
103
105
|
VERSION,
|
|
104
106
|
buildUserIdentityPrompt
|
|
105
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-B3LFGPU2.js";
|
|
106
108
|
import {
|
|
107
109
|
formatGitContextForPrompt,
|
|
108
110
|
getGitContext,
|
|
@@ -112,13 +114,15 @@ import {
|
|
|
112
114
|
fileCheckpoints
|
|
113
115
|
} from "./chunk-4BKXL7SM.js";
|
|
114
116
|
import {
|
|
115
|
-
DEFAULT_PATTERNS,
|
|
116
117
|
buildChatIndex,
|
|
117
118
|
clearChatIndex,
|
|
118
119
|
getChatIndexStatus,
|
|
119
|
-
scanString,
|
|
120
120
|
searchChatMemory
|
|
121
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-U5MY24UZ.js";
|
|
122
|
+
import {
|
|
123
|
+
DEFAULT_PATTERNS,
|
|
124
|
+
scanString
|
|
125
|
+
} from "./chunk-SLSWPBK3.js";
|
|
122
126
|
import "./chunk-KHYD3WXE.js";
|
|
123
127
|
import "./chunk-VNNYHW6N.js";
|
|
124
128
|
import "./chunk-OVWE4E46.js";
|
|
@@ -1769,7 +1773,7 @@ No tools match "${filter}".
|
|
|
1769
1773
|
const { join: join6 } = await import("path");
|
|
1770
1774
|
const { existsSync: existsSync6 } = await import("fs");
|
|
1771
1775
|
const { getGitRoot: getGitRoot2 } = await import("./git-context-7KIP4X2V.js");
|
|
1772
|
-
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-
|
|
1776
|
+
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-DQ5VJOGS.js");
|
|
1773
1777
|
const { approveProject, hashMcpFile } = await import("./project-trust-IFM7FXEV.js");
|
|
1774
1778
|
const cwd = process.cwd();
|
|
1775
1779
|
const projectRoot = getGitRoot2(cwd) ?? cwd;
|
|
@@ -2830,7 +2834,7 @@ ${hint}` : "")
|
|
|
2830
2834
|
usage: "/test [command|filter]",
|
|
2831
2835
|
async execute(args, ctx) {
|
|
2832
2836
|
try {
|
|
2833
|
-
const { executeTests } = await import("./run-tests-
|
|
2837
|
+
const { executeTests } = await import("./run-tests-5KWCHBQS.js");
|
|
2834
2838
|
const argStr = args.join(" ").trim();
|
|
2835
2839
|
let testArgs = {};
|
|
2836
2840
|
if (argStr) {
|
|
@@ -5560,7 +5564,7 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5560
5564
|
})();
|
|
5561
5565
|
void (async () => {
|
|
5562
5566
|
try {
|
|
5563
|
-
const { getChatIndexStatus: getChatIndexStatus2, buildChatIndex: buildChatIndex2 } = await import("./chat-index-
|
|
5567
|
+
const { getChatIndexStatus: getChatIndexStatus2, buildChatIndex: buildChatIndex2 } = await import("./chat-index-IF4EINLQ.js");
|
|
5564
5568
|
const initial = getChatIndexStatus2();
|
|
5565
5569
|
this.chatMemoryStatus = {
|
|
5566
5570
|
exists: initial.exists,
|
|
@@ -7530,7 +7534,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
7530
7534
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
7531
7535
|
process.exit(1);
|
|
7532
7536
|
}
|
|
7533
|
-
const { startWebServer } = await import("./server-
|
|
7537
|
+
const { startWebServer } = await import("./server-35OQV62B.js");
|
|
7534
7538
|
await startWebServer({ port, host: options.host });
|
|
7535
7539
|
});
|
|
7536
7540
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | logout-all <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -7697,12 +7701,12 @@ program.command("sessions").description("List recent conversation sessions").opt
|
|
|
7697
7701
|
console.log(footer + "\n");
|
|
7698
7702
|
});
|
|
7699
7703
|
program.command("doctor").description("Health check: API keys, config, MCP, recent crashes, tool usage, disk usage").option("--json", "Output as JSON (for scripting)").option("--reset-stats", "Reset accumulated tool usage statistics").action(async (options) => {
|
|
7700
|
-
const { runDoctorCli } = await import("./doctor-cli-
|
|
7704
|
+
const { runDoctorCli } = await import("./doctor-cli-TSCI4ORL.js");
|
|
7701
7705
|
await runDoctorCli({ json: !!options.json, resetStats: !!options.resetStats });
|
|
7702
7706
|
});
|
|
7703
7707
|
program.command("batch <action> [arg] [arg2]").description("Anthropic Message Batches: submit | list | status <id> | results <id> [out] | cancel <id>").option("--dry-run", "Parse and validate input without submitting (submit only)").action(async (action, arg, arg2, options) => {
|
|
7704
7708
|
try {
|
|
7705
|
-
const batch = await import("./batch-
|
|
7709
|
+
const batch = await import("./batch-LS3IJVBK.js");
|
|
7706
7710
|
switch (action) {
|
|
7707
7711
|
case "submit":
|
|
7708
7712
|
if (!arg) {
|
|
@@ -7745,7 +7749,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
|
|
|
7745
7749
|
}
|
|
7746
7750
|
});
|
|
7747
7751
|
program.command("mcp-serve").description("Start an MCP server over STDIO, exposing aicli's built-in tools to Claude Desktop / Cursor / other MCP clients").option("--allow-destructive", "Allow bash / run_interactive / task_create (always destructive in MCP mode)").option("--allow-outside-cwd", "Allow tool path arguments to escape the sandbox root \u2014 disabled by default").option("--tools <list>", "Comma-separated whitelist of tools to expose (default: all eligible tools)").option("--cwd <path>", "Working directory AND sandbox root (default: current directory)").action(async (options) => {
|
|
7748
|
-
const { startMcpServer } = await import("./server-
|
|
7752
|
+
const { startMcpServer } = await import("./server-DVIP7NLW.js");
|
|
7749
7753
|
await startMcpServer({
|
|
7750
7754
|
allowDestructive: !!options.allowDestructive,
|
|
7751
7755
|
allowOutsideCwd: !!options.allowOutsideCwd,
|
|
@@ -7754,7 +7758,7 @@ program.command("mcp-serve").description("Start an MCP server over STDIO, exposi
|
|
|
7754
7758
|
});
|
|
7755
7759
|
});
|
|
7756
7760
|
program.command("ci").description("Headless PR review (code + security) \u2014 reads git/gh diff, optionally posts to PR. Designed for GitHub Actions.").option("--pr <num>", "PR number; diff fetched via `gh pr diff <num>`", (v) => parseInt(v, 10)).option("--base <ref>", "Base ref for `git diff <ref>...HEAD` (ignored when --pr set)").option("--post", "Post review as a PR comment (requires gh CLI + GH_TOKEN, needs --pr)").option("--no-update", "Always create a new comment instead of updating the previous aicli review").option("--skip-code", "Skip the code review section").option("--skip-security", "Skip the security review section").option("--detailed", "Use the detailed code-review prompt").option("--max-diff <n>", "Max diff chars sent to the model (default 30000)", (v) => parseInt(v, 10)).option("--provider <id>", "Override provider (default: config.defaultProvider)").option("--model <id>", "Override model").option("--dry-run", "Print result to stdout instead of posting (overrides --post)").action(async (options) => {
|
|
7757
|
-
const { runCi } = await import("./ci-
|
|
7761
|
+
const { runCi } = await import("./ci-34ZQH43L.js");
|
|
7758
7762
|
const result = await runCi({
|
|
7759
7763
|
pr: options.pr,
|
|
7760
7764
|
base: options.base,
|
|
@@ -7828,6 +7832,9 @@ program.command("help").description("Show a comprehensive guide to all aicli fea
|
|
|
7828
7832
|
` ${Y}--preset <name>${R} Role preset (tech-review/brainstorm/code-review/debate)`,
|
|
7829
7833
|
` ${Y}--roles <file>${R} Custom roles JSON file`,
|
|
7830
7834
|
` ${Y}--mix [providers]${R} Mixed multi-model: spread providers across roles (e.g. claude,openai,deepseek)`,
|
|
7835
|
+
` ${Y}--steer${R} Human-in-the-loop: steer/stop between rounds`,
|
|
7836
|
+
` ${Y}--vote${R} Convergence voting: 2/3 [CONVERGED] majority ends early`,
|
|
7837
|
+
` ${Y}--no-save${R} Don't persist discussion to history (saved + replayable by default)`,
|
|
7831
7838
|
` ${Y}-c, --context <file>${R} Inject context doc (repeatable: -c a.md -c b.md)`,
|
|
7832
7839
|
` ${Y}--task${R} Task mode: agents plan & write code with tools`,
|
|
7833
7840
|
` ${Y}--distributed${R} Distributed mode (WebSocket, multi-process)`,
|
|
@@ -7885,7 +7892,7 @@ program.command("help").description("Show a comprehensive guide to all aicli fea
|
|
|
7885
7892
|
];
|
|
7886
7893
|
console.log(lines.join("\n"));
|
|
7887
7894
|
});
|
|
7888
|
-
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("--mix [providers]", "Mixed multi-model: spread configured providers across roles (or --mix claude,openai,deepseek)").option("--max-rounds <n>", "Max discussion rounds (default: 10)").option("--presets", "List available role presets").option("--task", "Task mode: plan \u2192 approve \uFFFD\uFFFD execute with tools (agents write code)").option("--task-rounds <n>", "Max tool-call rounds per task (default: 30)").option("-c, --context <file>", "Inject context document (repeatable: -c a.md -c b.md)", (val, prev) => prev.concat(val), []).option("--distributed", "Start WebSocket server so remote aicli instances can join as agents").option("--port <n>", "WebSocket port for distributed mode (default: 9527)", "9527").action(async (topic, options) => {
|
|
7895
|
+
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("--mix [providers]", "Mixed multi-model: spread configured providers across roles (or --mix claude,openai,deepseek)").option("--steer", "Human-in-the-loop: pause between rounds to inject guidance or stop (discuss mode)").option("--vote", "Convergence voting: agents may [CONVERGED]; 2/3 majority ends early (discuss mode)").option("--no-save", "Do not persist the discussion to ~/.aicli/history (discuss mode saves by default)").option("--max-rounds <n>", "Max discussion rounds (default: 10)").option("--presets", "List available role presets").option("--task", "Task mode: plan \u2192 approve \uFFFD\uFFFD execute with tools (agents write code)").option("--task-rounds <n>", "Max tool-call rounds per task (default: 30)").option("-c, --context <file>", "Inject context document (repeatable: -c a.md -c b.md)", (val, prev) => prev.concat(val), []).option("--distributed", "Start WebSocket server so remote aicli instances can join as agents").option("--port <n>", "WebSocket port for distributed mode (default: 9527)", "9527").action(async (topic, options) => {
|
|
7889
7896
|
const config = new ConfigManager();
|
|
7890
7897
|
const registry = new ProviderRegistry();
|
|
7891
7898
|
await registry.initialize(
|
|
@@ -7896,7 +7903,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
7896
7903
|
}),
|
|
7897
7904
|
config.get("customProviders")
|
|
7898
7905
|
);
|
|
7899
|
-
const { startHub } = await import("./hub-
|
|
7906
|
+
const { startHub } = await import("./hub-ZILVZWI2.js");
|
|
7900
7907
|
await startHub(
|
|
7901
7908
|
{
|
|
7902
7909
|
topic: topic ?? "",
|
|
@@ -7905,6 +7912,9 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
7905
7912
|
provider: options.provider,
|
|
7906
7913
|
model: options.model,
|
|
7907
7914
|
mix: options.mix,
|
|
7915
|
+
steer: options.steer === true,
|
|
7916
|
+
vote: options.vote === true,
|
|
7917
|
+
save: options.save !== false,
|
|
7908
7918
|
mode: options.task === true ? "task" : void 0,
|
|
7909
7919
|
maxRounds: options.maxRounds ? parseInt(options.maxRounds, 10) : void 0,
|
|
7910
7920
|
listPresets: options.presets === true,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
SessionManager
|
|
4
|
+
} from "./chunk-TOTEUETI.js";
|
|
5
|
+
import "./chunk-SLSWPBK3.js";
|
|
6
|
+
import "./chunk-PDX44BCA.js";
|
|
7
|
+
|
|
8
|
+
// src/hub/persist.ts
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
function discussionToMessages(state) {
|
|
11
|
+
const out = [];
|
|
12
|
+
const t0 = state.messages[0]?.timestamp ?? /* @__PURE__ */ new Date();
|
|
13
|
+
out.push({ role: "user", content: `\u{1F3DB} Topic: ${state.topic}`, timestamp: t0 });
|
|
14
|
+
for (const m of state.messages) {
|
|
15
|
+
if (m.speaker === "system") {
|
|
16
|
+
out.push({ role: "system", content: m.content, timestamp: m.timestamp });
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (m.speaker === "human") {
|
|
20
|
+
out.push({ role: "user", content: `\u{1F9ED} ${m.speakerName}: ${m.content}`, timestamp: m.timestamp });
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (m.passed || !m.content.trim()) continue;
|
|
24
|
+
const tag = m.converged ? " \u2713converged" : "";
|
|
25
|
+
out.push({
|
|
26
|
+
role: "assistant",
|
|
27
|
+
content: `**${m.speakerName}** (${m.speaker})${tag}
|
|
28
|
+
|
|
29
|
+
${m.content}`,
|
|
30
|
+
timestamp: m.timestamp
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (state.summary && state.summary.trim()) {
|
|
34
|
+
out.push({ role: "assistant", content: `\u{1F4CB} **Summary**
|
|
35
|
+
|
|
36
|
+
${state.summary}`, timestamp: /* @__PURE__ */ new Date() });
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
async function persistDiscussion(state, config, defaultProvider, defaultModel) {
|
|
41
|
+
const sm = new SessionManager(config);
|
|
42
|
+
const session = sm.createSession(defaultProvider, defaultModel);
|
|
43
|
+
session.messages = discussionToMessages(state);
|
|
44
|
+
session.title = `[Hub] ${state.topic.slice(0, 48)}`.replace(/\n/g, " ");
|
|
45
|
+
session.titleAiGenerated = true;
|
|
46
|
+
await sm.save();
|
|
47
|
+
return { id: session.id, path: join(config.getHistoryDir(), `${session.id}.json`) };
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
discussionToMessages,
|
|
51
|
+
persistDiscussion
|
|
52
|
+
};
|