@vpxa/aikit 0.1.113 → 0.1.115

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.
@@ -160,107 +160,6 @@ interface IGraphStore {
160
160
  close(): Promise<void>;
161
161
  }
162
162
  //#endregion
163
- //#region packages/store/src/store.interface.d.ts
164
- /** Options for searching the store */
165
- interface SearchOptions {
166
- /** Maximum number of results to return */
167
- limit?: number;
168
- /** Minimum similarity score (0-1) */
169
- minScore?: number;
170
- /** Filter by content type */
171
- contentType?: ContentType;
172
- /** Filter by coarse source type (source, documentation, test, config, generated) */
173
- sourceType?: SourceType;
174
- /** Filter by origin */
175
- origin?: KnowledgeOrigin;
176
- /** Filter by category */
177
- category?: string;
178
- /** Filter by tags (any match) */
179
- tags?: string[];
180
- }
181
- interface IKnowledgeStore {
182
- /** Initialize the store (create tables, etc.) */
183
- initialize(): Promise<void>;
184
- /** Add or update records with their embedding vectors */
185
- upsert(records: KnowledgeRecord[], vectors: Float32Array[]): Promise<void>;
186
- /** Add or update records with priority over bulk indexing writes */
187
- upsertInteractive(records: KnowledgeRecord[], vectors: Float32Array[]): Promise<void>;
188
- /** Add or update a record by reusing an existing vector instead of embedding again */
189
- upsertWithoutVector?(record: KnowledgeRecord, sourceRecordId: string): Promise<void>;
190
- /** Search by vector similarity */
191
- search(queryVector: Float32Array, options?: SearchOptions): Promise<SearchResult[]>;
192
- /** Coarse vector search using reduced-dimension embeddings (multi-resolution matryoshka) */
193
- coarseSearch?(queryVector: Float32Array, options?: SearchOptions): Promise<SearchResult[]>;
194
- /** Get a specific record by ID */
195
- getById(id: string): Promise<KnowledgeRecord | null>;
196
- /** Delete records by source path (used during re-indexing) */
197
- deleteBySourcePath(sourcePath: string): Promise<number>;
198
- /** Delete a specific record by ID */
199
- deleteById(id: string): Promise<boolean>;
200
- /** Delete a specific record by ID with priority over bulk indexing writes */
201
- deleteByIdInteractive(id: string): Promise<boolean>;
202
- /** Get all records for a source path */
203
- getBySourcePath(sourcePath: string): Promise<KnowledgeRecord[]>;
204
- /** Get index statistics */
205
- getStats(): Promise<IndexStats>;
206
- /** List all unique source paths in the store */
207
- listSourcePaths(): Promise<string[]>;
208
- /** Create a full-text search index on the content column for keyword search */
209
- createFtsIndex(): Promise<void>;
210
- /** Full-text keyword search (requires FTS index) */
211
- ftsSearch(query: string, options?: SearchOptions): Promise<SearchResult[]>;
212
- /** Drop the backing table entirely — used for hard resets (e.g. dimension changes) */
213
- dropTable(): Promise<void>;
214
- /** Release cached memory without closing the connection (lightweight idle cleanup). */
215
- releaseMemory?(): void;
216
- /** Register a callback invoked synchronously before the store closes. */
217
- onBeforeClose?(fn: () => void): void;
218
- /** Close the store connection */
219
- close(): Promise<void>;
220
- }
221
- //#endregion
222
- //#region packages/store/src/lance-store.d.ts
223
- declare class LanceStore implements IKnowledgeStore {
224
- private db;
225
- private table;
226
- private readonly dbPath;
227
- private readonly tableName;
228
- private _draining;
229
- private _priorityQueue;
230
- private _normalQueue;
231
- private _ftsReady;
232
- private _ftsRecoveryAttemptAt;
233
- private static readonly FTS_RECOVERY_COOLDOWN_MS;
234
- private enqueueWrite;
235
- private _drain;
236
- constructor(options?: {
237
- path?: string;
238
- tableName?: string;
239
- });
240
- initialize(): Promise<void>;
241
- upsert(records: KnowledgeRecord[], vectors: Float32Array[]): Promise<void>;
242
- upsertInteractive(records: KnowledgeRecord[], vectors: Float32Array[]): Promise<void>;
243
- private _upsertImpl;
244
- search(queryVector: Float32Array, options?: SearchOptions): Promise<SearchResult[]>;
245
- createFtsIndex(): Promise<void>;
246
- private _createFtsIndexImpl;
247
- ftsSearch(query: string, options?: SearchOptions): Promise<SearchResult[]>;
248
- getById(id: string): Promise<KnowledgeRecord | null>;
249
- deleteBySourcePath(sourcePath: string): Promise<number>;
250
- private _deleteBySourcePathImpl;
251
- deleteById(id: string): Promise<boolean>;
252
- deleteByIdInteractive(id: string): Promise<boolean>;
253
- private _deleteByIdImpl;
254
- getBySourcePath(sourcePath: string): Promise<KnowledgeRecord[]>;
255
- getStats(): Promise<IndexStats>;
256
- listSourcePaths(): Promise<string[]>;
257
- dropTable(): Promise<void>;
258
- private _dropTableImpl;
259
- close(): Promise<void>;
260
- private buildFilterString;
261
- private fromLanceRecord;
262
- }
263
- //#endregion
264
163
  //#region packages/store/src/sqlite-adapter.d.ts
265
164
  /**
266
165
  * SQLite adapter — selects between native better-sqlite3 (preferred) and
@@ -387,6 +286,65 @@ declare class SqliteGraphStore implements IGraphStore {
387
286
  close(): Promise<void>;
388
287
  }
389
288
  //#endregion
289
+ //#region packages/store/src/store.interface.d.ts
290
+ /** Options for searching the store */
291
+ interface SearchOptions {
292
+ /** Maximum number of results to return */
293
+ limit?: number;
294
+ /** Minimum similarity score (0-1) */
295
+ minScore?: number;
296
+ /** Filter by content type */
297
+ contentType?: ContentType;
298
+ /** Filter by coarse source type (source, documentation, test, config, generated) */
299
+ sourceType?: SourceType;
300
+ /** Filter by origin */
301
+ origin?: KnowledgeOrigin;
302
+ /** Filter by category */
303
+ category?: string;
304
+ /** Filter by tags (any match) */
305
+ tags?: string[];
306
+ }
307
+ interface IKnowledgeStore {
308
+ /** Initialize the store (create tables, etc.) */
309
+ initialize(): Promise<void>;
310
+ /** Add or update records with their embedding vectors */
311
+ upsert(records: KnowledgeRecord[], vectors: Float32Array[]): Promise<void>;
312
+ /** Add or update records with priority over bulk indexing writes */
313
+ upsertInteractive(records: KnowledgeRecord[], vectors: Float32Array[]): Promise<void>;
314
+ /** Add or update a record by reusing an existing vector instead of embedding again */
315
+ upsertWithoutVector?(record: KnowledgeRecord, sourceRecordId: string): Promise<void>;
316
+ /** Search by vector similarity */
317
+ search(queryVector: Float32Array, options?: SearchOptions): Promise<SearchResult[]>;
318
+ /** Coarse vector search using reduced-dimension embeddings (multi-resolution matryoshka) */
319
+ coarseSearch?(queryVector: Float32Array, options?: SearchOptions): Promise<SearchResult[]>;
320
+ /** Get a specific record by ID */
321
+ getById(id: string): Promise<KnowledgeRecord | null>;
322
+ /** Delete records by source path (used during re-indexing) */
323
+ deleteBySourcePath(sourcePath: string): Promise<number>;
324
+ /** Delete a specific record by ID */
325
+ deleteById(id: string): Promise<boolean>;
326
+ /** Delete a specific record by ID with priority over bulk indexing writes */
327
+ deleteByIdInteractive(id: string): Promise<boolean>;
328
+ /** Get all records for a source path */
329
+ getBySourcePath(sourcePath: string): Promise<KnowledgeRecord[]>;
330
+ /** Get index statistics */
331
+ getStats(): Promise<IndexStats>;
332
+ /** List all unique source paths in the store */
333
+ listSourcePaths(): Promise<string[]>;
334
+ /** Create a full-text search index on the content column for keyword search */
335
+ createFtsIndex(): Promise<void>;
336
+ /** Full-text keyword search (requires FTS index) */
337
+ ftsSearch(query: string, options?: SearchOptions): Promise<SearchResult[]>;
338
+ /** Drop the backing table entirely — used for hard resets (e.g. dimension changes) */
339
+ dropTable(): Promise<void>;
340
+ /** Release cached memory without closing the connection (lightweight idle cleanup). */
341
+ releaseMemory?(): void;
342
+ /** Register a callback invoked synchronously before the store closes. */
343
+ onBeforeClose?(fn: () => void): void;
344
+ /** Close the store connection */
345
+ close(): Promise<void>;
346
+ }
347
+ //#endregion
390
348
  //#region packages/store/src/sqlite-vec-store.d.ts
