devsmind-mcp 2.4.0 → 3.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.
Files changed (128) hide show
  1. package/README.md +326 -234
  2. package/dist/cli/activity.d.ts +9 -0
  3. package/dist/cli/activity.js +69 -0
  4. package/dist/cli/activity.js.map +1 -0
  5. package/dist/cli/describe.d.ts +31 -0
  6. package/dist/cli/describe.js +201 -0
  7. package/dist/cli/describe.js.map +1 -0
  8. package/dist/cli/diff.d.ts +14 -0
  9. package/dist/cli/diff.js +161 -0
  10. package/dist/cli/diff.js.map +1 -0
  11. package/dist/cli/embed.d.ts +6 -0
  12. package/dist/cli/embed.js +109 -0
  13. package/dist/cli/embed.js.map +1 -0
  14. package/dist/cli/extract-agent.d.ts +66 -0
  15. package/dist/cli/extract-agent.js +192 -0
  16. package/dist/cli/extract-agent.js.map +1 -0
  17. package/dist/cli/feedback.d.ts +11 -0
  18. package/dist/cli/feedback.js +90 -0
  19. package/dist/cli/feedback.js.map +1 -0
  20. package/dist/cli/index.js +128 -5
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/cli/init.d.ts +30 -0
  23. package/dist/cli/init.js +89 -18
  24. package/dist/cli/init.js.map +1 -1
  25. package/dist/cli/integrations/memory-topics.d.ts +44 -0
  26. package/dist/cli/integrations/memory-topics.js +295 -0
  27. package/dist/cli/integrations/memory-topics.js.map +1 -0
  28. package/dist/cli/integrations/memory.d.ts +11 -5
  29. package/dist/cli/integrations/memory.js +132 -37
  30. package/dist/cli/integrations/memory.js.map +1 -1
  31. package/dist/cli/integrations/prompt.d.ts +8 -0
  32. package/dist/cli/integrations/prompt.js +24 -3
  33. package/dist/cli/integrations/prompt.js.map +1 -1
  34. package/dist/cli/integrations/registry.d.ts +19 -5
  35. package/dist/cli/integrations/registry.js +23 -13
  36. package/dist/cli/integrations/registry.js.map +1 -1
  37. package/dist/cli/llm-client.d.ts +116 -0
  38. package/dist/cli/llm-client.js +322 -0
  39. package/dist/cli/llm-client.js.map +1 -0
  40. package/dist/cli/rule.d.ts +22 -2
  41. package/dist/cli/rule.js +113 -32
  42. package/dist/cli/rule.js.map +1 -1
  43. package/dist/cli/runner.d.ts +21 -0
  44. package/dist/cli/runner.js +94 -276
  45. package/dist/cli/runner.js.map +1 -1
  46. package/dist/cli/sync-progress.d.ts +9 -0
  47. package/dist/cli/sync-progress.js +41 -0
  48. package/dist/cli/sync-progress.js.map +1 -0
  49. package/dist/cli/sync.js +5 -2
  50. package/dist/cli/sync.js.map +1 -1
  51. package/dist/cli/view.js +3 -2
  52. package/dist/cli/view.js.map +1 -1
  53. package/dist/cli/workflow.js +26 -20
  54. package/dist/cli/workflow.js.map +1 -1
  55. package/dist/db/activity.d.ts +200 -0
  56. package/dist/db/activity.js +347 -0
  57. package/dist/db/activity.js.map +1 -0
  58. package/dist/db/analyze.js +18 -6
  59. package/dist/db/analyze.js.map +1 -1
  60. package/dist/db/database.d.ts +583 -99
  61. package/dist/db/database.js +1825 -553
  62. package/dist/db/database.js.map +1 -1
  63. package/dist/db/edges.d.ts +24 -0
  64. package/dist/db/edges.js +84 -0
  65. package/dist/db/edges.js.map +1 -1
  66. package/dist/db/embedder.d.ts +39 -0
  67. package/dist/db/embedder.js +0 -0
  68. package/dist/db/embedder.js.map +1 -0
  69. package/dist/db/feedback.d.ts +128 -0
  70. package/dist/db/feedback.js +182 -0
  71. package/dist/db/feedback.js.map +1 -0
  72. package/dist/db/file-diff.d.ts +32 -0
  73. package/dist/db/file-diff.js +110 -0
  74. package/dist/db/file-diff.js.map +1 -0
  75. package/dist/db/grep.d.ts +78 -0
  76. package/dist/db/grep.js +475 -0
  77. package/dist/db/grep.js.map +1 -0
  78. package/dist/db/message-revert.d.ts +63 -0
  79. package/dist/db/message-revert.js +258 -0
  80. package/dist/db/message-revert.js.map +1 -0
  81. package/dist/db/revert.d.ts +31 -0
  82. package/dist/db/revert.js +108 -0
  83. package/dist/db/revert.js.map +1 -0
  84. package/dist/db/schema.d.ts +49 -4
  85. package/dist/db/schema.js +125 -73
  86. package/dist/db/schema.js.map +1 -1
  87. package/dist/db/search-index.d.ts +65 -0
  88. package/dist/db/search-index.js +74 -0
  89. package/dist/db/search-index.js.map +1 -0
  90. package/dist/db/staging.d.ts +90 -5
  91. package/dist/db/staging.js +148 -22
  92. package/dist/db/staging.js.map +1 -1
  93. package/dist/mcp/server.d.ts +29 -7
  94. package/dist/mcp/server.js +2584 -809
  95. package/dist/mcp/server.js.map +1 -1
  96. package/dist/mcp/vendor/3d-force-graph.min.js +5 -0
  97. package/dist/mcp/vendor/force-graph.min.js +5 -0
  98. package/dist/mcp/vendor/model/model_int8.onnx +0 -0
  99. package/dist/mcp/vendor/model/vocab.txt +30522 -0
  100. package/dist/mcp/vendor/three.min.js +7 -0
  101. package/dist/mcp/view.css +419 -0
  102. package/dist/mcp/view.html +161 -0
  103. package/dist/mcp/view.js +245 -0
  104. package/dist/mcp/view_chat.js +382 -0
  105. package/dist/mcp/view_graph.js +576 -0
  106. package/dist/mcp/visualizer.d.ts +25 -2
  107. package/dist/mcp/visualizer.js +31 -4
  108. package/dist/mcp/visualizer.js.map +1 -1
  109. package/dist/utils/ast.d.ts +89 -0
  110. package/dist/utils/ast.js +378 -10
  111. package/dist/utils/ast.js.map +1 -1
  112. package/dist/utils/diff.d.ts +44 -0
  113. package/dist/utils/diff.js +78 -0
  114. package/dist/utils/diff.js.map +1 -0
  115. package/dist/utils/edit.d.ts +6 -0
  116. package/dist/utils/edit.js +47 -14
  117. package/dist/utils/edit.js.map +1 -1
  118. package/dist/utils/scanner.js +12 -4
  119. package/dist/utils/scanner.js.map +1 -1
  120. package/dist/utils/tokenize.d.ts +45 -0
  121. package/dist/utils/tokenize.js +129 -0
  122. package/dist/utils/tokenize.js.map +1 -0
  123. package/dist/utils/version.d.ts +14 -0
  124. package/dist/utils/version.js +61 -0
  125. package/dist/utils/version.js.map +1 -0
  126. package/package.json +18 -5
  127. package/dist/mcp/visualizer_2d.html +0 -635
  128. package/dist/mcp/visualizer_3d.html +0 -613
