@reposkein/mcp 0.1.1 → 0.1.2

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 (52) hide show
  1. package/README.md +56 -0
  2. package/dist/SKILL.md +31 -0
  3. package/dist/embed/cache.d.ts +51 -0
  4. package/dist/embed/cache.js +163 -0
  5. package/dist/embed/cache.js.map +1 -0
  6. package/dist/embed/hybrid.d.ts +43 -0
  7. package/dist/embed/hybrid.js +106 -0
  8. package/dist/embed/hybrid.js.map +1 -0
  9. package/dist/embed/provider.d.ts +34 -0
  10. package/dist/embed/provider.js +32 -0
  11. package/dist/embed/provider.js.map +1 -0
  12. package/dist/embed/providers/http.d.ts +35 -0
  13. package/dist/embed/providers/http.js +93 -0
  14. package/dist/embed/providers/http.js.map +1 -0
  15. package/dist/embed/providers/voyage.d.ts +32 -0
  16. package/dist/embed/providers/voyage.js +93 -0
  17. package/dist/embed/providers/voyage.js.map +1 -0
  18. package/dist/index.js +48 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/profile/impact.d.ts +43 -0
  21. package/dist/profile/impact.js +112 -0
  22. package/dist/profile/impact.js.map +1 -0
  23. package/dist/search/bm25f.d.ts +31 -0
  24. package/dist/search/bm25f.js +151 -0
  25. package/dist/search/bm25f.js.map +1 -0
  26. package/dist/store/GraphStore.d.ts +14 -0
  27. package/dist/store/GraphStore.js.map +1 -1
  28. package/dist/store/JsonlGraphStore.d.ts +2 -1
  29. package/dist/store/JsonlGraphStore.js +25 -0
  30. package/dist/store/JsonlGraphStore.js.map +1 -1
  31. package/dist/store/Neo4jGraphStore.d.ts +2 -1
  32. package/dist/store/Neo4jGraphStore.js +18 -0
  33. package/dist/store/Neo4jGraphStore.js.map +1 -1
  34. package/dist/store/UnconfiguredStore.d.ts +2 -1
  35. package/dist/store/UnconfiguredStore.js +3 -0
  36. package/dist/store/UnconfiguredStore.js.map +1 -1
  37. package/dist/temporal/gitlog.d.ts +65 -0
  38. package/dist/temporal/gitlog.js +254 -0
  39. package/dist/temporal/gitlog.js.map +1 -0
  40. package/dist/temporal/temporal.d.ts +22 -0
  41. package/dist/temporal/temporal.js +185 -0
  42. package/dist/temporal/temporal.js.map +1 -0
  43. package/dist/tools/impact.d.ts +11 -0
  44. package/dist/tools/impact.js +63 -0
  45. package/dist/tools/impact.js.map +1 -0
  46. package/dist/tools/semanticFind.d.ts +37 -0
  47. package/dist/tools/semanticFind.js +155 -0
  48. package/dist/tools/semanticFind.js.map +1 -0
  49. package/dist/tools/temporalContext.d.ts +12 -0
  50. package/dist/tools/temporalContext.js +55 -0
  51. package/dist/tools/temporalContext.js.map +1 -0
  52. package/package.json +1 -1
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Generic HTTP/local EmbeddingProvider implementation.
3
+ *
4
+ * POSTs to REPOSKEIN_EMBED_URL using an OpenAI-compatible request/response shape.
5
+ * This covers any locally-hosted embedding server, including:
6
+ * - voyage-4-nano (open-weight, HuggingFace: huggingface.co/voyageai/voyage-4-nano)
7
+ * when run via a local HTTP server (e.g. text-embeddings-inference, FastEmbed, etc.)
8
+ * - Any sentence-transformers / HuggingFace model via local server
9
+ * - Ollama embeddings endpoint
10
+ *
11
+ * Request body (OpenAI-compatible):
12
+ * { input: string[], model: string, input_type: "document"|"query" }
13
+ * Response body (OpenAI-compatible):
14
+ * { data: [{ embedding: number[] }, ...] }
15
+ * OR Voyage-style: { embeddings: number[][] }
16
+ * (tries .data[].embedding first, then .embeddings)
17
+ *
18
+ * Config env vars:
19
+ * REPOSKEIN_EMBED_PROVIDER=http
20
+ * REPOSKEIN_EMBED_URL (required; e.g. http://127.0.0.1:8080/v1/embeddings)
21
+ * REPOSKEIN_EMBED_MODEL (required; e.g. "voyage-4-nano")
22
+ * REPOSKEIN_EMBED_DIMS (required; output dimension of the local model)
23
+ */
24
+ const DEFAULT_DIMS = 1024;
25
+ export class HttpEmbeddingProvider {
26
+ _id = "http";
27
+ _url;
28
+ _modelId;
29
+ _dims;
30
+ constructor(env = process.env) {
31
+ const url = env["REPOSKEIN_EMBED_URL"];
32
+ if (!url) {
33
+ throw new Error("REPOSKEIN_EMBED_URL is required for REPOSKEIN_EMBED_PROVIDER=http");
34
+ }
35
+ const model = env["REPOSKEIN_EMBED_MODEL"];
36
+ if (!model) {
37
+ throw new Error("REPOSKEIN_EMBED_MODEL is required for REPOSKEIN_EMBED_PROVIDER=http");
38
+ }
39
+ this._url = url;
40
+ this._modelId = model;
41
+ const rawDims = env["REPOSKEIN_EMBED_DIMS"];
42
+ if (rawDims !== undefined) {
43
+ const d = Number(rawDims);
44
+ if (!Number.isInteger(d) || d <= 0) {
45
+ throw new Error(`Invalid REPOSKEIN_EMBED_DIMS="${rawDims}" — must be a positive integer (e.g. 256, 512, 1024, 2048)`);
46
+ }
47
+ this._dims = d;
48
+ }
49
+ else {
50
+ this._dims = DEFAULT_DIMS;
51
+ }
52
+ }
53
+ id() { return this._id; }
54
+ modelId() { return this._modelId; }
55
+ dims() { return this._dims; }
56
+ async embed(texts, kind) {
57
+ if (texts.length === 0)
58
+ return [];
59
+ const body = {
60
+ input: texts,
61
+ model: this._modelId,
62
+ input_type: kind,
63
+ };
64
+ const res = await fetch(this._url, {
65
+ method: "POST",
66
+ headers: { "Content-Type": "application/json" },
67
+ body: JSON.stringify(body),
68
+ });
69
+ if (!res.ok) {
70
+ const text = await res.text().catch(() => "(no body)");
71
+ throw new Error(`HTTP embedding server error ${res.status}: ${text}`);
72
+ }
73
+ const json = (await res.json());
74
+ // OpenAI-compatible shape: { data: [{ embedding: [...] }, ...] }
75
+ if ("data" in json && Array.isArray(json.data)) {
76
+ const out = json.data.map((d) => d.embedding);
77
+ if (out.length !== texts.length) {
78
+ throw new Error(`HTTP embedding server returned ${out.length} embeddings for ${texts.length} input texts — count mismatch`);
79
+ }
80
+ return out;
81
+ }
82
+ // Voyage-style shape: { embeddings: [[...], ...] }
83
+ if ("embeddings" in json && Array.isArray(json.embeddings)) {
84
+ const out = json.embeddings;
85
+ if (out.length !== texts.length) {
86
+ throw new Error(`HTTP embedding server returned ${out.length} embeddings for ${texts.length} input texts — count mismatch`);
87
+ }
88
+ return out;
89
+ }
90
+ throw new Error(`Unrecognized embedding server response shape: ${JSON.stringify(json)}`);
91
+ }
92
+ }
93
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/embed/providers/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Voyage AI EmbeddingProvider implementation.
3
+ *
4
+ * Endpoint: POST https://api.voyageai.com/v1/embeddings
5
+ * Response shape: { embeddings: number[][], total_tokens: number }
6
+ * (NOTE: response field is "embeddings" not "data[].embedding" — confirmed from Voyage docs)
7
+ *
8
+ * Models:
9
+ * - voyage-code-3: code-specialized, 1024 dims default (Matryoshka 256/512/1024/2048),
10
+ * 32K token context, 120K tokens/request batch limit.
11
+ * - voyage-4-nano: open-weight on HuggingFace (huggingface.co/voyageai/voyage-4-nano),
12
+ * 1024 dims default, 32K context. Covered by the `http` provider when run locally
13
+ * via any OpenAI-compatible embedding server.
14
+ *
15
+ * Config env vars:
16
+ * REPOSKEIN_EMBED_PROVIDER=voyage
17
+ * REPOSKEIN_EMBED_MODEL (default: voyage-code-3)
18
+ * REPOSKEIN_EMBED_DIMS (optional; 256|512|1024|2048; default: 1024)
19
+ * VOYAGE_API_KEY (required)
20
+ */
21
+ import type { EmbeddingProvider, EmbedKind } from "../provider.js";
22
+ export declare class VoyageEmbeddingProvider implements EmbeddingProvider {
23
+ private readonly _id;
24
+ private readonly _modelId;
25
+ private readonly _dims;
26
+ private readonly _apiKey;
27
+ constructor(env?: NodeJS.ProcessEnv);
28
+ id(): string;
29
+ modelId(): string;
30
+ dims(): number;
31
+ embed(texts: string[], kind: EmbedKind): Promise<number[][]>;
32
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Voyage AI EmbeddingProvider implementation.
3
+ *
4
+ * Endpoint: POST https://api.voyageai.com/v1/embeddings
5
+ * Response shape: { embeddings: number[][], total_tokens: number }
6
+ * (NOTE: response field is "embeddings" not "data[].embedding" — confirmed from Voyage docs)
7
+ *
8
+ * Models:
9
+ * - voyage-code-3: code-specialized, 1024 dims default (Matryoshka 256/512/1024/2048),
10
+ * 32K token context, 120K tokens/request batch limit.
11
+ * - voyage-4-nano: open-weight on HuggingFace (huggingface.co/voyageai/voyage-4-nano),
12
+ * 1024 dims default, 32K context. Covered by the `http` provider when run locally
13
+ * via any OpenAI-compatible embedding server.
14
+ *
15
+ * Config env vars:
16
+ * REPOSKEIN_EMBED_PROVIDER=voyage
17
+ * REPOSKEIN_EMBED_MODEL (default: voyage-code-3)
18
+ * REPOSKEIN_EMBED_DIMS (optional; 256|512|1024|2048; default: 1024)
19
+ * VOYAGE_API_KEY (required)
20
+ */
21
+ const VOYAGE_ENDPOINT = "https://api.voyageai.com/v1/embeddings";
22
+ const DEFAULT_MODEL = "voyage-code-3";
23
+ const DEFAULT_DIMS = 1024;
24
+ /** Max texts per request (Voyage API limit). */
25
+ const BATCH_SIZE = 1000;
26
+ export class VoyageEmbeddingProvider {
27
+ _id = "voyage";
28
+ _modelId;
29
+ _dims;
30
+ _apiKey;
31
+ constructor(env = process.env) {
32
+ const apiKey = env["VOYAGE_API_KEY"];
33
+ if (!apiKey) {
34
+ throw new Error("VOYAGE_API_KEY is required for REPOSKEIN_EMBED_PROVIDER=voyage");
35
+ }
36
+ this._apiKey = apiKey;
37
+ this._modelId = env["REPOSKEIN_EMBED_MODEL"] ?? DEFAULT_MODEL;
38
+ const rawDims = env["REPOSKEIN_EMBED_DIMS"];
39
+ if (rawDims !== undefined) {
40
+ const d = Number(rawDims);
41
+ if (!Number.isInteger(d) || d <= 0) {
42
+ throw new Error(`Invalid REPOSKEIN_EMBED_DIMS="${rawDims}" — must be a positive integer (e.g. 256, 512, 1024, 2048)`);
43
+ }
44
+ this._dims = d;
45
+ }
46
+ else {
47
+ this._dims = DEFAULT_DIMS;
48
+ }
49
+ }
50
+ id() { return this._id; }
51
+ modelId() { return this._modelId; }
52
+ dims() { return this._dims; }
53
+ async embed(texts, kind) {
54
+ if (texts.length === 0)
55
+ return [];
56
+ const results = [];
57
+ // Batch up to BATCH_SIZE texts per request
58
+ for (let i = 0; i < texts.length; i += BATCH_SIZE) {
59
+ const batch = texts.slice(i, i + BATCH_SIZE);
60
+ const body = {
61
+ input: batch,
62
+ model: this._modelId,
63
+ input_type: kind,
64
+ output_dimension: this._dims,
65
+ };
66
+ const res = await fetch(VOYAGE_ENDPOINT, {
67
+ method: "POST",
68
+ headers: {
69
+ "Content-Type": "application/json",
70
+ "Authorization": `Bearer ${this._apiKey}`,
71
+ },
72
+ body: JSON.stringify(body),
73
+ });
74
+ if (!res.ok) {
75
+ const text = await res.text().catch(() => "(no body)");
76
+ throw new Error(`Voyage API error ${res.status}: ${text}`);
77
+ }
78
+ const json = (await res.json());
79
+ if (!Array.isArray(json.embeddings)) {
80
+ throw new Error(`Voyage API response missing embeddings array: ${JSON.stringify(json)}`);
81
+ }
82
+ if (json.embeddings.length !== batch.length) {
83
+ throw new Error(`Voyage API returned ${json.embeddings.length} embeddings for batch of ${batch.length} texts — batch count mismatch`);
84
+ }
85
+ results.push(...json.embeddings);
86
+ }
87
+ if (results.length !== texts.length) {
88
+ throw new Error(`Voyage API returned ${results.length} total embeddings for ${texts.length} input texts — total count mismatch`);
89
+ }
90
+ return results;
91
+ }
92
+ }
93
+ //# sourceMappingURL=voyage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voyage.js","sourceRoot":"","sources":["../../../src/embed/providers/voyage.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -13,6 +13,9 @@ import { makeReadCypher } from "./tools/readCypher.js";
13
13
  import { makeGetContextProfile } from "./tools/getContextProfile.js";
14
14
  import { makeWriteSemanticSummary } from "./tools/writeSemanticSummary.js";
15
15
  import { makeInitCpgSkeleton, makeReindexFile } from "./tools/indexerTools.js";
16
+ import { makeSemanticFind } from "./tools/semanticFind.js";
17
+ import { makeTemporalContext } from "./tools/temporalContext.js";
18
+ import { makeImpact } from "./tools/impact.js";
16
19
  import { resolveRepoId } from "./store/repoId.js";
17
20
  /** Selects the store backend.
18
21
  * REPOSKEIN_STORE = "jsonl" | "neo4j" | "auto" (default "auto").
@@ -118,6 +121,51 @@ export async function main() {
118
121
  }
119
122
  return reindexFile(args);
120
123
  });
124
+ const semanticFind = repoId ? makeSemanticFind(store, repoId, repoPath ?? ".") : null;
125
+ server.registerTool("semantic_find", {
126
+ title: "Find code by meaning",
127
+ description: "Rank functions/classes by a lexical match over their qualified names, signatures, and agent-written summaries — the entry point to seed get_context_profile when you don't know where to start. Returns ranked node_ids. federated:true spans nested repos.",
128
+ inputSchema: {
129
+ query: z.string(),
130
+ limit: z.number().int().min(1).max(25).optional(),
131
+ kind: z.enum(["Function", "Class", "Interface", "Enum"]).optional(),
132
+ federated: z.boolean().optional(),
133
+ },
134
+ }, async (args) => {
135
+ if (!semanticFind) {
136
+ return { content: [{ type: "text", text: REPO_REQUIRED_MSG }], isError: true };
137
+ }
138
+ return semanticFind(args);
139
+ });
140
+ // get_temporal_context is gated on repoPath (not the store — it reads from .git directly).
141
+ const temporalContext = repoPath ? makeTemporalContext(repoPath) : null;
142
+ server.registerTool("get_temporal_context", {
143
+ title: "Git temporal context",
144
+ description: "Git-derived signals for a file: how often/recently it changes, who owns it, and which files most often change together with it (co-change) — answers \"what else should I touch?\". Advisory (derived from git history, not the committed graph). Before a cross-cutting change, use this to find files that historically change together.",
145
+ inputSchema: { path: z.string() },
146
+ }, async (args) => {
147
+ if (!temporalContext) {
148
+ return { content: [{ type: "text", text: REPO_REQUIRED_MSG }], isError: true };
149
+ }
150
+ return temporalContext(args);
151
+ });
152
+ const impact = repoId ? makeImpact(store, repoId) : null;
153
+ server.registerTool("impact", {
154
+ title: "Change impact + covering tests",
155
+ description: "Given a function/class, return its transitive callers (what could break if you change it) split into impacted code vs the tests that cover it (what to run). Resolves by node_id, file_path+name, or name. federated:true spans nested repos.",
156
+ inputSchema: {
157
+ node_id: z.string().optional(),
158
+ file_path: z.string().optional(),
159
+ name: z.string().optional(),
160
+ depth: z.number().int().min(1).max(5).optional(),
161
+ federated: z.boolean().optional(),
162
+ },
163
+ }, async (args) => {
164
+ if (!impact) {
165
+ return { content: [{ type: "text", text: REPO_REQUIRED_MSG }], isError: true };
166
+ }
167
+ return impact(args);
168
+ });
121
169
  if (!repoId) {
122
170
  console.error("[reposkein-mcp] REPOSKEIN_REPO_PATH not set; repo-scoped tools will return an error until it is configured");
123
171
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEjE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD;;;;;uDAKuD;AACvD,SAAS,UAAU,CAAC,QAA4B,EAAE,MAA0B;IAC1E,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IACnE,MAAM,UAAU,GACd,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC;IAEpF,MAAM,KAAK,GAAG,GAAe,EAAE;QAC7B,IAAI,CAAC;YACH,OAAO,eAAe,CAAC,OAAO,EAAE,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,iBAAiB,EAAE,CAAC;QACjC,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,QAAS,EAAE,MAAO,CAAC,CAAC,CAAC,CAAC,IAAI,iBAAiB,EAAE,CAAC;IACxF,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,KAAK,EAAE,CAAC;IACjB,CAAC;IACD,OAAO;IACP,IAAI,UAAU;QAAE,OAAO,IAAI,eAAe,CAAC,QAAS,EAAE,MAAO,CAAC,CAAC;IAC/D,OAAO,KAAK,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,iBAAiB,GACrB,2EAA2E;IAC3E,8EAA8E,CAAC;AAEjF,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IACjD,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACtE,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3E,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAEjD,MAAM,CAAC,YAAY,CACjB,aAAa,EACb;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EACT,qQAAqQ;QACvQ,WAAW,EAAE;YACX,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;YACjB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;YACpD,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;SAClC;KACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CACjC,CAAC;IAEF,2EAA2E;IAC3E,sEAAsE;IACtE,MAAM,iBAAiB,GAAG,MAAM,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/E,MAAM,CAAC,YAAY,CACjB,qBAAqB,EACrB;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EACT,mSAAmS;QACrS,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC3B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;YACtD,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;SAClC;KACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACjF,CAAC;QACD,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC,CACF,CAAC;IAEF,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,wBAAwB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7E,MAAM,CAAC,YAAY,CACjB,wBAAwB,EACxB;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EACT,sMAAsM;QACxM,WAAW,EAAE;YACX,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;YACnB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;YACnB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAC7B;KACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACjF,CAAC;QACD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CACF,CAAC;IAEF,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjE,MAAM,CAAC,YAAY,CACjB,mBAAmB,EACnB;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EACT,uJAAuJ;QACzJ,WAAW,EAAE;YACX,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC3B,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;SAC7B;KACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACjF,CAAC;QACD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CACF,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5D,MAAM,CAAC,YAAY,CACjB,cAAc,EACd;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EACT,4FAA4F;QAC9F,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;KAClC,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACjF,CAAC;QACD,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC,CACF,CAAC;IAEF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CACX,4GAA4G,CAC7G,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,+DAA+D;AAC/D,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;aAC5B,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aAClC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,CAAC;SAAM,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,GAAG,CAAC;QAC5F,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;aAClB,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aAClC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,CAAC;SAAM,CAAC;QACN,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { GraphStore } from "../store/GraphStore.js";
2
+ /**
3
+ * Mirrors the Rust indexer's `role_for` test classification (classify.rs).
4
+ * A file is a test file if:
5
+ * - any lowercased path segment equals "test" or "tests", or ends with ".tests"
6
+ * - the lowercased basename starts with "test_"
7
+ * - the basename contains "_test.", ".test.", ".spec.", or ".tests."
8
+ * - the original (case-preserving) basename ends with "Test.<ext>", "Tests.<ext>"
9
+ *
10
+ * "contest_results.py" → false (basename "contest_results.py" doesn't start with "test_").
11
+ */
12
+ export declare function isTestPath(filePath: string): boolean;
13
+ export interface ImpactRow {
14
+ node_id: string;
15
+ qualified_name: string;
16
+ file_path: string;
17
+ depth: number;
18
+ is_test: boolean;
19
+ }
20
+ export interface ImpactResult {
21
+ target: {
22
+ node_id: string;
23
+ qualified_name: string;
24
+ file_path: string;
25
+ };
26
+ depth: number;
27
+ impacted: ImpactRow[];
28
+ covering_tests: ImpactRow[];
29
+ counts: {
30
+ impacted: number;
31
+ covering_tests: number;
32
+ truncated: boolean;
33
+ };
34
+ }
35
+ /**
36
+ * BFS over callers to bounded depth with a maxNodes cap.
37
+ * NeighborRow does not carry file_path, so we fetch it via store.getNode().
38
+ * Deterministic ordering: depth asc, then node_id asc.
39
+ */
40
+ export declare function computeImpact(store: GraphStore, repoIds: string[], targetId: string, targetQN: string, targetFile: string, opts: {
41
+ depth: number;
42
+ maxNodes: number;
43
+ }): Promise<ImpactResult>;
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Mirrors the Rust indexer's `role_for` test classification (classify.rs).
3
+ * A file is a test file if:
4
+ * - any lowercased path segment equals "test" or "tests", or ends with ".tests"
5
+ * - the lowercased basename starts with "test_"
6
+ * - the basename contains "_test.", ".test.", ".spec.", or ".tests."
7
+ * - the original (case-preserving) basename ends with "Test.<ext>", "Tests.<ext>"
8
+ *
9
+ * "contest_results.py" → false (basename "contest_results.py" doesn't start with "test_").
10
+ */
11
+ export function isTestPath(filePath) {
12
+ const p = filePath.toLowerCase();
13
+ const basename = p.includes("/") ? p.slice(p.lastIndexOf("/") + 1) : p;
14
+ const origBasename = filePath.includes("/")
15
+ ? filePath.slice(filePath.lastIndexOf("/") + 1)
16
+ : filePath;
17
+ // Any path segment == "test" | "tests", or ends with ".tests"
18
+ const inTestDir = p.split("/").some((seg) => seg === "test" || seg === "tests" || seg.endsWith(".tests"));
19
+ if (inTestDir)
20
+ return true;
21
+ // Basename test_ prefix
22
+ if (basename.startsWith("test_"))
23
+ return true;
24
+ // Basename contains _test., .test., .spec., .tests.
25
+ if (basename.includes("_test.") ||
26
+ basename.includes(".test.") ||
27
+ basename.includes(".spec.") ||
28
+ basename.includes(".tests.")) {
29
+ return true;
30
+ }
31
+ // Case-sensitive: original basename ends with Test.<ext> or Tests.<ext>
32
+ // e.g. FooTest.java, FooTests.java, FooTests.cs
33
+ // Match any extension: "Test." followed by word chars, or "Tests." followed by word chars
34
+ if (/Test\.\w+$/.test(origBasename) || /Tests\.\w+$/.test(origBasename)) {
35
+ return true;
36
+ }
37
+ return false;
38
+ }
39
+ /**
40
+ * BFS over callers to bounded depth with a maxNodes cap.
41
+ * NeighborRow does not carry file_path, so we fetch it via store.getNode().
42
+ * Deterministic ordering: depth asc, then node_id asc.
43
+ */
44
+ export async function computeImpact(store, repoIds, targetId, targetQN, targetFile, opts) {
45
+ const { depth: maxDepth, maxNodes } = opts;
46
+ // visited: node_id → { qualifiedName, filePath, depth }
47
+ const visited = new Map();
48
+ // frontier: array of node_ids at the current level
49
+ let frontier = [targetId];
50
+ // Mark the target as visited at depth 0 (excluded from output)
51
+ visited.set(targetId, { qualified_name: targetQN, file_path: targetFile, depth: 0 });
52
+ let truncated = false;
53
+ for (let currentDepth = 1; currentDepth <= maxDepth && frontier.length > 0; currentDepth++) {
54
+ const nextFrontier = [];
55
+ // Collect all callers for all frontier nodes at this depth
56
+ // Use a generous per-node limit; we dedupe globally via visited
57
+ const PER_NODE_LIMIT = Math.max(maxNodes, 1000);
58
+ for (const nodeId of frontier) {
59
+ const callerRows = await store.callers(repoIds, nodeId, PER_NODE_LIMIT);
60
+ for (const row of callerRows) {
61
+ if (visited.has(row.id))
62
+ continue;
63
+ // Fetch file_path via getNode (NeighborRow doesn't carry it)
64
+ const node = await store.getNode(repoIds, row.id);
65
+ const filePath = node?.file_path ?? "";
66
+ const qualifiedName = node?.qualified_name ?? row.name;
67
+ visited.set(row.id, { qualified_name: qualifiedName, file_path: filePath, depth: currentDepth });
68
+ nextFrontier.push(row.id);
69
+ // Check maxNodes cap (excluding the target at depth 0)
70
+ if (visited.size - 1 >= maxNodes) {
71
+ truncated = true;
72
+ break;
73
+ }
74
+ }
75
+ if (truncated)
76
+ break;
77
+ }
78
+ if (truncated)
79
+ break;
80
+ frontier = nextFrontier;
81
+ }
82
+ // Partition visited (excluding the target) into impacted vs covering_tests
83
+ const allRows = [];
84
+ for (const [nodeId, info] of visited) {
85
+ if (nodeId === targetId)
86
+ continue;
87
+ const isTest = isTestPath(info.file_path);
88
+ allRows.push({
89
+ node_id: nodeId,
90
+ qualified_name: info.qualified_name,
91
+ file_path: info.file_path,
92
+ depth: info.depth,
93
+ is_test: isTest,
94
+ });
95
+ }
96
+ // Deterministic ordering: depth asc, then node_id asc
97
+ allRows.sort((a, b) => a.depth - b.depth || a.node_id.localeCompare(b.node_id));
98
+ const impacted = allRows.filter((r) => !r.is_test);
99
+ const covering_tests = allRows.filter((r) => r.is_test);
100
+ return {
101
+ target: { node_id: targetId, qualified_name: targetQN, file_path: targetFile },
102
+ depth: maxDepth,
103
+ impacted,
104
+ covering_tests,
105
+ counts: {
106
+ impacted: impacted.length,
107
+ covering_tests: covering_tests.length,
108
+ truncated,
109
+ },
110
+ };
111
+ }
112
+ //# sourceMappingURL=impact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact.js","sourceRoot":"","sources":["../../src/profile/impact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Deterministic BM25F lexical scorer for semantic_find.
3
+ *
4
+ * Architecture (design §3):
5
+ * - Tokenize by splitting on non-alphanumeric boundaries AND camelCase/PascalCase.
6
+ * - ASCII-lowercase, drop length-1 tokens. No stemming/stopwords.
7
+ * - Per-field weights: { qualified_name:10, name:8, summary:4, signature:2, file_path:1 }
8
+ * - BM25F with k1=1.2, b=0.75, IDF computed over whole corpus.
9
+ * - Deterministic: fixed iteration order, scores rounded to 6 decimal places,
10
+ * ties broken by node_id ascending.
11
+ * - Pure function: no clock, no random, no I/O.
12
+ */
13
+ import type { CorpusNode } from "../store/GraphStore.js";
14
+ export interface Scored {
15
+ node: CorpusNode;
16
+ score: number;
17
+ matched: string[];
18
+ }
19
+ /**
20
+ * Tokenize a string by:
21
+ * 1. Split on non-alphanumeric characters.
22
+ * 2. Split camelCase / PascalCase runs (lower→upper boundary, acronym+word boundary).
23
+ * 3. ASCII-lowercase.
24
+ * 4. Drop tokens of length ≤ 1.
25
+ */
26
+ export declare function tokenize(s: string): string[];
27
+ /**
28
+ * Rank corpus nodes by BM25F for the given query, returning up to limit results.
29
+ * Deterministic: identical corpus + query → identical ranking.
30
+ */
31
+ export declare function rankCorpus(corpus: CorpusNode[], query: string, limit: number): Scored[];