@reposkein/mcp 0.3.0 → 0.4.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 (98) hide show
  1. package/README.md +73 -1
  2. package/binary-digests.json +4 -4
  3. package/dist/SKILL.md +19 -0
  4. package/dist/cli/agentAdapters.d.ts +68 -0
  5. package/dist/cli/agentAdapters.js +223 -0
  6. package/dist/cli/agentAdapters.js.map +1 -0
  7. package/dist/cli/ansi.d.ts +24 -0
  8. package/dist/cli/ansi.js +40 -0
  9. package/dist/cli/ansi.js.map +1 -0
  10. package/dist/cli/doctor.d.ts +34 -2
  11. package/dist/cli/doctor.js +51 -6
  12. package/dist/cli/doctor.js.map +1 -1
  13. package/dist/cli/doctorFreshness.d.ts +43 -0
  14. package/dist/cli/doctorFreshness.js +111 -0
  15. package/dist/cli/doctorFreshness.js.map +1 -0
  16. package/dist/cli/doctorSummaries.d.ts +2 -0
  17. package/dist/cli/doctorSummaries.js +95 -0
  18. package/dist/cli/doctorSummaries.js.map +1 -0
  19. package/dist/cli/federatedDiscovery.d.ts +16 -0
  20. package/dist/cli/federatedDiscovery.js +75 -0
  21. package/dist/cli/federatedDiscovery.js.map +1 -0
  22. package/dist/cli/init.d.ts +69 -6
  23. package/dist/cli/init.js +194 -28
  24. package/dist/cli/init.js.map +1 -1
  25. package/dist/cli/sourceSlices.d.ts +17 -0
  26. package/dist/cli/sourceSlices.js +59 -0
  27. package/dist/cli/sourceSlices.js.map +1 -0
  28. package/dist/cli/stats.d.ts +29 -0
  29. package/dist/cli/stats.js +180 -0
  30. package/dist/cli/stats.js.map +1 -0
  31. package/dist/cli/view.d.ts +71 -3
  32. package/dist/cli/view.js +147 -12
  33. package/dist/cli/view.js.map +1 -1
  34. package/dist/index.d.ts +8 -0
  35. package/dist/index.js +286 -123
  36. package/dist/index.js.map +1 -1
  37. package/dist/indexer/fetchBinary.d.ts +14 -0
  38. package/dist/indexer/fetchBinary.js +81 -40
  39. package/dist/indexer/fetchBinary.js.map +1 -1
  40. package/dist/indexer/runIndexer.d.ts +0 -2
  41. package/dist/indexer/runIndexer.js +8 -4
  42. package/dist/indexer/runIndexer.js.map +1 -1
  43. package/dist/store/JsonlGraphStore.d.ts +13 -3
  44. package/dist/store/JsonlGraphStore.js +55 -17
  45. package/dist/store/JsonlGraphStore.js.map +1 -1
  46. package/dist/store/decisions.d.ts +20 -2
  47. package/dist/store/decisions.js +35 -2
  48. package/dist/store/decisions.js.map +1 -1
  49. package/dist/store/indexedAt.d.ts +18 -0
  50. package/dist/store/indexedAt.js +56 -0
  51. package/dist/store/indexedAt.js.map +1 -0
  52. package/dist/store/instrumentTool.d.ts +40 -0
  53. package/dist/store/instrumentTool.js +82 -0
  54. package/dist/store/instrumentTool.js.map +1 -0
  55. package/dist/store/repoContextCache.d.ts +15 -0
  56. package/dist/store/repoContextCache.js +26 -0
  57. package/dist/store/repoContextCache.js.map +1 -0
  58. package/dist/store/repoSession.d.ts +63 -0
  59. package/dist/store/repoSession.js +123 -0
  60. package/dist/store/repoSession.js.map +1 -0
  61. package/dist/store/resolveRepoPath.d.ts +31 -0
  62. package/dist/store/resolveRepoPath.js +85 -0
  63. package/dist/store/resolveRepoPath.js.map +1 -0
  64. package/dist/store/sessionLog.d.ts +98 -0
  65. package/dist/store/sessionLog.js +216 -0
  66. package/dist/store/sessionLog.js.map +1 -0
  67. package/dist/store/sessionStats.d.ts +55 -0
  68. package/dist/store/sessionStats.js +140 -0
  69. package/dist/store/sessionStats.js.map +1 -0
  70. package/dist/store/sidecar.d.ts +39 -3
  71. package/dist/store/sidecar.js +89 -5
  72. package/dist/store/sidecar.js.map +1 -1
  73. package/dist/store/summaryShards.d.ts +117 -0
  74. package/dist/store/summaryShards.js +291 -0
  75. package/dist/store/summaryShards.js.map +1 -0
  76. package/dist/store/teamConfig.d.ts +13 -0
  77. package/dist/store/teamConfig.js +49 -0
  78. package/dist/store/teamConfig.js.map +1 -0
  79. package/dist/tools/indexerTools.d.ts +14 -2
  80. package/dist/tools/indexerTools.js +17 -5
  81. package/dist/tools/indexerTools.js.map +1 -1
  82. package/dist/tools/recordDecision.js +6 -1
  83. package/dist/tools/recordDecision.js.map +1 -1
  84. package/dist/viz/assets/{graph.worker-CC7BeE-8.js → graph.worker-DkH6-lMU.js} +1 -1
  85. package/dist/viz/assets/index-CxqeGuRS.css +1 -0
  86. package/dist/viz/assets/index-DiNZyrXx.js +9 -0
  87. package/dist/viz/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  88. package/dist/viz/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  89. package/dist/viz/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
  90. package/dist/viz/assets/r3f-BZY3QR6_.js +336 -0
  91. package/dist/viz/assets/tanstack-CjXr-L-s.js +62 -0
  92. package/dist/viz/assets/three-Cpu5RUEM.js +4116 -0
  93. package/dist/viz/index.html +5 -4
  94. package/package.json +5 -4
  95. package/dist/viz/assets/index-C_8UkiJ8.js +0 -9
  96. package/dist/viz/assets/r3f-Cku1OhB-.js +0 -277
  97. package/dist/viz/assets/tanstack-DyXcNRWk.js +0 -77
  98. package/dist/viz/assets/three-Z8XaLGmf.js +0 -3839
