jinzd-ai-cli 0.4.78 → 0.4.80
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-CDCTUTIQ.js → batch-OUBKAHXG.js} +2 -2
- package/dist/{chunk-HELGL4RH.js → chunk-2ERX5Q55.js} +1 -1
- package/dist/{chunk-TNAPORYF.js → chunk-63R2GIRK.js} +1 -1
- package/dist/{chunk-GKDETNDH.js → chunk-6HZTXVTF.js} +53 -2
- package/dist/{chunk-FCVQ6OP5.js → chunk-C5QENJ4P.js} +1 -1
- package/dist/{chunk-HPDDAXFY.js → chunk-CQQQFNND.js} +38 -3
- package/dist/{chunk-EUE6VMGO.js → chunk-CU5ZSHGU.js} +3 -3
- package/dist/{chunk-UTCC3UMT.js → chunk-GTKJUEBS.js} +38 -3
- package/dist/{chunk-KHYHG2SO.js → chunk-IGHC7D62.js} +1 -1
- package/dist/electron-server.js +128 -7
- package/dist/{hub-BIFM6NOM.js → hub-SFJU4KJK.js} +1 -1
- package/dist/index.js +89 -14
- package/dist/{run-tests-MONKXJBT.js → run-tests-4PZKLURD.js} +1 -1
- package/dist/{run-tests-JBM4K5FO.js → run-tests-7N2WILA3.js} +2 -2
- package/dist/{semantic-RBWU76MD.js → semantic-ICJ536BG.js} +3 -1
- package/dist/{semantic-MD7HYPWZ.js → semantic-MYAXLDCZ.js} +3 -1
- package/dist/{server-GCE5V4SL.js → server-HJ64OR7A.js} +81 -11
- package/dist/{task-orchestrator-YAWEIZE7.js → task-orchestrator-RVKRP6LI.js} +4 -4
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ConfigManager
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-C5QENJ4P.js";
|
|
5
5
|
import "./chunk-2ZD3YTVM.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-2ERX5Q55.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/batch.ts
|
|
9
9
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
schemaToJsonSchema,
|
|
4
4
|
truncateForPersist
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CU5ZSHGU.js";
|
|
6
6
|
import {
|
|
7
7
|
AuthError,
|
|
8
8
|
ProviderError,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
MCP_PROTOCOL_VERSION,
|
|
19
19
|
MCP_TOOL_PREFIX,
|
|
20
20
|
VERSION
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-2ERX5Q55.js";
|
|
22
22
|
|
|
23
23
|
// src/providers/claude.ts
|
|
24
24
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -2135,6 +2135,12 @@ function getContentText(content) {
|
|
|
2135
2135
|
function makeBranchId() {
|
|
2136
2136
|
return Math.random().toString(16).slice(2, 8);
|
|
2137
2137
|
}
|
|
2138
|
+
function messagesEqual(a, b) {
|
|
2139
|
+
if (a.role !== b.role) return false;
|
|
2140
|
+
if (JSON.stringify(a.content) !== JSON.stringify(b.content)) return false;
|
|
2141
|
+
if (JSON.stringify(a.toolCalls ?? null) !== JSON.stringify(b.toolCalls ?? null)) return false;
|
|
2142
|
+
return true;
|
|
2143
|
+
}
|
|
2138
2144
|
var Session = class _Session {
|
|
2139
2145
|
id;
|
|
2140
2146
|
provider;
|
|
@@ -2376,6 +2382,51 @@ var Session = class _Session {
|
|
|
2376
2382
|
const m = this._inactiveBranchMessages.get(id);
|
|
2377
2383
|
return m ? m.slice() : null;
|
|
2378
2384
|
}
|
|
2385
|
+
// ── B3 Branch diff + cherry-pick (v0.4.80+) ────────────────────────
|
|
2386
|
+
/**
|
|
2387
|
+
* Compare messages between two branches. Finds the longest common prefix
|
|
2388
|
+
* by message equality (role + content + toolCalls shape) — NOT by fork
|
|
2389
|
+
* point metadata, so user-edited histories still diff cleanly.
|
|
2390
|
+
*
|
|
2391
|
+
* @param sourceId Branch to compare
|
|
2392
|
+
* @param targetId Branch to compare against (defaults to active branch)
|
|
2393
|
+
* @returns BranchDiff, or null if either branch id is unknown
|
|
2394
|
+
*/
|
|
2395
|
+
diffBranches(sourceId, targetId) {
|
|
2396
|
+
const tgt = targetId ?? this.activeBranchId;
|
|
2397
|
+
const src = this.getBranchMessages(sourceId);
|
|
2398
|
+
const dst = this.getBranchMessages(tgt);
|
|
2399
|
+
if (!src || !dst) return null;
|
|
2400
|
+
let i = 0;
|
|
2401
|
+
while (i < src.length && i < dst.length && messagesEqual(src[i], dst[i])) i++;
|
|
2402
|
+
return {
|
|
2403
|
+
sourceId,
|
|
2404
|
+
targetId: tgt,
|
|
2405
|
+
commonPrefix: i,
|
|
2406
|
+
sourceOnly: src.slice(i),
|
|
2407
|
+
targetOnly: dst.slice(i)
|
|
2408
|
+
};
|
|
2409
|
+
}
|
|
2410
|
+
/**
|
|
2411
|
+
* Copy a single message from another branch into the active branch
|
|
2412
|
+
* (appended at the end). Timestamp is reset to now so it's clear when
|
|
2413
|
+
* the cherry-pick happened.
|
|
2414
|
+
*
|
|
2415
|
+
* @returns the cloned message, or null if sourceId / msgIndex is invalid
|
|
2416
|
+
*/
|
|
2417
|
+
cherryPickMessage(sourceId, msgIndex) {
|
|
2418
|
+
const src = this.getBranchMessages(sourceId);
|
|
2419
|
+
if (!src) return null;
|
|
2420
|
+
if (msgIndex < 0 || msgIndex >= src.length) return null;
|
|
2421
|
+
const orig = src[msgIndex];
|
|
2422
|
+
const copy = {
|
|
2423
|
+
...orig,
|
|
2424
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
2425
|
+
};
|
|
2426
|
+
this.messages.push(copy);
|
|
2427
|
+
this.updated = /* @__PURE__ */ new Date();
|
|
2428
|
+
return copy;
|
|
2429
|
+
}
|
|
2379
2430
|
getMeta() {
|
|
2380
2431
|
return {
|
|
2381
2432
|
id: this.id,
|
|
@@ -12,8 +12,42 @@ import {
|
|
|
12
12
|
} from "./chunk-PFYAAX2S.js";
|
|
13
13
|
|
|
14
14
|
// src/symbols/semantic.ts
|
|
15
|
-
function
|
|
16
|
-
|
|
15
|
+
function pathTokens(absFile, root) {
|
|
16
|
+
if (!absFile) return "";
|
|
17
|
+
const norm = absFile.replace(/\\/g, "/");
|
|
18
|
+
let rel = norm;
|
|
19
|
+
if (root) {
|
|
20
|
+
const rootNorm = root.replace(/\\/g, "/").replace(/\/$/, "") + "/";
|
|
21
|
+
if (norm.toLowerCase().startsWith(rootNorm.toLowerCase())) {
|
|
22
|
+
rel = norm.slice(rootNorm.length);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const noExt = rel.replace(/\.[^./]+$/, "");
|
|
26
|
+
const parts = noExt.split(/[/.\-_]/).filter((t) => {
|
|
27
|
+
if (!t) return false;
|
|
28
|
+
if (t.length < 2) return false;
|
|
29
|
+
if (/^\d+$/.test(t)) return false;
|
|
30
|
+
if (t === "src" || t === "lib" || t === "app" || t === "dist") return false;
|
|
31
|
+
return true;
|
|
32
|
+
});
|
|
33
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34
|
+
const out = [];
|
|
35
|
+
for (const t of parts) {
|
|
36
|
+
const lower = t.toLowerCase();
|
|
37
|
+
if (seen.has(lower)) continue;
|
|
38
|
+
seen.add(lower);
|
|
39
|
+
out.push(t);
|
|
40
|
+
if (out.length >= 6) break;
|
|
41
|
+
}
|
|
42
|
+
return out.join(" ");
|
|
43
|
+
}
|
|
44
|
+
function buildEmbeddingText(s, root) {
|
|
45
|
+
const parts = [];
|
|
46
|
+
if (root) {
|
|
47
|
+
const tokens = pathTokens(s.location.file, root);
|
|
48
|
+
if (tokens) parts.push(tokens);
|
|
49
|
+
}
|
|
50
|
+
parts.push(s.kind, s.name);
|
|
17
51
|
if (s.container) parts.push(`in ${s.container}`);
|
|
18
52
|
if (s.signature) parts.push(s.signature);
|
|
19
53
|
if (s.doc) parts.push(s.doc);
|
|
@@ -42,7 +76,7 @@ async function rebuildSemanticIndex(root, opts = {}) {
|
|
|
42
76
|
const batch = [];
|
|
43
77
|
for (let j = i; j < end; j++) {
|
|
44
78
|
symbolIdx[j] = j;
|
|
45
|
-
batch.push(buildEmbeddingText(index.symbols[j]));
|
|
79
|
+
batch.push(buildEmbeddingText(index.symbols[j], index.root));
|
|
46
80
|
}
|
|
47
81
|
const batchStart = Date.now();
|
|
48
82
|
const rows = await embed(batch);
|
|
@@ -77,6 +111,7 @@ function hasSemanticIndex(root) {
|
|
|
77
111
|
}
|
|
78
112
|
|
|
79
113
|
export {
|
|
114
|
+
pathTokens,
|
|
80
115
|
buildEmbeddingText,
|
|
81
116
|
rebuildSemanticIndex,
|
|
82
117
|
semanticSearch,
|
|
@@ -13,13 +13,13 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
hasSemanticIndex,
|
|
15
15
|
semanticSearch
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-CQQQFNND.js";
|
|
17
17
|
import {
|
|
18
18
|
loadIndex
|
|
19
19
|
} from "./chunk-6VRJGH25.js";
|
|
20
20
|
import {
|
|
21
21
|
runTestsTool
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-IGHC7D62.js";
|
|
23
23
|
import {
|
|
24
24
|
CONFIG_DIR_NAME,
|
|
25
25
|
DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
SUBAGENT_ALLOWED_TOOLS,
|
|
28
28
|
SUBAGENT_DEFAULT_MAX_ROUNDS,
|
|
29
29
|
SUBAGENT_MAX_ROUNDS_LIMIT
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-2ERX5Q55.js";
|
|
31
31
|
|
|
32
32
|
// src/tools/builtin/bash.ts
|
|
33
33
|
import { execSync } from "child_process";
|
|
@@ -11,8 +11,42 @@ import {
|
|
|
11
11
|
} from "./chunk-XMA222FQ.js";
|
|
12
12
|
|
|
13
13
|
// src/symbols/semantic.ts
|
|
14
|
-
function
|
|
15
|
-
|
|
14
|
+
function pathTokens(absFile, root) {
|
|
15
|
+
if (!absFile) return "";
|
|
16
|
+
const norm = absFile.replace(/\\/g, "/");
|
|
17
|
+
let rel = norm;
|
|
18
|
+
if (root) {
|
|
19
|
+
const rootNorm = root.replace(/\\/g, "/").replace(/\/$/, "") + "/";
|
|
20
|
+
if (norm.toLowerCase().startsWith(rootNorm.toLowerCase())) {
|
|
21
|
+
rel = norm.slice(rootNorm.length);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const noExt = rel.replace(/\.[^./]+$/, "");
|
|
25
|
+
const parts = noExt.split(/[/.\-_]/).filter((t) => {
|
|
26
|
+
if (!t) return false;
|
|
27
|
+
if (t.length < 2) return false;
|
|
28
|
+
if (/^\d+$/.test(t)) return false;
|
|
29
|
+
if (t === "src" || t === "lib" || t === "app" || t === "dist") return false;
|
|
30
|
+
return true;
|
|
31
|
+
});
|
|
32
|
+
const seen = /* @__PURE__ */ new Set();
|
|
33
|
+
const out = [];
|
|
34
|
+
for (const t of parts) {
|
|
35
|
+
const lower = t.toLowerCase();
|
|
36
|
+
if (seen.has(lower)) continue;
|
|
37
|
+
seen.add(lower);
|
|
38
|
+
out.push(t);
|
|
39
|
+
if (out.length >= 6) break;
|
|
40
|
+
}
|
|
41
|
+
return out.join(" ");
|
|
42
|
+
}
|
|
43
|
+
function buildEmbeddingText(s, root) {
|
|
44
|
+
const parts = [];
|
|
45
|
+
if (root) {
|
|
46
|
+
const tokens = pathTokens(s.location.file, root);
|
|
47
|
+
if (tokens) parts.push(tokens);
|
|
48
|
+
}
|
|
49
|
+
parts.push(s.kind, s.name);
|
|
16
50
|
if (s.container) parts.push(`in ${s.container}`);
|
|
17
51
|
if (s.signature) parts.push(s.signature);
|
|
18
52
|
if (s.doc) parts.push(s.doc);
|
|
@@ -41,7 +75,7 @@ async function rebuildSemanticIndex(root, opts = {}) {
|
|
|
41
75
|
const batch = [];
|
|
42
76
|
for (let j = i; j < end; j++) {
|
|
43
77
|
symbolIdx[j] = j;
|
|
44
|
-
batch.push(buildEmbeddingText(index.symbols[j]));
|
|
78
|
+
batch.push(buildEmbeddingText(index.symbols[j], index.root));
|
|
45
79
|
}
|
|
46
80
|
const batchStart = Date.now();
|
|
47
81
|
const rows = await embed(batch);
|
|
@@ -76,6 +110,7 @@ function hasSemanticIndex(root) {
|
|
|
76
110
|
}
|
|
77
111
|
|
|
78
112
|
export {
|
|
113
|
+
pathTokens,
|
|
79
114
|
buildEmbeddingText,
|
|
80
115
|
rebuildSemanticIndex,
|
|
81
116
|
semanticSearch,
|
package/dist/electron-server.js
CHANGED
|
@@ -36,11 +36,11 @@ import {
|
|
|
36
36
|
VERSION,
|
|
37
37
|
buildUserIdentityPrompt,
|
|
38
38
|
runTestsTool
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-63R2GIRK.js";
|
|
40
40
|
import {
|
|
41
41
|
hasSemanticIndex,
|
|
42
42
|
semanticSearch
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-GTKJUEBS.js";
|
|
44
44
|
import {
|
|
45
45
|
loadIndex
|
|
46
46
|
} from "./chunk-BJAT4GNC.js";
|
|
@@ -2516,6 +2516,12 @@ function getContentText(content) {
|
|
|
2516
2516
|
function makeBranchId() {
|
|
2517
2517
|
return Math.random().toString(16).slice(2, 8);
|
|
2518
2518
|
}
|
|
2519
|
+
function messagesEqual(a, b) {
|
|
2520
|
+
if (a.role !== b.role) return false;
|
|
2521
|
+
if (JSON.stringify(a.content) !== JSON.stringify(b.content)) return false;
|
|
2522
|
+
if (JSON.stringify(a.toolCalls ?? null) !== JSON.stringify(b.toolCalls ?? null)) return false;
|
|
2523
|
+
return true;
|
|
2524
|
+
}
|
|
2519
2525
|
var Session = class _Session {
|
|
2520
2526
|
id;
|
|
2521
2527
|
provider;
|
|
@@ -2757,6 +2763,51 @@ var Session = class _Session {
|
|
|
2757
2763
|
const m = this._inactiveBranchMessages.get(id);
|
|
2758
2764
|
return m ? m.slice() : null;
|
|
2759
2765
|
}
|
|
2766
|
+
// ── B3 Branch diff + cherry-pick (v0.4.80+) ────────────────────────
|
|
2767
|
+
/**
|
|
2768
|
+
* Compare messages between two branches. Finds the longest common prefix
|
|
2769
|
+
* by message equality (role + content + toolCalls shape) — NOT by fork
|
|
2770
|
+
* point metadata, so user-edited histories still diff cleanly.
|
|
2771
|
+
*
|
|
2772
|
+
* @param sourceId Branch to compare
|
|
2773
|
+
* @param targetId Branch to compare against (defaults to active branch)
|
|
2774
|
+
* @returns BranchDiff, or null if either branch id is unknown
|
|
2775
|
+
*/
|
|
2776
|
+
diffBranches(sourceId, targetId) {
|
|
2777
|
+
const tgt = targetId ?? this.activeBranchId;
|
|
2778
|
+
const src = this.getBranchMessages(sourceId);
|
|
2779
|
+
const dst = this.getBranchMessages(tgt);
|
|
2780
|
+
if (!src || !dst) return null;
|
|
2781
|
+
let i = 0;
|
|
2782
|
+
while (i < src.length && i < dst.length && messagesEqual(src[i], dst[i])) i++;
|
|
2783
|
+
return {
|
|
2784
|
+
sourceId,
|
|
2785
|
+
targetId: tgt,
|
|
2786
|
+
commonPrefix: i,
|
|
2787
|
+
sourceOnly: src.slice(i),
|
|
2788
|
+
targetOnly: dst.slice(i)
|
|
2789
|
+
};
|
|
2790
|
+
}
|
|
2791
|
+
/**
|
|
2792
|
+
* Copy a single message from another branch into the active branch
|
|
2793
|
+
* (appended at the end). Timestamp is reset to now so it's clear when
|
|
2794
|
+
* the cherry-pick happened.
|
|
2795
|
+
*
|
|
2796
|
+
* @returns the cloned message, or null if sourceId / msgIndex is invalid
|
|
2797
|
+
*/
|
|
2798
|
+
cherryPickMessage(sourceId, msgIndex) {
|
|
2799
|
+
const src = this.getBranchMessages(sourceId);
|
|
2800
|
+
if (!src) return null;
|
|
2801
|
+
if (msgIndex < 0 || msgIndex >= src.length) return null;
|
|
2802
|
+
const orig = src[msgIndex];
|
|
2803
|
+
const copy = {
|
|
2804
|
+
...orig,
|
|
2805
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
2806
|
+
};
|
|
2807
|
+
this.messages.push(copy);
|
|
2808
|
+
this.updated = /* @__PURE__ */ new Date();
|
|
2809
|
+
return copy;
|
|
2810
|
+
}
|
|
2760
2811
|
getMeta() {
|
|
2761
2812
|
return {
|
|
2762
2813
|
id: this.id,
|
|
@@ -10241,7 +10292,7 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
10241
10292
|
" /diff [--stats] \u2014 Show file modifications in this session",
|
|
10242
10293
|
" /checkpoint [save|restore|delete] <name> \u2014 Session checkpoints",
|
|
10243
10294
|
" /fork [checkpoint] \u2014 Fork session from checkpoint or current",
|
|
10244
|
-
" /branch [list|new|switch|delete|rename] \u2014 Manage conversation branches",
|
|
10295
|
+
" /branch [list|new|switch|delete|rename|diff|cherry-pick] \u2014 Manage conversation branches (fork tree, cross-branch picks)",
|
|
10245
10296
|
" /index [status|rebuild|clear|semantic-rebuild|semantic-clear] \u2014 Symbol + semantic index (find_symbol / search_code)",
|
|
10246
10297
|
" /review [--staged] \u2014 AI code review from git diff",
|
|
10247
10298
|
" /security-review \u2014 Security vulnerability scan on git diff",
|
|
@@ -10581,7 +10632,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
10581
10632
|
lines.push(` ${marker}${b.id.padEnd(10)} ${b.title.padEnd(20)} (${count} msgs)${parent}`);
|
|
10582
10633
|
}
|
|
10583
10634
|
lines.push("");
|
|
10584
|
-
lines.push("Usage: /branch new <msgIndex> [title] | switch <id> | delete <id> | rename <id> <title>");
|
|
10635
|
+
lines.push("Usage: /branch new <msgIndex> [title] | switch <id> | delete <id> | rename <id> <title> | diff <id> | cherry-pick <id> <msgIndex>");
|
|
10585
10636
|
this.send({ type: "info", message: lines.join("\n") });
|
|
10586
10637
|
break;
|
|
10587
10638
|
}
|
|
@@ -10659,7 +10710,70 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
10659
10710
|
}
|
|
10660
10711
|
break;
|
|
10661
10712
|
}
|
|
10662
|
-
|
|
10713
|
+
if (sub === "diff") {
|
|
10714
|
+
const id = args[1];
|
|
10715
|
+
if (!id) {
|
|
10716
|
+
this.send({ type: "error", message: "Usage: /branch diff <id>" });
|
|
10717
|
+
break;
|
|
10718
|
+
}
|
|
10719
|
+
const d = session.diffBranches(id);
|
|
10720
|
+
if (!d) {
|
|
10721
|
+
this.send({ type: "error", message: `Branch "${id}" not found.` });
|
|
10722
|
+
break;
|
|
10723
|
+
}
|
|
10724
|
+
const preview = (m) => {
|
|
10725
|
+
const text = typeof m.content === "string" ? m.content : "[complex content]";
|
|
10726
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 70);
|
|
10727
|
+
};
|
|
10728
|
+
const lines = [
|
|
10729
|
+
`\u{1F500} diff ${id} (source) \u2194 ${session.activeBranchId} (active)`,
|
|
10730
|
+
`Common prefix: ${d.commonPrefix} message(s)`
|
|
10731
|
+
];
|
|
10732
|
+
if (d.sourceOnly.length === 0 && d.targetOnly.length === 0) {
|
|
10733
|
+
lines.push("Branches are identical.");
|
|
10734
|
+
} else {
|
|
10735
|
+
if (d.sourceOnly.length > 0) {
|
|
10736
|
+
lines.push("", `Only in ${id} (${d.sourceOnly.length}):`);
|
|
10737
|
+
d.sourceOnly.forEach(
|
|
10738
|
+
(m, i) => lines.push(` [${d.commonPrefix + i}] ${m.role}: ${preview(m)}`)
|
|
10739
|
+
);
|
|
10740
|
+
}
|
|
10741
|
+
if (d.targetOnly.length > 0) {
|
|
10742
|
+
lines.push("", `Only in ${session.activeBranchId} (active) (${d.targetOnly.length}):`);
|
|
10743
|
+
d.targetOnly.forEach(
|
|
10744
|
+
(m, i) => lines.push(` [${d.commonPrefix + i}] ${m.role}: ${preview(m)}`)
|
|
10745
|
+
);
|
|
10746
|
+
}
|
|
10747
|
+
lines.push("", `Use /branch cherry-pick ${id} <index> to copy a message into the active branch.`);
|
|
10748
|
+
}
|
|
10749
|
+
this.send({ type: "info", message: lines.join("\n") });
|
|
10750
|
+
break;
|
|
10751
|
+
}
|
|
10752
|
+
if (sub === "cherry-pick") {
|
|
10753
|
+
const id = args[1];
|
|
10754
|
+
const idxStr = args[2];
|
|
10755
|
+
if (!id || !idxStr) {
|
|
10756
|
+
this.send({ type: "error", message: "Usage: /branch cherry-pick <source-id> <msg-index>" });
|
|
10757
|
+
break;
|
|
10758
|
+
}
|
|
10759
|
+
const idx = parseInt(idxStr, 10);
|
|
10760
|
+
if (Number.isNaN(idx)) {
|
|
10761
|
+
this.send({ type: "error", message: `Invalid message index: "${idxStr}"` });
|
|
10762
|
+
break;
|
|
10763
|
+
}
|
|
10764
|
+
const picked = session.cherryPickMessage(id, idx);
|
|
10765
|
+
if (!picked) {
|
|
10766
|
+
this.send({ type: "error", message: `Cherry-pick failed \u2014 branch "${id}" not found, or index ${idx} out of range.` });
|
|
10767
|
+
break;
|
|
10768
|
+
}
|
|
10769
|
+
await this.sessions.save();
|
|
10770
|
+
const preview = typeof picked.content === "string" ? picked.content.replace(/\s+/g, " ").trim().slice(0, 60) : "[complex content]";
|
|
10771
|
+
this.send({ type: "info", message: `\u2713 Cherry-picked ${picked.role} message from "${id}"[${idx}] \u2192 active branch (${session.messages.length} msgs): ${preview}` });
|
|
10772
|
+
this.sendSessionMessages();
|
|
10773
|
+
this.sendStatus();
|
|
10774
|
+
break;
|
|
10775
|
+
}
|
|
10776
|
+
this.send({ type: "error", message: `Unknown subcommand: ${sub}. Use list/new/switch/delete/rename/diff/cherry-pick.` });
|
|
10663
10777
|
break;
|
|
10664
10778
|
}
|
|
10665
10779
|
// ── /index ──────────────────────────────────────────────────────
|
|
@@ -10705,12 +10819,19 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
10705
10819
|
this.send({ type: "error", message: "No symbol index yet. Run /index rebuild first." });
|
|
10706
10820
|
break;
|
|
10707
10821
|
}
|
|
10822
|
+
if (idx.symbolCount === 0) {
|
|
10823
|
+
this.send({
|
|
10824
|
+
type: "error",
|
|
10825
|
+
message: "No code symbols to embed. Semantic search needs TS/TSX/JS/JSX/Python source files \u2014 this project appears to have none. Not downloading the embedding model."
|
|
10826
|
+
});
|
|
10827
|
+
break;
|
|
10828
|
+
}
|
|
10708
10829
|
this.send({
|
|
10709
10830
|
type: "info",
|
|
10710
10831
|
message: `Building semantic index for ${idx.symbolCount} symbols\u2026 (first run downloads ~117 MB model)`
|
|
10711
10832
|
});
|
|
10712
10833
|
try {
|
|
10713
|
-
const { rebuildSemanticIndex } = await import("./semantic-
|
|
10834
|
+
const { rebuildSemanticIndex } = await import("./semantic-MYAXLDCZ.js");
|
|
10714
10835
|
const stats = await rebuildSemanticIndex(root);
|
|
10715
10836
|
const first = stats.modelFirstLoadMs ? ` (model load+first batch ${stats.modelFirstLoadMs}ms)` : "";
|
|
10716
10837
|
this.send({
|
|
@@ -10897,7 +11018,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
10897
11018
|
case "test": {
|
|
10898
11019
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
10899
11020
|
try {
|
|
10900
|
-
const { executeTests } = await import("./run-tests-
|
|
11021
|
+
const { executeTests } = await import("./run-tests-4PZKLURD.js");
|
|
10901
11022
|
const argStr = args.join(" ").trim();
|
|
10902
11023
|
let testArgs = {};
|
|
10903
11024
|
if (argStr) {
|
|
@@ -385,7 +385,7 @@ ${content}`);
|
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
387
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
388
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
388
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-RVKRP6LI.js");
|
|
389
389
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
390
390
|
let interrupted = false;
|
|
391
391
|
const onSigint = () => {
|
package/dist/index.js
CHANGED
|
@@ -30,10 +30,10 @@ import {
|
|
|
30
30
|
saveDevState,
|
|
31
31
|
sessionHasMeaningfulContent,
|
|
32
32
|
setupProxy
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-6HZTXVTF.js";
|
|
34
34
|
import {
|
|
35
35
|
ConfigManager
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-C5QENJ4P.js";
|
|
37
37
|
import {
|
|
38
38
|
ToolExecutor,
|
|
39
39
|
ToolRegistry,
|
|
@@ -49,16 +49,16 @@ import {
|
|
|
49
49
|
spawnAgentContext,
|
|
50
50
|
theme,
|
|
51
51
|
undoStack
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-CU5ZSHGU.js";
|
|
53
53
|
import "./chunk-2ZD3YTVM.js";
|
|
54
54
|
import {
|
|
55
55
|
fileCheckpoints
|
|
56
56
|
} from "./chunk-4BKXL7SM.js";
|
|
57
57
|
import "./chunk-NHNWUBXB.js";
|
|
58
|
-
import "./chunk-
|
|
58
|
+
import "./chunk-CQQQFNND.js";
|
|
59
59
|
import "./chunk-6VRJGH25.js";
|
|
60
60
|
import "./chunk-PFYAAX2S.js";
|
|
61
|
-
import "./chunk-
|
|
61
|
+
import "./chunk-IGHC7D62.js";
|
|
62
62
|
import {
|
|
63
63
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
64
64
|
AUTHOR,
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
SKILLS_DIR_NAME,
|
|
81
81
|
VERSION,
|
|
82
82
|
buildUserIdentityPrompt
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-2ERX5Q55.js";
|
|
84
84
|
|
|
85
85
|
// src/index.ts
|
|
86
86
|
import { program } from "commander";
|
|
@@ -978,7 +978,7 @@ function createDefaultCommands() {
|
|
|
978
978
|
" /bug [--copy] - Generate bug report template (--copy to clipboard)",
|
|
979
979
|
" /diff [--stats] - Show all file modifications in this session",
|
|
980
980
|
" /fork [checkpoint] - Fork session from checkpoint or current position",
|
|
981
|
-
" /branch [list|new|switch|delete|rename] - Manage conversation branches (fork tree)",
|
|
981
|
+
" /branch [list|new|switch|delete|rename|diff|cherry-pick] - Manage conversation branches (fork tree, cross-branch picks)",
|
|
982
982
|
" /index [status|rebuild|clear|semantic-rebuild|semantic-clear] - Symbol + semantic index (find_symbol / search_code)",
|
|
983
983
|
" /yolo [on|off] - Toggle session auto-approve (skip confirmations)",
|
|
984
984
|
" /exit - Exit"
|
|
@@ -2254,7 +2254,7 @@ ${hint}` : "")
|
|
|
2254
2254
|
{
|
|
2255
2255
|
name: "branch",
|
|
2256
2256
|
description: "Manage conversation branches (fork/switch/list/delete/rename)",
|
|
2257
|
-
usage: "/branch [list | new <msgIndex> [title] | switch <id> | delete <id> | rename <id> <title>]",
|
|
2257
|
+
usage: "/branch [list | new <msgIndex> [title] | switch <id> | delete <id> | rename <id> <title> | diff <id> | cherry-pick <id> <msgIndex>]",
|
|
2258
2258
|
async execute(args, ctx) {
|
|
2259
2259
|
const session = ctx.sessions.current;
|
|
2260
2260
|
if (!session) {
|
|
@@ -2280,6 +2280,8 @@ ${hint}` : "")
|
|
|
2280
2280
|
console.log(theme.dim(" /branch switch <id> \u2014 switch active branch"));
|
|
2281
2281
|
console.log(theme.dim(" /branch delete <id> \u2014 delete inactive branch"));
|
|
2282
2282
|
console.log(theme.dim(" /branch rename <id> <title> \u2014 rename a branch"));
|
|
2283
|
+
console.log(theme.dim(" /branch diff <id> \u2014 compare branch with active, list divergent messages"));
|
|
2284
|
+
console.log(theme.dim(" /branch cherry-pick <id> <idx> \u2014 copy one message from branch <id> into active"));
|
|
2283
2285
|
console.log();
|
|
2284
2286
|
return;
|
|
2285
2287
|
}
|
|
@@ -2363,7 +2365,74 @@ ${hint}` : "")
|
|
|
2363
2365
|
}
|
|
2364
2366
|
return;
|
|
2365
2367
|
}
|
|
2366
|
-
|
|
2368
|
+
if (sub === "diff") {
|
|
2369
|
+
const id = args[1];
|
|
2370
|
+
if (!id) {
|
|
2371
|
+
ctx.renderer.renderError("Usage: /branch diff <id> \u2014 diff the given branch against the active branch");
|
|
2372
|
+
return;
|
|
2373
|
+
}
|
|
2374
|
+
const d = session.diffBranches(id);
|
|
2375
|
+
if (!d) {
|
|
2376
|
+
ctx.renderer.renderError(`Branch "${id}" not found.`);
|
|
2377
|
+
return;
|
|
2378
|
+
}
|
|
2379
|
+
const active = session.activeBranchId;
|
|
2380
|
+
console.log(`
|
|
2381
|
+
${theme.info("diff")} ${id} (source) \u2194 ${active} (active)`);
|
|
2382
|
+
console.log(theme.dim(` Common prefix: ${d.commonPrefix} message(s)`));
|
|
2383
|
+
if (d.sourceOnly.length === 0 && d.targetOnly.length === 0) {
|
|
2384
|
+
console.log(theme.success(" Branches are identical.\n"));
|
|
2385
|
+
return;
|
|
2386
|
+
}
|
|
2387
|
+
const preview = (m) => {
|
|
2388
|
+
const text = typeof m.content === "string" ? m.content : "[complex content]";
|
|
2389
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 70);
|
|
2390
|
+
};
|
|
2391
|
+
if (d.sourceOnly.length > 0) {
|
|
2392
|
+
console.log(theme.dim(`
|
|
2393
|
+
Only in ${id} (${d.sourceOnly.length}):`));
|
|
2394
|
+
d.sourceOnly.forEach((m, i) => {
|
|
2395
|
+
console.log(` ${theme.dim(`[${d.commonPrefix + i}]`)} ${m.role}: ${preview(m)}`);
|
|
2396
|
+
});
|
|
2397
|
+
}
|
|
2398
|
+
if (d.targetOnly.length > 0) {
|
|
2399
|
+
console.log(theme.dim(`
|
|
2400
|
+
Only in ${active} (active) (${d.targetOnly.length}):`));
|
|
2401
|
+
d.targetOnly.forEach((m, i) => {
|
|
2402
|
+
console.log(` ${theme.dim(`[${d.commonPrefix + i}]`)} ${m.role}: ${preview(m)}`);
|
|
2403
|
+
});
|
|
2404
|
+
}
|
|
2405
|
+
console.log(theme.dim(`
|
|
2406
|
+
Use /branch cherry-pick ${id} <index> to copy a message into the active branch.
|
|
2407
|
+
`));
|
|
2408
|
+
return;
|
|
2409
|
+
}
|
|
2410
|
+
if (sub === "cherry-pick") {
|
|
2411
|
+
const id = args[1];
|
|
2412
|
+
const idxStr = args[2];
|
|
2413
|
+
if (!id || !idxStr) {
|
|
2414
|
+
ctx.renderer.renderError("Usage: /branch cherry-pick <source-id> <msg-index>");
|
|
2415
|
+
return;
|
|
2416
|
+
}
|
|
2417
|
+
const idx = parseInt(idxStr, 10);
|
|
2418
|
+
if (Number.isNaN(idx)) {
|
|
2419
|
+
ctx.renderer.renderError(`Invalid message index: "${idxStr}"`);
|
|
2420
|
+
return;
|
|
2421
|
+
}
|
|
2422
|
+
const picked = session.cherryPickMessage(id, idx);
|
|
2423
|
+
if (!picked) {
|
|
2424
|
+
ctx.renderer.renderError(`Cherry-pick failed \u2014 branch "${id}" not found, or index ${idx} out of range.`);
|
|
2425
|
+
return;
|
|
2426
|
+
}
|
|
2427
|
+
await ctx.sessions.save();
|
|
2428
|
+
const preview = typeof picked.content === "string" ? picked.content.replace(/\s+/g, " ").trim().slice(0, 60) : "[complex content]";
|
|
2429
|
+
console.log(theme.success(`
|
|
2430
|
+
\u2713 Cherry-picked ${picked.role} message from "${id}"[${idx}] \u2192 active branch (now ${session.messages.length} msgs)`));
|
|
2431
|
+
console.log(theme.dim(` ${preview}
|
|
2432
|
+
`));
|
|
2433
|
+
return;
|
|
2434
|
+
}
|
|
2435
|
+
ctx.renderer.renderError(`Unknown subcommand: ${sub}. Use list/new/switch/delete/rename/diff/cherry-pick.`);
|
|
2367
2436
|
}
|
|
2368
2437
|
},
|
|
2369
2438
|
// ── /index ────────────────────────────────────────────────────
|
|
@@ -2427,9 +2496,15 @@ ${hint}` : "")
|
|
|
2427
2496
|
ctx.renderer.renderError("No symbol index yet. Run `/index rebuild` first, then semantic-rebuild.");
|
|
2428
2497
|
return;
|
|
2429
2498
|
}
|
|
2499
|
+
if (idx.symbolCount === 0) {
|
|
2500
|
+
ctx.renderer.renderError(
|
|
2501
|
+
"No code symbols to embed. Semantic search needs source files in TS/TSX/JS/JSX/Python \u2014 this project appears to have none (check `/index rebuild` output). Nothing to do; not downloading the embedding model."
|
|
2502
|
+
);
|
|
2503
|
+
return;
|
|
2504
|
+
}
|
|
2430
2505
|
console.log(theme.dim(` Building semantic index for ${idx.symbolCount} symbols\u2026`));
|
|
2431
2506
|
console.log(theme.dim(" (First run downloads ~117 MB embedding model to ~/.aicli/models/)"));
|
|
2432
|
-
const { rebuildSemanticIndex } = await import("./semantic-
|
|
2507
|
+
const { rebuildSemanticIndex } = await import("./semantic-ICJ536BG.js");
|
|
2433
2508
|
try {
|
|
2434
2509
|
const stats = await rebuildSemanticIndex(root, {
|
|
2435
2510
|
onProgress: (done, total) => {
|
|
@@ -2495,7 +2570,7 @@ ${hint}` : "")
|
|
|
2495
2570
|
usage: "/test [command|filter]",
|
|
2496
2571
|
async execute(args, ctx) {
|
|
2497
2572
|
try {
|
|
2498
|
-
const { executeTests } = await import("./run-tests-
|
|
2573
|
+
const { executeTests } = await import("./run-tests-7N2WILA3.js");
|
|
2499
2574
|
const argStr = args.join(" ").trim();
|
|
2500
2575
|
let testArgs = {};
|
|
2501
2576
|
if (argStr) {
|
|
@@ -6388,7 +6463,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
6388
6463
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
6389
6464
|
process.exit(1);
|
|
6390
6465
|
}
|
|
6391
|
-
const { startWebServer } = await import("./server-
|
|
6466
|
+
const { startWebServer } = await import("./server-HJ64OR7A.js");
|
|
6392
6467
|
await startWebServer({ port, host: options.host });
|
|
6393
6468
|
});
|
|
6394
6469
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -6511,7 +6586,7 @@ program.command("sessions").description("List recent conversation sessions").act
|
|
|
6511
6586
|
});
|
|
6512
6587
|
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) => {
|
|
6513
6588
|
try {
|
|
6514
|
-
const batch = await import("./batch-
|
|
6589
|
+
const batch = await import("./batch-OUBKAHXG.js");
|
|
6515
6590
|
switch (action) {
|
|
6516
6591
|
case "submit":
|
|
6517
6592
|
if (!arg) {
|
|
@@ -6671,7 +6746,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
6671
6746
|
}),
|
|
6672
6747
|
config.get("customProviders")
|
|
6673
6748
|
);
|
|
6674
|
-
const { startHub } = await import("./hub-
|
|
6749
|
+
const { startHub } = await import("./hub-SFJU4KJK.js");
|
|
6675
6750
|
await startHub(
|
|
6676
6751
|
{
|
|
6677
6752
|
topic: topic ?? "",
|
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
buildEmbeddingText,
|
|
4
4
|
hasSemanticIndex,
|
|
5
|
+
pathTokens,
|
|
5
6
|
rebuildSemanticIndex,
|
|
6
7
|
semanticSearch
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-CQQQFNND.js";
|
|
8
9
|
import "./chunk-6VRJGH25.js";
|
|
9
10
|
import "./chunk-PFYAAX2S.js";
|
|
10
11
|
export {
|
|
11
12
|
buildEmbeddingText,
|
|
12
13
|
hasSemanticIndex,
|
|
14
|
+
pathTokens,
|
|
13
15
|
rebuildSemanticIndex,
|
|
14
16
|
semanticSearch
|
|
15
17
|
};
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildEmbeddingText,
|
|
3
3
|
hasSemanticIndex,
|
|
4
|
+
pathTokens,
|
|
4
5
|
rebuildSemanticIndex,
|
|
5
6
|
semanticSearch
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GTKJUEBS.js";
|
|
7
8
|
import "./chunk-BJAT4GNC.js";
|
|
8
9
|
import "./chunk-XMA222FQ.js";
|
|
9
10
|
export {
|
|
10
11
|
buildEmbeddingText,
|
|
11
12
|
hasSemanticIndex,
|
|
13
|
+
pathTokens,
|
|
12
14
|
rebuildSemanticIndex,
|
|
13
15
|
semanticSearch
|
|
14
16
|
};
|
|
@@ -20,10 +20,10 @@ import {
|
|
|
20
20
|
persistToolRound,
|
|
21
21
|
rebuildExtraMessages,
|
|
22
22
|
setupProxy
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-6HZTXVTF.js";
|
|
24
24
|
import {
|
|
25
25
|
ConfigManager
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-C5QENJ4P.js";
|
|
27
27
|
import {
|
|
28
28
|
ToolExecutor,
|
|
29
29
|
ToolRegistry,
|
|
@@ -41,14 +41,14 @@ import {
|
|
|
41
41
|
spawnAgentContext,
|
|
42
42
|
truncateOutput,
|
|
43
43
|
undoStack
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-CU5ZSHGU.js";
|
|
45
45
|
import "./chunk-2ZD3YTVM.js";
|
|
46
46
|
import "./chunk-4BKXL7SM.js";
|
|
47
47
|
import "./chunk-NHNWUBXB.js";
|
|
48
|
-
import "./chunk-
|
|
48
|
+
import "./chunk-CQQQFNND.js";
|
|
49
49
|
import "./chunk-6VRJGH25.js";
|
|
50
50
|
import "./chunk-PFYAAX2S.js";
|
|
51
|
-
import "./chunk-
|
|
51
|
+
import "./chunk-IGHC7D62.js";
|
|
52
52
|
import {
|
|
53
53
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
54
54
|
AUTHOR,
|
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
SKILLS_DIR_NAME,
|
|
68
68
|
VERSION,
|
|
69
69
|
buildUserIdentityPrompt
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-2ERX5Q55.js";
|
|
71
71
|
import {
|
|
72
72
|
AuthManager
|
|
73
73
|
} from "./chunk-BYNY5JPB.js";
|
|
@@ -1482,7 +1482,7 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
1482
1482
|
" /diff [--stats] \u2014 Show file modifications in this session",
|
|
1483
1483
|
" /checkpoint [save|restore|delete] <name> \u2014 Session checkpoints",
|
|
1484
1484
|
" /fork [checkpoint] \u2014 Fork session from checkpoint or current",
|
|
1485
|
-
" /branch [list|new|switch|delete|rename] \u2014 Manage conversation branches",
|
|
1485
|
+
" /branch [list|new|switch|delete|rename|diff|cherry-pick] \u2014 Manage conversation branches (fork tree, cross-branch picks)",
|
|
1486
1486
|
" /index [status|rebuild|clear|semantic-rebuild|semantic-clear] \u2014 Symbol + semantic index (find_symbol / search_code)",
|
|
1487
1487
|
" /review [--staged] \u2014 AI code review from git diff",
|
|
1488
1488
|
" /security-review \u2014 Security vulnerability scan on git diff",
|
|
@@ -1822,7 +1822,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1822
1822
|
lines.push(` ${marker}${b.id.padEnd(10)} ${b.title.padEnd(20)} (${count} msgs)${parent}`);
|
|
1823
1823
|
}
|
|
1824
1824
|
lines.push("");
|
|
1825
|
-
lines.push("Usage: /branch new <msgIndex> [title] | switch <id> | delete <id> | rename <id> <title>");
|
|
1825
|
+
lines.push("Usage: /branch new <msgIndex> [title] | switch <id> | delete <id> | rename <id> <title> | diff <id> | cherry-pick <id> <msgIndex>");
|
|
1826
1826
|
this.send({ type: "info", message: lines.join("\n") });
|
|
1827
1827
|
break;
|
|
1828
1828
|
}
|
|
@@ -1900,7 +1900,70 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1900
1900
|
}
|
|
1901
1901
|
break;
|
|
1902
1902
|
}
|
|
1903
|
-
|
|
1903
|
+
if (sub === "diff") {
|
|
1904
|
+
const id = args[1];
|
|
1905
|
+
if (!id) {
|
|
1906
|
+
this.send({ type: "error", message: "Usage: /branch diff <id>" });
|
|
1907
|
+
break;
|
|
1908
|
+
}
|
|
1909
|
+
const d = session.diffBranches(id);
|
|
1910
|
+
if (!d) {
|
|
1911
|
+
this.send({ type: "error", message: `Branch "${id}" not found.` });
|
|
1912
|
+
break;
|
|
1913
|
+
}
|
|
1914
|
+
const preview = (m) => {
|
|
1915
|
+
const text = typeof m.content === "string" ? m.content : "[complex content]";
|
|
1916
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 70);
|
|
1917
|
+
};
|
|
1918
|
+
const lines = [
|
|
1919
|
+
`\u{1F500} diff ${id} (source) \u2194 ${session.activeBranchId} (active)`,
|
|
1920
|
+
`Common prefix: ${d.commonPrefix} message(s)`
|
|
1921
|
+
];
|
|
1922
|
+
if (d.sourceOnly.length === 0 && d.targetOnly.length === 0) {
|
|
1923
|
+
lines.push("Branches are identical.");
|
|
1924
|
+
} else {
|
|
1925
|
+
if (d.sourceOnly.length > 0) {
|
|
1926
|
+
lines.push("", `Only in ${id} (${d.sourceOnly.length}):`);
|
|
1927
|
+
d.sourceOnly.forEach(
|
|
1928
|
+
(m, i) => lines.push(` [${d.commonPrefix + i}] ${m.role}: ${preview(m)}`)
|
|
1929
|
+
);
|
|
1930
|
+
}
|
|
1931
|
+
if (d.targetOnly.length > 0) {
|
|
1932
|
+
lines.push("", `Only in ${session.activeBranchId} (active) (${d.targetOnly.length}):`);
|
|
1933
|
+
d.targetOnly.forEach(
|
|
1934
|
+
(m, i) => lines.push(` [${d.commonPrefix + i}] ${m.role}: ${preview(m)}`)
|
|
1935
|
+
);
|
|
1936
|
+
}
|
|
1937
|
+
lines.push("", `Use /branch cherry-pick ${id} <index> to copy a message into the active branch.`);
|
|
1938
|
+
}
|
|
1939
|
+
this.send({ type: "info", message: lines.join("\n") });
|
|
1940
|
+
break;
|
|
1941
|
+
}
|
|
1942
|
+
if (sub === "cherry-pick") {
|
|
1943
|
+
const id = args[1];
|
|
1944
|
+
const idxStr = args[2];
|
|
1945
|
+
if (!id || !idxStr) {
|
|
1946
|
+
this.send({ type: "error", message: "Usage: /branch cherry-pick <source-id> <msg-index>" });
|
|
1947
|
+
break;
|
|
1948
|
+
}
|
|
1949
|
+
const idx = parseInt(idxStr, 10);
|
|
1950
|
+
if (Number.isNaN(idx)) {
|
|
1951
|
+
this.send({ type: "error", message: `Invalid message index: "${idxStr}"` });
|
|
1952
|
+
break;
|
|
1953
|
+
}
|
|
1954
|
+
const picked = session.cherryPickMessage(id, idx);
|
|
1955
|
+
if (!picked) {
|
|
1956
|
+
this.send({ type: "error", message: `Cherry-pick failed \u2014 branch "${id}" not found, or index ${idx} out of range.` });
|
|
1957
|
+
break;
|
|
1958
|
+
}
|
|
1959
|
+
await this.sessions.save();
|
|
1960
|
+
const preview = typeof picked.content === "string" ? picked.content.replace(/\s+/g, " ").trim().slice(0, 60) : "[complex content]";
|
|
1961
|
+
this.send({ type: "info", message: `\u2713 Cherry-picked ${picked.role} message from "${id}"[${idx}] \u2192 active branch (${session.messages.length} msgs): ${preview}` });
|
|
1962
|
+
this.sendSessionMessages();
|
|
1963
|
+
this.sendStatus();
|
|
1964
|
+
break;
|
|
1965
|
+
}
|
|
1966
|
+
this.send({ type: "error", message: `Unknown subcommand: ${sub}. Use list/new/switch/delete/rename/diff/cherry-pick.` });
|
|
1904
1967
|
break;
|
|
1905
1968
|
}
|
|
1906
1969
|
// ── /index ──────────────────────────────────────────────────────
|
|
@@ -1946,12 +2009,19 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1946
2009
|
this.send({ type: "error", message: "No symbol index yet. Run /index rebuild first." });
|
|
1947
2010
|
break;
|
|
1948
2011
|
}
|
|
2012
|
+
if (idx.symbolCount === 0) {
|
|
2013
|
+
this.send({
|
|
2014
|
+
type: "error",
|
|
2015
|
+
message: "No code symbols to embed. Semantic search needs TS/TSX/JS/JSX/Python source files \u2014 this project appears to have none. Not downloading the embedding model."
|
|
2016
|
+
});
|
|
2017
|
+
break;
|
|
2018
|
+
}
|
|
1949
2019
|
this.send({
|
|
1950
2020
|
type: "info",
|
|
1951
2021
|
message: `Building semantic index for ${idx.symbolCount} symbols\u2026 (first run downloads ~117 MB model)`
|
|
1952
2022
|
});
|
|
1953
2023
|
try {
|
|
1954
|
-
const { rebuildSemanticIndex } = await import("./semantic-
|
|
2024
|
+
const { rebuildSemanticIndex } = await import("./semantic-ICJ536BG.js");
|
|
1955
2025
|
const stats = await rebuildSemanticIndex(root);
|
|
1956
2026
|
const first = stats.modelFirstLoadMs ? ` (model load+first batch ${stats.modelFirstLoadMs}ms)` : "";
|
|
1957
2027
|
this.send({
|
|
@@ -2138,7 +2208,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2138
2208
|
case "test": {
|
|
2139
2209
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
2140
2210
|
try {
|
|
2141
|
-
const { executeTests } = await import("./run-tests-
|
|
2211
|
+
const { executeTests } = await import("./run-tests-7N2WILA3.js");
|
|
2142
2212
|
const argStr = args.join(" ").trim();
|
|
2143
2213
|
let testArgs = {};
|
|
2144
2214
|
if (argStr) {
|
|
@@ -4,17 +4,17 @@ import {
|
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
googleSearchContext,
|
|
6
6
|
truncateOutput
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-CU5ZSHGU.js";
|
|
8
8
|
import "./chunk-2ZD3YTVM.js";
|
|
9
9
|
import "./chunk-4BKXL7SM.js";
|
|
10
10
|
import "./chunk-NHNWUBXB.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-CQQQFNND.js";
|
|
12
12
|
import "./chunk-6VRJGH25.js";
|
|
13
13
|
import "./chunk-PFYAAX2S.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-IGHC7D62.js";
|
|
15
15
|
import {
|
|
16
16
|
SUBAGENT_ALLOWED_TOOLS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-2ERX5Q55.js";
|
|
18
18
|
|
|
19
19
|
// src/hub/task-orchestrator.ts
|
|
20
20
|
import { createInterface } from "readline";
|