@hizliemre/horse-code 0.1.2 → 0.2.0
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-LAJN3TWC.js → app-2GPGCDX6.js} +136 -329
- package/dist/{chunk-K2VERI5Q.js → chunk-23CLQ2KO.js} +365 -666
- package/dist/{chunk-KOWMHL23.js → chunk-5ZV42XGJ.js} +2 -2
- package/dist/{chunk-2SVAHH5N.js → chunk-63E73TGI.js} +2 -4
- package/dist/{chunk-DTWKSZXY.js → chunk-6OSEQOYY.js} +2 -2
- package/dist/{chunk-SSDLHWSF.js → chunk-6W4UH2BQ.js} +33 -1
- package/dist/{chunk-RPVAIS3P.js → chunk-7JMWPTJ5.js} +1724 -306
- package/dist/{chunk-VPAWRRHL.js → chunk-AE36LLL2.js} +31 -21
- package/dist/{chunk-FFYBY2NA.js → chunk-KAGKX2YT.js} +2 -4
- package/dist/{chunk-4EWK7HWQ.js → chunk-KKWZBZYK.js} +10 -0
- package/dist/{chunk-DRZSUQ7Q.js → chunk-LLL7QWXB.js} +18 -7
- package/dist/{chunk-WYQBRCKY.js → chunk-LNW557IO.js} +2 -2
- package/dist/{chunk-IW2KBAVZ.js → chunk-LPQU436C.js} +12 -1
- package/dist/chunk-M2RKCIGV.js +11 -0
- package/dist/{chunk-NNTIACT4.js → chunk-MRZVA5JB.js} +4 -4
- package/dist/{chunk-EQX7BQYN.js → chunk-UGESK765.js} +1 -1
- package/dist/{chunk-PGOYDOI4.js → chunk-XEGQT5EN.js} +3 -5
- package/dist/{chunk-FGVJFMK5.js → chunk-ZSQ24YDJ.js} +1 -1
- package/dist/cli.js +379 -93
- package/dist/{discover-5URG7C4J.js → discover-G2Z6XC3O.js} +9 -3
- package/dist/fix-JOIXQFVP.js +33 -0
- package/dist/git-QZTDZSJY.js +8 -0
- package/dist/{ongoing-XP6WXNI7.js → ongoing-WHYXPW24.js} +4 -4
- package/dist/{project-graph-IOPCSZUA.js → project-graph-5HNPRFQG.js} +2 -3
- package/dist/{run-LQOZ5I7Z.js → run-P6ZYL5JL.js} +2 -3
- package/dist/{save-skills-NSLBU33X.js → save-skills-X7U3KCPU.js} +1 -1
- package/dist/{trace-ZMB7LT7W.js → trace-X6TU3AG6.js} +2 -3
- package/dist/{trace-adopt-C6TUWFJL.js → trace-adopt-URECQWJV.js} +2 -3
- package/dist/{trace-run-F23MFTY4.js → trace-run-7U4WJZ3V.js} +6 -7
- package/dist/{triage-ES5OHZOS.js → triage-FCYHD2AQ.js} +8 -9
- package/dist/{verify-3R7DGUSI.js → verify-6SC4I77M.js} +18 -19
- package/package.json +1 -1
- package/dist/chunk-3UYA3KUG.js +0 -212
- package/dist/chunk-B67BK5GQ.js +0 -34
- package/dist/chunk-O74BDQKS.js +0 -28
- package/dist/fix-CMARU6JR.js +0 -34
- package/dist/git-VTSZALSR.js +0 -6
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
sessionBase
|
|
3
|
+
} from "./chunk-6W4UH2BQ.js";
|
|
4
|
+
|
|
1
5
|
// src/tui/format.ts
|
|
2
6
|
function fmtTokens(n) {
|
|
3
7
|
if (n >= 1e9) return `${(n / 1e9).toFixed(1)}B`;
|
|
@@ -443,22 +447,6 @@ function recallNote(tool, subject, turn, authored = false) {
|
|
|
443
447
|
}
|
|
444
448
|
|
|
445
449
|
// src/core/surrogates.ts
|
|
446
|
-
var LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
|
|
447
|
-
var REPLACEMENT = "\uFFFD";
|
|
448
|
-
function stripLoneSurrogates(text) {
|
|
449
|
-
LONE_SURROGATE.lastIndex = 0;
|
|
450
|
-
return LONE_SURROGATE.test(text) ? text.replace(LONE_SURROGATE, REPLACEMENT) : text;
|
|
451
|
-
}
|
|
452
|
-
function sanitizeForJson(value) {
|
|
453
|
-
if (typeof value === "string") return stripLoneSurrogates(value);
|
|
454
|
-
if (Array.isArray(value)) return value.map((v) => sanitizeForJson(v));
|
|
455
|
-
if (value && typeof value === "object") {
|
|
456
|
-
const out = {};
|
|
457
|
-
for (const [k, v] of Object.entries(value)) out[k] = sanitizeForJson(v);
|
|
458
|
-
return out;
|
|
459
|
-
}
|
|
460
|
-
return value;
|
|
461
|
-
}
|
|
462
450
|
function truncateSafe(text, max) {
|
|
463
451
|
if (text.length <= max || max <= 0) return text;
|
|
464
452
|
const code = text.charCodeAt(max - 1);
|
|
@@ -983,15 +971,19 @@ function shieldToolOutput(text) {
|
|
|
983
971
|
}
|
|
984
972
|
|
|
985
973
|
// src/agent/loop.ts
|
|
974
|
+
var DELEGATED_TOOL_NAMES = { file_change: "Write", command_execution: "Bash" };
|
|
986
975
|
function fmtChars(n) {
|
|
987
976
|
return n >= 1e3 ? `${(n / 1e3).toFixed(1)}k chars` : `${n} chars`;
|
|
988
977
|
}
|
|
989
978
|
function workingDirectoryNote(cwd) {
|
|
990
|
-
|
|
979
|
+
const here = `
|
|
991
980
|
|
|
992
981
|
# Working directory
|
|
993
982
|
|
|
994
983
|
You are already in \`${cwd}\`. Every relative path resolves from here, and every tool runs here \u2014 do not \`cd\` elsewhere, and do not go looking for the repository.`;
|
|
984
|
+
return sessionBase(cwd) === void 0 ? here : `${here}
|
|
985
|
+
|
|
986
|
+
This is a fresh git worktree, so everything git ignores is absent: no \`node_modules\`, no build output, no package caches. Source, tests and configuration are all here and current.`;
|
|
995
987
|
}
|
|
996
988
|
var COMPACT_KEYS_LOGGED = 24;
|
|
997
989
|
var agentSeq = 0;
|
|
@@ -1067,6 +1059,16 @@ async function* runRoleAgent(opts) {
|
|
|
1067
1059
|
toolCalls.push(ev.toolCall);
|
|
1068
1060
|
} else if (ev.type === "tool-progress") {
|
|
1069
1061
|
if (ev.path) opts.onLiveActivity?.(`writing ${ev.path.split("/").pop()} \xB7 ${fmtChars(ev.chars)}`);
|
|
1062
|
+
} else if (ev.type === "activity") {
|
|
1063
|
+
const what = ev.target ? ev.target.split("/").pop() ?? ev.target : "";
|
|
1064
|
+
opts.onActivity?.({
|
|
1065
|
+
tool: DELEGATED_TOOL_NAMES[ev.tool] ?? ev.tool,
|
|
1066
|
+
target: what,
|
|
1067
|
+
lines: 0,
|
|
1068
|
+
// Only a failure is worth a suffix. "done" on every row is the bullet said twice.
|
|
1069
|
+
summary: ev.ok === false ? "failed" : "",
|
|
1070
|
+
ok: ev.ok !== false
|
|
1071
|
+
});
|
|
1070
1072
|
} else if (ev.type === "usage") {
|
|
1071
1073
|
yield { type: "usage", promptTokens: ev.promptTokens, completionTokens: ev.completionTokens };
|
|
1072
1074
|
opts.onUsage?.({ promptTokens: ev.promptTokens, completionTokens: ev.completionTokens, model: activeModel });
|
|
@@ -1082,7 +1084,7 @@ async function* runRoleAgent(opts) {
|
|
|
1082
1084
|
break;
|
|
1083
1085
|
}
|
|
1084
1086
|
if (errored.retryable && !errored.capability && !errored.noBench) opts.onExhausted?.(activeModel, errored.message);
|
|
1085
|
-
if (errored.retryable &&
|
|
1087
|
+
if (errored.retryable && chainIdx < chain.length - 1) {
|
|
1086
1088
|
const next = chain[chainIdx + 1];
|
|
1087
1089
|
opts.onFallback?.(activeModel, next, errored.message);
|
|
1088
1090
|
chainIdx++;
|
|
@@ -1240,6 +1242,10 @@ var ToolRegistry = class {
|
|
|
1240
1242
|
}
|
|
1241
1243
|
};
|
|
1242
1244
|
|
|
1245
|
+
// src/core/types.ts
|
|
1246
|
+
var DEADLINE_MESSAGE = "the model did not answer within its deadline";
|
|
1247
|
+
var CHAIN_BUDGET_MESSAGE = "the chain's total budget ran out before this model was given a fair turn";
|
|
1248
|
+
|
|
1243
1249
|
// src/agent/structured.ts
|
|
1244
1250
|
function valueAt(args, path) {
|
|
1245
1251
|
let cur = args;
|
|
@@ -1255,6 +1261,11 @@ function whatWasWrong(issues, args) {
|
|
|
1255
1261
|
const got = valueAt(args, i.path);
|
|
1256
1262
|
const shown = got === void 0 ? "nothing" : JSON.stringify(got);
|
|
1257
1263
|
const head = where ? `${where}: ${i.message}` : i.message;
|
|
1264
|
+
if (got === void 0 && /received\s+(undefined|null|nothing)/i.test(i.message)) {
|
|
1265
|
+
const parent = i.path.length > 1 ? valueAt(args, i.path.slice(0, -1)) : args;
|
|
1266
|
+
const sent = parent && typeof parent === "object" ? Object.keys(parent) : [];
|
|
1267
|
+
return sent.length ? `${head} \u2014 you sent only ${sent.map((k) => `\`${k}\``).join(", ")}` : head;
|
|
1268
|
+
}
|
|
1258
1269
|
return `${head} \u2014 got ${shown.length > 120 ? `${shown.slice(0, 120)}\u2026` : shown}`;
|
|
1259
1270
|
}).join("; ");
|
|
1260
1271
|
}
|
|
@@ -1323,7 +1334,7 @@ async function runStructuredRole(opts, schema, maxAttempts = 2) {
|
|
|
1323
1334
|
}
|
|
1324
1335
|
if (ev.type === "abort") {
|
|
1325
1336
|
if (opts.signal.aborted) throw new Error("cancelled");
|
|
1326
|
-
errored = total?.aborted ?
|
|
1337
|
+
errored = total?.aborted ? CHAIN_BUDGET_MESSAGE : DEADLINE_MESSAGE;
|
|
1327
1338
|
break;
|
|
1328
1339
|
}
|
|
1329
1340
|
if (ev.type === "message.done") lastText = ev.message.content ?? lastText;
|
|
@@ -1356,13 +1367,12 @@ async function runStructuredRole(opts, schema, maxAttempts = 2) {
|
|
|
1356
1367
|
}
|
|
1357
1368
|
|
|
1358
1369
|
export {
|
|
1359
|
-
sanitizeForJson,
|
|
1360
|
-
truncateSafe,
|
|
1361
1370
|
fmtTokens,
|
|
1362
1371
|
fmtDuration,
|
|
1363
1372
|
relTime,
|
|
1364
1373
|
stripThinking,
|
|
1365
1374
|
handedOver,
|
|
1375
|
+
truncateSafe,
|
|
1366
1376
|
Telemetry,
|
|
1367
1377
|
sampleMemory,
|
|
1368
1378
|
estimateFreezeSeconds,
|
|
@@ -18,6 +18,7 @@ var DEFAULT_CONFIG = {
|
|
|
18
18
|
specKit: { version: "v0.13.2" },
|
|
19
19
|
mcp: {},
|
|
20
20
|
modelSources: [],
|
|
21
|
+
accounts: [],
|
|
21
22
|
traceDir: "",
|
|
22
23
|
/**
|
|
23
24
|
* Shipped as a REFERENCE, not a copy, for the reasons skills/README.md gives for exactly this shape: it is
|
|
@@ -60,6 +61,14 @@ var fileSchema = z.object({
|
|
|
60
61
|
council: z.object({ members: z.array(reviewerSchema) }).optional(),
|
|
61
62
|
specKit: z.object({ version: z.string() }).optional(),
|
|
62
63
|
modelSources: z.array(z.string()).optional(),
|
|
64
|
+
// Logged-in profile directories, in spill order. A path each, never a credential.
|
|
65
|
+
accounts: z.array(z.object({
|
|
66
|
+
kind: z.enum(["claude", "codex"]),
|
|
67
|
+
name: z.string(),
|
|
68
|
+
configDir: z.string(),
|
|
69
|
+
email: z.string().optional(),
|
|
70
|
+
plan: z.string().optional()
|
|
71
|
+
})).optional(),
|
|
63
72
|
traceDir: z.string().optional(),
|
|
64
73
|
// where /graph trace writes; empty = .horsecode/traces
|
|
65
74
|
mainBranch: z.string().optional(),
|
|
@@ -103,6 +112,7 @@ function loadConfig(opts) {
|
|
|
103
112
|
merged.roles = { ...global.roles ?? {}, ...projectSafe.roles ?? {} };
|
|
104
113
|
merged.mcp = { ...global.mcp ?? {}, ...projectSafe.mcp ?? {} };
|
|
105
114
|
merged.modelSources = projectSafe.modelSources ?? global.modelSources ?? [];
|
|
115
|
+
merged.accounts = global.accounts ?? [];
|
|
106
116
|
merged.maxParallel = projectSafe.maxParallel ?? global.maxParallel ?? DEFAULT_CONFIG.maxParallel;
|
|
107
117
|
merged.telemetry = projectSafe.telemetry ?? global.telemetry ?? DEFAULT_CONFIG.telemetry;
|
|
108
118
|
const spoken = global.skillSources !== void 0 || projectSafe.skillSources !== void 0;
|
|
@@ -2,21 +2,21 @@ import {
|
|
|
2
2
|
isMigrated,
|
|
3
3
|
loadMigratedSync,
|
|
4
4
|
migratedNotice
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-63E73TGI.js";
|
|
6
6
|
import {
|
|
7
7
|
telemetry
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-AE36LLL2.js";
|
|
9
9
|
import {
|
|
10
10
|
readBriefSync
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-6OSEQOYY.js";
|
|
12
12
|
import {
|
|
13
13
|
everTraceable,
|
|
14
14
|
readTraceSync
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-KAGKX2YT.js";
|
|
16
16
|
import {
|
|
17
17
|
areaOf,
|
|
18
18
|
loadGraphSync
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-XEGQT5EN.js";
|
|
20
20
|
|
|
21
21
|
// src/tools/read.ts
|
|
22
22
|
import { readFile } from "fs/promises";
|
|
@@ -948,9 +948,20 @@ ${core.join("\n")}`;
|
|
|
948
948
|
);
|
|
949
949
|
var graphTraceTool = {
|
|
950
950
|
name: "graph_trace",
|
|
951
|
-
|
|
951
|
+
/**
|
|
952
|
+
* The limit is stated HERE because this is the only place an agent reads before calling.
|
|
953
|
+
*
|
|
954
|
+
* Measured live in one run: four different lenses — `risk-judge`, `plan-observability`,
|
|
955
|
+
* `plan-architecture` and one more — each asked for a trace of `spec.md` or `plan.md`. The error they got
|
|
956
|
+
* back is a good one and says the failure is permanent, so none of them asked twice; but each learned it
|
|
957
|
+
* separately, at a turn apiece, because a lens has its own memo and cannot be told by the last one. An
|
|
958
|
+
* error teaches one agent after the fact. A description tells every agent before.
|
|
959
|
+
*/
|
|
960
|
+
description: `What a source file is responsible for and what to be careful of when changing it, in the product's terms. Far cheaper than reading the file. Use it to orient before opening unfamiliar code. SOURCE CODE ONLY (.ts, .cs, .py, .go, \u2026): a .md, .json or .txt path has no trace and never will \u2014 read documents with read_file. Pass "project" instead of a path to get the project brief: what the product is, its domain vocabulary, and the business rules the code must not violate. Read that FIRST in an unfamiliar codebase.`,
|
|
952
961
|
permissionLevel: "safe",
|
|
953
|
-
parameters: z4.object({
|
|
962
|
+
parameters: z4.object({
|
|
963
|
+
file: z4.string().describe('Repo-relative path to SOURCE code, e.g. "src/config/config.ts". Not a document.')
|
|
964
|
+
}),
|
|
954
965
|
describe: (args) => ({ allowKey: "graph:trace", preview: `graph_trace ${JSON.stringify(args)}`.slice(0, 120) }),
|
|
955
966
|
async run(args, ctx) {
|
|
956
967
|
const file = String(args.file ?? "");
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
memoryHints,
|
|
6
6
|
readFileTool,
|
|
7
7
|
reinforceUsed
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LLL7QWXB.js";
|
|
9
9
|
import {
|
|
10
10
|
ToolRegistry,
|
|
11
11
|
runStructuredRole
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-AE36LLL2.js";
|
|
13
13
|
|
|
14
14
|
// src/engine/triage.ts
|
|
15
15
|
import { z } from "zod";
|
|
@@ -15,7 +15,18 @@ var defaultGitRunner = (args, cwd) => new Promise((resolve) => {
|
|
|
15
15
|
child.on("error", (e) => resolve({ stdout, stderr: stderr + e.message, code: -1 }));
|
|
16
16
|
child.on("close", (code) => resolve({ stdout, stderr, code: code ?? -1 }));
|
|
17
17
|
});
|
|
18
|
+
var TAKES_A_VALUE = /* @__PURE__ */ new Set(["-c", "-C", "--git-dir", "--work-tree", "--namespace", "--exec-path", "--config-env"]);
|
|
19
|
+
function gitVerb(args) {
|
|
20
|
+
for (let i = 0; i < args.length; i++) {
|
|
21
|
+
const a = args[i];
|
|
22
|
+
if (a === void 0) continue;
|
|
23
|
+
if (!a.startsWith("-")) return a;
|
|
24
|
+
if (TAKES_A_VALUE.has(a)) i++;
|
|
25
|
+
}
|
|
26
|
+
return void 0;
|
|
27
|
+
}
|
|
18
28
|
|
|
19
29
|
export {
|
|
20
|
-
defaultGitRunner
|
|
30
|
+
defaultGitRunner,
|
|
31
|
+
gitVerb
|
|
21
32
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// src/engine/language.ts
|
|
2
|
+
function respondIn(language) {
|
|
3
|
+
if (!language || /^english$/i.test(language)) return "";
|
|
4
|
+
return `
|
|
5
|
+
|
|
6
|
+
Respond to the user in ${language}: everything you say to them, and every question you ask, is in ${language}. Code, identifiers, logs and commit messages keep whatever language the project uses.`;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
respondIn
|
|
11
|
+
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defaultGitRunner
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LPQU436C.js";
|
|
4
4
|
import {
|
|
5
5
|
briefForPrompt,
|
|
6
6
|
briefPrompt,
|
|
7
7
|
briefStatus,
|
|
8
8
|
gatherBriefInput,
|
|
9
9
|
saveBrief
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-6OSEQOYY.js";
|
|
11
11
|
import {
|
|
12
12
|
ensureGitignore,
|
|
13
13
|
loadTraceIndex,
|
|
@@ -19,10 +19,10 @@ import {
|
|
|
19
19
|
tracePrompt,
|
|
20
20
|
traceRootRel,
|
|
21
21
|
traceable
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-KAGKX2YT.js";
|
|
23
23
|
import {
|
|
24
24
|
loadGraph
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-XEGQT5EN.js";
|
|
26
26
|
|
|
27
27
|
// src/engine/trace-run.ts
|
|
28
28
|
async function traceableFiles(cwd, opts) {
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
stateRoot,
|
|
3
|
-
writableStateRoot
|
|
4
|
-
} from "./chunk-SSDLHWSF.js";
|
|
5
|
-
import {
|
|
3
|
+
writableStateRoot,
|
|
6
4
|
writeAtomic
|
|
7
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-6W4UH2BQ.js";
|
|
8
6
|
|
|
9
7
|
// src/engine/project-graph.ts
|
|
10
8
|
import { readFile, stat } from "fs/promises";
|
|
@@ -302,7 +300,7 @@ function pruneTooling(doc, alsoDrop = /* @__PURE__ */ new Set()) {
|
|
|
302
300
|
async function writtenTracePaths(cwd) {
|
|
303
301
|
const out = /* @__PURE__ */ new Set();
|
|
304
302
|
try {
|
|
305
|
-
const { loadTraceIndex, traceRootRel } = await import("./trace-
|
|
303
|
+
const { loadTraceIndex, traceRootRel } = await import("./trace-X6TU3AG6.js");
|
|
306
304
|
const index = await loadTraceIndex(cwd);
|
|
307
305
|
const root = traceRootRel().replace(/\\/g, "/");
|
|
308
306
|
for (const [file, rec] of Object.entries(index.traces)) {
|