@@ -0,0 +1,56 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { execFileSync } from "node:child_process";
3
+ import { join } from "node:path";
4
+ /** Path to the file recording the git commit SHA that was HEAD the last time
5
+ * the mcp-side index invocation path (`reposkein-mcp index`, or `init`'s
6
+ * initial index) completed successfully. Lives under `.reposkein/local/` —
7
+ * per-machine scratch that's gitignored and never committed — so it never
8
+ * survives a `git clone`. That's deliberate: a fresh clone has no idea what
9
+ * commit (if any) its nonexistent graph was built from, which is exactly
10
+ * the state `doctor --ci`'s `graph_stale` check should fail on. */
11
+ export function indexedAtPath(repoPath) {
12
+ return join(repoPath, ".reposkein", "local", "indexed-at");
13
+ }
14
+ /** Records the current git HEAD as "the commit the graph was just built
15
+ * from". Best-effort and silent: not a git repo / no HEAD yet / a read-only
16
+ * filesystem all just skip the write — `graph_stale` degrades to "never
17
+ * recorded" (fails, conservatively) rather than the index step itself
18
+ * failing over a scratch-file write. */
19
+ export function writeIndexedAtMarker(repoPath) {
20
+ let sha;
21
+ try {
22
+ sha = execFileSync("git", ["-C", repoPath, "rev-parse", "HEAD"], {
23
+ encoding: "utf8",
24
+ stdio: ["ignore", "pipe", "ignore"],
25
+ }).trim();
26
+ }
27
+ catch {
28
+ return;
29
+ }
30
+ if (!sha)
31
+ return;
32
+ try {
33
+ const path = indexedAtPath(repoPath);
34
+ mkdirSync(join(path, ".."), { recursive: true });
35
+ writeFileSync(path, sha + "\n", "utf8");
36
+ }
37
+ catch {
38
+ /* best-effort */
39
+ }
40
+ }
41
+ /** Reads the recorded indexed-at SHA, or null when never recorded — never
42
+ * indexed via the mcp-side path, or a fresh clone (local/ isn't committed,
43
+ * so it never carries over). */
44
+ export function readIndexedAtSha(repoPath) {
45
+ const path = indexedAtPath(repoPath);
46
+ if (!existsSync(path))
47
+ return null;
48
+ try {
49
+ const sha = readFileSync(path, "utf8").trim();
50
+ return sha || null;
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ //# sourceMappingURL=indexedAt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexedAt.js","sourceRoot":"","sources":["../../src/store/indexedAt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;oEAMoE;AACpE,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;AAC7D,CAAC;AAED;;;;yCAIyC;AACzC,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE;YAC/D,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACrC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,aAAa,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC;AAED;;iCAEiC;AACjC,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,OAAO,GAAG,IAAI,IAAI,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { RepoResolution } from "./resolveRepoPath.js";
2
+ import type { RepoSession } from "./repoSession.js";
3
+ import { type SessionLogger, type ToolResultLike } from "./sessionLog.js";
4
+ export interface ToolLogger {
5
+ /** `session.resolve()`, memoized for the lifetime of the CURRENT tool
6
+ * call (see `withLog`) — a handler that calls this (directly, or via
7
+ * `resolveActiveRepo`) and the logging wrapper both see the same
8
+ * filesystem walk, not two. Isolated per call via AsyncLocalStorage, so
9
+ * concurrent/overlapping tool calls never share a cached value. Falls
10
+ * back to a plain, uncached `session.resolve()` when called outside any
11
+ * `withLog`-wrapped call (e.g. server startup). */
12
+ cachedResolve(): RepoResolution;
13
+ /** Wraps a tool handler so its call is logged to the active repo's
14
+ * session log — see sessionLog.ts. `Args`/result type are inferred from
15
+ * the handler passed in, so call sites (`server.registerTool(name,
16
+ * config, withLog(name, async (args) => {...}))`) need no extra typing. */
17
+ withLog<Args, R extends ToolResultLike>(name: string, cb: (args: Args) => Promise<R>): (args: Args) => Promise<R>;
18
+ }
19
+ /** Builds the tool-call instrumentation for one MCP server connection: one
20
+ * `ToolLogger` shared across every `server.registerTool` call (REP-20).
21
+ *
22
+ * Two hot-path fixes from review round 1, both scoped to this module so
23
+ * they're covered without spinning up the whole server:
24
+ *
25
+ * 1. Single resolution per call — `cachedResolve()` memoizes
26
+ * `session.resolve()` per call (AsyncLocalStorage-scoped), so a
27
+ * handler's own resolution (via `resolveActiveRepo`, or a direct
28
+ * `cachedResolve()` call for the couple of tools that don't gate on a
29
+ * full repo context) and the logging wrapper's resolution are the same
30
+ * filesystem walk, not two.
31
+ * 2. Deferred write — the `finally` block below only captures cheap,
32
+ * already-computed references synchronously (tool name, argsShape, the
33
+ * resolved repo path, the result object BY REFERENCE, ok, ts) and
34
+ * returns immediately; JSON-parsing the result for `extractTouchedIds`
35
+ * and the actual file write happen in a `schedule()`-deferred callback
36
+ * (default `setImmediate`), which runs only after the response has
37
+ * already been handed back to the MCP transport. The deferred callback
38
+ * swallows every error itself — it must never surface as an unhandled
39
+ * exception/rejection. */
40
+ export declare function createToolLogger(session: RepoSession, sessionLogger: SessionLogger, schedule?: (fn: () => void) => void): ToolLogger;
@@ -0,0 +1,82 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { argsShapeOf, extractTouchedIds, resultByteSize } from "./sessionLog.js";
3
+ /** Builds the tool-call instrumentation for one MCP server connection: one
4
+ * `ToolLogger` shared across every `server.registerTool` call (REP-20).
5
+ *
6
+ * Two hot-path fixes from review round 1, both scoped to this module so
7
+ * they're covered without spinning up the whole server:
8
+ *
9
+ * 1. Single resolution per call — `cachedResolve()` memoizes
10
+ * `session.resolve()` per call (AsyncLocalStorage-scoped), so a
11
+ * handler's own resolution (via `resolveActiveRepo`, or a direct
12
+ * `cachedResolve()` call for the couple of tools that don't gate on a
13
+ * full repo context) and the logging wrapper's resolution are the same
14
+ * filesystem walk, not two.
15
+ * 2. Deferred write — the `finally` block below only captures cheap,
16
+ * already-computed references synchronously (tool name, argsShape, the
17
+ * resolved repo path, the result object BY REFERENCE, ok, ts) and
18
+ * returns immediately; JSON-parsing the result for `extractTouchedIds`
19
+ * and the actual file write happen in a `schedule()`-deferred callback
20
+ * (default `setImmediate`), which runs only after the response has
21
+ * already been handed back to the MCP transport. The deferred callback
22
+ * swallows every error itself — it must never surface as an unhandled
23
+ * exception/rejection. */
24
+ export function createToolLogger(session, sessionLogger, schedule = setImmediate) {
25
+ const als = new AsyncLocalStorage();
26
+ function cachedResolve() {
27
+ const store = als.getStore();
28
+ if (!store)
29
+ return session.resolve();
30
+ if (!store.value)
31
+ store.value = session.resolve();
32
+ return store.value;
33
+ }
34
+ function deferredLog(ts, repoPath, tool, argsShape, ok, result) {
35
+ schedule(() => {
36
+ try {
37
+ const resultBytes = resultByteSize(result);
38
+ const nodeIds = extractTouchedIds(result);
39
+ sessionLogger.logAt(ts, repoPath, {
40
+ tool,
41
+ argsShape,
42
+ resultBytes,
43
+ ...(nodeIds.length ? { nodeIds } : {}),
44
+ ok,
45
+ });
46
+ }
47
+ catch {
48
+ // deferred logging must never surface as an unhandled exception
49
+ }
50
+ });
51
+ }
52
+ function withLog(name, cb) {
53
+ return (args) => als.run({}, async () => {
54
+ let result;
55
+ let threw = false;
56
+ try {
57
+ result = await cb(args);
58
+ return result;
59
+ }
60
+ catch (err) {
61
+ threw = true;
62
+ throw err;
63
+ }
64
+ finally {
65
+ // Cheap, synchronous capture only — no JSON.parse, no fs calls on
66
+ // the hot path. `result` is captured BY REFERENCE; it isn't read
67
+ // until the deferred callback runs.
68
+ try {
69
+ const resolution = cachedResolve();
70
+ if (resolution.repoPath) {
71
+ deferredLog(new Date().toISOString(), resolution.repoPath, name, argsShapeOf(args), !threw && result?.isError !== true, result);
72
+ }
73
+ }
74
+ catch {
75
+ // instrumentation must never affect the tool call
76
+ }
77
+ }
78
+ });
79
+ }
80
+ return { cachedResolve, withLog };
81
+ }
82
+ //# sourceMappingURL=instrumentTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumentTool.js","sourceRoot":"","sources":["../../src/store/instrumentTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAA2C,MAAM,iBAAiB,CAAC;AAsB1H;;;;;;;;;;;;;;;;;;;;8BAoB8B;AAC9B,MAAM,UAAU,gBAAgB,CAC9B,OAAoB,EACpB,aAA4B,EAC5B,WAAqC,YAAY;IAEjD,MAAM,GAAG,GAAG,IAAI,iBAAiB,EAAa,CAAC;IAE/C,SAAS,aAAa;QACpB,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC,KAAK;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,KAAK;YAAE,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,SAAS,WAAW,CAClB,EAAU,EACV,QAAgB,EAChB,IAAY,EACZ,SAAmB,EACnB,EAAW,EACX,MAAkC;QAElC,QAAQ,CAAC,GAAG,EAAE;YACZ,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;gBAC3C,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;gBAC1C,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,EAAE;oBAChC,IAAI;oBACJ,SAAS;oBACT,WAAW;oBACX,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACtC,EAAE;iBACH,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,gEAAgE;YAClE,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,OAAO,CACd,IAAY,EACZ,EAA8B;QAE9B,OAAO,CAAC,IAAU,EAAc,EAAE,CAChC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,IAAI,EAAE;YACrB,IAAI,MAAqB,CAAC;YAC1B,IAAI,KAAK,GAAG,KAAK,CAAC;YAClB,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;gBACxB,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,GAAG,IAAI,CAAC;gBACb,MAAM,GAAG,CAAC;YACZ,CAAC;oBAAS,CAAC;gBACT,kEAAkE;gBAClE,iEAAiE;gBACjE,oCAAoC;gBACpC,IAAI,CAAC;oBACH,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;oBACnC,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;wBACxB,WAAW,CACT,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EACxB,UAAU,CAAC,QAAQ,EACnB,IAAI,EACJ,WAAW,CAAC,IAAI,CAAC,EACjB,CAAC,KAAK,IAAK,MAAqC,EAAE,OAAO,KAAK,IAAI,EAClE,MAAM,CACP,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,kDAAkD;gBACpD,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,15 @@
1
+ /** A minimal memoizing cache with a caching decision left to the caller —
2
+ * extracted so "never cache a failed/partial result" is one small, directly
3
+ * testable primitive rather than inline logic in mcp/src/index.ts.
4
+ *
5
+ * Context: index.ts's per-repoPath {repoId, store} cache used to cache
6
+ * every resolution unconditionally, including a repo whose `.reposkein/`
7
+ * exists but isn't indexed yet (no meta.json — `repoId` resolves to
8
+ * `undefined`). That froze a session on the failure forever: an agent that
9
+ * fixed the repo out-of-band (ran `reposkein-mcp index` in another
10
+ * terminal) stayed stuck until the server restarted, which defeats
11
+ * `select_repo`'s whole "no restart needed" point. `shouldCache` lets the
12
+ * caller keep re-attempting `compute` for exactly the states worth
13
+ * retrying, while still caching (and not repeatedly re-doing) real work
14
+ * for a successful resolution. */
15
+ export declare function makeCache<T>(compute: (key: string) => Promise<T>, shouldCache: (value: T) => boolean): (key: string) => Promise<T>;
@@ -0,0 +1,26 @@
1
+ /** A minimal memoizing cache with a caching decision left to the caller —
2
+ * extracted so "never cache a failed/partial result" is one small, directly
3
+ * testable primitive rather than inline logic in mcp/src/index.ts.
4
+ *
5
+ * Context: index.ts's per-repoPath {repoId, store} cache used to cache
6
+ * every resolution unconditionally, including a repo whose `.reposkein/`
7
+ * exists but isn't indexed yet (no meta.json — `repoId` resolves to
8
+ * `undefined`). That froze a session on the failure forever: an agent that
9
+ * fixed the repo out-of-band (ran `reposkein-mcp index` in another
10
+ * terminal) stayed stuck until the server restarted, which defeats
11
+ * `select_repo`'s whole "no restart needed" point. `shouldCache` lets the
12
+ * caller keep re-attempting `compute` for exactly the states worth
13
+ * retrying, while still caching (and not repeatedly re-doing) real work
14
+ * for a successful resolution. */
15
+ export function makeCache(compute, shouldCache) {
16
+ const cache = new Map();
17
+ return async (key) => {
18
+ if (cache.has(key))
19
+ return cache.get(key);
20
+ const value = await compute(key);
21
+ if (shouldCache(value))
22
+ cache.set(key, value);
23
+ return value;
24
+ };
25
+ }
26
+ //# sourceMappingURL=repoContextCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repoContextCache.js","sourceRoot":"","sources":["../../src/store/repoContextCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;mCAamC;AACnC,MAAM,UAAU,SAAS,CACvB,OAAoC,EACpC,WAAkC;IAElC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAa,CAAC;IACnC,OAAO,KAAK,EAAE,GAAW,EAAc,EAAE;QACvC,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAM,CAAC;QAC/C,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,WAAW,CAAC,KAAK,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { type RepoResolution } from "./resolveRepoPath.js";
2
+ export interface RepoInfo {
3
+ path: string;
4
+ /** From <path>/.reposkein/meta.json, when present. */
5
+ repo_id?: string;
6
+ /** Display name: repo_id if meta.json resolved one, else the directory's
7
+ * basename — always present so `select_repo` has something to match on
8
+ * even before the repo has been indexed (no meta.json yet). */
9
+ name: string;
10
+ /** Cheap line counts (not full parses) — omitted where the file is absent. */
11
+ nodes?: number;
12
+ edges?: number;
13
+ }
14
+ export declare function describeRepo(path: string): RepoInfo;
15
+ /** Every repo `list_repos` should report. Deliberately broader than
16
+ * `resolveRepoPath`'s own short-circuiting precedence: discovery always
17
+ * walks the filesystem (nearest ancestor with `.reposkein/`, else
18
+ * subdirectories) so a workspace's sibling repos are visible — and thus
19
+ * selectable via `select_repo` — even in a session where REPOSKEIN_REPO_PATH
20
+ * happens to pin one of them. That env pin is unioned in (deduped) so it's
21
+ * never missing from the list, but it does not suppress the others; only
22
+ * `resolveRepoPath`'s actual *default* pick (used by `resolve()` below)
23
+ * gives it priority over the walk. Sorted for deterministic output. */
24
+ export declare function discoverRepoPaths(opts: {
25
+ cwd: string;
26
+ envRepoPath?: string;
27
+ }): string[];
28
+ /** Tracks the MCP session's active repo across tool calls.
29
+ *
30
+ * Resolution precedence: `select_repo` (session-only; sticky for the rest of
31
+ * the connection) > REPOSKEIN_REPO_PATH > walk-up > walk-down. `select_repo`
32
+ * is deliberately allowed to override REPOSKEIN_REPO_PATH once called — it's
33
+ * the more specific, more recent signal, and it's how a workspace-mode
34
+ * session (multiple sibling repos, walk-down ambiguous) picks one to work
35
+ * with instead of restarting the server with a different env var. */
36
+ export declare class RepoSession {
37
+ private readonly cwd;
38
+ private readonly envRepoPath;
39
+ private selectedPath;
40
+ constructor(opts: {
41
+ cwd: string;
42
+ envRepoPath: string | undefined;
43
+ });
44
+ /** Current resolution, honoring an active `select_repo` pick first. */
45
+ resolve(): RepoResolution;
46
+ /** Every candidate repo for this session — see `discoverRepoPaths`. Each
47
+ * entry is flagged `selected` for whichever one `resolve()` currently
48
+ * returns, so an agent can see the effect of a prior `select_repo` call. */
49
+ list(): (RepoInfo & {
50
+ selected: boolean;
51
+ })[];
52
+ /** Sets the session-active repo by path, by its meta.json `repo_id`, or by
53
+ * display `name` (as returned by `list()`/`list_repos`) — never an
54
+ * arbitrary filesystem path, so this can't be used to point outside what
55
+ * resolution actually discovered. */
56
+ select(pathOrName: string): {
57
+ ok: true;
58
+ repo: RepoInfo;
59
+ } | {
60
+ ok: false;
61
+ error: string;
62
+ };
63
+ }
@@ -0,0 +1,123 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { basename, join } from "node:path";
3
+ import { resolveRepoPath, walkUp, walkDown } from "./resolveRepoPath.js";
4
+ function countLines(text) {
5
+ let n = 0;
6
+ for (const line of text.split("\n"))
7
+ if (line.trim())
8
+ n++;
9
+ return n;
10
+ }
11
+ function readMetaRepoId(path) {
12
+ try {
13
+ const meta = JSON.parse(readFileSync(join(path, ".reposkein", "meta.json"), "utf8"));
14
+ return typeof meta.repo_id === "string" ? meta.repo_id : undefined;
15
+ }
16
+ catch {
17
+ return undefined;
18
+ }
19
+ }
20
+ /** Line counts for nodes.jsonl / edges.jsonl if they exist — the same cheap
21
+ * "count non-empty lines" approach `cli/doctor.ts` uses, not a full parse. */
22
+ function cheapCounts(path) {
23
+ const out = {};
24
+ const nodesFile = join(path, ".reposkein", "nodes.jsonl");
25
+ const edgesFile = join(path, ".reposkein", "edges.jsonl");
26
+ try {
27
+ if (existsSync(nodesFile))
28
+ out.nodes = countLines(readFileSync(nodesFile, "utf8"));
29
+ }
30
+ catch {
31
+ /* unreadable — omit rather than fail list_repos over one repo */
32
+ }
33
+ try {
34
+ if (existsSync(edgesFile))
35
+ out.edges = countLines(readFileSync(edgesFile, "utf8"));
36
+ }
37
+ catch {
38
+ /* unreadable — omit */
39
+ }
40
+ return out;
41
+ }
42
+ export function describeRepo(path) {
43
+ const repo_id = readMetaRepoId(path);
44
+ return {
45
+ path,
46
+ ...(repo_id ? { repo_id } : {}),
47
+ name: repo_id ?? basename(path),
48
+ ...cheapCounts(path),
49
+ };
50
+ }
51
+ /** Every repo `list_repos` should report. Deliberately broader than
52
+ * `resolveRepoPath`'s own short-circuiting precedence: discovery always
53
+ * walks the filesystem (nearest ancestor with `.reposkein/`, else
54
+ * subdirectories) so a workspace's sibling repos are visible — and thus
55
+ * selectable via `select_repo` — even in a session where REPOSKEIN_REPO_PATH
56
+ * happens to pin one of them. That env pin is unioned in (deduped) so it's
57
+ * never missing from the list, but it does not suppress the others; only
58
+ * `resolveRepoPath`'s actual *default* pick (used by `resolve()` below)
59
+ * gives it priority over the walk. Sorted for deterministic output. */
60
+ export function discoverRepoPaths(opts) {
61
+ const up = walkUp(opts.cwd);
62
+ const physical = up ? [up] : walkDown(opts.cwd);
63
+ if (opts.envRepoPath && !physical.includes(opts.envRepoPath)) {
64
+ return [...physical, opts.envRepoPath].sort();
65
+ }
66
+ return physical;
67
+ }
68
+ /** Tracks the MCP session's active repo across tool calls.
69
+ *
70
+ * Resolution precedence: `select_repo` (session-only; sticky for the rest of
71
+ * the connection) > REPOSKEIN_REPO_PATH > walk-up > walk-down. `select_repo`
72
+ * is deliberately allowed to override REPOSKEIN_REPO_PATH once called — it's
73
+ * the more specific, more recent signal, and it's how a workspace-mode
74
+ * session (multiple sibling repos, walk-down ambiguous) picks one to work
75
+ * with instead of restarting the server with a different env var. */
76
+ export class RepoSession {
77
+ cwd;
78
+ envRepoPath;
79
+ selectedPath;
80
+ constructor(opts) {
81
+ this.cwd = opts.cwd;
82
+ this.envRepoPath = opts.envRepoPath;
83
+ }
84
+ /** Current resolution, honoring an active `select_repo` pick first. */
85
+ resolve() {
86
+ if (this.selectedPath)
87
+ return { repoPath: this.selectedPath, source: "explicit" };
88
+ return resolveRepoPath({ cwd: this.cwd, envRepoPath: this.envRepoPath });
89
+ }
90
+ /** Every candidate repo for this session — see `discoverRepoPaths`. Each
91
+ * entry is flagged `selected` for whichever one `resolve()` currently
92
+ * returns, so an agent can see the effect of a prior `select_repo` call. */
93
+ list() {
94
+ const active = this.resolve().repoPath;
95
+ return discoverRepoPaths({ cwd: this.cwd, envRepoPath: this.envRepoPath }).map((path) => ({
96
+ ...describeRepo(path),
97
+ selected: path === active,
98
+ }));
99
+ }
100
+ /** Sets the session-active repo by path, by its meta.json `repo_id`, or by
101
+ * display `name` (as returned by `list()`/`list_repos`) — never an
102
+ * arbitrary filesystem path, so this can't be used to point outside what
103
+ * resolution actually discovered. */
104
+ select(pathOrName) {
105
+ const candidates = discoverRepoPaths({ cwd: this.cwd, envRepoPath: this.envRepoPath }).map(describeRepo);
106
+ const hit = candidates.find((c) => c.path === pathOrName) ??
107
+ candidates.find((c) => c.repo_id === pathOrName) ??
108
+ candidates.find((c) => c.name === pathOrName);
109
+ if (!hit) {
110
+ return {
111
+ ok: false,
112
+ error: `No repo matching "${pathOrName}" among the discovered candidates` +
113
+ (candidates.length > 0
114
+ ? `: ${candidates.map((c) => c.path).join(", ")}.`
115
+ : " (none found).") +
116
+ " Call list_repos first and pass one of its `path` or `name` values.",
117
+ };
118
+ }
119
+ this.selectedPath = hit.path;
120
+ return { ok: true, repo: hit };
121
+ }
122
+ }
123
+ //# sourceMappingURL=repoSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repoSession.js","sourceRoot":"","sources":["../../src/store/repoSession.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ export type RepoResolutionSource = "explicit" | "env" | "walk-up" | "walk-down" | "none";
2
+ export interface RepoResolution {
3
+ /** Resolved repo root, or undefined if none could be determined. */
4
+ repoPath: string | undefined;
5
+ /** How repoPath was determined ("none" when nothing resolved). */
6
+ source: RepoResolutionSource;
7
+ /** Populated only when source is "none" because walk-down found 2+ hits
8
+ * (workspace mode, ambiguous) — name them so the caller can pick one. */
9
+ candidates?: string[];
10
+ }
11
+ /** Nearest ancestor of `cwd` (inclusive) containing `.reposkein/`. */
12
+ export declare function walkUp(cwd: string): string | undefined;
13
+ /** Scans descendants of `cwd` (bounded to `maxDepth` levels, skipping
14
+ * build/VCS/tool directories) for directories containing `.reposkein/`.
15
+ * Does not recurse further into a hit — nested repos are a graph-federation
16
+ * concern (see store/federation.ts), not a workspace-candidate one here.
17
+ * Returns hits sorted for deterministic ambiguity-error output. */
18
+ export declare function walkDown(cwd: string, maxDepth?: number): string[];
19
+ /** Zero-config repo resolution.
20
+ *
21
+ * Precedence: explicit tool arg > REPOSKEIN_REPO_PATH > walk-up > walk-down.
22
+ * - Walk-up: nearest ancestor of `cwd` (inclusive) containing `.reposkein/`.
23
+ * - Walk-down (workspace mode, only tried when no ancestor has one): scans
24
+ * `cwd`'s children/grandchildren for `.reposkein/` dirs. One hit auto-
25
+ * selects it. Zero or 2+ hits leave `repoPath` undefined ("none"); 2+
26
+ * populates `candidates` so the caller can build an actionable error. */
27
+ export declare function resolveRepoPath(opts: {
28
+ cwd: string;
29
+ envRepoPath?: string;
30
+ explicit?: string;
31
+ }): RepoResolution;
@@ -0,0 +1,85 @@
1
+ import { readdirSync, statSync } from "node:fs";
2
+ import { dirname, join, resolve as resolvePath } from "node:path";
3
+ const REPOSKEIN_DIR = ".reposkein";
4
+ /** Directories never treated as repo candidates while walking down: build
5
+ * output, VCS internals, other worktrees/tool state — never real repo roots. */
6
+ const SKIP_DIR_NAMES = new Set(["node_modules", ".git", "target", "dist", ".worktrees", ".claude"]);
7
+ function hasReposkeinDir(dir) {
8
+ try {
9
+ return statSync(join(dir, REPOSKEIN_DIR)).isDirectory();
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ /** Nearest ancestor of `cwd` (inclusive) containing `.reposkein/`. */
16
+ export function walkUp(cwd) {
17
+ let dir = resolvePath(cwd);
18
+ for (;;) {
19
+ if (hasReposkeinDir(dir))
20
+ return dir;
21
+ const parent = dirname(dir);
22
+ if (parent === dir)
23
+ return undefined; // reached filesystem root
24
+ dir = parent;
25
+ }
26
+ }
27
+ /** Scans descendants of `cwd` (bounded to `maxDepth` levels, skipping
28
+ * build/VCS/tool directories) for directories containing `.reposkein/`.
29
+ * Does not recurse further into a hit — nested repos are a graph-federation
30
+ * concern (see store/federation.ts), not a workspace-candidate one here.
31
+ * Returns hits sorted for deterministic ambiguity-error output. */
32
+ export function walkDown(cwd, maxDepth = 2) {
33
+ const root = resolvePath(cwd);
34
+ const hits = [];
35
+ function recurse(dir, depth) {
36
+ let entries;
37
+ try {
38
+ entries = readdirSync(dir, { withFileTypes: true });
39
+ }
40
+ catch {
41
+ return; // unreadable dir (permissions, race) — skip, don't fail resolution
42
+ }
43
+ for (const entry of entries) {
44
+ if (!entry.isDirectory())
45
+ continue;
46
+ if (entry.name === REPOSKEIN_DIR)
47
+ continue;
48
+ if (SKIP_DIR_NAMES.has(entry.name))
49
+ continue;
50
+ const full = join(dir, entry.name);
51
+ if (hasReposkeinDir(full)) {
52
+ hits.push(full);
53
+ continue;
54
+ }
55
+ if (depth < maxDepth)
56
+ recurse(full, depth + 1);
57
+ }
58
+ }
59
+ recurse(root, 1);
60
+ return hits.sort();
61
+ }
62
+ /** Zero-config repo resolution.
63
+ *
64
+ * Precedence: explicit tool arg > REPOSKEIN_REPO_PATH > walk-up > walk-down.
65
+ * - Walk-up: nearest ancestor of `cwd` (inclusive) containing `.reposkein/`.
66
+ * - Walk-down (workspace mode, only tried when no ancestor has one): scans
67
+ * `cwd`'s children/grandchildren for `.reposkein/` dirs. One hit auto-
68
+ * selects it. Zero or 2+ hits leave `repoPath` undefined ("none"); 2+
69
+ * populates `candidates` so the caller can build an actionable error. */
70
+ export function resolveRepoPath(opts) {
71
+ if (opts.explicit)
72
+ return { repoPath: opts.explicit, source: "explicit" };
73
+ if (opts.envRepoPath)
74
+ return { repoPath: opts.envRepoPath, source: "env" };
75
+ const up = walkUp(opts.cwd);
76
+ if (up)
77
+ return { repoPath: up, source: "walk-up" };
78
+ const down = walkDown(opts.cwd);
79
+ if (down.length === 1)
80
+ return { repoPath: down[0], source: "walk-down" };
81
+ if (down.length > 1)
82
+ return { repoPath: undefined, source: "none", candidates: down };
83
+ return { repoPath: undefined, source: "none" };
84
+ }
85
+ //# sourceMappingURL=resolveRepoPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveRepoPath.js","sourceRoot":"","sources":["../../src/store/resolveRepoPath.ts"],"names":[],"mappings":"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"}