@@ -34,17 +34,39 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.readStaged = readStaged;
37
+ exports.readStagedFileEdits = readStagedFileEdits;
38
+ exports.partitionStagedForSession = partitionStagedForSession;
39
+ exports.clearStagedForSession = clearStagedForSession;
37
40
  exports.stageEntry = stageEntry;
41
+ exports.stageFileEdit = stageFileEdit;
42
+ exports.overwriteStaged = overwriteStaged;
38
43
  exports.clearStaged = clearStaged;
44
+ exports.removeLastStagedEntry = removeLastStagedEntry;
45
+ exports.resolveEntryId = resolveEntryId;
39
46
  exports.commitStagedChanges = commitStagedChanges;
40
47
  exports.summarizeEntriesForWorkflow = summarizeEntriesForWorkflow;
41
48
  const fs = __importStar(require("fs"));
42
49
  const path = __importStar(require("path"));
43
50
  const edges_1 = require("./edges");
51
+ const embedder_1 = require("./embedder");
44
52
  const STAGING_FILE = 'history_scratchpad.json';
45
53
  function stagingPath(devmindPath) {
46
54
  return path.join(path.resolve(devmindPath), STAGING_FILE);
47
55
  }
56
+ function readBuffer(devmindPath) {
57
+ try {
58
+ const raw = fs.readFileSync(stagingPath(devmindPath), 'utf-8');
59
+ const buf = JSON.parse(raw);
60
+ return {
61
+ entries: Array.isArray(buf.entries) ? buf.entries : [],
62
+ file_edits: Array.isArray(buf.file_edits) ? buf.file_edits : [],
63
+ updated_at: buf.updated_at || new Date().toISOString()
64
+ };
65
+ }
66
+ catch {
67
+ return { entries: [], file_edits: [], updated_at: new Date().toISOString() };
68
+ }
69
+ }
48
70
  /** Atomic write (temp file + rename) so an accumulating buffer is never left half-written. */