391
349
  interface SqliteVecStoreOptions {
392
350
  /** Path to the .db file (file is created if missing) */
@@ -484,4 +442,4 @@ interface StoreConfig {
484
442
  }
485
443
  declare function createStore(config: StoreConfig): Promise<IKnowledgeStore>;
486
444
  //#endregion
487
- export { type DepthGroupedResult, type GraphEdge, type GraphNode, type GraphStats, type GraphTraversalOptions, type GraphTraversalResult, type GraphValidationResult, type IGraphStore, type IKnowledgeStore, type ISqliteAdapter, LanceStore, type ProcessInfo, type SearchOptions, type SqliteAdapterType, SqliteGraphStore, SqliteVecStore, type SqliteVecStoreOptions, type StoreBackend, type StoreConfig, type Symbol360, createSqlJsAdapter, createSqliteAdapter, createStore };
445
+ export { type DepthGroupedResult, type GraphEdge, type GraphNode, type GraphStats, type GraphTraversalOptions, type GraphTraversalResult, type GraphValidationResult, type IGraphStore, type IKnowledgeStore, type ISqliteAdapter, type ProcessInfo, type SearchOptions, type SqliteAdapterType, SqliteGraphStore, SqliteVecStore, type SqliteVecStoreOptions, type StoreBackend, type StoreConfig, type Symbol360, createSqlJsAdapter, createSqliteAdapter, createStore };
@@ -1,4 +1,4 @@
1
- import{t as e}from"./lance-store-BRoi-4qY.js";import{i as t,r as n,t as r}from"./sqlite-vec-store-DuGaWATy.js";import{AIKIT_PATHS as i}from"../../core/dist/index.js";import{existsSync as a,mkdirSync as o}from"node:fs";import{dirname as s,join as c}from"node:path";var l=class{adapter=null;reopenPromise=null;dbPath;externalAdapter;constructor(e={}){if(e.adapter)this.adapter=e.adapter,this.externalAdapter=!0,this.dbPath=``;else{let t=e.path??i.data;this.dbPath=c(t,`graph.db`),this.externalAdapter=!1}}async initialize(){if(this.externalAdapter){let e=this.getAdapter();this.createTables(e),this.migrateSchema(e),e.flush();return}let e=s(this.dbPath);a(e)||o(e,{recursive:!0}),this.adapter=await t(this.dbPath),this.configureAdapter(this.adapter),this.createTables(this.adapter),this.migrateSchema(this.adapter),this.adapter.flush()}configureAdapter(e){e.pragma(`journal_mode = WAL`),e.pragma(`foreign_keys = ON`)}createTables(e){e.exec(`
1
+ import{i as e,r as t,t as n}from"./sqlite-vec-store-DA6fzQiD.js";import{existsSync as r,mkdirSync as i}from"node:fs";import{AIKIT_PATHS as a}from"../../core/dist/index.js";import{dirname as o,join as s}from"node:path";var c=class{adapter=null;reopenPromise=null;dbPath;externalAdapter;constructor(e={}){if(e.adapter)this.adapter=e.adapter,this.externalAdapter=!0,this.dbPath=``;else{let t=e.path??a.data;this.dbPath=s(t,`graph.db`),this.externalAdapter=!1}}async initialize(){if(this.externalAdapter){let e=this.getAdapter();this.createTables(e),this.migrateSchema(e),e.flush();return}let t=o(this.dbPath);r(t)||i(t,{recursive:!0}),this.adapter=await e(this.dbPath),this.configureAdapter(this.adapter),this.createTables(this.adapter),this.migrateSchema(this.adapter),this.adapter.flush()}configureAdapter(e){e.pragma(`journal_mode = WAL`),e.pragma(`foreign_keys = ON`)}createTables(e){e.exec(`
2
2
  CREATE TABLE IF NOT EXISTS nodes (
3
3
  id TEXT PRIMARY KEY,
4
4
  type TEXT NOT NULL,
@@ -39,7 +39,7 @@ import{t as e}from"./lance-store-BRoi-4qY.js";import{i as t,r as n,t as r}from".
39
39
  FOREIGN KEY (process_id) REFERENCES processes(id) ON DELETE CASCADE,
40
40
  FOREIGN KEY (node_id) REFERENCES nodes(id) ON DELETE CASCADE
41
41
  )
42
- `),e.exec(`CREATE INDEX IF NOT EXISTS idx_process_steps_node ON process_steps(node_id)`)}migrateSchema(e){for(let t of[`ALTER TABLE edges ADD COLUMN confidence REAL DEFAULT 1.0`,`ALTER TABLE nodes ADD COLUMN community TEXT`])try{e.exec(t)}catch{}e.exec(`CREATE INDEX IF NOT EXISTS idx_nodes_community ON nodes(community)`)}getAdapter(){if(!this.adapter)throw Error(`SqliteGraphStore not initialized — call initialize() first`);return this.adapter}async ensureOpen(){if(this.adapter)return;if(this.externalAdapter)throw Error(`SqliteGraphStore: external adapter has been closed by its owner; cannot reopen`);if(this.reopenPromise)return this.reopenPromise;let e=this.reopenAdapter();this.reopenPromise=e;try{await e}finally{this.reopenPromise===e&&(this.reopenPromise=null)}}async reopenAdapter(){let e=await t(this.dbPath);this.configureAdapter(e),this.adapter=e}query(e,t=[]){return this.getAdapter().queryAll(e,t)}run(e,t=[]){this.getAdapter().run(e,t)}async upsertNode(e){await this.ensureOpen(),this.run(`INSERT INTO nodes (id, type, name, properties, source_record_id, source_path, created_at, community)
42
+ `),e.exec(`CREATE INDEX IF NOT EXISTS idx_process_steps_node ON process_steps(node_id)`)}migrateSchema(e){for(let t of[`ALTER TABLE edges ADD COLUMN confidence REAL DEFAULT 1.0`,`ALTER TABLE nodes ADD COLUMN community TEXT`])try{e.exec(t)}catch{}e.exec(`CREATE INDEX IF NOT EXISTS idx_nodes_community ON nodes(community)`)}getAdapter(){if(!this.adapter)throw Error(`SqliteGraphStore not initialized — call initialize() first`);return this.adapter}async ensureOpen(){if(this.adapter)return;if(this.externalAdapter)throw Error(`SqliteGraphStore: external adapter has been closed by its owner; cannot reopen`);if(this.reopenPromise)return this.reopenPromise;let e=this.reopenAdapter();this.reopenPromise=e;try{await e}finally{this.reopenPromise===e&&(this.reopenPromise=null)}}async reopenAdapter(){let t=await e(this.dbPath);this.configureAdapter(t),this.adapter=t}query(e,t=[]){return this.getAdapter().queryAll(e,t)}run(e,t=[]){this.getAdapter().run(e,t)}async upsertNode(e){await this.ensureOpen(),this.run(`INSERT INTO nodes (id, type, name, properties, source_record_id, source_path, created_at, community)
43
43
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
44
44
  ON CONFLICT(id) DO UPDATE SET
45
45
  type = excluded.type, name = excluded.name, properties = excluded.properties,
@@ -57,19 +57,19 @@ import{t as e}from"./lance-store-BRoi-4qY.js";import{i as t,r as n,t as r}from".
57
57
  VALUES (?, ?, ?, ?, ?, ?, ?)
58
58
  ON CONFLICT(id) DO UPDATE SET
59
59
  from_id = excluded.from_id, to_id = excluded.to_id,
60
- type = excluded.type, weight = excluded.weight, confidence = excluded.confidence, properties = excluded.properties`,[t.id,t.fromId,t.toId,t.type,t.weight??1,t.confidence??1,JSON.stringify(t.properties??{})]);t.exec(`COMMIT`),t.flush()}catch(e){throw t.exec(`ROLLBACK`),e}finally{t.pragma(`foreign_keys = ON`)}}async getNode(e){await this.ensureOpen();let t=this.query(`SELECT * FROM nodes WHERE id = ?`,[e]);return t.length>0?d(t[0]):null}async getNeighbors(e,t){await this.ensureOpen();let n=t?.direction??`both`,r=t?.edgeType,i=t?.limit??50,a=[],o=[],s=new Set;if(n===`outgoing`||n===`both`){let t=`
60
+ type = excluded.type, weight = excluded.weight, confidence = excluded.confidence, properties = excluded.properties`,[t.id,t.fromId,t.toId,t.type,t.weight??1,t.confidence??1,JSON.stringify(t.properties??{})]);t.exec(`COMMIT`),t.flush()}catch(e){throw t.exec(`ROLLBACK`),e}finally{t.pragma(`foreign_keys = ON`)}}async getNode(e){await this.ensureOpen();let t=this.query(`SELECT * FROM nodes WHERE id = ?`,[e]);return t.length>0?u(t[0]):null}async getNeighbors(e,t){await this.ensureOpen();let n=t?.direction??`both`,r=t?.edgeType,i=t?.limit??50,a=[],o=[],s=new Set;if(n===`outgoing`||n===`both`){let t=`
61
61
  SELECT e.id AS edge_id, e.from_id, e.to_id, e.type AS edge_type, e.weight,
62
62
  e.confidence AS edge_confidence, e.properties AS edge_props,
63
63
  n.id AS node_id, n.type AS node_type, n.name AS node_name, n.properties AS node_props,
64
64
  n.source_record_id AS node_src_rec, n.source_path AS node_src_path,
65
65
  n.created_at AS node_created, n.community AS node_community
66
- FROM edges e JOIN nodes n ON e.to_id = n.id WHERE e.from_id = ?`,n=[e];r&&(t+=` AND e.type = ?`,n.push(r)),t+=` LIMIT ?`,n.push(i);let c=this.query(t,n);for(let e of c)o.push(p(e)),s.has(e.node_id)||(s.add(e.node_id),a.push(m(e)))}if(n===`incoming`||n===`both`){let t=`
66
+ FROM edges e JOIN nodes n ON e.to_id = n.id WHERE e.from_id = ?`,n=[e];r&&(t+=` AND e.type = ?`,n.push(r)),t+=` LIMIT ?`,n.push(i);let c=this.query(t,n);for(let e of c)o.push(f(e)),s.has(e.node_id)||(s.add(e.node_id),a.push(p(e)))}if(n===`incoming`||n===`both`){let t=`
67
67
  SELECT e.id AS edge_id, e.from_id, e.to_id, e.type AS edge_type, e.weight,
68
68
  e.confidence AS edge_confidence, e.properties AS edge_props,
69
69
  n.id AS node_id, n.type AS node_type, n.name AS node_name, n.properties AS node_props,
70
70
  n.source_record_id AS node_src_rec, n.source_path AS node_src_path,
71
71
  n.created_at AS node_created, n.community AS node_community
72
- FROM edges e JOIN nodes n ON e.from_id = n.id WHERE e.to_id = ?`,n=[e];r&&(t+=` AND e.type = ?`,n.push(r)),t+=` LIMIT ?`,n.push(i);let c=this.query(t,n);for(let e of c)o.push(p(e)),s.has(e.node_id)||(s.add(e.node_id),a.push(m(e)))}return{nodes:a,edges:o}}async traverse(e,t){await this.ensureOpen();let n=t?.maxDepth??2,r=t?.direction??`both`,i=t?.edgeType,a=t?.limit??50,o=new Map,s=new Map,c=new Set,l=[{nodeId:e,depth:0}];for(;l.length>0&&o.size<a;){let e=l.shift();if(!e||c.has(e.nodeId)||e.depth>n)continue;c.add(e.nodeId);let t=await this.getNeighbors(e.nodeId,{direction:r,edgeType:i,limit:a-o.size});for(let r of t.nodes)o.has(r.id)||(o.set(r.id,r),e.depth+1<n&&l.push({nodeId:r.id,depth:e.depth+1}));for(let e of t.edges)s.set(e.id,e)}return{nodes:[...o.values()],edges:[...s.values()]}}async findNodes(e){await this.ensureOpen();let t=[],n=[];e.type&&(t.push(`type = ?`),n.push(e.type)),e.namePattern&&(t.push(`name LIKE ?`),n.push(`%${e.namePattern}%`)),e.sourcePath&&(t.push(`source_path = ?`),n.push(e.sourcePath));let r=t.length>0?`WHERE ${t.join(` AND `)}`:``,i=e.limit??100;return this.query(`SELECT * FROM nodes ${r} LIMIT ?`,[...n,i]).map(e=>d(e))}async findEdges(e){await this.ensureOpen();let t=[],n=[];e.type&&(t.push(`type = ?`),n.push(e.type)),e.fromId&&(t.push(`from_id = ?`),n.push(e.fromId)),e.toId&&(t.push(`to_id = ?`),n.push(e.toId));let r=t.length>0?`WHERE ${t.join(` AND `)}`:``,i=e.limit??100;return this.query(`SELECT * FROM edges ${r} LIMIT ?`,[...n,i]).map(e=>f(e))}async deleteNode(e){await this.ensureOpen();let t=this.getAdapter();t.exec(`BEGIN TRANSACTION`);try{this.run(`DELETE FROM edges WHERE from_id = ? OR to_id = ?`,[e,e]),this.run(`DELETE FROM nodes WHERE id = ?`,[e]),t.exec(`COMMIT`),t.flush()}catch(e){throw t.exec(`ROLLBACK`),e}}async deleteBySourcePath(e){await this.ensureOpen();let t=this.query(`SELECT id FROM nodes WHERE source_path = ?`,[e]);if(t.length===0)return 0;let n=this.getAdapter();n.exec(`BEGIN TRANSACTION`);try{for(let e of t)this.run(`DELETE FROM edges WHERE from_id = ? OR to_id = ?`,[e.id,e.id]);this.run(`DELETE FROM nodes WHERE source_path = ?`,[e]),n.exec(`COMMIT`),n.flush()}catch(e){throw n.exec(`ROLLBACK`),e}return t.length}async clear(){await this.ensureOpen();let e=this.getAdapter();e.exec(`BEGIN TRANSACTION`);try{this.run(`DELETE FROM process_steps`),this.run(`DELETE FROM processes`),this.run(`DELETE FROM edges`),this.run(`DELETE FROM nodes`),e.exec(`COMMIT`)}catch(t){throw e.exec(`ROLLBACK`),t}e.flush()}async getStats(){await this.ensureOpen();let e=this.query(`SELECT COUNT(*) as count FROM nodes`)[0]?.count??0,t=this.query(`SELECT COUNT(*) as count FROM edges`)[0]?.count??0,n=this.query(`SELECT type, COUNT(*) as count FROM nodes GROUP BY type`),r={};for(let e of n)r[e.type]=e.count;let i=this.query(`SELECT type, COUNT(*) as count FROM edges GROUP BY type`),a={};for(let e of i)a[e.type]=e.count;return{nodeCount:e,edgeCount:t,nodeTypes:r,edgeTypes:a}}async validate(){await this.ensureOpen();let e=await this.getStats(),t=this.query(`SELECT e.id AS edgeId,
72
+ FROM edges e JOIN nodes n ON e.from_id = n.id WHERE e.to_id = ?`,n=[e];r&&(t+=` AND e.type = ?`,n.push(r)),t+=` LIMIT ?`,n.push(i);let c=this.query(t,n);for(let e of c)o.push(f(e)),s.has(e.node_id)||(s.add(e.node_id),a.push(p(e)))}return{nodes:a,edges:o}}async traverse(e,t){await this.ensureOpen();let n=t?.maxDepth??2,r=t?.direction??`both`,i=t?.edgeType,a=t?.limit??50,o=new Map,s=new Map,c=new Set,l=[{nodeId:e,depth:0}];for(;l.length>0&&o.size<a;){let e=l.shift();if(!e||c.has(e.nodeId)||e.depth>n)continue;c.add(e.nodeId);let t=await this.getNeighbors(e.nodeId,{direction:r,edgeType:i,limit:a-o.size});for(let r of t.nodes)o.has(r.id)||(o.set(r.id,r),e.depth+1<n&&l.push({nodeId:r.id,depth:e.depth+1}));for(let e of t.edges)s.set(e.id,e)}return{nodes:[...o.values()],edges:[...s.values()]}}async findNodes(e){await this.ensureOpen();let t=[],n=[];e.type&&(t.push(`type = ?`),n.push(e.type)),e.namePattern&&(t.push(`name LIKE ?`),n.push(`%${e.namePattern}%`)),e.sourcePath&&(t.push(`source_path = ?`),n.push(e.sourcePath));let r=t.length>0?`WHERE ${t.join(` AND `)}`:``,i=e.limit??100;return this.query(`SELECT * FROM nodes ${r} LIMIT ?`,[...n,i]).map(e=>u(e))}async findEdges(e){await this.ensureOpen();let t=[],n=[];e.type&&(t.push(`type = ?`),n.push(e.type)),e.fromId&&(t.push(`from_id = ?`),n.push(e.fromId)),e.toId&&(t.push(`to_id = ?`),n.push(e.toId));let r=t.length>0?`WHERE ${t.join(` AND `)}`:``,i=e.limit??100;return this.query(`SELECT * FROM edges ${r} LIMIT ?`,[...n,i]).map(e=>d(e))}async deleteNode(e){await this.ensureOpen();let t=this.getAdapter();t.exec(`BEGIN TRANSACTION`);try{this.run(`DELETE FROM edges WHERE from_id = ? OR to_id = ?`,[e,e]),this.run(`DELETE FROM nodes WHERE id = ?`,[e]),t.exec(`COMMIT`),t.flush()}catch(e){throw t.exec(`ROLLBACK`),e}}async deleteBySourcePath(e){await this.ensureOpen();let t=this.query(`SELECT id FROM nodes WHERE source_path = ?`,[e]);if(t.length===0)return 0;let n=this.getAdapter();n.exec(`BEGIN TRANSACTION`);try{for(let e of t)this.run(`DELETE FROM edges WHERE from_id = ? OR to_id = ?`,[e.id,e.id]);this.run(`DELETE FROM nodes WHERE source_path = ?`,[e]),n.exec(`COMMIT`),n.flush()}catch(e){throw n.exec(`ROLLBACK`),e}return t.length}async clear(){await this.ensureOpen();let e=this.getAdapter();e.exec(`BEGIN TRANSACTION`);try{this.run(`DELETE FROM process_steps`),this.run(`DELETE FROM processes`),this.run(`DELETE FROM edges`),this.run(`DELETE FROM nodes`),e.exec(`COMMIT`)}catch(t){throw e.exec(`ROLLBACK`),t}e.flush()}async getStats(){await this.ensureOpen();let e=this.query(`SELECT COUNT(*) as count FROM nodes`)[0]?.count??0,t=this.query(`SELECT COUNT(*) as count FROM edges`)[0]?.count??0,n=this.query(`SELECT type, COUNT(*) as count FROM nodes GROUP BY type`),r={};for(let e of n)r[e.type]=e.count;let i=this.query(`SELECT type, COUNT(*) as count FROM edges GROUP BY type`),a={};for(let e of i)a[e.type]=e.count;return{nodeCount:e,edgeCount:t,nodeTypes:r,edgeTypes:a}}async validate(){await this.ensureOpen();let e=await this.getStats(),t=this.query(`SELECT e.id AS edgeId,
73
73
  CASE
74
74
  WHEN n1.id IS NULL THEN e.from_id
75
75
  WHEN n2.id IS NULL THEN e.to_id
@@ -87,4 +87,4 @@ import{t as e}from"./lance-store-BRoi-4qY.js";import{i as t,r as n,t as r}from".
87
87
  VALUES (?, ?, ?, '{}', ?)`,[a,e,t,o]);for(let e=0;e<n.length;e++)this.run(`INSERT INTO process_steps (process_id, node_id, step_order) VALUES (?, ?, ?)`,[a,n[e],e]);s.exec(`COMMIT`),s.flush()}catch(e){throw s.exec(`ROLLBACK`),e}return{id:a,entryNodeId:e,label:t,properties:{},steps:n,createdAt:o}}async getProcesses(e){await this.ensureOpen();let t;t=e?this.query(`SELECT DISTINCT p.id, p.entry_node_id, p.label, p.properties, p.created_at
88
88
  FROM processes p
89
89
  JOIN process_steps ps ON p.id = ps.process_id
90
- WHERE ps.node_id = ?`,[e]):this.query(`SELECT * FROM processes`);let n=[];for(let e of t){let t=this.query(`SELECT node_id FROM process_steps WHERE process_id = ? ORDER BY step_order`,[e.id]);n.push({id:e.id,entryNodeId:e.entry_node_id,label:e.label,properties:u(e.properties),steps:t.map(e=>e.node_id),createdAt:e.created_at})}return n}async deleteProcess(e){await this.ensureOpen();let t=this.getAdapter();t.exec(`BEGIN TRANSACTION`);try{this.run(`DELETE FROM process_steps WHERE process_id = ?`,[e]),this.run(`DELETE FROM processes WHERE id = ?`,[e]),t.exec(`COMMIT`),t.flush()}catch(e){throw t.exec(`ROLLBACK`),e}}async depthGroupedTraversal(e,t=3,n){await this.ensureOpen();let r=n?.direction??`both`,i=n?.edgeType,a=n?.limit??100,o={},s=new Set;s.add(e);let c=[e];for(let e=1;e<=t;e++){let t=[],n=[];for(let e of c){let o=await this.getNeighbors(e,{direction:r,edgeType:i,limit:a});for(let e of o.nodes)s.has(e.id)||(s.add(e.id),t.push(e.id),n.push(e))}if(n.length>0&&(o[e]=n),c=t,c.length===0||s.size>=a)break}return o}async getCohesionScore(e){await this.ensureOpen();let t=this.query(`SELECT id FROM nodes WHERE community = ?`,[e]);if(t.length===0)return 0;let n=new Set(t.map(e=>e.id)),r=t.map(()=>`?`).join(`,`),i=t.map(e=>e.id),a=this.query(`SELECT from_id, to_id FROM edges WHERE from_id IN (${r}) OR to_id IN (${r})`,[...i,...i]);if(a.length===0)return 0;let o=0;for(let e of a)n.has(e.from_id)&&n.has(e.to_id)&&o++;return o/a.length}async getSymbol360(e){let t=await this.getNode(e);if(!t)throw Error(`Node '${e}' not found`);let n=await this.findEdges({toId:e}),r=await this.findEdges({fromId:e}),i=await this.getProcesses(e);return{node:t,incoming:n,outgoing:r,community:t.community??null,processes:i}}releaseMemory(){if(this.adapter)try{this.adapter.exec(`PRAGMA shrink_memory`),this.adapter.exec(`PRAGMA wal_checkpoint(TRUNCATE)`)}catch{}}async close(){this.adapter&&=(this.externalAdapter||this.adapter.close(),null)}};function u(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function d(e){return{id:e.id,type:e.type,name:e.name,properties:u(e.properties),sourceRecordId:e.source_record_id??void 0,sourcePath:e.source_path??void 0,createdAt:e.created_at,community:e.community??void 0}}function f(e){return{id:e.id,fromId:e.from_id,toId:e.to_id,type:e.type,weight:e.weight??1,confidence:e.confidence??1,properties:u(e.properties)}}function p(e){return{id:e.edge_id,fromId:e.from_id,toId:e.to_id,type:e.edge_type,weight:e.weight??1,confidence:e.edge_confidence??1,properties:u(e.edge_props??`{}`)}}function m(e){return{id:e.node_id,type:e.node_type,name:e.node_name,properties:u(e.node_props??`{}`),sourceRecordId:e.node_src_rec??void 0,sourcePath:e.node_src_path??void 0,createdAt:e.node_created,community:e.node_community??void 0}}async function h(e){switch(e.backend){case`lancedb`:{let{LanceStore:t}=await import(`./lance-store-BRoi-4qY.js`).then(e=>e.n);return new t({path:e.path})}case`sqlite-vec`:{let{SqliteVecStore:t}=await import(`./sqlite-vec-store-DuGaWATy.js`).then(e=>e.n);return new t({path:e.path,adapter:e.adapter,embeddingDim:e.embeddingDim})}default:{let t=e.backend;throw Error(`Unknown store backend: "${t}". Supported: lancedb, sqlite-vec`)}}}export{e as LanceStore,l as SqliteGraphStore,r as SqliteVecStore,n as createSqlJsAdapter,t as createSqliteAdapter,h as createStore};
90
+ WHERE ps.node_id = ?`,[e]):this.query(`SELECT * FROM processes`);let n=[];for(let e of t){let t=this.query(`SELECT node_id FROM process_steps WHERE process_id = ? ORDER BY step_order`,[e.id]);n.push({id:e.id,entryNodeId:e.entry_node_id,label:e.label,properties:l(e.properties),steps:t.map(e=>e.node_id),createdAt:e.created_at})}return n}async deleteProcess(e){await this.ensureOpen();let t=this.getAdapter();t.exec(`BEGIN TRANSACTION`);try{this.run(`DELETE FROM process_steps WHERE process_id = ?`,[e]),this.run(`DELETE FROM processes WHERE id = ?`,[e]),t.exec(`COMMIT`),t.flush()}catch(e){throw t.exec(`ROLLBACK`),e}}async depthGroupedTraversal(e,t=3,n){await this.ensureOpen();let r=n?.direction??`both`,i=n?.edgeType,a=n?.limit??100,o={},s=new Set;s.add(e);let c=[e];for(let e=1;e<=t;e++){let t=[],n=[];for(let e of c){let o=await this.getNeighbors(e,{direction:r,edgeType:i,limit:a});for(let e of o.nodes)s.has(e.id)||(s.add(e.id),t.push(e.id),n.push(e))}if(n.length>0&&(o[e]=n),c=t,c.length===0||s.size>=a)break}return o}async getCohesionScore(e){await this.ensureOpen();let t=this.query(`SELECT id FROM nodes WHERE community = ?`,[e]);if(t.length===0)return 0;let n=new Set(t.map(e=>e.id)),r=t.map(()=>`?`).join(`,`),i=t.map(e=>e.id),a=this.query(`SELECT from_id, to_id FROM edges WHERE from_id IN (${r}) OR to_id IN (${r})`,[...i,...i]);if(a.length===0)return 0;let o=0;for(let e of a)n.has(e.from_id)&&n.has(e.to_id)&&o++;return o/a.length}async getSymbol360(e){let t=await this.getNode(e);if(!t)throw Error(`Node '${e}' not found`);let n=await this.findEdges({toId:e}),r=await this.findEdges({fromId:e}),i=await this.getProcesses(e);return{node:t,incoming:n,outgoing:r,community:t.community??null,processes:i}}releaseMemory(){if(this.adapter)try{this.adapter.exec(`PRAGMA shrink_memory`),this.adapter.exec(`PRAGMA wal_checkpoint(TRUNCATE)`)}catch{}}async close(){this.adapter&&=(this.externalAdapter||this.adapter.close(),null)}};function l(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function u(e){return{id:e.id,type:e.type,name:e.name,properties:l(e.properties),sourceRecordId:e.source_record_id??void 0,sourcePath:e.source_path??void 0,createdAt:e.created_at,community:e.community??void 0}}function d(e){return{id:e.id,fromId:e.from_id,toId:e.to_id,type:e.type,weight:e.weight??1,confidence:e.confidence??1,properties:l(e.properties)}}function f(e){return{id:e.edge_id,fromId:e.from_id,toId:e.to_id,type:e.edge_type,weight:e.weight??1,confidence:e.edge_confidence??1,properties:l(e.edge_props??`{}`)}}function p(e){return{id:e.node_id,type:e.node_type,name:e.node_name,properties:l(e.node_props??`{}`),sourceRecordId:e.node_src_rec??void 0,sourcePath:e.node_src_path??void 0,createdAt:e.node_created,community:e.node_community??void 0}}async function m(e){switch(e.backend){case`lancedb`:{let{LanceStore:t}=await import(`./lance-store-D1JolXlO.js`);return new t({path:e.path})}case`sqlite-vec`:{let{SqliteVecStore:t}=await import(`./sqlite-vec-store-DA6fzQiD.js`).then(e=>e.n);return new t({path:e.path,adapter:e.adapter,embeddingDim:e.embeddingDim})}default:{let t=e.backend;throw Error(`Unknown store backend: "${t}". Supported: lancedb, sqlite-vec`)}}}export{c as SqliteGraphStore,n as SqliteVecStore,t as createSqlJsAdapter,e as createSqliteAdapter,m as createStore};
@@ -0,0 +1 @@
1
+ import{EMBEDDING_DEFAULTS as e,SEARCH_DEFAULTS as t,STORE_DEFAULTS as n,createLogger as r,serializeError as i,sourceTypeContentTypes as a}from"../../core/dist/index.js";import{Index as o,connect as s}from"@lancedb/lancedb";function c(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}const l=/^[\w.\-/ ]+$/,u=r(`store`);function d(e,t){if(!l.test(e))throw Error(`Invalid ${t} filter value: contains disallowed characters`);return e.replace(/'/g,`''`)}var f=class r{db=null;table=null;dbPath;tableName;_draining=!1;_priorityQueue=[];_normalQueue=[];_ftsReady=!1;_ftsRecoveryAttemptAt=0;static FTS_RECOVERY_COOLDOWN_MS=300*1e3;enqueueWrite(e,t=!1){return new Promise((n,r)=>{let i=async()=>{try{n(await e())}catch(e){r(e)}};t?this._priorityQueue.push(i):this._normalQueue.push(i),this._drain()})}async _drain(){if(!this._draining){this._draining=!0;try{for(;this._priorityQueue.length>0||this._normalQueue.length>0;){let e=this._priorityQueue.shift()??this._normalQueue.shift();e&&await e()}}finally{this._draining=!1}}}constructor(e){this.dbPath=e?.path??n.path,this.tableName=e?.tableName??n.tableName}async initialize(){this.db=await s(this.dbPath),(await this.db.tableNames()).includes(this.tableName)&&(this.table=await this.db.openTable(this.tableName),await this.createFtsIndex())}async upsert(e,t){if(e.length!==0){if(e.length!==t.length)throw Error(`Record count (${e.length}) does not match vector count (${t.length})`);return this.enqueueWrite(()=>this._upsertImpl(e,t))}}async upsertInteractive(e,t){if(e.length!==0){if(e.length!==t.length)throw Error(`Record count (${e.length}) does not match vector count (${t.length})`);return this.enqueueWrite(()=>this._upsertImpl(e,t),!0)}}async _upsertImpl(e,t){let n=e.map((e,n)=>({id:e.id,vector:Array.from(t[n]),content:e.content,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath??``,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:e.fileHash,indexedAt:e.indexedAt,origin:e.origin,tags:JSON.stringify(e.tags),category:e.category??``,version:e.version}));if(this.table){let t=[...new Set(e.map(e=>e.sourcePath))];for(let e of t)try{await this.table.delete(`sourcePath = '${d(e,`sourcePath`)}'`)}catch{}await this.table.add(n)}else try{this.table=await this.db?.createTable(this.tableName,n)??null}catch(e){if(String(e).includes(`already exists`)&&this.db)this.table=await this.db.openTable(this.tableName),await this.table.add(n);else throw e}}async search(e,n){if(!this.table)return[];let r=n?.limit??t.maxResults,i=n?.minScore??t.minScore,a=this.table.search(e).limit(r*2),o=this.buildFilterString(n);return o&&(a=a.where(o)),(await a.toArray()).map(e=>({record:this.fromLanceRecord(e),score:1-(e._distance??1)})).filter(e=>e.score>=i).slice(0,r)}async createFtsIndex(){return this.enqueueWrite(()=>this._createFtsIndexImpl())}async _createFtsIndexImpl(){if(this.table)try{await this.table.createIndex(`content`,{config:o.fts({withPosition:!0}),replace:!0}),this._ftsReady=!0,this._ftsRecoveryAttemptAt=0,u.info(`FTS index created/updated`,{column:`content`})}catch(e){u.warn(`FTS index creation failed`,i(e))}}async ftsSearch(e,n){if(!this.table)return[];if(!this._ftsReady){let e=Date.now();if(e-this._ftsRecoveryAttemptAt<r.FTS_RECOVERY_COOLDOWN_MS)return[];this._ftsRecoveryAttemptAt=e;try{await this.createFtsIndex()}catch{return[]}if(!this._ftsReady)return[]}let a=n?.limit??t.maxResults;try{let t=this.table.search(e).limit(a*2),r=this.buildFilterString(n);return r&&(t=t.where(r)),(await t.toArray()).map(e=>({record:this.fromLanceRecord(e),score:e._score??e._relevance_score??0}))}catch(e){return(e instanceof Error?e.message:String(e)).includes(`INVERTED index`)?(u.debug(`FTS search skipped — index not yet available`),this._ftsReady=!1):u.warn(`FTS search failed`,i(e)),[]}}async getById(e){if(!this.table)return null;let t=await this.table.query().where(`id = '${d(e,`id`)}'`).limit(1).toArray();return t.length===0?null:this.fromLanceRecord(t[0])}async deleteBySourcePath(e){return this.enqueueWrite(()=>this._deleteBySourcePathImpl(e))}async _deleteBySourcePathImpl(e){if(!this.table)return 0;let t=await this.getBySourcePath(e);return t.length===0?0:(await this.table.delete(`sourcePath = '${d(e,`sourcePath`)}'`),t.length)}async deleteById(e){return this.enqueueWrite(()=>this._deleteByIdImpl(e))}async deleteByIdInteractive(e){return this.enqueueWrite(()=>this._deleteByIdImpl(e),!0)}async _deleteByIdImpl(e){return!this.table||!await this.getById(e)?!1:(await this.table.delete(`id = '${d(e,`id`)}'`),!0)}async getBySourcePath(e){return this.table?(await this.table.query().where(`sourcePath = '${d(e,`sourcePath`)}'`).limit(1e3).toArray()).map(e=>this.fromLanceRecord(e)):[]}async getStats(){if(!this.table)return{totalRecords:0,totalFiles:0,contentTypeBreakdown:{},lastIndexedAt:null,storeBackend:`lancedb`,embeddingModel:e.model};let t=await this.table.countRows(),n=await this.table.query().select([`sourcePath`,`contentType`,`indexedAt`]).limit(1e5).toArray(),r={},i=new Set,a=null;for(let e of n){let t=e;r[t.contentType]=(r[t.contentType]??0)+1,i.add(t.sourcePath),(!a||t.indexedAt>a)&&(a=t.indexedAt)}return{totalRecords:t,totalFiles:i.size,contentTypeBreakdown:r,lastIndexedAt:a,storeBackend:`lancedb`,embeddingModel:e.model}}async listSourcePaths(){if(!this.table)return[];let e=await this.table.query().select([`sourcePath`]).limit(1e5).toArray();return[...new Set(e.map(e=>e.sourcePath))]}async dropTable(){return this.enqueueWrite(()=>this._dropTableImpl())}async _dropTableImpl(){if(this.db&&(await this.db.tableNames()).includes(this.tableName))for(let e=1;e<=3;e++)try{await this.db.dropTable(this.tableName);break}catch(t){if(e===3)throw t;let n=e*500;u.warn(`dropTable attempt failed, retrying`,{attempt:e,delayMs:n}),await new Promise(e=>setTimeout(e,n))}this.table=null}async close(){try{this.db&&typeof this.db.close==`function`&&await this.db.close()}catch{}this.table=null,this.db=null}buildFilterString(e){let t=[];if(e?.contentType&&t.push(`contentType = '${d(e.contentType,`contentType`)}'`),e?.sourceType){let n=a(e.sourceType);if(n.length>0){let e=n.map(e=>`'${d(e,`sourceType`)}'`).join(`, `);t.push(`contentType IN (${e})`)}}if(e?.origin&&t.push(`origin = '${d(e.origin,`origin`)}'`),e?.category&&t.push(`category = '${d(e.category,`category`)}'`),e?.tags&&e.tags.length>0){let n=e.tags.map(e=>`tags LIKE '%${d(e,`tag`)}%'`);t.push(`(${n.join(` OR `)})`)}return t.length>0?t.join(` AND `):null}fromLanceRecord(e){return{id:e.id,content:e.content,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath||void 0,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:e.fileHash,indexedAt:e.indexedAt,origin:e.origin,tags:c(e.tags),category:e.category||void 0,version:e.version}}};export{f as LanceStore};
@@ -1,4 +1,4 @@
1
- import{n as e,t}from"./rolldown-runtime-BynbHzcv.js";import{createRequire as n}from"node:module";import{EMBEDDING_DEFAULTS as r,SEARCH_DEFAULTS as i,STORE_DEFAULTS as a,createLogger as o,serializeError as s,sourceTypeContentTypes as c}from"../../core/dist/index.js";import{existsSync as l,mkdirSync as u,readFileSync as d,renameSync as f,unlinkSync as p,writeFileSync as m}from"node:fs";import{dirname as h}from"node:path";const g=o(`sqlite-adapter`),_=n(import.meta.url);var v=class{type=`better-sqlite3`;vectorCapable=!1;db=null;stmtCache=new Map;async open(e){let t;try{t=_(`better-sqlite3`)}catch(e){throw Error(`better-sqlite3 native binding unavailable: ${e instanceof Error?e.message:String(e)}`)}this.db=new t(e),this.db.pragma(`journal_mode = WAL`),this.db.pragma(`foreign_keys = ON`),this.db.pragma(`synchronous = NORMAL`);try{_(`sqlite-vec`).load(this.db),this.vectorCapable=!0,g.info(`sqlite-vec extension loaded`)}catch(e){this.vectorCapable=!1,g.warn(`sqlite-vec extension failed to load; vector search disabled`,s(e))}}exec(e){this.getDb().exec(e)}pragma(e){this.getDb().pragma(e)}queryAll(e,t=[]){let n=this.prepareCached(e);return t.length>0?n.all(...t):n.all()}run(e,t=[]){let n=this.prepareCached(e);t.length>0?n.run(...t):n.run()}flush(){}close(){this.db&&=(this.stmtCache.clear(),this.db.close(),null)}getDb(){if(!this.db)throw Error(`BetterSqlite3Adapter: database not opened`);return this.db}prepareCached(e){let t=this.stmtCache.get(e);if(t)return t;let n=this.getDb().prepare(e);return this.stmtCache.set(e,n),n}};function y(e){return _.resolve(`sql.js/dist/${e}`)}var b=class{type=`sql.js`;vectorCapable=!1;db=null;dbPath=``;dirty=!1;inTransaction=!1;async open(e){this.dbPath=e;let t=(await import(`sql.js`)).default,n=await t({locateFile:e=>y(e)});if(l(e)){let t=d(e);this.db=new n.Database(t)}else this.db=new n.Database}exec(e){let t=e.trimStart().toUpperCase();this.getDb().run(e),t.startsWith(`BEGIN`)?this.inTransaction=!0:(t.startsWith(`COMMIT`)||t.startsWith(`ROLLBACK`))&&(this.inTransaction=!1),this.dirty=!0}pragma(e){this.getDb().exec(`PRAGMA ${e}`)}queryAll(e,t=[]){let n=this.getDb().prepare(e);try{t.length>0&&n.bind(t);let e=[];for(;n.step();)e.push(n.getAsObject());return e}finally{n.free()}}run(e,t=[]){let n=this.getDb(),r=e.trimStart().toUpperCase(),i=!this.inTransaction&&(r.startsWith(`INSERT`)||r.startsWith(`UPDATE`));i&&n.run(`SAVEPOINT fk_check`);try{if(t.length>0){let r=n.prepare(e);try{r.bind(t),r.step()}finally{r.free()}}else n.run(e);if(i){if(n.exec(`PRAGMA foreign_key_check`).length>0)throw n.run(`ROLLBACK TO fk_check`),n.run(`RELEASE fk_check`),Error(`FOREIGN KEY constraint failed`);n.run(`RELEASE fk_check`)}}catch(e){if(i)try{n.run(`ROLLBACK TO fk_check`),n.run(`RELEASE fk_check`)}catch{}throw e}this.dirty=!0}flush(){if(!this.dirty||!this.db)return;let e=this.db.export(),t=`${this.dbPath}.tmp`;m(t,Buffer.from(e)),f(t,this.dbPath),this.dirty=!1}close(){if(this.db){let e=this.db,t;try{this.flush()}catch(e){t=e;try{p(`${this.dbPath}.tmp`)}catch{}}try{e.close()}finally{this.db=null}if(t)throw t}}getDb(){if(!this.db)throw Error(`SqlJsAdapter: database not opened`);return this.db}};let x=!1;async function S(e){let t=new v;try{return await t.open(e),t}catch(e){x||(x=!0,g.warn(`[aikit] better-sqlite3 unavailable — falling back to sql.js (vector search disabled). Reinstall with prebuild support or rebuild from source to enable vector search.`,s(e)))}let n=new b;try{return await n.open(e),n}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`[aikit] SQLite adapter "sql.js" failed to load: ${t}`)}}async function C(e){let t=new b;return await t.open(e),t}var w=t({SqliteVecStore:()=>A});function T(e){let t=0;for(let n=0;n<e.length;n++){let r=e[n]<0?-e[n]:e[n];r>t&&(t=r)}let n=new Int8Array(e.length);if(t===0)return Buffer.from(n.buffer,n.byteOffset,n.byteLength);let r=127/t;for(let t=0;t<e.length;t++){let i=Math.round(e[t]*r);n[t]=i<-127?-127:i>127?127:i}return Buffer.from(n.buffer,n.byteOffset,n.byteLength)}const E=/^[\w.\-/ ]+$/,D=o(`sqlite-vec-store`);function O(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function k(e,t){if(!E.test(e))throw Error(`Invalid ${t} filter value: contains disallowed characters`);return e}var A=class{adapter=null;externalAdapter;dbPath;embeddingDim;coarseDim;vectorEnabled=!1;warnedVectorDisabled=!1;_draining=!1;_priorityQueue=[];_normalQueue=[];_onCloseHooks=[];constructor(e={}){this.embeddingDim=e.embeddingDim??r.dimensions,this.coarseDim=Math.min(128,this.embeddingDim),e.adapter?(this.adapter=e.adapter,this.externalAdapter=!0,this.dbPath=``):(this.dbPath=e.path??`${a.path}/aikit.db`,this.externalAdapter=!1)}async initialize(){if(!this.adapter){let e=h(this.dbPath);l(e)||u(e,{recursive:!0}),this.adapter=await S(this.dbPath)}this.vectorEnabled=this.adapter.vectorCapable,this.createKnowledgeTable(),this.createFtsTable(),this.vectorEnabled?this.ensureVecTable():this.warnedVectorDisabled||(this.warnedVectorDisabled=!0,D.warn(`SqliteVecStore: vector search disabled (sqlite-vec extension not loaded). Hybrid search will return FTS-only results.`))}getDiagnostics(){let t=this.adapter,n=t?t.constructor.name:`unknown`,r=null,i=this.externalAdapter?``:this.dbPath;if(i)try{let{statSync:t}=e(`node:fs`);r=t(i).size}catch{r=null}return{adapterType:n,vectorSearchEnabled:this.vectorEnabled,degradedMode:!this.vectorEnabled,dbPath:i,dbSizeBytes:r,embeddingDim:this.embeddingDim,vectorDtype:`int8`}}createKnowledgeTable(){let e=this.getAdapter();e.exec(`
1
+ import{createRequire as e}from"node:module";import{existsSync as t,mkdirSync as n,readFileSync as r,renameSync as i,unlinkSync as a,writeFileSync as o}from"node:fs";import{EMBEDDING_DEFAULTS as s,SEARCH_DEFAULTS as c,STORE_DEFAULTS as l,createLogger as u,serializeError as d,sourceTypeContentTypes as f}from"../../core/dist/index.js";import{dirname as p}from"node:path";var m=Object.defineProperty,h=(e,t)=>{let n={};for(var r in e)m(n,r,{get:e[r],enumerable:!0});return t||m(n,Symbol.toStringTag,{value:`Module`}),n},g=e(import.meta.url);const _=u(`sqlite-adapter`),v=e(import.meta.url);var y=class{type=`better-sqlite3`;vectorCapable=!1;db=null;stmtCache=new Map;async open(e){let t;try{t=v(`better-sqlite3`)}catch(e){throw Error(`better-sqlite3 native binding unavailable: ${e instanceof Error?e.message:String(e)}`)}this.db=new t(e),this.db.pragma(`journal_mode = WAL`),this.db.pragma(`foreign_keys = ON`),this.db.pragma(`synchronous = NORMAL`);try{v(`sqlite-vec`).load(this.db),this.vectorCapable=!0,_.info(`sqlite-vec extension loaded`)}catch(e){this.vectorCapable=!1,_.warn(`sqlite-vec extension failed to load; vector search disabled`,d(e))}}exec(e){this.getDb().exec(e)}pragma(e){this.getDb().pragma(e)}queryAll(e,t=[]){let n=this.prepareCached(e);return t.length>0?n.all(...t):n.all()}run(e,t=[]){let n=this.prepareCached(e);t.length>0?n.run(...t):n.run()}flush(){}close(){this.db&&=(this.stmtCache.clear(),this.db.close(),null)}getDb(){if(!this.db)throw Error(`BetterSqlite3Adapter: database not opened`);return this.db}prepareCached(e){let t=this.stmtCache.get(e);if(t)return t;let n=this.getDb().prepare(e);return this.stmtCache.set(e,n),n}};function b(e){return v.resolve(`sql.js/dist/${e}`)}var x=class{type=`sql.js`;vectorCapable=!1;db=null;dbPath=``;dirty=!1;inTransaction=!1;async open(e){this.dbPath=e;let n=(await import(`sql.js`)).default,i=await n({locateFile:e=>b(e)});if(t(e)){let t=r(e);this.db=new i.Database(t)}else this.db=new i.Database}exec(e){let t=e.trimStart().toUpperCase();this.getDb().run(e),t.startsWith(`BEGIN`)?this.inTransaction=!0:(t.startsWith(`COMMIT`)||t.startsWith(`ROLLBACK`))&&(this.inTransaction=!1),this.dirty=!0}pragma(e){this.getDb().exec(`PRAGMA ${e}`)}queryAll(e,t=[]){let n=this.getDb().prepare(e);try{t.length>0&&n.bind(t);let e=[];for(;n.step();)e.push(n.getAsObject());return e}finally{n.free()}}run(e,t=[]){let n=this.getDb(),r=e.trimStart().toUpperCase(),i=!this.inTransaction&&(r.startsWith(`INSERT`)||r.startsWith(`UPDATE`));i&&n.run(`SAVEPOINT fk_check`);try{if(t.length>0){let r=n.prepare(e);try{r.bind(t),r.step()}finally{r.free()}}else n.run(e);if(i){if(n.exec(`PRAGMA foreign_key_check`).length>0)throw n.run(`ROLLBACK TO fk_check`),n.run(`RELEASE fk_check`),Error(`FOREIGN KEY constraint failed`);n.run(`RELEASE fk_check`)}}catch(e){if(i)try{n.run(`ROLLBACK TO fk_check`),n.run(`RELEASE fk_check`)}catch{}throw e}this.dirty=!0}flush(){if(!this.dirty||!this.db)return;let e=this.db.export(),t=`${this.dbPath}.tmp`;o(t,Buffer.from(e)),i(t,this.dbPath),this.dirty=!1}close(){if(this.db){let e=this.db,t;try{this.flush()}catch(e){t=e;try{a(`${this.dbPath}.tmp`)}catch{}}try{e.close()}finally{this.db=null}if(t)throw t}}getDb(){if(!this.db)throw Error(`SqlJsAdapter: database not opened`);return this.db}};let S=!1;async function C(e){let t=new y;try{return await t.open(e),t}catch(e){S||(S=!0,_.warn(`[aikit] better-sqlite3 unavailable — falling back to sql.js (vector search disabled). Reinstall with prebuild support or rebuild from source to enable vector search.`,d(e)))}let n=new x;try{return await n.open(e),n}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`[aikit] SQLite adapter "sql.js" failed to load: ${t}`)}}async function w(e){let t=new x;return await t.open(e),t}var T=h({SqliteVecStore:()=>j});function E(e){let t=0;for(let n=0;n<e.length;n++){let r=e[n]<0?-e[n]:e[n];r>t&&(t=r)}let n=new Int8Array(e.length);if(t===0)return Buffer.from(n.buffer,n.byteOffset,n.byteLength);let r=127/t;for(let t=0;t<e.length;t++){let i=Math.round(e[t]*r);n[t]=i<-127?-127:i>127?127:i}return Buffer.from(n.buffer,n.byteOffset,n.byteLength)}const D=/^[\w.\-/ ]+$/,O=u(`sqlite-vec-store`);function k(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function A(e,t){if(!D.test(e))throw Error(`Invalid ${t} filter value: contains disallowed characters`);return e}var j=class{adapter=null;externalAdapter;dbPath;embeddingDim;coarseDim;vectorEnabled=!1;warnedVectorDisabled=!1;_draining=!1;_priorityQueue=[];_normalQueue=[];_onCloseHooks=[];constructor(e={}){this.embeddingDim=e.embeddingDim??s.dimensions,this.coarseDim=Math.min(128,this.embeddingDim),e.adapter?(this.adapter=e.adapter,this.externalAdapter=!0,this.dbPath=``):(this.dbPath=e.path??`${l.path}/aikit.db`,this.externalAdapter=!1)}async initialize(){if(!this.adapter){let e=p(this.dbPath);t(e)||n(e,{recursive:!0}),this.adapter=await C(this.dbPath)}this.vectorEnabled=this.adapter.vectorCapable,this.createKnowledgeTable(),this.createFtsTable(),this.vectorEnabled?this.ensureVecTable():this.warnedVectorDisabled||(this.warnedVectorDisabled=!0,O.warn(`SqliteVecStore: vector search disabled (sqlite-vec extension not loaded). Hybrid search will return FTS-only results.`))}getDiagnostics(){let e=this.adapter,t=e?e.constructor.name:`unknown`,n=null,r=this.externalAdapter?``:this.dbPath;if(r)try{let{statSync:e}=g(`node:fs`);n=e(r).size}catch{n=null}return{adapterType:t,vectorSearchEnabled:this.vectorEnabled,degradedMode:!this.vectorEnabled,dbPath:r,dbSizeBytes:n,embeddingDim:this.embeddingDim,vectorDtype:`int8`}}createKnowledgeTable(){let e=this.getAdapter();e.exec(`
2
2
  CREATE TABLE IF NOT EXISTS knowledge (
3
3
  id TEXT PRIMARY KEY,
4
4
  content TEXT NOT NULL,
@@ -23,7 +23,7 @@ import{n as e,t}from"./rolldown-runtime-BynbHzcv.js";import{createRequire as n}f
23
23
  content,
24
24
  tokenize = 'unicode61 remove_diacritics 2'
25
25
  )
26
- `)}ensureVecTable(){let e=this.getAdapter(),t=e.queryAll(`SELECT name, sql FROM sqlite_master WHERE type='table' AND name='vec_knowledge'`);if(t.length>0){let n=t[0].sql??``,r=n.match(/(?:float|int8)\[(\d+)\]/i),i=r?Number(r[1]):null,a=/int8\[/i.test(n);(i!==null&&i!==this.embeddingDim||!a)&&(D.warn(`Vec table schema mismatch — dropping for recreation`,{existingDim:i,newDim:this.embeddingDim,wasInt8:a}),e.exec(`DROP TABLE vec_knowledge`))}e.exec(`
26
+ `)}ensureVecTable(){let e=this.getAdapter(),t=e.queryAll(`SELECT name, sql FROM sqlite_master WHERE type='table' AND name='vec_knowledge'`);if(t.length>0){let n=t[0].sql??``,r=n.match(/(?:float|int8)\[(\d+)\]/i),i=r?Number(r[1]):null,a=/int8\[/i.test(n);(i!==null&&i!==this.embeddingDim||!a)&&(O.warn(`Vec table schema mismatch — dropping for recreation`,{existingDim:i,newDim:this.embeddingDim,wasInt8:a}),e.exec(`DROP TABLE vec_knowledge`))}e.exec(`
27
27
  CREATE VIRTUAL TABLE IF NOT EXISTS vec_knowledge USING vec0(
28
28
  embedding int8[${this.embeddingDim}] distance_metric=cosine,
29
29
  +knowledge_id TEXT
@@ -33,7 +33,7 @@ import{n as e,t}from"./rolldown-runtime-BynbHzcv.js";import{createRequire as n}f
33
33
  embedding int8[${this.coarseDim}] distance_metric=cosine,
34
34
  +knowledge_id TEXT
35
35
  )
36
- `)}enqueueWrite(e,t=!1){return new Promise((n,r)=>{let i=async()=>{try{n(await e())}catch(e){r(e)}};t?this._priorityQueue.push(i):this._normalQueue.push(i),this._drain()})}async _drain(){if(!this._draining){this._draining=!0;try{for(;this._priorityQueue.length>0||this._normalQueue.length>0;){let e=this._priorityQueue.shift()??this._normalQueue.shift();e&&await e()}}finally{this._draining=!1}}}async upsert(e,t){if(e.length!==0){if(e.length!==t.length)throw Error(`Record count (${e.length}) does not match vector count (${t.length})`);return this.enqueueWrite(()=>this._upsertImpl(e,t))}}async upsertInteractive(e,t){if(e.length!==0){if(e.length!==t.length)throw Error(`Record count (${e.length}) does not match vector count (${t.length})`);return this.enqueueWrite(()=>this._upsertImpl(e,t),!0)}}async upsertWithoutVector(e,t){return this.enqueueWrite(async()=>{let n=this.getAdapter(),r=e;n.exec(`BEGIN`);try{if(this.upsertKnowledgeRow(r),n.run(`DELETE FROM knowledge_fts WHERE id = ?`,[r.id]),n.run(`INSERT INTO knowledge_fts (id, content) VALUES (?, ?)`,[r.id,r.content]),this.vectorEnabled){let e=n.queryAll(`SELECT embedding FROM vec_knowledge WHERE knowledge_id = ?`,[t]);if(e.length>0){if(n.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[r.id]),n.run(`INSERT INTO vec_knowledge (embedding, knowledge_id) VALUES (vec_int8(?), ?)`,[e[0].embedding,r.id]),this.coarseDim<this.embeddingDim){let e=n.queryAll(`SELECT embedding FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[t]);e.length>0&&(n.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[r.id]),n.run(`INSERT INTO vec_knowledge_coarse (embedding, knowledge_id) VALUES (vec_int8(?), ?)`,[e[0].embedding,r.id]))}}else D.warn(`upsertWithoutVector: source vector not found, record will lack vector`,{recordId:r.id,sourceRecordId:t})}n.exec(`COMMIT`)}catch(e){try{n.exec(`ROLLBACK`)}catch{}throw e}n.flush()})}upsertKnowledgeRow(e){this.getAdapter().run(`INSERT INTO knowledge (id, content, sourcePath, contentType, headingPath, chunkIndex,
36
+ `)}enqueueWrite(e,t=!1){return new Promise((n,r)=>{let i=async()=>{try{n(await e())}catch(e){r(e)}};t?this._priorityQueue.push(i):this._normalQueue.push(i),this._drain()})}async _drain(){if(!this._draining){this._draining=!0;try{for(;this._priorityQueue.length>0||this._normalQueue.length>0;){let e=this._priorityQueue.shift()??this._normalQueue.shift();e&&await e()}}finally{this._draining=!1}}}async upsert(e,t){if(e.length!==0){if(e.length!==t.length)throw Error(`Record count (${e.length}) does not match vector count (${t.length})`);return this.enqueueWrite(()=>this._upsertImpl(e,t))}}async upsertInteractive(e,t){if(e.length!==0){if(e.length!==t.length)throw Error(`Record count (${e.length}) does not match vector count (${t.length})`);return this.enqueueWrite(()=>this._upsertImpl(e,t),!0)}}async upsertWithoutVector(e,t){return this.enqueueWrite(async()=>{let n=this.getAdapter(),r=e;n.exec(`BEGIN`);try{if(this.upsertKnowledgeRow(r),n.run(`DELETE FROM knowledge_fts WHERE id = ?`,[r.id]),n.run(`INSERT INTO knowledge_fts (id, content) VALUES (?, ?)`,[r.id,r.content]),this.vectorEnabled){let e=n.queryAll(`SELECT embedding FROM vec_knowledge WHERE knowledge_id = ?`,[t]);if(e.length>0){if(n.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[r.id]),n.run(`INSERT INTO vec_knowledge (embedding, knowledge_id) VALUES (vec_int8(?), ?)`,[e[0].embedding,r.id]),this.coarseDim<this.embeddingDim){let e=n.queryAll(`SELECT embedding FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[t]);e.length>0&&(n.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[r.id]),n.run(`INSERT INTO vec_knowledge_coarse (embedding, knowledge_id) VALUES (vec_int8(?), ?)`,[e[0].embedding,r.id]))}}else O.warn(`upsertWithoutVector: source vector not found, record will lack vector`,{recordId:r.id,sourceRecordId:t})}n.exec(`COMMIT`)}catch(e){try{n.exec(`ROLLBACK`)}catch{}throw e}n.flush()})}upsertKnowledgeRow(e){this.getAdapter().run(`INSERT INTO knowledge (id, content, sourcePath, contentType, headingPath, chunkIndex,
37
37
  totalChunks, startLine, endLine, fileHash, content_hash, indexedAt, origin, tags, category, version)
38
38
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
39
39
  ON CONFLICT(id) DO UPDATE SET
@@ -51,7 +51,7 @@ import{n as e,t}from"./rolldown-runtime-BynbHzcv.js";import{createRequire as n}f
51
51
  origin = excluded.origin,
52
52
  tags = excluded.tags,
53
53
  category = excluded.category,
54
- version = excluded.version`,[e.id,e.content,e.sourcePath,e.contentType,e.headingPath??``,e.chunkIndex,e.totalChunks,e.startLine,e.endLine,e.fileHash,e.contentHash??``,e.indexedAt,e.origin,JSON.stringify(e.tags??[]),e.category??``,e.version])}async _upsertImpl(e,t){let n=this.getAdapter();n.exec(`BEGIN`);try{for(let r=0;r<e.length;r++){let i=e[r];if(this.upsertKnowledgeRow(i),n.run(`DELETE FROM knowledge_fts WHERE id = ?`,[i.id]),n.run(`INSERT INTO knowledge_fts (id, content) VALUES (?, ?)`,[i.id,i.content]),this.vectorEnabled&&(n.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[i.id]),n.run(`INSERT INTO vec_knowledge (embedding, knowledge_id) VALUES (vec_int8(?), ?)`,[T(t[r]),i.id]),this.coarseDim<this.embeddingDim)){let e=t[r].subarray(0,this.coarseDim);n.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[i.id]),n.run(`INSERT INTO vec_knowledge_coarse (embedding, knowledge_id) VALUES (vec_int8(?), ?)`,[T(e),i.id])}}n.exec(`COMMIT`)}catch(e){try{n.exec(`ROLLBACK`)}catch{}throw e}n.flush()}async search(e,t){if(!this.vectorEnabled)return this.warnedVectorDisabled||(this.warnedVectorDisabled=!0,D.warn(`search() called but vector backend is disabled — returning []`)),[];let n=this.getAdapter(),r=t?.limit??i.maxResults,a=t?.minScore??i.minScore,o=r*4,c=`
54
+ version = excluded.version`,[e.id,e.content,e.sourcePath,e.contentType,e.headingPath??``,e.chunkIndex,e.totalChunks,e.startLine,e.endLine,e.fileHash,e.contentHash??``,e.indexedAt,e.origin,JSON.stringify(e.tags??[]),e.category??``,e.version])}async _upsertImpl(e,t){let n=this.getAdapter();n.exec(`BEGIN`);try{for(let r=0;r<e.length;r++){let i=e[r];if(this.upsertKnowledgeRow(i),n.run(`DELETE FROM knowledge_fts WHERE id = ?`,[i.id]),n.run(`INSERT INTO knowledge_fts (id, content) VALUES (?, ?)`,[i.id,i.content]),this.vectorEnabled&&(n.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[i.id]),n.run(`INSERT INTO vec_knowledge (embedding, knowledge_id) VALUES (vec_int8(?), ?)`,[E(t[r]),i.id]),this.coarseDim<this.embeddingDim)){let e=t[r].subarray(0,this.coarseDim);n.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[i.id]),n.run(`INSERT INTO vec_knowledge_coarse (embedding, knowledge_id) VALUES (vec_int8(?), ?)`,[E(e),i.id])}}n.exec(`COMMIT`)}catch(e){try{n.exec(`ROLLBACK`)}catch{}throw e}n.flush()}async search(e,t){if(!this.vectorEnabled)return this.warnedVectorDisabled||(this.warnedVectorDisabled=!0,O.warn(`search() called but vector backend is disabled — returning []`)),[];let n=this.getAdapter(),r=t?.limit??c.maxResults,i=t?.minScore??c.minScore,a=r*4,o=`
55
55
  SELECT k.*, v.distance AS _distance
56
56
  FROM (
57
57
  SELECT knowledge_id, distance
@@ -64,7 +64,7 @@ import{n as e,t}from"./rolldown-runtime-BynbHzcv.js";import{createRequire as n}f
64
64
  ${this.buildFilterSqlSuffix(t)}
65
65
  ORDER BY v.distance ASC
66
66
  LIMIT ?
67
- `,l;try{l=n.queryAll(c,[T(e),o,r])}catch(e){return D.warn(`vector search failed`,s(e)),[]}return l.map(e=>({record:this.fromRow(e),score:1-(e._distance??1)})).filter(e=>e.score>=a).slice(0,r)}async coarseSearch(e,t){if(!this.vectorEnabled||this.coarseDim>=this.embeddingDim)return this.search(e,t);let n=this.getAdapter(),r=t?.limit??i.maxResults,a=t?.minScore??i.minScore,o=r*4,c=e.subarray(0,this.coarseDim),l=`
67
+ `,s;try{s=n.queryAll(o,[E(e),a,r])}catch(e){return O.warn(`vector search failed`,d(e)),[]}return s.map(e=>({record:this.fromRow(e),score:1-(e._distance??1)})).filter(e=>e.score>=i).slice(0,r)}async coarseSearch(e,t){if(!this.vectorEnabled||this.coarseDim>=this.embeddingDim)return this.search(e,t);let n=this.getAdapter(),r=t?.limit??c.maxResults,i=t?.minScore??c.minScore,a=r*4,o=e.subarray(0,this.coarseDim),s=`
68
68
  SELECT k.*, v.distance AS _distance
69
69
  FROM (
70
70
  SELECT knowledge_id, distance
@@ -77,7 +77,7 @@ import{n as e,t}from"./rolldown-runtime-BynbHzcv.js";import{createRequire as n}f
77
77
  ${this.buildFilterSqlSuffix(t)}
78
78
  ORDER BY v.distance ASC
79
79
  LIMIT ?
80
- `,u;try{u=n.queryAll(l,[T(c),o,r])}catch(n){return D.warn(`coarse vector search failed, falling back to full search`,s(n)),this.search(e,t)}return u.length===0?this.search(e,t):u.map(e=>({record:this.fromRow(e),score:1-(e._distance??1)})).filter(e=>e.score>=a).slice(0,r)}async ftsSearch(e,t){if(!e||e.trim().length===0)return[];let n=this.getAdapter(),r=t?.limit??i.maxResults,a=`
80
+ `,l;try{l=n.queryAll(s,[E(o),a,r])}catch(n){return O.warn(`coarse vector search failed, falling back to full search`,d(n)),this.search(e,t)}return l.length===0?this.search(e,t):l.map(e=>({record:this.fromRow(e),score:1-(e._distance??1)})).filter(e=>e.score>=i).slice(0,r)}async ftsSearch(e,t){if(!e||e.trim().length===0)return[];let n=this.getAdapter(),r=t?.limit??c.maxResults,i=`
81
81
  SELECT k.*, bm25(knowledge_fts) AS _bm25
82
82
  FROM knowledge_fts
83
83
  JOIN knowledge k ON k.id = knowledge_fts.id
@@ -85,4 +85,4 @@ import{n as e,t}from"./rolldown-runtime-BynbHzcv.js";import{createRequire as n}f
85
85
  ${this.buildFilterSqlSuffix(t,!0)}
86
86
  ORDER BY _bm25 ASC
87
87
  LIMIT ?
88
- `,o;try{let t=j(e);o=n.queryAll(a,[t,r])}catch(e){return D.warn(`fts search failed`,s(e)),[]}return o.map(e=>({record:this.fromRow(e),score:M(e._bm25)}))}async getById(e){let t=this.getAdapter().queryAll(`SELECT * FROM knowledge WHERE id = ? LIMIT 1`,[e]);return t.length===0?null:this.fromRow(t[0])}async deleteBySourcePath(e){return this.enqueueWrite(()=>this._deleteBySourcePathImpl(e))}async _deleteBySourcePathImpl(e){let t=this.getAdapter(),n=t.queryAll(`SELECT id FROM knowledge WHERE sourcePath = ?`,[e]);if(n.length===0)return 0;t.exec(`BEGIN`);try{for(let{id:e}of n)this.vectorEnabled&&(t.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[e]),this.coarseDim<this.embeddingDim&&t.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[e])),t.run(`DELETE FROM knowledge_fts WHERE id = ?`,[e]);t.run(`DELETE FROM knowledge WHERE sourcePath = ?`,[e]),t.exec(`COMMIT`)}catch(e){try{t.exec(`ROLLBACK`)}catch{}throw e}return t.flush(),n.length}async deleteById(e){return this.enqueueWrite(()=>this._deleteByIdImpl(e))}async deleteByIdInteractive(e){return this.enqueueWrite(()=>this._deleteByIdImpl(e),!0)}async _deleteByIdImpl(e){let t=this.getAdapter();if(t.queryAll(`SELECT id FROM knowledge WHERE id = ? LIMIT 1`,[e]).length===0)return!1;t.exec(`BEGIN`);try{this.vectorEnabled&&(t.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[e]),this.coarseDim<this.embeddingDim&&t.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[e])),t.run(`DELETE FROM knowledge_fts WHERE id = ?`,[e]),t.run(`DELETE FROM knowledge WHERE id = ?`,[e]),t.exec(`COMMIT`)}catch(e){try{t.exec(`ROLLBACK`)}catch{}throw e}return t.flush(),!0}async getBySourcePath(e){return this.getAdapter().queryAll(`SELECT * FROM knowledge WHERE sourcePath = ? ORDER BY chunkIndex ASC`,[e]).map(e=>this.fromRow(e))}async getStats(){let e=this.getAdapter(),t=e.queryAll(`SELECT COUNT(*) AS n FROM knowledge`)[0]?.n??0;if(t===0)return{totalRecords:0,totalFiles:0,contentTypeBreakdown:{},lastIndexedAt:null,storeBackend:`sqlite-vec`,embeddingModel:r.model};let n=e.queryAll(`SELECT COUNT(DISTINCT sourcePath) AS n FROM knowledge`),i=e.queryAll(`SELECT contentType, COUNT(*) AS n FROM knowledge GROUP BY contentType`),a=e.queryAll(`SELECT MAX(indexedAt) AS ts FROM knowledge`),o={};for(let e of i)o[e.contentType]=e.n;return{totalRecords:t,totalFiles:n[0]?.n??0,contentTypeBreakdown:o,lastIndexedAt:a[0]?.ts??null,storeBackend:`sqlite-vec`,embeddingModel:r.model}}async listSourcePaths(){return this.getAdapter().queryAll(`SELECT DISTINCT sourcePath FROM knowledge ORDER BY sourcePath`).map(e=>e.sourcePath)}async createFtsIndex(){this.createFtsTable()}async dropTable(){return this.enqueueWrite(()=>this._dropTableImpl())}async _dropTableImpl(){let e=this.getAdapter();e.exec(`DROP TABLE IF EXISTS knowledge_fts`),this.vectorEnabled&&(this.coarseDim<this.embeddingDim&&e.exec(`DROP TABLE IF EXISTS vec_knowledge_coarse`),e.exec(`DROP TABLE IF EXISTS vec_knowledge`)),e.exec(`DROP TABLE IF EXISTS knowledge`),e.flush(),this.createKnowledgeTable(),this.createFtsTable(),this.vectorEnabled&&this.ensureVecTable()}releaseMemory(){if(this.adapter)try{this.adapter.exec(`PRAGMA shrink_memory`),this.adapter.exec(`PRAGMA wal_checkpoint(TRUNCATE)`)}catch{}}onBeforeClose(e){this._onCloseHooks.push(e)}async close(){for(let e of this._onCloseHooks)try{e()}catch{}for(this._onCloseHooks.length=0;this._priorityQueue.length>0||this._normalQueue.length>0||this._draining;)await new Promise(e=>setTimeout(e,5));this.adapter&&!this.externalAdapter&&this.adapter.close(),this.adapter=null}getAdapter(){if(!this.adapter)throw Error(`SqliteVecStore: not initialized — call initialize() first`);return this.adapter}buildFilterSqlSuffix(e,t=!1){if(!e)return``;let n=[];if(e.contentType&&n.push(`k.contentType = '${k(e.contentType,`contentType`)}'`),e.sourceType){let t=c(e.sourceType);if(t.length>0){let e=t.map(e=>`'${k(e,`sourceType`)}'`).join(`, `);n.push(`k.contentType IN (${e})`)}}if(e.origin&&n.push(`k.origin = '${k(e.origin,`origin`)}'`),e.category&&n.push(`k.category = '${k(e.category,`category`)}'`),e.tags&&e.tags.length>0){let t=e.tags.map(e=>`k.tags LIKE '%' || '${k(e,`tag`)}' || '%'`);n.push(`(${t.join(` OR `)})`)}if(n.length===0)return``;let r=n.join(` AND `);return t?`AND ${r}`:`WHERE ${r}`}fromRow(e){return{id:e.id,content:e.content,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath||void 0,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:e.fileHash,contentHash:e.content_hash||void 0,indexedAt:e.indexedAt,origin:e.origin,tags:O(e.tags),category:e.category||void 0,version:e.version}}};function j(e){let t=e.replace(/["'()*:^-]/g,` `).trim();return t?t.split(/\s+/).filter(e=>e.length>0).map(e=>`"${e}"`).join(` OR `):`""`}function M(e){return e==null||Number.isNaN(e)?0:1-Math.exp(-Math.abs(e)/5)}export{S as i,w as n,C as r,A as t};
88
+ `,a;try{let t=M(e);a=n.queryAll(i,[t,r])}catch(e){return O.warn(`fts search failed`,d(e)),[]}return a.map(e=>({record:this.fromRow(e),score:N(e._bm25)}))}async getById(e){let t=this.getAdapter().queryAll(`SELECT * FROM knowledge WHERE id = ? LIMIT 1`,[e]);return t.length===0?null:this.fromRow(t[0])}async deleteBySourcePath(e){return this.enqueueWrite(()=>this._deleteBySourcePathImpl(e))}async _deleteBySourcePathImpl(e){let t=this.getAdapter(),n=t.queryAll(`SELECT id FROM knowledge WHERE sourcePath = ?`,[e]);if(n.length===0)return 0;t.exec(`BEGIN`);try{for(let{id:e}of n)this.vectorEnabled&&(t.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[e]),this.coarseDim<this.embeddingDim&&t.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[e])),t.run(`DELETE FROM knowledge_fts WHERE id = ?`,[e]);t.run(`DELETE FROM knowledge WHERE sourcePath = ?`,[e]),t.exec(`COMMIT`)}catch(e){try{t.exec(`ROLLBACK`)}catch{}throw e}return t.flush(),n.length}async deleteById(e){return this.enqueueWrite(()=>this._deleteByIdImpl(e))}async deleteByIdInteractive(e){return this.enqueueWrite(()=>this._deleteByIdImpl(e),!0)}async _deleteByIdImpl(e){let t=this.getAdapter();if(t.queryAll(`SELECT id FROM knowledge WHERE id = ? LIMIT 1`,[e]).length===0)return!1;t.exec(`BEGIN`);try{this.vectorEnabled&&(t.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[e]),this.coarseDim<this.embeddingDim&&t.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[e])),t.run(`DELETE FROM knowledge_fts WHERE id = ?`,[e]),t.run(`DELETE FROM knowledge WHERE id = ?`,[e]),t.exec(`COMMIT`)}catch(e){try{t.exec(`ROLLBACK`)}catch{}throw e}return t.flush(),!0}async getBySourcePath(e){return this.getAdapter().queryAll(`SELECT * FROM knowledge WHERE sourcePath = ? ORDER BY chunkIndex ASC`,[e]).map(e=>this.fromRow(e))}async getStats(){let e=this.getAdapter(),t=e.queryAll(`SELECT COUNT(*) AS n FROM knowledge`)[0]?.n??0;if(t===0)return{totalRecords:0,totalFiles:0,contentTypeBreakdown:{},lastIndexedAt:null,storeBackend:`sqlite-vec`,embeddingModel:s.model};let n=e.queryAll(`SELECT COUNT(DISTINCT sourcePath) AS n FROM knowledge`),r=e.queryAll(`SELECT contentType, COUNT(*) AS n FROM knowledge GROUP BY contentType`),i=e.queryAll(`SELECT MAX(indexedAt) AS ts FROM knowledge`),a={};for(let e of r)a[e.contentType]=e.n;return{totalRecords:t,totalFiles:n[0]?.n??0,contentTypeBreakdown:a,lastIndexedAt:i[0]?.ts??null,storeBackend:`sqlite-vec`,embeddingModel:s.model}}async listSourcePaths(){return this.getAdapter().queryAll(`SELECT DISTINCT sourcePath FROM knowledge ORDER BY sourcePath`).map(e=>e.sourcePath)}async createFtsIndex(){this.createFtsTable()}async dropTable(){return this.enqueueWrite(()=>this._dropTableImpl())}async _dropTableImpl(){let e=this.getAdapter();e.exec(`DROP TABLE IF EXISTS knowledge_fts`),this.vectorEnabled&&(this.coarseDim<this.embeddingDim&&e.exec(`DROP TABLE IF EXISTS vec_knowledge_coarse`),e.exec(`DROP TABLE IF EXISTS vec_knowledge`)),e.exec(`DROP TABLE IF EXISTS knowledge`),e.flush(),this.createKnowledgeTable(),this.createFtsTable(),this.vectorEnabled&&this.ensureVecTable()}releaseMemory(){if(this.adapter)try{this.adapter.exec(`PRAGMA shrink_memory`),this.adapter.exec(`PRAGMA wal_checkpoint(TRUNCATE)`)}catch{}}onBeforeClose(e){this._onCloseHooks.push(e)}async close(){for(let e of this._onCloseHooks)try{e()}catch{}for(this._onCloseHooks.length=0;this._priorityQueue.length>0||this._normalQueue.length>0||this._draining;)await new Promise(e=>setTimeout(e,5));this.adapter&&!this.externalAdapter&&this.adapter.close(),this.adapter=null}getAdapter(){if(!this.adapter)throw Error(`SqliteVecStore: not initialized — call initialize() first`);return this.adapter}buildFilterSqlSuffix(e,t=!1){if(!e)return``;let n=[];if(e.contentType&&n.push(`k.contentType = '${A(e.contentType,`contentType`)}'`),e.sourceType){let t=f(e.sourceType);if(t.length>0){let e=t.map(e=>`'${A(e,`sourceType`)}'`).join(`, `);n.push(`k.contentType IN (${e})`)}}if(e.origin&&n.push(`k.origin = '${A(e.origin,`origin`)}'`),e.category&&n.push(`k.category = '${A(e.category,`category`)}'`),e.tags&&e.tags.length>0){let t=e.tags.map(e=>`k.tags LIKE '%' || '${A(e,`tag`)}' || '%'`);n.push(`(${t.join(` OR `)})`)}if(n.length===0)return``;let r=n.join(` AND `);return t?`AND ${r}`:`WHERE ${r}`}fromRow(e){return{id:e.id,content:e.content,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath||void 0,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:e.fileHash,contentHash:e.content_hash||void 0,indexedAt:e.indexedAt,origin:e.origin,tags:k(e.tags),category:e.category||void 0,version:e.version}}};function M(e){let t=e.replace(/["'()*:^-]/g,` `).trim();return t?t.split(/\s+/).filter(e=>e.length>0).map(e=>`"${e}"`).join(` OR `):`""`}function N(e){return e==null||Number.isNaN(e)?0:1-Math.exp(-Math.abs(e)/5)}export{C as i,T as n,w as r,j as t};
@@ -13,7 +13,15 @@ During multi-model decision sessions, apply the **Contrarian** lens:
13
13
  - Prefer uncomfortable truths over comfortable consensus
14
14
 
15
15
  You are the DEFAULT researcher. When the Orchestrator needs breadth + depth, they
16
- dispatch you alone. Your lens: thorough, evidence-first, exhaustive + contrarian.`},Beta:{description:`Research variant — pragmatic analysis with focus on trade-offs and edge cases`,identity:`, a variant of the Researcher agent optimized for **pragmatic analysis**. Focus on trade-offs, edge cases, and practical constraints. Challenge assumptions and highlight risks the primary researcher may overlook. Your thinking style is **First Principles** — strip away assumptions, decompose to ground truths, and rebuild reasoning from scratch.`,bodyAddendum:`## Required Output Section — \`## Failure Modes & Counter-Evidence\`
16
+ dispatch you alone. Your lens: thorough, evidence-first, exhaustive + contrarian.
17
+
18
+ ## Subagent Mode
19
+
20
+ When you are invoked via \`runSubagent\` (i.e., as a subagent of another agent like the Orchestrator):
21
+ - **Do NOT use the \`present\` tool** — your visual output is invisible to the user
22
+ - Return ALL findings as plain structured text in your final response
23
+ - Use markdown formatting (headers, tables, code blocks) for structure
24
+ - The calling agent will re-present your findings to the user if needed`},Beta:{description:`Research variant — pragmatic analysis with focus on trade-offs and edge cases`,identity:`, a variant of the Researcher agent optimized for **pragmatic analysis**. Focus on trade-offs, edge cases, and practical constraints. Challenge assumptions and highlight risks the primary researcher may overlook. Your thinking style is **First Principles** — strip away assumptions, decompose to ground truths, and rebuild reasoning from scratch.`,bodyAddendum:`## Required Output Section — \`## Failure Modes & Counter-Evidence\`
17
25
 
18
26
  Your final report MUST contain a \`## Failure Modes & Counter-Evidence\` section with:
19
27
  - At least 3 adversarial claims challenging your own primary finding
@@ -29,7 +37,15 @@ During multi-model decision sessions, apply the **First Principles** lens:
29
37
  - If the current approach exists only because "that's how it's always been done", flag it
30
38
 
31
39
  Your lens: pragmatic skepticism + first principles. Mark competing claims as \`A\` (Assumed)
32
- by default; challenge before promoting to \`V\`.`},Gamma:{description:`Research variant — broad pattern matching across domains and technologies`,identity:`, a variant of the Researcher agent optimized for **cross-domain pattern matching**. Draw connections from other domains, frameworks, and industries. Bring breadth where Alpha brings depth. Your thinking style is **Expansionist** — look for the bigger opportunity, find what's undervalued, and identify patterns others dismiss.`,bodyAddendum:`## Required Output Section — \`## Cross-Domain Analogies\`
40
+ by default; challenge before promoting to \`V\`.
41
+
42
+ ## Subagent Mode
43
+
44
+ When you are invoked via \`runSubagent\` (i.e., as a subagent of another agent like the Orchestrator):
45
+ - **Do NOT use the \`present\` tool** — your visual output is invisible to the user
46
+ - Return ALL findings as plain structured text in your final response
47
+ - Use markdown formatting (headers, tables, code blocks) for structure
48
+ - The calling agent will re-present your findings to the user if needed`},Gamma:{description:`Research variant — broad pattern matching across domains and technologies`,identity:`, a variant of the Researcher agent optimized for **cross-domain pattern matching**. Draw connections from other domains, frameworks, and industries. Bring breadth where Alpha brings depth. Your thinking style is **Expansionist** — look for the bigger opportunity, find what's undervalued, and identify patterns others dismiss.`,bodyAddendum:`## Required Output Section — \`## Cross-Domain Analogies\`
33
49
 
34
50
  Your final report MUST contain a \`## Cross-Domain Analogies\` section with:
35
51
  - At least 2 patterns from other tools/frameworks/domains that apply to the question
@@ -45,7 +61,15 @@ During multi-model decision sessions, apply the **Expansionist** lens:
45
61
  - Challenge narrow framing: "Is this really just an X problem, or is it also a Y problem?"
46
62
 
47
63
  Your lens: cross-domain pattern matching + expansionist. Weight \`web_search\` + \`web_fetch\`
48
- higher than peers. Assume the LLM's training data is stale — verify with fresh searches.`},Delta:{description:`Research variant — implementation feasibility and performance implications`,identity:`, a variant of the Researcher agent optimized for **implementation feasibility**. Focus on performance implications, scaling concerns, and concrete implementation paths. Ground theoretical proposals in practical reality. Your thinking style is **Executor** — focus on what can actually be built, the fastest path to value, and real-world constraints.`,bodyAddendum:`## Required Output Section — \`## Implementation Cost & Feasibility\`
64
+ higher than peers. Assume the LLM's training data is stale — verify with fresh searches.
65
+
66
+ ## Subagent Mode
67
+
68
+ When you are invoked via \`runSubagent\` (i.e., as a subagent of another agent like the Orchestrator):
69
+ - **Do NOT use the \`present\` tool** — your visual output is invisible to the user
70
+ - Return ALL findings as plain structured text in your final response
71
+ - Use markdown formatting (headers, tables, code blocks) for structure
72
+ - The calling agent will re-present your findings to the user if needed`},Delta:{description:`Research variant — implementation feasibility and performance implications`,identity:`, a variant of the Researcher agent optimized for **implementation feasibility**. Focus on performance implications, scaling concerns, and concrete implementation paths. Ground theoretical proposals in practical reality. Your thinking style is **Executor** — focus on what can actually be built, the fastest path to value, and real-world constraints.`,bodyAddendum:`## Required Output Section — \`## Implementation Cost & Feasibility\`
49
73
 
50
74
  Your final report MUST contain a \`## Implementation Cost & Feasibility\` section with:
51
75
  - Complexity snapshot: you MUST call \`measure({ path })\` on any file ≥ 50 LOC in the
@@ -62,7 +86,15 @@ During multi-model decision sessions, apply the **Executor** lens:
62
86
  - Reject elegant theory that can't survive contact with the codebase
63
87
 
64
88
  Your lens: implementation feasibility + executor. Prefer \`measure\` + \`blast_radius\` +
65
- \`analyze({ aspect: "patterns", ... })\` over abstract reasoning.`}}},"Code-Reviewer":{title:`The Quality Guardian`,description:`Code review specialist analyzing code for quality, security, performance, and maintainability`,argumentHint:`File path, PR, or code to review`,toolRole:`reviewer`,sharedBase:`code-reviewer-base`,category:`review`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`typescript`,`When reviewing TypeScript code — type patterns, best practices`]],variants:{Alpha:{description:`Primary code reviewer`,identity:`, the primary Code-Reviewer agent. Your lens is **compliance and red-teaming** — you hunt for correctness bugs, security holes, and contract violations that will break in production.`,bodyAddendum:`## Review Lens: Compliance & Red-Team
89
+ \`analyze({ aspect: "patterns", ... })\` over abstract reasoning.
90
+
91
+ ## Subagent Mode
92
+
93
+ When you are invoked via \`runSubagent\` (i.e., as a subagent of another agent like the Orchestrator):
94
+ - **Do NOT use the \`present\` tool** — your visual output is invisible to the user
95
+ - Return ALL findings as plain structured text in your final response
96
+ - Use markdown formatting (headers, tables, code blocks) for structure
97
+ - The calling agent will re-present your findings to the user if needed`}}},"Code-Reviewer":{title:`The Quality Guardian`,description:`Code review specialist analyzing code for quality, security, performance, and maintainability`,argumentHint:`File path, PR, or code to review`,toolRole:`reviewer`,sharedBase:`code-reviewer-base`,category:`review`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`typescript`,`When reviewing TypeScript code — type patterns, best practices`]],variants:{Alpha:{description:`Primary code reviewer`,identity:`, the primary Code-Reviewer agent. Your lens is **compliance and red-teaming** — you hunt for correctness bugs, security holes, and contract violations that will break in production.`,bodyAddendum:`## Review Lens: Compliance & Red-Team
66
98
 
67
99
  Your primary focus areas (in order of priority):
68
100
  1. **Correctness** — Logic errors, race conditions, null/undefined paths, off-by-one
@@ -88,6 +88,7 @@ This is the **proportional response** — match ceremony to complexity. Floor-ti
88
88
  | Task matches a custom flow's description/tags exactly | That custom flow |
89
89
 
90
90
  - **Auto-start:** When exactly one flow matches, start it immediately — \`flow({ action: 'start', name: '<matched>', topic: '<task description>' })\` — and inform the user which flow was activated and why. The \`topic\` becomes the \`.flows/\` directory name (slugified).
91
+ - **Root detection (multi-root):** If the flow list response shows \`allRoots.length > 1\`, identify which root(s) the task targets (from file paths in the task, or via \`blast_radius\`/\`graph\`). Always pass \`roots\` in multi-root workspaces: \`flow({ action: 'start', name: '<flow>', topic: '<task>', roots: ['<target-repo-path>'] })\`. Omitting \`roots\` creates \`.flows/\` at the workspace root — almost never the intended location.
91
92
  - **Ask only when ambiguous:** If the task could fit multiple flows, or no flow clearly matches, present the options and let the user choose.
92
93
  - Do NOT present a menu for obvious cases. Speed matters.
93
94
  4. **Every Standard/Critical task goes through a flow.** Floor-tier tasks use the fast path above.
@@ -180,6 +181,7 @@ Batch 2 (after batch 1):
180
181
  5. **Artifacts Path** — the active flow's run directory and artifacts path from \`flow({ action: 'status' })\` (e.g. \`.flows/add-authentication/.spec/\`)
181
182
  6. **FORGE** — tier + task_id + evidence requirements (reviewers add CRITICAL/HIGH claims into your task_id; never create their own)
182
183
  7. **Self-Review** — checklist before declaring status
184
+ 8. **No present** — "Do NOT use the \`present\` tool — return all findings as structured text"
183
185
 
184
186
  **Subagent status protocol:** \`DONE\` | \`DONE_WITH_CONCERNS\` | \`NEEDS_CONTEXT\` | \`BLOCKED\`
185
187
 
@@ -204,7 +206,7 @@ When the IDE workspace contains **multiple repository roots**, flows support cro
204
206
 
205
207
  **Detection:** \`flow({ action: 'list' })\` and \`flow({ action: 'status' })\` return \`allRoots\` — the list of all workspace roots. When \`allRoots.length > 1\`, the workspace is multi-root.
206
208
 
207
- **Single-repo task (default):** Omit the \`roots\` parameterflow creates \`.flows/\` in the primary root only.
209
+ **Single-repo task (default):** If the workspace has only one root, omit \`roots\`. In multi-root workspaces, **always pass \`roots\`** targeting the specific repo omitting it creates \`.flows/\` at the workspace root, which is almost never the intended location.
208
210
 
209
211
  **Multi-repo task:** Pass \`roots\` to \`flow({ action: 'start', ... })\` listing ALL participating repositories:
210
212
  \`\`\`
@@ -221,7 +223,7 @@ This creates \`.flows/cross-repo-auth/\` with synchronized \`meta.json\` in each
221
223
 
222
224
  | Signal | Action |
223
225
  |--------|--------|
224
- | Task touches files in 1 repo | Omit \`roots\` (single-root default) |
226
+ | Task touches files in 1 repo | Pass that repo as \`roots\` (in multi-root workspaces) |
225
227
  | Task touches files in 2+ repos | Pass those repos as \`roots\` |
226
228
  | Shared types/contracts change | Include all repos that consume them |
227
229
  | Unsure which repos are affected | Use \`blast_radius\` + \`graph\` first, then decide |
@@ -284,6 +286,7 @@ For maximum token efficiency, instruct subagents to use the **meta-tool discover
284
286
  ## Subagent Output Relay
285
287
 
286
288
  When subagents complete, their visual outputs (from \`present\`) are NOT visible to the user.
289
+ **Prevention:** Always include "Do NOT use the \`present\` tool — return all findings as plain text" in every subagent dispatch prompt, including researcher dispatches for the Multi-Model Decision Protocol.
287
290
  **You MUST relay key findings:**
288
291
 
289
292
  1. After every subagent completes, extract key data from the returned text
@@ -344,6 +347,7 @@ Before every tool call, verify:
344
347
  | \`lesson-learned\` | After completing work — extract engineering principles |
345
348
  | \`docs\` | During \`_docs-sync\` epilogue — living documentation convention, templates, change-to-doc mapping |
346
349
  | \`repo-access\` | **IMMEDIATELY** when YOU or any subagent get auth failures from \`web_fetch\`, \`http\`, or git commands (401, 403, 404, SSO redirect, login HTML, "Permission denied"). NEVER declare a repo "inaccessible" without first loading this skill and walking the Strategy Ladder |
350
+ | \`browser-use\` | When \`repo-access\` Strategy Ladder is exhausted and auth requires browser interaction (SAML SSO, OAuth consent, 2FA). Also for web scraping, form filling, UI testing, or any task needing a real browser. Pairs with \`repo-access\` |
347
351
 
348
352
  ## Repo Access — HARD RULE
349
353
 
@@ -351,7 +355,8 @@ Before every tool call, verify:
351
355
  1. **STOP** — do NOT declare the repo "inaccessible" or "behind SSO"
352
356
  2. **Load the \`repo-access\` skill** and follow its Strategy Ladder
353
357
  3. **Walk all 5 steps** before concluding access is impossible
354
- 4. **Include \`repo-access\` in subagent prompts** when delegating tasks that touch the same repo
358
+ 4. If Strategy Ladder is exhausted and auth requires browser interaction → **load \`browser-use\` skill** for browser-based auth recovery (SAML SSO, OAuth, 2FA flows)
359
+ 5. **Include \`repo-access\` and \`browser-use\` in subagent prompts** when delegating tasks that touch the same repo
355
360
 
356
361
  This applies to YOU (the Orchestrator) when you use \`web_fetch\`/\`http\` directly, not just subagents.
357
362
 
@@ -441,6 +446,7 @@ The Planner is typically activated by the Orchestrator as part of a flow step (e
441
446
  ## Subagent Output Relay
442
447
 
443
448
  When subagents complete, their visual outputs (from \`present\`) are NOT visible to the user.
449
+ **Prevention:** Always include "Do NOT use the \`present\` tool — return all findings as plain text" in every subagent dispatch prompt, including researcher dispatches for the Multi-Model Decision Protocol.
444
450
  **You MUST relay key findings:**
445
451
 
446
452
  1. After every subagent completes, extract key data from the returned text
@@ -492,7 +498,8 @@ When subagents complete, their visual outputs (from \`present\`) are NOT visible
492
498
  | \`c4-architecture\` | When the plan involves architectural changes — generate C4 diagrams |
493
499
  | \`adr-skill\` | When the plan involves non-trivial technical decisions — create executable ADRs |
494
500
  | \`session-handoff\` | When context window is filling up, planning session ending, or major milestone completed |
495
- | \`repo-access\` | When the plan involves accessing private, enterprise, or self-hosted repositories |`,Implementer:"**Read `AGENTS.md`** in the workspace root for project conventions and AI Kit protocol.\n\nLoad the `aikit` skill for full tool documentation, workflow chains, and session protocol.\n\n## Implementation Protocol\n\n1. **Understand scope** — Read the phase objective, identify target files\n2. **Write test first** (Red) — Create failing tests that define expected behavior\n3. **Implement** (Green) — Write minimal code to make tests pass\n4. **Refactor** — Clean up while keeping tests green\n5. **Validate** — `check`, `test_run`, `blast_radius`\n6. **Persist** — `remember` any decisions or patterns discovered\n\n## Rules\n\n- **Test-first always** — No implementation without a failing test\n- **Minimal code** — Don't build what isn't asked for\n- **Follow existing patterns** — Search AI Kit for conventions before creating new ones (`search(\"convention\")`, `knowledge({ action: \"list\", category: \"conventions\" })`)\n- **Never modify tests to make them pass** — Fix the implementation instead\n- **Run `check` after every change** — Catch errors early\n- **Loop-break** — If the same test fails 3 times with the same error after your fixes, STOP. Re-read the error from scratch, check your assumptions with `trace` or `symbol`, and try a fundamentally different approach. Do not attempt a 4th fix in the same direction\n- **Think-first for complex tasks** — If a task involves 3+ files or non-obvious logic, outline your approach before writing code. Check existing patterns with `search` first. Design, then implement\n\n## Pre-Edit Checklist (before modifying any file)\n\n1. **Understand consumers** — `graph({action:'find_nodes', name_pattern:'<target>'})` → `graph({action:'neighbors', node_id, direction:'incoming'})`. See who calls/imports before changing a contract.\n2. **Compress, don't raw-read** — `file_summary` then `compact({path, query})` for the specific area. Only `read_file` when you need exact lines for `replace_string_in_file`.\n3. **Snapshot risky edits** — `checkpoint({action:'save', label:'pre-<scope>'})` before cross-cutting changes. `checkpoint({action:'restore', ...})` if `check`/`test_run` fails.\n4. **Estimate blast radius** — `blast_radius({changed_files:[...]})` BEFORE editing when changing a public/shared symbol; re-run AFTER to confirm actual impact matches.\n5. **TDD when tests exist** — write/extend the failing test first, then minimum code to pass.\n\n## Post-Edit Checklist\n\n1. `check({})` — typecheck + lint must pass clean\n2. `test_run({})` — full suite or targeted pattern\n3. If Orchestrator passed a `task_id`: `evidence_map({action:'add', task_id, claim, status:'V', receipt:'file.ts#Lxx'})` for each verified contract/acceptance claim. Do NOT run the gate — Orchestrator owns it.",Frontend:"**Read `AGENTS.md`** in the workspace root for project conventions and AI Kit protocol.\n\nLoad the `aikit` skill for full tool documentation, workflow chains, and session protocol.\n\n## Frontend Protocol\n\n1. **Search AI Kit** for existing component patterns and design tokens\n2. **Write component tests first** — Accessibility, rendering, interaction\n3. **Implement** — Follow existing component patterns, use design system tokens\n4. **Validate** — `check`, `test_run`, visual review\n5. **Persist** — `remember` new component patterns\n\n## Rules\n\n- **Accessibility first** — ARIA attributes, keyboard navigation, screen reader support\n- **Follow design system** — Use existing tokens, don't create one-off values\n- **Responsive by default** — Mobile-first, test all breakpoints\n- **Test-first** — Component tests before implementation\n\n## Frontend Exploration Mode\n\n| Need | Tool |\n|------|------|\n| Component dependency graph | `graph({action:'neighbors', node_id:'src/components/X.tsx', direction:'incoming'})` |\n| Stale / unused components | `dead_symbols({ path:'src/components' })` |\n| React / a11y / library API research | `web_search({ query })`, `web_fetch({ urls })` |\n| Component complexity hotspots | `measure({ path:'src/components' })` |\n| Verify a component's callers | `graph({action:'find_nodes', name_pattern})` → `neighbors` |\n\n## Visual Validation Protocol (post `test_run`)\n\n**Pre-flight (MANDATORY before any browser step):**\n1. Read `package.json` scripts — identify dev command (e.g. `dev`, `start`, `vite`)\n2. Determine default port (check script args, `vite.config.*`, or env)\n3. Check if dev server already running on port (attempt `http({ url:'http://localhost:<port>' })`)\n4. If NOT running, delegate to a helper or use `createAndRunTask` to start `npm run dev`\n in the background; wait for ready signal\n5. Capture the base URL\n\n**Validation:**\n6. `open_browser_page({ url })` — render target component page\n7. `screenshot_page` + `read_page` — capture visual + DOM\n8. Keyboard-only navigation check: simulate Tab/Enter/Escape via `type_in_page` —\n verify focus ring, activation, dismiss\n9. Compare against design tokens / Figma URL if supplied\n10. Fail fast if color contrast < 4.5:1 (WCAG AA) or focus indicator missing\n\nIf the pre-flight dev server cannot be started (e.g. sandbox), fall back to\n`compact` inspection of the component source + describe expected visual behavior.",Debugger:`**Read \`AGENTS.md\`** in the workspace root for project conventions and AI Kit protocol.
501
+ | \`repo-access\` | When the plan involves accessing private, enterprise, or self-hosted repositories |
502
+ | \`browser-use\` | When the plan involves browser-based auth recovery, web scraping, or interacting with web applications that require login |`,Implementer:"**Read `AGENTS.md`** in the workspace root for project conventions and AI Kit protocol.\n\nLoad the `aikit` skill for full tool documentation, workflow chains, and session protocol.\n\n## Implementation Protocol\n\n1. **Understand scope** — Read the phase objective, identify target files\n2. **Write test first** (Red) — Create failing tests that define expected behavior\n3. **Implement** (Green) — Write minimal code to make tests pass\n4. **Refactor** — Clean up while keeping tests green\n5. **Validate** — `check`, `test_run`, `blast_radius`\n6. **Persist** — `remember` any decisions or patterns discovered\n\n## Rules\n\n- **Test-first always** — No implementation without a failing test\n- **Minimal code** — Don't build what isn't asked for\n- **Follow existing patterns** — Search AI Kit for conventions before creating new ones (`search(\"convention\")`, `knowledge({ action: \"list\", category: \"conventions\" })`)\n- **Never modify tests to make them pass** — Fix the implementation instead\n- **Run `check` after every change** — Catch errors early\n- **Loop-break** — If the same test fails 3 times with the same error after your fixes, STOP. Re-read the error from scratch, check your assumptions with `trace` or `symbol`, and try a fundamentally different approach. Do not attempt a 4th fix in the same direction\n- **Think-first for complex tasks** — If a task involves 3+ files or non-obvious logic, outline your approach before writing code. Check existing patterns with `search` first. Design, then implement\n\n## Pre-Edit Checklist (before modifying any file)\n\n1. **Understand consumers** — `graph({action:'find_nodes', name_pattern:'<target>'})` → `graph({action:'neighbors', node_id, direction:'incoming'})`. See who calls/imports before changing a contract.\n2. **Compress, don't raw-read** — `file_summary` then `compact({path, query})` for the specific area. Only `read_file` when you need exact lines for `replace_string_in_file`.\n3. **Snapshot risky edits** — `checkpoint({action:'save', label:'pre-<scope>'})` before cross-cutting changes. `checkpoint({action:'restore', ...})` if `check`/`test_run` fails.\n4. **Estimate blast radius** — `blast_radius({changed_files:[...]})` BEFORE editing when changing a public/shared symbol; re-run AFTER to confirm actual impact matches.\n5. **TDD when tests exist** — write/extend the failing test first, then minimum code to pass.\n\n## Post-Edit Checklist\n\n1. `check({})` — typecheck + lint must pass clean\n2. `test_run({})` — full suite or targeted pattern\n3. If Orchestrator passed a `task_id`: `evidence_map({action:'add', task_id, claim, status:'V', receipt:'file.ts#Lxx'})` for each verified contract/acceptance claim. Do NOT run the gate — Orchestrator owns it.",Frontend:"**Read `AGENTS.md`** in the workspace root for project conventions and AI Kit protocol.\n\nLoad the `aikit` skill for full tool documentation, workflow chains, and session protocol.\n\n## Frontend Protocol\n\n1. **Search AI Kit** for existing component patterns and design tokens\n2. **Write component tests first** — Accessibility, rendering, interaction\n3. **Implement** — Follow existing component patterns, use design system tokens\n4. **Validate** — `check`, `test_run`, visual review\n5. **Persist** — `remember` new component patterns\n\n## Rules\n\n- **Accessibility first** — ARIA attributes, keyboard navigation, screen reader support\n- **Follow design system** — Use existing tokens, don't create one-off values\n- **Responsive by default** — Mobile-first, test all breakpoints\n- **Test-first** — Component tests before implementation\n\n## Frontend Exploration Mode\n\n| Need | Tool |\n|------|------|\n| Component dependency graph | `graph({action:'neighbors', node_id:'src/components/X.tsx', direction:'incoming'})` |\n| Stale / unused components | `dead_symbols({ path:'src/components' })` |\n| React / a11y / library API research | `web_search({ query })`, `web_fetch({ urls })` |\n| Component complexity hotspots | `measure({ path:'src/components' })` |\n| Verify a component's callers | `graph({action:'find_nodes', name_pattern})` → `neighbors` |\n\n## Visual Validation Protocol (post `test_run`)\n\n**Pre-flight (MANDATORY before any browser step):**\n1. Read `package.json` scripts — identify dev command (e.g. `dev`, `start`, `vite`)\n2. Determine default port (check script args, `vite.config.*`, or env)\n3. Check if dev server already running on port (attempt `http({ url:'http://localhost:<port>' })`)\n4. If NOT running, delegate to a helper or use `createAndRunTask` to start `npm run dev`\n in the background; wait for ready signal\n5. Capture the base URL\n\n**Validation:**\n6. `open_browser_page({ url })` — render target component page\n7. `screenshot_page` + `read_page` — capture visual + DOM\n8. Keyboard-only navigation check: simulate Tab/Enter/Escape via `type_in_page` —\n verify focus ring, activation, dismiss\n9. Compare against design tokens / Figma URL if supplied\n10. Fail fast if color contrast < 4.5:1 (WCAG AA) or focus indicator missing\n\nIf the pre-flight dev server cannot be started (e.g. sandbox), fall back to\n`compact` inspection of the component source + describe expected visual behavior.",Debugger:`**Read \`AGENTS.md\`** in the workspace root for project conventions and AI Kit protocol.
496
503
 
497
504
  Load the \`aikit\` skill for full tool documentation, workflow chains, and session protocol.
498
505
 
@@ -1 +1 @@
1
- const e={aikit:{description:`AI Kit search, analysis, memory, and developer tools`,source:`scaffold/skills/aikit/SKILL.md`,required:!0},brainstorming:{description:`Brainstorming & design exploration workflow`,source:`scaffold/skills/brainstorming/SKILL.md`,required:!0,sidecars:[`scaffold/skills/brainstorming/spec-document-reviewer-prompt.md`]},"multi-agents-development":{description:`Multi-agent orchestration, task decomposition, parallel dispatch, and review pipeline patterns`,source:`scaffold/skills/multi-agents-development/SKILL.md`,required:!0,sidecars:[`scaffold/skills/multi-agents-development/implementer-prompt.md`,`scaffold/skills/multi-agents-development/spec-review-prompt.md`,`scaffold/skills/multi-agents-development/code-quality-review-prompt.md`,`scaffold/skills/multi-agents-development/architecture-review-prompt.md`,`scaffold/skills/multi-agents-development/parallel-dispatch-example.md`]},"adr-skill":{description:`Architecture Decision Records — create, maintain, and review ADRs for significant technical decisions`,source:`scaffold/skills/adr-skill/SKILL.md`,required:!0,sidecars:[`scaffold/skills/adr-skill/assets/templates/adr-madr.md`,`scaffold/skills/adr-skill/assets/templates/adr-readme.md`,`scaffold/skills/adr-skill/assets/templates/adr-simple.md`,`scaffold/skills/adr-skill/references/adr-conventions.md`,`scaffold/skills/adr-skill/references/examples.md`,`scaffold/skills/adr-skill/references/review-checklist.md`,`scaffold/skills/adr-skill/references/template-variants.md`,`scaffold/skills/adr-skill/scripts/bootstrap_adr.js`,`scaffold/skills/adr-skill/scripts/new_adr.js`,`scaffold/skills/adr-skill/scripts/set_adr_status.js`]},"c4-architecture":{description:`C4 model architecture diagrams using Mermaid — system context, container, component, and deployment views`,source:`scaffold/skills/c4-architecture/SKILL.md`,required:!0,sidecars:[`scaffold/skills/c4-architecture/references/advanced-patterns.md`,`scaffold/skills/c4-architecture/references/c4-syntax.md`,`scaffold/skills/c4-architecture/references/common-mistakes.md`]},"frontend-design":{description:`Frontend design system — visual design thinking, typography, color, layout, motion, accessibility, and anti-pattern detection`,source:`scaffold/skills/frontend-design/SKILL.md`,required:!1},"lesson-learned":{description:`Extract engineering lessons from recent code changes via git history analysis`,source:`scaffold/skills/lesson-learned/SKILL.md`,required:!0,sidecars:[`scaffold/skills/lesson-learned/references/anti-patterns.md`,`scaffold/skills/lesson-learned/references/se-principles.md`]},present:{description:`Rich interactive dashboards, charts, tables, timelines, and data visualizations via the present MCP tool`,source:`scaffold/skills/present/SKILL.md`,required:!0},react:{description:`React development patterns — component architecture, React 19 APIs, Server Components, TypeScript integration`,source:`scaffold/skills/react/SKILL.md`,required:!1},"requirements-clarity":{description:`Clarify ambiguous requirements through focused dialogue — score 0-100 until ≥90 before implementation`,source:`scaffold/skills/requirements-clarity/SKILL.md`,required:!0},"session-handoff":{description:`Comprehensive handoff documents for seamless AI agent session transfers and context preservation`,source:`scaffold/skills/session-handoff/SKILL.md`,required:!0,sidecars:[`scaffold/skills/session-handoff/references/handoff-template.md`,`scaffold/skills/session-handoff/references/resume-checklist.md`,`scaffold/skills/session-handoff/scripts/check_staleness.js`,`scaffold/skills/session-handoff/scripts/create_handoff.js`,`scaffold/skills/session-handoff/scripts/list_handoffs.js`,`scaffold/skills/session-handoff/scripts/validate_handoff.js`]},typescript:{description:`TypeScript development patterns — type system, compiler config, advanced types, async patterns, module organization`,source:`scaffold/skills/typescript/SKILL.md`,required:!1},docs:{description:`Living documentation management — Diátaxis framework, docs/ convention, staleness detection, integration with adr-skill and c4-architecture`,source:`scaffold/skills/docs/SKILL.md`,required:!0},"repo-access":{description:`Progressive repository access recovery for private and enterprise git repos — strategy ladder from HTTPS to SSH to CLI OAuth to PAT to local clone`,source:`scaffold/skills/repo-access/SKILL.md`,required:!0,sidecars:[`scaffold/skills/repo-access/references/platform-matrix.md`,`scaffold/skills/repo-access/references/error-patterns.md`]}};export{e as PLUGINS};
1
+ const e={aikit:{description:`AI Kit search, analysis, memory, and developer tools`,source:`scaffold/skills/aikit/SKILL.md`,required:!0},brainstorming:{description:`Brainstorming & design exploration workflow`,source:`scaffold/skills/brainstorming/SKILL.md`,required:!0,sidecars:[`scaffold/skills/brainstorming/spec-document-reviewer-prompt.md`]},"multi-agents-development":{description:`Multi-agent orchestration, task decomposition, parallel dispatch, and review pipeline patterns`,source:`scaffold/skills/multi-agents-development/SKILL.md`,required:!0,sidecars:[`scaffold/skills/multi-agents-development/implementer-prompt.md`,`scaffold/skills/multi-agents-development/spec-review-prompt.md`,`scaffold/skills/multi-agents-development/code-quality-review-prompt.md`,`scaffold/skills/multi-agents-development/architecture-review-prompt.md`,`scaffold/skills/multi-agents-development/parallel-dispatch-example.md`]},"adr-skill":{description:`Architecture Decision Records — create, maintain, and review ADRs for significant technical decisions`,source:`scaffold/skills/adr-skill/SKILL.md`,required:!0,sidecars:[`scaffold/skills/adr-skill/assets/templates/adr-madr.md`,`scaffold/skills/adr-skill/assets/templates/adr-readme.md`,`scaffold/skills/adr-skill/assets/templates/adr-simple.md`,`scaffold/skills/adr-skill/references/adr-conventions.md`,`scaffold/skills/adr-skill/references/examples.md`,`scaffold/skills/adr-skill/references/review-checklist.md`,`scaffold/skills/adr-skill/references/template-variants.md`,`scaffold/skills/adr-skill/scripts/bootstrap_adr.js`,`scaffold/skills/adr-skill/scripts/new_adr.js`,`scaffold/skills/adr-skill/scripts/set_adr_status.js`]},"c4-architecture":{description:`C4 model architecture diagrams using Mermaid — system context, container, component, and deployment views`,source:`scaffold/skills/c4-architecture/SKILL.md`,required:!0,sidecars:[`scaffold/skills/c4-architecture/references/advanced-patterns.md`,`scaffold/skills/c4-architecture/references/c4-syntax.md`,`scaffold/skills/c4-architecture/references/common-mistakes.md`]},"frontend-design":{description:`Frontend design system — visual design thinking, typography, color, layout, motion, accessibility, and anti-pattern detection`,source:`scaffold/skills/frontend-design/SKILL.md`,required:!1},"lesson-learned":{description:`Extract engineering lessons from recent code changes via git history analysis`,source:`scaffold/skills/lesson-learned/SKILL.md`,required:!0,sidecars:[`scaffold/skills/lesson-learned/references/anti-patterns.md`,`scaffold/skills/lesson-learned/references/se-principles.md`]},present:{description:`Rich interactive dashboards, charts, tables, timelines, and data visualizations via the present MCP tool`,source:`scaffold/skills/present/SKILL.md`,required:!0},react:{description:`React development patterns — component architecture, React 19 APIs, Server Components, TypeScript integration`,source:`scaffold/skills/react/SKILL.md`,required:!1},"requirements-clarity":{description:`Clarify ambiguous requirements through focused dialogue — score 0-100 until ≥90 before implementation`,source:`scaffold/skills/requirements-clarity/SKILL.md`,required:!0},"session-handoff":{description:`Comprehensive handoff documents for seamless AI agent session transfers and context preservation`,source:`scaffold/skills/session-handoff/SKILL.md`,required:!0,sidecars:[`scaffold/skills/session-handoff/references/handoff-template.md`,`scaffold/skills/session-handoff/references/resume-checklist.md`,`scaffold/skills/session-handoff/scripts/check_staleness.js`,`scaffold/skills/session-handoff/scripts/create_handoff.js`,`scaffold/skills/session-handoff/scripts/list_handoffs.js`,`scaffold/skills/session-handoff/scripts/validate_handoff.js`]},typescript:{description:`TypeScript development patterns — type system, compiler config, advanced types, async patterns, module organization`,source:`scaffold/skills/typescript/SKILL.md`,required:!1},docs:{description:`Living documentation management — Diátaxis framework, docs/ convention, staleness detection, integration with adr-skill and c4-architecture`,source:`scaffold/skills/docs/SKILL.md`,required:!0},"repo-access":{description:`Progressive repository access recovery for private and enterprise git repos — strategy ladder from HTTPS to SSH to CLI OAuth to PAT to local clone`,source:`scaffold/skills/repo-access/SKILL.md`,required:!0,sidecars:[`scaffold/skills/repo-access/references/platform-matrix.md`,`scaffold/skills/repo-access/references/error-patterns.md`]},"browser-use":{description:`Browser automation for AI agents using Playwright MCP browser tools — zero setup authentication recovery, data extraction, form filling, and web interaction. Works with any MCP client. Pairs with repo-access as final escalation for SSO/login wall recovery.`,source:`scaffold/skills/browser-use/SKILL.md`,required:!1,sidecars:[`scaffold/skills/browser-use/references/auth-patterns.md`]}};export{e as PLUGINS};