@hizliemre/horse-code 0.1.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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/dist/app-SB2L34JW.js +6217 -0
  4. package/dist/chunk-2DGO2BUB.js +4490 -0
  5. package/dist/chunk-2SVAHH5N.js +60 -0
  6. package/dist/chunk-3XVZXTB6.js +4469 -0
  7. package/dist/chunk-5UWA2UBM.js +69 -0
  8. package/dist/chunk-7TBYMFMG.js +147 -0
  9. package/dist/chunk-B67BK5GQ.js +34 -0
  10. package/dist/chunk-BY4DP7IE.js +20 -0
  11. package/dist/chunk-DKVIN43T.js +54 -0
  12. package/dist/chunk-DTWKSZXY.js +162 -0
  13. package/dist/chunk-F2IALVBU.js +212 -0
  14. package/dist/chunk-FFYBY2NA.js +392 -0
  15. package/dist/chunk-FGVJFMK5.js +123 -0
  16. package/dist/chunk-H2FDGPVW.js +42 -0
  17. package/dist/chunk-HBSC2HT2.js +85 -0
  18. package/dist/chunk-IW2KBAVZ.js +21 -0
  19. package/dist/chunk-JWAEW7AJ.js +121 -0
  20. package/dist/chunk-NNTIACT4.js +163 -0
  21. package/dist/chunk-O74BDQKS.js +28 -0
  22. package/dist/chunk-PGOYDOI4.js +426 -0
  23. package/dist/chunk-QF4MP6BS.js +69 -0
  24. package/dist/chunk-SSDLHWSF.js +35 -0
  25. package/dist/chunk-TOPZL5SU.js +1052 -0
  26. package/dist/chunk-YBWTCXUS.js +153 -0
  27. package/dist/chunk-YILDXPSI.js +1363 -0
  28. package/dist/clean-YOQATBMZ.js +18 -0
  29. package/dist/cli.js +1495 -0
  30. package/dist/discover-5URG7C4J.js +52 -0
  31. package/dist/fix-HBBOTUWM.js +34 -0
  32. package/dist/frontmatter-UNIPNLLO.js +6 -0
  33. package/dist/git-VTSZALSR.js +6 -0
  34. package/dist/install-O34KMWJB.js +113 -0
  35. package/dist/main-branch-KGWUINYQ.js +19 -0
  36. package/dist/ongoing-OV5XROTU.js +70 -0
  37. package/dist/project-graph-IOPCSZUA.js +56 -0
  38. package/dist/run-LQOZ5I7Z.js +610 -0
  39. package/dist/save-skills-OHYGVTQ4.js +13 -0
  40. package/dist/source-cache-XEK5WN7I.js +29 -0
  41. package/dist/trace-ZMB7LT7W.js +66 -0
  42. package/dist/trace-adopt-C6TUWFJL.js +79 -0
  43. package/dist/trace-run-F23MFTY4.js +24 -0
  44. package/dist/triage-2J3T5PVQ.js +30 -0
  45. package/dist/verify-WQ3GHION.js +479 -0
  46. package/dist/worktree-F7TWLWLN.js +87 -0
  47. package/package.json +64 -0
