pi-vault-mind 0.14.2 → 0.16.3

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 (164) hide show
  1. package/CHANGELOG.md +293 -0
  2. package/README.md +5 -5
  3. package/agents/broadcaster.agent.md +2 -2
  4. package/agents/heavy-lifter.agent.md +1 -1
  5. package/agents/main.agent.md +29 -0
  6. package/agents/manager.agent.md +1 -1
  7. package/agents/miner.agent.md +1 -1
  8. package/dist/packages/obsidian/src/client.js +331 -0
  9. package/dist/packages/obsidian/src/types.js +1 -0
  10. package/dist/src/activity.d.ts +49 -0
  11. package/dist/src/activity.js +175 -0
  12. package/dist/src/agent-bus/Agent.d.ts +9 -1
  13. package/dist/src/agent-bus/Agent.js +18 -2
  14. package/dist/src/agent-bus/index.d.ts +5 -5
  15. package/dist/src/agent-bus/index.js +1 -1
  16. package/dist/src/agent-queue.js +12 -3
  17. package/dist/src/agents/BroadcasterAgent.d.ts +1 -1
  18. package/dist/src/agents/BroadcasterAgent.js +2 -2
  19. package/dist/src/agents/HeavyLifterAgent.d.ts +1 -1
  20. package/dist/src/agents/HeavyLifterAgent.js +2 -2
  21. package/dist/src/agents/ManagerAgent.js +1 -1
  22. package/dist/src/agents/MinerAgent.d.ts +1 -1
  23. package/dist/src/agents/MinerAgent.js +2 -2
  24. package/dist/src/agents/index.d.ts +2 -2
  25. package/dist/src/agents/index.js +2 -2
  26. package/dist/src/auth.d.ts +17 -15
  27. package/dist/src/auth.js +26 -37
  28. package/dist/src/autosync.js +2 -2
  29. package/dist/src/commands.d.ts +2 -19
  30. package/dist/src/commands.js +301 -231
  31. package/dist/src/config-keys.d.ts +16 -0
  32. package/dist/src/config-keys.js +45 -0
  33. package/dist/src/discover-schema.js +4 -4
  34. package/dist/src/edits.d.ts +21 -0
  35. package/dist/src/edits.js +75 -0
  36. package/dist/src/embedding-probe.d.ts +34 -0
  37. package/dist/src/embedding-probe.js +142 -0
  38. package/dist/src/embedding-providers.d.ts +133 -0
  39. package/dist/src/embedding-providers.js +173 -0
  40. package/dist/src/embedding-secrets.d.ts +38 -0
  41. package/dist/src/embedding-secrets.js +291 -0
  42. package/dist/src/engine.d.ts +6 -0
  43. package/dist/src/engine.js +78 -6
  44. package/dist/src/events.js +7 -10
  45. package/dist/src/extension-packages.d.ts +9 -0
  46. package/dist/src/extension-packages.js +14 -0
  47. package/dist/src/git.d.ts +19 -0
  48. package/dist/src/git.js +78 -0
  49. package/dist/src/graph.d.ts +2 -1
  50. package/dist/src/graph.js +47 -13
  51. package/dist/src/identities-config.d.ts +6 -0
  52. package/dist/src/identities-config.js +39 -0
  53. package/dist/src/identity-injector.js +1 -1
  54. package/dist/src/index.js +9 -26
  55. package/dist/src/lance.d.ts +9 -0
  56. package/dist/src/lance.js +143 -203
  57. package/dist/src/modal-client.d.ts +16 -0
  58. package/dist/src/modal-client.js +16 -0
  59. package/dist/src/modal-config.d.ts +37 -14
  60. package/dist/src/modal-config.js +59 -32
  61. package/dist/src/model-router.d.ts +27 -0
  62. package/dist/src/model-router.js +67 -0
  63. package/dist/src/models.d.ts +42 -0
  64. package/dist/src/models.js +78 -0
  65. package/dist/src/personalize.js +17 -3
  66. package/dist/src/scaffold.d.ts +48 -0
  67. package/dist/src/scaffold.js +246 -0
  68. package/dist/src/server.d.ts +47 -4
  69. package/dist/src/server.js +988 -221
  70. package/dist/src/session-search.d.ts +63 -0
  71. package/dist/src/session-search.js +379 -0
  72. package/dist/src/settings-ui.d.ts +2 -2
  73. package/dist/src/settings-ui.js +76 -135
  74. package/dist/src/sync.d.ts +3 -3
  75. package/dist/src/sync.js +19 -15
  76. package/dist/src/tool-catalog.d.ts +18 -0
  77. package/dist/src/tool-catalog.js +232 -0
  78. package/dist/src/tools/marksman.js +1 -1
  79. package/dist/src/tools.js +111 -65
  80. package/dist/src/types.d.ts +127 -71
  81. package/dist/src/utils.d.ts +57 -6
  82. package/dist/src/utils.js +114 -28
  83. package/dist/src/vault-tools.d.ts +34 -0
  84. package/dist/src/vault-tools.js +99 -0
  85. package/dist/src/vault-writer.js +4 -1
  86. package/dist/src/vm-handlers.js +140 -43
  87. package/dist/src/watcher.js +9 -9
  88. package/dist/test/activity-tool.test.js +54 -0
  89. package/dist/test/agent-bus/Agent.test.js +174 -0
  90. package/dist/test/agent-bus/AgentLoader.test.js +180 -0
  91. package/dist/test/agent-bus/AgentRegistry.test.js +86 -0
  92. package/dist/test/agent-bus/LLMProvider.test.js +162 -0
  93. package/dist/test/agent-bus/TaskQueue.test.js +256 -0
  94. package/dist/test/agent-dispatch-context.test.js +73 -0
  95. package/dist/test/agent-queue.test.js +1 -1
  96. package/dist/test/agents/Agents.test.js +282 -0
  97. package/dist/test/auth.test.js +57 -56
  98. package/dist/test/bridge-identity.test.js +34 -3
  99. package/dist/test/classify-search-mode.test.js +51 -0
  100. package/dist/test/commands.test.js +410 -0
  101. package/dist/test/config-merge.test.js +98 -0
  102. package/dist/test/context-capture.test.js +56 -0
  103. package/dist/test/discover-schema.test.js +8 -5
  104. package/dist/test/dispatch.test.js +45 -91
  105. package/dist/test/edits.test.js +144 -0
  106. package/dist/test/embedding-probe.test.js +424 -0
  107. package/dist/test/embedding-providers.test.js +157 -0
  108. package/dist/test/embedding-secrets.test.js +210 -0
  109. package/dist/test/engine-identity.test.js +1 -1
  110. package/dist/test/events.test.js +675 -0
  111. package/dist/test/git-bridge.test.js +160 -0
  112. package/dist/test/graph.test.js +464 -0
  113. package/dist/test/helpers/server.js +81 -0
  114. package/dist/test/identity-injector.test.js +197 -0
  115. package/dist/test/index.test.js +5 -7
  116. package/dist/test/lance-modal.test.js +67 -2
  117. package/dist/test/lance.test.js +429 -0
  118. package/dist/test/modal-client.test.js +1 -1
  119. package/dist/test/modal-config.test.js +92 -79
  120. package/dist/test/model-readiness.test.js +122 -0
  121. package/dist/test/model-router.test.js +99 -0
  122. package/dist/test/obsidian-client.test.js +42 -0
  123. package/dist/test/personalize.test.js +1 -1
  124. package/dist/test/rest-models.test.js +153 -0
  125. package/dist/test/rest-queue.test.js +135 -87
  126. package/dist/test/rest-setup.test.js +625 -115
  127. package/dist/test/rest-vm.test.js +355 -94
  128. package/dist/test/server-cors.test.js +48 -0
  129. package/dist/test/server-ws.test.js +61 -34
  130. package/dist/test/session-crud.test.js +323 -0
  131. package/dist/test/session-search.test.js +139 -0
  132. package/dist/test/settings-ui.test.js +113 -4
  133. package/dist/test/sync.test.js +12 -12
  134. package/dist/test/tombstone.test.js +8 -10
  135. package/dist/test/tool-catalog.test.js +86 -0
  136. package/dist/test/utils.test.js +588 -0
  137. package/dist/test/vault-tools.test.js +103 -12
  138. package/dist/test/vault-writer.test.js +371 -0
  139. package/dist/test/vm-handlers.test.js +620 -0
  140. package/extension-packages.json +9 -0
  141. package/package.json +107 -90
  142. package/pi-vault-mind.config.example.json +24 -2
  143. package/scripts/check-deps.sh +35 -32
  144. package/scripts/cli-e2e.mjs +215 -0
  145. package/scripts/configuration-e2e.mjs +783 -0
  146. package/scripts/e2e-commands.mjs +391 -0
  147. package/scripts/e2e-ws.mjs +3 -2
  148. package/scripts/fetch-modal-token.sh +4 -3
  149. package/scripts/generate-config-keys-json.mjs +45 -0
  150. package/scripts/generate-extension-packages-json.mjs +55 -0
  151. package/scripts/pi-session-query +0 -0
  152. package/scripts/publish-obsidian-plugin.sh +0 -0
  153. package/scripts/reset-test-vault.sh +2 -2
  154. package/scripts/setup-test-config.sh +0 -0
  155. package/scripts/setup-vault-pi.sh +48 -9
  156. package/scripts/test-slash-commands.mjs +2 -2
  157. package/scripts/vault-pi.sh +12 -3
  158. package/skills/github-release-notes-file/SKILL.md +42 -0
  159. package/skills/obsidian-guided-test-session/SKILL.md +110 -0
  160. package/skills/obsidian-interactive-test/SKILL.md +88 -0
  161. package/skills/obsidian-plugin-publish/SKILL.md +58 -0
  162. package/skills/pi-vault-mind-release/SKILL.md +141 -0
  163. package/skills/pre-test-release/SKILL.md +116 -0
  164. package/dist/test/auto-indexer.test.js +0 -2
