devsmind-mcp 2.4.0 → 4.0.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/README.md +317 -234
- package/dist/cli/activity.d.ts +9 -0
- package/dist/cli/activity.js +69 -0
- package/dist/cli/activity.js.map +1 -0
- package/dist/cli/describe.d.ts +31 -0
- package/dist/cli/describe.js +201 -0
- package/dist/cli/describe.js.map +1 -0
- package/dist/cli/diff.d.ts +14 -0
- package/dist/cli/diff.js +161 -0
- package/dist/cli/diff.js.map +1 -0
- package/dist/cli/embed.d.ts +6 -0
- package/dist/cli/embed.js +109 -0
- package/dist/cli/embed.js.map +1 -0
- package/dist/cli/extract-agent.d.ts +66 -0
- package/dist/cli/extract-agent.js +192 -0
- package/dist/cli/extract-agent.js.map +1 -0
- package/dist/cli/feedback.d.ts +11 -0
- package/dist/cli/feedback.js +90 -0
- package/dist/cli/feedback.js.map +1 -0
- package/dist/cli/index.js +139 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts +30 -0
- package/dist/cli/init.js +89 -18
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/integrations/memory-topics.d.ts +55 -0
- package/dist/cli/integrations/memory-topics.js +318 -0
- package/dist/cli/integrations/memory-topics.js.map +1 -0
- package/dist/cli/integrations/memory.d.ts +17 -6
- package/dist/cli/integrations/memory.js +52 -139
- package/dist/cli/integrations/memory.js.map +1 -1
- package/dist/cli/integrations/prompt.d.ts +8 -0
- package/dist/cli/integrations/prompt.js +24 -3
- package/dist/cli/integrations/prompt.js.map +1 -1
- package/dist/cli/integrations/registry.d.ts +26 -9
- package/dist/cli/integrations/registry.js +61 -30
- package/dist/cli/integrations/registry.js.map +1 -1
- package/dist/cli/llm-client.d.ts +116 -0
- package/dist/cli/llm-client.js +322 -0
- package/dist/cli/llm-client.js.map +1 -0
- package/dist/cli/rule.d.ts +22 -2
- package/dist/cli/rule.js +110 -34
- package/dist/cli/rule.js.map +1 -1
- package/dist/cli/runner.d.ts +21 -0
- package/dist/cli/runner.js +94 -276
- package/dist/cli/runner.js.map +1 -1
- package/dist/cli/sync-progress.d.ts +9 -0
- package/dist/cli/sync-progress.js +41 -0
- package/dist/cli/sync-progress.js.map +1 -0
- package/dist/cli/sync.js +5 -2
- package/dist/cli/sync.js.map +1 -1
- package/dist/cli/view.js +3 -2
- package/dist/cli/view.js.map +1 -1
- package/dist/cli/workflow.js +26 -20
- package/dist/cli/workflow.js.map +1 -1
- package/dist/db/activity-graph.d.ts +55 -0
- package/dist/db/activity-graph.js +314 -0
- package/dist/db/activity-graph.js.map +1 -0
- package/dist/db/activity.d.ts +221 -0
- package/dist/db/activity.js +348 -0
- package/dist/db/activity.js.map +1 -0
- package/dist/db/analyze.js +18 -6
- package/dist/db/analyze.js.map +1 -1
- package/dist/db/database.d.ts +654 -102
- package/dist/db/database.js +1911 -558
- package/dist/db/database.js.map +1 -1
- package/dist/db/edges.d.ts +24 -0
- package/dist/db/edges.js +84 -0
- package/dist/db/edges.js.map +1 -1
- package/dist/db/embedder.d.ts +39 -0
- package/dist/db/embedder.js +0 -0
- package/dist/db/embedder.js.map +1 -0
- package/dist/db/feedback.d.ts +128 -0
- package/dist/db/feedback.js +182 -0
- package/dist/db/feedback.js.map +1 -0
- package/dist/db/file-diff.d.ts +32 -0
- package/dist/db/file-diff.js +110 -0
- package/dist/db/file-diff.js.map +1 -0
- package/dist/db/grep.d.ts +78 -0
- package/dist/db/grep.js +475 -0
- package/dist/db/grep.js.map +1 -0
- package/dist/db/index-build.d.ts +75 -0
- package/dist/db/index-build.js +177 -0
- package/dist/db/index-build.js.map +1 -0
- package/dist/db/message-revert.d.ts +63 -0
- package/dist/db/message-revert.js +258 -0
- package/dist/db/message-revert.js.map +1 -0
- package/dist/db/revert.d.ts +31 -0
- package/dist/db/revert.js +108 -0
- package/dist/db/revert.js.map +1 -0
- package/dist/db/schema.d.ts +49 -4
- package/dist/db/schema.js +125 -73
- package/dist/db/schema.js.map +1 -1
- package/dist/db/search-index.d.ts +65 -0
- package/dist/db/search-index.js +74 -0
- package/dist/db/search-index.js.map +1 -0
- package/dist/db/staging.d.ts +91 -5
- package/dist/db/staging.js +148 -22
- package/dist/db/staging.js.map +1 -1
- package/dist/mcp/server.d.ts +29 -7
- package/dist/mcp/server.js +2637 -878
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/vendor/3d-force-graph.min.js +5 -0
- package/dist/mcp/vendor/force-graph.min.js +5 -0
- package/dist/mcp/vendor/model/model_int8.onnx +0 -0
- package/dist/mcp/vendor/model/vocab.txt +30522 -0
- package/dist/mcp/vendor/three.min.js +7 -0
- package/dist/mcp/view.css +419 -0
- package/dist/mcp/view.html +161 -0
- package/dist/mcp/view.js +245 -0
- package/dist/mcp/view_chat.js +382 -0
- package/dist/mcp/view_graph.js +576 -0
- package/dist/mcp/visualizer.d.ts +25 -2
- package/dist/mcp/visualizer.js +31 -4
- package/dist/mcp/visualizer.js.map +1 -1
- package/dist/utils/ast.d.ts +89 -0
- package/dist/utils/ast.js +378 -10
- package/dist/utils/ast.js.map +1 -1
- package/dist/utils/diff.d.ts +44 -0
- package/dist/utils/diff.js +78 -0
- package/dist/utils/diff.js.map +1 -0
- package/dist/utils/edit.d.ts +6 -0
- package/dist/utils/edit.js +47 -14
- package/dist/utils/edit.js.map +1 -1
- package/dist/utils/scanner.d.ts +6 -4
- package/dist/utils/scanner.js +18 -8
- package/dist/utils/scanner.js.map +1 -1
- package/dist/utils/tokenize.d.ts +45 -0
- package/dist/utils/tokenize.js +129 -0
- package/dist/utils/tokenize.js.map +1 -0
- package/dist/utils/version.d.ts +14 -0
- package/dist/utils/version.js +61 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +18 -5
- package/dist/mcp/visualizer_2d.html +0 -635
- package/dist/mcp/visualizer_3d.html +0 -613
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local semantic embedding via a vendored `all-MiniLM-L6-v2` (int8 ONNX), loaded through the
|
|
3
|
+
* OPTIONAL `onnxruntime-node` dependency. Self-contained on purpose — no DB, no MCP — so it can
|
|
4
|
+
* be unit-tested against known WordPiece output and a semantic sanity check in isolation.
|
|
5
|
+
*
|
|
6
|
+
* `onnxruntime-node` is in `optionalDependencies`, not `dependencies`: an install can fail on an
|
|
7
|
+
* unsupported platform without breaking devsmind. Every entry point here degrades to returning
|
|
8
|
+
* null rather than throwing, so callers just fall back to BM25-only search.
|
|
9
|
+
*/
|
|
10
|
+
export declare const EMBEDDING_MODEL_ID = "minilm-l6-v2-int8-v1";
|
|
11
|
+
export declare const EMBEDDING_DIM = 384;
|
|
12
|
+
export interface TokenizedInput {
|
|
13
|
+
inputIds: number[];
|
|
14
|
+
attentionMask: number[];
|
|
15
|
+
}
|
|
16
|
+
/** Tokenizes one string into [CLS] ... [SEP], padded/truncated to `maxTokens`. Exported for unit tests. */
|
|
17
|
+
export declare function tokenize(text: string, maxTokens?: number): TokenizedInput | null;
|
|
18
|
+
/** True if onnxruntime-node loaded, the model file exists, and the vocab parsed. Cheap after first call. */
|
|
19
|
+
export declare function isEmbedderAvailable(): Promise<boolean>;
|
|
20
|
+
/** L2-normalized components are in [-1,1], so a fixed scale of 127 needs no per-vector factor. */
|
|
21
|
+
export declare function quantizeInt8(vec: Float32Array): Int8Array;
|
|
22
|
+
/** Cosine similarity between two int8-quantized vectors, approximated via integer dot product. */
|
|
23
|
+
export declare function cosineInt8(a: Int8Array, b: Int8Array): number;
|
|
24
|
+
/**
|
|
25
|
+
* Embeds a batch of texts in one ONNX call. Returns null (not a rejected promise) if the
|
|
26
|
+
* embedder is unavailable for any reason — missing dependency, missing model, load failure —
|
|
27
|
+
* so every caller's fallback path is the same "treat as absent" branch, not exception handling.
|
|
28
|
+
*/
|
|
29
|
+
export declare function embedBatch(texts: string[]): Promise<Float32Array[] | null>;
|
|
30
|
+
/**
|
|
31
|
+
* Fingerprint of the description a vector was computed from — a vector is stale the instant
|
|
32
|
+
* its description is edited, and this catches that precisely (unlike the BM25 index's coarse
|
|
33
|
+
* whole-corpus fingerprint). Not a security hash, just a fast staleness check.
|
|
34
|
+
*/
|
|
35
|
+
export declare function hashDescription(text: string): string;
|
|
36
|
+
/** Convenience wrapper: embed one text, quantized, or null if the embedder is unavailable. */
|
|
37
|
+
export declare function embedTextInt8(text: string): Promise<Int8Array | null>;
|
|
38
|
+
/** Batched convenience wrapper mirroring `embedTextInt8`, for the generation paths in Phase 3. */
|
|
39
|
+
export declare function embedTextsInt8(texts: string[]): Promise<Int8Array[] | null>;
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedder.js","sourceRoot":"","sources":["../../src/db/embedder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compulsory-but-cheap feedback captured on every `commit_changes` call — the graph only earns
|
|
3
|
+
* trust if agents that discover it's wrong can say so, and the whole point is capturing that
|
|
4
|
+
* signal WITHOUT disrupting the working agent's flow: this module only appends, synchronously,
|
|
5
|
+
* to a local file. No extra round-trip, no live graph mutation, no agent ever blocked on this.
|
|
6
|
+
*
|
|
7
|
+
* Two files, two audiences, both under the gitignored `.devmind/local/` tree (same convention as
|
|
8
|
+
* activity.ts — private per-developer working state, never pushed):
|
|
9
|
+
* - `feedback_graph.jsonl` — machine-actionable. Read later by a supervised batch session
|
|
10
|
+
* (graph-fix tools) that verifies each entry against current code
|
|
11
|
+
* before writing anything to the graph. Never auto-applied live.
|
|
12
|
+
* - `feedback_product.jsonl` — human-actionable. Aggregated by a person into "how do we make
|
|
13
|
+
* DevsMind better", never read by an agent to mutate anything.
|
|
14
|
+
*
|
|
15
|
+
* `"none"` is a first-class, legitimate, expected answer on every field — a required field is
|
|
16
|
+
* required to be ANSWERED, not required to contain a problem. Making "none" cheap is what stops a
|
|
17
|
+
* compulsory field from pressuring an agent into inventing issues just to fill it in.
|
|
18
|
+
*/
|
|
19
|
+
export type GraphFeedbackCategory = 'graph_problem' | 'edge_problem';
|
|
20
|
+
export type ProductFeedbackCategory = 'tools_used' | 'dropped_and_why' | 'devsmind_better';
|
|
21
|
+
/** How sure the reporting agent is. Only `confirmed` entries with evidence are strong candidates
|
|
22
|
+
* for the batch session to act on directly; `suspected` entries need the batch session to verify
|
|
23
|
+
* first (or are low priority until corroborated by a repeat report). */
|
|
24
|
+
export type FeedbackConfidence = 'suspected' | 'confirmed';
|
|
25
|
+
export interface FeedbackEvidence {
|
|
26
|
+
file: string;
|
|
27
|
+
line?: number;
|
|
28
|
+
snippet?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface GraphFeedbackEntry {
|
|
31
|
+
/** Stable identity, minted at append time — what {@link markGraphFeedbackProcessed} targets. */
|
|
32
|
+
id: string;
|
|
33
|
+
ts: string;
|
|
34
|
+
session_id: string;
|
|
35
|
+
category: GraphFeedbackCategory;
|
|
36
|
+
text: string;
|
|
37
|
+
node_id?: string;
|
|
38
|
+
confidence: FeedbackConfidence;
|
|
39
|
+
evidence?: FeedbackEvidence;
|
|
40
|
+
/** Set by the batch graph-fix session once it has verified/applied this entry, so repeated
|
|
41
|
+
* batch runs don't re-chew the same report. Absent/false = not yet processed. */
|
|
42
|
+
processed?: boolean;
|
|
43
|
+
}
|
|
44
|
+
export interface ProductFeedbackEntry {
|
|
45
|
+
ts: string;
|
|
46
|
+
session_id: string;
|
|
47
|
+
category: ProductFeedbackCategory;
|
|
48
|
+
text: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* A recurring pattern the batch graph-fix session noticed while resolving feedback — e.g. "every
|
|
52
|
+
* one of these 12 reports was the same framework's generated-binding pattern" — worth turning
|
|
53
|
+
* into a PERMANENT deterministic rule (a detector like Phase C's RTK one) instead of fixing the
|
|
54
|
+
* same class of miss by hand forever. This is a candidate log for a human to review, not something
|
|
55
|
+
* an agent acts on automatically — writing an actual detector is real engineering work.
|
|
56
|
+
*/
|
|
57
|
+
export interface IndexerRuleCandidate {
|
|
58
|
+
ts: string;
|
|
59
|
+
/** Short description of the pattern, e.g. "Vue computed() properties never get aliased". */
|
|
60
|
+
pattern: string;
|
|
61
|
+
/** How many feedback entries this pattern was inferred from — the priority signal. */
|
|
62
|
+
evidence_count: number;
|
|
63
|
+
/** A few representative examples (file:line style strings), not every occurrence. */
|
|
64
|
+
examples: string[];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Appends one graph-correction report. Evidence is required to mark an entry `confirmed` — an
|
|
68
|
+
* unevidenced report is downgraded to `suspected` regardless of what the caller claimed, since a
|
|
69
|
+
* "graph problem" with no `file:line` to check is not reconstructable once the code has moved on
|
|
70
|
+
* (this may be read weeks later, in the batch session — see the module doc).
|
|
71
|
+
*/
|
|
72
|
+
export declare function appendGraphFeedback(devmindPath: string, entry: {
|
|
73
|
+
session_id: string;
|
|
74
|
+
category: GraphFeedbackCategory;
|
|
75
|
+
text: string;
|
|
76
|
+
node_id?: string;
|
|
77
|
+
evidence?: FeedbackEvidence;
|
|
78
|
+
}): void;
|
|
79
|
+
/** Appends one product-improvement report — never read by an agent, only aggregated for a human. */
|
|
80
|
+
export declare function appendProductFeedback(devmindPath: string, entry: {
|
|
81
|
+
session_id: string;
|
|
82
|
+
category: ProductFeedbackCategory;
|
|
83
|
+
text: string;
|
|
84
|
+
}): void;
|
|
85
|
+
/**
|
|
86
|
+
* Reads graph-feedback entries — the batch graph-fix session's input. Unprocessed only by
|
|
87
|
+
* default (`opts.includeProcessed` to see everything, e.g. for an audit/report).
|
|
88
|
+
*/
|
|
89
|
+
export declare function readGraphFeedback(devmindPath: string, opts?: {
|
|
90
|
+
includeProcessed?: boolean;
|
|
91
|
+
}): GraphFeedbackEntry[];
|
|
92
|
+
/** Reads every product-feedback entry recorded so far — for human aggregation/reporting. */
|
|
93
|
+
export declare function readProductFeedback(devmindPath: string): ProductFeedbackEntry[];
|
|
94
|
+
/**
|
|
95
|
+
* Marks graph-feedback entries as processed by id — rewrites the whole file (atomic temp+rename,
|
|
96
|
+
* same convention as `staging.ts`'s `writeBuffer`), since JSONL is append-only and a past line
|
|
97
|
+
* can't be edited in place. Idempotent: marking an already-processed or unknown id is a no-op for
|
|
98
|
+
* that id. Called by the batch graph-fix session once it has verified and applied (or explicitly
|
|
99
|
+
* rejected) an entry, so a later batch run never re-chews the same report.
|
|
100
|
+
*/
|
|
101
|
+
export declare function markGraphFeedbackProcessed(devmindPath: string, ids: string[]): void;
|
|
102
|
+
/** One node/category's worth of graph feedback, grouped together — frequency is the priority
|
|
103
|
+
* signal: the same report surfacing many times means it's worth acting on first, and a single
|
|
104
|
+
* `record_alias`/`link_nodes` call can resolve every entry in the cluster at once. */
|
|
105
|
+
export interface GraphFeedbackCluster {
|
|
106
|
+
node_id: string;
|
|
107
|
+
category: GraphFeedbackCategory;
|
|
108
|
+
count: number;
|
|
109
|
+
entries: GraphFeedbackEntry[];
|
|
110
|
+
/** Highest confidence among the cluster's entries — one `confirmed` report is enough to make
|
|
111
|
+
* the whole cluster worth verifying first, even alongside otherwise-`suspected` duplicates. */
|
|
112
|
+
confidence: FeedbackConfidence;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Groups graph-feedback entries by `(node_id, category)` and sorts by frequency (most-reported
|
|
116
|
+
* first) — the clustering the batch session's `read_graph_feedback` tool exposes, so 30 identical
|
|
117
|
+
* reports of the same RTK miss show up as ONE cluster of size 30, not 30 things to individually
|
|
118
|
+
* re-investigate.
|
|
119
|
+
*/
|
|
120
|
+
export declare function clusterGraphFeedback(entries: GraphFeedbackEntry[]): GraphFeedbackCluster[];
|
|
121
|
+
/** Appends one indexer-rule candidate — see {@link IndexerRuleCandidate}. */
|
|
122
|
+
export declare function appendIndexerRuleCandidate(devmindPath: string, entry: {
|
|
123
|
+
pattern: string;
|
|
124
|
+
evidence_count: number;
|
|
125
|
+
examples: string[];
|
|
126
|
+
}): void;
|
|
127
|
+
/** Reads every indexer-rule candidate recorded so far — for a human to review/prioritize. */
|
|
128
|
+
export declare function readIndexerRuleCandidates(devmindPath: string): IndexerRuleCandidate[];
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.appendGraphFeedback = appendGraphFeedback;
|
|
37
|
+
exports.appendProductFeedback = appendProductFeedback;
|
|
38
|
+
exports.readGraphFeedback = readGraphFeedback;
|
|
39
|
+
exports.readProductFeedback = readProductFeedback;
|
|
40
|
+
exports.markGraphFeedbackProcessed = markGraphFeedbackProcessed;
|
|
41
|
+
exports.clusterGraphFeedback = clusterGraphFeedback;
|
|
42
|
+
exports.appendIndexerRuleCandidate = appendIndexerRuleCandidate;
|
|
43
|
+
exports.readIndexerRuleCandidates = readIndexerRuleCandidates;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const crypto = __importStar(require("crypto"));
|
|
47
|
+
const activity_1 = require("./activity");
|
|
48
|
+
function graphFeedbackPath(devmindPath) {
|
|
49
|
+
return path.join((0, activity_1.localDir)(devmindPath), 'feedback_graph.jsonl');
|
|
50
|
+
}
|
|
51
|
+
function productFeedbackPath(devmindPath) {
|
|
52
|
+
return path.join((0, activity_1.localDir)(devmindPath), 'feedback_product.jsonl');
|
|
53
|
+
}
|
|
54
|
+
function indexerRuleCandidatesPath(devmindPath) {
|
|
55
|
+
return path.join((0, activity_1.localDir)(devmindPath), 'indexer_rule_candidates.jsonl');
|
|
56
|
+
}
|
|
57
|
+
function appendJsonl(devmindPath, target, entry) {
|
|
58
|
+
(0, activity_1.ensureGitignored)(devmindPath);
|
|
59
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
60
|
+
fs.appendFileSync(target, JSON.stringify(entry) + '\n', 'utf-8');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Appends one graph-correction report. Evidence is required to mark an entry `confirmed` — an
|
|
64
|
+
* unevidenced report is downgraded to `suspected` regardless of what the caller claimed, since a
|
|
65
|
+
* "graph problem" with no `file:line` to check is not reconstructable once the code has moved on
|
|
66
|
+
* (this may be read weeks later, in the batch session — see the module doc).
|
|
67
|
+
*/
|
|
68
|
+
function appendGraphFeedback(devmindPath, entry) {
|
|
69
|
+
const confidence = entry.evidence ? 'confirmed' : 'suspected';
|
|
70
|
+
const record = {
|
|
71
|
+
id: crypto.randomUUID(),
|
|
72
|
+
ts: new Date().toISOString(),
|
|
73
|
+
session_id: entry.session_id,
|
|
74
|
+
category: entry.category,
|
|
75
|
+
text: entry.text,
|
|
76
|
+
node_id: entry.node_id,
|
|
77
|
+
confidence,
|
|
78
|
+
evidence: entry.evidence
|
|
79
|
+
};
|
|
80
|
+
appendJsonl(devmindPath, graphFeedbackPath(devmindPath), record);
|
|
81
|
+
}
|
|
82
|
+
/** Appends one product-improvement report — never read by an agent, only aggregated for a human. */
|
|
83
|
+
function appendProductFeedback(devmindPath, entry) {
|
|
84
|
+
const record = {
|
|
85
|
+
ts: new Date().toISOString(),
|
|
86
|
+
session_id: entry.session_id,
|
|
87
|
+
category: entry.category,
|
|
88
|
+
text: entry.text
|
|
89
|
+
};
|
|
90
|
+
appendJsonl(devmindPath, productFeedbackPath(devmindPath), record);
|
|
91
|
+
}
|
|
92
|
+
function readJsonl(target) {
|
|
93
|
+
if (!fs.existsSync(target))
|
|
94
|
+
return [];
|
|
95
|
+
const lines = fs.readFileSync(target, 'utf-8').split('\n').map(l => l.trim()).filter(Boolean);
|
|
96
|
+
const out = [];
|
|
97
|
+
for (const line of lines) {
|
|
98
|
+
try {
|
|
99
|
+
out.push(JSON.parse(line));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// A partially-written line (crash mid-append) — skip it rather than fail the whole read.
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Reads graph-feedback entries — the batch graph-fix session's input. Unprocessed only by
|
|
109
|
+
* default (`opts.includeProcessed` to see everything, e.g. for an audit/report).
|
|
110
|
+
*/
|
|
111
|
+
function readGraphFeedback(devmindPath, opts = {}) {
|
|
112
|
+
const all = readJsonl(graphFeedbackPath(devmindPath));
|
|
113
|
+
return opts.includeProcessed ? all : all.filter(e => !e.processed);
|
|
114
|
+
}
|
|
115
|
+
/** Reads every product-feedback entry recorded so far — for human aggregation/reporting. */
|
|
116
|
+
function readProductFeedback(devmindPath) {
|
|
117
|
+
return readJsonl(productFeedbackPath(devmindPath));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Marks graph-feedback entries as processed by id — rewrites the whole file (atomic temp+rename,
|
|
121
|
+
* same convention as `staging.ts`'s `writeBuffer`), since JSONL is append-only and a past line
|
|
122
|
+
* can't be edited in place. Idempotent: marking an already-processed or unknown id is a no-op for
|
|
123
|
+
* that id. Called by the batch graph-fix session once it has verified and applied (or explicitly
|
|
124
|
+
* rejected) an entry, so a later batch run never re-chews the same report.
|
|
125
|
+
*/
|
|
126
|
+
function markGraphFeedbackProcessed(devmindPath, ids) {
|
|
127
|
+
if (ids.length === 0)
|
|
128
|
+
return;
|
|
129
|
+
const target = graphFeedbackPath(devmindPath);
|
|
130
|
+
const all = readJsonl(target);
|
|
131
|
+
const idSet = new Set(ids);
|
|
132
|
+
const updated = all.map(e => (idSet.has(e.id) ? { ...e, processed: true } : e));
|
|
133
|
+
(0, activity_1.ensureGitignored)(devmindPath);
|
|
134
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
135
|
+
const tmp = `${target}.${process.pid}.tmp`;
|
|
136
|
+
fs.writeFileSync(tmp, updated.map(e => JSON.stringify(e)).join('\n') + (updated.length ? '\n' : ''), 'utf-8');
|
|
137
|
+
fs.renameSync(tmp, target);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Groups graph-feedback entries by `(node_id, category)` and sorts by frequency (most-reported
|
|
141
|
+
* first) — the clustering the batch session's `read_graph_feedback` tool exposes, so 30 identical
|
|
142
|
+
* reports of the same RTK miss show up as ONE cluster of size 30, not 30 things to individually
|
|
143
|
+
* re-investigate.
|
|
144
|
+
*/
|
|
145
|
+
function clusterGraphFeedback(entries) {
|
|
146
|
+
const groups = new Map();
|
|
147
|
+
for (const e of entries) {
|
|
148
|
+
const key = `${e.node_id ?? 'unknown'}::${e.category}`;
|
|
149
|
+
const arr = groups.get(key);
|
|
150
|
+
if (arr)
|
|
151
|
+
arr.push(e);
|
|
152
|
+
else
|
|
153
|
+
groups.set(key, [e]);
|
|
154
|
+
}
|
|
155
|
+
const clusters = [];
|
|
156
|
+
for (const [key, es] of groups) {
|
|
157
|
+
const sep = key.lastIndexOf('::');
|
|
158
|
+
clusters.push({
|
|
159
|
+
node_id: key.slice(0, sep),
|
|
160
|
+
category: key.slice(sep + 2),
|
|
161
|
+
count: es.length,
|
|
162
|
+
entries: es,
|
|
163
|
+
confidence: es.some(e => e.confidence === 'confirmed') ? 'confirmed' : 'suspected'
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return clusters.sort((a, b) => b.count - a.count);
|
|
167
|
+
}
|
|
168
|
+
/** Appends one indexer-rule candidate — see {@link IndexerRuleCandidate}. */
|
|
169
|
+
function appendIndexerRuleCandidate(devmindPath, entry) {
|
|
170
|
+
const record = {
|
|
171
|
+
ts: new Date().toISOString(),
|
|
172
|
+
pattern: entry.pattern,
|
|
173
|
+
evidence_count: entry.evidence_count,
|
|
174
|
+
examples: entry.examples
|
|
175
|
+
};
|
|
176
|
+
appendJsonl(devmindPath, indexerRuleCandidatesPath(devmindPath), record);
|
|
177
|
+
}
|
|
178
|
+
/** Reads every indexer-rule candidate recorded so far — for a human to review/prioritize. */
|
|
179
|
+
function readIndexerRuleCandidates(devmindPath) {
|
|
180
|
+
return readJsonl(indexerRuleCandidatesPath(devmindPath));
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=feedback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feedback.js","sourceRoot":"","sources":["../../src/db/feedback.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { MessageEdit } from './activity';
|
|
2
|
+
import { DiffLine } from '../utils/diff';
|
|
3
|
+
export interface FileDiffResult {
|
|
4
|
+
file_path: string;
|
|
5
|
+
before_file: string;
|
|
6
|
+
after_file: string;
|
|
7
|
+
hunks: DiffLine[];
|
|
8
|
+
drifted: boolean;
|
|
9
|
+
drift_reason?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Reconstructs the whole-file "before" state for one file's worth of edits from a single
|
|
13
|
+
* activity message, by undoing each edit's `after -> before` in memory, newest-first — the same
|
|
14
|
+
* ordering `revertOneMessageAtomically` (message-revert.ts) uses when it does this for real on
|
|
15
|
+
* disk. `fileEdits` must already be filtered to one file_path, in chronological (oldest-first)
|
|
16
|
+
* order, matching how they appear in `ActivityMessage.edits`.
|
|
17
|
+
*
|
|
18
|
+
* Drift (a hand-edit, a pull, a later message touching the same text) means some `after` snippet
|
|
19
|
+
* no longer matches the file uniquely — reported rather than guessed at, same as revert refuses
|
|
20
|
+
* rather than forcing a mismatched restore.
|
|
21
|
+
*/
|
|
22
|
+
export declare function reconstructBeforeFile(liveContent: string, fileEdits: MessageEdit[]): {
|
|
23
|
+
before: string;
|
|
24
|
+
drifted: boolean;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Collapses every edit a message made to ONE file into a single git-style whole-file diff,
|
|
28
|
+
* reading the live file off disk as the "after" state. On drift, the reconstruction is not
|
|
29
|
+
* trustworthy — the caller should fall back to the per-node `diffSnapshots(before, after)` for
|
|
30
|
+
* this file instead of rendering a wrong whole-file diff.
|
|
31
|
+
*/
|
|
32
|
+
export declare function fileDiffForMessage(filePath: string, fileEdits: MessageEdit[]): FileDiffResult;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.reconstructBeforeFile = reconstructBeforeFile;
|
|
37
|
+
exports.fileDiffForMessage = fileDiffForMessage;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const diff_1 = require("../utils/diff");
|
|
40
|
+
/**
|
|
41
|
+
* Same single-occurrence exact-match semantics as replaceTextInFile (src/utils/edit.ts), but
|
|
42
|
+
* in-memory and read-only — no disk write, no atomic-rename. Returns null (rather than throwing)
|
|
43
|
+
* when `oldString` isn't found exactly once, so the caller can treat that as drift.
|
|
44
|
+
*/
|
|
45
|
+
function replaceOnce(content, oldString, newString) {
|
|
46
|
+
if (oldString === newString)
|
|
47
|
+
return content; // a no-op edit (before === after) has nothing to undo
|
|
48
|
+
if (oldString === '')
|
|
49
|
+
return null; // no anchor to locate — can't undo an insertion blind
|
|
50
|
+
let count = 0;
|
|
51
|
+
for (let i = content.indexOf(oldString); i !== -1; i = content.indexOf(oldString, i + oldString.length)) {
|
|
52
|
+
count++;
|
|
53
|
+
if (count > 1)
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
if (count !== 1)
|
|
57
|
+
return null;
|
|
58
|
+
const i = content.indexOf(oldString);
|
|
59
|
+
return content.slice(0, i) + newString + content.slice(i + oldString.length);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Reconstructs the whole-file "before" state for one file's worth of edits from a single
|
|
63
|
+
* activity message, by undoing each edit's `after -> before` in memory, newest-first — the same
|
|
64
|
+
* ordering `revertOneMessageAtomically` (message-revert.ts) uses when it does this for real on
|
|
65
|
+
* disk. `fileEdits` must already be filtered to one file_path, in chronological (oldest-first)
|
|
66
|
+
* order, matching how they appear in `ActivityMessage.edits`.
|
|
67
|
+
*
|
|
68
|
+
* Drift (a hand-edit, a pull, a later message touching the same text) means some `after` snippet
|
|
69
|
+
* no longer matches the file uniquely — reported rather than guessed at, same as revert refuses
|
|
70
|
+
* rather than forcing a mismatched restore.
|
|
71
|
+
*/
|
|
72
|
+
function reconstructBeforeFile(liveContent, fileEdits) {
|
|
73
|
+
const newestFirst = fileEdits.slice().reverse();
|
|
74
|
+
let content = liveContent;
|
|
75
|
+
for (const edit of newestFirst) {
|
|
76
|
+
const undone = replaceOnce(content, edit.after, edit.before);
|
|
77
|
+
if (undone === null)
|
|
78
|
+
return { before: content, drifted: true };
|
|
79
|
+
content = undone;
|
|
80
|
+
}
|
|
81
|
+
return { before: content, drifted: false };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Collapses every edit a message made to ONE file into a single git-style whole-file diff,
|
|
85
|
+
* reading the live file off disk as the "after" state. On drift, the reconstruction is not
|
|
86
|
+
* trustworthy — the caller should fall back to the per-node `diffSnapshots(before, after)` for
|
|
87
|
+
* this file instead of rendering a wrong whole-file diff.
|
|
88
|
+
*/
|
|
89
|
+
function fileDiffForMessage(filePath, fileEdits) {
|
|
90
|
+
let live;
|
|
91
|
+
try {
|
|
92
|
+
live = fs.readFileSync(filePath, 'utf-8');
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return { file_path: filePath, before_file: '', after_file: '', hunks: [], drifted: true, drift_reason: 'file no longer exists on disk' };
|
|
96
|
+
}
|
|
97
|
+
const { before, drifted } = reconstructBeforeFile(live, fileEdits);
|
|
98
|
+
if (drifted) {
|
|
99
|
+
return {
|
|
100
|
+
file_path: filePath,
|
|
101
|
+
before_file: before,
|
|
102
|
+
after_file: live,
|
|
103
|
+
hunks: [],
|
|
104
|
+
drifted: true,
|
|
105
|
+
drift_reason: 'file has changed since this message was recorded — showing per-change diffs instead'
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return { file_path: filePath, before_file: before, after_file: live, hunks: (0, diff_1.diffSnapshots)(before, live, 8), drifted: false };
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=file-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-diff.js","sourceRoot":"","sources":["../../src/db/file-diff.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,sDASC;AAQD,gDAqBC;AAhFD,uCAAyB;AAEzB,wCAAwD;AAWxD;;;;GAIG;AACH,SAAS,WAAW,CAAC,OAAe,EAAE,SAAiB,EAAE,SAAiB;IACxE,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC,CAAC,sDAAsD;IACnG,IAAI,SAAS,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC,CAAC,sDAAsD;IACzF,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACxG,KAAK,EAAE,CAAC;QACR,IAAI,KAAK,GAAG,CAAC;YAAE,MAAM;IACvB,CAAC;IACD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7B,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,qBAAqB,CAAC,WAAmB,EAAE,SAAwB;IACjF,MAAM,WAAW,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC;IAChD,IAAI,OAAO,GAAG,WAAW,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC/D,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,QAAgB,EAAE,SAAwB;IAC3E,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,+BAA+B,EAAE,CAAC;IAC3I,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,qBAAqB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACnE,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO;YACL,SAAS,EAAE,QAAQ;YACnB,WAAW,EAAE,MAAM;YACnB,UAAU,EAAE,IAAI;YAChB,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,IAAI;YACb,YAAY,EAAE,qFAAqF;SACpG,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,IAAA,oBAAa,EAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC/H,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True if a path is a lockfile or build artifact excluded from search by default. Exported so
|
|
3
|
+
* `searchNodes` can tell an agent that explicitly scoped `path` AT such a file WHY it got nothing
|
|
4
|
+
* back, rather than leaving it to read as "the pattern isn't in there".
|
|
5
|
+
*/
|
|
6
|
+
export declare function isDefaultIgnoredFile(filePath: string): boolean;
|
|
7
|
+
export interface GrepHit {
|
|
8
|
+
file_path: string;
|
|
9
|
+
line_number: number;
|
|
10
|
+
line_content: string;
|
|
11
|
+
/** The actual substring the regex matched at this hit (lowercased) — used to attribute and
|
|
12
|
+
* rank matches without needing a fixed keyword list, since the pattern may be a single regex
|
|
13
|
+
* with no discrete "terms" of its own (e.g. `on\w+Tap`). */
|
|
14
|
+
matched_text: string;
|
|
15
|
+
}
|
|
16
|
+
export interface GrepResult {
|
|
17
|
+
hits: GrepHit[];
|
|
18
|
+
truncated: boolean;
|
|
19
|
+
files_scanned: number;
|
|
20
|
+
}
|
|
21
|
+
export interface RankedFile {
|
|
22
|
+
file_path: string;
|
|
23
|
+
total_matches: number;
|
|
24
|
+
/** Per-matched-text counts in this file — how the AI sees which part of the pattern actually landed. */
|
|
25
|
+
match_counts: Record<string, number>;
|
|
26
|
+
/** How many DISTINCT matched strings landed here — the strongest relevance signal. */
|
|
27
|
+
distinct_matches: number;
|
|
28
|
+
score: number;
|
|
29
|
+
/** A few representative matching lines (capped), for the AI to eyeball without opening the file.
|
|
30
|
+
* `symbol` — the containing function/class, when resolvable — is populated by the CALLER
|
|
31
|
+
* (`DevMindDatabase.annotateSampleLinesWithSymbol`), never by grep.ts itself: this module is
|
|
32
|
+
* deliberately dependency-free (no DB/AST access), see the file-level doc comment. */
|
|
33
|
+
sample_lines: {
|
|
34
|
+
line_number: number;
|
|
35
|
+
line_content: string;
|
|
36
|
+
symbol?: string;
|
|
37
|
+
}[];
|
|
38
|
+
}
|
|
39
|
+
/** `rankGrepHits`' result: a capped page of files plus the TRUE total, so the caller can tell
|
|
40
|
+
* "nothing more to find" from "more exists past this page" instead of guessing from a bare list. */
|
|
41
|
+
export interface RankGrepHitsResult {
|
|
42
|
+
files: RankedFile[];
|
|
43
|
+
/** Total distinct files that matched, before the `maxFiles`/`offset` page was cut. */
|
|
44
|
+
total: number;
|
|
45
|
+
}
|
|
46
|
+
/** Escapes a literal string so it matches as text, not as a regex pattern. Exported so callers
|
|
47
|
+
* building a regex out of LITERAL terms (e.g. `searchNodes` deriving one from query tokens when
|
|
48
|
+
* no explicit `pattern` was given) can reuse the exact same escaping grep.ts uses internally. */
|
|
49
|
+
export declare function escapeRegExp(s: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Greps every configured repo root (or, when `opts.scopePath` is given, just that one folder or
|
|
52
|
+
* file) for `pattern` — a real regex, used as-is. Returns raw hits plus whether the deadline
|
|
53
|
+
* forced an early, partial stop. Ranking is a separate pure step (`rankGrepHits`).
|
|
54
|
+
*
|
|
55
|
+
* Invalid regex throws `Invalid regex pattern: <message>` immediately (same shape as the
|
|
56
|
+
* precedent already established by `DevMindDatabase.searchCode`) rather than surfacing as an
|
|
57
|
+
* opaque failure deeper in the walk.
|
|
58
|
+
*/
|
|
59
|
+
export declare function grepRepos(repoRoots: string[], pattern: string, opts?: {
|
|
60
|
+
ignoredPaths?: string[];
|
|
61
|
+
timeoutMs?: number;
|
|
62
|
+
caseInsensitive?: boolean;
|
|
63
|
+
scopePath?: string;
|
|
64
|
+
}): Promise<GrepResult>;
|
|
65
|
+
/**
|
|
66
|
+
* Ranks raw hits into a capped, ordered PAGE of files — the anti-firehose gate — plus the TRUE
|
|
67
|
+
* total file count before that cap, so a caller can tell "that's everything" from "more exists,
|
|
68
|
+
* ask for the next page" instead of guessing from a bare capped list. Unranked hits across 8
|
|
69
|
+
* repos can be hundreds; dumping them recreates the exact "15-20 low-confidence results I have to
|
|
70
|
+
* eyeball-filter" complaint that made the AI distrust the tool. So: group by file, score by match
|
|
71
|
+
* count weighted toward RARER matched strings (IDF-shaped, same instinct as BM25), reward files
|
|
72
|
+
* matching MULTIPLE distinct strings, sort with a stable tiebreaker, and page.
|
|
73
|
+
*/
|
|
74
|
+
export declare function rankGrepHits(hits: GrepHit[], opts?: {
|
|
75
|
+
maxFiles?: number;
|
|
76
|
+
maxSampleLines?: number;
|
|
77
|
+
offset?: number;
|
|
78
|
+
}): RankGrepHitsResult;
|