49
71
  function writeBuffer(devmindPath, buf) {
50
72
  const target = stagingPath(devmindPath);
@@ -53,21 +75,78 @@ function writeBuffer(devmindPath, buf) {
53
75
  fs.renameSync(tmp, target);
54
76
  }
55
77
  function readStaged(devmindPath) {
56
- try {
57
- const raw = fs.readFileSync(stagingPath(devmindPath), 'utf-8');
58
- const buf = JSON.parse(raw);
59
- return Array.isArray(buf.entries) ? buf.entries : [];
78
+ return readBuffer(devmindPath).entries;
79
+ }
80
+ function readStagedFileEdits(devmindPath) {
81
+ return readBuffer(devmindPath).file_edits;
82
+ }
83
+ /**
84
+ * An entry with no `session_id` predates this field (a buffer written before session-scoping
85
+ * existed) — there is no session left to ever reclaim it, so it is treated as belonging to
86
+ * whoever commits next rather than staying stranded in the buffer forever. Anything stamped
87
+ * with a DIFFERENT session's id is a genuinely different in-flight task and must not be swept
88
+ * up by someone else's commit.
89
+ */
90
+ function belongsToSession(item, sessionId) {
91
+ return !item.session_id || item.session_id === sessionId;
92
+ }
93
+ /**
94
+ * Splits the shared buffer into "what this session may commit" vs. "left behind" — the fix for
95
+ * the multi-session bug where `commit_changes` used to flush the ENTIRE buffer regardless of who
96
+ * staged what, silently pulling unrelated in-flight work (sometimes from other repos entirely)
97
+ * into a commit and stamping it with the committing session's reasoning. A plain commit now only
98
+ * ever touches its own session's staged work; other sessions' entries stay staged untouched.
99
+ */
100
+ function partitionStagedForSession(devmindPath, sessionId) {
101
+ const buf = readBuffer(devmindPath);
102
+ const entries = buf.entries.filter(e => belongsToSession(e, sessionId));
103
+ const fileEdits = buf.file_edits.filter(e => belongsToSession(e, sessionId));
104
+ const otherSessionsPending = (buf.entries.length - entries.length) + (buf.file_edits.length - fileEdits.length);
105
+ return { entries, fileEdits, otherSessionsPending };
106
+ }
107
+ /**
108
+ * Removes only this session's staged entries/file edits, leaving any other session's pending
109
+ * work in place — the scoped counterpart to `clearStaged`, which used to wipe the whole buffer
110
+ * (including work another session had not committed yet) after every commit.
111
+ */
112
+ function clearStagedForSession(devmindPath, sessionId) {
113
+ const buf = readBuffer(devmindPath);
114
+ const entries = buf.entries.filter(e => !belongsToSession(e, sessionId));
115
+ const file_edits = buf.file_edits.filter(e => !belongsToSession(e, sessionId));
116
+ if (entries.length || file_edits.length) {
117
+ writeBuffer(devmindPath, { entries, file_edits, updated_at: new Date().toISOString() });
60
118
  }
61
- catch {
62
- return [];
119
+ else {
120
+ clearStaged(devmindPath);
63
121
  }
64
122
  }
65
- /** Appends one entry to the buffer and returns the new pending count. */
123
+ /** Appends one entry to the buffer (stamping `staged_at`) and returns the new pending count. */
66
124
  function stageEntry(devmindPath, entry) {
67
- const entries = readStaged(devmindPath);
68
- entries.push(entry);
69
- writeBuffer(devmindPath, { entries, updated_at: new Date().toISOString() });
70
- return entries.length;
125
+ const buf = readBuffer(devmindPath);
126
+ buf.entries.push({ ...entry, staged_at: entry.staged_at || new Date().toISOString() });
127
+ buf.updated_at = new Date().toISOString();
128
+ writeBuffer(devmindPath, buf);
129
+ return buf.entries.length;
130
+ }
131
+ /** Appends one whole-file edit to the buffer (stamping `staged_at`) and returns the new pending count. */
132
+ function stageFileEdit(devmindPath, edit) {
133
+ const buf = readBuffer(devmindPath);
134
+ buf.file_edits.push({ ...edit, staged_at: edit.staged_at || new Date().toISOString() });
135
+ buf.updated_at = new Date().toISOString();
136
+ writeBuffer(devmindPath, buf);
137
+ return buf.file_edits.length;
138
+ }
139
+ /**
140
+ * Replaces the buffer's entries wholesale, keeping `file_edits` untouched — used by
141
+ * `add_description` to persist a description written onto an already-staged entry (e.g. after
142
+ * a `commit_changes` rejection), since `readStaged` returns a fresh array each call and
143
+ * mutating it in memory has no effect until it's written back.
144
+ */
145
+ function overwriteStaged(devmindPath, entries) {
146
+ const buf = readBuffer(devmindPath);
147
+ buf.entries = entries;
148
+ buf.updated_at = new Date().toISOString();
149
+ writeBuffer(devmindPath, buf);
71
150
  }
72
151
  function clearStaged(devmindPath) {
73
152
  const target = stagingPath(devmindPath);
@@ -77,7 +156,32 @@ function clearStaged(devmindPath) {
77
156
  }
78
157
  catch { /* ignore */ }
79
158
  }
80
- /** Resolves an entry's raw node_id to the canonical `{repo}/relpath#symbol` form. */
159
+ /**
160
+ * Drops the newest staged entry for one node and returns it, or null if the node has none.
161
+ *
162
+ * Newest rather than all: the buffer can hold several edits to the same entity, and reverting is
163
+ * an undo of the last one. An entry removed here was never committed, so nothing else has to be
164
+ * unwound — there is no history row yet for it to have written.
165
+ */
166
+ function removeLastStagedEntry(devmindPath, nodeId) {
167
+ const buf = readBuffer(devmindPath);
168
+ const idx = buf.entries.map(e => e.node_id).lastIndexOf(nodeId);
169
+ if (idx === -1)
170
+ return null;
171
+ const [removed] = buf.entries.splice(idx, 1);
172
+ if (buf.entries.length || buf.file_edits.length) {
173
+ buf.updated_at = new Date().toISOString();
174
+ writeBuffer(devmindPath, buf);
175
+ }
176
+ else {
177
+ clearStaged(devmindPath);
178
+ }
179
+ return removed;
180
+ }
181
+ /** Resolves an entry's raw node_id to the canonical `{repo}/relpath#symbol` form. Exported so
182
+ * the commit_changes gate can check "does this node already exist" using the exact same
183
+ * canonicalization commitStagedChanges itself uses — a mismatch there would let a node the
184
+ * gate thinks is new slip through uncommitted, or block one that's actually already described. */
81
185
  function resolveEntryId(db, entry) {
82
186
  if (entry.node_id.includes('#'))
83
187
  return entry.node_id;
@@ -92,14 +196,20 @@ function resolveEntryId(db, entry) {
92
196
  * auto-creating any missing target nodes. Only the staged nodes' own outbound edges
93
197
  * are recomputed; every other node's edges are left intact.
94
198
  *
199
+ * `reasoning` is ONE object covering the whole batch — every entry in one commit serves one
200
+ * request, so it is asked for once here rather than repeated on every staged entry. Kept as an
201
+ * object (not pre-formatted) all the way to `updateHistory`, since the configured-developer
202
+ * override only fires on the object form.
203
+ *
95
204
  * Idempotent: re-running the same batch yields the same graph (upsert + INSERT OR IGNORE +
96
205
  * clear-then-resolve). Callers should clear the buffer only after this returns successfully.
97
206
  */
98
- function commitStagedChanges(db, devmindPath, entries) {
207
+ async function commitStagedChanges(db, devmindPath, entries, reasoning) {
99
208
  const stagedIds = [];
100
209
  const historyIds = [];
101
210
  // Pass 1 — nodes + history (+ any explicit connections the caller supplied).
102
211
  const explicitEdges = [];
212
+ const toEmbed = [];
103
213
  for (const entry of entries) {
104
214
  const nodeId = resolveEntryId(db, entry);
105
215
  stagedIds.push(nodeId);
@@ -110,12 +220,16 @@ function commitStagedChanges(db, devmindPath, entries) {
110
220
  name,
111
221
  type,
112
222
  file_path: entry.file_path,
113
- signature: entry.signature || null
223
+ signature: entry.signature || null,
224
+ description: entry.description || null
114
225
  });
226
+ if (entry.description)
227
+ toEmbed.push({ node_id: nodeId, description: entry.description });
115
228
  const history = db.updateHistory({
116
229
  node_id: nodeId,
117
230
  code_snapshot: entry.code_snapshot,
118
- reasoning: entry.reasoning,
231
+ code_before: entry.code_before,
232
+ reasoning,
119
233
  session_id: entry.session_id
120
234
  });
121
235
  historyIds.push(history.id);
@@ -124,6 +238,18 @@ function commitStagedChanges(db, devmindPath, entries) {
124
238
  explicitEdges.push({ source: c.source_node_id || nodeId, target: c.target_node_id });
125
239
  }
126
240
  }
241
+ // Batched, not per-entry — this is where a STAGED description (from stage_change, or from
242
+ // add_description filling in a gate rejection) first has somewhere to actually store a vector.
243
+ // No-op (embedTextsInt8 returns null) if the optional ONNX dependency is unavailable; those
244
+ // nodes just fall into the `devsmind embed` queue like any other unembedded description.
245
+ if (toEmbed.length > 0) {
246
+ const vectors = await (0, embedder_1.embedTextsInt8)(toEmbed.map(t => t.description));
247
+ if (vectors) {
248
+ for (let i = 0; i < toEmbed.length; i++) {
249
+ db.upsertNodeVector(toEmbed[i].node_id, vectors[i], (0, embedder_1.hashDescription)(toEmbed[i].description));
250
+ }
251
+ }
252
+ }
127
253
  // Pass 2 — AST edge resolution for the batch (clear stale outbound edges of staged nodes first).
128
254
  const { edgesAdded, missingFilled } = (0, edges_1.resolveEdgesForNodes)(db, devmindPath, stagedIds, { clearSources: true });
129
255
  // Apply any explicit edges the caller passed, on top of AST resolution (additive).
@@ -139,13 +265,13 @@ function commitStagedChanges(db, devmindPath, entries) {
139
265
  node_ids: stagedIds
140
266
  };
141
267
  }
142
- /** Builds a short workflow-step summary from a batch of staged entries' `what_changed` reasoning. */
143
- function summarizeEntriesForWorkflow(entries) {
144
- const bits = entries.map(e => {
145
- if (typeof e.reasoning === 'object' && e.reasoning.what_changed)
146
- return e.reasoning.what_changed;
147
- return e.node_id;
148
- });
268
+ /** Builds a short workflow-step/activity summary for a commit. The commit's own `reasoning`
269
+ * (one object covering the whole batch) is authoritative when it has a `what_changed`; falls
270
+ * back to naming the staged entities for a bare-string reasoning. */
271
+ function summarizeEntriesForWorkflow(entries, reasoning) {
272
+ if (typeof reasoning === 'object' && reasoning.what_changed)
273
+ return reasoning.what_changed;
274
+ const bits = entries.map(e => e.node_id);
149
275
  return bits.length === 1 ? bits[0] : `${bits.length} entities updated: ${bits.join('; ')}`;
150
276
  }
151
277
  //# sourceMappingURL=staging.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"staging.js","sourceRoot":"","sources":["../../src/db/staging.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"staging.js","sourceRoot":"","sources":["../../src/db/staging.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import express from 'express';
1
3
  export declare const DEVSMIND_PORT = 4513;
2
4
  /**
3
5
  * Sent to every MCP client at connection time via the protocol's `instructions`
@@ -7,18 +9,38 @@ export declare const DEVSMIND_PORT = 4513;
7
9
  * `description` (resent every call), this is easy for a long session to lose
8
10
  * track of too, so it should carry only what's genuinely cross-cutting.
9
11
  */
10
- export declare const DEVSMIND_INSTRUCTIONS = "DevsMind is this team's persistent shared code memory \u2014 not a personal tool you reach for only when asked to search something. Every teammate's AI agent, in every session, reads from the SAME graph you are about to write to. There is no \"your copy.\"\n\nIf you skip recording a change, you are not skipping a formality. You are leaving the whole team's graph stale for every other AI agent that queries this code later \u2014 tomorrow, on a different task, in a different session. And the reasoning behind your change (why it was made, what ticket drove it, what was broken before, what you tried and rejected) exists ONLY in this conversation, right now. It is not in the diff. It is not in the commit message. If it isn't captured this turn, it is gone forever \u2014 no reindex, no log, no git blame can recover it later.\n\nNon-negotiable workflow:\n1. Before any filesystem search or file read: call search_nodes first. It searches names/reasoning and automatically falls back to a full code-content search if nothing matches \u2014 one call covers both, never start with grep.\n2. To read one function/class: call get_node_code instead of opening the file. It parses live from disk, so it's cheaper and always current.\n3. Before touching any function's signature: call get_node_graph. Git shows you what changed; it never shows you what depends on it. Find out before you break something, not after.\n4. Before refactoring: call get_node_history. Git blame tells you who and when; it never tells you why. The actual decision context only exists here.\n5. Write EVERY file with edit_node \u2014 .ts, .vue, .css, .json, .xml, .md, anything \u2014 and never your editor's own edit/write tools. It takes file_path + old_string + new_string exactly like an ordinary edit tool and never refuses a file type; to create a file that doesn't exist yet, pass old_string: \"\" and the whole file as new_string. Because it knows where your text landed, it works out which function/class you changed and records your reasoning against it automatically: no node_id to look up, no code_snapshot to send back, and no stage_change call. It answers with every caller of what you changed. Writes landing outside any function (markup, config, an import) record nothing \u2014 normal and expected, not a failure.\n6. stage_change is now only for what no parser can read: a language with no AST support (.py, .go, .java, .cs, .rb, .php, .rs, .swift, .kt, .dart). edit_node still writes those files, and its response tells you when it couldn't trace one \u2014 so never guess. One call per node, not per file, never batched for later. On a long task, call commit_changes at natural checkpoints too (not only once at the very end) \u2014 waiting until the whole task is \"done\" is how staged work gets left uncommitted when a session runs long.\n7. Scope: the graph is source code only (functions/classes/logic). stage_change will be REJECTED for stylesheets, markup, JSON/config, docs, images, or any other non-code asset. Do not stage those files \u2014 they have no callers/callees to resolve and only bloat the graph.\n8. When you start work that might relate to a multi-session feature, call workflow_list first. If a paused workflow's description looks related to what you're about to do, ask the user whether to resume it (workflow_resume) instead of starting fresh and silently losing its decision history \u2014 git blame never shows you a paused feature's prior context, only this does.\n9. If a workflow is active, commit_changes already logs a step for you from what you staged \u2014 you do NOT need a separate workflow_add_step call for the normal case. Only call workflow_add_step directly for something a commit doesn't cover (a decision with no code change, or a pending_tasks note).";
12
+ export declare const DEVSMIND_INSTRUCTIONS = "DevsMind is this team's persistent shared code memory \u2014 not a personal tool you reach for only when asked to search something. Every teammate's AI agent, in every session, reads from the SAME graph you are about to write to. There is no \"your copy.\"\n\nIf you skip recording a change, you are not skipping a formality. You are leaving the whole team's graph stale for every other AI agent that queries this code later \u2014 tomorrow, on a different task, in a different session. And the reasoning behind your change (why it was made, what ticket drove it, what was broken before, what you tried and rejected) exists ONLY in this conversation, right now. It is not in the diff. It is not in the commit message. If it isn't captured at commit_changes this turn, it is gone forever \u2014 no reindex, no log, no git blame can recover it later.\n\nNon-negotiable workflow:\n1. Call start_session once, before your first WRITE of the conversation (edit_node/stage_change/commit_changes and the other mutating tools). It mints a session_id that every write REQUIRES \u2014 it ties a request's edits together on the local Activity log and makes them revertable as a unit \u2014 and every response echoes it back so it stays in front of you, including after a context compaction. Read-only tools (search_nodes, get_node_code, list_nodes, and the other getters) do NOT need it: search and read freely from the very first call. Never invent a session_id yourself; if a write errors saying session_id is required, start_session was skipped \u2014 call it now, then retry. If you are resuming a conversation that already called start_session earlier (visible in the reloaded history), reuse that same session_id instead of starting a new one.\n2. Before any filesystem search, grep, or file read: call search_nodes FIRST \u2014 it is now the one call for both \"find this node\" AND \"find where X lives across files\", so you should not need an external grep. Two inputs, pass either or both: a natural-language query (a real phrase \u2014 drives meaning-matching, so \"authentication\" finds a node described only as \"sign-in\") and/or pattern, a REAL regex used exactly as you'd give it to grep (e.g. \"heartRed|onLikeTap|item.liked\" \u2014 nothing is re-escaped or split for you). Pattern-only is a precision mode: exact grep + code-body matches, no semantic blur. It returns two buckets: nodes (the indexed graph \u2014 the primary answer for \"which function/class\", with a true nodes_total before the top-20 cap) and files (a real grep of every repo, or just the path scope if given \u2014 the answer for things the graph does not index: CSS, JSON, config, .env, markup, wiring like \"where is CORS configured\" or \"what mounts this middleware\" \u2014 each sample line reports which function/class it falls inside, and files_total tells you honestly whether there's more than the page shown; pass a bigger offset for the next page). Triage by each node's confidence and relevance, NOT by which name looks right to you \u2014 confidence reflects how many independent layers corroborated the hit, which your own reading of a name cannot. Lockfiles and build artifacts are excluded by default, so what comes back is real source. If the response carries a compacted field, it was trimmed to fit and says exactly what was dropped \u2014 all counts stay exact, and compact:false gets you the untrimmed payload. It only returns real evidence \u2014 genuinely-absent things come back empty with a hint; if so, retry once with a different pattern/query before concluding it is not there. Only drop to a manual grep/read if search_nodes itself says truncated, or you need full file context after it points you at the file.\n3. To read one function/class: call get_node_code instead of opening the file, and do not follow it with a file read for context \u2014 this is the ONE node-read call, not a lean summary. It already includes the file's imports, the node's own name/type/signature/description, up to 20 named callers AND callees per direction (with exact uses/used_by counts even when the lists are capped), and up to 40 other declarations from the same file (file_outline \u2014 this is how you tell \"was this renamed?\" or \"what else lives here\" without opening the file). Reach further in the SAME call instead of a second tool: graph_depth + graph_direction walks the transitive graph past the direct neighbors already included (add graph_code:true for a whole call flow's source in one round trip \u2014 if some nodes' code doesn't fit the budget they are named in graph.code_omitted_node_ids, so fetch exactly those rather than re-running blind), and history:\"full\" returns every revision with diffable edits, pageable with history_limit/history_offset. Every capped section is honest about it (*_truncated, *_hint) \u2014 a hint means more is reachable in this same call, not a dead end.\n4. Before touching any function's signature: get_node_code already includes its direct callers by name (used_by_nodes) \u2014 for the FULL transitive blast radius, pass graph_direction:\"in\" with a graph_depth of 2-3 in that same call. Git shows you what changed; it never shows you what depends on it. Find out before you break something, not after.\n5. Before refactoring: get_node_code already includes the last 3 changes' reasoning by default \u2014 for the full revision trail with diffable before/after edits, pass history:\"full\" in that same call. Git blame tells you who and when; it never tells you why. The actual decision context only exists here.\n6. Write EVERY file with edit_node \u2014 .ts, .vue, .css, .json, .xml, .md, anything \u2014 and never your editor's own edit/write tools. It takes file_path + old_string + new_string exactly like an ordinary edit tool and never refuses a file type; to create a file that doesn't exist yet, pass old_string: \"\" and the whole file as new_string. Because it knows where your text landed, it works out which function/class you changed automatically: no node_id to look up, no code_snapshot to send back, and no stage_change call. It answers with every caller of what you changed. Writes landing outside any function (markup, config, an import) get no graph node \u2014 normal and expected, not a failure \u2014 but the whole-file change is still staged for the local activity log, so commit_changes makes it revertable there like any other edit.\n7. stage_change is now only for what no parser can read: a language with no AST support (.py, .go, .java, .cs, .rb, .php, .rs, .swift, .kt, .dart). edit_node still writes those files, and its response tells you when it couldn't trace one \u2014 so never guess. One call per node, not per file, never batched for later. On a long task, call commit_changes at natural checkpoints too (not only once at the very end) \u2014 waiting until the whole task is \"done\" is how staged work gets left uncommitted when a session runs long.\n8. Scope: the graph is source code only (functions/classes/logic). stage_change will be REJECTED for stylesheets, markup, JSON/config, docs, images, or any other non-code asset. Do not stage those files \u2014 they have no callers/callees to resolve and only bloat the graph.\n9. commit_changes REQUIRES a message AND a reasoning \u2014 the call fails without either. message is the user's request, verbatim, that led to this commit; it builds a local, private, never-pushed activity log (devsmind view \u2192 Activity) grouping your work by request and letting the user revert a request as a whole. Pass the exact same text again on a later commit that's still answering the same request \u2014 that merges them into one entry instead of splitting it. reasoning (what_changed/why/goal) is ONE object covering everything staged since the last commit \u2014 a commit is one logical change, so it gets one why, recorded against every node it touches, not one per edit_node/stage_change call.\n10. commit_changes also REFUSES any batch containing a brand-NEW node with no description \u2014 a description is what makes that node findable later by a natural-language search_nodes query instead of only by its exact identifier. If edit_node or stage_change just created a node, call add_description with it (1-3 sentences of what it does and the domain concepts involved \u2014 never a restatement of the name) before commit_changes will accept it. Nothing staged is lost by the refusal; retry the same commit_changes call once it's described. Existing nodes are never gated by this \u2014 only ones new this commit.\n11. A workflow is a named log of how ONE piece of functionality grew, across many sessions \u2014 read it to learn how the code got this way. start_session tells you if there is a recent one worth continuing; otherwise, when starting work that might belong to an existing multi-session feature, call workflow_list. If a description matches, ask the user before continuing it, then workflow_bind to attach THIS session. Binding is local to you: it never moves, pauses, or steals anyone else's workflow, and two sessions can work different ones at the same time.\n12. Once bound, commit_changes logs a step for you automatically \u2014 you do NOT need workflow_add_step for ordinary code work. Call it for the thing a commit cannot express: a DECISION OR RESEARCH FINDING THAT CHANGED NO CODE (\"evaluated X, rejected it because Y\"), attaching the docs behind it via doc_paths. That is the one kind of knowledge nothing else keeps \u2014 git has the diff, history has the per-node reasoning, but neither records what was considered and rejected. If you did work while unbound, or on the wrong workflow, workflow_sync attaches it afterwards from your local activity log: it previews first and only writes when you pass confirm:true, so nothing has to be got right in the moment.\n13. commit_changes also REQUIRES a feedback object (5 fields) \u2014 this is the only channel that improves DevsMind over time, so answer it for real, not as a formality. Before writing \"none\" on any field, actually check: did anything in THIS task take an extra tool call, a guess, a re-read, or a wrong turn? There almost always is something, even on an easy task \u2014 a specific one-line answer with evidence (file:line) is far more useful than a reflexive \"none\". \"none\" is correct only when you genuinely paid attention and nothing applies. Noticed something worth reporting but aren't committing right now (or don't want to wait until you are)? Call add_feedback directly \u2014 same 5 categories, but any one or more, nothing required, no commit needed. Passing evidence (file + snippet) on a graph_problem/edge_problem gets it verified fresh at call time and marked confirmed instead of suspected.";
13
+ /** Binds this process to one project's `.devmind` dir. Called once at server startup. */
14
+ export declare function bindDevmindPath(devmindPath: string): void;
15
+ /** The bound project path, or null if this server is running unbound (tests / legacy). */
16
+ export declare function getBoundDevmindPath(): string | null;
11
17
  /**
12
- * Start DevsMind as an HTTP MCP server on port 4500.
13
- * IDEs connect via: http://localhost:4500/mcp
14
- *
15
- * Port mnemonic: devs→45 (D=4,E=5) + mind→13 (M=13) = 4513
18
+ * Closes every cached DB connection (best-effort) and clears the cache. Normally only reached via
19
+ * the SIGINT/SIGTERM shutdown handlers below; exported so tests can release a fixture's cached
20
+ * connection between cases instead of leaking a locked `brain.db` handle until the test process exits.
16
21
  */
17
- export declare function runHttpMcpServer(port?: number): Promise<void>;
22
+ export declare function cleanup(): void;
23
+ /**
24
+ * Creates and wires up a DevsMind MCP Server instance.
25
+ * When the process is bound to one project (`bindDevmindPath`, the normal `devsmind start` path),
26
+ * every tool serves that brain and no `devmind_path` arg is required or advertised. Unbound (the
27
+ * in-process test path, or a server started with no brain to auto-detect), it falls back to the
28
+ * legacy behavior: each call carries `devmind_path` and opens the db from there.
29
+ * Exported so tests can drive tools in-process (e.g. via an InMemoryTransport pair) without
30
+ * binding a real port.
31
+ */
32
+ export declare function createMcpServer(): Server;
33
+ /**
34
+ * Builds the Express app (view UI + activity/revert APIs + the stateless /mcp endpoint) without
35
+ * binding a port. Exported so tests can drive it in-process via supertest; `runHttpMcpServer`
36
+ * below is the only caller that actually `listen()`s on it.
37
+ */
38
+ export declare function createHttpApp(port?: number): express.Application;
39
+ export declare function runHttpMcpServer(port?: number, devmindPath?: string): Promise<void>;
18
40
  /**
19
41
  * Start DevsMind as a stdio MCP server.
20
42
  * Used when an IDE manages the process directly (e.g. Cursor stdio plugin mode).
21
43
  */
22
- export declare function runStdioMcpServer(): void;
44
+ export declare function runStdioMcpServer(devmindPath?: string): void;
23
45
  /** @deprecated Use runHttpMcpServer() or runStdioMcpServer() directly */
24
46
  export declare function runMcpServer(): void;