@mmnto/mcp 1.12.0 → 1.14.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/dist/context.d.ts +58 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +220 -6
- package/dist/context.js.map +1 -1
- package/dist/context.test.js +108 -2
- package/dist/context.test.js.map +1 -1
- package/dist/smoke-test.d.ts +2 -0
- package/dist/smoke-test.d.ts.map +1 -0
- package/dist/smoke-test.js +196 -0
- package/dist/smoke-test.js.map +1 -0
- package/dist/tools/search-knowledge.d.ts +6 -0
- package/dist/tools/search-knowledge.d.ts.map +1 -1
- package/dist/tools/search-knowledge.js +493 -40
- package/dist/tools/search-knowledge.js.map +1 -1
- package/dist/tools/search-knowledge.test.js +901 -56
- package/dist/tools/search-knowledge.test.js.map +1 -1
- package/package.json +2 -2
package/dist/context.d.ts
CHANGED
|
@@ -5,11 +5,69 @@ export interface ServerContext {
|
|
|
5
5
|
config: TotemConfig;
|
|
6
6
|
store: LanceStore;
|
|
7
7
|
embedder: Embedder;
|
|
8
|
+
/**
|
|
9
|
+
* Linked Totem indexes keyed by their derived link name (mmnto/totem#1294
|
|
10
|
+
* Cross-Repo Context Mesh, Phase 2). The name is computed from the
|
|
11
|
+
* basename of the resolved linked path with any leading dot stripped
|
|
12
|
+
* (e.g. `.strategy` → `'strategy'`, `../totem-playground` → `'totem-playground'`).
|
|
13
|
+
*
|
|
14
|
+
* Populated during `initContext()` from `config.linkedIndexes`. Each entry
|
|
15
|
+
* is a LanceStore constructed with a `sourceContext` that tags every
|
|
16
|
+
* result with its source repo + absolute path. Empty when no linked
|
|
17
|
+
* indexes are configured or when every linked index failed to initialize.
|
|
18
|
+
*
|
|
19
|
+
* Used by `search_knowledge` for boundary routing:
|
|
20
|
+
* - `boundary === '<link-name>'` → route only to that linked store
|
|
21
|
+
* - `boundary === undefined` → federated search across primary + all linked
|
|
22
|
+
*/
|
|
23
|
+
linkedStores: Map<string, LanceStore>;
|
|
24
|
+
/**
|
|
25
|
+
* Per-link initialization errors captured during `initContext()` for the
|
|
26
|
+
* first-query-warn-block pattern (mmnto/totem#1294 Phase 2). When a
|
|
27
|
+
* linked index fails to initialize — missing directory, broken config,
|
|
28
|
+
* dimension mismatch, name collision — the error is stored here keyed
|
|
29
|
+
* by the intended link name. The first `search_knowledge` call after
|
|
30
|
+
* server startup surfaces these as a system warning so the agent sees
|
|
31
|
+
* the failure in-context. The server does NOT crash on any of these
|
|
32
|
+
* failures — that would destroy the agent's access to local tools.
|
|
33
|
+
*/
|
|
34
|
+
linkedStoreInitErrors: Map<string, string>;
|
|
8
35
|
}
|
|
9
36
|
/**
|
|
10
37
|
* Re-open the cached LanceStore connection after a full sync rebuild.
|
|
11
38
|
* No-op if the context hasn't been initialized yet.
|
|
39
|
+
*
|
|
40
|
+
* mmnto/totem#1294 Phase 2: also reconnects every linked store. Without
|
|
41
|
+
* this, a `totem sync` in a linked repo would invalidate that repo's
|
|
42
|
+
* LanceDB table handle, and subsequent federated queries would silently
|
|
43
|
+
* drop that repo's results (or fail explicit-boundary queries) until the
|
|
44
|
+
* MCP server was restarted.
|
|
45
|
+
*
|
|
46
|
+
* mmnto/totem#1295 GCA HIGH: per-link reconnect failures are best-effort
|
|
47
|
+
* and DO NOT mutate `linkedStores`. Earlier revisions evicted broken
|
|
48
|
+
* stores from the active map on reconnect failure, but that caused two
|
|
49
|
+
* problems: (1) transient issues (temporary file lock during a parallel
|
|
50
|
+
* sync) would cause permanent context loss until server restart, and
|
|
51
|
+
* (2) a subsequent fix in the linked repo couldn't be picked up without
|
|
52
|
+
* restart. The current behavior: record the error for the first-query
|
|
53
|
+
* warning path, leave the store in `linkedStores`, and let the next
|
|
54
|
+
* `search_knowledge` call attempt a targeted reconnect again via
|
|
55
|
+
* `federatedSearch`. Trades some log spam for resilience — the correct
|
|
56
|
+
* Tenet 4 tradeoff per the bot review on PR mmnto/totem#1295.
|
|
12
57
|
*/
|
|
58
|
+
/**
|
|
59
|
+
* Pure reconnect logic — takes a `ServerContext` explicitly so it can be
|
|
60
|
+
* unit-tested without standing up the full `initContext` pipeline.
|
|
61
|
+
*
|
|
62
|
+
* Reconnects the primary store first, then iterates every linked store
|
|
63
|
+
* and reconnects each. Linked-store reconnect failures are intentionally
|
|
64
|
+
* silent here — see the comment in `reconnectStore` below for the full
|
|
65
|
+
* Tenet 4 reasoning.
|
|
66
|
+
*
|
|
67
|
+
* Exported with an underscore prefix to mark it as a test seam, not a
|
|
68
|
+
* public API. Production code should always use `reconnectStore()`.
|
|
69
|
+
*/
|
|
70
|
+
export declare function _reconnectOnContext(ctx: ServerContext): Promise<void>;
|
|
13
71
|
export declare function reconnectStore(): Promise<void>;
|
|
14
72
|
/**
|
|
15
73
|
* Load environment variables from .env file (does not override existing).
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAEL,UAAU,EAIX,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAEL,UAAU,EAIX,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB;;;;;;;;;;;;;;OAcG;IACH,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACtC;;;;;;;;;OASG;IACH,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAKD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2B3E;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAGpD;AAuBD;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAKzC;AA0ND;;;;;GAKG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CASzD"}
|
package/dist/context.js
CHANGED
|
@@ -7,12 +7,90 @@ let initPromise;
|
|
|
7
7
|
/**
|
|
8
8
|
* Re-open the cached LanceStore connection after a full sync rebuild.
|
|
9
9
|
* No-op if the context hasn't been initialized yet.
|
|
10
|
+
*
|
|
11
|
+
* mmnto/totem#1294 Phase 2: also reconnects every linked store. Without
|
|
12
|
+
* this, a `totem sync` in a linked repo would invalidate that repo's
|
|
13
|
+
* LanceDB table handle, and subsequent federated queries would silently
|
|
14
|
+
* drop that repo's results (or fail explicit-boundary queries) until the
|
|
15
|
+
* MCP server was restarted.
|
|
16
|
+
*
|
|
17
|
+
* mmnto/totem#1295 GCA HIGH: per-link reconnect failures are best-effort
|
|
18
|
+
* and DO NOT mutate `linkedStores`. Earlier revisions evicted broken
|
|
19
|
+
* stores from the active map on reconnect failure, but that caused two
|
|
20
|
+
* problems: (1) transient issues (temporary file lock during a parallel
|
|
21
|
+
* sync) would cause permanent context loss until server restart, and
|
|
22
|
+
* (2) a subsequent fix in the linked repo couldn't be picked up without
|
|
23
|
+
* restart. The current behavior: record the error for the first-query
|
|
24
|
+
* warning path, leave the store in `linkedStores`, and let the next
|
|
25
|
+
* `search_knowledge` call attempt a targeted reconnect again via
|
|
26
|
+
* `federatedSearch`. Trades some log spam for resilience — the correct
|
|
27
|
+
* Tenet 4 tradeoff per the bot review on PR mmnto/totem#1295.
|
|
10
28
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Pure reconnect logic — takes a `ServerContext` explicitly so it can be
|
|
31
|
+
* unit-tested without standing up the full `initContext` pipeline.
|
|
32
|
+
*
|
|
33
|
+
* Reconnects the primary store first, then iterates every linked store
|
|
34
|
+
* and reconnects each. Linked-store reconnect failures are intentionally
|
|
35
|
+
* silent here — see the comment in `reconnectStore` below for the full
|
|
36
|
+
* Tenet 4 reasoning.
|
|
37
|
+
*
|
|
38
|
+
* Exported with an underscore prefix to mark it as a test seam, not a
|
|
39
|
+
* public API. Production code should always use `reconnectStore()`.
|
|
40
|
+
*/
|
|
41
|
+
export async function _reconnectOnContext(ctx) {
|
|
42
|
+
await ctx.store.reconnect();
|
|
43
|
+
// mmnto/totem#1295 CR MAJOR: do NOT mutate `linkedStoreInitErrors` from
|
|
44
|
+
// here. That map holds INIT-time warnings (empty store, broken path,
|
|
45
|
+
// collision) which are static config issues that a runtime reconnect
|
|
46
|
+
// can't fix. Earlier revisions deleted entries on successful reconnect
|
|
47
|
+
// (suppressing the static warning) and OVERWROTE entries on failed
|
|
48
|
+
// reconnect (replacing the original diagnostic with a generic reconnect
|
|
49
|
+
// message). Both broke the `performSearch` Case 3 routing — a user
|
|
50
|
+
// querying `boundary: 'strategy'` after a reconnect cycle would either
|
|
51
|
+
// miss the empty-store warning entirely or see a misleading reconnect
|
|
52
|
+
// error instead of the original cause.
|
|
53
|
+
//
|
|
54
|
+
// Runtime failures on a per-query basis are surfaced via the per-query
|
|
55
|
+
// `runtimeFailures` map populated by `federatedSearch`. That path is
|
|
56
|
+
// the correct place for transient runtime state.
|
|
57
|
+
for (const [, linkedStore] of ctx.linkedStores.entries()) {
|
|
58
|
+
try {
|
|
59
|
+
await linkedStore.reconnect();
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Best-effort: a failed reconnect here is not actionable. The next
|
|
63
|
+
// query will hit the broken store via `federatedSearch`, fail, and
|
|
64
|
+
// surface a per-query runtime warning to the agent. We intentionally
|
|
65
|
+
// do NOT mutate global state — see the comment block above.
|
|
66
|
+
}
|
|
14
67
|
}
|
|
15
68
|
}
|
|
69
|
+
export async function reconnectStore() {
|
|
70
|
+
if (!cached)
|
|
71
|
+
return;
|
|
72
|
+
await _reconnectOnContext(cached);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Derive a stable link name from a linked-index path. Used for both the
|
|
76
|
+
* `ServerContext.linkedStores` map key and the `sourceRepo` tag stamped
|
|
77
|
+
* on every SearchResult from that store.
|
|
78
|
+
*
|
|
79
|
+
* Rule: take the basename of the resolved absolute path and strip any
|
|
80
|
+
* leading dot. Examples:
|
|
81
|
+
* `.strategy` → `strategy`
|
|
82
|
+
* `../totem-playground` → `totem-playground`
|
|
83
|
+
* `/abs/path/to/foo` → `foo`
|
|
84
|
+
*
|
|
85
|
+
* The leading-dot strip exists because the canonical submodule path in
|
|
86
|
+
* this project is `.strategy` (git submodule convention) and agents will
|
|
87
|
+
* want to pass `boundary: 'strategy'` without the dot.
|
|
88
|
+
*/
|
|
89
|
+
function deriveLinkName(linkedPath, cwd) {
|
|
90
|
+
const resolved = path.resolve(cwd, linkedPath);
|
|
91
|
+
const base = path.basename(resolved);
|
|
92
|
+
return base.replace(/^\./, '');
|
|
93
|
+
}
|
|
16
94
|
/**
|
|
17
95
|
* Load environment variables from .env file (does not override existing).
|
|
18
96
|
*/
|
|
@@ -33,7 +111,10 @@ async function loadConfig(configPath) {
|
|
|
33
111
|
return TotemConfigSchema.parse(raw);
|
|
34
112
|
}
|
|
35
113
|
/**
|
|
36
|
-
* Perform one-time initialization: load config, create embedder and store
|
|
114
|
+
* Perform one-time initialization: load config, create embedder and store,
|
|
115
|
+
* and wire up any linked indexes for the Cross-Repo Context Mesh
|
|
116
|
+
* (mmnto/totem#1294 Phase 2).
|
|
117
|
+
*
|
|
37
118
|
* Sets the module-level `cached` variable and returns the context.
|
|
38
119
|
*/
|
|
39
120
|
async function initContext() {
|
|
@@ -47,9 +128,142 @@ async function initContext() {
|
|
|
47
128
|
const embedding = requireEmbedding(config);
|
|
48
129
|
const embedder = createEmbedder(embedding);
|
|
49
130
|
const storePath = path.join(projectRoot, config.lanceDir);
|
|
50
|
-
|
|
131
|
+
// Primary store gets its own SourceContext so `absoluteFilePath` is
|
|
132
|
+
// populated on every local result. `sourceRepo` stays undefined —
|
|
133
|
+
// primary hits don't carry a source tag.
|
|
134
|
+
const store = new LanceStore(storePath, embedder, { absolutePathRoot: projectRoot });
|
|
51
135
|
await store.connect();
|
|
52
|
-
|
|
136
|
+
// ─── Linked index initialization (mmnto/totem#1294 Phase 2 + #1295 fixes) ──
|
|
137
|
+
//
|
|
138
|
+
// For every path in `config.linkedIndexes`, attempt to:
|
|
139
|
+
// 1. Derive a stable link name via basename + leading-dot strip
|
|
140
|
+
// 2. Detect and reject name collisions (2+ links resolving to the same name)
|
|
141
|
+
// 3. Load the linked repo's .env (may contain provider API keys)
|
|
142
|
+
// 4. Resolve the linked directory, load its config
|
|
143
|
+
// 5. Validate embedder provider/model AND dimensions match primary
|
|
144
|
+
// 6. Construct a LanceStore with sourceContext tagged for federation
|
|
145
|
+
// 7. Connect it
|
|
146
|
+
// 8. Empty stores: add to linkedStores AND record warning (NOT fatal —
|
|
147
|
+
// a subsequent `totem sync` in the linked repo can populate it
|
|
148
|
+
// without requiring an MCP server restart)
|
|
149
|
+
//
|
|
150
|
+
// Any initialization failure is captured into `linkedStoreInitErrors`
|
|
151
|
+
// keyed by the link name and surfaced on the first `search_knowledge`
|
|
152
|
+
// call. The server itself does NOT crash on any linked-store failure —
|
|
153
|
+
// that would tear down local tools too and produce a worse user
|
|
154
|
+
// experience than missing context. Runtime search failures use a
|
|
155
|
+
// separate per-query warning path (see `search-knowledge.ts`).
|
|
156
|
+
const linkedStores = new Map();
|
|
157
|
+
const linkedStoreInitErrors = new Map();
|
|
158
|
+
for (const linkedPath of config.linkedIndexes ?? []) {
|
|
159
|
+
const name = deriveLinkName(linkedPath, projectRoot);
|
|
160
|
+
// Collision detection — the first-wins so downstream lookups are stable.
|
|
161
|
+
//
|
|
162
|
+
// Key the error under the BARE `name`, not a descriptive composite, so
|
|
163
|
+
// `performSearch` Case 3 (`linkedStoreInitErrors.has(boundary)`) can
|
|
164
|
+
// resolve a user-supplied boundary to the collision message instead of
|
|
165
|
+
// silently falling through to raw-prefix search on the primary.
|
|
166
|
+
// mmnto/totem#1295 GCA HIGH — maintain the original identifier
|
|
167
|
+
// throughout the pipeline.
|
|
168
|
+
//
|
|
169
|
+
// If the bare name is already in errors (because the first iteration
|
|
170
|
+
// failed for an unrelated reason), append the collision note rather
|
|
171
|
+
// than overwrite — both pieces of information matter to the operator.
|
|
172
|
+
if (linkedStores.has(name) || linkedStoreInitErrors.has(name)) {
|
|
173
|
+
const collisionNote = `Path "${linkedPath}" also derives the link name "${name}". ` +
|
|
174
|
+
`Rename one of the linked directories or remove the duplicate from config.linkedIndexes.`;
|
|
175
|
+
const existing = linkedStoreInitErrors.get(name);
|
|
176
|
+
linkedStoreInitErrors.set(name, existing
|
|
177
|
+
? `${existing}\n COLLISION: ${collisionNote}`
|
|
178
|
+
: `Another linked index already claims the name "${name}". ${collisionNote}`);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
const resolvedPath = path.resolve(projectRoot, linkedPath);
|
|
183
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
184
|
+
throw new TotemConfigError(`Linked index path does not exist: ${resolvedPath}`, 'Check that the path is correct, and that the linked repository is cloned or the submodule is initialized.', 'CONFIG_MISSING');
|
|
185
|
+
}
|
|
186
|
+
const linkedConfigPath = path.join(resolvedPath, 'totem.config.ts');
|
|
187
|
+
if (!fs.existsSync(linkedConfigPath)) {
|
|
188
|
+
throw new TotemConfigError(`Linked index has no totem.config.ts: ${linkedConfigPath}`, "The linked directory must be a Totem-managed project. Run 'totem init' in that directory, or remove it from linkedIndexes.", 'CONFIG_MISSING');
|
|
189
|
+
}
|
|
190
|
+
// mmnto/totem#1295 GCA HIGH: linked repos may have their own `.env`
|
|
191
|
+
// files containing embedder API keys. Load them BEFORE evaluating
|
|
192
|
+
// the linked config — `loadEnv` uses `dotenv` without override, so
|
|
193
|
+
// primary env vars stay authoritative when they overlap.
|
|
194
|
+
//
|
|
195
|
+
// SAFETY INVARIANT (mmnto/totem#1295 GCA HIGH #2): `loadEnv` mutates
|
|
196
|
+
// the GLOBAL `process.env`, not a per-repo scope. Node.js does not
|
|
197
|
+
// provide isolated env per module. Consequences:
|
|
198
|
+
//
|
|
199
|
+
// 1. Primary `.env` keys remain authoritative (dotenv `override:
|
|
200
|
+
// false`), so primary always wins on key collision.
|
|
201
|
+
// 2. If two LINKED repos define the same key (and primary doesn't),
|
|
202
|
+
// the FIRST linked repo in `config.linkedIndexes` order wins.
|
|
203
|
+
// Subsequent linked repos' values are silently dropped.
|
|
204
|
+
// 3. The merged env is visible to ALL subsequent code in this
|
|
205
|
+
// process — including primary code that runs after init.
|
|
206
|
+
//
|
|
207
|
+
// For now this is acceptable because (a) the typical mesh has 1
|
|
208
|
+
// linked repo, (b) embedder API keys are usually identical across
|
|
209
|
+
// sibling repos in a workspace, and (c) the deterministic ordering
|
|
210
|
+
// (config order) is documented behavior. If this becomes a footgun,
|
|
211
|
+
// file a follow-up to scope env loading per linked-config evaluation
|
|
212
|
+
// (e.g., snapshot/restore process.env around `loadConfig`).
|
|
213
|
+
loadEnv(resolvedPath);
|
|
214
|
+
const linkedConfig = await loadConfig(linkedConfigPath);
|
|
215
|
+
if (!linkedConfig.embedding) {
|
|
216
|
+
throw new TotemConfigError(`Linked index at ${resolvedPath} has no embedding provider configured.`, 'Cross-repo search requires the linked index to have the same embedder as the primary repo. Add an `embedding` block to the linked totem.config.ts.', 'CONFIG_MISSING');
|
|
217
|
+
}
|
|
218
|
+
// Validate the linked embedder matches the primary embedder
|
|
219
|
+
// provider and model. Different providers produce incompatible
|
|
220
|
+
// vector spaces (Tenet 7 / ADR-068 — version-pin, don't hand-wave).
|
|
221
|
+
if (linkedConfig.embedding.provider !== embedding.provider ||
|
|
222
|
+
linkedConfig.embedding.model !== embedding.model) {
|
|
223
|
+
throw new TotemConfigError(`Linked index embedder mismatch: primary uses ${embedding.provider}/${embedding.model ?? 'default'}, linked uses ${linkedConfig.embedding.provider}/${linkedConfig.embedding.model ?? 'default'}.`, 'Cross-repo semantic search requires the same embedder on both sides. Rebuild the linked index with the primary embedder, or remove the link from config.linkedIndexes.', 'CONFIG_INVALID');
|
|
224
|
+
}
|
|
225
|
+
const linkedEmbedder = createEmbedder(linkedConfig.embedding);
|
|
226
|
+
// mmnto/totem#1295 CR MAJOR: provider + model match is not
|
|
227
|
+
// sufficient. The same embedder can be instantiated with different
|
|
228
|
+
// output dimensions (config `dimensions` override). Cross-repo
|
|
229
|
+
// federation across mismatched dimensions would merge scores from
|
|
230
|
+
// incompatible vector spaces as if they were comparable. Validate
|
|
231
|
+
// the resolved dimensions after construction.
|
|
232
|
+
if (linkedEmbedder.dimensions !== embedder.dimensions) {
|
|
233
|
+
throw new TotemConfigError(`Linked index embedder dimension mismatch: primary produces ${embedder.dimensions}-dim vectors, linked at ${resolvedPath} produces ${linkedEmbedder.dimensions}-dim. Federation would merge scores from incompatible vector spaces.`, "Align the linked repo embedder dimensions with the primary by updating the linked repo's totem.config.ts embedding.dimensions field, then rebuild the linked index via `totem sync --full` in that repo.", 'CONFIG_INVALID');
|
|
234
|
+
}
|
|
235
|
+
const linkedLanceDir = path.join(resolvedPath, linkedConfig.lanceDir);
|
|
236
|
+
const linkedStore = new LanceStore(linkedLanceDir, linkedEmbedder, {
|
|
237
|
+
sourceRepo: name,
|
|
238
|
+
absolutePathRoot: resolvedPath,
|
|
239
|
+
});
|
|
240
|
+
await linkedStore.connect();
|
|
241
|
+
// mmnto/totem#1295 GCA HIGH: empty linked stores are NOT fatal.
|
|
242
|
+
// A subsequent `totem sync` in the linked repo can populate it
|
|
243
|
+
// without requiring an MCP server restart. Add the store to the
|
|
244
|
+
// active map but also record a warning so the first query surfaces
|
|
245
|
+
// the "run totem sync" hint. (Maps are not mutually exclusive — a
|
|
246
|
+
// store can be in BOTH linkedStores AND linkedStoreInitErrors if
|
|
247
|
+
// it's queryable but has a non-fatal issue like being empty.)
|
|
248
|
+
linkedStores.set(name, linkedStore);
|
|
249
|
+
const rowCount = await linkedStore.count();
|
|
250
|
+
if (rowCount === 0) {
|
|
251
|
+
linkedStoreInitErrors.set(name, `Linked index at ${resolvedPath} is empty (0 rows). Federated queries will return no hits from this repo until you run 'totem sync' in that directory.`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
catch (err) {
|
|
255
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
256
|
+
linkedStoreInitErrors.set(name, msg);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
cached = {
|
|
260
|
+
projectRoot,
|
|
261
|
+
config,
|
|
262
|
+
store,
|
|
263
|
+
embedder,
|
|
264
|
+
linkedStores,
|
|
265
|
+
linkedStoreInitErrors,
|
|
266
|
+
};
|
|
53
267
|
return cached;
|
|
54
268
|
}
|
|
55
269
|
/**
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,OAAO,EACL,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/dist/context.test.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as os from 'node:os';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
5
|
-
import { loadEnv } from './context.js';
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
+
import { _reconnectOnContext, loadEnv } from './context.js';
|
|
6
6
|
describe('loadEnv', () => {
|
|
7
7
|
let tmpDir;
|
|
8
8
|
const injectedKeys = [];
|
|
@@ -66,4 +66,110 @@ describe('loadEnv', () => {
|
|
|
66
66
|
expect(process.env[key]).toBe('original');
|
|
67
67
|
});
|
|
68
68
|
});
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// _reconnectOnContext (mmnto/totem#1295 CR MAJOR fix)
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
describe('_reconnectOnContext', () => {
|
|
73
|
+
/**
|
|
74
|
+
* Build a minimal `ServerContext` with stub LanceStores. Cast through
|
|
75
|
+
* `unknown` to satisfy the structural type — production stores have
|
|
76
|
+
* many more methods, but the reconnect path only touches `.reconnect()`.
|
|
77
|
+
*/
|
|
78
|
+
function makeStubContext(opts) {
|
|
79
|
+
const linkedStoresMap = new Map();
|
|
80
|
+
for (const { name, reconnect } of opts.linkedStores) {
|
|
81
|
+
linkedStoresMap.set(name, { reconnect });
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
projectRoot: '/fake',
|
|
85
|
+
config: {},
|
|
86
|
+
store: { reconnect: opts.primaryReconnect },
|
|
87
|
+
embedder: {},
|
|
88
|
+
linkedStores: linkedStoresMap,
|
|
89
|
+
linkedStoreInitErrors: new Map(opts.initErrors),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
it('preserves init-time warnings when linked stores reconnect successfully', async () => {
|
|
93
|
+
// CR MAJOR catch: earlier code DELETED entries from
|
|
94
|
+
// linkedStoreInitErrors on successful reconnect, suppressing static
|
|
95
|
+
// warnings (e.g., empty store) that a runtime reconnect can't fix.
|
|
96
|
+
// After the fix, init warnings must survive any reconnect cycle.
|
|
97
|
+
const linkedReconnect = vi.fn(async () => { });
|
|
98
|
+
const ctx = makeStubContext({
|
|
99
|
+
primaryReconnect: vi.fn(async () => { }),
|
|
100
|
+
linkedStores: [{ name: 'strategy', reconnect: linkedReconnect }],
|
|
101
|
+
initErrors: [['strategy', 'Linked index is empty (0 rows).']],
|
|
102
|
+
});
|
|
103
|
+
await _reconnectOnContext(ctx);
|
|
104
|
+
// Linked store reconnect was called (Shield AI catch — also covered
|
|
105
|
+
// by the search-knowledge integration test, but asserted here too).
|
|
106
|
+
expect(linkedReconnect).toHaveBeenCalledOnce();
|
|
107
|
+
// Init warning is UNCHANGED — the reconnect did not delete or mutate it.
|
|
108
|
+
expect(ctx.linkedStoreInitErrors.get('strategy')).toBe('Linked index is empty (0 rows).');
|
|
109
|
+
expect(ctx.linkedStoreInitErrors.size).toBe(1);
|
|
110
|
+
});
|
|
111
|
+
it('preserves init-time warnings when linked store reconnect throws', async () => {
|
|
112
|
+
// CR MAJOR catch: earlier code OVERWROTE entries with
|
|
113
|
+
// "Reconnect after primary retry failed: <msg>" on reconnect failure,
|
|
114
|
+
// replacing the original diagnostic with a less useful generic message.
|
|
115
|
+
// After the fix, init warnings survive reconnect failures untouched.
|
|
116
|
+
const linkedReconnect = vi.fn(async () => {
|
|
117
|
+
throw new Error('Stale handle');
|
|
118
|
+
});
|
|
119
|
+
const ctx = makeStubContext({
|
|
120
|
+
primaryReconnect: vi.fn(async () => { }),
|
|
121
|
+
linkedStores: [{ name: 'strategy', reconnect: linkedReconnect }],
|
|
122
|
+
initErrors: [['strategy', 'Linked index is empty (0 rows).']],
|
|
123
|
+
});
|
|
124
|
+
await _reconnectOnContext(ctx);
|
|
125
|
+
expect(linkedReconnect).toHaveBeenCalledOnce();
|
|
126
|
+
// The original empty-store warning is unchanged. Crucially, it has
|
|
127
|
+
// NOT been overwritten with a "Reconnect after primary retry failed"
|
|
128
|
+
// message — that would lose the original diagnostic and break Case 3
|
|
129
|
+
// routing in performSearch.
|
|
130
|
+
expect(ctx.linkedStoreInitErrors.get('strategy')).toBe('Linked index is empty (0 rows).');
|
|
131
|
+
expect(ctx.linkedStoreInitErrors.size).toBe(1);
|
|
132
|
+
});
|
|
133
|
+
it('does not add new entries to linkedStoreInitErrors on reconnect failure', async () => {
|
|
134
|
+
// Even when there was NO init error (clean startup), a runtime
|
|
135
|
+
// reconnect failure must not introduce one. The per-query runtime
|
|
136
|
+
// warning path (`runtimeFailures`) is the correct surface for
|
|
137
|
+
// transient runtime state, not the init-error map.
|
|
138
|
+
const linkedReconnect = vi.fn(async () => {
|
|
139
|
+
throw new Error('Transient lock');
|
|
140
|
+
});
|
|
141
|
+
const ctx = makeStubContext({
|
|
142
|
+
primaryReconnect: vi.fn(async () => { }),
|
|
143
|
+
linkedStores: [{ name: 'strategy', reconnect: linkedReconnect }],
|
|
144
|
+
initErrors: [],
|
|
145
|
+
});
|
|
146
|
+
await _reconnectOnContext(ctx);
|
|
147
|
+
expect(linkedReconnect).toHaveBeenCalledOnce();
|
|
148
|
+
expect(ctx.linkedStoreInitErrors.size).toBe(0);
|
|
149
|
+
});
|
|
150
|
+
it('reconnects every linked store even if one in the middle throws', async () => {
|
|
151
|
+
// Best-effort iteration: a single broken store does not stop the
|
|
152
|
+
// reconnect loop from touching the others. Crucial for the multi-link
|
|
153
|
+
// mesh — one stale handle should not prevent the rest from refreshing.
|
|
154
|
+
const okA = vi.fn(async () => { });
|
|
155
|
+
const broken = vi.fn(async () => {
|
|
156
|
+
throw new Error('boom');
|
|
157
|
+
});
|
|
158
|
+
const okB = vi.fn(async () => { });
|
|
159
|
+
const ctx = makeStubContext({
|
|
160
|
+
primaryReconnect: vi.fn(async () => { }),
|
|
161
|
+
linkedStores: [
|
|
162
|
+
{ name: 'a', reconnect: okA },
|
|
163
|
+
{ name: 'broken', reconnect: broken },
|
|
164
|
+
{ name: 'b', reconnect: okB },
|
|
165
|
+
],
|
|
166
|
+
initErrors: [],
|
|
167
|
+
});
|
|
168
|
+
await _reconnectOnContext(ctx);
|
|
169
|
+
expect(okA).toHaveBeenCalledOnce();
|
|
170
|
+
expect(broken).toHaveBeenCalledOnce();
|
|
171
|
+
expect(okB).toHaveBeenCalledOnce();
|
|
172
|
+
expect(ctx.linkedStoreInitErrors.size).toBe(0);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
69
175
|
//# sourceMappingURL=context.test.js.map
|
package/dist/context.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.test.js","sourceRoot":"","sources":["../src/context.test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"context.test.js","sourceRoot":"","sources":["../src/context.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoke-test.d.ts","sourceRoot":"","sources":["../src/smoke-test.ts"],"names":[],"mappings":""}
|