@hizliemre/horse-code 0.2.0 → 0.3.1
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/{app-2GPGCDX6.js → app-4WN37LZ3.js} +282 -57
- package/dist/{chunk-7JMWPTJ5.js → chunk-27F44PBD.js} +221 -1363
- package/dist/{chunk-23CLQ2KO.js → chunk-2WXG35EM.js} +19 -15
- package/dist/{chunk-LNW557IO.js → chunk-372X5HHU.js} +2 -2
- package/dist/{chunk-5ZV42XGJ.js → chunk-3ACDNDCG.js} +1 -1
- package/dist/{chunk-XEGQT5EN.js → chunk-4M6LXNG2.js} +1 -1
- package/dist/{chunk-6OSEQOYY.js → chunk-6S4WWQMN.js} +2 -2
- package/dist/{chunk-LLL7QWXB.js → chunk-BFIZMM4G.js} +6 -6
- package/dist/chunk-CYLPQWIF.js +214 -0
- package/dist/chunk-G45RWL7S.js +289 -0
- package/dist/{chunk-AE36LLL2.js → chunk-JLWQCA7B.js} +2 -209
- package/dist/{chunk-KKWZBZYK.js → chunk-JR2JLRE3.js} +26 -4
- package/dist/{run-P6ZYL5JL.js → chunk-QJYVZPLG.js} +133 -389
- package/dist/{chunk-UGESK765.js → chunk-UTHLEW5V.js} +1 -1
- package/dist/chunk-YULQ4URQ.js +1220 -0
- package/dist/{chunk-KAGKX2YT.js → chunk-ZPJP2VH5.js} +10 -1
- package/dist/cli.js +586 -104
- package/dist/{fix-JOIXQFVP.js → fix-QCL5AITT.js} +10 -8
- package/dist/{ongoing-WHYXPW24.js → ongoing-6NUSPSCV.js} +3 -2
- package/dist/{project-graph-5HNPRFQG.js → project-graph-OGIM2B33.js} +1 -1
- package/dist/run-V5ZLZ3LS.js +274 -0
- package/dist/{save-skills-X7U3KCPU.js → save-skills-NPKTYNAF.js} +2 -1
- package/dist/{trace-X6TU3AG6.js → trace-UVMZZRA5.js} +1 -1
- package/dist/{trace-adopt-URECQWJV.js → trace-adopt-7HWELJFE.js} +1 -1
- package/dist/{trace-run-7U4WJZ3V.js → trace-run-CZWEZ4R6.js} +8 -4
- package/dist/{triage-FCYHD2AQ.js → triage-IFCVL5MA.js} +7 -6
- package/dist/{verify-6SC4I77M.js → verify-HWZBTK5X.js} +16 -12
- package/package.json +1 -1
- package/dist/chunk-MRZVA5JB.js +0 -163
|
@@ -10,46 +10,51 @@ import {
|
|
|
10
10
|
restoreTerminal,
|
|
11
11
|
runJob,
|
|
12
12
|
sttySane
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-2WXG35EM.js";
|
|
14
14
|
import "./chunk-M2RKCIGV.js";
|
|
15
15
|
import {
|
|
16
|
-
DURABLE_ROLES,
|
|
17
|
-
REQUIRED_ROLES,
|
|
18
|
-
ROLE_PROFILES,
|
|
19
16
|
RoleFitness,
|
|
20
|
-
adjustRoleModels,
|
|
21
17
|
asChoice,
|
|
22
|
-
capabilityScore,
|
|
23
18
|
describeUnfinished,
|
|
24
|
-
effortFor,
|
|
25
|
-
filterModelsForRole,
|
|
26
|
-
isKnownModel,
|
|
27
|
-
modelBand,
|
|
28
|
-
mostCapable,
|
|
29
|
-
newestPrimary,
|
|
30
|
-
sourceOf,
|
|
31
|
-
strongestPrimary,
|
|
32
19
|
toSlug,
|
|
33
20
|
unfinishedSessions
|
|
34
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-27F44PBD.js";
|
|
35
22
|
import "./chunk-QF4MP6BS.js";
|
|
36
|
-
import "./chunk-
|
|
23
|
+
import "./chunk-UTHLEW5V.js";
|
|
37
24
|
import "./chunk-ZSQ24YDJ.js";
|
|
38
25
|
import {
|
|
39
26
|
saveRoleSkills
|
|
40
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-JR2JLRE3.js";
|
|
41
28
|
import {
|
|
42
29
|
objectField,
|
|
43
30
|
patchConfig
|
|
44
31
|
} from "./chunk-H2FDGPVW.js";
|
|
45
|
-
import
|
|
32
|
+
import {
|
|
33
|
+
DURABLE_ROLES,
|
|
34
|
+
REQUIRED_ROLES,
|
|
35
|
+
ROLE_PROFILES,
|
|
36
|
+
adjustRoleModels,
|
|
37
|
+
capabilityScore,
|
|
38
|
+
cliFor,
|
|
39
|
+
effortFor,
|
|
40
|
+
filterModelsForRole,
|
|
41
|
+
isKnownModel,
|
|
42
|
+
modelBand,
|
|
43
|
+
mostCapable,
|
|
44
|
+
newestPrimary,
|
|
45
|
+
sourceOf,
|
|
46
|
+
strongestPrimary
|
|
47
|
+
} from "./chunk-YULQ4URQ.js";
|
|
48
|
+
import "./chunk-G45RWL7S.js";
|
|
46
49
|
import "./chunk-LPQU436C.js";
|
|
47
50
|
import {
|
|
48
51
|
memoryNote,
|
|
49
52
|
memoryState,
|
|
50
53
|
walkFiles
|
|
51
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-BFIZMM4G.js";
|
|
52
55
|
import "./chunk-63E73TGI.js";
|
|
56
|
+
import "./chunk-CYLPQWIF.js";
|
|
57
|
+
import "./chunk-6S4WWQMN.js";
|
|
53
58
|
import {
|
|
54
59
|
estimateFreezeSeconds,
|
|
55
60
|
fmtDuration,
|
|
@@ -59,15 +64,14 @@ import {
|
|
|
59
64
|
stripThinking,
|
|
60
65
|
telemetry,
|
|
61
66
|
writeHeapSnapshot
|
|
62
|
-
} from "./chunk-
|
|
63
|
-
import "./chunk-6OSEQOYY.js";
|
|
67
|
+
} from "./chunk-JLWQCA7B.js";
|
|
64
68
|
import {
|
|
65
69
|
traceRootRel
|
|
66
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-ZPJP2VH5.js";
|
|
67
71
|
import {
|
|
68
72
|
buildProjectGraph,
|
|
69
73
|
graphStatus
|
|
70
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-4M6LXNG2.js";
|
|
71
75
|
import {
|
|
72
76
|
writeAtomic
|
|
73
77
|
} from "./chunk-6W4UH2BQ.js";
|
|
@@ -356,7 +360,7 @@ async function connectAllMcp(specs) {
|
|
|
356
360
|
|
|
357
361
|
// src/tui/app.tsx
|
|
358
362
|
import { homedir as homedir2 } from "os";
|
|
359
|
-
import { join as
|
|
363
|
+
import { join as join7 } from "path";
|
|
360
364
|
import { basename } from "path";
|
|
361
365
|
|
|
362
366
|
// src/tui/labels.ts
|
|
@@ -1737,6 +1741,8 @@ var COMMANDS = [
|
|
|
1737
1741
|
{ name: "/memories", desc: "List remembered facts (/forget N to remove)" },
|
|
1738
1742
|
{ name: "/forget", desc: "Forget a remembered fact (/forget N)" },
|
|
1739
1743
|
{ name: "/mcp", desc: "Connected MCP servers (/mcp add <url|command> installs one and verifies it)" },
|
|
1744
|
+
{ name: "/init", desc: "Set this project up for horse-code \u2014 commit the knowledge, keep the derived files out" },
|
|
1745
|
+
{ name: "/models", desc: "Models each connected subscription serves, and which ones a role is running" },
|
|
1740
1746
|
{ name: "/sources", desc: "Show your connected model sources (/sources refresh re-detects)" },
|
|
1741
1747
|
{ name: "/migrate", desc: "Bring a project from Claude Code / Codex / Cursor into horse-code (rules, memory, skills)" },
|
|
1742
1748
|
{ name: "/continue-from-claude", desc: "Continue work started in a Claude Code worktree (/continue-from-claude <name>) \u2014 its branch becomes the base" },
|
|
@@ -1748,6 +1754,7 @@ var COMMANDS = [
|
|
|
1748
1754
|
{ name: "/monitor", desc: "Where the run's time is going (/monitor enable shows the panel, disable hides it, log shows the file, heap writes a snapshot)" },
|
|
1749
1755
|
{ name: "/watch", desc: "Watch any command \u2014 each line it prints becomes an event (/watch <cmd>, /watch stop N)" },
|
|
1750
1756
|
{ name: "/paste", desc: "Put the clipboard's image into the input (same as Ctrl+V, for terminals that swallow it)" },
|
|
1757
|
+
{ name: "/start-smoke-test", desc: "Walk the finished feature's manual verification one step at a time, and record what you saw into its guide" },
|
|
1751
1758
|
{ name: "/help", desc: "List the available commands" },
|
|
1752
1759
|
{ name: "/clear", desc: "Clear the conversation" },
|
|
1753
1760
|
{ name: "/exit", desc: "Quit horse-code" }
|
|
@@ -1957,7 +1964,7 @@ function rankFiles(files, query, limit = 8) {
|
|
|
1957
1964
|
}
|
|
1958
1965
|
|
|
1959
1966
|
// src/tui/components.tsx
|
|
1960
|
-
import { join as
|
|
1967
|
+
import { join as join3 } from "path";
|
|
1961
1968
|
import { homedir } from "os";
|
|
1962
1969
|
|
|
1963
1970
|
// src/tui/paste.ts
|
|
@@ -2288,7 +2295,130 @@ function shortName(command) {
|
|
|
2288
2295
|
return first.split("/").pop()?.slice(0, 24) || "watch";
|
|
2289
2296
|
}
|
|
2290
2297
|
|
|
2298
|
+
// src/engine/smoke-test.ts
|
|
2299
|
+
import { existsSync, readFileSync as readFileSync2, readdirSync } from "fs";
|
|
2300
|
+
import { join as join2 } from "path";
|
|
2301
|
+
function splitInstructions(paragraph) {
|
|
2302
|
+
return paragraph.split(/(?<=[.!?])\s+/).map((s) => s.trim()).filter((s) => s.length > 12);
|
|
2303
|
+
}
|
|
2304
|
+
function parseGuide(path, markdown) {
|
|
2305
|
+
const lines = markdown.split("\n");
|
|
2306
|
+
const title = lines.find((l) => l.startsWith("# "))?.slice(2).trim() ?? "Manual verification";
|
|
2307
|
+
const preconditions = [];
|
|
2308
|
+
const scenarios = [];
|
|
2309
|
+
const steps = [];
|
|
2310
|
+
let section = "other";
|
|
2311
|
+
let scenario = "";
|
|
2312
|
+
let buffer = [];
|
|
2313
|
+
const flush = () => {
|
|
2314
|
+
if (!scenario) {
|
|
2315
|
+
buffer = [];
|
|
2316
|
+
return;
|
|
2317
|
+
}
|
|
2318
|
+
const text = buffer.join(" ").trim();
|
|
2319
|
+
for (const instruction of splitInstructions(text)) {
|
|
2320
|
+
steps.push({ n: steps.length + 1, scenario, scenarioIndex: Math.max(0, scenarios.length - 1), instruction });
|
|
2321
|
+
}
|
|
2322
|
+
buffer = [];
|
|
2323
|
+
};
|
|
2324
|
+
for (const line of lines) {
|
|
2325
|
+
const h2 = /^##\s+(?!#)(.*)$/.exec(line);
|
|
2326
|
+
const h3 = /^###\s+(.*)$/.exec(line);
|
|
2327
|
+
if (h2) {
|
|
2328
|
+
flush();
|
|
2329
|
+
scenario = "";
|
|
2330
|
+
section = /ön koşul|precondition/i.test(h2[1]) ? "pre" : /senaryo|scenario/i.test(h2[1]) ? "scenario" : "other";
|
|
2331
|
+
continue;
|
|
2332
|
+
}
|
|
2333
|
+
if (h3) {
|
|
2334
|
+
flush();
|
|
2335
|
+
if (section === "scenario") {
|
|
2336
|
+
scenario = h3[1].trim();
|
|
2337
|
+
scenarios.push(scenario);
|
|
2338
|
+
}
|
|
2339
|
+
continue;
|
|
2340
|
+
}
|
|
2341
|
+
const text = line.trim();
|
|
2342
|
+
if (!text) {
|
|
2343
|
+
flush();
|
|
2344
|
+
continue;
|
|
2345
|
+
}
|
|
2346
|
+
if (section === "pre") {
|
|
2347
|
+
const item = /^\d+\.\s+(.*)$/.exec(text)?.[1] ?? /^[-*]\s+(.*)$/.exec(text)?.[1];
|
|
2348
|
+
if (item) preconditions.push(item);
|
|
2349
|
+
continue;
|
|
2350
|
+
}
|
|
2351
|
+
if (section === "scenario" && scenario) buffer.push(text);
|
|
2352
|
+
}
|
|
2353
|
+
flush();
|
|
2354
|
+
return { path, title, preconditions, steps, scenarios };
|
|
2355
|
+
}
|
|
2356
|
+
function renderStep(step, total) {
|
|
2357
|
+
return `**Ad\u0131m ${step.n}/${total}** \u2014 _${step.scenario}_
|
|
2358
|
+
|
|
2359
|
+
${step.instruction}`;
|
|
2360
|
+
}
|
|
2361
|
+
function recordOutcome(markdown, scenarioIndex, status, evidence) {
|
|
2362
|
+
const want = scenarioIndex + 1;
|
|
2363
|
+
return markdown.split("\n").map((line) => {
|
|
2364
|
+
if (!line.startsWith("|")) return line;
|
|
2365
|
+
const cells = line.split("|");
|
|
2366
|
+
if (cells.length < 4) return line;
|
|
2367
|
+
if (Number(/^\s*(\d+)/.exec(cells[1] ?? "")?.[1]) !== want) return line;
|
|
2368
|
+
cells[2] = ` ${status} `;
|
|
2369
|
+
cells[3] = ` ${evidence.replace(/\|/g, "\\|").replace(/\s+/g, " ").trim()} `;
|
|
2370
|
+
return cells.join("|");
|
|
2371
|
+
}).join("\n");
|
|
2372
|
+
}
|
|
2373
|
+
function scenarioOutcome(results) {
|
|
2374
|
+
const status = results.some((r) => r.status === "ba\u015Far\u0131s\u0131z") ? "ba\u015Far\u0131s\u0131z" : results.every((r) => r.status === "\xE7al\u0131\u015Ft\u0131r\u0131lmad\u0131") ? "\xE7al\u0131\u015Ft\u0131r\u0131lmad\u0131" : "ge\xE7ti";
|
|
2375
|
+
const evidence = results.filter((r) => r.evidence.trim()).map((r) => `${r.step.n}. ${r.evidence.trim()}`).join(" ");
|
|
2376
|
+
return { status, evidence: evidence || "g\xF6zlem kaydedilmedi" };
|
|
2377
|
+
}
|
|
2378
|
+
function findGuide(projectRoot) {
|
|
2379
|
+
const roots = [projectRoot, ...worktreeRoots(projectRoot)];
|
|
2380
|
+
let best;
|
|
2381
|
+
for (const root of roots) {
|
|
2382
|
+
let names = [];
|
|
2383
|
+
try {
|
|
2384
|
+
names = readdirSync(join2(root, "specs"));
|
|
2385
|
+
} catch {
|
|
2386
|
+
continue;
|
|
2387
|
+
}
|
|
2388
|
+
for (const slug of names) {
|
|
2389
|
+
if (!/^\d{3}-/.test(slug)) continue;
|
|
2390
|
+
const path = join2(root, "specs", slug, "quickstart.md");
|
|
2391
|
+
if (!existsSync(path)) continue;
|
|
2392
|
+
if (!best || slug > best.slug) best = { root, slug, path };
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
return best;
|
|
2396
|
+
}
|
|
2397
|
+
function worktreeRoots(projectRoot) {
|
|
2398
|
+
const dir = join2(projectRoot, ".horsecode", "worktrees");
|
|
2399
|
+
try {
|
|
2400
|
+
return readdirSync(dir).map((s) => join2(dir, s, "base")).filter((p) => existsSync(p));
|
|
2401
|
+
} catch {
|
|
2402
|
+
return [];
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
function progressLine(done, total) {
|
|
2406
|
+
const width = 24;
|
|
2407
|
+
const filled = total ? Math.round(done / total * width) : 0;
|
|
2408
|
+
return `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)} ${done}/${total}`;
|
|
2409
|
+
}
|
|
2410
|
+
function loadGuide(projectRoot) {
|
|
2411
|
+
const found = findGuide(projectRoot);
|
|
2412
|
+
if (!found) {
|
|
2413
|
+
return { error: "No `specs/NNN-\u2026/quickstart.md` in this project or any of its session worktrees \u2014 a feature run writes one when it finishes." };
|
|
2414
|
+
}
|
|
2415
|
+
const guide = parseGuide(found.path, readFileSync2(found.path, "utf8"));
|
|
2416
|
+
if (!guide.steps.length) return { error: `${found.path} has no scenarios to walk \u2014 it may not be a verification guide.` };
|
|
2417
|
+
return { ...guide, slug: found.slug };
|
|
2418
|
+
}
|
|
2419
|
+
|
|
2291
2420
|
// src/tui/components.tsx
|
|
2421
|
+
import { readFileSync as readFileSync3, writeFileSync } from "fs";
|
|
2292
2422
|
import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2293
2423
|
function parsePending(raw) {
|
|
2294
2424
|
const t = raw.replace(/^\s+/, "");
|
|
@@ -3042,7 +3172,7 @@ function ViewportLines({ lines, height }) {
|
|
|
3042
3172
|
lines.map((line, i) => /* @__PURE__ */ jsx4(Text4, { children: line.length === 0 ? " " : line.map((s, j) => /* @__PURE__ */ jsx4(Text4, { color: s.color, backgroundColor: s.backgroundColor, bold: s.bold, italic: s.italic, dimColor: s.dim, children: s.text }, j)) }, i))
|
|
3043
3173
|
] });
|
|
3044
3174
|
}
|
|
3045
|
-
function App({ controller, fullscreen = false, model, coachModel, refinerModel, listModels, setModel, setRoleModel, listRoles, adjustRoles, listSessions, resumeSession, listPins, addPin, removePin, listMemories, addMemory, removeMemory, listMcp, sourcesInfo, refreshSources, listSkills, updateSkills, addSkill, graphStatus: graphStatus2, buildGraph, planTraces, runTraces, cleanWorktrees, migrate, continueFromClaude, addMcp, answerByTheWay, telemetryPath, parallel, setParallel, permMode, setPermMode, cancelJob, onExit }) {
|
|
3175
|
+
function App({ controller, fullscreen = false, model, coachModel, refinerModel, listModels, setModel, setRoleModel, listRoles, adjustRoles, modelsPanel, initProject, listSessions, resumeSession, listPins, addPin, removePin, listMemories, addMemory, removeMemory, listMcp, sourcesInfo, refreshSources, listSkills, updateSkills, addSkill, graphStatus: graphStatus2, buildGraph, planTraces, runTraces, cleanWorktrees, migrate, continueFromClaude, addMcp, answerByTheWay, telemetryPath, parallel, setParallel, permMode, setPermMode, cancelJob, onExit }) {
|
|
3046
3176
|
const [state, setState] = useState3(controller.getState());
|
|
3047
3177
|
useEffect3(() => controller.subscribe(() => setState(controller.getState())), [controller]);
|
|
3048
3178
|
const { stdout } = useStdout();
|
|
@@ -3255,10 +3385,10 @@ _Type \`/resume N\` to continue one._`);
|
|
|
3255
3385
|
}
|
|
3256
3386
|
try {
|
|
3257
3387
|
const { writeFile: writeFile3, mkdir: mkdir3 } = await import("fs/promises");
|
|
3258
|
-
const dir =
|
|
3388
|
+
const dir = join3(homedir(), ".horsecode", "pastes");
|
|
3259
3389
|
await mkdir3(dir, { recursive: true });
|
|
3260
3390
|
const id = ++imageIdRef.current;
|
|
3261
|
-
const file =
|
|
3391
|
+
const file = join3(dir, `paste-${process.pid}-${id}.png`);
|
|
3262
3392
|
await writeFile3(file, Buffer.from(uri.slice(uri.indexOf(",") + 1), "base64"));
|
|
3263
3393
|
imageMapRef.current.set(id, file);
|
|
3264
3394
|
const tok = imageToken(id);
|
|
@@ -3498,6 +3628,35 @@ ${rows.join("\n")}
|
|
|
3498
3628
|
|
|
3499
3629
|
_\`/mcp add <url|command>\` to install another._`);
|
|
3500
3630
|
};
|
|
3631
|
+
const doInit = async () => {
|
|
3632
|
+
if (!initProject) {
|
|
3633
|
+
controller.note("Project setup is not available.");
|
|
3634
|
+
return;
|
|
3635
|
+
}
|
|
3636
|
+
controller.note("Setting the project up\u2026");
|
|
3637
|
+
let report;
|
|
3638
|
+
try {
|
|
3639
|
+
report = await initProject();
|
|
3640
|
+
} catch (e) {
|
|
3641
|
+
controller.note(`init error: ${e instanceof Error ? e.message : String(e)}`);
|
|
3642
|
+
return;
|
|
3643
|
+
}
|
|
3644
|
+
controller.note(report.text);
|
|
3645
|
+
if (!report.canImport || !migrate) return;
|
|
3646
|
+
if (await controller.ask("Read these and import what they say?", { options: ["Import", "Skip"] }) !== "Import") {
|
|
3647
|
+
controller.note("Left alone. Run `/init` again, or `/migrate`, whenever you want them read.");
|
|
3648
|
+
return;
|
|
3649
|
+
}
|
|
3650
|
+
controller.note(await migrate(report.extra));
|
|
3651
|
+
};
|
|
3652
|
+
const doModels = () => {
|
|
3653
|
+
if (!modelsPanel) {
|
|
3654
|
+
controller.note("Models are not available.");
|
|
3655
|
+
return;
|
|
3656
|
+
}
|
|
3657
|
+
const inUse = [...new Set((listRoles?.() ?? []).flatMap((r) => r.models))];
|
|
3658
|
+
controller.note(modelsPanel(inUse));
|
|
3659
|
+
};
|
|
3501
3660
|
const doSources = (arg) => {
|
|
3502
3661
|
const info = sourcesInfo?.();
|
|
3503
3662
|
if (arg.trim().toLowerCase() === "refresh") {
|
|
@@ -3561,6 +3720,56 @@ _\`/sources refresh\` to re-probe your connected subscriptions._`);
|
|
|
3561
3720
|
}
|
|
3562
3721
|
);
|
|
3563
3722
|
};
|
|
3723
|
+
const doSmokeTest = async () => {
|
|
3724
|
+
const guide = loadGuide(process.cwd());
|
|
3725
|
+
if ("error" in guide) {
|
|
3726
|
+
controller.note(guide.error);
|
|
3727
|
+
return;
|
|
3728
|
+
}
|
|
3729
|
+
controller.note(
|
|
3730
|
+
`\u{1F9EA} **${guide.title}**
|
|
3731
|
+
|
|
3732
|
+
\`${guide.slug}\` \xB7 ${guide.steps.length} ad\u0131m \xB7 ${guide.scenarios.length} senaryo`
|
|
3733
|
+
);
|
|
3734
|
+
if (guide.preconditions.length) {
|
|
3735
|
+
controller.note(`**Ba\u015Flamadan \xF6nce**
|
|
3736
|
+
${guide.preconditions.map((p) => `- ${p}`).join("\n")}`);
|
|
3737
|
+
}
|
|
3738
|
+
controller.note(
|
|
3739
|
+
"Her ad\u0131mda ne g\xF6rd\xFC\u011F\xFCn\xFC yap\u0131\u015Ft\u0131r \u2014 API yan\u0131t\u0131, DB sat\u0131r\u0131, log kayd\u0131. horse-code veritaban\u0131na ve Loki'ye kendisi bakmaz; kan\u0131t senin g\xF6zlemin olarak kaydedilir."
|
|
3740
|
+
);
|
|
3741
|
+
if (await controller.ask("Ortam haz\u0131r m\u0131?", { options: ["Ba\u015Fla", "\u0130ptal"] }) !== "Ba\u015Fla") {
|
|
3742
|
+
controller.note("B\u0131rak\u0131ld\u0131 \u2014 rehberde hi\xE7bir \u015Fey de\u011Fi\u015Fmedi.");
|
|
3743
|
+
return;
|
|
3744
|
+
}
|
|
3745
|
+
let markdown = readFileSync3(guide.path, "utf8");
|
|
3746
|
+
let batch = [];
|
|
3747
|
+
const flush = (index) => {
|
|
3748
|
+
if (!batch.length) return;
|
|
3749
|
+
const { status, evidence } = scenarioOutcome(batch);
|
|
3750
|
+
markdown = recordOutcome(markdown, index, status, evidence);
|
|
3751
|
+
writeFileSync(guide.path, markdown);
|
|
3752
|
+
controller.note(`\u{1F4DD} _${guide.scenarios[index]}_ \u2192 **${status}**`);
|
|
3753
|
+
batch = [];
|
|
3754
|
+
};
|
|
3755
|
+
for (const [i, step] of guide.steps.entries()) {
|
|
3756
|
+
const previous = guide.steps[i - 1];
|
|
3757
|
+
if (previous && previous.scenarioIndex !== step.scenarioIndex) flush(previous.scenarioIndex);
|
|
3758
|
+
controller.note(renderStep(step, guide.steps.length));
|
|
3759
|
+
const answer = await controller.ask("Sonu\xE7?", { options: ["ge\xE7ti", "ba\u015Far\u0131s\u0131z", "atla", "durdur"] });
|
|
3760
|
+
if (answer === "durdur") {
|
|
3761
|
+
flush(step.scenarioIndex);
|
|
3762
|
+
controller.note(`Durduruldu \u2014 ${step.n - 1}/${guide.steps.length} ad\u0131m kaydedildi.`);
|
|
3763
|
+
return;
|
|
3764
|
+
}
|
|
3765
|
+
const status = answer === "ge\xE7ti" ? "ge\xE7ti" : answer === "ba\u015Far\u0131s\u0131z" ? "ba\u015Far\u0131s\u0131z" : "\xE7al\u0131\u015Ft\u0131r\u0131lmad\u0131";
|
|
3766
|
+
const evidence = status === "\xE7al\u0131\u015Ft\u0131r\u0131lmad\u0131" ? "" : await controller.ask("Ne g\xF6zlemledin? (API yan\u0131t\u0131 / DB sat\u0131r\u0131 / log)");
|
|
3767
|
+
batch.push({ step, status, evidence });
|
|
3768
|
+
controller.note(progressLine(step.n, guide.steps.length));
|
|
3769
|
+
}
|
|
3770
|
+
flush(guide.steps[guide.steps.length - 1].scenarioIndex);
|
|
3771
|
+
controller.note(`\u2705 Bitti \u2014 ${guide.path} g\xFCncellendi.`);
|
|
3772
|
+
};
|
|
3564
3773
|
const doGraph = (arg) => {
|
|
3565
3774
|
if (!graphStatus2 || !buildGraph) {
|
|
3566
3775
|
controller.note("The project graph is not available.");
|
|
@@ -3724,8 +3933,11 @@ _\`/skills add <github-url>\` to install one \xB7 \`/skills update\` re-installs
|
|
|
3724
3933
|
else if (c.name === "/remember") doRemember("");
|
|
3725
3934
|
else if (c.name === "/forget") doForget("");
|
|
3726
3935
|
else if (c.name === "/mcp") doMcp("");
|
|
3936
|
+
else if (c.name === "/init") void doInit();
|
|
3937
|
+
else if (c.name === "/models") doModels();
|
|
3727
3938
|
else if (c.name === "/sources") doSources("");
|
|
3728
3939
|
else if (c.name === "/skills") doSkills("");
|
|
3940
|
+
else if (c.name === "/start-smoke-test") void doSmokeTest();
|
|
3729
3941
|
else if (c.name === "/graph") doGraph("");
|
|
3730
3942
|
else if (c.name === "/clean-worktrees") doCleanWorktrees("");
|
|
3731
3943
|
else if (c.name === "/paste") pasteImage();
|
|
@@ -4015,9 +4227,9 @@ _\`/skills add <github-url>\` to install one \xB7 \`/skills update\` re-installs
|
|
|
4015
4227
|
const cw = Math.max(1, size.cols - 4);
|
|
4016
4228
|
const inputH = draft.split("\n").reduce((n, l) => n + Math.max(1, Math.ceil((l.length + 3) / cw)), 0);
|
|
4017
4229
|
const running = mode === "running";
|
|
4018
|
-
const
|
|
4230
|
+
const progressLine2 = running && !state.pending;
|
|
4019
4231
|
const doneLine = !!state.meta && !state.meta.running && !state.pending;
|
|
4020
|
-
const showStatus =
|
|
4232
|
+
const showStatus = progressLine2 || !!state.pending || doneLine;
|
|
4021
4233
|
const choiceOptionsForFit = state.pending?.options ?? [];
|
|
4022
4234
|
const pendingBodyMax = state.pending ? Math.max(
|
|
4023
4235
|
1,
|
|
@@ -4028,7 +4240,7 @@ _\`/skills add <github-url>\` to install one \xB7 \`/skills update\` re-installs
|
|
|
4028
4240
|
flattenMarkdown(parsePending(state.pending.question).body, pendingBodyWidth(size.cols)).length,
|
|
4029
4241
|
pendingBodyMax
|
|
4030
4242
|
) : 0;
|
|
4031
|
-
const statusH = (
|
|
4243
|
+
const statusH = (progressLine2 || doneLine ? 1 : 0) + pendingLines;
|
|
4032
4244
|
const inputMarginTop = showStatus ? 0 : 1;
|
|
4033
4245
|
const choiceOptions = state.pending?.options ?? [];
|
|
4034
4246
|
const choiceActive = choiceOptions.length > 0 && !choiceDismissed;
|
|
@@ -4075,7 +4287,7 @@ _\`/skills add <github-url>\` to install one \xB7 \`/skills update\` re-installs
|
|
|
4075
4287
|
/* @__PURE__ */ jsx4(Box4, { paddingLeft: CHAT_INDENT, children: /* @__PURE__ */ jsx4(ViewportLines, { lines: windowed, height: viewportH }) }),
|
|
4076
4288
|
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: clamped > 0 ? ` \u2193 ${clamped} more \xB7 \u2193/PgDn to jump to bottom` : " " }),
|
|
4077
4289
|
showStatus ? /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
4078
|
-
|
|
4290
|
+
progressLine2 ? /* @__PURE__ */ jsx4(Box4, { paddingLeft: 2, children: /* @__PURE__ */ jsx4(ProgressView, { phase: state.phase, detail: state.detail, refinerModel: refinerModel?.(), meta: state.meta, cols: size.cols, live: state.liveActivity }) }) : null,
|
|
4079
4291
|
doneLine ? /* @__PURE__ */ jsx4(Box4, { paddingLeft: 2, children: /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: `${donePhrase(state.phase)} for ${fmtDuration(state.meta?.durationMs ?? 0)}${state.meta && state.meta.calls > 0 ? ` \xB7 \u2191${fmtTokens(state.meta.promptTokens)} \u2193${fmtTokens(state.meta.completionTokens)} \xB7 ${state.meta.calls} call${state.meta.calls === 1 ? "" : "s"}` : ""}` }) }) : null,
|
|
4080
4292
|
state.pending ? /* @__PURE__ */ jsx4(PendingQuestion, { text: state.pending.question, cols: size.cols, maxLines: pendingBodyMax }) : null
|
|
4081
4293
|
] }) : null,
|
|
@@ -4268,6 +4480,15 @@ _\`/skills add <github-url>\` to install one \xB7 \`/skills update\` re-installs
|
|
|
4268
4480
|
doMcp(trimmed.slice("/mcp".length).trim());
|
|
4269
4481
|
return;
|
|
4270
4482
|
}
|
|
4483
|
+
if (cmd === "/start-smoke-test") {
|
|
4484
|
+
setScroll(0);
|
|
4485
|
+
setDraft("");
|
|
4486
|
+
setDraftCursor(0);
|
|
4487
|
+
usedPastes();
|
|
4488
|
+
controller.echoCommand(trimmed);
|
|
4489
|
+
void doSmokeTest();
|
|
4490
|
+
return;
|
|
4491
|
+
}
|
|
4271
4492
|
if (cmd.startsWith("/graph ")) {
|
|
4272
4493
|
setScroll(0);
|
|
4273
4494
|
setDraft("");
|
|
@@ -4379,7 +4600,7 @@ async function saveMode(home, mode) {
|
|
|
4379
4600
|
// src/session/store.ts
|
|
4380
4601
|
import { mkdir, readFile as readFile2, readdir } from "fs/promises";
|
|
4381
4602
|
import { createHash } from "crypto";
|
|
4382
|
-
import { join as
|
|
4603
|
+
import { join as join4 } from "path";
|
|
4383
4604
|
var SessionStore = class {
|
|
4384
4605
|
activeId;
|
|
4385
4606
|
dir;
|
|
@@ -4387,7 +4608,7 @@ var SessionStore = class {
|
|
|
4387
4608
|
constructor(opts) {
|
|
4388
4609
|
this.now = opts.now ?? (() => Date.now());
|
|
4389
4610
|
const hash = createHash("sha256").update(opts.cwd).digest("hex").slice(0, 16);
|
|
4390
|
-
this.dir =
|
|
4611
|
+
this.dir = join4(opts.home, ".horsecode", "projects", hash, "sessions");
|
|
4391
4612
|
this.activeId = `s${this.now()}`;
|
|
4392
4613
|
}
|
|
4393
4614
|
/** The id this store currently writes to (a fresh one, or a resumed session's id after setActive). */
|
|
@@ -4399,7 +4620,7 @@ var SessionStore = class {
|
|
|
4399
4620
|
this.activeId = id;
|
|
4400
4621
|
}
|
|
4401
4622
|
file(id) {
|
|
4402
|
-
return
|
|
4623
|
+
return join4(this.dir, `${id}.json`);
|
|
4403
4624
|
}
|
|
4404
4625
|
/** Overwrite the active session with the current messages (no-op on an empty transcript). */
|
|
4405
4626
|
async save(messages) {
|
|
@@ -4426,7 +4647,7 @@ var SessionStore = class {
|
|
|
4426
4647
|
for (const n of names) {
|
|
4427
4648
|
if (!n.endsWith(".json")) continue;
|
|
4428
4649
|
try {
|
|
4429
|
-
const d = JSON.parse(await readFile2(
|
|
4650
|
+
const d = JSON.parse(await readFile2(join4(this.dir, n), "utf8"));
|
|
4430
4651
|
out.push({ id: d.id, title: d.title, updatedAt: d.updatedAt, count: d.count });
|
|
4431
4652
|
} catch {
|
|
4432
4653
|
}
|
|
@@ -4452,7 +4673,7 @@ function titleOf(messages) {
|
|
|
4452
4673
|
// src/session/pins.ts
|
|
4453
4674
|
import { mkdir as mkdir2, readFile as readFile3 } from "fs/promises";
|
|
4454
4675
|
import { createHash as createHash2 } from "crypto";
|
|
4455
|
-
import { join as
|
|
4676
|
+
import { join as join5, dirname } from "path";
|
|
4456
4677
|
var MAX_PINS = 20;
|
|
4457
4678
|
var MAX_PIN_CHARS = 500;
|
|
4458
4679
|
var PinStore = class {
|
|
@@ -4460,7 +4681,7 @@ var PinStore = class {
|
|
|
4460
4681
|
cache;
|
|
4461
4682
|
constructor(opts) {
|
|
4462
4683
|
const hash = createHash2("sha256").update(opts.cwd).digest("hex").slice(0, 16);
|
|
4463
|
-
this.file =
|
|
4684
|
+
this.file = join5(opts.home, ".horsecode", "projects", hash, "pins.json");
|
|
4464
4685
|
}
|
|
4465
4686
|
/** Load pins from disk (memoized). Missing/corrupt → empty. */
|
|
4466
4687
|
async load() {
|
|
@@ -4650,7 +4871,7 @@ var ModelHealth = class {
|
|
|
4650
4871
|
}
|
|
4651
4872
|
const live = all.filter((m) => !dead.has(m));
|
|
4652
4873
|
const configured = new Set(this.port.registries().flatMap((r) => r.knownModels()));
|
|
4653
|
-
const curated = live.filter((m) => configured.has(m));
|
|
4874
|
+
const curated = live.filter((m) => configured.has(m) || cliFor(m) !== void 0);
|
|
4654
4875
|
telemetry().event("decision.pool", {
|
|
4655
4876
|
"hc.decision": "pool",
|
|
4656
4877
|
"hc.pool.catalog": all.length,
|
|
@@ -4995,7 +5216,7 @@ First explain your key choices in a few short sentences, including which skills
|
|
|
4995
5216
|
// src/engine/scan-repo.ts
|
|
4996
5217
|
import { spawn as spawn2 } from "child_process";
|
|
4997
5218
|
import { readFile as readFile4 } from "fs/promises";
|
|
4998
|
-
import { join as
|
|
5219
|
+
import { join as join6 } from "path";
|
|
4999
5220
|
var MANIFESTS = ["package.json", "pyproject.toml", "requirements.txt", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle", "composer.json"];
|
|
5000
5221
|
var MAX_FILES = 2e4;
|
|
5001
5222
|
function gitFiles(cwd) {
|
|
@@ -5015,7 +5236,7 @@ async function scanRepo(cwd) {
|
|
|
5015
5236
|
for (const name of MANIFESTS) {
|
|
5016
5237
|
if (!files.includes(name)) continue;
|
|
5017
5238
|
try {
|
|
5018
|
-
manifests[name] = await readFile4(
|
|
5239
|
+
manifests[name] = await readFile4(join6(cwd, name), "utf8");
|
|
5019
5240
|
} catch {
|
|
5020
5241
|
}
|
|
5021
5242
|
}
|
|
@@ -5192,7 +5413,7 @@ function startupSummary(f) {
|
|
|
5192
5413
|
|
|
5193
5414
|
// src/tui/app.tsx
|
|
5194
5415
|
import { execFileSync } from "child_process";
|
|
5195
|
-
import { existsSync } from "fs";
|
|
5416
|
+
import { existsSync as existsSync2 } from "fs";
|
|
5196
5417
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
5197
5418
|
async function runTui(opts) {
|
|
5198
5419
|
const controller = new TuiController();
|
|
@@ -5242,7 +5463,7 @@ async function runTuiRepl(opts) {
|
|
|
5242
5463
|
const chain = regFor(r).chain(r);
|
|
5243
5464
|
return { name: r, model: chain[0] ?? "", models: chain, council: reviewNames.has(r), decider: councilNames.includes(r) };
|
|
5244
5465
|
});
|
|
5245
|
-
const fitness = deps0.fitness ?? new RoleFitness(
|
|
5466
|
+
const fitness = deps0.fitness ?? new RoleFitness(join7(homedir2(), ".horsecode", "model-fitness.json"));
|
|
5246
5467
|
for (const r of [deps0.roleRegistry, deps0.teamRegistries.spec, deps0.teamRegistries.plan, deps0.teamRegistries.code, deps0.councilRegistry]) {
|
|
5247
5468
|
r.setFitness(fitness);
|
|
5248
5469
|
}
|
|
@@ -5373,7 +5594,7 @@ Question: ${question}` }
|
|
|
5373
5594
|
};
|
|
5374
5595
|
const addMcp = async (input) => {
|
|
5375
5596
|
const { parseCommand, parseConfigBlock, extractFromPage, verify } = await import("./install-O34KMWJB.js");
|
|
5376
|
-
const { saveMcpServer } = await import("./save-skills-
|
|
5597
|
+
const { saveMcpServer } = await import("./save-skills-NPKTYNAF.js");
|
|
5377
5598
|
let cand = parseCommand(input) ?? parseConfigBlock(input);
|
|
5378
5599
|
if (!cand) {
|
|
5379
5600
|
const url = input.trim();
|
|
@@ -5442,14 +5663,15 @@ _This project has no worktrees under \`.claude/worktrees\`._`}`);
|
|
|
5442
5663
|
controller.note(`Could not continue from that worktree: ${e instanceof Error ? e.message : String(e)}`);
|
|
5443
5664
|
}
|
|
5444
5665
|
};
|
|
5445
|
-
const migrate = async () => {
|
|
5666
|
+
const migrate = async (extra) => {
|
|
5446
5667
|
if (!opts.memStore) return "Migration needs the memory store, which is not available in this session.";
|
|
5447
5668
|
const progressLines = /* @__PURE__ */ new Map();
|
|
5448
|
-
const { runMigration, describeResult } = await import("./run-
|
|
5669
|
+
const { runMigration, describeResult } = await import("./run-V5ZLZ3LS.js");
|
|
5449
5670
|
const r = await runMigration({
|
|
5450
5671
|
cwd: process.cwd(),
|
|
5451
5672
|
home: homedir2(),
|
|
5452
5673
|
provider: deps.provider,
|
|
5674
|
+
...extra?.length ? { extra } : {},
|
|
5453
5675
|
/**
|
|
5454
5676
|
* The architect's whole CHAIN, not just its head.
|
|
5455
5677
|
*
|
|
@@ -5524,12 +5746,13 @@ _Restart to pick them up in already-built prompts._` : `No role carries one perm
|
|
|
5524
5746
|
};
|
|
5525
5747
|
const refreshGraphIfStale = async () => {
|
|
5526
5748
|
try {
|
|
5527
|
-
const
|
|
5749
|
+
const dir = await (opts.derivedDir?.() ?? Promise.resolve(process.cwd()));
|
|
5750
|
+
const before = await graphStatus(dir);
|
|
5528
5751
|
if (before.built && !before.stale) return;
|
|
5529
5752
|
const first = !before.built;
|
|
5530
5753
|
controller.note(first ? `\u{1F9E0} Building the code graph for the first time \u2014 this reads the whole project, so it takes a few minutes. It runs once; after this, start-up only updates what changed.` : `\u{1F504} The code graph is out of date \u2014 updating it.`);
|
|
5531
5754
|
controller.startBusy(first ? "building the code graph" : "updating the code graph");
|
|
5532
|
-
const r = await buildProjectGraph(
|
|
5755
|
+
const r = await buildProjectGraph(dir);
|
|
5533
5756
|
controller.endBusy();
|
|
5534
5757
|
controller.note(r.ok ? `\u2705 Code graph ready \u2014 ${(r.nodes ?? 0).toLocaleString("en-US")} symbols, ${(r.edges ?? 0).toLocaleString("en-US")} relationships.` : `\u26A0\uFE0F The code graph could not be built: ${r.message}`);
|
|
5535
5758
|
} catch {
|
|
@@ -5671,7 +5894,7 @@ _${saved ? `Saved to your config \u2014 future sessions start with these. ` : ""
|
|
|
5671
5894
|
rules: rulesFromMemory().length,
|
|
5672
5895
|
memory: { total: all.length, rules: kindOf("rule"), lessons: kindOf("lesson"), facts: kindOf("fact") },
|
|
5673
5896
|
skills: opts.listSkills?.().length ?? 0,
|
|
5674
|
-
constitution:
|
|
5897
|
+
constitution: existsSync2(join7(process.cwd(), ".specify", "memory", "constitution.md")),
|
|
5675
5898
|
graph: { built: false, nodes: 0 },
|
|
5676
5899
|
traceRoot: traceRootRel(),
|
|
5677
5900
|
...(() => {
|
|
@@ -5711,7 +5934,7 @@ _${saved ? `Saved to your config \u2014 future sessions start with these. ` : ""
|
|
|
5711
5934
|
const cwd = process.cwd();
|
|
5712
5935
|
const main = await recordedMainBranch(cwd) ?? await detectMainBranch(cwd, defaultGitRunner);
|
|
5713
5936
|
if (!main) return;
|
|
5714
|
-
const { ongoingWork, chooseOngoing } = await import("./ongoing-
|
|
5937
|
+
const { ongoingWork, chooseOngoing } = await import("./ongoing-6NUSPSCV.js");
|
|
5715
5938
|
const open = await ongoingWork(defaultGitRunner, cwd, main);
|
|
5716
5939
|
if (!open.length) return;
|
|
5717
5940
|
const picked = await chooseOngoing(deps, read, open[0]?.language, open);
|
|
@@ -5730,11 +5953,11 @@ _${saved ? `Saved to your config \u2014 future sessions start with these. ` : ""
|
|
|
5730
5953
|
})();
|
|
5731
5954
|
void (async () => {
|
|
5732
5955
|
try {
|
|
5733
|
-
const { loadTraceIndex } = await import("./trace-
|
|
5956
|
+
const { loadTraceIndex } = await import("./trace-UVMZZRA5.js");
|
|
5734
5957
|
let index = await loadTraceIndex(process.cwd());
|
|
5735
5958
|
startupExtra.traces = Object.keys(index.traces).length;
|
|
5736
5959
|
paintSummary();
|
|
5737
|
-
const { graphStatus: graphStatus2 } = await import("./project-graph-
|
|
5960
|
+
const { graphStatus: graphStatus2 } = await import("./project-graph-OGIM2B33.js");
|
|
5738
5961
|
const g = await graphStatus2(process.cwd());
|
|
5739
5962
|
startupExtra.graph = { built: g.built, nodes: g.nodes, stale: g.stale };
|
|
5740
5963
|
if (!g.built || g.stale) {
|
|
@@ -5743,18 +5966,18 @@ _${saved ? `Saved to your config \u2014 future sessions start with these. ` : ""
|
|
|
5743
5966
|
const after = await graphStatus2(process.cwd());
|
|
5744
5967
|
startupExtra.graph = { built: after.built, nodes: after.nodes, stale: after.stale };
|
|
5745
5968
|
}
|
|
5746
|
-
const g0 = await import("./project-graph-
|
|
5969
|
+
const g0 = await import("./project-graph-OGIM2B33.js").then((m) => m.loadGraphSync(process.cwd()));
|
|
5747
5970
|
if (g0) {
|
|
5748
5971
|
const files = /* @__PURE__ */ new Set();
|
|
5749
5972
|
for (const n of g0.nodes) if (n.source_file) files.add(n.source_file);
|
|
5750
|
-
const { adoptDocs, indexAdoption, describeAdoption } = await import("./trace-adopt-
|
|
5973
|
+
const { adoptDocs, indexAdoption, describeAdoption } = await import("./trace-adopt-7HWELJFE.js");
|
|
5751
5974
|
const adoption = await adoptDocs(process.cwd(), files);
|
|
5752
5975
|
const { readFile: readFile5 } = await import("fs/promises");
|
|
5753
5976
|
const r = await indexAdoption(
|
|
5754
5977
|
process.cwd(),
|
|
5755
5978
|
index,
|
|
5756
5979
|
adoption,
|
|
5757
|
-
async (f) => readFile5(
|
|
5980
|
+
async (f) => readFile5(join7(process.cwd(), f), "utf8").catch(() => void 0)
|
|
5758
5981
|
);
|
|
5759
5982
|
if (r.added) {
|
|
5760
5983
|
index = r.index;
|
|
@@ -5763,8 +5986,8 @@ _${saved ? `Saved to your config \u2014 future sessions start with these. ` : ""
|
|
|
5763
5986
|
}
|
|
5764
5987
|
startupExtra.traces = Object.keys(index.traces).length;
|
|
5765
5988
|
paintSummary();
|
|
5766
|
-
const { traceableFiles } = await import("./trace-run-
|
|
5767
|
-
const { traceCoverage } = await import("./trace-
|
|
5989
|
+
const { traceableFiles } = await import("./trace-run-CZWEZ4R6.js");
|
|
5990
|
+
const { traceCoverage } = await import("./trace-UVMZZRA5.js");
|
|
5768
5991
|
startupExtra.coverage = await traceCoverage(process.cwd(), await traceableFiles(process.cwd()), index);
|
|
5769
5992
|
paintSummary();
|
|
5770
5993
|
} catch {
|
|
@@ -5880,6 +6103,8 @@ _${saved ? `Saved to your config \u2014 future sessions start with these. ` : ""
|
|
|
5880
6103
|
setRoleModel: applyChainPersisted,
|
|
5881
6104
|
listRoles,
|
|
5882
6105
|
adjustRoles,
|
|
6106
|
+
modelsPanel: opts.modelsPanel,
|
|
6107
|
+
initProject: opts.initProject,
|
|
5883
6108
|
listSkills: opts.listSkills,
|
|
5884
6109
|
updateSkills: opts.updateSkills,
|
|
5885
6110
|
addSkill: opts.addSkill,
|