@theclawlab/xdb 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +90 -0
- package/USAGE.md +347 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +2197 -0
- package/dist/cli.js.map +1 -0
- package/package.json +41 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/col.ts","../src/collection-manager.ts","../src/errors.ts","../src/policy-registry.ts","../src/commands/policy.ts","../src/commands/put.ts","../src/embedding-client.ts","../src/config-manager.ts","../src/embedder.ts","../src/data-writer.ts","../src/engines/lancedb-engine.ts","../src/engines/sqlite-engine.ts","../src/commands/find.ts","../src/data-finder.ts","../src/commands/config.ts","../src/commands/embed.ts","../src/embed-io.ts","../src/embedding-models.ts","../src/help.ts"],"sourcesContent":["import { Command } from 'commander';\r\nimport { readFileSync } from 'node:fs';\r\nimport { join, dirname } from 'node:path';\r\nimport { fileURLToPath } from 'node:url';\r\nimport { registerColCommands } from './commands/col.js';\r\nimport { registerPolicyCommands } from './commands/policy.js';\r\nimport { registerPutCommand } from './commands/put.js';\r\nimport { registerFindCommand } from './commands/find.js';\r\nimport { registerConfigCommands } from './commands/config.js';\r\nimport { registerEmbedCommand } from './commands/embed.js';\r\nimport { installHelp, addColExamples, addPolicyExamples, addPutExamples, addFindExamples } from './help.js';\r\n\r\n// Gracefully handle EPIPE (broken pipe, e.g. `xdb ... | head`)\r\nprocess.stdout.on('error', (err: NodeJS.ErrnoException) => {\r\n if (err.code === 'EPIPE') process.exit(0);\r\n throw err;\r\n});\r\nprocess.stderr.on('error', (err: NodeJS.ErrnoException) => {\r\n if (err.code === 'EPIPE') process.exit(0);\r\n throw err;\r\n});\r\n\r\n// Read version from package.json\r\nconst __dirname = dirname(fileURLToPath(import.meta.url));\r\nconst { version: pkgVersion } = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8')) as { version: string };\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('xdb')\r\n .description('Intent-driven data hub CLI for AI agents')\r\n .version(`xdb ${pkgVersion}`)\r\n .showHelpAfterError(true);\r\n\r\nprogram.exitOverride();\r\n\r\n// Install help system\r\ninstallHelp(program);\r\n\r\n// --- col subcommand (collection management) ---\r\nconst col = program\r\n .command('col')\r\n .description('Manage collections');\r\n\r\nregisterColCommands(col);\r\naddColExamples(col);\r\n\r\n// --- policy subcommand (policy discovery) ---\r\nconst policy = program\r\n .command('policy')\r\n .description('Discover available policies');\r\n\r\nregisterPolicyCommands(policy);\r\naddPolicyExamples(policy);\r\n\r\npolicy.action(() => {\r\n policy.outputHelp();\r\n});\r\n\r\n// --- put command (data writing) ---\r\nregisterPutCommand(program);\r\naddPutExamples(program.commands.find(c => c.name() === 'put')!);\r\n\r\n// --- find command (data retrieval) ---\r\nregisterFindCommand(program);\r\naddFindExamples(program.commands.find(c => c.name() === 'find')!);\r\n\r\n// --- config command (embed service configuration) ---\r\nconst config = program\r\n .command('config')\r\n .description('Manage xdb configuration');\r\n\r\nregisterConfigCommands(config);\r\n\r\n// --- embed command ---\r\nregisterEmbedCommand(program);\r\n\r\n// Ensure errors go to stderr (Requirement 10.3)\r\nprogram.configureOutput({\r\n writeErr: (str) => process.stderr.write(str),\r\n writeOut: (str) => process.stdout.write(str),\r\n});\r\n\r\n// Show help if no args (col also shows help if no subcommand)\r\ncol.action(() => {\r\n col.outputHelp();\r\n});\r\n\r\n(async () => {\r\n try {\r\n await program.parseAsync(process.argv);\r\n } catch (err) {\r\n if (err && typeof err === 'object' && 'exitCode' in err) {\r\n const exitCode = (err as { exitCode: number }).exitCode;\r\n // Map commander's exit code 1 (argument errors) to 2 per spec\r\n process.exitCode = exitCode === 1 ? 2 : exitCode;\r\n } else {\r\n process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\\n`);\r\n process.exitCode = 1;\r\n }\r\n }\r\n})();\r\n","import { homedir } from 'node:os';\r\nimport { join } from 'node:path';\r\nimport type { Command } from 'commander';\r\nimport { CollectionManager } from '../collection-manager.js';\r\nimport { PolicyRegistry } from '../policy-registry.js';\r\nimport { handleError, PARAMETER_ERROR, XDBError } from '../errors.js';\r\n\r\nfunction getDataRoot(): string {\r\n return join(homedir(), '.local', 'share', 'xdb');\r\n}\r\n\r\n/** Format bytes into a human-readable string */\r\nfunction formatBytes(bytes: number): string {\r\n if (bytes < 1024) return `${bytes} B`;\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\r\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\r\n}\r\n\r\nexport function registerColCommands(col: Command): void {\r\n col\r\n .command('init <name>')\r\n .description('Initialize a new collection')\r\n .requiredOption('--policy <policy>', 'Policy name (main/minor format)')\r\n .option('--params <json>', 'Custom parameters as JSON to override policy defaults')\r\n .action(async (name: string, opts: { policy: string; params?: string }) => {\r\n try {\r\n const registry = new PolicyRegistry();\r\n let params: Record<string, unknown> | undefined;\r\n if (opts.params) {\r\n try {\r\n params = JSON.parse(opts.params) as Record<string, unknown>;\r\n } catch {\r\n throw new XDBError(PARAMETER_ERROR, `Invalid JSON for --params: ${opts.params}`);\r\n }\r\n }\r\n const config = registry.resolve(opts.policy, params);\r\n registry.validate(config);\r\n const manager = new CollectionManager(getDataRoot());\r\n await manager.init(name, config);\r\n process.stderr.write(`Collection \"${name}\" created (policy: ${config.main}/${config.minor})\\n`);\r\n } catch (err) {\r\n handleError(err);\r\n }\r\n });\r\n\r\n col\r\n .command('list')\r\n .description('List all collections')\r\n .option('--json', 'Output as JSON array')\r\n .action(async (opts: { json?: boolean }) => {\r\n try {\r\n const manager = new CollectionManager(getDataRoot());\r\n const collections = await manager.list();\r\n\r\n if (opts.json) {\r\n process.stdout.write(JSON.stringify(collections) + '\\n');\r\n return;\r\n }\r\n\r\n // Human-readable output\r\n if (collections.length === 0) {\r\n process.stderr.write('No collections found.\\n');\r\n return;\r\n }\r\n\r\n for (const info of collections) {\r\n const dim = info.embeddingDimension ? `, dim=${info.embeddingDimension}` : '';\r\n process.stdout.write(\r\n `${info.name} policy=${info.policy} records=${info.recordCount} size=${formatBytes(info.sizeBytes)}${dim}\\n`,\r\n );\r\n }\r\n } catch (err) {\r\n handleError(err);\r\n }\r\n });\r\n\r\n col\r\n .command('info <name>')\r\n .description('Show detailed information about a collection')\r\n .option('--json', 'Output as JSON')\r\n .action(async (name: string, opts: { json?: boolean }) => {\r\n try {\r\n const manager = new CollectionManager(getDataRoot());\r\n const meta = await manager.load(name);\r\n const collections = await manager.list();\r\n const stats = collections.find((c) => c.name === name);\r\n\r\n const info = {\r\n name: meta.name,\r\n createdAt: meta.createdAt,\r\n policy: `${meta.policy.main}/${meta.policy.minor}`,\r\n engines: meta.policy.main,\r\n autoIndex: meta.policy.autoIndex ?? false,\r\n fields: meta.policy.fields,\r\n embeddingDimension: meta.embeddingDimension ?? null,\r\n recordCount: stats?.recordCount ?? 0,\r\n sizeBytes: stats?.sizeBytes ?? 0,\r\n path: join(getDataRoot(), 'collections', name),\r\n };\r\n\r\n if (opts.json) {\r\n process.stdout.write(JSON.stringify(info) + '\\n');\r\n return;\r\n }\r\n\r\n process.stdout.write(`name: ${info.name}\\n`);\r\n process.stdout.write(`createdAt: ${info.createdAt}\\n`);\r\n process.stdout.write(`path: ${info.path}\\n`);\r\n process.stdout.write(`policy: ${info.policy}\\n`);\r\n process.stdout.write(`engines: ${info.engines}\\n`);\r\n process.stdout.write(`autoIndex: ${info.autoIndex}\\n`);\r\n process.stdout.write(`records: ${info.recordCount}\\n`);\r\n process.stdout.write(`size: ${formatBytes(info.sizeBytes)}\\n`);\r\n if (info.embeddingDimension) {\r\n process.stdout.write(`embedDim: ${info.embeddingDimension}\\n`);\r\n }\r\n\r\n const fieldNames = Object.keys(info.fields);\r\n if (fieldNames.length > 0) {\r\n process.stdout.write(`fields:\\n`);\r\n for (const [f, cfg] of Object.entries(info.fields)) {\r\n process.stdout.write(` ${f} findCaps=[${cfg.findCaps.join(', ')}]\\n`);\r\n }\r\n } else {\r\n process.stdout.write(`fields: (none)\\n`);\r\n }\r\n } catch (err) {\r\n handleError(err);\r\n }\r\n });\r\n\r\n col\r\n .command('rm <name>')\r\n .description('Remove a collection')\r\n .action(async (name: string) => {\r\n try {\r\n const manager = new CollectionManager(getDataRoot());\r\n await manager.remove(name);\r\n process.stderr.write(`Collection \"${name}\" removed.\\n`);\r\n } catch (err) {\r\n handleError(err);\r\n }\r\n });\r\n}\r\n","import { readdir, mkdir, rm, stat, readFile, writeFile } from 'node:fs/promises';\r\nimport { join } from 'node:path';\r\nimport { PARAMETER_ERROR, RUNTIME_ERROR, XDBError } from './errors.js';\r\nimport type { PolicyConfig } from './policy-registry.js';\r\n\r\nexport interface CollectionMeta {\r\n name: string;\r\n policy: PolicyConfig;\r\n createdAt: string;\r\n /** Embedding vector dimension, recorded on first vector write for consistency checks. */\r\n embeddingDimension?: number;\r\n}\r\n\r\nexport interface CollectionInfo {\r\n name: string;\r\n policy: string; // \"main/minor\"\r\n recordCount: number;\r\n sizeBytes: number;\r\n embeddingDimension?: number;\r\n}\r\n\r\nexport class CollectionManager {\r\n private collectionsDir: string;\r\n\r\n constructor(private dataRoot: string) {\r\n this.collectionsDir = join(dataRoot, 'collections');\r\n }\r\n\r\n /** Ensure the dataRoot and collections directory exist. */\r\n private async ensureRoot(): Promise<void> {\r\n await mkdir(this.collectionsDir, { recursive: true });\r\n }\r\n\r\n private collectionPath(name: string): string {\r\n return join(this.collectionsDir, name);\r\n }\r\n\r\n private metaPath(name: string): string {\r\n return join(this.collectionPath(name), 'collection_meta.json');\r\n }\r\n\r\n /**\r\n * Create a new collection directory and write collection_meta.json.\r\n * Throws PARAMETER_ERROR if the collection already exists.\r\n */\r\n async init(name: string, policy: PolicyConfig): Promise<void> {\r\n await this.ensureRoot();\r\n\r\n if (await this.exists(name)) {\r\n throw new XDBError(PARAMETER_ERROR, `Collection \"${name}\" already exists`);\r\n }\r\n\r\n const colPath = this.collectionPath(name);\r\n await mkdir(colPath, { recursive: true });\r\n\r\n const meta: CollectionMeta = {\r\n name,\r\n policy,\r\n createdAt: new Date().toISOString(),\r\n };\r\n\r\n await writeFile(this.metaPath(name), JSON.stringify(meta, null, 2), 'utf-8');\r\n }\r\n\r\n /**\r\n * Scan the collections directory and return info for each collection.\r\n */\r\n async list(): Promise<CollectionInfo[]> {\r\n await this.ensureRoot();\r\n\r\n let entries: string[];\r\n try {\r\n entries = await readdir(this.collectionsDir);\r\n } catch {\r\n return [];\r\n }\r\n\r\n const results: CollectionInfo[] = [];\r\n\r\n for (const entry of entries) {\r\n const colPath = this.collectionPath(entry);\r\n try {\r\n const s = await stat(colPath);\r\n if (!s.isDirectory()) continue;\r\n\r\n const meta = await this.load(entry);\r\n const sizeBytes = await this.calcDirSize(colPath);\r\n const recordCount = await this.countRecords(colPath, meta.policy);\r\n\r\n results.push({\r\n name: meta.name,\r\n policy: `${meta.policy.main}/${meta.policy.minor}`,\r\n recordCount,\r\n sizeBytes,\r\n ...(meta.embeddingDimension !== undefined ? { embeddingDimension: meta.embeddingDimension } : {}),\r\n });\r\n } catch {\r\n // Skip directories without valid meta\r\n continue;\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * Count records in a collection by opening the appropriate engine.\r\n * Prefers SQLite (cheaper to open) when available, falls back to LanceDB.\r\n */\r\n private async countRecords(colPath: string, policy: PolicyConfig): Promise<number> {\r\n const hasSqlite = policy.main === 'hybrid' || policy.main === 'relational';\r\n const hasLance = policy.main === 'hybrid' || policy.main === 'vector';\r\n\r\n if (hasSqlite) {\r\n try {\r\n const { default: Database } = await import('better-sqlite3');\r\n const dbPath = join(colPath, 'relational.db');\r\n // Check file exists before opening\r\n try { await stat(dbPath); } catch { return 0; }\r\n const db = new Database(dbPath, { readonly: true });\r\n try {\r\n const row = db.prepare('SELECT COUNT(*) as cnt FROM records').get() as { cnt: number } | undefined;\r\n return row?.cnt ?? 0;\r\n } catch {\r\n return 0;\r\n } finally {\r\n db.close();\r\n }\r\n } catch {\r\n return 0;\r\n }\r\n }\r\n\r\n if (hasLance) {\r\n try {\r\n const lancedb = await import('@lancedb/lancedb');\r\n const dbPath = join(colPath, 'vector.lance');\r\n try { await stat(dbPath); } catch { return 0; }\r\n const db = await lancedb.connect(dbPath);\r\n const tableNames = await db.tableNames();\r\n if (tableNames.includes('data')) {\r\n const table = await db.openTable('data');\r\n const count = await table.countRows();\r\n table.close();\r\n db.close();\r\n return count;\r\n }\r\n db.close();\r\n return 0;\r\n } catch {\r\n return 0;\r\n }\r\n }\r\n\r\n return 0;\r\n }\r\n\r\n /**\r\n * Recursively delete a collection directory.\r\n * Throws PARAMETER_ERROR if the collection doesn't exist.\r\n */\r\n async remove(name: string): Promise<void> {\r\n await this.ensureRoot();\r\n\r\n if (!(await this.exists(name))) {\r\n throw new XDBError(PARAMETER_ERROR, `Collection \"${name}\" does not exist`);\r\n }\r\n\r\n await rm(this.collectionPath(name), { recursive: true, force: true });\r\n }\r\n\r\n /**\r\n * Read and parse collection_meta.json for a collection.\r\n * Throws PARAMETER_ERROR if the collection doesn't exist.\r\n */\r\n async load(name: string): Promise<CollectionMeta> {\r\n if (!(await this.exists(name))) {\r\n throw new XDBError(PARAMETER_ERROR, `Collection \"${name}\" does not exist`);\r\n }\r\n\r\n try {\r\n const raw = await readFile(this.metaPath(name), 'utf-8');\r\n return JSON.parse(raw) as CollectionMeta;\r\n } catch (err) {\r\n if (err instanceof XDBError) throw err;\r\n throw new XDBError(RUNTIME_ERROR, `Failed to read metadata for collection \"${name}\": ${(err as Error).message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Check if a collection directory exists.\r\n */\r\n async exists(name: string): Promise<boolean> {\r\n try {\r\n const s = await stat(this.collectionPath(name));\r\n return s.isDirectory();\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Update the embeddingDimension in collection_meta.json.\r\n * Only writes if the current meta has no embeddingDimension set.\r\n * Throws PARAMETER_ERROR if dimension conflicts with existing value.\r\n */\r\n async recordEmbeddingDimension(name: string, dimension: number): Promise<void> {\r\n const meta = await this.load(name);\r\n if (meta.embeddingDimension !== undefined) {\r\n if (meta.embeddingDimension !== dimension) {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n `Embedding dimension mismatch for collection \"${name}\": expected ${meta.embeddingDimension}, got ${dimension}. This usually means the embedding model has changed. Remove and recreate the collection to use a different model.`,\r\n );\r\n }\r\n return; // already recorded, same dimension\r\n }\r\n meta.embeddingDimension = dimension;\r\n await writeFile(this.metaPath(name), JSON.stringify(meta, null, 2), 'utf-8');\r\n }\r\n\r\n /** Calculate total size of all files in a directory (non-recursive for simplicity). */\r\n private async calcDirSize(dirPath: string): Promise<number> {\r\n let total = 0;\r\n try {\r\n const entries = await readdir(dirPath);\r\n for (const entry of entries) {\r\n const entryPath = join(dirPath, entry);\r\n const s = await stat(entryPath);\r\n if (s.isFile()) {\r\n total += s.size;\r\n } else if (s.isDirectory()) {\r\n total += await this.calcDirSize(entryPath);\r\n }\r\n }\r\n } catch {\r\n // Ignore errors in size calculation\r\n }\r\n return total;\r\n }\r\n}\r\n","// Error type constants with associated exit codes\r\nexport const PARAMETER_ERROR = 2;\r\nexport const CAPABILITY_ERROR = 2;\r\nexport const RUNTIME_ERROR = 1;\r\n\r\n/**\r\n * Unified error class for xdb.\r\n * All errors carry an exit code and a descriptive message.\r\n */\r\nexport class XDBError extends Error {\r\n constructor(\r\n public readonly exitCode: number,\r\n message: string,\r\n ) {\r\n super(message);\r\n this.name = 'XDBError';\r\n }\r\n}\r\n\r\n/**\r\n * Write a formatted error message to stderr.\r\n * Format: \"Error: <descriptive message>\\n\"\r\n * If a suggestion is provided, append it.\r\n */\r\nexport function outputError(err: XDBError): void {\r\n process.stderr.write(`Error: ${err.message}\\n`);\r\n}\r\n\r\n/**\r\n * Handle an error by writing it to stderr and exiting with the appropriate code.\r\n * If the error is not an XDBError, it is treated as a RUNTIME_ERROR.\r\n */\r\nexport function handleError(err: unknown): never {\r\n if (err instanceof XDBError) {\r\n outputError(err);\r\n process.exit(err.exitCode);\r\n }\r\n const message = err instanceof Error ? err.message : String(err);\r\n const xdbErr = new XDBError(RUNTIME_ERROR, message);\r\n outputError(xdbErr);\r\n process.exit(xdbErr.exitCode);\r\n}\r\n","import { PARAMETER_ERROR, XDBError } from './errors.js';\r\n\r\nexport interface FieldConfig {\r\n findCaps: Array<'similar' | 'match'>;\r\n}\r\n\r\nexport interface PolicyConfig {\r\n main: 'hybrid' | 'relational' | 'vector';\r\n minor: string;\r\n fields: Record<string, FieldConfig>;\r\n autoIndex?: boolean;\r\n}\r\n\r\nconst BUILTIN_POLICIES: Record<string, PolicyConfig> = {\r\n 'hybrid/knowledge-base': {\r\n main: 'hybrid',\r\n minor: 'knowledge-base',\r\n fields: { content: { findCaps: ['similar', 'match'] } },\r\n autoIndex: true,\r\n },\r\n 'relational/structured-logs': {\r\n main: 'relational',\r\n minor: 'structured-logs',\r\n fields: {},\r\n autoIndex: true,\r\n },\r\n 'relational/simple-kv': {\r\n main: 'relational',\r\n minor: 'simple-kv',\r\n fields: {},\r\n autoIndex: false,\r\n },\r\n 'vector/feature-store': {\r\n main: 'vector',\r\n minor: 'feature-store',\r\n fields: { tensor: { findCaps: ['similar'] } },\r\n autoIndex: false,\r\n },\r\n};\r\n\r\nconst DEFAULT_MINORS: Record<string, string> = {\r\n hybrid: 'knowledge-base',\r\n relational: 'structured-logs',\r\n vector: 'feature-store',\r\n};\r\n\r\n/** Allowed findCaps per main engine type */\r\nconst ALLOWED_CAPS: Record<string, Set<string>> = {\r\n hybrid: new Set(['similar', 'match']),\r\n relational: new Set(['match']),\r\n vector: new Set(['similar']),\r\n};\r\n\r\nexport class PolicyRegistry {\r\n /**\r\n * Resolve a policy string like \"hybrid/knowledge-base\" or just \"hybrid\"\r\n * into a full PolicyConfig. Optionally deep-merge params overrides.\r\n */\r\n resolve(policyStr: string, params?: Record<string, unknown>): PolicyConfig {\r\n let fullName = policyStr;\r\n\r\n // If no slash, resolve using default minor\r\n if (!policyStr.includes('/')) {\r\n const defaultMinor = DEFAULT_MINORS[policyStr];\r\n if (!defaultMinor) {\r\n const available = Object.keys(BUILTIN_POLICIES).join(', ');\r\n throw new XDBError(PARAMETER_ERROR, `Unknown policy \"${policyStr}\". Available policies: ${available}`);\r\n }\r\n fullName = `${policyStr}/${defaultMinor}`;\r\n }\r\n\r\n const builtin = BUILTIN_POLICIES[fullName];\r\n if (!builtin) {\r\n const available = Object.keys(BUILTIN_POLICIES).join(', ');\r\n throw new XDBError(PARAMETER_ERROR, `Unknown policy \"${fullName}\". Available policies: ${available}`);\r\n }\r\n\r\n // Deep clone the builtin policy\r\n const config: PolicyConfig = {\r\n main: builtin.main,\r\n minor: builtin.minor,\r\n fields: deepCloneFields(builtin.fields),\r\n ...(builtin.autoIndex !== undefined ? { autoIndex: builtin.autoIndex } : {}),\r\n };\r\n\r\n // Merge params overrides (especially fields)\r\n if (params) {\r\n if (params.fields && typeof params.fields === 'object') {\r\n const paramFields = params.fields as Record<string, FieldConfig>;\r\n for (const [fieldName, fieldConfig] of Object.entries(paramFields)) {\r\n config.fields[fieldName] = { findCaps: [...fieldConfig.findCaps] };\r\n }\r\n }\r\n if (params.autoIndex !== undefined) {\r\n config.autoIndex = params.autoIndex as boolean;\r\n } }\r\n\r\n return config;\r\n }\r\n\r\n /**\r\n * Validate that a PolicyConfig's findCaps are compatible with its main engine type.\r\n * Throws XDBError(PARAMETER_ERROR) if validation fails.\r\n */\r\n validate(config: PolicyConfig): void {\r\n const allowed = ALLOWED_CAPS[config.main];\r\n if (!allowed) {\r\n throw new XDBError(PARAMETER_ERROR, `Unknown main engine type \"${config.main}\"`);\r\n }\r\n\r\n for (const [fieldName, fieldConfig] of Object.entries(config.fields)) {\r\n for (const cap of fieldConfig.findCaps) {\r\n if (!allowed.has(cap)) {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n `findCaps \"${cap}\" is not compatible with engine type \"${config.main}\" (field: \"${fieldName}\")`,\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n /** List all available built-in policies. */\r\n listPolicies(): PolicyConfig[] {\r\n return Object.values(BUILTIN_POLICIES).map((p) => ({\r\n main: p.main,\r\n minor: p.minor,\r\n fields: deepCloneFields(p.fields),\r\n ...(p.autoIndex !== undefined ? { autoIndex: p.autoIndex } : {}),\r\n }));\r\n }\r\n}\r\n\r\nfunction deepCloneFields(fields: Record<string, FieldConfig>): Record<string, FieldConfig> {\r\n const result: Record<string, FieldConfig> = {};\r\n for (const [key, value] of Object.entries(fields)) {\r\n result[key] = { findCaps: [...value.findCaps] };\r\n }\r\n return result;\r\n}\r\n","import type { Command } from 'commander';\r\nimport { PolicyRegistry } from '../policy-registry.js';\r\nimport { handleError } from '../errors.js';\r\n\r\n/** Engine descriptions for human-readable output */\r\nconst ENGINE_DESC: Record<string, string> = {\r\n hybrid: 'LanceDB + SQLite',\r\n relational: 'SQLite',\r\n vector: 'LanceDB',\r\n};\r\n\r\nexport function registerPolicyCommands(policy: Command): void {\r\n policy\r\n .command('list')\r\n .description('List all available built-in policies')\r\n .option('--json', 'Output as JSON array')\r\n .action((opts: { json?: boolean }) => {\r\n process.stderr.write(\"[Deprecated] xdb policy list is deprecated. Use 'xdb config' instead.\\n\");\r\n try {\r\n const registry = new PolicyRegistry();\r\n const policies = registry.listPolicies();\r\n\r\n if (opts.json) {\r\n process.stdout.write(JSON.stringify(policies) + '\\n');\r\n return;\r\n }\r\n\r\n for (const p of policies) {\r\n const name = `${p.main}/${p.minor}`;\r\n const engines = ENGINE_DESC[p.main] ?? p.main;\r\n const fieldNames = Object.keys(p.fields);\r\n const fieldsStr = fieldNames.length > 0\r\n ? fieldNames.map((f) => {\r\n const caps = p.fields[f]!.findCaps.join(', ');\r\n return `${f} [${caps}]`;\r\n }).join('; ')\r\n : '(none)';\r\n const autoIdx = p.autoIndex ? 'yes' : 'no';\r\n\r\n process.stdout.write(`${name}\\n`);\r\n process.stdout.write(` engines: ${engines}\\n`);\r\n process.stdout.write(` fields: ${fieldsStr}\\n`);\r\n process.stdout.write(` autoIndex: ${autoIdx}\\n`);\r\n }\r\n } catch (err) {\r\n handleError(err);\r\n }\r\n });\r\n}\r\n","import { homedir } from 'node:os';\r\nimport { join } from 'node:path';\r\nimport type { Command } from 'commander';\r\nimport { CollectionManager } from '../collection-manager.js';\r\nimport { Embedder } from '../embedder.js';\r\nimport { DataWriter } from '../data-writer.js';\r\nimport { handleError, PARAMETER_ERROR, XDBError } from '../errors.js';\r\nimport { LanceDBEngine } from '../engines/lancedb-engine.js';\r\nimport { SQLiteEngine } from '../engines/sqlite-engine.js';\r\nimport type { PolicyConfig } from '../policy-registry.js';\r\n\r\nfunction getDataRoot(): string {\r\n return join(homedir(), '.local', 'share', 'xdb');\r\n}\r\n\r\n/** Read all of stdin as a string. Returns empty string if stdin is a TTY. */\r\nfunction readStdin(): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n if (process.stdin.isTTY) {\r\n resolve('');\r\n return;\r\n }\r\n const chunks: Buffer[] = [];\r\n process.stdin.on('data', (chunk: Buffer) => chunks.push(chunk));\r\n process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\r\n process.stdin.on('error', reject);\r\n });\r\n}\r\n\r\n/** Parse JSONL string into an array of records. Throws on invalid JSON. */\r\nfunction parseJsonl(input: string): Record<string, unknown>[] {\r\n const lines = input.split('\\n').filter((l) => l.trim().length > 0);\r\n return lines.map((line, i) => {\r\n try {\r\n const parsed = JSON.parse(line);\r\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\r\n throw new Error('Expected a JSON object');\r\n }\r\n return parsed as Record<string, unknown>;\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new XDBError(PARAMETER_ERROR, `Invalid JSON at line ${i + 1}: ${msg}`);\r\n }\r\n });\r\n}\r\n\r\n/** Determine which engines to open based on policy */\r\nfunction needsLance(policy: PolicyConfig): boolean {\r\n return policy.main === 'hybrid' || policy.main === 'vector';\r\n}\r\n\r\nfunction needsSqlite(policy: PolicyConfig): boolean {\r\n return policy.main === 'hybrid' || policy.main === 'relational';\r\n}\r\n\r\nexport function registerPutCommand(program: Command): void {\r\n program\r\n .command('put <collection> [json]')\r\n .description('Write data to a collection')\r\n .option('--batch', 'Enable batch write mode for JSONL stdin input')\r\n .option('--json', 'Output stats as JSON (batch mode)')\r\n .action(async (collection: string, json: string | undefined, opts: { batch?: boolean; json?: boolean }) => {\r\n try {\r\n await executePut(getDataRoot(), collection, json, !!opts.batch, !!opts.json);\r\n } catch (err) {\r\n handleError(err);\r\n }\r\n });\r\n}\r\n\r\nexport async function executePut(\r\n dataRoot: string,\r\n collection: string,\r\n json: string | undefined,\r\n batch: boolean,\r\n jsonOutput: boolean = false,\r\n): Promise<void> {\r\n // 1. Load collection meta\r\n const manager = new CollectionManager(dataRoot);\r\n const meta = await manager.load(collection); // throws if not exists (Req 4.7)\r\n const policy = meta.policy;\r\n const colPath = join(dataRoot, 'collections', collection);\r\n\r\n // 2. Open engines based on policy\r\n let lanceEngine: LanceDBEngine | undefined;\r\n let sqliteEngine: SQLiteEngine | undefined;\r\n\r\n try {\r\n if (needsLance(policy)) {\r\n lanceEngine = await LanceDBEngine.open(colPath);\r\n }\r\n if (needsSqlite(policy)) {\r\n sqliteEngine = SQLiteEngine.open(colPath);\r\n sqliteEngine.initSchema(policy);\r\n }\r\n\r\n // 3. Create Embedder and DataWriter\r\n const embedder = new Embedder();\r\n const writer = new DataWriter(policy, embedder, lanceEngine, sqliteEngine, async (dim) => {\r\n await manager.recordEmbeddingDimension(collection, dim);\r\n });\r\n\r\n // 4. Collect records\r\n let records: Record<string, unknown>[];\r\n\r\n if (json !== undefined) {\r\n // Positional argument: single JSON object\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(json);\r\n } catch {\r\n throw new XDBError(PARAMETER_ERROR, `Invalid JSON: ${json}`);\r\n }\r\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\r\n throw new XDBError(PARAMETER_ERROR, 'Invalid input: expected a JSON object');\r\n }\r\n records = [parsed as Record<string, unknown>];\r\n } else {\r\n // Read from stdin (JSONL)\r\n const input = await readStdin();\r\n if (input.trim().length === 0) {\r\n throw new XDBError(PARAMETER_ERROR, 'No input provided. Pass JSON as argument or pipe JSONL via stdin.');\r\n }\r\n records = parseJsonl(input);\r\n }\r\n\r\n // 5. Write data\r\n if (batch) {\r\n const stats = await writer.writeBatch(records);\r\n if (jsonOutput) {\r\n process.stdout.write(JSON.stringify(stats) + '\\n');\r\n } else {\r\n process.stderr.write(`Batch complete: ${stats.inserted} inserted, ${stats.updated} updated, ${stats.errors} errors\\n`);\r\n }\r\n } else {\r\n for (const record of records) {\r\n await writer.write(record);\r\n }\r\n process.stderr.write(`${records.length} record(s) written to \"${collection}\"\\n`);\r\n }\r\n } finally {\r\n // 6. Close engines\r\n if (lanceEngine) await lanceEngine.close();\r\n if (sqliteEngine) sqliteEngine.close();\r\n }\r\n}\r\n","/**\r\n * Embedding API client for OpenAI-compatible endpoints.\r\n * Calls provider HTTP endpoints directly.\r\n */\r\n\r\nimport { XDBError, RUNTIME_ERROR, PARAMETER_ERROR } from './errors.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface EmbeddingRequest {\r\n texts: string[];\r\n model: string;\r\n}\r\n\r\nexport interface EmbeddingResponse {\r\n embeddings: number[][];\r\n model: string;\r\n usage: {\r\n promptTokens: number;\r\n totalTokens: number;\r\n };\r\n}\r\n\r\nexport interface EmbeddingClientConfig {\r\n provider: string;\r\n apiKey: string;\r\n model: string;\r\n baseUrl?: string;\r\n providerOptions?: Record<string, any>;\r\n /** The API type, e.g. 'azure-openai-responses' */\r\n api?: string;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Provider default base URLs\r\n// ---------------------------------------------------------------------------\r\n\r\nconst PROVIDER_DEFAULT_BASE_URLS: Record<string, string> = {\r\n openai: 'https://api.openai.com',\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// EmbeddingClient\r\n// ---------------------------------------------------------------------------\r\n\r\nexport class EmbeddingClient {\r\n private readonly endpoint: string;\r\n private readonly apiKey: string;\r\n private readonly model: string;\r\n private readonly isAzure: boolean;\r\n\r\n constructor(config: EmbeddingClientConfig) {\r\n this.apiKey = config.apiKey;\r\n this.model = config.model;\r\n const apiType = config.api ?? config.provider;\r\n this.isAzure = apiType === 'azure-openai-responses' || apiType === 'azure-openai';\r\n this.endpoint = this.isAzure\r\n ? EmbeddingClient.resolveAzureEndpoint(config.baseUrl, config.model, config.providerOptions)\r\n : EmbeddingClient.resolveEndpoint(config.provider, config.baseUrl);\r\n }\r\n\r\n /**\r\n * Resolve the full embeddings API endpoint URL.\r\n * If baseUrl is provided, use it; otherwise fall back to the provider default.\r\n */\r\n static resolveEndpoint(provider: string, baseUrl?: string): string {\r\n const base =\r\n baseUrl ?? (Object.hasOwn(PROVIDER_DEFAULT_BASE_URLS, provider) ? PROVIDER_DEFAULT_BASE_URLS[provider] : undefined);\r\n if (!base) {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n `No base URL configured for provider \"${provider}\". Please specify a baseUrl.`,\r\n );\r\n }\r\n // Strip trailing slash before appending path\r\n return `${base.replace(/\\/+$/, '')}/v1/embeddings`;\r\n }\r\n\r\n /**\r\n * Resolve the Azure OpenAI embeddings endpoint URL.\r\n * Azure format: {baseUrl}/openai/deployments/{deployment}/embeddings?api-version={version}\r\n */\r\n static resolveAzureEndpoint(baseUrl?: string, model?: string, providerOptions?: Record<string, any>): string {\r\n if (!baseUrl) {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n 'Azure OpenAI requires a baseUrl. Please specify a baseUrl.',\r\n );\r\n }\r\n // For embeddings, use the model name as deployment name (embedding deployments\r\n // are typically named after the model). azureDeploymentName in providerOptions\r\n // usually refers to the chat model deployment, not the embedding one.\r\n const deployment = model ?? providerOptions?.azureDeploymentName;\r\n if (!deployment) {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n 'Azure OpenAI requires a deployment name. Specify a model or set providerOptions.azureDeploymentName.',\r\n );\r\n }\r\n const apiVersion = providerOptions?.azureApiVersion;\r\n // If azureApiVersion looks invalid (e.g. \"v1\"), fall back to a known good default\r\n const resolvedVersion = (apiVersion && /^\\d{4}-\\d{2}-\\d{2}/.test(apiVersion))\r\n ? apiVersion\r\n : '2024-06-01';\r\n // Strip any /openai/v1 or trailing path from baseUrl to get the resource root\r\n const resourceBase = baseUrl.replace(/\\/openai\\/v1\\/?$/, '').replace(/\\/+$/, '');\r\n return `${resourceBase}/openai/deployments/${deployment}/embeddings?api-version=${resolvedVersion}`;\r\n }\r\n\r\n /**\r\n * Call the embedding API for the given texts.\r\n */\r\n async embed(request: EmbeddingRequest): Promise<EmbeddingResponse> {\r\n const body = JSON.stringify({\r\n model: request.model,\r\n input: request.texts,\r\n });\r\n\r\n let response: Response;\r\n try {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n };\r\n if (this.isAzure) {\r\n headers['api-key'] = this.apiKey;\r\n } else {\r\n headers['Authorization'] = `Bearer ${this.apiKey}`;\r\n }\r\n\r\n response = await fetch(this.endpoint, {\r\n method: 'POST',\r\n headers,\r\n body,\r\n });\r\n } catch (err: unknown) {\r\n // Network-level errors (timeout, DNS, connection refused, etc.)\r\n const message = err instanceof Error ? err.message : String(err);\r\n throw new XDBError(\r\n RUNTIME_ERROR,\r\n `Network error calling embedding API: ${message}`,\r\n );\r\n }\r\n\r\n if (!response.ok) {\r\n let detail = '';\r\n try {\r\n const errorBody = await response.text();\r\n detail = errorBody;\r\n } catch {\r\n // ignore – we already have the status code\r\n }\r\n throw new XDBError(\r\n RUNTIME_ERROR,\r\n `Embedding API error (${response.status}): ${detail || response.statusText}`,\r\n );\r\n }\r\n\r\n // Parse successful response (OpenAI-compatible format)\r\n const json = (await response.json()) as {\r\n data: { embedding: number[]; index: number }[];\r\n model: string;\r\n usage: { prompt_tokens: number; total_tokens: number };\r\n };\r\n\r\n // Sort by index to guarantee order matches input order\r\n const sorted = [...json.data].sort((a, b) => a.index - b.index);\r\n\r\n return {\r\n embeddings: sorted.map((d) => d.embedding),\r\n model: json.model,\r\n usage: {\r\n promptTokens: json.usage.prompt_tokens,\r\n totalTokens: json.usage.total_tokens,\r\n },\r\n };\r\n }\r\n}\r\n","import * as fs from 'fs/promises';\r\nimport * as path from 'path';\r\nimport * as os from 'os';\r\nimport { XDBError, PARAMETER_ERROR, RUNTIME_ERROR } from './errors.js';\r\n\r\nexport interface XdbProviderConfig {\r\n name: string;\r\n apiKey?: string;\r\n baseUrl?: string;\r\n api?: string; // e.g. 'azure-openai'\r\n providerOptions?: Record<string, unknown>;\r\n}\r\n\r\nexport interface XdbConfig {\r\n defaultEmbedProvider?: string;\r\n defaultEmbedModel?: string;\r\n providers: XdbProviderConfig[];\r\n}\r\n\r\n/** Minimal shape of pai's config file we care about for embed fallback */\r\ninterface PaiConfig {\r\n defaultEmbedProvider?: string;\r\n defaultEmbedModel?: string;\r\n providers?: Array<{\r\n name: string;\r\n apiKey?: string;\r\n baseUrl?: string;\r\n api?: string;\r\n providerOptions?: Record<string, unknown>;\r\n oauth?: unknown;\r\n }>;\r\n}\r\n\r\nconst DEFAULT_CONFIG_PATH = path.join(os.homedir(), '.config', 'xdb', 'default.json');\r\nconst PAI_CONFIG_PATH = path.join(os.homedir(), '.config', 'pai', 'default.json');\r\n\r\nconst EMPTY_CONFIG: XdbConfig = {\r\n providers: [],\r\n};\r\n\r\nexport class XdbConfigManager {\r\n private readonly configPath: string;\r\n private readonly paiConfigPath: string;\r\n\r\n constructor(configPath?: string, paiConfigPath?: string) {\r\n this.configPath = configPath ?? DEFAULT_CONFIG_PATH;\r\n this.paiConfigPath = paiConfigPath ?? PAI_CONFIG_PATH;\r\n }\r\n\r\n async load(): Promise<XdbConfig> {\r\n let raw: string;\r\n try {\r\n raw = await fs.readFile(this.configPath, 'utf-8');\r\n } catch (err: unknown) {\r\n // File not found → return empty default config\r\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\r\n return { ...EMPTY_CONFIG, providers: [] };\r\n }\r\n throw new XDBError(RUNTIME_ERROR, `Failed to read config file: ${(err as Error).message}`);\r\n }\r\n\r\n try {\r\n const parsed = JSON.parse(raw) as XdbConfig;\r\n // Ensure providers array exists\r\n if (!Array.isArray(parsed.providers)) {\r\n parsed.providers = [];\r\n }\r\n return parsed;\r\n } catch {\r\n throw new XDBError(RUNTIME_ERROR, `Config file contains invalid JSON: ${this.configPath}`);\r\n }\r\n }\r\n\r\n async save(config: XdbConfig): Promise<void> {\r\n const dir = path.dirname(this.configPath);\r\n try {\r\n await fs.mkdir(dir, { recursive: true });\r\n } catch (err: unknown) {\r\n throw new XDBError(RUNTIME_ERROR, `Failed to create config directory: ${(err as Error).message}`);\r\n }\r\n\r\n try {\r\n await fs.writeFile(this.configPath, JSON.stringify(config, null, 2), 'utf-8');\r\n } catch (err: unknown) {\r\n throw new XDBError(RUNTIME_ERROR, `Failed to write config file: ${(err as Error).message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Resolve API key for a provider.\r\n * Priority: XDB_<PROVIDER>_API_KEY env var > config file apiKey\r\n */\r\n async resolveApiKey(providerName: string): Promise<string> {\r\n // Build env var name: uppercase, hyphens → underscores, prefix XDB_, suffix _API_KEY\r\n const envVarName = `XDB_${providerName.toUpperCase().replace(/-/g, '_')}_API_KEY`;\r\n const envValue = process.env[envVarName];\r\n if (envValue) {\r\n return envValue;\r\n }\r\n\r\n const config = await this.load();\r\n const providerConfig = config.providers.find((p) => p.name === providerName);\r\n if (providerConfig?.apiKey) {\r\n return providerConfig.apiKey;\r\n }\r\n\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n `No API key found for provider \"${providerName}\". ` +\r\n `Set the ${envVarName} environment variable or run: xdb config embed --set-key <apiKey>`,\r\n );\r\n }\r\n\r\n /**\r\n * Try to load pai's config as an embed fallback.\r\n * Returns null if pai config doesn't exist or has no embed settings.\r\n */\r\n private async loadPaiFallback(): Promise<{ provider: string; model: string; providerConfig: XdbProviderConfig; apiKey: string } | null> {\r\n let raw: string;\r\n try {\r\n raw = await fs.readFile(this.paiConfigPath, 'utf-8');\r\n } catch {\r\n return null;\r\n }\r\n\r\n let pai: PaiConfig;\r\n try {\r\n pai = JSON.parse(raw) as PaiConfig;\r\n } catch {\r\n return null;\r\n }\r\n\r\n const provider = pai.defaultEmbedProvider;\r\n const model = pai.defaultEmbedModel;\r\n if (!provider || !model) return null;\r\n\r\n const paiProvider = pai.providers?.find((p) => p.name === provider);\r\n if (!paiProvider) return null;\r\n\r\n // pai OAuth providers don't have a usable apiKey for embedding — skip them\r\n if (!paiProvider.apiKey) return null;\r\n\r\n const providerConfig: XdbProviderConfig = {\r\n name: paiProvider.name,\r\n apiKey: paiProvider.apiKey,\r\n ...(paiProvider.baseUrl !== undefined && { baseUrl: paiProvider.baseUrl }),\r\n ...(paiProvider.api !== undefined && { api: paiProvider.api }),\r\n ...(paiProvider.providerOptions !== undefined && { providerOptions: paiProvider.providerOptions }),\r\n };\r\n\r\n return { provider, model, providerConfig, apiKey: paiProvider.apiKey };\r\n }\r\n\r\n /**\r\n * Resolve the current embed configuration (provider + model + providerConfig + apiKey).\r\n * Priority:\r\n * 1. xdb's own config (~/.config/xdb/default.json or XDB_* env vars)\r\n * 2. pai's config (~/.config/pai/default.json) as fallback\r\n * Throws XDBError(PARAMETER_ERROR) if neither source has embed config.\r\n */\r\n async resolveEmbedConfig(): Promise<{\r\n provider: string;\r\n model: string;\r\n providerConfig: XdbProviderConfig;\r\n apiKey: string;\r\n }> {\r\n const config = await this.load();\r\n\r\n const provider = config.defaultEmbedProvider;\r\n const model = config.defaultEmbedModel;\r\n\r\n if (provider && model) {\r\n const providerConfig = config.providers.find((p) => p.name === provider) ?? { name: provider };\r\n const apiKey = await this.resolveApiKey(provider);\r\n return { provider, model, providerConfig, apiKey };\r\n }\r\n\r\n // Fallback: try pai config\r\n const paiFallback = await this.loadPaiFallback();\r\n if (paiFallback) {\r\n return paiFallback;\r\n }\r\n\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n 'No embed provider configured. Run: xdb config embed --set-provider <name>\\n' +\r\n 'Or configure pai embed settings: pai model default --embed-provider <name> --embed-model <model>',\r\n );\r\n }\r\n}\r\n","import { XDBError, RUNTIME_ERROR } from './errors.js';\r\nimport { EmbeddingClient } from './embedding-client.js';\r\nimport { XdbConfigManager } from './config-manager.js';\r\n\r\n/**\r\n * Internal embedder that calls EmbeddingClient directly.\r\n * Returns number[] / number[][] — no hex encoding.\r\n */\r\nexport class Embedder {\r\n private readonly configManager: XdbConfigManager;\r\n\r\n constructor(configManager?: XdbConfigManager) {\r\n this.configManager = configManager ?? new XdbConfigManager();\r\n }\r\n\r\n /**\r\n * Embed a single text string into a vector.\r\n * Returns number[] directly (no hex encoding).\r\n */\r\n async embed(text: string): Promise<number[]> {\r\n const { model, providerConfig, apiKey } = await this.configManager.resolveEmbedConfig();\r\n const client = new EmbeddingClient({\r\n provider: providerConfig.name,\r\n apiKey,\r\n model,\r\n ...(providerConfig.baseUrl !== undefined ? { baseUrl: providerConfig.baseUrl } : {}),\r\n ...(providerConfig.api !== undefined ? { api: providerConfig.api } : {}),\r\n ...(providerConfig.providerOptions !== undefined ? { providerOptions: providerConfig.providerOptions } : {}),\r\n });\r\n try {\r\n const response = await client.embed({ texts: [text], model });\r\n return response.embeddings[0]!;\r\n } catch (err) {\r\n if (err instanceof XDBError) throw err;\r\n throw new XDBError(RUNTIME_ERROR, `Embedding failed: ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n }\r\n\r\n /**\r\n * Embed multiple texts in a single batch call.\r\n * Returns number[][] directly (no hex encoding).\r\n */\r\n async embedBatch(texts: string[]): Promise<number[][]> {\r\n const { model, providerConfig, apiKey } = await this.configManager.resolveEmbedConfig();\r\n const client = new EmbeddingClient({\r\n provider: providerConfig.name,\r\n apiKey,\r\n model,\r\n ...(providerConfig.baseUrl !== undefined ? { baseUrl: providerConfig.baseUrl } : {}),\r\n ...(providerConfig.api !== undefined ? { api: providerConfig.api } : {}),\r\n ...(providerConfig.providerOptions !== undefined ? { providerOptions: providerConfig.providerOptions } : {}),\r\n });\r\n try {\r\n const response = await client.embed({ texts, model });\r\n return response.embeddings;\r\n } catch (err) {\r\n if (err instanceof XDBError) throw err;\r\n throw new XDBError(RUNTIME_ERROR, `Embedding failed: ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n }\r\n}\r\n","import { v4 as uuidv4 } from 'uuid';\r\nimport { PARAMETER_ERROR, XDBError } from './errors.js';\r\nimport type { Embedder } from './embedder.js';\r\nimport type { LanceDBEngine } from './engines/lancedb-engine.js';\r\nimport type { SQLiteEngine } from './engines/sqlite-engine.js';\r\nimport type { PolicyConfig } from './policy-registry.js';\r\n\r\nexport interface WriteResult {\r\n inserted: number;\r\n updated: number;\r\n errors: number;\r\n}\r\n\r\nexport class DataWriter {\r\n private dimensionRecorded = false;\r\n\r\n constructor(\r\n private policy: PolicyConfig,\r\n private embedder: Embedder,\r\n private lanceEngine?: LanceDBEngine,\r\n private sqliteEngine?: SQLiteEngine,\r\n private onEmbeddingDimension?: (dimension: number) => Promise<void>,\r\n ) {}\r\n\r\n /** Report embedding dimension on first encounter */\r\n private async reportDimension(vector: number[]): Promise<void> {\r\n if (this.dimensionRecorded || !this.onEmbeddingDimension) return;\r\n this.dimensionRecorded = true;\r\n await this.onEmbeddingDimension(vector.length);\r\n }\r\n\r\n /**\r\n * Write a single record. Auto-generates UUID if no `id` field present.\r\n * Routes data to engines based on Policy findCaps configuration.\r\n */\r\n async write(record: Record<string, unknown>): Promise<WriteResult> {\r\n this.validateRecord(record);\r\n\r\n // Auto-generate UUID if missing\r\n if (record.id === undefined || record.id === null) {\r\n record = { ...record, id: uuidv4() };\r\n }\r\n\r\n const result: WriteResult = { inserted: 0, updated: 0, errors: 0 };\r\n\r\n // Determine which engines need data\r\n const hasSimilarFields = this.getSimilarFields().length > 0;\r\n const needsSqlite = this.needsSqliteWrite();\r\n\r\n // Write to LanceDB if there are similar fields\r\n if (hasSimilarFields && this.lanceEngine) {\r\n const vectorRecord = await this.buildVectorRecord(record);\r\n const lanceResult = await this.lanceEngine.upsert([vectorRecord]);\r\n result.inserted += lanceResult.inserted;\r\n result.updated += lanceResult.updated;\r\n }\r\n\r\n // Write to SQLite if needed\r\n if (needsSqlite && this.sqliteEngine) {\r\n const sqliteResult = this.sqliteEngine.upsert([record]);\r\n // Only count SQLite stats if LanceDB didn't already count\r\n if (!hasSimilarFields || !this.lanceEngine) {\r\n result.inserted += sqliteResult.inserted;\r\n result.updated += sqliteResult.updated;\r\n }\r\n }\r\n\r\n // If neither engine was written to, still count as inserted\r\n if ((!hasSimilarFields || !this.lanceEngine) && (!needsSqlite || !this.sqliteEngine)) {\r\n result.inserted = 1;\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Batch write with transaction optimization and error tolerance.\r\n * Failed records are skipped with a warning to stderr.\r\n */\r\n async writeBatch(records: Record<string, unknown>[]): Promise<WriteResult> {\r\n const result: WriteResult = { inserted: 0, updated: 0, errors: 0 };\r\n\r\n // Validate and prepare records, assigning UUIDs where needed\r\n const prepared: Record<string, unknown>[] = [];\r\n const validIndices: number[] = [];\r\n\r\n for (let i = 0; i < records.length; i++) {\r\n try {\r\n this.validateRecord(records[i]);\r\n let rec = records[i]!;\r\n if (rec.id === undefined || rec.id === null) {\r\n rec = { ...rec, id: uuidv4() };\r\n }\r\n prepared.push(rec);\r\n validIndices.push(i);\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n process.stderr.write(`Warning: Line ${i + 1}: ${msg}\\n`);\r\n result.errors++;\r\n }\r\n }\r\n\r\n if (prepared.length === 0) {\r\n return result;\r\n }\r\n\r\n const hasSimilarFields = this.getSimilarFields().length > 0;\r\n const needsSqlite = this.needsSqliteWrite();\r\n\r\n // Write to LanceDB with batch embedding\r\n if (hasSimilarFields && this.lanceEngine) {\r\n const vectorRecords: Record<string, unknown>[] = [];\r\n const similarFields = this.getSimilarFields();\r\n\r\n // Collect all texts for batch embedding\r\n const textsPerField: Map<string, string[]> = new Map();\r\n for (const field of similarFields) {\r\n textsPerField.set(field, prepared.map((r) => String(r[field] ?? '')));\r\n }\r\n\r\n // Batch embed each similar field\r\n const vectorsPerField: Map<string, number[][]> = new Map();\r\n for (const [field, texts] of textsPerField) {\r\n const vectors = await this.embedder.embedBatch(texts);\r\n if (vectors.length > 0) {\r\n await this.reportDimension(vectors[0]!);\r\n }\r\n vectorsPerField.set(field, vectors);\r\n }\r\n\r\n // Build vector records\r\n for (let i = 0; i < prepared.length; i++) {\r\n const rec: Record<string, unknown> = { ...prepared[i] };\r\n for (const [field, vectors] of vectorsPerField) {\r\n rec[`${field}_vector`] = new Float32Array(vectors[i]!);\r\n }\r\n vectorRecords.push(rec);\r\n }\r\n\r\n try {\r\n const lanceResult = await this.lanceEngine.upsert(vectorRecords);\r\n result.inserted += lanceResult.inserted;\r\n result.updated += lanceResult.updated;\r\n } catch (err) {\r\n // In batch mode, lance failures count as errors for all records\r\n const msg = err instanceof Error ? err.message : String(err);\r\n process.stderr.write(`Warning: LanceDB batch write failed: ${msg}\\n`);\r\n result.errors += prepared.length;\r\n // If SQLite also needs writing, still attempt it\r\n if (needsSqlite && this.sqliteEngine) {\r\n const sqliteResult = this.sqliteEngine.batchUpsert(prepared);\r\n // Don't double-count — these were already counted as errors from lance\r\n // Just do the sqlite write for data consistency\r\n void sqliteResult;\r\n }\r\n return result;\r\n }\r\n }\r\n\r\n // Write to SQLite with batch transaction\r\n if (needsSqlite && this.sqliteEngine) {\r\n const sqliteResult = this.sqliteEngine.batchUpsert(prepared);\r\n // Only count SQLite stats if LanceDB didn't already count\r\n if (!hasSimilarFields || !this.lanceEngine) {\r\n result.inserted += sqliteResult.inserted;\r\n result.updated += sqliteResult.updated;\r\n }\r\n result.errors += sqliteResult.errors;\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /** Get field names that have 'similar' findCaps */\r\n private getSimilarFields(): string[] {\r\n return Object.entries(this.policy.fields)\r\n .filter(([, cfg]) => cfg.findCaps.includes('similar'))\r\n .map(([name]) => name);\r\n }\r\n\r\n /** Check if SQLite write is needed based on policy */\r\n private needsSqliteWrite(): boolean {\r\n // Has match fields\r\n const hasMatchFields = Object.values(this.policy.fields)\r\n .some((cfg) => cfg.findCaps.includes('match'));\r\n // autoIndex is enabled\r\n return hasMatchFields || !!this.policy.autoIndex;\r\n }\r\n\r\n /** Validate that a record is a valid object */\r\n private validateRecord(record: unknown): void {\r\n if (record === null || record === undefined || typeof record !== 'object' || Array.isArray(record)) {\r\n throw new XDBError(PARAMETER_ERROR, 'Invalid input: expected a JSON object');\r\n }\r\n }\r\n\r\n /** Build a record with vector fields for LanceDB */\r\n private async buildVectorRecord(record: Record<string, unknown>): Promise<Record<string, unknown>> {\r\n const similarFields = this.getSimilarFields();\r\n const vectorRecord: Record<string, unknown> = { ...record };\r\n\r\n for (const field of similarFields) {\r\n const text = String(record[field] ?? '');\r\n const vector = await this.embedder.embed(text);\r\n await this.reportDimension(vector);\r\n vectorRecord[`${field}_vector`] = new Float32Array(vector);\r\n }\r\n\r\n return vectorRecord;\r\n }\r\n}\r\n","import * as lancedb from '@lancedb/lancedb';\r\nimport { join } from 'node:path';\r\nimport { RUNTIME_ERROR, XDBError } from '../errors.js';\r\nimport type { SearchResult } from './sqlite-engine.js';\r\n\r\nexport type { SearchResult };\r\n\r\nconst DEFAULT_TABLE_NAME = 'data';\r\n\r\nexport class LanceDBEngine {\r\n private db: lancedb.Connection;\r\n private table: lancedb.Table;\r\n\r\n protected constructor(db: lancedb.Connection, table: lancedb.Table) {\r\n this.db = db;\r\n this.table = table;\r\n }\r\n\r\n /**\r\n * Open or create a LanceDB connection at `<collectionPath>/vector.lance/`.\r\n * If the table does not exist, it will be created on first upsert.\r\n */\r\n static async open(collectionPath: string, tableName?: string): Promise<LanceDBEngine> {\r\n const name = tableName ?? DEFAULT_TABLE_NAME;\r\n try {\r\n const dbPath = join(collectionPath, 'vector.lance');\r\n const db = await lancedb.connect(dbPath);\r\n\r\n // Try to open existing table, or leave table as null until first write\r\n let table: lancedb.Table;\r\n const tableNames = await db.tableNames();\r\n if (tableNames.includes(name)) {\r\n table = await db.openTable(name);\r\n } else {\r\n // Return an engine with a deferred table — will be created on first upsert\r\n return new LanceDBEngineDeferred(db, name);\r\n }\r\n\r\n return new LanceDBEngine(db, table);\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new XDBError(RUNTIME_ERROR, `Failed to open LanceDB: ${msg}`);\r\n }\r\n }\r\n\r\n /**\r\n * Write records containing vector fields, executing upsert (merge insert on \"id\").\r\n * Records should contain an `id` field and at least one vector field (array of numbers).\r\n */\r\n async upsert(records: Record<string, unknown>[]): Promise<{ inserted: number; updated: number }> {\r\n if (records.length === 0) {\r\n return { inserted: 0, updated: 0 };\r\n }\r\n\r\n try {\r\n const countBefore = await this.table.countRows();\r\n\r\n // Build a proper Arrow Table with FixedSizeList for vector columns.\r\n // LanceDB's mergeInsert path calls makeArrowTable without vectorColumns,\r\n // which would flatten Float32Array into individual numeric columns.\r\n const arrowTable = LanceDBEngine.toArrowTable(records);\r\n\r\n await this.table\r\n .mergeInsert('id')\r\n .whenMatchedUpdateAll()\r\n .whenNotMatchedInsertAll()\r\n .execute(arrowTable);\r\n\r\n const countAfter = await this.table.countRows();\r\n const netNew = countAfter - countBefore;\r\n const updated = records.length - netNew;\r\n\r\n return { inserted: netNew, updated };\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new XDBError(RUNTIME_ERROR, `LanceDB upsert failed: ${msg}`);\r\n }\r\n }\r\n\r\n /**\r\n * Convert records with Float32Array fields into a proper Arrow Table.\r\n * Detects Float32Array fields, registers them as vectorColumns, and\r\n * uses makeArrowTable to create FixedSizeList<Float32> columns.\r\n * If no Float32Array fields are found, returns records as-is for default handling.\r\n */\r\n protected static toArrowTable(records: Record<string, unknown>[]): Record<string, unknown>[] | ReturnType<typeof lancedb.makeArrowTable> {\r\n // Detect Float32Array fields\r\n const vectorColumnNames = new Set<string>();\r\n for (const rec of records) {\r\n for (const [key, value] of Object.entries(rec)) {\r\n if (value instanceof Float32Array) {\r\n vectorColumnNames.add(key);\r\n }\r\n }\r\n if (vectorColumnNames.size > 0) break; // Only need to check first record\r\n }\r\n\r\n if (vectorColumnNames.size === 0) {\r\n return records; // No vector fields, let LanceDB handle normally\r\n }\r\n\r\n // Build vectorColumns config and convert Float32Array to plain Array\r\n const vectorColumns: Record<string, lancedb.VectorColumnOptions> = {};\r\n for (const name of vectorColumnNames) {\r\n vectorColumns[name] = new lancedb.VectorColumnOptions();\r\n }\r\n\r\n const converted = records.map((rec) => {\r\n const out: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(rec)) {\r\n out[key] = value instanceof Float32Array ? Array.from(value) : value;\r\n }\r\n return out;\r\n });\r\n\r\n return lancedb.makeArrowTable(converted, { vectorColumns });\r\n }\r\n\r\n /**\r\n * Nearest neighbor vector search with optional pre-filter.\r\n */\r\n async vectorSearch(\r\n queryVector: number[],\r\n options: { limit: number; filter?: string; column?: string },\r\n ): Promise<SearchResult[]> {\r\n try {\r\n let query = this.table\r\n .vectorSearch(queryVector)\r\n .column(options.column ?? 'vector')\r\n .limit(options.limit);\r\n\r\n if (options.filter) {\r\n query = query.where(options.filter);\r\n }\r\n\r\n const results = await query.toArray();\r\n\r\n return results.map((row) => {\r\n const data: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(row)) {\r\n // Skip internal distance field and vector fields (Float32Array / large number arrays)\r\n if (key === '_distance') continue;\r\n if (key.endsWith('_vector')) continue;\r\n data[key] = value;\r\n }\r\n const result: SearchResult = {\r\n data,\r\n _engine: 'lancedb' as const,\r\n };\r\n // Convert cosine distance [0,2] → cosine similarity [0,1]: 1 - distance/2\r\n if (row._distance != null) {\r\n result._score = 1 - (row._distance as number) / 2;\r\n }\r\n return result;\r\n });\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new XDBError(RUNTIME_ERROR, `LanceDB vector search failed: ${msg}`);\r\n }\r\n }\r\n\r\n /**\r\n * Scalar filter query (no vector search).\r\n */\r\n async filterSearch(filter: string, limit: number): Promise<SearchResult[]> {\r\n try {\r\n const results = await this.table.query().where(filter).limit(limit).toArray();\r\n\r\n return results.map((row) => {\r\n const data: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(row)) {\r\n if (key.endsWith('_vector')) continue;\r\n data[key] = value;\r\n }\r\n return {\r\n data,\r\n _engine: 'lancedb' as const,\r\n };\r\n });\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new XDBError(RUNTIME_ERROR, `LanceDB filter search failed: ${msg}`);\r\n }\r\n }\r\n\r\n /**\r\n * Count total rows in the table.\r\n */\r\n async countRows(): Promise<number> {\r\n return this.table.countRows();\r\n }\r\n\r\n /**\r\n * Close the database connection.\r\n */\r\n async close(): Promise<void> {\r\n this.table.close();\r\n this.db.close();\r\n }\r\n}\r\n\r\n\r\n/**\r\n * A deferred variant of LanceDBEngine that creates the table on first upsert.\r\n * This is needed because LanceDB requires data to infer schema when creating a table.\r\n */\r\nclass LanceDBEngineDeferred extends LanceDBEngine {\r\n private deferredDb: lancedb.Connection;\r\n private tableName: string;\r\n private initialized = false;\r\n\r\n constructor(db: lancedb.Connection, tableName: string) {\r\n // Call parent with db and a placeholder — we override all methods\r\n super(db, undefined as unknown as lancedb.Table);\r\n this.deferredDb = db;\r\n this.tableName = tableName;\r\n }\r\n\r\n private async ensureTable(records?: Record<string, unknown>[]): Promise<lancedb.Table> {\r\n if (this.initialized) {\r\n return (this as any).table;\r\n }\r\n\r\n if (!records || records.length === 0) {\r\n throw new XDBError(RUNTIME_ERROR, 'LanceDB table does not exist yet. Write data first.');\r\n }\r\n\r\n // Use toArrowTable to properly handle Float32Array → FixedSizeList<Float32>\r\n const data = LanceDBEngine.toArrowTable(records);\r\n const table = await this.deferredDb.createTable(this.tableName, data);\r\n // Patch the parent's private fields\r\n (this as any).table = table;\r\n this.initialized = true;\r\n return table;\r\n }\r\n\r\n override async upsert(records: Record<string, unknown>[]): Promise<{ inserted: number; updated: number }> {\r\n if (records.length === 0) {\r\n return { inserted: 0, updated: 0 };\r\n }\r\n\r\n if (!this.initialized) {\r\n try {\r\n await this.ensureTable(records);\r\n return { inserted: records.length, updated: 0 };\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new XDBError(RUNTIME_ERROR, `LanceDB upsert failed: ${msg}`);\r\n }\r\n }\r\n\r\n return super.upsert(records);\r\n }\r\n\r\n override async vectorSearch(\r\n queryVector: number[],\r\n options: { limit: number; filter?: string; column?: string },\r\n ): Promise<SearchResult[]> {\r\n if (!this.initialized) {\r\n return [];\r\n }\r\n return super.vectorSearch(queryVector, options);\r\n }\r\n\r\n override async filterSearch(filter: string, limit: number): Promise<SearchResult[]> {\r\n if (!this.initialized) {\r\n return [];\r\n }\r\n return super.filterSearch(filter, limit);\r\n }\r\n\r\n override async countRows(): Promise<number> {\r\n if (!this.initialized) {\r\n return 0;\r\n }\r\n return super.countRows();\r\n }\r\n\r\n override async close(): Promise<void> {\r\n if (this.initialized) {\r\n (this as any).table.close();\r\n }\r\n this.deferredDb.close();\r\n }\r\n}\r\n","import Database from 'better-sqlite3';\r\nimport { join } from 'node:path';\r\nimport { RUNTIME_ERROR, XDBError } from '../errors.js';\r\nimport type { PolicyConfig } from '../policy-registry.js';\r\n\r\nexport interface SearchResult {\r\n data: Record<string, unknown>;\r\n _score?: number;\r\n _engine: 'lancedb' | 'sqlite';\r\n}\r\n\r\nexport class SQLiteEngine {\r\n private db: Database.Database;\r\n private hasFts = false;\r\n private ftsFields: string[] = [];\r\n\r\n private constructor(db: Database.Database) {\r\n this.db = db;\r\n }\r\n\r\n /**\r\n * Open or create a SQLite database at `<collectionPath>/relational.db`.\r\n */\r\n static open(collectionPath: string): SQLiteEngine {\r\n try {\r\n const dbPath = join(collectionPath, 'relational.db');\r\n const db = new Database(dbPath);\r\n db.pragma('journal_mode = WAL');\r\n return new SQLiteEngine(db);\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new XDBError(RUNTIME_ERROR, `Failed to open SQLite database: ${msg}`);\r\n }\r\n }\r\n\r\n /**\r\n * Initialize table schema based on Policy configuration.\r\n * Creates the records table and, if the policy has fields with 'match' findCaps,\r\n * creates a standalone FTS5 virtual table for full-text search.\r\n */\r\n initSchema(policy: PolicyConfig): void {\r\n this.db.exec(`\r\n CREATE TABLE IF NOT EXISTS records (\r\n id TEXT PRIMARY KEY,\r\n data JSON NOT NULL\r\n );\r\n `);\r\n\r\n // Determine which fields have 'match' findCaps\r\n this.ftsFields = Object.entries(policy.fields)\r\n .filter(([, cfg]) => cfg.findCaps.includes('match'))\r\n .map(([name]) => name);\r\n\r\n if (this.ftsFields.length > 0) {\r\n const columnDefs = this.ftsFields.join(', ');\r\n // Standalone FTS5 table (no content= sync) — we manage inserts/deletes manually\r\n this.db.exec(`\r\n CREATE VIRTUAL TABLE IF NOT EXISTS records_fts USING fts5(\r\n id UNINDEXED,\r\n ${columnDefs}\r\n );\r\n `);\r\n this.hasFts = true;\r\n }\r\n }\r\n\r\n /**\r\n * Sync FTS index for a single record: delete old entry then insert new one.\r\n */\r\n private syncFts(record: Record<string, unknown>): void {\r\n if (!this.hasFts) return;\r\n const id = String(record.id);\r\n\r\n // Delete existing FTS entry\r\n this.db.prepare('DELETE FROM records_fts WHERE id = ?').run(id);\r\n\r\n // Insert new FTS entry\r\n const cols = ['id', ...this.ftsFields];\r\n const placeholders = cols.map(() => '?').join(', ');\r\n const values = [id, ...this.ftsFields.map((f) => String(record[f] ?? ''))];\r\n this.db.prepare(`INSERT INTO records_fts (${cols.join(', ')}) VALUES (${placeholders})`).run(...values);\r\n }\r\n\r\n /**\r\n * Upsert records into the database. Each record must have an `id` field.\r\n * Uses INSERT OR REPLACE for upsert semantics.\r\n */\r\n upsert(records: Record<string, unknown>[]): { inserted: number; updated: number } {\r\n let inserted = 0;\r\n let updated = 0;\r\n\r\n const checkStmt = this.db.prepare('SELECT 1 FROM records WHERE id = ?');\r\n const upsertStmt = this.db.prepare(\r\n 'INSERT OR REPLACE INTO records (id, data) VALUES (?, ?)',\r\n );\r\n\r\n const txn = this.db.transaction(() => {\r\n for (const record of records) {\r\n const id = String(record.id);\r\n const exists = checkStmt.get(id);\r\n upsertStmt.run(id, JSON.stringify(record));\r\n this.syncFts(record);\r\n if (exists) {\r\n updated++;\r\n } else {\r\n inserted++;\r\n }\r\n }\r\n });\r\n\r\n txn();\r\n return { inserted, updated };\r\n }\r\n\r\n /**\r\n * Batch upsert with error tolerance. Wraps in a transaction.\r\n * Individual record failures are counted but don't abort the batch.\r\n */\r\n batchUpsert(records: Record<string, unknown>[]): { inserted: number; updated: number; errors: number } {\r\n let inserted = 0;\r\n let updated = 0;\r\n let errors = 0;\r\n\r\n const checkStmt = this.db.prepare('SELECT 1 FROM records WHERE id = ?');\r\n const upsertStmt = this.db.prepare(\r\n 'INSERT OR REPLACE INTO records (id, data) VALUES (?, ?)',\r\n );\r\n\r\n const txn = this.db.transaction(() => {\r\n for (const record of records) {\r\n try {\r\n const id = String(record.id);\r\n const exists = checkStmt.get(id);\r\n upsertStmt.run(id, JSON.stringify(record));\r\n this.syncFts(record);\r\n if (exists) {\r\n updated++;\r\n } else {\r\n inserted++;\r\n }\r\n } catch {\r\n errors++;\r\n }\r\n }\r\n });\r\n\r\n txn();\r\n return { inserted, updated, errors };\r\n }\r\n\r\n /**\r\n * Full-text search using FTS5.\r\n */\r\n ftsSearch(query: string, limit: number): SearchResult[] {\r\n if (!this.hasFts) {\r\n return [];\r\n }\r\n\r\n const stmt = this.db.prepare(`\r\n SELECT r.data, fts.rank\r\n FROM records_fts fts\r\n JOIN records r ON r.id = fts.id\r\n WHERE records_fts MATCH ?\r\n ORDER BY fts.rank\r\n LIMIT ?\r\n `);\r\n\r\n const rows = stmt.all(query, limit) as Array<{ data: string; rank: number }>;\r\n return rows.map((row) => ({\r\n data: JSON.parse(row.data) as Record<string, unknown>,\r\n _score: -row.rank, // FTS5 rank is negative; negate for positive score\r\n _engine: 'sqlite' as const,\r\n }));\r\n }\r\n\r\n /**\r\n * Condition-based filtering using a WHERE clause applied to JSON data.\r\n */\r\n whereSearch(filter: string, limit: number): SearchResult[] {\r\n try {\r\n const stmt = this.db.prepare(`\r\n SELECT data FROM records WHERE ${filter} LIMIT ?\r\n `);\r\n const rows = stmt.all(limit) as Array<{ data: string }>;\r\n return rows.map((row) => ({\r\n data: JSON.parse(row.data) as Record<string, unknown>,\r\n _engine: 'sqlite' as const,\r\n }));\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new XDBError(RUNTIME_ERROR, `WHERE filter error: ${msg}`);\r\n }\r\n }\r\n\r\n /**\r\n * Combined FTS + WHERE search.\r\n */\r\n ftsWhereSearch(query: string, filter: string, limit: number): SearchResult[] {\r\n if (!this.hasFts) {\r\n return [];\r\n }\r\n\r\n try {\r\n const stmt = this.db.prepare(`\r\n SELECT r.data, fts.rank\r\n FROM records_fts fts\r\n JOIN records r ON r.id = fts.id\r\n WHERE records_fts MATCH ? AND ${filter}\r\n ORDER BY fts.rank\r\n LIMIT ?\r\n `);\r\n const rows = stmt.all(query, limit) as Array<{ data: string; rank: number }>;\r\n return rows.map((row) => ({\r\n data: JSON.parse(row.data) as Record<string, unknown>,\r\n _score: -row.rank,\r\n _engine: 'sqlite' as const,\r\n }));\r\n } catch (err) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n throw new XDBError(RUNTIME_ERROR, `FTS+WHERE filter error: ${msg}`);\r\n }\r\n }\r\n\r\n /**\r\n * Count total rows in the records table.\r\n */\r\n countRows(): number {\r\n const row = this.db.prepare('SELECT COUNT(*) as cnt FROM records').get() as { cnt: number };\r\n return row.cnt;\r\n }\r\n\r\n /**\r\n * Close the database connection.\r\n */\r\n close(): void {\r\n this.db.close();\r\n }\r\n}\r\n","import { homedir } from 'node:os';\r\nimport { join } from 'node:path';\r\nimport type { Command } from 'commander';\r\nimport { CollectionManager } from '../collection-manager.js';\r\nimport { Embedder } from '../embedder.js';\r\nimport { DataFinder } from '../data-finder.js';\r\nimport { handleError, PARAMETER_ERROR, XDBError } from '../errors.js';\r\nimport { LanceDBEngine } from '../engines/lancedb-engine.js';\r\nimport { SQLiteEngine } from '../engines/sqlite-engine.js';\r\nimport type { PolicyConfig } from '../policy-registry.js';\r\n\r\nfunction getDataRoot(): string {\r\n return join(homedir(), '.local', 'share', 'xdb');\r\n}\r\n\r\n/** Read all of stdin as a string. Returns empty string if stdin is a TTY. */\r\nfunction readStdin(): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n if (process.stdin.isTTY) {\r\n resolve('');\r\n return;\r\n }\r\n const chunks: Buffer[] = [];\r\n process.stdin.on('data', (chunk: Buffer) => chunks.push(chunk));\r\n process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\r\n process.stdin.on('error', reject);\r\n });\r\n}\r\n\r\n/** Determine which engines to open based on policy */\r\nfunction needsLance(policy: PolicyConfig): boolean {\r\n return policy.main === 'hybrid' || policy.main === 'vector';\r\n}\r\n\r\nfunction needsSqlite(policy: PolicyConfig): boolean {\r\n return policy.main === 'hybrid' || policy.main === 'relational';\r\n}\r\n\r\nexport function registerFindCommand(program: Command): void {\r\n program\r\n .command('find <collection> [query]')\r\n .description('Search data in a collection')\r\n .option('-s, --similar', 'Semantic similarity search')\r\n .option('-m, --match', 'Full-text search')\r\n .option('-w, --where <sql>', 'SQL WHERE clause for filtering')\r\n .option('-l, --limit <n>', 'Maximum number of results', '10')\r\n .option('--json', 'Output as JSONL (machine-readable)')\r\n .action(\r\n async (\r\n collection: string,\r\n query: string | undefined,\r\n opts: { similar?: boolean; match?: boolean; where?: string; limit: string; json?: boolean },\r\n ) => {\r\n try {\r\n await executeFind(getDataRoot(), collection, query, opts);\r\n } catch (err) {\r\n handleError(err);\r\n }\r\n },\r\n );\r\n}\r\n\r\nexport async function executeFind(\r\n dataRoot: string,\r\n collection: string,\r\n query: string | undefined,\r\n opts: { similar?: boolean; match?: boolean; where?: string; limit: string; json?: boolean },\r\n): Promise<void> {\r\n // 1. Load collection meta\r\n const manager = new CollectionManager(dataRoot);\r\n const meta = await manager.load(collection); // throws if not exists\r\n const policy = meta.policy;\r\n const colPath = join(dataRoot, 'collections', collection);\r\n\r\n // Parse limit\r\n const limit = parseInt(opts.limit, 10);\r\n if (isNaN(limit) || limit <= 0) {\r\n throw new XDBError(PARAMETER_ERROR, `Invalid limit value: ${opts.limit}`);\r\n }\r\n\r\n // 2. If no query positional arg, read from stdin (Req 6.2)\r\n if (query === undefined && (opts.similar || opts.match)) {\r\n const stdinText = await readStdin();\r\n const trimmed = stdinText.trim();\r\n if (trimmed.length > 0) {\r\n query = trimmed;\r\n }\r\n }\r\n\r\n // 3. Open engines based on policy\r\n let lanceEngine: LanceDBEngine | undefined;\r\n let sqliteEngine: SQLiteEngine | undefined;\r\n\r\n try {\r\n if (needsLance(policy)) {\r\n lanceEngine = await LanceDBEngine.open(colPath);\r\n }\r\n if (needsSqlite(policy)) {\r\n sqliteEngine = SQLiteEngine.open(colPath);\r\n sqliteEngine.initSchema(policy);\r\n }\r\n\r\n // 4. Create Embedder and DataFinder\r\n const embedder = new Embedder();\r\n const finder = new DataFinder(policy, embedder, lanceEngine, sqliteEngine);\r\n\r\n // 5. Execute find\r\n const results = await finder.find(query, {\r\n ...(opts.similar !== undefined ? { similar: opts.similar } : {}),\r\n ...(opts.match !== undefined ? { match: opts.match } : {}),\r\n ...(opts.where !== undefined ? { where: opts.where } : {}),\r\n limit,\r\n });\r\n\r\n // 6. Output results\r\n if (results.length === 0) {\r\n if (!opts.json) {\r\n process.stderr.write('No results found.\\n');\r\n }\r\n return;\r\n }\r\n\r\n if (opts.json) {\r\n // JSONL output (Req 6.3, 7.2, 10.2)\r\n for (const result of results) {\r\n const output: Record<string, unknown> = {\r\n ...result.data,\r\n _score: result._score,\r\n _engine: result._engine,\r\n };\r\n process.stdout.write(JSON.stringify(output) + '\\n');\r\n }\r\n } else {\r\n // Human-readable output\r\n for (const result of results) {\r\n const score = typeof result._score === 'number' ? ` (score: ${result._score.toFixed(4)})` : '';\r\n const id = result.data.id ? `[${result.data.id}]` : '';\r\n // Show a compact summary of the data\r\n const dataKeys = Object.keys(result.data).filter((k) => k !== 'id');\r\n const preview = dataKeys\r\n .slice(0, 3)\r\n .map((k) => {\r\n const v = result.data[k];\r\n const s = typeof v === 'string' ? v : JSON.stringify(v);\r\n const truncated = s != null && s.length > 60 ? s.substring(0, 57) + '...' : s;\r\n return `${k}=${truncated}`;\r\n })\r\n .join(' ');\r\n const more = dataKeys.length > 3 ? ` (+${dataKeys.length - 3} more)` : '';\r\n process.stdout.write(`${id}${score} ${preview}${more}\\n`);\r\n }\r\n process.stderr.write(`${results.length} result(s) found.\\n`);\r\n }\r\n } finally {\r\n // 7. Close engines\r\n if (lanceEngine) await lanceEngine.close();\r\n if (sqliteEngine) sqliteEngine.close();\r\n }\r\n}\r\n","import { PARAMETER_ERROR, XDBError } from './errors.js';\r\nimport type { Embedder } from './embedder.js';\r\nimport type { LanceDBEngine } from './engines/lancedb-engine.js';\r\nimport type { SQLiteEngine, SearchResult } from './engines/sqlite-engine.js';\r\nimport type { PolicyConfig } from './policy-registry.js';\r\n\r\nexport type { SearchResult };\r\n\r\nexport interface FindOptions {\r\n similar?: boolean;\r\n match?: boolean;\r\n where?: string;\r\n limit: number;\r\n}\r\n\r\nexport class DataFinder {\r\n constructor(\r\n private policy: PolicyConfig,\r\n private embedder: Embedder,\r\n private lanceEngine?: LanceDBEngine,\r\n private sqliteEngine?: SQLiteEngine,\r\n ) {}\r\n\r\n /**\r\n * Execute a search based on intent flags and return results.\r\n * Routes to the appropriate engine(s) based on --similar/--match/--where.\r\n */\r\n async find(query: string | undefined, options: FindOptions): Promise<SearchResult[]> {\r\n const limit = options.limit ?? 10;\r\n\r\n if (options.similar) {\r\n return this.handleSimilar(query, options.where, limit);\r\n }\r\n\r\n if (options.match) {\r\n return this.handleMatch(query, options.where, limit);\r\n }\r\n\r\n if (options.where) {\r\n return this.handleWhereOnly(options.where, limit);\r\n }\r\n\r\n // No intent flags → parameter error\r\n throw new XDBError(PARAMETER_ERROR, 'No search intent specified. Use --similar, --match, or --where');\r\n }\r\n\r\n /** --similar: vector search via LanceDB */\r\n private async handleSimilar(query: string | undefined, where: string | undefined, limit: number): Promise<SearchResult[]> {\r\n // Capability check: policy must have fields with 'similar' findCaps\r\n if (!this.hasCap('similar')) {\r\n throw new XDBError(PARAMETER_ERROR, 'This collection does not support semantic search (no fields with \"similar\" findCaps)');\r\n }\r\n\r\n if (!query) {\r\n throw new XDBError(PARAMETER_ERROR, 'Query text is required for --similar search');\r\n }\r\n\r\n // Determine the vector column name: first field with 'similar' cap + '_vector'\r\n const similarField = this.getSimilarFields()[0];\r\n const column = `${similarField}_vector`;\r\n\r\n const vector = await this.embedder.embed(query);\r\n return this.lanceEngine!.vectorSearch(vector, {\r\n limit,\r\n ...(where !== undefined ? { filter: where } : {}),\r\n column,\r\n });\r\n }\r\n\r\n /** --match: full-text search via SQLite FTS5 */\r\n private async handleMatch(query: string | undefined, where: string | undefined, limit: number): Promise<SearchResult[]> {\r\n // Capability check: policy must have fields with 'match' findCaps\r\n if (!this.hasCap('match')) {\r\n throw new XDBError(PARAMETER_ERROR, 'This collection does not support full-text search (no fields with \"match\" findCaps)');\r\n }\r\n\r\n if (!query) {\r\n throw new XDBError(PARAMETER_ERROR, 'Query text is required for --match search');\r\n }\r\n\r\n if (where) {\r\n return this.sqliteEngine!.ftsWhereSearch(query, where, limit);\r\n }\r\n return this.sqliteEngine!.ftsSearch(query, limit);\r\n }\r\n\r\n /** --where only (no --similar or --match): prefer SQLite, fallback to LanceDB */\r\n private async handleWhereOnly(where: string, limit: number): Promise<SearchResult[]> {\r\n if (this.sqliteEngine) {\r\n return this.sqliteEngine.whereSearch(where, limit);\r\n }\r\n\r\n // Only LanceDB available → convert to native filter\r\n if (this.lanceEngine) {\r\n return this.lanceEngine.filterSearch(where, limit);\r\n }\r\n\r\n throw new XDBError(PARAMETER_ERROR, 'No search engine available for this collection');\r\n }\r\n\r\n /** Check if the policy has any field with the given findCap */\r\n private hasCap(cap: 'similar' | 'match'): boolean {\r\n return Object.values(this.policy.fields).some((cfg) => cfg.findCaps.includes(cap));\r\n }\r\n\r\n /** Get field names that have 'similar' findCaps */\r\n private getSimilarFields(): string[] {\r\n return Object.entries(this.policy.fields)\r\n .filter(([, cfg]) => cfg.findCaps.includes('similar'))\r\n .map(([name]) => name);\r\n }\r\n}\r\n","import type { Command } from 'commander';\r\nimport { XdbConfigManager } from '../config-manager.js';\r\nimport { PolicyRegistry } from '../policy-registry.js';\r\nimport { handleError, XDBError, PARAMETER_ERROR } from '../errors.js';\r\n\r\n/** Engine descriptions for human-readable output */\r\nconst ENGINE_DESC: Record<string, string> = {\r\n hybrid: 'LanceDB + SQLite',\r\n relational: 'SQLite',\r\n vector: 'LanceDB',\r\n};\r\n\r\n/** Mask an API key for display: show first 3 chars + last 4 chars */\r\nfunction maskApiKey(key: string): string {\r\n if (key.length <= 7) return '****';\r\n return `${key.slice(0, 3)}...${key.slice(-4)}`;\r\n}\r\n\r\n/** Core logic for `xdb config` (no subcommand), extracted for testability */\r\nexport async function executeConfig(\r\n opts: { json?: boolean },\r\n manager: XdbConfigManager = new XdbConfigManager(),\r\n): Promise<void> {\r\n const cfg = await manager.load();\r\n const registry = new PolicyRegistry();\r\n const policies = registry.listPolicies();\r\n\r\n if (opts.json) {\r\n let hasApiKey = false;\r\n const provider = cfg.defaultEmbedProvider;\r\n if (provider) {\r\n try {\r\n await manager.resolveApiKey(provider);\r\n hasApiKey = true;\r\n } catch {\r\n hasApiKey = false;\r\n }\r\n }\r\n\r\n const providerConfig = cfg.providers.find((p) => p.name === provider);\r\n\r\n const output = {\r\n embed: {\r\n provider: cfg.defaultEmbedProvider ?? null,\r\n model: cfg.defaultEmbedModel ?? null,\r\n baseUrl: providerConfig?.baseUrl ?? null,\r\n hasApiKey,\r\n },\r\n policies,\r\n };\r\n process.stdout.write(JSON.stringify(output, null, 2) + '\\n');\r\n return;\r\n }\r\n\r\n // Human-readable output\r\n const provider = cfg.defaultEmbedProvider ?? '(not set)';\r\n const model = cfg.defaultEmbedModel ?? '(not set)';\r\n const providerConfig = cfg.providers.find((p) => p.name === cfg.defaultEmbedProvider);\r\n const baseUrl = providerConfig?.baseUrl ?? '(default)';\r\n\r\n let apiKeyDisplay = '(not set)';\r\n if (cfg.defaultEmbedProvider) {\r\n try {\r\n const key = await manager.resolveApiKey(cfg.defaultEmbedProvider);\r\n apiKeyDisplay = maskApiKey(key);\r\n } catch {\r\n apiKeyDisplay = '(not set)';\r\n }\r\n }\r\n\r\n process.stdout.write('Embed Configuration:\\n');\r\n process.stdout.write(` provider: ${provider}\\n`);\r\n process.stdout.write(` model: ${model}\\n`);\r\n process.stdout.write(` base-url: ${baseUrl}\\n`);\r\n process.stdout.write(` api-key: ${apiKeyDisplay}\\n`);\r\n process.stdout.write('\\n');\r\n process.stdout.write('Available Policies:\\n');\r\n\r\n for (const p of policies) {\r\n const name = `${p.main}/${p.minor}`;\r\n const engines = ENGINE_DESC[p.main] ?? p.main;\r\n const fieldNames = Object.keys(p.fields);\r\n const fieldsStr =\r\n fieldNames.length > 0\r\n ? fieldNames\r\n .map((f) => {\r\n const caps = p.fields[f]!.findCaps.join(', ');\r\n return `${f} [${caps}]`;\r\n })\r\n .join('; ')\r\n : '(none)';\r\n const autoIdx = p.autoIndex ? 'yes' : 'no';\r\n\r\n process.stdout.write(` ${name}\\n`);\r\n process.stdout.write(` engines: ${engines}\\n`);\r\n process.stdout.write(` fields: ${fieldsStr}\\n`);\r\n process.stdout.write(` autoIndex: ${autoIdx}\\n`);\r\n }\r\n}\r\n\r\nexport interface ConfigEmbedOptions {\r\n setProvider?: string;\r\n setModel?: string;\r\n setKey?: string;\r\n setBaseUrl?: string;\r\n}\r\n\r\n/** Core logic for `xdb config embed`, extracted for testability */\r\nexport async function executeConfigEmbed(\r\n opts: ConfigEmbedOptions,\r\n manager: XdbConfigManager = new XdbConfigManager(),\r\n): Promise<void> {\r\n const cfg = await manager.load();\r\n\r\n if (opts.setProvider !== undefined) {\r\n cfg.defaultEmbedProvider = opts.setProvider;\r\n await manager.save(cfg);\r\n process.stdout.write(`Embed provider set to: ${opts.setProvider}\\n`);\r\n }\r\n\r\n if (opts.setModel !== undefined) {\r\n cfg.defaultEmbedModel = opts.setModel;\r\n await manager.save(cfg);\r\n process.stdout.write(`Embed model set to: ${opts.setModel}\\n`);\r\n }\r\n\r\n if (opts.setKey !== undefined) {\r\n if (!cfg.defaultEmbedProvider) {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n 'No embed provider configured. Run: xdb config embed --set-provider <name>',\r\n );\r\n }\r\n const existing = cfg.providers.find((p) => p.name === cfg.defaultEmbedProvider);\r\n if (existing) {\r\n existing.apiKey = opts.setKey;\r\n } else {\r\n cfg.providers.push({ name: cfg.defaultEmbedProvider!, apiKey: opts.setKey });\r\n }\r\n await manager.save(cfg);\r\n process.stdout.write(`API key set for provider: ${cfg.defaultEmbedProvider}\\n`);\r\n }\r\n\r\n if (opts.setBaseUrl !== undefined) {\r\n if (!cfg.defaultEmbedProvider) {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n 'No embed provider configured. Run: xdb config embed --set-provider <name>',\r\n );\r\n }\r\n const existing = cfg.providers.find((p) => p.name === cfg.defaultEmbedProvider);\r\n if (existing) {\r\n existing.baseUrl = opts.setBaseUrl;\r\n } else {\r\n cfg.providers.push({ name: cfg.defaultEmbedProvider!, baseUrl: opts.setBaseUrl });\r\n }\r\n await manager.save(cfg);\r\n process.stdout.write(`Base URL set for provider: ${cfg.defaultEmbedProvider}\\n`);\r\n }\r\n}\r\n\r\nexport function registerConfigCommands(config: Command): void {\r\n // xdb config (no subcommand): display full current configuration\r\n config\r\n .option('--json', 'Output as JSON')\r\n .action(async (opts: { json?: boolean }) => {\r\n try {\r\n await executeConfig(opts);\r\n } catch (err) {\r\n handleError(err);\r\n }\r\n });\r\n\r\n // xdb config embed subcommand\r\n config\r\n .command('embed')\r\n .description('Manage embed service configuration')\r\n .option('--set-provider <name>', 'Set the default embed provider')\r\n .option('--set-model <model>', 'Set the default embed model')\r\n .option('--set-key <apiKey>', 'Set the API key for the current provider')\r\n .option('--set-base-url <url>', 'Set the base URL for the current provider')\r\n .action(async (opts: ConfigEmbedOptions) => {\r\n try {\r\n await executeConfigEmbed(opts);\r\n } catch (err) {\r\n handleError(err);\r\n }\r\n });\r\n}\r\n","import { readFile } from 'node:fs/promises';\r\nimport type { Command } from 'commander';\r\nimport { XdbConfigManager } from '../config-manager.js';\r\nimport { EmbeddingClient } from '../embedding-client.js';\r\nimport { parseBatchInput, formatEmbeddingOutput } from '../embed-io.js';\r\nimport { truncateText, EMBEDDING_MODEL_LIMITS } from '../embedding-models.js';\r\nimport { handleError, XDBError, PARAMETER_ERROR, RUNTIME_ERROR } from '../errors.js';\r\n\r\n/** Read all data from stdin */\r\nasync function readStdin(): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n let data = '';\r\n process.stdin.setEncoding('utf-8');\r\n process.stdin.on('data', (chunk) => { data += chunk; });\r\n process.stdin.on('end', () => { resolve(data); });\r\n process.stdin.on('error', (err) => {\r\n reject(new XDBError(RUNTIME_ERROR, `Failed to read from stdin: ${err.message}`));\r\n });\r\n });\r\n}\r\n\r\nexport interface EmbedOptions {\r\n batch?: boolean;\r\n json?: boolean;\r\n inputFile?: string;\r\n}\r\n\r\nexport type EmbeddingClientLike = {\r\n embed: (req: import('../embedding-client.js').EmbeddingRequest) => Promise<import('../embedding-client.js').EmbeddingResponse>;\r\n};\r\n\r\n/** Core embed logic, extracted for testability */\r\nexport async function executeEmbed(\r\n text: string | undefined,\r\n opts: EmbedOptions,\r\n manager: XdbConfigManager = new XdbConfigManager(),\r\n clientFactory?: (config: import('../embedding-client.js').EmbeddingClientConfig) => EmbeddingClientLike,\r\n): Promise<void> {\r\n const { provider, model, providerConfig, apiKey } = await manager.resolveEmbedConfig();\r\n\r\n // Resolve input source\r\n const hasExplicitInput = text !== undefined || opts.inputFile !== undefined;\r\n const stdinAvailable = !process.stdin.isTTY && !hasExplicitInput;\r\n\r\n const sourceCount = [\r\n text !== undefined,\r\n stdinAvailable,\r\n opts.inputFile !== undefined,\r\n ].filter(Boolean).length;\r\n\r\n if (sourceCount > 1) {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n 'Multiple input sources specified. Provide input via argument, stdin, or --input-file (only one).',\r\n );\r\n }\r\n\r\n let rawInput: string;\r\n if (text !== undefined) {\r\n rawInput = text;\r\n } else if (opts.inputFile) {\r\n try {\r\n rawInput = await readFile(opts.inputFile, 'utf-8');\r\n } catch (err) {\r\n throw new XDBError(\r\n RUNTIME_ERROR,\r\n `Failed to read input file: ${err instanceof Error ? err.message : String(err)}`,\r\n );\r\n }\r\n } else if (stdinAvailable) {\r\n rawInput = await readStdin();\r\n } else {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n 'No input text provided. Provide input via argument, stdin, or --input-file.',\r\n );\r\n }\r\n\r\n // Parse batch or single input\r\n let texts: string[];\r\n if (opts.batch) {\r\n texts = parseBatchInput(rawInput);\r\n } else {\r\n texts = [rawInput];\r\n }\r\n\r\n // Truncate texts that exceed model limits, warn to stderr\r\n texts = texts.map((t) => {\r\n const result = truncateText(t, model);\r\n if (result.truncated) {\r\n const truncatedTokens = Math.ceil(result.text.length / 4);\r\n const modelLimit = EMBEDDING_MODEL_LIMITS[model] ?? truncatedTokens;\r\n if (opts.json) {\r\n const warning = {\r\n type: 'warning',\r\n data: {\r\n message: `Input text truncated from ~${result.originalTokens} tokens to ${truncatedTokens} tokens (model limit: ${modelLimit})`,\r\n originalTokens: result.originalTokens,\r\n truncatedTokens,\r\n },\r\n };\r\n process.stderr.write(JSON.stringify(warning) + '\\n');\r\n } else {\r\n process.stderr.write(\r\n `[Warning] Input text truncated from ~${result.originalTokens} tokens to ${truncatedTokens} tokens (model limit: ${modelLimit})\\n`,\r\n );\r\n }\r\n }\r\n return result.text;\r\n });\r\n\r\n // Build client config\r\n const clientConfig: {\r\n provider: string;\r\n apiKey: string;\r\n model: string;\r\n baseUrl?: string;\r\n providerOptions?: Record<string, any>;\r\n api?: string;\r\n } = { provider, apiKey, model };\r\n\r\n if (providerConfig.baseUrl) {\r\n clientConfig.baseUrl = providerConfig.baseUrl;\r\n }\r\n if (providerConfig.api) {\r\n clientConfig.api = providerConfig.api;\r\n }\r\n\r\n const client = clientFactory ? clientFactory(clientConfig) : new EmbeddingClient(clientConfig);\r\n const response = await client.embed({ texts, model });\r\n\r\n // Format and write output\r\n const output = formatEmbeddingOutput(response, {\r\n json: opts.json ?? false,\r\n batch: opts.batch ?? false,\r\n });\r\n process.stdout.write(output + '\\n');\r\n}\r\n\r\nexport function registerEmbedCommand(program: Command): void {\r\n program\r\n .command('embed [text]')\r\n .description('Embed text using the configured embedding provider')\r\n .option('--batch', 'Parse input as a JSON string array for batch embedding')\r\n .option('--json', 'Output as JSON')\r\n .option('--input-file <path>', 'Read input from a file')\r\n .action(async (text: string | undefined, opts: { batch?: boolean; json?: boolean; inputFile?: string }) => {\r\n try {\r\n await executeEmbed(text, opts);\r\n } catch (err) {\r\n handleError(err);\r\n }\r\n });\r\n}\r\n","/**\r\n * Batch input parsing and embedding output formatting for the embed command.\r\n */\r\n\r\nimport { XDBError, PARAMETER_ERROR } from './errors.js';\r\nimport type { EmbeddingResponse } from './embedding-client.js';\r\n\r\n/**\r\n * Encode a float64 number[] vector as a hex string array of float32 values (big-endian).\r\n * Each float32 becomes one 8-char hex string, e.g. [0.5, -1.0] → [\"3f000000\", \"bf800000\"].\r\n * This is lossless at float32 precision and more compact than a JSON number array.\r\n */\r\nexport function vectorToHex(vec: number[]): string[] {\r\n const buf = new ArrayBuffer(4);\r\n const view = new DataView(buf);\r\n const result: string[] = new Array(vec.length);\r\n for (let i = 0; i < vec.length; i++) {\r\n view.setFloat32(0, vec[i]!, false); // big-endian\r\n let hex = '';\r\n for (let b = 0; b < 4; b++) {\r\n const byte = view.getUint8(b);\r\n hex += (byte < 16 ? '0' : '') + byte.toString(16);\r\n }\r\n result[i] = hex;\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * Parse a raw string as a JSON string array for batch embedding.\r\n * Throws XDBError (exitCode PARAMETER_ERROR) if the JSON is invalid or not an array of strings.\r\n * Returns an empty array if the input is an empty JSON array.\r\n */\r\nexport function parseBatchInput(raw: string): string[] {\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n 'Invalid batch input: not valid JSON',\r\n );\r\n }\r\n\r\n if (!Array.isArray(parsed)) {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n 'Invalid batch input: expected a JSON array of strings',\r\n );\r\n }\r\n\r\n for (let i = 0; i < parsed.length; i++) {\r\n if (typeof parsed[i] !== 'string') {\r\n throw new XDBError(\r\n PARAMETER_ERROR,\r\n `Invalid batch input: element at index ${i} is not a string`,\r\n );\r\n }\r\n }\r\n\r\n return parsed as string[];\r\n}\r\n\r\n/**\r\n * Format an EmbeddingResponse for stdout output.\r\n *\r\n * Vectors are encoded as hex string arrays (each float32 → one 8-char hex string).\r\n * This preserves float32 precision exactly and is more compact than a JSON number array.\r\n *\r\n * Plain text mode (json=false):\r\n * Single: one line with the hex array, e.g. [\"3f800000\",\"bf800000\"]\r\n * Batch: one hex array per line\r\n *\r\n * JSON mode (json=true):\r\n * Single: { \"embedding\": [\"<hex>\", ...], \"model\": \"...\", \"usage\": { ... } }\r\n * Batch: { \"embeddings\": [[\"<hex>\", ...], ...], \"model\": \"...\", \"usage\": { ... } }\r\n */\r\nexport function formatEmbeddingOutput(\r\n result: EmbeddingResponse,\r\n options: { json: boolean; batch: boolean },\r\n): string {\r\n if (!options.json) {\r\n // Plain text: each embedding as a hex string array on its own line\r\n return result.embeddings\r\n .map((emb) => JSON.stringify(vectorToHex(emb)))\r\n .join('\\n');\r\n }\r\n\r\n // JSON mode\r\n const usage = {\r\n prompt_tokens: result.usage.promptTokens,\r\n total_tokens: result.usage.totalTokens,\r\n };\r\n\r\n if (options.batch) {\r\n return JSON.stringify({\r\n embeddings: result.embeddings.map((emb) => vectorToHex(emb)),\r\n model: result.model,\r\n usage,\r\n });\r\n }\r\n\r\n // Single mode – use \"embedding\" (singular) with the first vector\r\n return JSON.stringify({\r\n embedding: vectorToHex(result.embeddings[0]!),\r\n model: result.model,\r\n usage,\r\n });\r\n}\r\n","/**\r\n * Embedding model token limits and text truncation utilities.\r\n */\r\n\r\n/**\r\n * Built-in maximum token limits for common embedding models.\r\n */\r\nexport const EMBEDDING_MODEL_LIMITS: Record<string, number> = {\r\n // OpenAI\r\n 'text-embedding-3-small': 8191,\r\n 'text-embedding-3-large': 8191,\r\n 'text-embedding-ada-002': 8191,\r\n // Google\r\n 'text-embedding-004': 2048,\r\n // Cohere\r\n 'embed-english-v3.0': 512,\r\n 'embed-multilingual-v3.0': 512,\r\n 'embed-english-light-v3.0': 512,\r\n 'embed-multilingual-light-v3.0': 512,\r\n};\r\n\r\n/** Characters per token estimate */\r\nconst CHARS_PER_TOKEN = 4;\r\n\r\nexport interface TruncateResult {\r\n text: string;\r\n truncated: boolean;\r\n originalTokens: number;\r\n}\r\n\r\n/**\r\n * Estimate token count using simple character-level approximation (1 token ≈ 4 characters).\r\n */\r\nexport function estimateTokens(text: string): number {\r\n return Math.ceil(text.length / CHARS_PER_TOKEN);\r\n}\r\n\r\n/**\r\n * Truncate text to fit within a model's token limit.\r\n *\r\n * - If the model is not in EMBEDDING_MODEL_LIMITS, returns the original text unchanged.\r\n * - Uses simple character-level estimation (1 token ≈ 4 characters).\r\n */\r\nexport function truncateText(text: string, model: string): TruncateResult {\r\n const limit = EMBEDDING_MODEL_LIMITS[model];\r\n const originalTokens = estimateTokens(text);\r\n\r\n // Unknown model — skip truncation\r\n if (limit === undefined) {\r\n return { text, truncated: false, originalTokens };\r\n }\r\n\r\n // Within limit — no truncation needed\r\n if (originalTokens <= limit) {\r\n return { text, truncated: false, originalTokens };\r\n }\r\n\r\n // Truncate: limit * CHARS_PER_TOKEN characters\r\n const maxChars = limit * CHARS_PER_TOKEN;\r\n return {\r\n text: text.slice(0, maxChars),\r\n truncated: true,\r\n originalTokens,\r\n };\r\n}\r\n","import type { Command } from 'commander';\r\n\r\n// ── Help text data ──────────────────────────────────────────\r\n\r\nconst MAIN_EXAMPLES = `\r\nExamples:\r\n $ xdb col init my-docs --policy hybrid/knowledge-base\r\n $ xdb put my-docs '{\"content\":\"How to use tar\"}'\r\n $ xdb find my-docs \"compress files\" --similar\r\n $ xdb col list\r\n $ xdb col info my-docs\r\n $ xdb policy list\r\n\r\nPrerequisites:\r\n 向量化功能依赖 pai 命令。请确保 pai 已安装并配置了 embedding provider:\r\n pai model default --embed-provider openai --embed-model text-embedding-3-small\r\n\r\nData:\r\n 数据目录: ~/.local/share/xdb/`;\r\n\r\nconst MAIN_VERBOSE = `\r\nPolicies:\r\n hybrid/knowledge-base 向量 + 全文检索(最常用)\r\n relational/structured-logs 结构化日志\r\n relational/simple-kv 简单键值对\r\n vector/feature-store 特征存储\r\n\r\nStorage:\r\n ~/.local/share/xdb/collections/<name>/\r\n collection_meta.json Policy 快照 + 元数据\r\n vector.lance/ LanceDB 向量数据\r\n relational.db SQLite 关系数据 + FTS\r\n\r\nExit Codes:\r\n 0 成功\r\n 2 参数错误 / 集合不存在 / 能力不匹配\r\n 1 运行时错误(引擎故障、pai 调用失败等)`;\r\n\r\nconst COL_INIT_EXAMPLES = `\r\nExamples:\r\n $ xdb col init my-docs --policy hybrid/knowledge-base\r\n $ xdb col init logs --policy relational\r\n $ xdb col init my-col --policy hybrid --params '{\"fields\":{\"title\":{\"findCaps\":[\"match\"]}}}'`;\r\n\r\nconst COL_LIST_EXAMPLES = `\r\nExamples:\r\n $ xdb col list\r\n $ xdb col list --json # JSON array 输出`;\r\n\r\nconst COL_RM_EXAMPLES = `\r\nExamples:\r\n $ xdb col rm my-docs\r\n\r\nWarning: 此操作不可逆,将物理删除集合目录及所有索引文件。`;\r\n\r\nconst COL_INFO_EXAMPLES = `\r\nExamples:\r\n $ xdb col info my-docs # 人类可读\r\n $ xdb col info my-docs --json # JSON 输出`;\r\n\r\nconst POLICY_LIST_EXAMPLES = `\r\nExamples:\r\n $ xdb policy list # 人类可读\r\n $ xdb policy list --json # JSON 输出`;\r\n\r\nconst PUT_EXAMPLES = `\r\nExamples:\r\n $ xdb put my-docs '{\"content\":\"How to use tar\"}' # 位置参数\r\n $ echo '{\"content\":\"Git branching\"}' | xdb put my-docs # stdin 输入\r\n $ cat data.jsonl | xdb put my-docs --batch # 批量写入\r\n\r\nStdin:\r\n 支持通过管道传入 JSON 或 JSONL 数据。\r\n\r\nNote:\r\n 相同 id 的记录执行 upsert(幂等操作)。\r\n --batch --json 输出: {\"inserted\":N,\"updated\":N,\"errors\":N}`;\r\n\r\nconst FIND_EXAMPLES = `\r\nExamples:\r\n $ xdb find my-docs \"compress files\" --similar # 语义搜索\r\n $ xdb find my-docs \"tar compression\" --match # 全文检索\r\n $ xdb find my-docs --where \"json_extract(data, '$.category') = 'network'\"\r\n $ echo \"database optimization\" | xdb find my-docs --similar # stdin 查询\r\n\r\nStdin:\r\n 支持通过管道传入查询文本(用于 --similar 和 --match)。\r\n\r\nJSON output (--json):\r\n JSONL 格式,每行一个结果,含 _score 和 _engine 元数据。`;\r\n\r\n// ── Setup functions ─────────────────────────────────────────\r\n\r\nexport function installHelp(program: Command): void {\r\n program.addHelpText('after', MAIN_EXAMPLES);\r\n installVerboseHelp(program);\r\n}\r\n\r\nexport function addColExamples(col: Command): void {\r\n // Add examples to col subcommands after they are registered\r\n for (const sub of col.commands) {\r\n const name = sub.name();\r\n if (name === 'init') sub.addHelpText('after', COL_INIT_EXAMPLES);\r\n else if (name === 'list') sub.addHelpText('after', COL_LIST_EXAMPLES);\r\n else if (name === 'rm') sub.addHelpText('after', COL_RM_EXAMPLES);\r\n else if (name === 'info') sub.addHelpText('after', COL_INFO_EXAMPLES);\r\n }\r\n}\r\n\r\nexport function addPolicyExamples(policy: Command): void {\r\n for (const sub of policy.commands) {\r\n const name = sub.name();\r\n if (name === 'list') sub.addHelpText('after', POLICY_LIST_EXAMPLES);\r\n }\r\n}\r\n\r\nexport function addPutExamples(cmd: Command): void {\r\n cmd.addHelpText('after', PUT_EXAMPLES);\r\n}\r\n\r\nexport function addFindExamples(cmd: Command): void {\r\n cmd.addHelpText('after', FIND_EXAMPLES);\r\n}\r\n\r\nfunction installVerboseHelp(program: Command): void {\r\n program.option('--verbose', '(与 --help 一起使用) 显示完整帮助信息');\r\n program.on('option:verbose', () => {\r\n (program as unknown as Record<string, boolean>).__verboseHelp = true;\r\n });\r\n program.addHelpText('afterAll', () => {\r\n if ((program as unknown as Record<string, boolean>).__verboseHelp) {\r\n return MAIN_VERBOSE;\r\n }\r\n return '';\r\n });\r\n}\r\n"],"mappings":"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","names":["join","dirname","join","policy","Database","lancedb","config","join","col","config","policy","homedir","join","config","config","policy","needsSqlite","join","join","join","join","policy","getDataRoot","join","homedir","policy","program","homedir","join","policy","getDataRoot","join","homedir","readStdin","needsLance","policy","needsSqlite","program","ENGINE_DESC","provider","providerConfig","config","readFile","readStdin","readFile","program","program","col","policy","dirname","join"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@theclawlab/xdb",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Intent-driven data hub CLI for AI agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"xdb": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsup",
|
|
11
|
+
"test": "vitest",
|
|
12
|
+
"test:watch": "vitest",
|
|
13
|
+
"release:local": "npm run build && npm link",
|
|
14
|
+
"release:public": "npm test && npm run build && npm publish --access public",
|
|
15
|
+
"release:public:skip-test": "npm run build && npm publish --access public"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public",
|
|
20
|
+
"registry": "https://registry.npmjs.org"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md",
|
|
25
|
+
"USAGE.md"
|
|
26
|
+
],
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@lancedb/lancedb": "^0.15.0",
|
|
29
|
+
"better-sqlite3": "^11.8.1",
|
|
30
|
+
"commander": "^13.1.0",
|
|
31
|
+
"uuid": "^11.1.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
35
|
+
"@types/uuid": "^10.0.0",
|
|
36
|
+
"fast-check": "^4.1.1",
|
|
37
|
+
"tsup": "^8.5.0",
|
|
38
|
+
"typescript": "^5.8.3",
|
|
39
|
+
"vitest": "^3.2.1"
|
|
40
|
+
}
|
|
41
|
+
}
|