@@ -0,0 +1,52 @@
1
+ import {
2
+ isFreeModel
3
+ } from "./chunk-O74BDQKS.js";
4
+
5
+ // src/providers/discover.ts
6
+ async function fetchCatalog(opts) {
7
+ const fetchFn = opts.fetch ?? globalThis.fetch;
8
+ const headers = {};
9
+ if (opts.apiKey) headers.Authorization = `Bearer ${opts.apiKey}`;
10
+ const res = await fetchFn(`${opts.baseUrl.replace(/\/$/, "")}/api/v1/models`, { headers });
11
+ if (!res.ok) throw new Error(`omniroute models ${res.status}`);
12
+ const body = await res.json();
13
+ return (body.data ?? []).filter((m) => typeof m?.id === "string");
14
+ }
15
+ function makeProbe(opts) {
16
+ const fetchFn = opts.fetch ?? globalThis.fetch;
17
+ const headers = { "Content-Type": "application/json" };
18
+ if (opts.apiKey) headers.Authorization = `Bearer ${opts.apiKey}`;
19
+ const url = `${opts.baseUrl.replace(/\/$/, "")}/api/v1/chat/completions`;
20
+ const timeoutMs = opts.timeoutMs ?? 25e3;
21
+ return async (model) => {
22
+ try {
23
+ const res = await fetchFn(url, {
24
+ method: "POST",
25
+ headers,
26
+ body: JSON.stringify({ model, stream: false, max_tokens: 1, messages: [{ role: "user", content: "hi" }] }),
27
+ signal: AbortSignal.timeout(timeoutMs)
28
+ });
29
+ return res.status === 200 || res.status === 429;
30
+ } catch {
31
+ return false;
32
+ }
33
+ };
34
+ }
35
+ var META_SOURCES = /* @__PURE__ */ new Set(["combo"]);
36
+ var isCheapModel = (id) => /haiku|flash|mini|lite|\bfast\b/i.test(id);
37
+ async function discoverSources(opts) {
38
+ const probeModel = /* @__PURE__ */ new Map();
39
+ for (const m of opts.catalog) {
40
+ if (!m.owned_by || isFreeModel(m.id, m.name) || META_SOURCES.has(m.owned_by)) continue;
41
+ const cur = probeModel.get(m.owned_by);
42
+ if (!cur || isCheapModel(m.id) && !isCheapModel(cur)) probeModel.set(m.owned_by, m.id);
43
+ }
44
+ const entries = [...probeModel.entries()];
45
+ const results = await Promise.all(entries.map(async ([source, model]) => ({ source, ok: await opts.probe(model) })));
46
+ return results.filter((r) => r.ok).map((r) => r.source).sort();
47
+ }
48
+ export {
49
+ discoverSources,
50
+ fetchCatalog,
51
+ makeProbe
52
+ };
@@ -0,0 +1,34 @@
1
+ import {
2
+ FIX_ATTEMPTS,
3
+ cardFromFinding,
4
+ commitFix,
5
+ commitOnly,
6
+ describeFix,
7
+ describeSmallChange,
8
+ dirtyPaths,
9
+ runFix,
10
+ runSmallChange
11
+ } from "./chunk-JWAEW7AJ.js";
12
+ import "./chunk-3XVZXTB6.js";
13
+ import "./chunk-FGVJFMK5.js";
14
+ import "./chunk-NNTIACT4.js";
15
+ import "./chunk-IW2KBAVZ.js";
16
+ import "./chunk-TOPZL5SU.js";
17
+ import "./chunk-2SVAHH5N.js";
18
+ import "./chunk-YILDXPSI.js";
19
+ import "./chunk-DTWKSZXY.js";
20
+ import "./chunk-FFYBY2NA.js";
21
+ import "./chunk-PGOYDOI4.js";
22
+ import "./chunk-SSDLHWSF.js";
23
+ import "./chunk-B67BK5GQ.js";
24
+ export {
25
+ FIX_ATTEMPTS,
26
+ cardFromFinding,
27
+ commitFix,
28
+ commitOnly,
29
+ describeFix,
30
+ describeSmallChange,
31
+ dirtyPaths,
32
+ runFix,
33
+ runSmallChange
34
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ parseFrontmatter
3
+ } from "./chunk-BY4DP7IE.js";
4
+ export {
5
+ parseFrontmatter
6
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ defaultGitRunner
3
+ } from "./chunk-IW2KBAVZ.js";
4
+ export {
5
+ defaultGitRunner
6
+ };
@@ -0,0 +1,113 @@
1
+ import {
2
+ connectMcpServer
3
+ } from "./chunk-5UWA2UBM.js";
4
+
5
+ // src/mcp/install.ts
6
+ var MAX_PAGE_CHARS = 4e4;
7
+ function pageText(html) {
8
+ const text = html.replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<[^>]+>/g, " ").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/[ \t]+/g, " ").replace(/\n{3,}/g, "\n\n");
9
+ return text.length > MAX_PAGE_CHARS ? text.slice(0, MAX_PAGE_CHARS) : text;
10
+ }
11
+ function parseCommand(input) {
12
+ const t = input.trim();
13
+ if (/^https?:\/\//i.test(t) || t.startsWith("{")) return void 0;
14
+ const argv = t.match(/"[^"]*"|'[^']*'|\S+/g)?.map((a) => a.replace(/^['"]|['"]$/g, "")) ?? [];
15
+ if (argv.length < 2) return void 0;
16
+ if (!/^(npx|node|python3?|uvx|uv|bunx|deno|docker|sh|bash)$/.test(argv[0])) return void 0;
17
+ return { name: guessName(argv), spec: { command: argv }, source: "the command you gave" };
18
+ }
19
+ function guessName(argv) {
20
+ const pkg = argv.slice(1).find((a) => !a.startsWith("-") && a !== "mcp");
21
+ const raw = (pkg ?? argv[0]).replace(/^@/, "").replace(/@[^/]*$/, "");
22
+ return raw.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase() || "server";
23
+ }
24
+ function parseConfigBlock(input) {
25
+ const t = input.trim();
26
+ if (!t.startsWith("{")) return void 0;
27
+ try {
28
+ const parsed = JSON.parse(t);
29
+ const wrapper = parsed.mcpServers ?? parsed.servers;
30
+ const [name, body] = wrapper ? Object.entries(wrapper)[0] ?? [] : ["server", parsed];
31
+ if (!body) return void 0;
32
+ const spec = toSpec(body);
33
+ return spec ? { name: name ?? "server", spec, source: "the configuration you pasted" } : void 0;
34
+ } catch {
35
+ return void 0;
36
+ }
37
+ }
38
+ function toSpec(body) {
39
+ if (typeof body.url === "string") return { url: body.url };
40
+ if (typeof body.command === "string") {
41
+ const args = Array.isArray(body.args) ? body.args.filter((a) => typeof a === "string") : [];
42
+ return { command: [body.command, ...args] };
43
+ }
44
+ if (Array.isArray(body.command)) {
45
+ const argv = body.command.filter((a) => typeof a === "string");
46
+ return argv.length ? { command: argv } : void 0;
47
+ }
48
+ return void 0;
49
+ }
50
+ var EXTRACT = (url, text) => `This page documents how to install an MCP (Model Context Protocol) server. Extract the server configuration.
51
+
52
+ Pages usually show the SAME server several times, once per editor (Cursor, VS Code, Claude Code, \u2026). They differ only in which file the JSON goes in \u2014 the server itself is the same. Return it ONCE.
53
+
54
+ Answer with a fenced json block:
55
+ {"name":"<short identifier>","command":["<program>","<arg>", \u2026]}
56
+ or, for a remote server:
57
+ {"name":"<short identifier>","url":"https://\u2026"}
58
+
59
+ Rules:
60
+ - Take the command EXACTLY as documented, including flags like -y. A missing flag produces a server that hangs on a prompt nobody can see.
61
+ - Do not invent a command. If the page does not state one, answer {"name":"","command":[]}.
62
+ - The name becomes the prefix on every tool the server exposes: short, lowercase, no spaces.
63
+
64
+ Page: ${url}
65
+
66
+ ${text}`;
67
+ async function extractFromPage(opts) {
68
+ const req = {
69
+ model: opts.model,
70
+ messages: [
71
+ { role: "system", content: "You extract MCP server configuration from documentation. You never invent a command." },
72
+ { role: "user", content: EXTRACT(opts.url, pageText(opts.html)) }
73
+ ],
74
+ tools: []
75
+ };
76
+ let out = "";
77
+ for await (const ev of opts.provider.chat(req, opts.signal ?? new AbortController().signal)) {
78
+ if (ev.type === "text-delta") out += ev.text;
79
+ else if (ev.type === "error") throw new Error(ev.message);
80
+ }
81
+ const fence = /```(?:json)?\s*([\s\S]*?)```/.exec(out);
82
+ try {
83
+ const parsed = JSON.parse(fence ? fence[1] : out.slice(out.indexOf("{")));
84
+ const spec = toSpec(parsed);
85
+ if (!spec) return void 0;
86
+ const name = (parsed.name ?? "").trim() || guessName("command" in spec ? spec.command : ["server"]);
87
+ return { name, spec, source: opts.url };
88
+ } catch {
89
+ return void 0;
90
+ }
91
+ }
92
+ async function verify(spec, name, timeoutMs = 6e4) {
93
+ try {
94
+ const conn = await Promise.race([
95
+ connectMcpServer(name, spec),
96
+ new Promise((_, rej) => setTimeout(() => rej(new Error("it did not respond in time")), timeoutMs))
97
+ ]);
98
+ const tools = conn.tools.map((t) => ({ name: t.name, readOnly: t.readOnly }));
99
+ await conn.close();
100
+ if (!tools.length) return { ok: false, tools: [], error: "it connected but exposes no tools" };
101
+ return { ok: true, tools };
102
+ } catch (e) {
103
+ return { ok: false, tools: [], error: e instanceof Error ? e.message : String(e) };
104
+ }
105
+ }
106
+ export {
107
+ MAX_PAGE_CHARS,
108
+ extractFromPage,
109
+ pageText,
110
+ parseCommand,
111
+ parseConfigBlock,
112
+ verify
113
+ };
@@ -0,0 +1,19 @@
1
+ import {
2
+ COMMON_MAIN_BRANCHES,
3
+ MAIN_BRANCH_QUESTION,
4
+ detectMainBranch,
5
+ mainBranchChoices,
6
+ recordedMainBranch,
7
+ resolveMainBranch,
8
+ saveMainBranch
9
+ } from "./chunk-QF4MP6BS.js";
10
+ import "./chunk-H2FDGPVW.js";
11
+ export {
12
+ COMMON_MAIN_BRANCHES,
13
+ MAIN_BRANCH_QUESTION,
14
+ detectMainBranch,
15
+ mainBranchChoices,
16
+ recordedMainBranch,
17
+ resolveMainBranch,
18
+ saveMainBranch
19
+ };
@@ -0,0 +1,70 @@
1
+ import {
2
+ surveySessions
3
+ } from "./chunk-YBWTCXUS.js";
4
+ import {
5
+ askInUserLanguage
6
+ } from "./chunk-HBSC2HT2.js";
7
+ import {
8
+ checkpointMtime,
9
+ readCheckpoint
10
+ } from "./chunk-FGVJFMK5.js";
11
+ import "./chunk-YILDXPSI.js";
12
+ import "./chunk-B67BK5GQ.js";
13
+
14
+ // src/engine/ongoing.ts
15
+ import { join } from "path";
16
+ var MAX_WHAT_CHARS = 110;
17
+ function oneLine(text) {
18
+ const t = text.replace(/\s+/g, " ").trim();
19
+ return t.length <= MAX_WHAT_CHARS ? t : `${t.slice(0, MAX_WHAT_CHARS - 1).trimEnd()}\u2026`;
20
+ }
21
+ async function whatIsHappening(git, repoRoot, root, baseBranch) {
22
+ const cp = readCheckpoint(root);
23
+ if (cp?.refinedPrompt?.trim()) return oneLine(cp.refinedPrompt);
24
+ if (cp?.title?.trim()) return oneLine(cp.title.replace(/-/g, " "));
25
+ const last = await git(["log", "-1", "--format=%s", baseBranch], repoRoot);
26
+ if (last.code === 0 && last.stdout.trim()) return oneLine(last.stdout);
27
+ return "no description was recorded for this work";
28
+ }
29
+ async function ongoingWork(git, repoRoot, mainBranch) {
30
+ const survey = await surveySessions(git, repoRoot, mainBranch).catch(() => []);
31
+ const out = [];
32
+ for (const s of survey) {
33
+ if (s.verdict !== "unmerged" && s.verdict !== "dirty") continue;
34
+ const cp = readCheckpoint(s.root);
35
+ out.push({
36
+ slug: s.slug,
37
+ root: s.root,
38
+ baseWorktree: join(s.root, "base"),
39
+ baseBranch: s.baseBranch,
40
+ what: await whatIsHappening(git, repoRoot, s.root, s.baseBranch),
41
+ state: s.detail,
42
+ when: checkpointMtime(s.root),
43
+ ...cp?.language ? { language: cp.language } : {}
44
+ });
45
+ }
46
+ return out.sort((a, b) => b.when - a.when);
47
+ }
48
+ var NEW_WORK_LABEL = "Start fresh \u2014 a new worktree";
49
+ var ONGOING_QUESTION = "There is work already open in this project that has not reached the main branch. Carry on with one of these, or start something new?";
50
+ function ongoingChoices(items) {
51
+ return [
52
+ ...items.map((o) => ({ label: o.slug, description: `${o.what} \u2014 ${o.state}` })),
53
+ { label: NEW_WORK_LABEL, description: "Nothing above is this; open a new worktree for it." }
54
+ ];
55
+ }
56
+ async function chooseOngoing(deps, askUser, language, items) {
57
+ if (!items.length) return void 0;
58
+ const choices = ongoingChoices(items);
59
+ const answer = (await askInUserLanguage(deps, askUser, language, ONGOING_QUESTION, choices)).trim();
60
+ const at = choices.findIndex((c) => c.label === answer);
61
+ return at >= 0 && at < items.length ? items[at] : void 0;
62
+ }
63
+ export {
64
+ MAX_WHAT_CHARS,
65
+ NEW_WORK_LABEL,
66
+ ONGOING_QUESTION,
67
+ chooseOngoing,
68
+ ongoingChoices,
69
+ ongoingWork
70
+ };
@@ -0,0 +1,56 @@
1
+ import {
2
+ BUILD_IDLE_TIMEOUT_MS,
3
+ GRAPH_DIR,
4
+ GRAPH_FILE,
5
+ LABELS_FILE,
6
+ LABEL_LOSS_LIMIT,
7
+ MAX_STALE_CHECK,
8
+ STAMP_FILE,
9
+ areaOf,
10
+ buildProjectGraph,
11
+ changedSince,
12
+ failureReason,
13
+ graphPath,
14
+ graphRoot,
15
+ graphStatus,
16
+ graphifyPython,
17
+ labelsPath,
18
+ loadGraph,
19
+ loadGraphSync,
20
+ namedCount,
21
+ parseAreas,
22
+ parseGraph,
23
+ pruneAreaNames,
24
+ pruneTooling,
25
+ readStamp,
26
+ stampPath
27
+ } from "./chunk-PGOYDOI4.js";
28
+ import "./chunk-SSDLHWSF.js";
29
+ import "./chunk-B67BK5GQ.js";
30
+ export {
31
+ BUILD_IDLE_TIMEOUT_MS,
32
+ GRAPH_DIR,
33
+ GRAPH_FILE,
34
+ LABELS_FILE,
35
+ LABEL_LOSS_LIMIT,
36
+ MAX_STALE_CHECK,
37
+ STAMP_FILE,
38
+ areaOf,
39
+ buildProjectGraph,
40
+ changedSince,
41
+ failureReason,
42
+ graphPath,
43
+ graphRoot,
44
+ graphStatus,
45
+ graphifyPython,
46
+ labelsPath,
47
+ loadGraph,
48
+ loadGraphSync,
49
+ namedCount,
50
+ parseAreas,
51
+ parseGraph,
52
+ pruneAreaNames,
53
+ pruneTooling,
54
+ readStamp,
55
+ stampPath
56
+ };