@vpxa/aikit 0.1.114 → 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.
- package/package.json +1 -1
- package/packages/cli/dist/index.js +1 -1
- package/packages/core/dist/index.d.ts +5 -1
- package/packages/embeddings/dist/index.d.ts +55 -1
- package/packages/embeddings/dist/index.js +1 -1
- package/packages/server/dist/config-D4z6-EcI.js +1 -0
- package/packages/server/dist/index.js +1 -1
- package/packages/server/dist/{server-qD-mw6RP.js → server-Cbe4LQqt.js} +178 -178
- package/packages/store/dist/index.d.ts +60 -102
- package/packages/store/dist/index.js +6 -6
- package/packages/store/dist/lance-store-D1JolXlO.js +1 -0
- package/packages/store/dist/{sqlite-vec-store-DuGaWATy.js → sqlite-vec-store-DA6fzQiD.js} +7 -7
- package/scaffold/dist/definitions/agents.mjs +36 -4
- package/scaffold/dist/definitions/bodies.mjs +6 -2
- package/scaffold/dist/definitions/protocols.mjs +3 -0
- package/packages/server/dist/config-BL-I_FFY.js +0 -1
- package/packages/store/dist/lance-store-BRoi-4qY.js +0 -1
- package/packages/store/dist/rolldown-runtime-BynbHzcv.js +0 -1
|
@@ -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,
|
|
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{
|
|
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
|
|
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?
|
|
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(
|
|
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(
|
|
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:
|
|
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{
|
|
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)&&(
|
|
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
|
|
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(?), ?)`,[
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
-
`,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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):**
|
|
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 |
|
|
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
|
|
@@ -443,6 +446,7 @@ The Planner is typically activated by the Orchestrator as part of a flow step (e
|
|
|
443
446
|
## Subagent Output Relay
|
|
444
447
|
|
|
445
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.
|
|
446
450
|
**You MUST relay key findings:**
|
|
447
451
|
|
|
448
452
|
1. After every subagent completes, extract key data from the returned text
|
|
@@ -896,6 +896,8 @@ The Orchestrator uses **multi-model decision analysis** to resolve non-trivial t
|
|
|
896
896
|
|
|
897
897
|
Dispatch ALL available Researcher variants **in parallel** via \`runSubagent\` — one call per variant, same question, simultaneous. Each returns an independent recommendation grounded in their thinking style:
|
|
898
898
|
|
|
899
|
+
**IMPORTANT: Include this instruction in every researcher dispatch prompt: "You are running as a subagent. Do NOT use the \`present\` tool — return all analysis as plain text."**
|
|
900
|
+
|
|
899
901
|
| Variant | Thinking Style | Lens |
|
|
900
902
|
|---------|---------------|------|
|
|
901
903
|
| **Alpha** | Contrarian | Actively seeks flaws, fatal assumptions, hidden risks |
|
|
@@ -971,6 +973,7 @@ Trigger the decision protocol when there is an **unresolved non-trivial technica
|
|
|
971
973
|
## Key Rules
|
|
972
974
|
|
|
973
975
|
- **\`runSubagent\` is ALWAYS available** — it is a core tool in every environment (VS Code, CLI, Copilot Chat). NEVER claim it is unavailable. NEVER simulate researchers inline by "applying lenses yourself." If you cannot call \`runSubagent\`, you have a tool-loading issue — retry or escalate, do NOT degrade to single-agent inline simulation.
|
|
976
|
+
- **No \`present\` in subagents** — always include "Do NOT use the \`present\` tool — return all analysis as plain text" in every researcher dispatch prompt. Subagent visual outputs are invisible to the user.
|
|
974
977
|
- Always launch in **parallel**, minimum 4 variants
|
|
975
978
|
- Use exact case-sensitive agent names — never rename or alias
|
|
976
979
|
- **Anonymize** researcher outputs before peer review (A/B/C/D, not agent names)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{existsSync as e,readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{fileURLToPath as i}from"node:url";import{AIKIT_PATHS as a,EMBEDDING_DEFAULTS as o,createLogger as s,getPartitionDir as c,isUserInstalled as l,registerWorkspace as u,serializeError as d}from"../../core/dist/index.js";const f=n(i(import.meta.url)),p=s(`server`),m=[`auto`,`manual`,`smart`];function h(e){return typeof e==`string`&&m.includes(e)}function g(e,t,n){let i=r(e),a=r(t);if(!i.startsWith(a))throw Error(`Config ${n} path escapes workspace root: ${e} is not under ${t}`);return i}function _(e){let t=process.env.AIKIT_INDEX_MODE;if(h(t))return t;if(e.indexMode)return e.indexMode;let n=process.env.AIKIT_AUTO_INDEX;return n===void 0?e.autoIndex===void 0?`smart`:e.autoIndex?`auto`:`manual`:n===`true`?`auto`:`manual`}function v(){let i=process.env.AIKIT_CONFIG_PATH??(e(r(process.cwd(),`aikit.config.json`))?r(process.cwd(),`aikit.config.json`):r(f,`..`,`..`,`..`,`aikit.config.json`));try{if(!e(i))return p.info(`No config file found, using defaults`,{configPath:i}),y();let o=t(i,`utf-8`),s=JSON.parse(o);if(!s.sources||!Array.isArray(s.sources)||s.sources.length===0)throw Error(`Config must have at least one source`);if(!s.store?.path)throw Error(`Config must specify store.path`);if(s.autoIndex!==void 0&&typeof s.autoIndex!=`boolean`)throw Error(`Config autoIndex must be a boolean`);if(s.indexMode!==void 0&&!h(s.indexMode))throw Error(`Config indexMode must be one of: ${m.join(`, `)}`);let c=n(i);return s.sources=s.sources.map(e=>({...e,path:g(r(c,e.path),c,`source`)})),s.store.path=g(r(c,s.store.path),c,`store`),s.curated=s.curated??{path:a.aiCurated},s.curated.path=g(r(c,s.curated.path),c,`curated`),b(s,c),s.indexMode=_(s),s}catch(e){return p.error(`Failed to load config`,{configPath:i,...d(e)}),p.warn(`Falling back to default configuration`,{configPath:i}),y()}}function y(){let e=process.env.AIKIT_WORKSPACE_ROOT??process.cwd(),t={sources:[{path:e,excludePatterns:[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],serverName:`aikit`,indexing:{chunkSize:1500,chunkOverlap:200,minChunkSize:100},embedding:{model:o.model,dimensions:o.dimensions},store:{backend:`sqlite-vec`,path:r(e,a.data)},curated:{path:r(e,a.aiCurated)},onboardDir:r(e,a.aiContext),stateDir:r(e,a.state)};return b(t,e),t.indexMode=_(t),t}function b(e,t){if(!l())return;let n=t,i=u(n);e.store.path=r(c(i.partition)),e.onboardDir=r(c(i.partition),`onboard`),e.stateDir=r(c(i.partition),`state`),e.curated||={path:r(n,a.aiCurated)}}function x(t,n){if(!e(n))throw Error(`Workspace root does not exist: ${n}`);p.info(`Reconfiguring for workspace root`,{workspaceRoot:n});try{process.chdir(n),p.info(`Changed process cwd to workspace root`,{cwd:process.cwd()})}catch(e){p.warn(`Failed to chdir to workspace root`,{workspaceRoot:n,...d(e)})}t.sources=[{path:n,excludePatterns:t.sources[0]?.excludePatterns??[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],t.store.path=r(n,a.data),t.curated={path:r(n,a.aiCurated)},t.onboardDir=r(n,a.aiContext),t.stateDir=r(n,a.state),b(t,n)}export{v as loadConfig,x as reconfigureForWorkspace,_ as resolveIndexMode};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./rolldown-runtime-BynbHzcv.js";import{EMBEDDING_DEFAULTS as t,SEARCH_DEFAULTS as n,STORE_DEFAULTS as r,createLogger as i,serializeError as a,sourceTypeContentTypes as o}from"../../core/dist/index.js";import{Index as s,connect as c}from"@lancedb/lancedb";var l=e({LanceStore:()=>m});function u(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}const d=/^[\w.\-/ ]+$/,f=i(`store`);function p(e,t){if(!d.test(e))throw Error(`Invalid ${t} filter value: contains disallowed characters`);return e.replace(/'/g,`''`)}var m=class e{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??r.path,this.tableName=e?.tableName??r.tableName}async initialize(){this.db=await c(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 = '${p(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,t){if(!this.table)return[];let r=t?.limit??n.maxResults,i=t?.minScore??n.minScore,a=this.table.search(e).limit(r*2),o=this.buildFilterString(t);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:s.fts({withPosition:!0}),replace:!0}),this._ftsReady=!0,this._ftsRecoveryAttemptAt=0,f.info(`FTS index created/updated`,{column:`content`})}catch(e){f.warn(`FTS index creation failed`,a(e))}}async ftsSearch(t,r){if(!this.table)return[];if(!this._ftsReady){let t=Date.now();if(t-this._ftsRecoveryAttemptAt<e.FTS_RECOVERY_COOLDOWN_MS)return[];this._ftsRecoveryAttemptAt=t;try{await this.createFtsIndex()}catch{return[]}if(!this._ftsReady)return[]}let i=r?.limit??n.maxResults;try{let e=this.table.search(t).limit(i*2),n=this.buildFilterString(r);return n&&(e=e.where(n)),(await e.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`)?(f.debug(`FTS search skipped — index not yet available`),this._ftsReady=!1):f.warn(`FTS search failed`,a(e)),[]}}async getById(e){if(!this.table)return null;let t=await this.table.query().where(`id = '${p(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 = '${p(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 = '${p(e,`id`)}'`),!0)}async getBySourcePath(e){return this.table?(await this.table.query().where(`sourcePath = '${p(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:t.model};let e=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:e,totalFiles:i.size,contentTypeBreakdown:r,lastIndexedAt:a,storeBackend:`lancedb`,embeddingModel:t.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;f.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 = '${p(e.contentType,`contentType`)}'`),e?.sourceType){let n=o(e.sourceType);if(n.length>0){let e=n.map(e=>`'${p(e,`sourceType`)}'`).join(`, `);t.push(`contentType IN (${e})`)}}if(e?.origin&&t.push(`origin = '${p(e.origin,`origin`)}'`),e?.category&&t.push(`category = '${p(e.category,`category`)}'`),e?.tags&&e.tags.length>0){let n=e.tags.map(e=>`tags LIKE '%${p(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:u(e.tags),category:e.category||void 0,version:e.version}}};export{l as n,m as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{createRequire as e}from"node:module";var t=Object.defineProperty,n=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},r=e(import.meta.url);export{r as n,n as t};
|