jinzd-ai-cli 0.4.79 → 0.4.81
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-SMUURFMA.js → batch-JOYUXWBK.js} +2 -2
- package/dist/{chunk-ZT7RZYWE.js → chunk-44MKM6OO.js} +1 -1
- package/dist/{chunk-RRL5572W.js → chunk-BPIKBXGZ.js} +1 -1
- package/dist/{chunk-HPDDAXFY.js → chunk-CQQQFNND.js} +38 -3
- package/dist/{chunk-UTCC3UMT.js → chunk-GTKJUEBS.js} +38 -3
- package/dist/{chunk-MOE2D3NR.js → chunk-HFSSDFQN.js} +3 -3
- package/dist/{chunk-34OKHMTQ.js → chunk-JWE53S2U.js} +1 -1
- package/dist/{chunk-EGJAMKAZ.js → chunk-U7ZSIOKV.js} +84 -2
- package/dist/{chunk-FU6WMYXS.js → chunk-VEWRTIMX.js} +1 -1
- package/dist/electron-server.js +184 -18
- package/dist/{hub-BDEFIXFF.js → hub-WLBLPBT2.js} +1 -1
- package/dist/index.js +120 -29
- package/dist/{run-tests-O2CYJF3Y.js → run-tests-Q2GGLRK6.js} +1 -1
- package/dist/{run-tests-WPSQCOIG.js → run-tests-UX6KNA4R.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-MHY4E453.js → server-LXE5HXOQ.js} +106 -22
- package/dist/{task-orchestrator-MWZ7NMES.js → task-orchestrator-2GGIA6EG.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-JWE53S2U.js";
|
|
5
5
|
import "./chunk-2ZD3YTVM.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-BPIKBXGZ.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/batch.ts
|
|
9
9
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -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,
|
|
@@ -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,
|
|
@@ -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-44MKM6OO.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-BPIKBXGZ.js";
|
|
31
31
|
|
|
32
32
|
// src/tools/builtin/bash.ts
|
|
33
33
|
import { execSync } from "child_process";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
schemaToJsonSchema,
|
|
4
4
|
truncateForPersist
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-HFSSDFQN.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-BPIKBXGZ.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;
|
|
@@ -2370,12 +2376,88 @@ var Session = class _Session {
|
|
|
2370
2376
|
this.updated = /* @__PURE__ */ new Date();
|
|
2371
2377
|
return true;
|
|
2372
2378
|
}
|
|
2379
|
+
/**
|
|
2380
|
+
* Resolve a user-supplied branch reference (v0.4.81+).
|
|
2381
|
+
*
|
|
2382
|
+
* Accepts the 6-hex branch id, the branch's display title, or an unambiguous
|
|
2383
|
+
* id prefix (≥2 chars). This exists because users naturally type the title
|
|
2384
|
+
* they chose at `/branch new`, not the auto-generated id — every other
|
|
2385
|
+
* `/branch <sub>` used to error on that with "not found".
|
|
2386
|
+
*
|
|
2387
|
+
* Resolution order:
|
|
2388
|
+
* 1. Exact id match
|
|
2389
|
+
* 2. Exact title match (unique)
|
|
2390
|
+
* 3. Id prefix match (unique, length ≥ 2)
|
|
2391
|
+
*
|
|
2392
|
+
* @returns `{ ok: true, id }` on success; on failure `{ ok: false, reason, matches }`
|
|
2393
|
+
* where `matches` lists candidates for ambiguous input so callers
|
|
2394
|
+
* can render a helpful error.
|
|
2395
|
+
*/
|
|
2396
|
+
resolveBranchRef(ref) {
|
|
2397
|
+
if (!ref) return { ok: false, reason: "not-found", matches: [] };
|
|
2398
|
+
const byId = this.branches.find((b) => b.id === ref);
|
|
2399
|
+
if (byId) return { ok: true, id: byId.id };
|
|
2400
|
+
const byTitle = this.branches.filter((b) => b.title === ref);
|
|
2401
|
+
if (byTitle.length === 1) return { ok: true, id: byTitle[0].id };
|
|
2402
|
+
if (byTitle.length > 1) return { ok: false, reason: "ambiguous", matches: byTitle };
|
|
2403
|
+
if (ref.length >= 2) {
|
|
2404
|
+
const byPrefix = this.branches.filter((b) => b.id.startsWith(ref));
|
|
2405
|
+
if (byPrefix.length === 1) return { ok: true, id: byPrefix[0].id };
|
|
2406
|
+
if (byPrefix.length > 1) return { ok: false, reason: "ambiguous", matches: byPrefix };
|
|
2407
|
+
}
|
|
2408
|
+
return { ok: false, reason: "not-found", matches: [] };
|
|
2409
|
+
}
|
|
2373
2410
|
/** Messages of any branch (active or inactive) — read-only copy. */
|
|
2374
2411
|
getBranchMessages(id) {
|
|
2375
2412
|
if (id === this.activeBranchId) return this.messages.slice();
|
|
2376
2413
|
const m = this._inactiveBranchMessages.get(id);
|
|
2377
2414
|
return m ? m.slice() : null;
|
|
2378
2415
|
}
|
|
2416
|
+
// ── B3 Branch diff + cherry-pick (v0.4.80+) ────────────────────────
|
|
2417
|
+
/**
|
|
2418
|
+
* Compare messages between two branches. Finds the longest common prefix
|
|
2419
|
+
* by message equality (role + content + toolCalls shape) — NOT by fork
|
|
2420
|
+
* point metadata, so user-edited histories still diff cleanly.
|
|
2421
|
+
*
|
|
2422
|
+
* @param sourceId Branch to compare
|
|
2423
|
+
* @param targetId Branch to compare against (defaults to active branch)
|
|
2424
|
+
* @returns BranchDiff, or null if either branch id is unknown
|
|
2425
|
+
*/
|
|
2426
|
+
diffBranches(sourceId, targetId) {
|
|
2427
|
+
const tgt = targetId ?? this.activeBranchId;
|
|
2428
|
+
const src = this.getBranchMessages(sourceId);
|
|
2429
|
+
const dst = this.getBranchMessages(tgt);
|
|
2430
|
+
if (!src || !dst) return null;
|
|
2431
|
+
let i = 0;
|
|
2432
|
+
while (i < src.length && i < dst.length && messagesEqual(src[i], dst[i])) i++;
|
|
2433
|
+
return {
|
|
2434
|
+
sourceId,
|
|
2435
|
+
targetId: tgt,
|
|
2436
|
+
commonPrefix: i,
|
|
2437
|
+
sourceOnly: src.slice(i),
|
|
2438
|
+
targetOnly: dst.slice(i)
|
|
2439
|
+
};
|
|
2440
|
+
}
|
|
2441
|
+
/**
|
|
2442
|
+
* Copy a single message from another branch into the active branch
|
|
2443
|
+
* (appended at the end). Timestamp is reset to now so it's clear when
|
|
2444
|
+
* the cherry-pick happened.
|
|
2445
|
+
*
|
|
2446
|
+
* @returns the cloned message, or null if sourceId / msgIndex is invalid
|
|
2447
|
+
*/
|
|
2448
|
+
cherryPickMessage(sourceId, msgIndex) {
|
|
2449
|
+
const src = this.getBranchMessages(sourceId);
|
|
2450
|
+
if (!src) return null;
|
|
2451
|
+
if (msgIndex < 0 || msgIndex >= src.length) return null;
|
|
2452
|
+
const orig = src[msgIndex];
|
|
2453
|
+
const copy = {
|
|
2454
|
+
...orig,
|
|
2455
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
2456
|
+
};
|
|
2457
|
+
this.messages.push(copy);
|
|
2458
|
+
this.updated = /* @__PURE__ */ new Date();
|
|
2459
|
+
return copy;
|
|
2460
|
+
}
|
|
2379
2461
|
getMeta() {
|
|
2380
2462
|
return {
|
|
2381
2463
|
id: this.id,
|
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-VEWRTIMX.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;
|
|
@@ -2751,12 +2757,88 @@ var Session = class _Session {
|
|
|
2751
2757
|
this.updated = /* @__PURE__ */ new Date();
|
|
2752
2758
|
return true;
|
|
2753
2759
|
}
|
|
2760
|
+
/**
|
|
2761
|
+
* Resolve a user-supplied branch reference (v0.4.81+).
|
|
2762
|
+
*
|
|
2763
|
+
* Accepts the 6-hex branch id, the branch's display title, or an unambiguous
|
|
2764
|
+
* id prefix (≥2 chars). This exists because users naturally type the title
|
|
2765
|
+
* they chose at `/branch new`, not the auto-generated id — every other
|
|
2766
|
+
* `/branch <sub>` used to error on that with "not found".
|
|
2767
|
+
*
|
|
2768
|
+
* Resolution order:
|
|
2769
|
+
* 1. Exact id match
|
|
2770
|
+
* 2. Exact title match (unique)
|
|
2771
|
+
* 3. Id prefix match (unique, length ≥ 2)
|
|
2772
|
+
*
|
|
2773
|
+
* @returns `{ ok: true, id }` on success; on failure `{ ok: false, reason, matches }`
|
|
2774
|
+
* where `matches` lists candidates for ambiguous input so callers
|
|
2775
|
+
* can render a helpful error.
|
|
2776
|
+
*/
|
|
2777
|
+
resolveBranchRef(ref) {
|
|
2778
|
+
if (!ref) return { ok: false, reason: "not-found", matches: [] };
|
|
2779
|
+
const byId = this.branches.find((b) => b.id === ref);
|
|
2780
|
+
if (byId) return { ok: true, id: byId.id };
|
|
2781
|
+
const byTitle = this.branches.filter((b) => b.title === ref);
|
|
2782
|
+
if (byTitle.length === 1) return { ok: true, id: byTitle[0].id };
|
|
2783
|
+
if (byTitle.length > 1) return { ok: false, reason: "ambiguous", matches: byTitle };
|
|
2784
|
+
if (ref.length >= 2) {
|
|
2785
|
+
const byPrefix = this.branches.filter((b) => b.id.startsWith(ref));
|
|
2786
|
+
if (byPrefix.length === 1) return { ok: true, id: byPrefix[0].id };
|
|
2787
|
+
if (byPrefix.length > 1) return { ok: false, reason: "ambiguous", matches: byPrefix };
|
|
2788
|
+
}
|
|
2789
|
+
return { ok: false, reason: "not-found", matches: [] };
|
|
2790
|
+
}
|
|
2754
2791
|
/** Messages of any branch (active or inactive) — read-only copy. */
|
|
2755
2792
|
getBranchMessages(id) {
|
|
2756
2793
|
if (id === this.activeBranchId) return this.messages.slice();
|
|
2757
2794
|
const m = this._inactiveBranchMessages.get(id);
|
|
2758
2795
|
return m ? m.slice() : null;
|
|
2759
2796
|
}
|
|
2797
|
+
// ── B3 Branch diff + cherry-pick (v0.4.80+) ────────────────────────
|
|
2798
|
+
/**
|
|
2799
|
+
* Compare messages between two branches. Finds the longest common prefix
|
|
2800
|
+
* by message equality (role + content + toolCalls shape) — NOT by fork
|
|
2801
|
+
* point metadata, so user-edited histories still diff cleanly.
|
|
2802
|
+
*
|
|
2803
|
+
* @param sourceId Branch to compare
|
|
2804
|
+
* @param targetId Branch to compare against (defaults to active branch)
|
|
2805
|
+
* @returns BranchDiff, or null if either branch id is unknown
|
|
2806
|
+
*/
|
|
2807
|
+
diffBranches(sourceId, targetId) {
|
|
2808
|
+
const tgt = targetId ?? this.activeBranchId;
|
|
2809
|
+
const src = this.getBranchMessages(sourceId);
|
|
2810
|
+
const dst = this.getBranchMessages(tgt);
|
|
2811
|
+
if (!src || !dst) return null;
|
|
2812
|
+
let i = 0;
|
|
2813
|
+
while (i < src.length && i < dst.length && messagesEqual(src[i], dst[i])) i++;
|
|
2814
|
+
return {
|
|
2815
|
+
sourceId,
|
|
2816
|
+
targetId: tgt,
|
|
2817
|
+
commonPrefix: i,
|
|
2818
|
+
sourceOnly: src.slice(i),
|
|
2819
|
+
targetOnly: dst.slice(i)
|
|
2820
|
+
};
|
|
2821
|
+
}
|
|
2822
|
+
/**
|
|
2823
|
+
* Copy a single message from another branch into the active branch
|
|
2824
|
+
* (appended at the end). Timestamp is reset to now so it's clear when
|
|
2825
|
+
* the cherry-pick happened.
|
|
2826
|
+
*
|
|
2827
|
+
* @returns the cloned message, or null if sourceId / msgIndex is invalid
|
|
2828
|
+
*/
|
|
2829
|
+
cherryPickMessage(sourceId, msgIndex) {
|
|
2830
|
+
const src = this.getBranchMessages(sourceId);
|
|
2831
|
+
if (!src) return null;
|
|
2832
|
+
if (msgIndex < 0 || msgIndex >= src.length) return null;
|
|
2833
|
+
const orig = src[msgIndex];
|
|
2834
|
+
const copy = {
|
|
2835
|
+
...orig,
|
|
2836
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
2837
|
+
};
|
|
2838
|
+
this.messages.push(copy);
|
|
2839
|
+
this.updated = /* @__PURE__ */ new Date();
|
|
2840
|
+
return copy;
|
|
2841
|
+
}
|
|
2760
2842
|
getMeta() {
|
|
2761
2843
|
return {
|
|
2762
2844
|
id: this.id,
|
|
@@ -10241,7 +10323,7 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
10241
10323
|
" /diff [--stats] \u2014 Show file modifications in this session",
|
|
10242
10324
|
" /checkpoint [save|restore|delete] <name> \u2014 Session checkpoints",
|
|
10243
10325
|
" /fork [checkpoint] \u2014 Fork session from checkpoint or current",
|
|
10244
|
-
" /branch [list|new|switch|delete|rename] \u2014 Manage conversation branches",
|
|
10326
|
+
" /branch [list|new|switch|delete|rename|diff|cherry-pick] \u2014 Manage conversation branches (fork tree, cross-branch picks)",
|
|
10245
10327
|
" /index [status|rebuild|clear|semantic-rebuild|semantic-clear] \u2014 Symbol + semantic index (find_symbol / search_code)",
|
|
10246
10328
|
" /review [--staged] \u2014 AI code review from git diff",
|
|
10247
10329
|
" /security-review \u2014 Security vulnerability scan on git diff",
|
|
@@ -10571,6 +10653,17 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
10571
10653
|
break;
|
|
10572
10654
|
}
|
|
10573
10655
|
const sub = args[0]?.toLowerCase();
|
|
10656
|
+
const resolve6 = (ref) => {
|
|
10657
|
+
const r = session.resolveBranchRef(ref);
|
|
10658
|
+
if (r.ok) return r.id;
|
|
10659
|
+
if (r.reason === "ambiguous") {
|
|
10660
|
+
const list = r.matches.map((m) => `${m.id} (${m.title})`).join(", ");
|
|
10661
|
+
this.send({ type: "error", message: `Ambiguous branch reference "${ref}". Matches: ${list}. Use the 6-char id.` });
|
|
10662
|
+
} else {
|
|
10663
|
+
this.send({ type: "error", message: `Branch "${ref}" not found. Use /branch list to see all branches.` });
|
|
10664
|
+
}
|
|
10665
|
+
return null;
|
|
10666
|
+
};
|
|
10574
10667
|
if (!sub || sub === "list") {
|
|
10575
10668
|
const branches = session.listBranches();
|
|
10576
10669
|
const lines = [`\u{1F33F} Branches (${branches.length}):`, ""];
|
|
@@ -10581,7 +10674,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
10581
10674
|
lines.push(` ${marker}${b.id.padEnd(10)} ${b.title.padEnd(20)} (${count} msgs)${parent}`);
|
|
10582
10675
|
}
|
|
10583
10676
|
lines.push("");
|
|
10584
|
-
lines.push("Usage: /branch new <msgIndex> [title] | switch <id> | delete <id> | rename <id> <title>");
|
|
10677
|
+
lines.push("Usage: /branch new <msgIndex> [title] | switch <id|title> | delete <id|title> | rename <id|title> <new title> | diff <id|title> | cherry-pick <id|title> <msgIndex>");
|
|
10585
10678
|
this.send({ type: "info", message: lines.join("\n") });
|
|
10586
10679
|
break;
|
|
10587
10680
|
}
|
|
@@ -10609,11 +10702,13 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
10609
10702
|
break;
|
|
10610
10703
|
}
|
|
10611
10704
|
if (sub === "switch") {
|
|
10612
|
-
const
|
|
10613
|
-
if (!
|
|
10614
|
-
this.send({ type: "error", message: "Usage: /branch switch <id>" });
|
|
10705
|
+
const ref = args[1];
|
|
10706
|
+
if (!ref) {
|
|
10707
|
+
this.send({ type: "error", message: "Usage: /branch switch <id|title>" });
|
|
10615
10708
|
break;
|
|
10616
10709
|
}
|
|
10710
|
+
const id = resolve6(ref);
|
|
10711
|
+
if (!id) break;
|
|
10617
10712
|
const ok = session.switchBranch(id);
|
|
10618
10713
|
if (ok) {
|
|
10619
10714
|
await this.sessions.save();
|
|
@@ -10622,33 +10717,37 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
10622
10717
|
this.sendSessionMessages();
|
|
10623
10718
|
this.sendStatus();
|
|
10624
10719
|
} else {
|
|
10625
|
-
this.send({ type: "error", message: `Cannot switch to "${id}" (
|
|
10720
|
+
this.send({ type: "error", message: `Cannot switch to "${id}" (already active).` });
|
|
10626
10721
|
}
|
|
10627
10722
|
break;
|
|
10628
10723
|
}
|
|
10629
10724
|
if (sub === "delete") {
|
|
10630
|
-
const
|
|
10631
|
-
if (!
|
|
10632
|
-
this.send({ type: "error", message: "Usage: /branch delete <id>" });
|
|
10725
|
+
const ref = args[1];
|
|
10726
|
+
if (!ref) {
|
|
10727
|
+
this.send({ type: "error", message: "Usage: /branch delete <id|title>" });
|
|
10633
10728
|
break;
|
|
10634
10729
|
}
|
|
10730
|
+
const id = resolve6(ref);
|
|
10731
|
+
if (!id) break;
|
|
10635
10732
|
const ok = session.deleteBranch(id);
|
|
10636
10733
|
if (ok) {
|
|
10637
10734
|
await this.sessions.save();
|
|
10638
10735
|
this.send({ type: "info", message: `\u2713 Deleted branch "${id}"` });
|
|
10639
10736
|
this.sendStatus();
|
|
10640
10737
|
} else {
|
|
10641
|
-
this.send({ type: "error", message: `Cannot delete "${id}" (
|
|
10738
|
+
this.send({ type: "error", message: `Cannot delete "${id}" (active, or last remaining branch).` });
|
|
10642
10739
|
}
|
|
10643
10740
|
break;
|
|
10644
10741
|
}
|
|
10645
10742
|
if (sub === "rename") {
|
|
10646
|
-
const
|
|
10743
|
+
const ref = args[1];
|
|
10647
10744
|
const title = args.slice(2).join(" ").trim();
|
|
10648
|
-
if (!
|
|
10649
|
-
this.send({ type: "error", message: "Usage: /branch rename <id> <new title>" });
|
|
10745
|
+
if (!ref || !title) {
|
|
10746
|
+
this.send({ type: "error", message: "Usage: /branch rename <id|title> <new title>" });
|
|
10650
10747
|
break;
|
|
10651
10748
|
}
|
|
10749
|
+
const id = resolve6(ref);
|
|
10750
|
+
if (!id) break;
|
|
10652
10751
|
const ok = session.renameBranch(id, title);
|
|
10653
10752
|
if (ok) {
|
|
10654
10753
|
await this.sessions.save();
|
|
@@ -10659,7 +10758,74 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
10659
10758
|
}
|
|
10660
10759
|
break;
|
|
10661
10760
|
}
|
|
10662
|
-
|
|
10761
|
+
if (sub === "diff") {
|
|
10762
|
+
const ref = args[1];
|
|
10763
|
+
if (!ref) {
|
|
10764
|
+
this.send({ type: "error", message: "Usage: /branch diff <id|title>" });
|
|
10765
|
+
break;
|
|
10766
|
+
}
|
|
10767
|
+
const id = resolve6(ref);
|
|
10768
|
+
if (!id) break;
|
|
10769
|
+
const d = session.diffBranches(id);
|
|
10770
|
+
if (!d) {
|
|
10771
|
+
this.send({ type: "error", message: `Branch "${id}" not found.` });
|
|
10772
|
+
break;
|
|
10773
|
+
}
|
|
10774
|
+
const preview = (m) => {
|
|
10775
|
+
const text = typeof m.content === "string" ? m.content : "[complex content]";
|
|
10776
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 70);
|
|
10777
|
+
};
|
|
10778
|
+
const lines = [
|
|
10779
|
+
`\u{1F500} diff ${id} (source) \u2194 ${session.activeBranchId} (active)`,
|
|
10780
|
+
`Common prefix: ${d.commonPrefix} message(s)`
|
|
10781
|
+
];
|
|
10782
|
+
if (d.sourceOnly.length === 0 && d.targetOnly.length === 0) {
|
|
10783
|
+
lines.push("Branches are identical.");
|
|
10784
|
+
} else {
|
|
10785
|
+
if (d.sourceOnly.length > 0) {
|
|
10786
|
+
lines.push("", `Only in ${id} (${d.sourceOnly.length}):`);
|
|
10787
|
+
d.sourceOnly.forEach(
|
|
10788
|
+
(m, i) => lines.push(` [${d.commonPrefix + i}] ${m.role}: ${preview(m)}`)
|
|
10789
|
+
);
|
|
10790
|
+
}
|
|
10791
|
+
if (d.targetOnly.length > 0) {
|
|
10792
|
+
lines.push("", `Only in ${session.activeBranchId} (active) (${d.targetOnly.length}):`);
|
|
10793
|
+
d.targetOnly.forEach(
|
|
10794
|
+
(m, i) => lines.push(` [${d.commonPrefix + i}] ${m.role}: ${preview(m)}`)
|
|
10795
|
+
);
|
|
10796
|
+
}
|
|
10797
|
+
lines.push("", `Use /branch cherry-pick ${id} <index> to copy a message into the active branch.`);
|
|
10798
|
+
}
|
|
10799
|
+
this.send({ type: "info", message: lines.join("\n") });
|
|
10800
|
+
break;
|
|
10801
|
+
}
|
|
10802
|
+
if (sub === "cherry-pick") {
|
|
10803
|
+
const ref = args[1];
|
|
10804
|
+
const idxStr = args[2];
|
|
10805
|
+
if (!ref || !idxStr) {
|
|
10806
|
+
this.send({ type: "error", message: "Usage: /branch cherry-pick <source-id|title> <msg-index>" });
|
|
10807
|
+
break;
|
|
10808
|
+
}
|
|
10809
|
+
const id = resolve6(ref);
|
|
10810
|
+
if (!id) break;
|
|
10811
|
+
const idx = parseInt(idxStr, 10);
|
|
10812
|
+
if (Number.isNaN(idx)) {
|
|
10813
|
+
this.send({ type: "error", message: `Invalid message index: "${idxStr}"` });
|
|
10814
|
+
break;
|
|
10815
|
+
}
|
|
10816
|
+
const picked = session.cherryPickMessage(id, idx);
|
|
10817
|
+
if (!picked) {
|
|
10818
|
+
this.send({ type: "error", message: `Cherry-pick failed \u2014 index ${idx} out of range for branch "${id}".` });
|
|
10819
|
+
break;
|
|
10820
|
+
}
|
|
10821
|
+
await this.sessions.save();
|
|
10822
|
+
const preview = typeof picked.content === "string" ? picked.content.replace(/\s+/g, " ").trim().slice(0, 60) : "[complex content]";
|
|
10823
|
+
this.send({ type: "info", message: `\u2713 Cherry-picked ${picked.role} message from "${id}"[${idx}] \u2192 active branch (${session.messages.length} msgs): ${preview}` });
|
|
10824
|
+
this.sendSessionMessages();
|
|
10825
|
+
this.sendStatus();
|
|
10826
|
+
break;
|
|
10827
|
+
}
|
|
10828
|
+
this.send({ type: "error", message: `Unknown subcommand: ${sub}. Use list/new/switch/delete/rename/diff/cherry-pick.` });
|
|
10663
10829
|
break;
|
|
10664
10830
|
}
|
|
10665
10831
|
// ── /index ──────────────────────────────────────────────────────
|
|
@@ -10717,7 +10883,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
10717
10883
|
message: `Building semantic index for ${idx.symbolCount} symbols\u2026 (first run downloads ~117 MB model)`
|
|
10718
10884
|
});
|
|
10719
10885
|
try {
|
|
10720
|
-
const { rebuildSemanticIndex } = await import("./semantic-
|
|
10886
|
+
const { rebuildSemanticIndex } = await import("./semantic-MYAXLDCZ.js");
|
|
10721
10887
|
const stats = await rebuildSemanticIndex(root);
|
|
10722
10888
|
const first = stats.modelFirstLoadMs ? ` (model load+first batch ${stats.modelFirstLoadMs}ms)` : "";
|
|
10723
10889
|
this.send({
|
|
@@ -10904,7 +11070,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
10904
11070
|
case "test": {
|
|
10905
11071
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
10906
11072
|
try {
|
|
10907
|
-
const { executeTests } = await import("./run-tests-
|
|
11073
|
+
const { executeTests } = await import("./run-tests-Q2GGLRK6.js");
|
|
10908
11074
|
const argStr = args.join(" ").trim();
|
|
10909
11075
|
let testArgs = {};
|
|
10910
11076
|
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-2GGIA6EG.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-U7ZSIOKV.js";
|
|
34
34
|
import {
|
|
35
35
|
ConfigManager
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-JWE53S2U.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-HFSSDFQN.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-44MKM6OO.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-BPIKBXGZ.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|title> | delete <id|title> | rename <id|title> <new> | diff <id|title> | cherry-pick <id|title> <msgIndex>]",
|
|
2258
2258
|
async execute(args, ctx) {
|
|
2259
2259
|
const session = ctx.sessions.current;
|
|
2260
2260
|
if (!session) {
|
|
@@ -2262,6 +2262,17 @@ ${hint}` : "")
|
|
|
2262
2262
|
return;
|
|
2263
2263
|
}
|
|
2264
2264
|
const sub = args[0]?.toLowerCase();
|
|
2265
|
+
const resolve3 = (ref) => {
|
|
2266
|
+
const r = session.resolveBranchRef(ref);
|
|
2267
|
+
if (r.ok) return r.id;
|
|
2268
|
+
if (r.reason === "ambiguous") {
|
|
2269
|
+
const list = r.matches.map((m) => `${m.id} (${m.title})`).join(", ");
|
|
2270
|
+
ctx.renderer.renderError(`Ambiguous branch reference "${ref}". Matches: ${list}. Use the 6-char id.`);
|
|
2271
|
+
} else {
|
|
2272
|
+
ctx.renderer.renderError(`Branch "${ref}" not found. Try /branch list to see all branches.`);
|
|
2273
|
+
}
|
|
2274
|
+
return null;
|
|
2275
|
+
};
|
|
2265
2276
|
if (!sub || sub === "list") {
|
|
2266
2277
|
const branches = session.listBranches();
|
|
2267
2278
|
console.log(theme.heading(`
|
|
@@ -2276,10 +2287,13 @@ ${hint}` : "")
|
|
|
2276
2287
|
);
|
|
2277
2288
|
}
|
|
2278
2289
|
console.log();
|
|
2279
|
-
console.log(theme.dim(" /branch new <msgIndex> [title]
|
|
2280
|
-
console.log(theme.dim(" /branch switch <id>
|
|
2281
|
-
console.log(theme.dim(" /branch delete <id>
|
|
2282
|
-
console.log(theme.dim(" /branch rename <id> <
|
|
2290
|
+
console.log(theme.dim(" /branch new <msgIndex> [title] \u2014 fork active branch at message N"));
|
|
2291
|
+
console.log(theme.dim(" /branch switch <id|title> \u2014 switch active branch"));
|
|
2292
|
+
console.log(theme.dim(" /branch delete <id|title> \u2014 delete inactive branch"));
|
|
2293
|
+
console.log(theme.dim(" /branch rename <id|title> <new> \u2014 rename a branch"));
|
|
2294
|
+
console.log(theme.dim(" /branch diff <id|title> \u2014 compare branch with active, list divergent messages"));
|
|
2295
|
+
console.log(theme.dim(" /branch cherry-pick <id|title> <idx> \u2014 copy one message from branch into active"));
|
|
2296
|
+
console.log(theme.dim(" (id, title, or unique id-prefix all work)"));
|
|
2283
2297
|
console.log();
|
|
2284
2298
|
return;
|
|
2285
2299
|
}
|
|
@@ -2308,11 +2322,13 @@ ${hint}` : "")
|
|
|
2308
2322
|
return;
|
|
2309
2323
|
}
|
|
2310
2324
|
if (sub === "switch") {
|
|
2311
|
-
const
|
|
2312
|
-
if (!
|
|
2313
|
-
ctx.renderer.renderError("Usage: /branch switch <id>");
|
|
2325
|
+
const ref = args[1];
|
|
2326
|
+
if (!ref) {
|
|
2327
|
+
ctx.renderer.renderError("Usage: /branch switch <id|title>");
|
|
2314
2328
|
return;
|
|
2315
2329
|
}
|
|
2330
|
+
const id = resolve3(ref);
|
|
2331
|
+
if (!id) return;
|
|
2316
2332
|
const ok = session.switchBranch(id);
|
|
2317
2333
|
if (ok) {
|
|
2318
2334
|
await ctx.sessions.save();
|
|
@@ -2322,16 +2338,18 @@ ${hint}` : "")
|
|
|
2322
2338
|
console.log(theme.dim(` ${session.messages.length} messages on this branch
|
|
2323
2339
|
`));
|
|
2324
2340
|
} else {
|
|
2325
|
-
ctx.renderer.renderError(`Cannot switch to "${id}" (
|
|
2341
|
+
ctx.renderer.renderError(`Cannot switch to "${id}" (already active).`);
|
|
2326
2342
|
}
|
|
2327
2343
|
return;
|
|
2328
2344
|
}
|
|
2329
2345
|
if (sub === "delete") {
|
|
2330
|
-
const
|
|
2331
|
-
if (!
|
|
2332
|
-
ctx.renderer.renderError("Usage: /branch delete <id>");
|
|
2346
|
+
const ref = args[1];
|
|
2347
|
+
if (!ref) {
|
|
2348
|
+
ctx.renderer.renderError("Usage: /branch delete <id|title>");
|
|
2333
2349
|
return;
|
|
2334
2350
|
}
|
|
2351
|
+
const id = resolve3(ref);
|
|
2352
|
+
if (!id) return;
|
|
2335
2353
|
const ok = session.deleteBranch(id);
|
|
2336
2354
|
if (ok) {
|
|
2337
2355
|
await ctx.sessions.save();
|
|
@@ -2340,18 +2358,20 @@ ${hint}` : "")
|
|
|
2340
2358
|
`));
|
|
2341
2359
|
} else {
|
|
2342
2360
|
ctx.renderer.renderError(
|
|
2343
|
-
`Cannot delete "${id}" (
|
|
2361
|
+
`Cannot delete "${id}" (active, or last remaining branch).`
|
|
2344
2362
|
);
|
|
2345
2363
|
}
|
|
2346
2364
|
return;
|
|
2347
2365
|
}
|
|
2348
2366
|
if (sub === "rename") {
|
|
2349
|
-
const
|
|
2367
|
+
const ref = args[1];
|
|
2350
2368
|
const title = args.slice(2).join(" ").trim();
|
|
2351
|
-
if (!
|
|
2352
|
-
ctx.renderer.renderError("Usage: /branch rename <id> <new title>");
|
|
2369
|
+
if (!ref || !title) {
|
|
2370
|
+
ctx.renderer.renderError("Usage: /branch rename <id|title> <new title>");
|
|
2353
2371
|
return;
|
|
2354
2372
|
}
|
|
2373
|
+
const id = resolve3(ref);
|
|
2374
|
+
if (!id) return;
|
|
2355
2375
|
const ok = session.renameBranch(id, title);
|
|
2356
2376
|
if (ok) {
|
|
2357
2377
|
await ctx.sessions.save();
|
|
@@ -2363,7 +2383,78 @@ ${hint}` : "")
|
|
|
2363
2383
|
}
|
|
2364
2384
|
return;
|
|
2365
2385
|
}
|
|
2366
|
-
|
|
2386
|
+
if (sub === "diff") {
|
|
2387
|
+
const ref = args[1];
|
|
2388
|
+
if (!ref) {
|
|
2389
|
+
ctx.renderer.renderError("Usage: /branch diff <id|title> \u2014 diff the given branch against the active branch");
|
|
2390
|
+
return;
|
|
2391
|
+
}
|
|
2392
|
+
const id = resolve3(ref);
|
|
2393
|
+
if (!id) return;
|
|
2394
|
+
const d = session.diffBranches(id);
|
|
2395
|
+
if (!d) {
|
|
2396
|
+
ctx.renderer.renderError(`Branch "${id}" not found.`);
|
|
2397
|
+
return;
|
|
2398
|
+
}
|
|
2399
|
+
const active = session.activeBranchId;
|
|
2400
|
+
console.log(`
|
|
2401
|
+
${theme.info("diff")} ${id} (source) \u2194 ${active} (active)`);
|
|
2402
|
+
console.log(theme.dim(` Common prefix: ${d.commonPrefix} message(s)`));
|
|
2403
|
+
if (d.sourceOnly.length === 0 && d.targetOnly.length === 0) {
|
|
2404
|
+
console.log(theme.success(" Branches are identical.\n"));
|
|
2405
|
+
return;
|
|
2406
|
+
}
|
|
2407
|
+
const preview = (m) => {
|
|
2408
|
+
const text = typeof m.content === "string" ? m.content : "[complex content]";
|
|
2409
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 70);
|
|
2410
|
+
};
|
|
2411
|
+
if (d.sourceOnly.length > 0) {
|
|
2412
|
+
console.log(theme.dim(`
|
|
2413
|
+
Only in ${id} (${d.sourceOnly.length}):`));
|
|
2414
|
+
d.sourceOnly.forEach((m, i) => {
|
|
2415
|
+
console.log(` ${theme.dim(`[${d.commonPrefix + i}]`)} ${m.role}: ${preview(m)}`);
|
|
2416
|
+
});
|
|
2417
|
+
}
|
|
2418
|
+
if (d.targetOnly.length > 0) {
|
|
2419
|
+
console.log(theme.dim(`
|
|
2420
|
+
Only in ${active} (active) (${d.targetOnly.length}):`));
|
|
2421
|
+
d.targetOnly.forEach((m, i) => {
|
|
2422
|
+
console.log(` ${theme.dim(`[${d.commonPrefix + i}]`)} ${m.role}: ${preview(m)}`);
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
console.log(theme.dim(`
|
|
2426
|
+
Use /branch cherry-pick ${id} <index> to copy a message into the active branch.
|
|
2427
|
+
`));
|
|
2428
|
+
return;
|
|
2429
|
+
}
|
|
2430
|
+
if (sub === "cherry-pick") {
|
|
2431
|
+
const ref = args[1];
|
|
2432
|
+
const idxStr = args[2];
|
|
2433
|
+
if (!ref || !idxStr) {
|
|
2434
|
+
ctx.renderer.renderError("Usage: /branch cherry-pick <source-id|title> <msg-index>");
|
|
2435
|
+
return;
|
|
2436
|
+
}
|
|
2437
|
+
const id = resolve3(ref);
|
|
2438
|
+
if (!id) return;
|
|
2439
|
+
const idx = parseInt(idxStr, 10);
|
|
2440
|
+
if (Number.isNaN(idx)) {
|
|
2441
|
+
ctx.renderer.renderError(`Invalid message index: "${idxStr}"`);
|
|
2442
|
+
return;
|
|
2443
|
+
}
|
|
2444
|
+
const picked = session.cherryPickMessage(id, idx);
|
|
2445
|
+
if (!picked) {
|
|
2446
|
+
ctx.renderer.renderError(`Cherry-pick failed \u2014 index ${idx} out of range for branch "${id}".`);
|
|
2447
|
+
return;
|
|
2448
|
+
}
|
|
2449
|
+
await ctx.sessions.save();
|
|
2450
|
+
const preview = typeof picked.content === "string" ? picked.content.replace(/\s+/g, " ").trim().slice(0, 60) : "[complex content]";
|
|
2451
|
+
console.log(theme.success(`
|
|
2452
|
+
\u2713 Cherry-picked ${picked.role} message from "${id}"[${idx}] \u2192 active branch (now ${session.messages.length} msgs)`));
|
|
2453
|
+
console.log(theme.dim(` ${preview}
|
|
2454
|
+
`));
|
|
2455
|
+
return;
|
|
2456
|
+
}
|
|
2457
|
+
ctx.renderer.renderError(`Unknown subcommand: ${sub}. Use list/new/switch/delete/rename/diff/cherry-pick.`);
|
|
2367
2458
|
}
|
|
2368
2459
|
},
|
|
2369
2460
|
// ── /index ────────────────────────────────────────────────────
|
|
@@ -2435,7 +2526,7 @@ ${hint}` : "")
|
|
|
2435
2526
|
}
|
|
2436
2527
|
console.log(theme.dim(` Building semantic index for ${idx.symbolCount} symbols\u2026`));
|
|
2437
2528
|
console.log(theme.dim(" (First run downloads ~117 MB embedding model to ~/.aicli/models/)"));
|
|
2438
|
-
const { rebuildSemanticIndex } = await import("./semantic-
|
|
2529
|
+
const { rebuildSemanticIndex } = await import("./semantic-ICJ536BG.js");
|
|
2439
2530
|
try {
|
|
2440
2531
|
const stats = await rebuildSemanticIndex(root, {
|
|
2441
2532
|
onProgress: (done, total) => {
|
|
@@ -2501,7 +2592,7 @@ ${hint}` : "")
|
|
|
2501
2592
|
usage: "/test [command|filter]",
|
|
2502
2593
|
async execute(args, ctx) {
|
|
2503
2594
|
try {
|
|
2504
|
-
const { executeTests } = await import("./run-tests-
|
|
2595
|
+
const { executeTests } = await import("./run-tests-UX6KNA4R.js");
|
|
2505
2596
|
const argStr = args.join(" ").trim();
|
|
2506
2597
|
let testArgs = {};
|
|
2507
2598
|
if (argStr) {
|
|
@@ -6394,7 +6485,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
6394
6485
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
6395
6486
|
process.exit(1);
|
|
6396
6487
|
}
|
|
6397
|
-
const { startWebServer } = await import("./server-
|
|
6488
|
+
const { startWebServer } = await import("./server-LXE5HXOQ.js");
|
|
6398
6489
|
await startWebServer({ port, host: options.host });
|
|
6399
6490
|
});
|
|
6400
6491
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -6517,7 +6608,7 @@ program.command("sessions").description("List recent conversation sessions").act
|
|
|
6517
6608
|
});
|
|
6518
6609
|
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) => {
|
|
6519
6610
|
try {
|
|
6520
|
-
const batch = await import("./batch-
|
|
6611
|
+
const batch = await import("./batch-JOYUXWBK.js");
|
|
6521
6612
|
switch (action) {
|
|
6522
6613
|
case "submit":
|
|
6523
6614
|
if (!arg) {
|
|
@@ -6677,7 +6768,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
6677
6768
|
}),
|
|
6678
6769
|
config.get("customProviders")
|
|
6679
6770
|
);
|
|
6680
|
-
const { startHub } = await import("./hub-
|
|
6771
|
+
const { startHub } = await import("./hub-WLBLPBT2.js");
|
|
6681
6772
|
await startHub(
|
|
6682
6773
|
{
|
|
6683
6774
|
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-U7ZSIOKV.js";
|
|
24
24
|
import {
|
|
25
25
|
ConfigManager
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-JWE53S2U.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-HFSSDFQN.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-44MKM6OO.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-BPIKBXGZ.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",
|
|
@@ -1812,6 +1812,17 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1812
1812
|
break;
|
|
1813
1813
|
}
|
|
1814
1814
|
const sub = args[0]?.toLowerCase();
|
|
1815
|
+
const resolve3 = (ref) => {
|
|
1816
|
+
const r = session.resolveBranchRef(ref);
|
|
1817
|
+
if (r.ok) return r.id;
|
|
1818
|
+
if (r.reason === "ambiguous") {
|
|
1819
|
+
const list = r.matches.map((m) => `${m.id} (${m.title})`).join(", ");
|
|
1820
|
+
this.send({ type: "error", message: `Ambiguous branch reference "${ref}". Matches: ${list}. Use the 6-char id.` });
|
|
1821
|
+
} else {
|
|
1822
|
+
this.send({ type: "error", message: `Branch "${ref}" not found. Use /branch list to see all branches.` });
|
|
1823
|
+
}
|
|
1824
|
+
return null;
|
|
1825
|
+
};
|
|
1815
1826
|
if (!sub || sub === "list") {
|
|
1816
1827
|
const branches = session.listBranches();
|
|
1817
1828
|
const lines = [`\u{1F33F} Branches (${branches.length}):`, ""];
|
|
@@ -1822,7 +1833,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1822
1833
|
lines.push(` ${marker}${b.id.padEnd(10)} ${b.title.padEnd(20)} (${count} msgs)${parent}`);
|
|
1823
1834
|
}
|
|
1824
1835
|
lines.push("");
|
|
1825
|
-
lines.push("Usage: /branch new <msgIndex> [title] | switch <id> | delete <id> | rename <id> <title>");
|
|
1836
|
+
lines.push("Usage: /branch new <msgIndex> [title] | switch <id|title> | delete <id|title> | rename <id|title> <new title> | diff <id|title> | cherry-pick <id|title> <msgIndex>");
|
|
1826
1837
|
this.send({ type: "info", message: lines.join("\n") });
|
|
1827
1838
|
break;
|
|
1828
1839
|
}
|
|
@@ -1850,11 +1861,13 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1850
1861
|
break;
|
|
1851
1862
|
}
|
|
1852
1863
|
if (sub === "switch") {
|
|
1853
|
-
const
|
|
1854
|
-
if (!
|
|
1855
|
-
this.send({ type: "error", message: "Usage: /branch switch <id>" });
|
|
1864
|
+
const ref = args[1];
|
|
1865
|
+
if (!ref) {
|
|
1866
|
+
this.send({ type: "error", message: "Usage: /branch switch <id|title>" });
|
|
1856
1867
|
break;
|
|
1857
1868
|
}
|
|
1869
|
+
const id = resolve3(ref);
|
|
1870
|
+
if (!id) break;
|
|
1858
1871
|
const ok = session.switchBranch(id);
|
|
1859
1872
|
if (ok) {
|
|
1860
1873
|
await this.sessions.save();
|
|
@@ -1863,33 +1876,37 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1863
1876
|
this.sendSessionMessages();
|
|
1864
1877
|
this.sendStatus();
|
|
1865
1878
|
} else {
|
|
1866
|
-
this.send({ type: "error", message: `Cannot switch to "${id}" (
|
|
1879
|
+
this.send({ type: "error", message: `Cannot switch to "${id}" (already active).` });
|
|
1867
1880
|
}
|
|
1868
1881
|
break;
|
|
1869
1882
|
}
|
|
1870
1883
|
if (sub === "delete") {
|
|
1871
|
-
const
|
|
1872
|
-
if (!
|
|
1873
|
-
this.send({ type: "error", message: "Usage: /branch delete <id>" });
|
|
1884
|
+
const ref = args[1];
|
|
1885
|
+
if (!ref) {
|
|
1886
|
+
this.send({ type: "error", message: "Usage: /branch delete <id|title>" });
|
|
1874
1887
|
break;
|
|
1875
1888
|
}
|
|
1889
|
+
const id = resolve3(ref);
|
|
1890
|
+
if (!id) break;
|
|
1876
1891
|
const ok = session.deleteBranch(id);
|
|
1877
1892
|
if (ok) {
|
|
1878
1893
|
await this.sessions.save();
|
|
1879
1894
|
this.send({ type: "info", message: `\u2713 Deleted branch "${id}"` });
|
|
1880
1895
|
this.sendStatus();
|
|
1881
1896
|
} else {
|
|
1882
|
-
this.send({ type: "error", message: `Cannot delete "${id}" (
|
|
1897
|
+
this.send({ type: "error", message: `Cannot delete "${id}" (active, or last remaining branch).` });
|
|
1883
1898
|
}
|
|
1884
1899
|
break;
|
|
1885
1900
|
}
|
|
1886
1901
|
if (sub === "rename") {
|
|
1887
|
-
const
|
|
1902
|
+
const ref = args[1];
|
|
1888
1903
|
const title = args.slice(2).join(" ").trim();
|
|
1889
|
-
if (!
|
|
1890
|
-
this.send({ type: "error", message: "Usage: /branch rename <id> <new title>" });
|
|
1904
|
+
if (!ref || !title) {
|
|
1905
|
+
this.send({ type: "error", message: "Usage: /branch rename <id|title> <new title>" });
|
|
1891
1906
|
break;
|
|
1892
1907
|
}
|
|
1908
|
+
const id = resolve3(ref);
|
|
1909
|
+
if (!id) break;
|
|
1893
1910
|
const ok = session.renameBranch(id, title);
|
|
1894
1911
|
if (ok) {
|
|
1895
1912
|
await this.sessions.save();
|
|
@@ -1900,7 +1917,74 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1900
1917
|
}
|
|
1901
1918
|
break;
|
|
1902
1919
|
}
|
|
1903
|
-
|
|
1920
|
+
if (sub === "diff") {
|
|
1921
|
+
const ref = args[1];
|
|
1922
|
+
if (!ref) {
|
|
1923
|
+
this.send({ type: "error", message: "Usage: /branch diff <id|title>" });
|
|
1924
|
+
break;
|
|
1925
|
+
}
|
|
1926
|
+
const id = resolve3(ref);
|
|
1927
|
+
if (!id) break;
|
|
1928
|
+
const d = session.diffBranches(id);
|
|
1929
|
+
if (!d) {
|
|
1930
|
+
this.send({ type: "error", message: `Branch "${id}" not found.` });
|
|
1931
|
+
break;
|
|
1932
|
+
}
|
|
1933
|
+
const preview = (m) => {
|
|
1934
|
+
const text = typeof m.content === "string" ? m.content : "[complex content]";
|
|
1935
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 70);
|
|
1936
|
+
};
|
|
1937
|
+
const lines = [
|
|
1938
|
+
`\u{1F500} diff ${id} (source) \u2194 ${session.activeBranchId} (active)`,
|
|
1939
|
+
`Common prefix: ${d.commonPrefix} message(s)`
|
|
1940
|
+
];
|
|
1941
|
+
if (d.sourceOnly.length === 0 && d.targetOnly.length === 0) {
|
|
1942
|
+
lines.push("Branches are identical.");
|
|
1943
|
+
} else {
|
|
1944
|
+
if (d.sourceOnly.length > 0) {
|
|
1945
|
+
lines.push("", `Only in ${id} (${d.sourceOnly.length}):`);
|
|
1946
|
+
d.sourceOnly.forEach(
|
|
1947
|
+
(m, i) => lines.push(` [${d.commonPrefix + i}] ${m.role}: ${preview(m)}`)
|
|
1948
|
+
);
|
|
1949
|
+
}
|
|
1950
|
+
if (d.targetOnly.length > 0) {
|
|
1951
|
+
lines.push("", `Only in ${session.activeBranchId} (active) (${d.targetOnly.length}):`);
|
|
1952
|
+
d.targetOnly.forEach(
|
|
1953
|
+
(m, i) => lines.push(` [${d.commonPrefix + i}] ${m.role}: ${preview(m)}`)
|
|
1954
|
+
);
|
|
1955
|
+
}
|
|
1956
|
+
lines.push("", `Use /branch cherry-pick ${id} <index> to copy a message into the active branch.`);
|
|
1957
|
+
}
|
|
1958
|
+
this.send({ type: "info", message: lines.join("\n") });
|
|
1959
|
+
break;
|
|
1960
|
+
}
|
|
1961
|
+
if (sub === "cherry-pick") {
|
|
1962
|
+
const ref = args[1];
|
|
1963
|
+
const idxStr = args[2];
|
|
1964
|
+
if (!ref || !idxStr) {
|
|
1965
|
+
this.send({ type: "error", message: "Usage: /branch cherry-pick <source-id|title> <msg-index>" });
|
|
1966
|
+
break;
|
|
1967
|
+
}
|
|
1968
|
+
const id = resolve3(ref);
|
|
1969
|
+
if (!id) break;
|
|
1970
|
+
const idx = parseInt(idxStr, 10);
|
|
1971
|
+
if (Number.isNaN(idx)) {
|
|
1972
|
+
this.send({ type: "error", message: `Invalid message index: "${idxStr}"` });
|
|
1973
|
+
break;
|
|
1974
|
+
}
|
|
1975
|
+
const picked = session.cherryPickMessage(id, idx);
|
|
1976
|
+
if (!picked) {
|
|
1977
|
+
this.send({ type: "error", message: `Cherry-pick failed \u2014 index ${idx} out of range for branch "${id}".` });
|
|
1978
|
+
break;
|
|
1979
|
+
}
|
|
1980
|
+
await this.sessions.save();
|
|
1981
|
+
const preview = typeof picked.content === "string" ? picked.content.replace(/\s+/g, " ").trim().slice(0, 60) : "[complex content]";
|
|
1982
|
+
this.send({ type: "info", message: `\u2713 Cherry-picked ${picked.role} message from "${id}"[${idx}] \u2192 active branch (${session.messages.length} msgs): ${preview}` });
|
|
1983
|
+
this.sendSessionMessages();
|
|
1984
|
+
this.sendStatus();
|
|
1985
|
+
break;
|
|
1986
|
+
}
|
|
1987
|
+
this.send({ type: "error", message: `Unknown subcommand: ${sub}. Use list/new/switch/delete/rename/diff/cherry-pick.` });
|
|
1904
1988
|
break;
|
|
1905
1989
|
}
|
|
1906
1990
|
// ── /index ──────────────────────────────────────────────────────
|
|
@@ -1958,7 +2042,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1958
2042
|
message: `Building semantic index for ${idx.symbolCount} symbols\u2026 (first run downloads ~117 MB model)`
|
|
1959
2043
|
});
|
|
1960
2044
|
try {
|
|
1961
|
-
const { rebuildSemanticIndex } = await import("./semantic-
|
|
2045
|
+
const { rebuildSemanticIndex } = await import("./semantic-ICJ536BG.js");
|
|
1962
2046
|
const stats = await rebuildSemanticIndex(root);
|
|
1963
2047
|
const first = stats.modelFirstLoadMs ? ` (model load+first batch ${stats.modelFirstLoadMs}ms)` : "";
|
|
1964
2048
|
this.send({
|
|
@@ -2145,7 +2229,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2145
2229
|
case "test": {
|
|
2146
2230
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
2147
2231
|
try {
|
|
2148
|
-
const { executeTests } = await import("./run-tests-
|
|
2232
|
+
const { executeTests } = await import("./run-tests-UX6KNA4R.js");
|
|
2149
2233
|
const argStr = args.join(" ").trim();
|
|
2150
2234
|
let testArgs = {};
|
|
2151
2235
|
if (argStr) {
|
|
@@ -4,17 +4,17 @@ import {
|
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
googleSearchContext,
|
|
6
6
|
truncateOutput
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HFSSDFQN.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-44MKM6OO.js";
|
|
15
15
|
import {
|
|
16
16
|
SUBAGENT_ALLOWED_TOOLS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-BPIKBXGZ.js";
|
|
18
18
|
|
|
19
19
|
// src/hub/task-orchestrator.ts
|
|
20
20
|
import { createInterface } from "readline";
|