@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,15 @@
|
|
|
1
|
+
import type BetterSqlite3 from 'better-sqlite3';
|
|
2
|
+
import type { ISyncStatusRepository, SyncStatusRecord } from './types.js';
|
|
3
|
+
import { SyncStatus } from './types.js';
|
|
4
|
+
export declare class SyncStatusRepository implements ISyncStatusRepository {
|
|
5
|
+
private readonly setStmt;
|
|
6
|
+
private readonly getStmt;
|
|
7
|
+
private readonly getPendingStmt;
|
|
8
|
+
private readonly getByStatusStmt;
|
|
9
|
+
constructor(db: BetterSqlite3.Database);
|
|
10
|
+
set(blobId: string, status: SyncStatus, errorMessage?: string): void;
|
|
11
|
+
get(blobId: string): SyncStatusRecord | null;
|
|
12
|
+
getPending(): SyncStatusRecord[];
|
|
13
|
+
getByStatus(status: SyncStatus): SyncStatusRecord[];
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=sync-status-repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-status-repo.d.ts","sourceRoot":"","sources":["../../storage/sync-status-repo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAkBxC,qBAAa,oBAAqB,YAAW,qBAAqB;IAChE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;IACzD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0B;gBAE9C,EAAE,EAAE,aAAa,CAAC,QAAQ;IAetC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI;IAIpE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAK5C,UAAU,IAAI,gBAAgB,EAAE;IAKhC,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,EAAE;CAIpD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { SyncStatus } from './types.js';
|
|
2
|
+
function rowToRecord(row) {
|
|
3
|
+
return {
|
|
4
|
+
blobId: row.blob_id,
|
|
5
|
+
status: row.status,
|
|
6
|
+
lastAttempt: row.last_attempt ?? undefined,
|
|
7
|
+
errorMessage: row.error_message ?? undefined,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export class SyncStatusRepository {
|
|
11
|
+
setStmt;
|
|
12
|
+
getStmt;
|
|
13
|
+
getPendingStmt;
|
|
14
|
+
getByStatusStmt;
|
|
15
|
+
constructor(db) {
|
|
16
|
+
this.setStmt = db.prepare(`
|
|
17
|
+
INSERT OR REPLACE INTO sync_status (blob_id, status, last_attempt, error_message)
|
|
18
|
+
VALUES (?, ?, datetime('now'), ?)
|
|
19
|
+
`);
|
|
20
|
+
this.getStmt = db.prepare('SELECT * FROM sync_status WHERE blob_id = ?');
|
|
21
|
+
this.getPendingStmt = db.prepare(`SELECT * FROM sync_status WHERE status IN ('${SyncStatus.LocalOnly}', '${SyncStatus.SyncFailed}')`);
|
|
22
|
+
this.getByStatusStmt = db.prepare('SELECT * FROM sync_status WHERE status = ?');
|
|
23
|
+
}
|
|
24
|
+
set(blobId, status, errorMessage) {
|
|
25
|
+
this.setStmt.run(blobId, status, errorMessage ?? null);
|
|
26
|
+
}
|
|
27
|
+
get(blobId) {
|
|
28
|
+
const row = this.getStmt.get(blobId);
|
|
29
|
+
return row ? rowToRecord(row) : null;
|
|
30
|
+
}
|
|
31
|
+
getPending() {
|
|
32
|
+
const rows = this.getPendingStmt.all();
|
|
33
|
+
return rows.map(rowToRecord);
|
|
34
|
+
}
|
|
35
|
+
getByStatus(status) {
|
|
36
|
+
const rows = this.getByStatusStmt.all(status);
|
|
37
|
+
return rows.map(rowToRecord);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=sync-status-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-status-repo.js","sourceRoot":"","sources":["../../storage/sync-status-repo.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AASxC,SAAS,WAAW,CAAC,GAAkB;IACrC,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,MAAM,EAAE,GAAG,CAAC,MAAoB;QAChC,WAAW,EAAE,GAAG,CAAC,YAAY,IAAI,SAAS;QAC1C,YAAY,EAAE,GAAG,CAAC,aAAa,IAAI,SAAS;KAC7C,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,oBAAoB;IACd,OAAO,CAA0B;IACjC,OAAO,CAA0B;IACjC,cAAc,CAA0B;IACxC,eAAe,CAA0B;IAE1D,YAAY,EAA0B;QACpC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC;;;KAGzB,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,6CAA6C,CAAC,CAAC;QAEzE,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC,OAAO,CAC9B,+CAA+C,UAAU,CAAC,SAAS,OAAO,UAAU,CAAC,UAAU,IAAI,CACpG,CAAC;QAEF,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC,OAAO,CAAC,4CAA4C,CAAC,CAAC;IAClF,CAAC;IAED,GAAG,CAAC,MAAc,EAAE,MAAkB,EAAE,YAAqB;QAC3D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,IAAI,IAAI,CAAC,CAAC;IACzD,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAA8B,CAAC;QAClE,OAAO,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;IAED,UAAU;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,EAAqB,CAAC;QAC1D,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IAED,WAAW,CAAC,MAAkB;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAoB,CAAC;QACjE,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;CACF"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/** Source record in the database */
|
|
2
|
+
export interface SourceRecord {
|
|
3
|
+
id: string;
|
|
4
|
+
url: string;
|
|
5
|
+
title: string;
|
|
6
|
+
tags: string[];
|
|
7
|
+
chunkCount: number;
|
|
8
|
+
blobSizeBytes: number;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
updatedAt: string;
|
|
11
|
+
lastAccessedAt: string;
|
|
12
|
+
deletedAt?: string;
|
|
13
|
+
}
|
|
14
|
+
/** Chunk record in the database */
|
|
15
|
+
export interface ChunkRecord {
|
|
16
|
+
id: string;
|
|
17
|
+
sourceId: string;
|
|
18
|
+
chunkIndex: number;
|
|
19
|
+
content: string;
|
|
20
|
+
embedding: Float32Array;
|
|
21
|
+
tokenCount: number;
|
|
22
|
+
model: string;
|
|
23
|
+
}
|
|
24
|
+
/** Sync status for a blob */
|
|
25
|
+
export declare enum SyncStatus {
|
|
26
|
+
LocalOnly = "local_only",
|
|
27
|
+
Synced = "synced",
|
|
28
|
+
PendingDelete = "pending_delete",
|
|
29
|
+
SyncFailed = "sync_failed"
|
|
30
|
+
}
|
|
31
|
+
/** Sync status record */
|
|
32
|
+
export interface SyncStatusRecord {
|
|
33
|
+
blobId: string;
|
|
34
|
+
status: SyncStatus;
|
|
35
|
+
lastAttempt?: string;
|
|
36
|
+
errorMessage?: string;
|
|
37
|
+
}
|
|
38
|
+
/** Pagination options */
|
|
39
|
+
export interface PaginationOptions {
|
|
40
|
+
limit: number;
|
|
41
|
+
offset: number;
|
|
42
|
+
}
|
|
43
|
+
/** Filter options for listing sources */
|
|
44
|
+
export interface SourceFilter {
|
|
45
|
+
tags?: string[];
|
|
46
|
+
/** Only include sources created after this date */
|
|
47
|
+
since?: string;
|
|
48
|
+
/** Search title substring */
|
|
49
|
+
titleSearch?: string;
|
|
50
|
+
/** Include soft-deleted sources */
|
|
51
|
+
includeDeleted?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/** Database configuration */
|
|
54
|
+
export interface DatabaseConfig {
|
|
55
|
+
/** Path to the SQLite database file */
|
|
56
|
+
path: string;
|
|
57
|
+
/** Project name (undefined for personal KB) */
|
|
58
|
+
projectName?: string;
|
|
59
|
+
}
|
|
60
|
+
/** Source repository interface */
|
|
61
|
+
export interface ISourceRepository {
|
|
62
|
+
insert(source: Omit<SourceRecord, 'createdAt' | 'updatedAt' | 'lastAccessedAt'>): SourceRecord;
|
|
63
|
+
getById(id: string): SourceRecord | null;
|
|
64
|
+
list(filter?: SourceFilter, pagination?: PaginationOptions): SourceRecord[];
|
|
65
|
+
count(filter?: SourceFilter): number;
|
|
66
|
+
softDelete(id: string): boolean;
|
|
67
|
+
restore(id: string): boolean;
|
|
68
|
+
updateLastAccessed(id: string): void;
|
|
69
|
+
}
|
|
70
|
+
/** Result of a keyword search */
|
|
71
|
+
export interface KeywordSearchResult {
|
|
72
|
+
sourceId: string;
|
|
73
|
+
chunkIndex: number;
|
|
74
|
+
content: string;
|
|
75
|
+
snippet: string;
|
|
76
|
+
rank: number;
|
|
77
|
+
}
|
|
78
|
+
/** Chunk repository interface */
|
|
79
|
+
export interface IChunkRepository {
|
|
80
|
+
insertMany(chunks: Omit<ChunkRecord, 'id'>[]): ChunkRecord[];
|
|
81
|
+
getBySourceId(sourceId: string): ChunkRecord[];
|
|
82
|
+
deleteBySourceId(sourceId: string): number;
|
|
83
|
+
/** Search chunk content using FTS5 keyword matching */
|
|
84
|
+
searchKeyword(query: string, topK: number): KeywordSearchResult[];
|
|
85
|
+
}
|
|
86
|
+
/** Sync status repository interface */
|
|
87
|
+
export interface ISyncStatusRepository {
|
|
88
|
+
set(blobId: string, status: SyncStatus, errorMessage?: string): void;
|
|
89
|
+
get(blobId: string): SyncStatusRecord | null;
|
|
90
|
+
getPending(): SyncStatusRecord[];
|
|
91
|
+
getByStatus(status: SyncStatus): SyncStatusRecord[];
|
|
92
|
+
}
|
|
93
|
+
/** Embedding index for in-memory search */
|
|
94
|
+
export interface IEmbeddingIndex {
|
|
95
|
+
/** Load all embeddings from database */
|
|
96
|
+
load(): void;
|
|
97
|
+
/** Add embeddings for a source */
|
|
98
|
+
add(sourceId: string, chunks: {
|
|
99
|
+
chunkIndex: number;
|
|
100
|
+
embedding: Float32Array;
|
|
101
|
+
}[]): void;
|
|
102
|
+
/** Remove embeddings for a source */
|
|
103
|
+
remove(sourceId: string): void;
|
|
104
|
+
/** Search for similar embeddings, return indices sorted by score */
|
|
105
|
+
search(query: Float32Array, topK: number): {
|
|
106
|
+
sourceId: string;
|
|
107
|
+
chunkIndex: number;
|
|
108
|
+
score: number;
|
|
109
|
+
}[];
|
|
110
|
+
/** Total number of embeddings in the index */
|
|
111
|
+
readonly size: number;
|
|
112
|
+
}
|
|
113
|
+
/** Database manager for multiple KBs */
|
|
114
|
+
export interface IDatabaseManager {
|
|
115
|
+
/** Get or create the personal database */
|
|
116
|
+
getPersonalDb(): IDatabase;
|
|
117
|
+
/** Get or create a project database */
|
|
118
|
+
getProjectDb(projectName: string): IDatabase;
|
|
119
|
+
/** List all project databases */
|
|
120
|
+
listProjects(): {
|
|
121
|
+
name: string;
|
|
122
|
+
path: string;
|
|
123
|
+
sizeBytes: number;
|
|
124
|
+
sourceCount: number;
|
|
125
|
+
}[];
|
|
126
|
+
/** Delete a project database */
|
|
127
|
+
deleteProject(projectName: string): boolean;
|
|
128
|
+
/** Close all open databases */
|
|
129
|
+
closeAll(): void;
|
|
130
|
+
}
|
|
131
|
+
/** Combined database interface */
|
|
132
|
+
export interface IDatabase {
|
|
133
|
+
readonly sources: ISourceRepository;
|
|
134
|
+
readonly chunks: IChunkRepository;
|
|
135
|
+
readonly syncStatus: ISyncStatusRepository;
|
|
136
|
+
readonly embeddingIndex: IEmbeddingIndex;
|
|
137
|
+
close(): void;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../storage/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Sync status for a blob */
|
|
2
|
+
export var SyncStatus;
|
|
3
|
+
(function (SyncStatus) {
|
|
4
|
+
SyncStatus["LocalOnly"] = "local_only";
|
|
5
|
+
SyncStatus["Synced"] = "synced";
|
|
6
|
+
SyncStatus["PendingDelete"] = "pending_delete";
|
|
7
|
+
SyncStatus["SyncFailed"] = "sync_failed";
|
|
8
|
+
})(SyncStatus || (SyncStatus = {}));
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../storage/types.ts"],"names":[],"mappings":"AAyBA,6BAA6B;AAC7B,MAAM,CAAN,IAAY,UAKX;AALD,WAAY,UAAU;IACpB,sCAAwB,CAAA;IACxB,+BAAiB,CAAA;IACjB,8CAAgC,CAAA;IAChC,wCAA0B,CAAA;AAC5B,CAAC,EALW,UAAU,KAAV,UAAU,QAKrB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ISyncHttpClient } from './types.js';
|
|
2
|
+
import type { IEncryptionService, DerivedKeySet } from '../crypto/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Verify encryption keys by writing, reading, and verifying a canary blob.
|
|
5
|
+
*
|
|
6
|
+
* This is used on first sync to confirm that the local encryption keys
|
|
7
|
+
* can successfully round-trip through the server. The canary blob is
|
|
8
|
+
* deleted after verification.
|
|
9
|
+
*
|
|
10
|
+
* @returns true if the canary was written, read back, decrypted, and
|
|
11
|
+
* verified successfully; false otherwise.
|
|
12
|
+
*/
|
|
13
|
+
export declare function verifyCanary(client: ISyncHttpClient, encryptionService: IEncryptionService, keys: DerivedKeySet): Promise<boolean>;
|
|
14
|
+
//# sourceMappingURL=canary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canary.d.ts","sourceRoot":"","sources":["../../sync/canary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAiB,MAAM,oBAAoB,CAAC;AAE3F;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,eAAe,EACvB,iBAAiB,EAAE,kBAAkB,EACrC,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,OAAO,CAAC,CA6ClB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify encryption keys by writing, reading, and verifying a canary blob.
|
|
3
|
+
*
|
|
4
|
+
* This is used on first sync to confirm that the local encryption keys
|
|
5
|
+
* can successfully round-trip through the server. The canary blob is
|
|
6
|
+
* deleted after verification.
|
|
7
|
+
*
|
|
8
|
+
* @returns true if the canary was written, read back, decrypted, and
|
|
9
|
+
* verified successfully; false otherwise.
|
|
10
|
+
*/
|
|
11
|
+
export async function verifyCanary(client, encryptionService, keys) {
|
|
12
|
+
const canaryPayload = {
|
|
13
|
+
type: 'canary',
|
|
14
|
+
value: 'chaoskb-canary-v1',
|
|
15
|
+
};
|
|
16
|
+
const blobId = encryptionService.generateBlobId();
|
|
17
|
+
try {
|
|
18
|
+
// Encrypt the canary payload
|
|
19
|
+
const { bytes } = encryptionService.encrypt(canaryPayload, keys);
|
|
20
|
+
// Upload to server
|
|
21
|
+
const putResponse = await client.put(`/v1/blobs/${blobId}`, bytes);
|
|
22
|
+
if (!putResponse.ok && putResponse.status !== 201) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
// Download back from server
|
|
26
|
+
const getResponse = await client.get(`/v1/blobs/${blobId}`);
|
|
27
|
+
if (!getResponse.ok) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
// Decrypt
|
|
31
|
+
const downloadedBytes = new Uint8Array(await getResponse.arrayBuffer());
|
|
32
|
+
const envelope = JSON.parse(new TextDecoder().decode(downloadedBytes));
|
|
33
|
+
const { payload } = encryptionService.decrypt(envelope, keys);
|
|
34
|
+
// Verify
|
|
35
|
+
if (payload.type !== 'canary' || payload.value !== 'chaoskb-canary-v1') {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
// Always attempt to clean up the canary blob
|
|
45
|
+
try {
|
|
46
|
+
await client.delete(`/v1/blobs/${blobId}`);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Best-effort cleanup — ignore failures
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=canary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canary.js","sourceRoot":"","sources":["../../sync/canary.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAuB,EACvB,iBAAqC,EACrC,IAAmB;IAEnB,MAAM,aAAa,GAAkB;QACnC,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,mBAAmB;KAC3B,CAAC;IAEF,MAAM,MAAM,GAAG,iBAAiB,CAAC,cAAc,EAAE,CAAC;IAElD,IAAI,CAAC;QACH,6BAA6B;QAC7B,MAAM,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QAEjE,mBAAmB;QACnB,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,aAAa,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC;QACnE,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,WAAW,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAClD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,4BAA4B;QAC5B,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,aAAa,MAAM,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;YACpB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,UAAU;QACV,MAAM,eAAe,GAAG,IAAI,UAAU,CAAC,MAAM,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;QACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;QACvE,MAAM,EAAE,OAAO,EAAE,GAAG,iBAAiB,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAE9D,SAAS;QACT,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAK,OAAyB,CAAC,KAAK,KAAK,mBAAmB,EAAE,CAAC;YAC1F,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;YAAS,CAAC;QACT,6CAA6C;QAC7C,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,MAAM,EAAE,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,wCAAwC;QAC1C,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ISyncHttpClient, SyncResult, SyncState } from './types.js';
|
|
2
|
+
import type { IDatabase } from '../storage/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Full sync for new devices — downloads all blobs from the server.
|
|
5
|
+
*
|
|
6
|
+
* Supports resumability via a cursor persisted in SyncState. If a previous
|
|
7
|
+
* full sync was interrupted, it resumes from where it left off.
|
|
8
|
+
*
|
|
9
|
+
* @param client - HTTP client for server communication
|
|
10
|
+
* @param storage - Local database
|
|
11
|
+
* @param state - Mutable sync state; fullSyncCursor is updated during pagination.
|
|
12
|
+
* The caller is responsible for persisting state to disk after each call.
|
|
13
|
+
* @returns SyncResult with counts of processed blobs
|
|
14
|
+
*/
|
|
15
|
+
export declare function fullSync(client: ISyncHttpClient, storage: IDatabase, state: SyncState): Promise<SyncResult>;
|
|
16
|
+
//# sourceMappingURL=full-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"full-sync.d.ts","sourceRoot":"","sources":["../../sync/full-sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgB,UAAU,EAAa,SAAS,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AASrD;;;;;;;;;;;GAWG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,SAAS,EAClB,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,UAAU,CAAC,CAqFrB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { SyncStatus } from '../storage/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Full sync for new devices — downloads all blobs from the server.
|
|
4
|
+
*
|
|
5
|
+
* Supports resumability via a cursor persisted in SyncState. If a previous
|
|
6
|
+
* full sync was interrupted, it resumes from where it left off.
|
|
7
|
+
*
|
|
8
|
+
* @param client - HTTP client for server communication
|
|
9
|
+
* @param storage - Local database
|
|
10
|
+
* @param state - Mutable sync state; fullSyncCursor is updated during pagination.
|
|
11
|
+
* The caller is responsible for persisting state to disk after each call.
|
|
12
|
+
* @returns SyncResult with counts of processed blobs
|
|
13
|
+
*/
|
|
14
|
+
export async function fullSync(client, storage, state) {
|
|
15
|
+
const errors = [];
|
|
16
|
+
let newBlobs = 0;
|
|
17
|
+
let cursor = state.fullSyncCursor;
|
|
18
|
+
state.fullSyncInProgress = true;
|
|
19
|
+
while (true) {
|
|
20
|
+
const listPath = cursor ? `/v1/blobs?cursor=${encodeURIComponent(cursor)}` : '/v1/blobs';
|
|
21
|
+
const listResponse = await client.get(listPath);
|
|
22
|
+
if (!listResponse.ok) {
|
|
23
|
+
errors.push({
|
|
24
|
+
message: `Failed to list blobs: HTTP ${listResponse.status}`,
|
|
25
|
+
code: 'LIST_FAILED',
|
|
26
|
+
retryable: listResponse.status >= 500,
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
newBlobs,
|
|
30
|
+
updatedBlobs: 0,
|
|
31
|
+
deletedBlobs: 0,
|
|
32
|
+
conflicts: [],
|
|
33
|
+
errors,
|
|
34
|
+
success: false,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const page = (await listResponse.json());
|
|
38
|
+
if (page.blobs.length === 0) {
|
|
39
|
+
// No more pages — full sync complete
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
for (const blobMeta of page.blobs) {
|
|
43
|
+
try {
|
|
44
|
+
const blobResponse = await client.get(`/v1/blobs/${blobMeta.id}`);
|
|
45
|
+
if (!blobResponse.ok) {
|
|
46
|
+
errors.push({
|
|
47
|
+
blobId: blobMeta.id,
|
|
48
|
+
message: `Failed to download blob: HTTP ${blobResponse.status}`,
|
|
49
|
+
code: 'DOWNLOAD_FAILED',
|
|
50
|
+
retryable: blobResponse.status >= 500,
|
|
51
|
+
});
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const blobData = new Uint8Array(await blobResponse.arrayBuffer());
|
|
55
|
+
void blobData; // Consumed by higher-layer processing
|
|
56
|
+
storage.syncStatus.set(blobMeta.id, SyncStatus.Synced);
|
|
57
|
+
newBlobs++;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
errors.push({
|
|
61
|
+
blobId: blobMeta.id,
|
|
62
|
+
message: error instanceof Error ? error.message : String(error),
|
|
63
|
+
code: 'DOWNLOAD_ERROR',
|
|
64
|
+
retryable: true,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Update cursor for resumability
|
|
69
|
+
if (page.cursor) {
|
|
70
|
+
cursor = page.cursor;
|
|
71
|
+
state.fullSyncCursor = cursor;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
// No more pages
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Mark full sync as complete
|
|
79
|
+
state.fullSyncInProgress = false;
|
|
80
|
+
state.fullSyncCursor = undefined;
|
|
81
|
+
state.lastSyncTimestamp = new Date().toISOString();
|
|
82
|
+
return {
|
|
83
|
+
newBlobs,
|
|
84
|
+
updatedBlobs: 0,
|
|
85
|
+
deletedBlobs: 0,
|
|
86
|
+
conflicts: [],
|
|
87
|
+
errors,
|
|
88
|
+
success: errors.length === 0,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=full-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"full-sync.js","sourceRoot":"","sources":["../../sync/full-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ISyncHttpClient } from './types.js';
|
|
2
|
+
import type { SyncConfig } from './types.js';
|
|
3
|
+
import type { SSHSigner } from './ssh-signer.js';
|
|
4
|
+
import { SequenceCounter } from './sequence.js';
|
|
5
|
+
/** Error that indicates the request can be retried after a delay. */
|
|
6
|
+
export declare class RetryableError extends Error {
|
|
7
|
+
/** Seconds to wait before retrying */
|
|
8
|
+
readonly retryAfterSeconds: number;
|
|
9
|
+
constructor(message: string, retryAfterSeconds: number);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* HTTP client for ChaosKB server communication.
|
|
13
|
+
*
|
|
14
|
+
* Enforces HTTPS, signs every request with the SSH signer, and
|
|
15
|
+
* provides error handling for rate-limiting and network failures.
|
|
16
|
+
*/
|
|
17
|
+
export declare class SyncHttpClient implements ISyncHttpClient {
|
|
18
|
+
private readonly baseUrl;
|
|
19
|
+
private readonly signer;
|
|
20
|
+
private readonly sequence;
|
|
21
|
+
constructor(config: SyncConfig, signer: SSHSigner, sequence?: SequenceCounter);
|
|
22
|
+
get(path: string): Promise<Response>;
|
|
23
|
+
put(path: string, body: Uint8Array): Promise<Response>;
|
|
24
|
+
delete(path: string): Promise<Response>;
|
|
25
|
+
post(path: string, body?: Uint8Array): Promise<Response>;
|
|
26
|
+
private request;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=http-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../sync/http-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,qEAAqE;AACrE,qBAAa,cAAe,SAAQ,KAAK;IACvC,sCAAsC;IACtC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM;CAKvD;AAKD;;;;;GAKG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;gBAE/B,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,eAAe;IAYvE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIpC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC;IAItD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIvC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC;YAIhD,OAAO;CAsDtB"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { SequenceCounter } from './sequence.js';
|
|
2
|
+
/** Error that indicates the request can be retried after a delay. */
|
|
3
|
+
export class RetryableError extends Error {
|
|
4
|
+
/** Seconds to wait before retrying */
|
|
5
|
+
retryAfterSeconds;
|
|
6
|
+
constructor(message, retryAfterSeconds) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'RetryableError';
|
|
9
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Default request timeout in milliseconds. */
|
|
13
|
+
const REQUEST_TIMEOUT_MS = 30_000;
|
|
14
|
+
/**
|
|
15
|
+
* HTTP client for ChaosKB server communication.
|
|
16
|
+
*
|
|
17
|
+
* Enforces HTTPS, signs every request with the SSH signer, and
|
|
18
|
+
* provides error handling for rate-limiting and network failures.
|
|
19
|
+
*/
|
|
20
|
+
export class SyncHttpClient {
|
|
21
|
+
baseUrl;
|
|
22
|
+
signer;
|
|
23
|
+
sequence;
|
|
24
|
+
constructor(config, signer, sequence) {
|
|
25
|
+
this.sequence = sequence ?? new SequenceCounter();
|
|
26
|
+
if (!config.endpoint.startsWith('https://')) {
|
|
27
|
+
throw new Error(`TLS required: endpoint must start with https://, got "${config.endpoint}"`);
|
|
28
|
+
}
|
|
29
|
+
// Strip trailing slash for clean URL joining
|
|
30
|
+
this.baseUrl = config.endpoint.replace(/\/+$/, '');
|
|
31
|
+
this.signer = signer;
|
|
32
|
+
}
|
|
33
|
+
async get(path) {
|
|
34
|
+
return this.request('GET', path);
|
|
35
|
+
}
|
|
36
|
+
async put(path, body) {
|
|
37
|
+
return this.request('PUT', path, body);
|
|
38
|
+
}
|
|
39
|
+
async delete(path) {
|
|
40
|
+
return this.request('DELETE', path);
|
|
41
|
+
}
|
|
42
|
+
async post(path, body) {
|
|
43
|
+
return this.request('POST', path, body);
|
|
44
|
+
}
|
|
45
|
+
async request(method, path, body) {
|
|
46
|
+
const seq = this.sequence.next();
|
|
47
|
+
const result = await this.signer.signRequest(method, path, seq, body);
|
|
48
|
+
const headers = {
|
|
49
|
+
Authorization: result.authorization,
|
|
50
|
+
'X-ChaosKB-Timestamp': result.timestamp,
|
|
51
|
+
'X-ChaosKB-Sequence': String(result.sequence),
|
|
52
|
+
'X-ChaosKB-PublicKey': result.publicKey,
|
|
53
|
+
};
|
|
54
|
+
if (body) {
|
|
55
|
+
headers['Content-Type'] = 'application/octet-stream';
|
|
56
|
+
}
|
|
57
|
+
const url = `${this.baseUrl}${path}`;
|
|
58
|
+
const controller = new AbortController();
|
|
59
|
+
const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
60
|
+
let response;
|
|
61
|
+
try {
|
|
62
|
+
response = await fetch(url, {
|
|
63
|
+
method,
|
|
64
|
+
headers,
|
|
65
|
+
body: body ?? undefined,
|
|
66
|
+
signal: controller.signal,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
clearTimeout(timeoutId);
|
|
71
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
72
|
+
throw new Error(`Request timed out after ${REQUEST_TIMEOUT_MS}ms: ${method} ${path}`);
|
|
73
|
+
}
|
|
74
|
+
throw new Error(`Network error: ${method} ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
clearTimeout(timeoutId);
|
|
78
|
+
}
|
|
79
|
+
if (response.status === 401) {
|
|
80
|
+
throw new Error('Authentication failed: invalid or expired SSH signature');
|
|
81
|
+
}
|
|
82
|
+
if (response.status === 429) {
|
|
83
|
+
const retryAfterHeader = response.headers.get('Retry-After');
|
|
84
|
+
const retryAfterSeconds = retryAfterHeader ? parseInt(retryAfterHeader, 10) : 60;
|
|
85
|
+
throw new RetryableError(`Rate limited: ${method} ${path}`, isNaN(retryAfterSeconds) ? 60 : retryAfterSeconds);
|
|
86
|
+
}
|
|
87
|
+
return response;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=http-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../sync/http-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ISyncHttpClient, SyncResult } from './types.js';
|
|
2
|
+
import type { IDatabase } from '../storage/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Download changes from the server since the last sync timestamp.
|
|
5
|
+
*
|
|
6
|
+
* On first sync (no lastSyncTimestamp), downloads metadata for all blobs.
|
|
7
|
+
* For each new/updated blob, downloads the content and stores it locally.
|
|
8
|
+
* For each tombstone, soft-deletes the local record if it exists.
|
|
9
|
+
*
|
|
10
|
+
* Conflict resolution strategy:
|
|
11
|
+
* - New remote blobs (not present locally): accept as-is
|
|
12
|
+
* - Remote blob updated, local is synced: accept remote update
|
|
13
|
+
* - Remote blob updated, local has unsynchronized changes: last-write-wins
|
|
14
|
+
* - Remote tombstone, local has unsynchronized changes: keep local (local_wins)
|
|
15
|
+
*/
|
|
16
|
+
export declare function incrementalSync(client: ISyncHttpClient, storage: IDatabase, lastSyncTimestamp?: string): Promise<SyncResult>;
|
|
17
|
+
//# sourceMappingURL=incremental-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incremental-sync.d.ts","sourceRoot":"","sources":["../../sync/incremental-sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAoB,UAAU,EAA2B,MAAM,YAAY,CAAC;AACzG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,SAAS,EAClB,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,UAAU,CAAC,CAsJrB"}
|