@de-otio/chaoskb-client 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/agent-registry/config-merger.d.ts +28 -0
- package/dist/cli/agent-registry/config-merger.d.ts.map +1 -0
- package/dist/cli/agent-registry/config-merger.js +90 -0
- package/dist/cli/agent-registry/config-merger.js.map +1 -0
- package/dist/cli/agent-registry/detector.d.ts +7 -0
- package/dist/cli/agent-registry/detector.d.ts.map +1 -0
- package/dist/cli/agent-registry/detector.js +100 -0
- package/dist/cli/agent-registry/detector.js.map +1 -0
- package/dist/cli/agent-registry/index.d.ts +26 -0
- package/dist/cli/agent-registry/index.d.ts.map +1 -0
- package/dist/cli/agent-registry/index.js +77 -0
- package/dist/cli/agent-registry/index.js.map +1 -0
- package/dist/cli/agent-registry/path-validator.d.ts +11 -0
- package/dist/cli/agent-registry/path-validator.d.ts.map +1 -0
- package/dist/cli/agent-registry/path-validator.js +69 -0
- package/dist/cli/agent-registry/path-validator.js.map +1 -0
- package/dist/cli/agent-registry/registry.json +108 -0
- package/dist/cli/agent-registry/types.d.ts +29 -0
- package/dist/cli/agent-registry/types.d.ts.map +1 -0
- package/dist/cli/agent-registry/types.js +2 -0
- package/dist/cli/agent-registry/types.js.map +1 -0
- package/dist/cli/bootstrap-lock.d.ts +7 -0
- package/dist/cli/bootstrap-lock.d.ts.map +1 -0
- package/dist/cli/bootstrap-lock.js +62 -0
- package/dist/cli/bootstrap-lock.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +23 -0
- package/dist/cli/bootstrap.d.ts.map +1 -0
- package/dist/cli/bootstrap.js +438 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/commands/config.d.ts +13 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +244 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/devices.d.ts +21 -0
- package/dist/cli/commands/devices.d.ts.map +1 -0
- package/dist/cli/commands/devices.js +229 -0
- package/dist/cli/commands/devices.js.map +1 -0
- package/dist/cli/commands/export.d.ts +12 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +183 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/import.d.ts +26 -0
- package/dist/cli/commands/import.d.ts.map +1 -0
- package/dist/cli/commands/import.js +311 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/kb.d.ts +39 -0
- package/dist/cli/commands/kb.d.ts.map +1 -0
- package/dist/cli/commands/kb.js +138 -0
- package/dist/cli/commands/kb.js.map +1 -0
- package/dist/cli/commands/project.d.ts +6 -0
- package/dist/cli/commands/project.d.ts.map +1 -0
- package/dist/cli/commands/project.js +115 -0
- package/dist/cli/commands/project.js.map +1 -0
- package/dist/cli/commands/projects.d.ts +33 -0
- package/dist/cli/commands/projects.d.ts.map +1 -0
- package/dist/cli/commands/projects.js +189 -0
- package/dist/cli/commands/projects.js.map +1 -0
- package/dist/cli/commands/register.d.ts +8 -0
- package/dist/cli/commands/register.d.ts.map +1 -0
- package/dist/cli/commands/register.js +146 -0
- package/dist/cli/commands/register.js.map +1 -0
- package/dist/cli/commands/rotate-key.d.ts +16 -0
- package/dist/cli/commands/rotate-key.d.ts.map +1 -0
- package/dist/cli/commands/rotate-key.js +197 -0
- package/dist/cli/commands/rotate-key.js.map +1 -0
- package/dist/cli/commands/setup-sync.d.ts +2 -0
- package/dist/cli/commands/setup-sync.d.ts.map +1 -0
- package/dist/cli/commands/setup-sync.js +165 -0
- package/dist/cli/commands/setup-sync.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +12 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +39 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/status.d.ts +5 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +96 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +4 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -0
- package/dist/cli/commands/uninstall.js +85 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/commands/unregister.d.ts +2 -0
- package/dist/cli/commands/unregister.d.ts.map +1 -0
- package/dist/cli/commands/unregister.js +46 -0
- package/dist/cli/commands/unregister.js.map +1 -0
- package/dist/cli/device-metadata.d.ts +15 -0
- package/dist/cli/device-metadata.d.ts.map +1 -0
- package/dist/cli/device-metadata.js +58 -0
- package/dist/cli/device-metadata.js.map +1 -0
- package/dist/cli/github.d.ts +38 -0
- package/dist/cli/github.d.ts.map +1 -0
- package/dist/cli/github.js +159 -0
- package/dist/cli/github.js.map +1 -0
- package/dist/cli/guide-hashes.json +13 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +226 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/mcp-server.d.ts +205 -0
- package/dist/cli/mcp-server.d.ts.map +1 -0
- package/dist/cli/mcp-server.js +366 -0
- package/dist/cli/mcp-server.js.map +1 -0
- package/dist/cli/tools/kb-delete.d.ts +10 -0
- package/dist/cli/tools/kb-delete.d.ts.map +1 -0
- package/dist/cli/tools/kb-delete.js +28 -0
- package/dist/cli/tools/kb-delete.js.map +1 -0
- package/dist/cli/tools/kb-ingest.d.ts +13 -0
- package/dist/cli/tools/kb-ingest.d.ts.map +1 -0
- package/dist/cli/tools/kb-ingest.js +72 -0
- package/dist/cli/tools/kb-ingest.js.map +1 -0
- package/dist/cli/tools/kb-list.d.ts +20 -0
- package/dist/cli/tools/kb-list.d.ts.map +1 -0
- package/dist/cli/tools/kb-list.js +24 -0
- package/dist/cli/tools/kb-list.js.map +1 -0
- package/dist/cli/tools/kb-query-shared.d.ts +27 -0
- package/dist/cli/tools/kb-query-shared.d.ts.map +1 -0
- package/dist/cli/tools/kb-query-shared.js +28 -0
- package/dist/cli/tools/kb-query-shared.js.map +1 -0
- package/dist/cli/tools/kb-query.d.ts +20 -0
- package/dist/cli/tools/kb-query.d.ts.map +1 -0
- package/dist/cli/tools/kb-query.js +109 -0
- package/dist/cli/tools/kb-query.js.map +1 -0
- package/dist/cli/tools/kb-summary.d.ts +29 -0
- package/dist/cli/tools/kb-summary.d.ts.map +1 -0
- package/dist/cli/tools/kb-summary.js +89 -0
- package/dist/cli/tools/kb-summary.js.map +1 -0
- package/dist/cli/tools/kb-sync-status.d.ts +7 -0
- package/dist/cli/tools/kb-sync-status.d.ts.map +1 -0
- package/dist/cli/tools/kb-sync-status.js +48 -0
- package/dist/cli/tools/kb-sync-status.js.map +1 -0
- package/dist/crypto/aad.d.ts +8 -0
- package/dist/crypto/aad.d.ts.map +1 -0
- package/dist/crypto/aad.js +11 -0
- package/dist/crypto/aad.js.map +1 -0
- package/dist/crypto/aead.d.ts +21 -0
- package/dist/crypto/aead.d.ts.map +1 -0
- package/dist/crypto/aead.js +43 -0
- package/dist/crypto/aead.js.map +1 -0
- package/dist/crypto/argon2.d.ts +11 -0
- package/dist/crypto/argon2.d.ts.map +1 -0
- package/dist/crypto/argon2.js +33 -0
- package/dist/crypto/argon2.js.map +1 -0
- package/dist/crypto/blob-id.d.ts +6 -0
- package/dist/crypto/blob-id.d.ts.map +1 -0
- package/dist/crypto/blob-id.js +33 -0
- package/dist/crypto/blob-id.js.map +1 -0
- package/dist/crypto/canonical-json.d.ts +6 -0
- package/dist/crypto/canonical-json.d.ts.map +1 -0
- package/dist/crypto/canonical-json.js +88 -0
- package/dist/crypto/canonical-json.js.map +1 -0
- package/dist/crypto/commitment.d.ts +12 -0
- package/dist/crypto/commitment.d.ts.map +1 -0
- package/dist/crypto/commitment.js +37 -0
- package/dist/crypto/commitment.js.map +1 -0
- package/dist/crypto/encryption-service.d.ts +19 -0
- package/dist/crypto/encryption-service.d.ts.map +1 -0
- package/dist/crypto/encryption-service.js +38 -0
- package/dist/crypto/encryption-service.js.map +1 -0
- package/dist/crypto/envelope-cbor.d.ts +37 -0
- package/dist/crypto/envelope-cbor.d.ts.map +1 -0
- package/dist/crypto/envelope-cbor.js +124 -0
- package/dist/crypto/envelope-cbor.js.map +1 -0
- package/dist/crypto/envelope.d.ts +34 -0
- package/dist/crypto/envelope.d.ts.map +1 -0
- package/dist/crypto/envelope.js +160 -0
- package/dist/crypto/envelope.js.map +1 -0
- package/dist/crypto/hkdf.d.ts +16 -0
- package/dist/crypto/hkdf.d.ts.map +1 -0
- package/dist/crypto/hkdf.js +33 -0
- package/dist/crypto/hkdf.js.map +1 -0
- package/dist/crypto/index.d.ts +15 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +15 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/crypto/invite.d.ts +31 -0
- package/dist/crypto/invite.d.ts.map +1 -0
- package/dist/crypto/invite.js +137 -0
- package/dist/crypto/invite.js.map +1 -0
- package/dist/crypto/keyring.d.ts +37 -0
- package/dist/crypto/keyring.d.ts.map +1 -0
- package/dist/crypto/keyring.js +219 -0
- package/dist/crypto/keyring.js.map +1 -0
- package/dist/crypto/known-keys.d.ts +34 -0
- package/dist/crypto/known-keys.d.ts.map +1 -0
- package/dist/crypto/known-keys.js +106 -0
- package/dist/crypto/known-keys.js.map +1 -0
- package/dist/crypto/project-keys.d.ts +26 -0
- package/dist/crypto/project-keys.d.ts.map +1 -0
- package/dist/crypto/project-keys.js +69 -0
- package/dist/crypto/project-keys.js.map +1 -0
- package/dist/crypto/secure-buffer.d.ts +31 -0
- package/dist/crypto/secure-buffer.d.ts.map +1 -0
- package/dist/crypto/secure-buffer.js +61 -0
- package/dist/crypto/secure-buffer.js.map +1 -0
- package/dist/crypto/ssh-agent.d.ts +16 -0
- package/dist/crypto/ssh-agent.d.ts.map +1 -0
- package/dist/crypto/ssh-agent.js +225 -0
- package/dist/crypto/ssh-agent.js.map +1 -0
- package/dist/crypto/ssh-keys.d.ts +19 -0
- package/dist/crypto/ssh-keys.d.ts.map +1 -0
- package/dist/crypto/ssh-keys.js +121 -0
- package/dist/crypto/ssh-keys.js.map +1 -0
- package/dist/crypto/tiers/enhanced.d.ts +25 -0
- package/dist/crypto/tiers/enhanced.d.ts.map +1 -0
- package/dist/crypto/tiers/enhanced.js +56 -0
- package/dist/crypto/tiers/enhanced.js.map +1 -0
- package/dist/crypto/tiers/maximum.d.ts +19 -0
- package/dist/crypto/tiers/maximum.d.ts.map +1 -0
- package/dist/crypto/tiers/maximum.js +25 -0
- package/dist/crypto/tiers/maximum.js.map +1 -0
- package/dist/crypto/tiers/standard.d.ts +27 -0
- package/dist/crypto/tiers/standard.d.ts.map +1 -0
- package/dist/crypto/tiers/standard.js +147 -0
- package/dist/crypto/tiers/standard.js.map +1 -0
- package/dist/crypto/types.d.ts +169 -0
- package/dist/crypto/types.d.ts.map +1 -0
- package/dist/crypto/types.js +11 -0
- package/dist/crypto/types.js.map +1 -0
- package/dist/pipeline/chunker.d.ts +27 -0
- package/dist/pipeline/chunker.d.ts.map +1 -0
- package/dist/pipeline/chunker.js +96 -0
- package/dist/pipeline/chunker.js.map +1 -0
- package/dist/pipeline/content-pipeline.d.ts +24 -0
- package/dist/pipeline/content-pipeline.d.ts.map +1 -0
- package/dist/pipeline/content-pipeline.js +49 -0
- package/dist/pipeline/content-pipeline.js.map +1 -0
- package/dist/pipeline/embedder.d.ts +49 -0
- package/dist/pipeline/embedder.d.ts.map +1 -0
- package/dist/pipeline/embedder.js +195 -0
- package/dist/pipeline/embedder.js.map +1 -0
- package/dist/pipeline/extract.d.ts +17 -0
- package/dist/pipeline/extract.d.ts.map +1 -0
- package/dist/pipeline/extract.js +70 -0
- package/dist/pipeline/extract.js.map +1 -0
- package/dist/pipeline/fetch.d.ts +26 -0
- package/dist/pipeline/fetch.d.ts.map +1 -0
- package/dist/pipeline/fetch.js +91 -0
- package/dist/pipeline/fetch.js.map +1 -0
- package/dist/pipeline/index.d.ts +10 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +10 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/model-manager.d.ts +57 -0
- package/dist/pipeline/model-manager.d.ts.map +1 -0
- package/dist/pipeline/model-manager.js +234 -0
- package/dist/pipeline/model-manager.js.map +1 -0
- package/dist/pipeline/search.d.ts +37 -0
- package/dist/pipeline/search.d.ts.map +1 -0
- package/dist/pipeline/search.js +65 -0
- package/dist/pipeline/search.js.map +1 -0
- package/dist/pipeline/tokenizer.d.ts +29 -0
- package/dist/pipeline/tokenizer.d.ts.map +1 -0
- package/dist/pipeline/tokenizer.js +54 -0
- package/dist/pipeline/tokenizer.js.map +1 -0
- package/dist/pipeline/types.d.ts +86 -0
- package/dist/pipeline/types.d.ts.map +1 -0
- package/dist/pipeline/types.js +2 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/pipeline/wordpiece-tokenizer.d.ts +60 -0
- package/dist/pipeline/wordpiece-tokenizer.d.ts.map +1 -0
- package/dist/pipeline/wordpiece-tokenizer.js +251 -0
- package/dist/pipeline/wordpiece-tokenizer.js.map +1 -0
- package/dist/storage/chunk-repo.d.ts +29 -0
- package/dist/storage/chunk-repo.d.ts.map +1 -0
- package/dist/storage/chunk-repo.js +115 -0
- package/dist/storage/chunk-repo.js.map +1 -0
- package/dist/storage/database-manager.d.ts +17 -0
- package/dist/storage/database-manager.d.ts.map +1 -0
- package/dist/storage/database-manager.js +100 -0
- package/dist/storage/database-manager.js.map +1 -0
- package/dist/storage/database.d.ts +10 -0
- package/dist/storage/database.d.ts.map +1 -0
- package/dist/storage/database.js +34 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/embedding-index.d.ts +22 -0
- package/dist/storage/embedding-index.d.ts.map +1 -0
- package/dist/storage/embedding-index.js +78 -0
- package/dist/storage/embedding-index.js.map +1 -0
- package/dist/storage/index.d.ts +10 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +10 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/kb-database.d.ts +11 -0
- package/dist/storage/kb-database.d.ts.map +1 -0
- package/dist/storage/kb-database.js +24 -0
- package/dist/storage/kb-database.js.map +1 -0
- package/dist/storage/schema.d.ts +6 -0
- package/dist/storage/schema.d.ts.map +1 -0
- package/dist/storage/schema.js +122 -0
- package/dist/storage/schema.js.map +1 -0
- package/dist/storage/source-repo.d.ts +20 -0
- package/dist/storage/source-repo.d.ts.map +1 -0
- package/dist/storage/source-repo.js +120 -0
- package/dist/storage/source-repo.js.map +1 -0
- package/dist/storage/sync-status-repo.d.ts +15 -0
- package/dist/storage/sync-status-repo.d.ts.map +1 -0
- package/dist/storage/sync-status-repo.js +40 -0
- package/dist/storage/sync-status-repo.js.map +1 -0
- package/dist/storage/types.d.ts +139 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +9 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/sync/canary.d.ts +14 -0
- package/dist/sync/canary.d.ts.map +1 -0
- package/dist/sync/canary.js +53 -0
- package/dist/sync/canary.js.map +1 -0
- package/dist/sync/full-sync.d.ts +16 -0
- package/dist/sync/full-sync.d.ts.map +1 -0
- package/dist/sync/full-sync.js +91 -0
- package/dist/sync/full-sync.js.map +1 -0
- package/dist/sync/http-client.d.ts +28 -0
- package/dist/sync/http-client.d.ts.map +1 -0
- package/dist/sync/http-client.js +90 -0
- package/dist/sync/http-client.js.map +1 -0
- package/dist/sync/incremental-sync.d.ts +17 -0
- package/dist/sync/incremental-sync.d.ts.map +1 -0
- package/dist/sync/incremental-sync.js +155 -0
- package/dist/sync/incremental-sync.js.map +1 -0
- package/dist/sync/index.d.ts +12 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +12 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/quota.d.ts +17 -0
- package/dist/sync/quota.d.ts.map +1 -0
- package/dist/sync/quota.js +48 -0
- package/dist/sync/quota.js.map +1 -0
- package/dist/sync/sequence.d.ts +21 -0
- package/dist/sync/sequence.d.ts.map +1 -0
- package/dist/sync/sequence.js +49 -0
- package/dist/sync/sequence.js.map +1 -0
- package/dist/sync/ssh-signer.d.ts +59 -0
- package/dist/sync/ssh-signer.d.ts.map +1 -0
- package/dist/sync/ssh-signer.js +241 -0
- package/dist/sync/ssh-signer.js.map +1 -0
- package/dist/sync/sync-service.d.ts +48 -0
- package/dist/sync/sync-service.d.ts.map +1 -0
- package/dist/sync/sync-service.js +116 -0
- package/dist/sync/sync-service.js.map +1 -0
- package/dist/sync/types.d.ts +106 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +2 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/sync/upload-queue.d.ts +40 -0
- package/dist/sync/upload-queue.d.ts.map +1 -0
- package/dist/sync/upload-queue.js +148 -0
- package/dist/sync/upload-queue.js.map +1 -0
- package/dist/sync/verification.d.ts +17 -0
- package/dist/sync/verification.d.ts.map +1 -0
- package/dist/sync/verification.js +25 -0
- package/dist/sync/verification.js.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +16 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import { KBDatabase } from './kb-database.js';
|
|
5
|
+
const PROJECT_NAME_RE = /^[a-zA-Z0-9_-]+$/;
|
|
6
|
+
export class DatabaseManager {
|
|
7
|
+
baseDir;
|
|
8
|
+
databases = new Map();
|
|
9
|
+
constructor(baseDir) {
|
|
10
|
+
this.baseDir = baseDir ?? path.join(os.homedir(), '.chaoskb');
|
|
11
|
+
if (!fs.existsSync(this.baseDir)) {
|
|
12
|
+
fs.mkdirSync(this.baseDir, { recursive: true, mode: 0o700 });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
getPersonalDb() {
|
|
16
|
+
const key = '__personal__';
|
|
17
|
+
let db = this.databases.get(key);
|
|
18
|
+
if (db)
|
|
19
|
+
return db;
|
|
20
|
+
const dbPath = path.join(this.baseDir, 'local.db');
|
|
21
|
+
db = new KBDatabase({ path: dbPath });
|
|
22
|
+
this.databases.set(key, db);
|
|
23
|
+
return db;
|
|
24
|
+
}
|
|
25
|
+
getProjectDb(projectName) {
|
|
26
|
+
if (!PROJECT_NAME_RE.test(projectName)) {
|
|
27
|
+
throw new Error(`Invalid project name "${projectName}": only alphanumeric characters, hyphens, and underscores are allowed`);
|
|
28
|
+
}
|
|
29
|
+
const key = `project:${projectName}`;
|
|
30
|
+
let db = this.databases.get(key);
|
|
31
|
+
if (db)
|
|
32
|
+
return db;
|
|
33
|
+
const projectDir = path.join(this.baseDir, 'projects', projectName);
|
|
34
|
+
if (!fs.existsSync(projectDir)) {
|
|
35
|
+
fs.mkdirSync(projectDir, { recursive: true, mode: 0o700 });
|
|
36
|
+
}
|
|
37
|
+
const dbPath = path.join(projectDir, 'local.db');
|
|
38
|
+
db = new KBDatabase({ path: dbPath, projectName });
|
|
39
|
+
this.databases.set(key, db);
|
|
40
|
+
return db;
|
|
41
|
+
}
|
|
42
|
+
listProjects() {
|
|
43
|
+
const projectsDir = path.join(this.baseDir, 'projects');
|
|
44
|
+
if (!fs.existsSync(projectsDir)) {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
const entries = fs.readdirSync(projectsDir, { withFileTypes: true });
|
|
48
|
+
const results = [];
|
|
49
|
+
for (const entry of entries) {
|
|
50
|
+
if (!entry.isDirectory())
|
|
51
|
+
continue;
|
|
52
|
+
const projectDir = path.join(projectsDir, entry.name);
|
|
53
|
+
const dbPath = path.join(projectDir, 'local.db');
|
|
54
|
+
if (!fs.existsSync(dbPath))
|
|
55
|
+
continue;
|
|
56
|
+
const stats = fs.statSync(dbPath);
|
|
57
|
+
let sourceCount = 0;
|
|
58
|
+
// Open the DB temporarily to get the source count
|
|
59
|
+
try {
|
|
60
|
+
const db = this.getProjectDb(entry.name);
|
|
61
|
+
sourceCount = db.sources.count();
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// If we can't open the DB, just report 0 sources
|
|
65
|
+
}
|
|
66
|
+
results.push({
|
|
67
|
+
name: entry.name,
|
|
68
|
+
path: projectDir,
|
|
69
|
+
sizeBytes: stats.size,
|
|
70
|
+
sourceCount,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return results;
|
|
74
|
+
}
|
|
75
|
+
deleteProject(projectName) {
|
|
76
|
+
if (!PROJECT_NAME_RE.test(projectName)) {
|
|
77
|
+
throw new Error(`Invalid project name "${projectName}": only alphanumeric characters, hyphens, and underscores are allowed`);
|
|
78
|
+
}
|
|
79
|
+
const projectDir = path.join(this.baseDir, 'projects', projectName);
|
|
80
|
+
if (!fs.existsSync(projectDir)) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
// Close the DB if it's open
|
|
84
|
+
const key = `project:${projectName}`;
|
|
85
|
+
const db = this.databases.get(key);
|
|
86
|
+
if (db) {
|
|
87
|
+
db.close();
|
|
88
|
+
this.databases.delete(key);
|
|
89
|
+
}
|
|
90
|
+
fs.rmSync(projectDir, { recursive: true, force: true });
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
closeAll() {
|
|
94
|
+
for (const db of this.databases.values()) {
|
|
95
|
+
db.close();
|
|
96
|
+
}
|
|
97
|
+
this.databases.clear();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=database-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-manager.js","sourceRoot":"","sources":["../../storage/database-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import BetterSqlite3 from 'better-sqlite3';
|
|
2
|
+
import type { DatabaseConfig } from './types.js';
|
|
3
|
+
export declare class Database {
|
|
4
|
+
private readonly _db;
|
|
5
|
+
constructor(config: DatabaseConfig);
|
|
6
|
+
get db(): BetterSqlite3.Database;
|
|
7
|
+
close(): void;
|
|
8
|
+
transaction<T>(fn: () => T): T;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../storage/database.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAG3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAyB;gBAEjC,MAAM,EAAE,cAAc;IAuBlC,IAAI,EAAE,IAAI,aAAa,CAAC,QAAQ,CAE/B;IAED,KAAK,IAAI,IAAI;IAIb,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;CAG/B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import BetterSqlite3 from 'better-sqlite3';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { initializeSchema } from './schema.js';
|
|
5
|
+
export class Database {
|
|
6
|
+
_db;
|
|
7
|
+
constructor(config) {
|
|
8
|
+
const dbDir = path.dirname(config.path);
|
|
9
|
+
if (!fs.existsSync(dbDir)) {
|
|
10
|
+
fs.mkdirSync(dbDir, { recursive: true, mode: 0o700 });
|
|
11
|
+
}
|
|
12
|
+
const isNew = !fs.existsSync(config.path);
|
|
13
|
+
this._db = new BetterSqlite3(config.path);
|
|
14
|
+
if (isNew) {
|
|
15
|
+
fs.chmodSync(config.path, 0o600);
|
|
16
|
+
}
|
|
17
|
+
// Configure database pragmas
|
|
18
|
+
this._db.pragma('journal_mode = WAL');
|
|
19
|
+
this._db.pragma('foreign_keys = ON');
|
|
20
|
+
this._db.pragma('busy_timeout = 5000');
|
|
21
|
+
// Initialize schema
|
|
22
|
+
initializeSchema(this._db);
|
|
23
|
+
}
|
|
24
|
+
get db() {
|
|
25
|
+
return this._db;
|
|
26
|
+
}
|
|
27
|
+
close() {
|
|
28
|
+
this._db.close();
|
|
29
|
+
}
|
|
30
|
+
transaction(fn) {
|
|
31
|
+
return this._db.transaction(fn)();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../storage/database.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,OAAO,QAAQ;IACF,GAAG,CAAyB;IAE7C,YAAY,MAAsB;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAE1C,IAAI,CAAC,GAAG,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAE1C,IAAI,KAAK,EAAE,CAAC;YACV,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;QAED,6BAA6B;QAC7B,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACtC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACrC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;QAEvC,oBAAoB;QACpB,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,WAAW,CAAI,EAAW;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,CAAC;IACpC,CAAC;CACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type BetterSqlite3 from 'better-sqlite3';
|
|
2
|
+
import type { IEmbeddingIndex } from './types.js';
|
|
3
|
+
export declare class EmbeddingIndex implements IEmbeddingIndex {
|
|
4
|
+
private readonly db;
|
|
5
|
+
/** sourceId -> chunkIndex -> embedding */
|
|
6
|
+
private readonly embeddings;
|
|
7
|
+
private _size;
|
|
8
|
+
constructor(db: BetterSqlite3.Database);
|
|
9
|
+
load(): void;
|
|
10
|
+
add(sourceId: string, chunks: {
|
|
11
|
+
chunkIndex: number;
|
|
12
|
+
embedding: Float32Array;
|
|
13
|
+
}[]): void;
|
|
14
|
+
remove(sourceId: string): void;
|
|
15
|
+
search(query: Float32Array, topK: number): {
|
|
16
|
+
sourceId: string;
|
|
17
|
+
chunkIndex: number;
|
|
18
|
+
score: number;
|
|
19
|
+
}[];
|
|
20
|
+
get size(): number;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=embedding-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-index.d.ts","sourceRoot":"","sources":["../../storage/embedding-index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAsBlD,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyB;IAC5C,0CAA0C;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqD;IAChF,OAAO,CAAC,KAAK,CAAK;gBAEN,EAAE,EAAE,aAAa,CAAC,QAAQ;IAItC,IAAI,IAAI,IAAI;IAyBZ,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,YAAY,CAAA;KAAE,EAAE,GAAG,IAAI;IAetF,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQ9B,MAAM,CACJ,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,GACX;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE;IAe5D,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
function cosineSimilarity(a, b) {
|
|
2
|
+
let dot = 0;
|
|
3
|
+
let magA = 0;
|
|
4
|
+
let magB = 0;
|
|
5
|
+
for (let i = 0; i < a.length; i++) {
|
|
6
|
+
dot += a[i] * b[i];
|
|
7
|
+
magA += a[i] * a[i];
|
|
8
|
+
magB += b[i] * b[i];
|
|
9
|
+
}
|
|
10
|
+
const denom = Math.sqrt(magA) * Math.sqrt(magB);
|
|
11
|
+
if (denom === 0)
|
|
12
|
+
return 0;
|
|
13
|
+
return dot / denom;
|
|
14
|
+
}
|
|
15
|
+
export class EmbeddingIndex {
|
|
16
|
+
db;
|
|
17
|
+
/** sourceId -> chunkIndex -> embedding */
|
|
18
|
+
embeddings = new Map();
|
|
19
|
+
_size = 0;
|
|
20
|
+
constructor(db) {
|
|
21
|
+
this.db = db;
|
|
22
|
+
}
|
|
23
|
+
load() {
|
|
24
|
+
this.embeddings.clear();
|
|
25
|
+
this._size = 0;
|
|
26
|
+
const stmt = this.db.prepare('SELECT source_id, chunk_index, embedding FROM chunks WHERE embedding IS NOT NULL');
|
|
27
|
+
const rows = stmt.all();
|
|
28
|
+
for (const row of rows) {
|
|
29
|
+
if (!row.embedding || row.embedding.length === 0)
|
|
30
|
+
continue;
|
|
31
|
+
const uint8 = new Uint8Array(row.embedding);
|
|
32
|
+
const embedding = new Float32Array(uint8.buffer, uint8.byteOffset, uint8.byteLength / 4);
|
|
33
|
+
let sourceMap = this.embeddings.get(row.source_id);
|
|
34
|
+
if (!sourceMap) {
|
|
35
|
+
sourceMap = new Map();
|
|
36
|
+
this.embeddings.set(row.source_id, sourceMap);
|
|
37
|
+
}
|
|
38
|
+
sourceMap.set(row.chunk_index, embedding);
|
|
39
|
+
this._size++;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
add(sourceId, chunks) {
|
|
43
|
+
let sourceMap = this.embeddings.get(sourceId);
|
|
44
|
+
if (!sourceMap) {
|
|
45
|
+
sourceMap = new Map();
|
|
46
|
+
this.embeddings.set(sourceId, sourceMap);
|
|
47
|
+
}
|
|
48
|
+
for (const chunk of chunks) {
|
|
49
|
+
if (!sourceMap.has(chunk.chunkIndex)) {
|
|
50
|
+
this._size++;
|
|
51
|
+
}
|
|
52
|
+
sourceMap.set(chunk.chunkIndex, chunk.embedding);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
remove(sourceId) {
|
|
56
|
+
const sourceMap = this.embeddings.get(sourceId);
|
|
57
|
+
if (sourceMap) {
|
|
58
|
+
this._size -= sourceMap.size;
|
|
59
|
+
this.embeddings.delete(sourceId);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
search(query, topK) {
|
|
63
|
+
const results = [];
|
|
64
|
+
for (const [sourceId, sourceMap] of this.embeddings) {
|
|
65
|
+
for (const [chunkIndex, embedding] of sourceMap) {
|
|
66
|
+
const score = cosineSimilarity(query, embedding);
|
|
67
|
+
results.push({ sourceId, chunkIndex, score });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Sort descending by score and take top K
|
|
71
|
+
results.sort((a, b) => b.score - a.score);
|
|
72
|
+
return results.slice(0, topK);
|
|
73
|
+
}
|
|
74
|
+
get size() {
|
|
75
|
+
return this._size;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=embedding-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-index.js","sourceRoot":"","sources":["../../storage/embedding-index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export { initializeSchema, migrateSchema, SCHEMA_VERSION } from './schema.js';
|
|
3
|
+
export { Database } from './database.js';
|
|
4
|
+
export { SourceRepository } from './source-repo.js';
|
|
5
|
+
export { ChunkRepository } from './chunk-repo.js';
|
|
6
|
+
export { SyncStatusRepository } from './sync-status-repo.js';
|
|
7
|
+
export { EmbeddingIndex } from './embedding-index.js';
|
|
8
|
+
export { DatabaseManager } from './database-manager.js';
|
|
9
|
+
export { KBDatabase } from './kb-database.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export { initializeSchema, migrateSchema, SCHEMA_VERSION } from './schema.js';
|
|
3
|
+
export { Database } from './database.js';
|
|
4
|
+
export { SourceRepository } from './source-repo.js';
|
|
5
|
+
export { ChunkRepository } from './chunk-repo.js';
|
|
6
|
+
export { SyncStatusRepository } from './sync-status-repo.js';
|
|
7
|
+
export { EmbeddingIndex } from './embedding-index.js';
|
|
8
|
+
export { DatabaseManager } from './database-manager.js';
|
|
9
|
+
export { KBDatabase } from './kb-database.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IDatabase, ISourceRepository, IChunkRepository, ISyncStatusRepository, IEmbeddingIndex, DatabaseConfig } from './types.js';
|
|
2
|
+
export declare class KBDatabase implements IDatabase {
|
|
3
|
+
private readonly database;
|
|
4
|
+
readonly sources: ISourceRepository;
|
|
5
|
+
readonly chunks: IChunkRepository;
|
|
6
|
+
readonly syncStatus: ISyncStatusRepository;
|
|
7
|
+
readonly embeddingIndex: IEmbeddingIndex;
|
|
8
|
+
constructor(config: DatabaseConfig);
|
|
9
|
+
close(): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=kb-database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-database.d.ts","sourceRoot":"","sources":["../../storage/kb-database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACf,MAAM,YAAY,CAAC;AAOpB,qBAAa,UAAW,YAAW,SAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IAEpC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC;IAC3C,QAAQ,CAAC,cAAc,EAAE,eAAe,CAAC;gBAE7B,MAAM,EAAE,cAAc;IAUlC,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Database } from './database.js';
|
|
2
|
+
import { SourceRepository } from './source-repo.js';
|
|
3
|
+
import { ChunkRepository } from './chunk-repo.js';
|
|
4
|
+
import { SyncStatusRepository } from './sync-status-repo.js';
|
|
5
|
+
import { EmbeddingIndex } from './embedding-index.js';
|
|
6
|
+
export class KBDatabase {
|
|
7
|
+
database;
|
|
8
|
+
sources;
|
|
9
|
+
chunks;
|
|
10
|
+
syncStatus;
|
|
11
|
+
embeddingIndex;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.database = new Database(config);
|
|
14
|
+
const db = this.database.db;
|
|
15
|
+
this.sources = new SourceRepository(db);
|
|
16
|
+
this.chunks = new ChunkRepository(db);
|
|
17
|
+
this.syncStatus = new SyncStatusRepository(db);
|
|
18
|
+
this.embeddingIndex = new EmbeddingIndex(db);
|
|
19
|
+
}
|
|
20
|
+
close() {
|
|
21
|
+
this.database.close();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=kb-database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-database.js","sourceRoot":"","sources":["../../storage/kb-database.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,OAAO,UAAU;IACJ,QAAQ,CAAW;IAE3B,OAAO,CAAoB;IAC3B,MAAM,CAAmB;IACzB,UAAU,CAAwB;IAClC,cAAc,CAAkB;IAEzC,YAAY,MAAsB;QAChC,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAE5B,IAAI,CAAC,OAAO,GAAG,IAAI,gBAAgB,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,IAAI,oBAAoB,CAAC,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,cAAc,GAAG,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type BetterSqlite3 from 'better-sqlite3';
|
|
2
|
+
export declare const SCHEMA_VERSION = 2;
|
|
3
|
+
export declare const CREATE_TABLES_SQL: string[];
|
|
4
|
+
export declare function initializeSchema(db: BetterSqlite3.Database): void;
|
|
5
|
+
export declare function migrateSchema(db: BetterSqlite3.Database): void;
|
|
6
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../storage/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAEhD,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC,eAAO,MAAM,iBAAiB,EAAE,MAAM,EAuDrC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,aAAa,CAAC,QAAQ,GAAG,IAAI,CAiBjE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,aAAa,CAAC,QAAQ,GAAG,IAAI,CAyB9D"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
export const SCHEMA_VERSION = 2;
|
|
2
|
+
export const CREATE_TABLES_SQL = [
|
|
3
|
+
`CREATE TABLE IF NOT EXISTS sources (
|
|
4
|
+
id TEXT PRIMARY KEY,
|
|
5
|
+
url TEXT NOT NULL,
|
|
6
|
+
title TEXT NOT NULL DEFAULT '',
|
|
7
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
8
|
+
chunk_count INTEGER NOT NULL DEFAULT 0,
|
|
9
|
+
blob_size_bytes INTEGER NOT NULL DEFAULT 0,
|
|
10
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
11
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
12
|
+
last_accessed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
13
|
+
deleted_at TEXT
|
|
14
|
+
)`,
|
|
15
|
+
`CREATE TABLE IF NOT EXISTS chunks (
|
|
16
|
+
id TEXT PRIMARY KEY,
|
|
17
|
+
source_id TEXT NOT NULL REFERENCES sources(id),
|
|
18
|
+
chunk_index INTEGER NOT NULL,
|
|
19
|
+
content TEXT NOT NULL,
|
|
20
|
+
embedding BLOB,
|
|
21
|
+
token_count INTEGER NOT NULL DEFAULT 0,
|
|
22
|
+
model TEXT NOT NULL DEFAULT '',
|
|
23
|
+
UNIQUE(source_id, chunk_index)
|
|
24
|
+
)`,
|
|
25
|
+
`CREATE TABLE IF NOT EXISTS sync_status (
|
|
26
|
+
blob_id TEXT PRIMARY KEY,
|
|
27
|
+
status TEXT NOT NULL DEFAULT 'local_only',
|
|
28
|
+
last_attempt TEXT,
|
|
29
|
+
error_message TEXT
|
|
30
|
+
)`,
|
|
31
|
+
`CREATE TABLE IF NOT EXISTS schema_version (
|
|
32
|
+
version INTEGER NOT NULL
|
|
33
|
+
)`,
|
|
34
|
+
// FTS5 virtual table for keyword search over chunk content
|
|
35
|
+
`CREATE VIRTUAL TABLE IF NOT EXISTS chunks_fts USING fts5(
|
|
36
|
+
content,
|
|
37
|
+
source_id UNINDEXED,
|
|
38
|
+
chunk_index UNINDEXED,
|
|
39
|
+
content='chunks',
|
|
40
|
+
content_rowid='rowid'
|
|
41
|
+
)`,
|
|
42
|
+
// Triggers to keep FTS index in sync with the chunks table
|
|
43
|
+
`CREATE TRIGGER IF NOT EXISTS chunks_ai AFTER INSERT ON chunks BEGIN
|
|
44
|
+
INSERT INTO chunks_fts(rowid, content, source_id, chunk_index)
|
|
45
|
+
VALUES (new.rowid, new.content, new.source_id, new.chunk_index);
|
|
46
|
+
END`,
|
|
47
|
+
`CREATE TRIGGER IF NOT EXISTS chunks_ad AFTER DELETE ON chunks BEGIN
|
|
48
|
+
INSERT INTO chunks_fts(chunks_fts, rowid, content, source_id, chunk_index)
|
|
49
|
+
VALUES ('delete', old.rowid, old.content, old.source_id, old.chunk_index);
|
|
50
|
+
END`,
|
|
51
|
+
`CREATE TRIGGER IF NOT EXISTS chunks_au AFTER UPDATE ON chunks BEGIN
|
|
52
|
+
INSERT INTO chunks_fts(chunks_fts, rowid, content, source_id, chunk_index)
|
|
53
|
+
VALUES ('delete', old.rowid, old.content, old.source_id, old.chunk_index);
|
|
54
|
+
INSERT INTO chunks_fts(rowid, content, source_id, chunk_index)
|
|
55
|
+
VALUES (new.rowid, new.content, new.source_id, new.chunk_index);
|
|
56
|
+
END`,
|
|
57
|
+
];
|
|
58
|
+
export function initializeSchema(db) {
|
|
59
|
+
const existing = db
|
|
60
|
+
.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='schema_version'`)
|
|
61
|
+
.get();
|
|
62
|
+
if (existing) {
|
|
63
|
+
// Schema already exists, run migrations instead
|
|
64
|
+
migrateSchema(db);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
db.transaction(() => {
|
|
68
|
+
for (const sql of CREATE_TABLES_SQL) {
|
|
69
|
+
db.exec(sql);
|
|
70
|
+
}
|
|
71
|
+
db.prepare('INSERT INTO schema_version (version) VALUES (?)').run(SCHEMA_VERSION);
|
|
72
|
+
})();
|
|
73
|
+
}
|
|
74
|
+
export function migrateSchema(db) {
|
|
75
|
+
const row = db.prepare('SELECT version FROM schema_version').get();
|
|
76
|
+
if (!row) {
|
|
77
|
+
// No version row — initialize from scratch
|
|
78
|
+
for (const sql of CREATE_TABLES_SQL) {
|
|
79
|
+
db.exec(sql);
|
|
80
|
+
}
|
|
81
|
+
db.prepare('INSERT INTO schema_version (version) VALUES (?)').run(SCHEMA_VERSION);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const currentVersion = row.version;
|
|
85
|
+
if (currentVersion >= SCHEMA_VERSION) {
|
|
86
|
+
return; // Already up to date
|
|
87
|
+
}
|
|
88
|
+
if (currentVersion < 2) {
|
|
89
|
+
runMigrationV2(db);
|
|
90
|
+
}
|
|
91
|
+
db.prepare('UPDATE schema_version SET version = ?').run(SCHEMA_VERSION);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Migration v2: Add FTS5 full-text search index for keyword search.
|
|
95
|
+
*/
|
|
96
|
+
function runMigrationV2(db) {
|
|
97
|
+
db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS chunks_fts USING fts5(
|
|
98
|
+
content,
|
|
99
|
+
source_id UNINDEXED,
|
|
100
|
+
chunk_index UNINDEXED,
|
|
101
|
+
content='chunks',
|
|
102
|
+
content_rowid='rowid'
|
|
103
|
+
)`);
|
|
104
|
+
db.exec(`CREATE TRIGGER IF NOT EXISTS chunks_ai AFTER INSERT ON chunks BEGIN
|
|
105
|
+
INSERT INTO chunks_fts(rowid, content, source_id, chunk_index)
|
|
106
|
+
VALUES (new.rowid, new.content, new.source_id, new.chunk_index);
|
|
107
|
+
END`);
|
|
108
|
+
db.exec(`CREATE TRIGGER IF NOT EXISTS chunks_ad AFTER DELETE ON chunks BEGIN
|
|
109
|
+
INSERT INTO chunks_fts(chunks_fts, rowid, content, source_id, chunk_index)
|
|
110
|
+
VALUES ('delete', old.rowid, old.content, old.source_id, old.chunk_index);
|
|
111
|
+
END`);
|
|
112
|
+
db.exec(`CREATE TRIGGER IF NOT EXISTS chunks_au AFTER UPDATE ON chunks BEGIN
|
|
113
|
+
INSERT INTO chunks_fts(chunks_fts, rowid, content, source_id, chunk_index)
|
|
114
|
+
VALUES ('delete', old.rowid, old.content, old.source_id, old.chunk_index);
|
|
115
|
+
INSERT INTO chunks_fts(rowid, content, source_id, chunk_index)
|
|
116
|
+
VALUES (new.rowid, new.content, new.source_id, new.chunk_index);
|
|
117
|
+
END`);
|
|
118
|
+
// Backfill: populate FTS index from existing chunk data
|
|
119
|
+
db.exec(`INSERT INTO chunks_fts(rowid, content, source_id, chunk_index)
|
|
120
|
+
SELECT rowid, content, source_id, chunk_index FROM chunks`);
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../storage/schema.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,MAAM,CAAC,MAAM,iBAAiB,GAAa;IACzC;;;;;;;;;;;IAWE;IACF;;;;;;;;;IASE;IACF;;;;;IAKE;IACF;;IAEE;IACF,2DAA2D;IAC3D;;;;;;IAME;IACF,2DAA2D;IAC3D;;;MAGI;IACJ;;;MAGI;IACJ;;;;;MAKI;CACL,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,EAA0B;IACzD,MAAM,QAAQ,GAAG,EAAE;SAChB,OAAO,CAAC,6EAA6E,CAAC;SACtF,GAAG,EAAkC,CAAC;IAEzC,IAAI,QAAQ,EAAE,CAAC;QACb,gDAAgD;QAChD,aAAa,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO;IACT,CAAC;IAED,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;QAClB,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;YACpC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;QACD,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACpF,CAAC,CAAC,EAAE,CAAC;AACP,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAA0B;IACtD,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,GAAG,EAEnD,CAAC;IAEd,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,2CAA2C;QAC3C,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;YACpC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;QACD,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAClF,OAAO;IACT,CAAC;IAED,MAAM,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC;IAEnC,IAAI,cAAc,IAAI,cAAc,EAAE,CAAC;QACrC,OAAO,CAAC,qBAAqB;IAC/B,CAAC;IAED,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACvB,cAAc,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;IAED,EAAE,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAC1E,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,EAA0B;IAChD,EAAE,CAAC,IAAI,CAAC;;;;;;IAMN,CAAC,CAAC;IAEJ,EAAE,CAAC,IAAI,CAAC;;;MAGJ,CAAC,CAAC;IAEN,EAAE,CAAC,IAAI,CAAC;;;MAGJ,CAAC,CAAC;IAEN,EAAE,CAAC,IAAI,CAAC;;;;;MAKJ,CAAC,CAAC;IAEN,wDAAwD;IACxD,EAAE,CAAC,IAAI,CAAC;8DACoD,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type BetterSqlite3 from 'better-sqlite3';
|
|
2
|
+
import type { ISourceRepository, SourceRecord, SourceFilter, PaginationOptions } from './types.js';
|
|
3
|
+
export declare class SourceRepository implements ISourceRepository {
|
|
4
|
+
private readonly db;
|
|
5
|
+
private readonly insertStmt;
|
|
6
|
+
private readonly getByIdStmt;
|
|
7
|
+
private readonly softDeleteStmt;
|
|
8
|
+
private readonly restoreStmt;
|
|
9
|
+
private readonly updateLastAccessedStmt;
|
|
10
|
+
constructor(db: BetterSqlite3.Database);
|
|
11
|
+
insert(source: Omit<SourceRecord, 'createdAt' | 'updatedAt' | 'lastAccessedAt'>): SourceRecord;
|
|
12
|
+
getById(id: string): SourceRecord | null;
|
|
13
|
+
list(filter?: SourceFilter, pagination?: PaginationOptions): SourceRecord[];
|
|
14
|
+
count(filter?: SourceFilter): number;
|
|
15
|
+
softDelete(id: string): boolean;
|
|
16
|
+
restore(id: string): boolean;
|
|
17
|
+
updateLastAccessed(id: string): void;
|
|
18
|
+
private buildFilterQuery;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=source-repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-repo.d.ts","sourceRoot":"","sources":["../../storage/source-repo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,iBAAiB,EAClB,MAAM,YAAY,CAAC;AA8BpB,qBAAa,gBAAiB,YAAW,iBAAiB;IACxD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyB;IAE5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0B;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;IACzD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA0B;gBAErD,EAAE,EAAE,aAAa,CAAC,QAAQ;IAuBtC,MAAM,CACJ,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,WAAW,GAAG,gBAAgB,CAAC,GACvE,YAAY;IAaf,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAKxC,IAAI,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,YAAY,EAAE;IAO3E,KAAK,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM;IAOpC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAK/B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAK5B,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIpC,OAAO,CAAC,gBAAgB;CAiEzB"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
function rowToRecord(row) {
|
|
2
|
+
return {
|
|
3
|
+
id: row.id,
|
|
4
|
+
url: row.url,
|
|
5
|
+
title: row.title,
|
|
6
|
+
tags: JSON.parse(row.tags),
|
|
7
|
+
chunkCount: row.chunk_count,
|
|
8
|
+
blobSizeBytes: row.blob_size_bytes,
|
|
9
|
+
createdAt: row.created_at,
|
|
10
|
+
updatedAt: row.updated_at,
|
|
11
|
+
lastAccessedAt: row.last_accessed_at,
|
|
12
|
+
deletedAt: row.deleted_at ?? undefined,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export class SourceRepository {
|
|
16
|
+
db;
|
|
17
|
+
insertStmt;
|
|
18
|
+
getByIdStmt;
|
|
19
|
+
softDeleteStmt;
|
|
20
|
+
restoreStmt;
|
|
21
|
+
updateLastAccessedStmt;
|
|
22
|
+
constructor(db) {
|
|
23
|
+
this.db = db;
|
|
24
|
+
this.insertStmt = db.prepare(`
|
|
25
|
+
INSERT INTO sources (id, url, title, tags, chunk_count, blob_size_bytes)
|
|
26
|
+
VALUES (@id, @url, @title, @tags, @chunkCount, @blobSizeBytes)
|
|
27
|
+
`);
|
|
28
|
+
this.getByIdStmt = db.prepare('SELECT * FROM sources WHERE id = ?');
|
|
29
|
+
this.softDeleteStmt = db.prepare(`UPDATE sources SET deleted_at = datetime('now'), updated_at = datetime('now') WHERE id = ? AND deleted_at IS NULL`);
|
|
30
|
+
this.restoreStmt = db.prepare(`UPDATE sources SET deleted_at = NULL, updated_at = datetime('now') WHERE id = ? AND deleted_at IS NOT NULL`);
|
|
31
|
+
this.updateLastAccessedStmt = db.prepare(`UPDATE sources SET last_accessed_at = datetime('now') WHERE id = ?`);
|
|
32
|
+
}
|
|
33
|
+
insert(source) {
|
|
34
|
+
this.insertStmt.run({
|
|
35
|
+
id: source.id,
|
|
36
|
+
url: source.url,
|
|
37
|
+
title: source.title,
|
|
38
|
+
tags: JSON.stringify(source.tags),
|
|
39
|
+
chunkCount: source.chunkCount,
|
|
40
|
+
blobSizeBytes: source.blobSizeBytes,
|
|
41
|
+
});
|
|
42
|
+
return this.getById(source.id);
|
|
43
|
+
}
|
|
44
|
+
getById(id) {
|
|
45
|
+
const row = this.getByIdStmt.get(id);
|
|
46
|
+
return row ? rowToRecord(row) : null;
|
|
47
|
+
}
|
|
48
|
+
list(filter, pagination) {
|
|
49
|
+
const { sql, params } = this.buildFilterQuery('SELECT *', filter, pagination);
|
|
50
|
+
const stmt = this.db.prepare(sql);
|
|
51
|
+
const rows = stmt.all(...params);
|
|
52
|
+
return rows.map(rowToRecord);
|
|
53
|
+
}
|
|
54
|
+
count(filter) {
|
|
55
|
+
const { sql, params } = this.buildFilterQuery('SELECT COUNT(*) as cnt', filter);
|
|
56
|
+
const stmt = this.db.prepare(sql);
|
|
57
|
+
const row = stmt.get(...params);
|
|
58
|
+
return row.cnt;
|
|
59
|
+
}
|
|
60
|
+
softDelete(id) {
|
|
61
|
+
const result = this.softDeleteStmt.run(id);
|
|
62
|
+
return result.changes > 0;
|
|
63
|
+
}
|
|
64
|
+
restore(id) {
|
|
65
|
+
const result = this.restoreStmt.run(id);
|
|
66
|
+
return result.changes > 0;
|
|
67
|
+
}
|
|
68
|
+
updateLastAccessed(id) {
|
|
69
|
+
this.updateLastAccessedStmt.run(id);
|
|
70
|
+
}
|
|
71
|
+
buildFilterQuery(selectClause, filter, pagination) {
|
|
72
|
+
const conditions = [];
|
|
73
|
+
const params = [];
|
|
74
|
+
// Default: exclude deleted unless includeDeleted is true
|
|
75
|
+
if (!filter?.includeDeleted) {
|
|
76
|
+
conditions.push('deleted_at IS NULL');
|
|
77
|
+
}
|
|
78
|
+
if (filter?.tags && filter.tags.length > 0) {
|
|
79
|
+
// Match sources that have ALL specified tags
|
|
80
|
+
// Each tag must be present in the JSON array
|
|
81
|
+
for (const tag of filter.tags) {
|
|
82
|
+
conditions.push(`json_each.value = ?`);
|
|
83
|
+
params.push(tag);
|
|
84
|
+
}
|
|
85
|
+
// Use a subquery approach instead: check each tag is in the array
|
|
86
|
+
// Reset and use a different approach
|
|
87
|
+
conditions.length = 0;
|
|
88
|
+
params.length = 0;
|
|
89
|
+
if (!filter?.includeDeleted) {
|
|
90
|
+
conditions.push('deleted_at IS NULL');
|
|
91
|
+
}
|
|
92
|
+
for (const tag of filter.tags) {
|
|
93
|
+
conditions.push(`EXISTS (SELECT 1 FROM json_each(sources.tags) WHERE json_each.value = ?)`);
|
|
94
|
+
params.push(tag);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (filter?.since) {
|
|
98
|
+
conditions.push('created_at > ?');
|
|
99
|
+
params.push(filter.since);
|
|
100
|
+
}
|
|
101
|
+
if (filter?.titleSearch) {
|
|
102
|
+
conditions.push('title LIKE ?');
|
|
103
|
+
params.push(`%${filter.titleSearch}%`);
|
|
104
|
+
}
|
|
105
|
+
let sql = `${selectClause} FROM sources`;
|
|
106
|
+
if (conditions.length > 0) {
|
|
107
|
+
sql += ` WHERE ${conditions.join(' AND ')}`;
|
|
108
|
+
}
|
|
109
|
+
// Only add ORDER BY and LIMIT for non-count queries
|
|
110
|
+
if (!selectClause.includes('COUNT')) {
|
|
111
|
+
sql += ' ORDER BY created_at DESC';
|
|
112
|
+
if (pagination) {
|
|
113
|
+
sql += ' LIMIT ? OFFSET ?';
|
|
114
|
+
params.push(pagination.limit, pagination.offset);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return { sql, params };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=source-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-repo.js","sourceRoot":"","sources":["../../storage/source-repo.ts"],"names":[],"mappings":"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"}
|