package/dist/src/graph.js CHANGED
@@ -1,5 +1,10 @@
1
- import { connect } from "./lance.js";
2
- const RELATION_TYPES = ["relates-to", "depends-on", "contradicts", "is-a", "part-of"];
1
+ import * as arrow from "apache-arrow";
2
+ import { connect, filterByVisibility } from "./lance.js";
3
+ function escapeWhereValue(value) {
4
+ const escaped = value.replace(/\\/g, "\\\\").replace(/'/g, "''");
5
+ return `'${escaped}'`;
6
+ }
7
+ const _RELATION_TYPES = ["relates-to", "depends-on", "contradicts", "is-a", "part-of"];
3
8
  const extractEntities = (fact) => {
4
9
  // Simple regex-based entity extraction as a lightweight alternative to LLM
5
10
  const entities = [];
@@ -92,7 +97,7 @@ export const graphUpsert = async (dataDir, cfg, entry) => {
92
97
  for (const entity of entities) {
93
98
  const existing = await entityTable
94
99
  .query()
95
- .where(`name = '${entity.name.replace(/'/g, "''")}'`)
100
+ .where(`name = ${escapeWhereValue(entity.name)}`)
96
101
  .limit(1)
97
102
  .toArray();
98
103
  if (existing.length === 0) {
@@ -143,12 +148,12 @@ export const graphUpsert = async (dataDir, cfg, entry) => {
143
148
  continue;
144
149
  const fromExisting = await entityTable
145
150
  .query()
146
- .where(`name = '${rel.from.replace(/'/g, "''")}'`)
151
+ .where(`name = ${escapeWhereValue(rel.from)}`)
147
152
  .limit(1)
148
153
  .toArray();
149
154
  const toExisting = await entityTable
150
155
  .query()
151
- .where(`name = '${rel.to.replace(/'/g, "''")}'`)
156
+ .where(`name = ${escapeWhereValue(rel.to)}`)
152
157
  .limit(1)
153
158
  .toArray();
154
159
  if (fromExisting.length === 0 || toExisting.length === 0)
@@ -169,14 +174,14 @@ export const graphUpsert = async (dataDir, cfg, entry) => {
169
174
  ]);
170
175
  }
171
176
  };
172
- export const queryGraph = async (dataDir, cfg, entityQuery, depth) => {
177
+ export const queryGraph = async (dataDir, cfg, entityQuery, depth, identity) => {
173
178
  const conn = await connect(dataDir);
174
179
  const entityTable = await getGraphTable(conn, dataDir, cfg, "entities");
175
180
  const relationTable = await getGraphTable(conn, dataDir, cfg, "relations");
176
181
  // Find seed entities
177
182
  const seedResults = await entityTable
178
183
  .query()
179
- .where(`name LIKE '%${entityQuery.replace(/'/g, "''")}%'`)
184
+ .where(`name LIKE ${escapeWhereValue(`%${entityQuery}%`)}`)
180
185
  .limit(5)
181
186
  .toArray();
182
187
  if (seedResults.length === 0) {
@@ -196,12 +201,12 @@ export const queryGraph = async (dataDir, cfg, entityQuery, depth) => {
196
201
  // Find relations where this entity is source or target
197
202
  const outgoing = await relationTable
198
203
  .query()
199
- .where(`from_entity_id = '${eid}'`)
204
+ .where(`from_entity_id = ${escapeWhereValue(eid)}`)
200
205
  .limit(20)
201
206
  .toArray();
202
207
  const incoming = await relationTable
203
208
  .query()
204
- .where(`to_entity_id = '${eid}'`)
209
+ .where(`to_entity_id = ${escapeWhereValue(eid)}`)
205
210
  .limit(20)
206
211
  .toArray();
207
212
  for (const rel of [...outgoing, ...incoming]) {
@@ -212,7 +217,7 @@ export const queryGraph = async (dataDir, cfg, entityQuery, depth) => {
212
217
  if (!visitedIds.has(otherId)) {
213
218
  const otherEntity = await entityTable
214
219
  .query()
215
- .where(`id = '${otherId}'`)
220
+ .where(`id = ${escapeWhereValue(otherId)}`)
216
221
  .limit(1)
217
222
  .toArray();
218
223
  if (otherEntity.length > 0) {
@@ -223,12 +228,41 @@ export const queryGraph = async (dataDir, cfg, entityQuery, depth) => {
223
228
  }
224
229
  frontier = nextFrontier;
225
230
  }
226
- return { entities: seedResults, relations: allRelations };
231
+ const filteredEntities = filterByVisibility(seedResults, identity);
232
+ const filteredRelations = filterByVisibility(allRelations, identity);
233
+ return { entities: filteredEntities, relations: filteredRelations };
227
234
  };
228
- async function getGraphTable(conn, _dataDir, cfg, name) {
235
+ function makeEntitySchema() {
236
+ return new arrow.Schema([
237
+ new arrow.Field("id", new arrow.Utf8(), true),
238
+ new arrow.Field("name", new arrow.Utf8(), true),
239
+ new arrow.Field("type", new arrow.Utf8(), true),
240
+ new arrow.Field("aliases", new arrow.Utf8(), true),
241
+ new arrow.Field("summary", new arrow.Utf8(), true),
242
+ new arrow.Field("collection_ids", new arrow.Utf8(), true),
243
+ new arrow.Field("created_at", new arrow.Utf8(), true),
244
+ new arrow.Field("updated_at", new arrow.Utf8(), true),
245
+ ]);
246
+ }
247
+ function makeRelationSchema() {
248
+ return new arrow.Schema([
249
+ new arrow.Field("id", new arrow.Utf8(), true),
250
+ new arrow.Field("from_entity_id", new arrow.Utf8(), true),
251
+ new arrow.Field("to_entity_id", new arrow.Utf8(), true),
252
+ new arrow.Field("relation_type", new arrow.Utf8(), true),
253
+ new arrow.Field("fact", new arrow.Utf8(), true),
254
+ new arrow.Field("fact_strength", new arrow.Float32(), true),
255
+ new arrow.Field("source_entry_ids", new arrow.Utf8(), true),
256
+ new arrow.Field("valid_at", new arrow.Utf8(), true),
257
+ new arrow.Field("expired_at", new arrow.Utf8(), true),
258
+ new arrow.Field("created_at", new arrow.Utf8(), true),
259
+ ]);
260
+ }
261
+ async function getGraphTable(conn, _dataDir, _cfg, name) {
229
262
  const existing = await conn.tableNames();
230
263
  if (existing.includes(name)) {
231
264
  return conn.openTable(name);
232
265
  }
233
- return conn.openTable(name);
266
+ const schema = name === "entities" ? makeEntitySchema() : makeRelationSchema();
267
+ return conn.createEmptyTable(name, schema);
234
268
  }
@@ -0,0 +1,6 @@
1
+ import type { IdentitiesConfig } from "./types.js";
2
+ /**
3
+ * Write a partial identities config into the vault-local config layer.
4
+ * Deep-merges into vaultMind.identities so existing roles are preserved.
5
+ */
6
+ export declare function writeIdentitiesLayer(cwd: string, identities: Partial<IdentitiesConfig>): void;
@@ -0,0 +1,39 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { getConfigPath } from "./utils.js";
4
+ /** Deep-merge two objects. Reused from server.ts pattern. */
5
+ function deepMerge(base, overlay) {
6
+ const result = { ...base };
7
+ for (const key of Object.keys(overlay)) {
8
+ const ov = overlay[key];
9
+ if (ov &&
10
+ typeof ov === "object" &&
11
+ !Array.isArray(ov) &&
12
+ typeof result[key] === "object" &&
13
+ result[key] !== null &&
14
+ !Array.isArray(result[key])) {
15
+ result[key] = deepMerge(result[key], ov);
16
+ }
17
+ else {
18
+ result[key] = ov;
19
+ }
20
+ }
21
+ return result;
22
+ }
23
+ /**
24
+ * Write a partial identities config into the vault-local config layer.
25
+ * Deep-merges into vaultMind.identities so existing roles are preserved.
26
+ */
27
+ export function writeIdentitiesLayer(cwd, identities) {
28
+ const configPath = getConfigPath(cwd);
29
+ const existing = fs.existsSync(configPath)
30
+ ? JSON.parse(fs.readFileSync(configPath, "utf-8"))
31
+ : {};
32
+ const vaultMind = existing.vaultMind || {};
33
+ vaultMind.identities = deepMerge(vaultMind.identities || {}, identities);
34
+ existing.vaultMind = vaultMind;
35
+ const dir = path.dirname(configPath);
36
+ if (!fs.existsSync(dir))
37
+ fs.mkdirSync(dir, { recursive: true });
38
+ fs.writeFileSync(configPath, `${JSON.stringify(existing, null, 2)}\n`, "utf-8");
39
+ }
@@ -32,7 +32,7 @@ const BOUNDARY_PROMPTS = {
32
32
  "--- IDENTITY BOUNDARY: Broadcaster ---",
33
33
  "You are the Broadcaster agent. Your capability boundary:",
34
34
  "- You MAY: read files, write files, edit files.",
35
- "- You MAY: search collections via vm_search, vm_fts_search.",
35
+ "- You MAY: search collections via vm_search.",
36
36
  "- You MUST NOT: run bash commands, grep, or find.",
37
37
  "- You MUST NOT: write to the durable knowledge store.",
38
38
  "- You MUST NOT: publish or spawn sub-agents.",
package/dist/src/index.js CHANGED
@@ -13,7 +13,7 @@ import { registerIntakeTool } from "./intake.js";
13
13
  import { startServer, stopServer } from "./server.js";
14
14
  import { clearEngineStatus, clearWatcherStatus, registerStatusCapture, setEngineStatus, } from "./status.js";
15
15
  import { registerTools } from "./tools.js";
16
- import { EXT_ROOT, findConfig, loadConfig } from "./utils.js";
16
+ import { EXT_ROOT, isVaultMindReady, loadConfig } from "./utils.js";
17
17
  import { registerVaultTools } from "./vault-tools.js";
18
18
  import { registerAllExtensionTools } from "./vm-handlers.js";
19
19
  import { startWatcher, stopWatcher, subscribeJobCompleted } from "./watcher.js";
@@ -37,30 +37,13 @@ export default function (pi) {
37
37
  * during extension loading — the runtime must be initialized first. */
38
38
  pi.on("session_start", async (_event, ctx) => {
39
39
  updateActiveCollectionWidget(ctx);
40
- /* Only enable ACM when THIS vault has been configured (setup has been run).
41
- * Check the PROJECT config only — not the merged global+project config.
42
- * The global config may have remoteUrl/localUrl from other vaults, which
43
- * would incorrectly trigger ACM on a fresh vault. */
44
- const paths = findConfig(ctx.cwd);
45
- const projectCfg = paths.project
46
- ? (() => {
47
- try {
48
- return JSON.parse(fs.readFileSync(paths.project, "utf-8"));
49
- }
50
- catch {
51
- return {};
52
- }
53
- })()
54
- : {};
55
- const projectEmbed = projectCfg.vaultMind?.embedding;
56
- const projectAgentLLM = projectCfg.vaultMind?.agentLLM;
57
- const isSetup = !!(projectEmbed?.remoteUrl ||
58
- projectEmbed?.localUrl ||
59
- projectEmbed?.model ||
60
- projectAgentLLM?.model);
40
+ /* Auto-enable ACM only when this vault is completely configured and
41
+ * ready. isVaultMindReady reads the RAW config file (not the merged
42
+ * config, whose DEFAULT_CONFIG always populates embedding.localUrl and
43
+ * would make a fresh vault look ready). */
61
44
  const sessionCfg = loadConfig(ctx.cwd);
62
45
  const piCtxCfg = sessionCfg.extensionCompatibility?.["pi-context"];
63
- if (isSetup && piCtxCfg?.enabled && piCtxCfg?.autoEnableAcm !== false) {
46
+ if (isVaultMindReady(ctx.cwd) && piCtxCfg?.enabled && piCtxCfg?.autoEnableAcm !== false) {
64
47
  enableACM(pi);
65
48
  }
66
49
  /* register shortcut */
@@ -122,9 +105,9 @@ export default function (pi) {
122
105
  startWatcher(pi, autoVaultMap, watcherState);
123
106
  }, 2000);
124
107
  }
125
- if (cfg.vaultMind.embedding.remoteUrl && cfg.vaultMind.embedding.modal?.sync?.autoSync) {
126
- stopAutoSync = startAutoSync(cfg.vaultMind.embedding.modal?.sync?.autoSyncIntervalMs ?? 300000);
127
- console.log(`[pi-vault-mind] Modal auto-sync enabled (every ${cfg.vaultMind.embedding.modal?.sync?.autoSyncIntervalMs ?? 300000}ms)`);
108
+ if (cfg.vaultMind.embedding.remoteUrl && cfg.vaultMind.embedding.sync?.autoSync) {
109
+ stopAutoSync = startAutoSync(cfg.vaultMind.embedding.sync?.autoSyncIntervalMs ?? 300000);
110
+ console.log(`[pi-vault-mind] Modal auto-sync enabled (every ${cfg.vaultMind.embedding.sync?.autoSyncIntervalMs ?? 300000}ms)`);
128
111
  }
129
112
  }
130
113
  catch {
@@ -11,6 +11,9 @@ export declare const upsertEntry: (dataDir: string, collectionName: string, entr
11
11
  * text + metadata. Idempotent (re-fetching a boundary row is a no-op).
12
12
  */
13
13
  export declare const upsertPrecomputed: (dataDir: string, collectionName: string, model: string, dim: number, rows: Array<Record<string, unknown>>, cfg: VaultMindConfig, identity?: AgentIdentity) => Promise<void>;
14
+ /** Filter results by visibility: show public entries + entries owned by the reader. No identity = no filter (backward compat).
15
+ * Records without visibility/origin_identity fields (e.g. graph entities/relations) are treated as public. */
16
+ export declare function filterByVisibility(results: unknown[], identity?: AgentIdentity): unknown[];
14
17
  /**
15
18
  * Deterministic JSONL query for a collection. Applies optional substring search,
16
19
  * exact field filters, identity visibility filter, and pagination.
@@ -18,4 +21,10 @@ export declare const upsertPrecomputed: (dataDir: string, collectionName: string
18
21
  export declare const queryCollection: (collectionPath: string, schema: string[], query: string | null | undefined, filters: Record<string, string> | undefined, limit: number, offset: number, identity?: AgentIdentity) => Promise<unknown[]>;
19
22
  export declare const searchHybrid: (dataDir: string, collectionName: string, query: string, limit: number, cfg: VaultMindConfig, identity?: AgentIdentity) => Promise<unknown[]>;
20
23
  export declare const searchFts: (dataDir: string, collectionName: string, query: string, limit: number, cfg: VaultMindConfig, identity?: AgentIdentity) => Promise<unknown[]>;
24
+ /**
25
+ * Rank-merge vector and FTS results: vector hits score higher, deduplicated by
26
+ * id or fact. Each result is tagged with `_source: "vector" | "fts"`. Falls
27
+ * back gracefully — if either path fails, the other still contributes.
28
+ */
29
+ export declare const searchHybridRanked: (dataDir: string, collectionName: string, query: string, limit: number, cfg: VaultMindConfig, identity?: AgentIdentity) => Promise<unknown[]>;
21
30
  export declare const getStatus: (dataDir: string) => Promise<Record<string, unknown>>;