daftari 1.29.0 → 1.31.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/CHANGELOG.md +281 -0
- package/README.md +263 -9
- package/dist/access/rbac.d.ts +1 -0
- package/dist/access/rbac.d.ts.map +1 -1
- package/dist/access/rbac.js +7 -0
- package/dist/access/rbac.js.map +1 -1
- package/dist/asof/git-read.d.ts +17 -0
- package/dist/asof/git-read.d.ts.map +1 -0
- package/dist/asof/git-read.js +163 -0
- package/dist/asof/git-read.js.map +1 -0
- package/dist/asof/index.d.ts +2 -0
- package/dist/asof/index.d.ts.map +1 -0
- package/dist/asof/index.js +151 -0
- package/dist/asof/index.js.map +1 -0
- package/dist/asof/report.d.ts +11 -0
- package/dist/asof/report.d.ts.map +1 -0
- package/dist/asof/report.js +119 -0
- package/dist/asof/report.js.map +1 -0
- package/dist/asof/snapshot.d.ts +72 -0
- package/dist/asof/snapshot.d.ts.map +1 -0
- package/dist/asof/snapshot.js +207 -0
- package/dist/asof/snapshot.js.map +1 -0
- package/dist/audit/checks/broken_refs.d.ts +1 -1
- package/dist/audit/checks/broken_refs.d.ts.map +1 -1
- package/dist/audit/checks/broken_refs.js +77 -22
- package/dist/audit/checks/broken_refs.js.map +1 -1
- package/dist/audit/collect.d.ts +1 -0
- package/dist/audit/collect.d.ts.map +1 -1
- package/dist/audit/collect.js +22 -2
- package/dist/audit/collect.js.map +1 -1
- package/dist/audit/index.d.ts.map +1 -1
- package/dist/audit/index.js +9 -3
- package/dist/audit/index.js.map +1 -1
- package/dist/audit/links.d.ts.map +1 -1
- package/dist/audit/links.js +9 -3
- package/dist/audit/links.js.map +1 -1
- package/dist/audit/report.d.ts.map +1 -1
- package/dist/audit/report.js +2 -0
- package/dist/audit/report.js.map +1 -1
- package/dist/audit/types.d.ts +4 -1
- package/dist/audit/types.d.ts.map +1 -1
- package/dist/audit/types.js.map +1 -1
- package/dist/backfill/apply.js +2 -2
- package/dist/backfill/apply.js.map +1 -1
- package/dist/backfill/derive.d.ts.map +1 -1
- package/dist/backfill/derive.js +1 -0
- package/dist/backfill/derive.js.map +1 -1
- package/dist/backfill/plan.js +2 -2
- package/dist/backfill/plan.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +36 -0
- package/dist/cli.js.map +1 -1
- package/dist/consolidate/call-budget.d.ts +3 -0
- package/dist/consolidate/call-budget.d.ts.map +1 -0
- package/dist/consolidate/call-budget.js +37 -0
- package/dist/consolidate/call-budget.js.map +1 -0
- package/dist/consolidate/constants.d.ts +1 -0
- package/dist/consolidate/constants.d.ts.map +1 -1
- package/dist/consolidate/constants.js +5 -0
- package/dist/consolidate/constants.js.map +1 -1
- package/dist/consolidate/index.d.ts.map +1 -1
- package/dist/consolidate/index.js +96 -27
- package/dist/consolidate/index.js.map +1 -1
- package/dist/court/docket.d.ts +39 -0
- package/dist/court/docket.d.ts.map +1 -0
- package/dist/court/docket.js +103 -0
- package/dist/court/docket.js.map +1 -0
- package/dist/court/index.d.ts +2 -0
- package/dist/court/index.d.ts.map +1 -0
- package/dist/court/index.js +169 -0
- package/dist/court/index.js.map +1 -0
- package/dist/court/precedent.d.ts +18 -0
- package/dist/court/precedent.d.ts.map +1 -0
- package/dist/court/precedent.js +89 -0
- package/dist/court/precedent.js.map +1 -0
- package/dist/court/report.d.ts +10 -0
- package/dist/court/report.d.ts.map +1 -0
- package/dist/court/report.js +77 -0
- package/dist/court/report.js.map +1 -0
- package/dist/curation/consumes.d.ts +24 -0
- package/dist/curation/consumes.d.ts.map +1 -0
- package/dist/curation/consumes.js +122 -0
- package/dist/curation/consumes.js.map +1 -0
- package/dist/curation/edge-staleness.d.ts +47 -0
- package/dist/curation/edge-staleness.d.ts.map +1 -0
- package/dist/curation/edge-staleness.js +258 -0
- package/dist/curation/edge-staleness.js.map +1 -0
- package/dist/curation/edges.d.ts.map +1 -1
- package/dist/curation/edges.js +164 -10
- package/dist/curation/edges.js.map +1 -1
- package/dist/curation/lint.d.ts +4 -1
- package/dist/curation/lint.d.ts.map +1 -1
- package/dist/curation/lint.js +61 -6
- package/dist/curation/lint.js.map +1 -1
- package/dist/curation/provenance.d.ts +2 -0
- package/dist/curation/provenance.d.ts.map +1 -1
- package/dist/curation/provenance.js +2 -0
- package/dist/curation/provenance.js.map +1 -1
- package/dist/curation/read-log.d.ts +19 -0
- package/dist/curation/read-log.d.ts.map +1 -0
- package/dist/curation/read-log.js +120 -0
- package/dist/curation/read-log.js.map +1 -0
- package/dist/curation/review-throughput.d.ts +24 -0
- package/dist/curation/review-throughput.d.ts.map +1 -0
- package/dist/curation/review-throughput.js +102 -0
- package/dist/curation/review-throughput.js.map +1 -0
- package/dist/curation/staged-actions.d.ts +11 -1
- package/dist/curation/staged-actions.d.ts.map +1 -1
- package/dist/curation/staged-actions.js +117 -30
- package/dist/curation/staged-actions.js.map +1 -1
- package/dist/curation/staleness.js +1 -1
- package/dist/curation/staleness.js.map +1 -1
- package/dist/curation/structural.d.ts +16 -0
- package/dist/curation/structural.d.ts.map +1 -0
- package/dist/curation/structural.js +64 -0
- package/dist/curation/structural.js.map +1 -0
- package/dist/curation/tension-access.d.ts +7 -0
- package/dist/curation/tension-access.d.ts.map +1 -0
- package/dist/curation/tension-access.js +44 -0
- package/dist/curation/tension-access.js.map +1 -0
- package/dist/curation/tension-blast.d.ts +6 -1
- package/dist/curation/tension-blast.d.ts.map +1 -1
- package/dist/curation/tension-blast.js +11 -2
- package/dist/curation/tension-blast.js.map +1 -1
- package/dist/curation/tension-clusters.d.ts +1 -1
- package/dist/curation/tension-clusters.d.ts.map +1 -1
- package/dist/curation/tension-clusters.js +5 -2
- package/dist/curation/tension-clusters.js.map +1 -1
- package/dist/curation/tension.d.ts +6 -2
- package/dist/curation/tension.d.ts.map +1 -1
- package/dist/curation/tension.js +86 -35
- package/dist/curation/tension.js.map +1 -1
- package/dist/curation/tier0.d.ts +27 -0
- package/dist/curation/tier0.d.ts.map +1 -0
- package/dist/curation/tier0.js +196 -0
- package/dist/curation/tier0.js.map +1 -0
- package/dist/curation/tier1.d.ts +30 -0
- package/dist/curation/tier1.d.ts.map +1 -0
- package/dist/curation/tier1.js +142 -0
- package/dist/curation/tier1.js.map +1 -0
- package/dist/curation/tier2.d.ts +43 -0
- package/dist/curation/tier2.d.ts.map +1 -0
- package/dist/curation/tier2.js +182 -0
- package/dist/curation/tier2.js.map +1 -0
- package/dist/curation/vault-docs.d.ts +5 -1
- package/dist/curation/vault-docs.d.ts.map +1 -1
- package/dist/curation/vault-docs.js +15 -1
- package/dist/curation/vault-docs.js.map +1 -1
- package/dist/eval/generate.js +22 -5
- package/dist/eval/generate.js.map +1 -1
- package/dist/eval/index.d.ts.map +1 -1
- package/dist/eval/index.js +173 -25
- package/dist/eval/index.js.map +1 -1
- package/dist/eval/llm-openrouter.d.ts +9 -0
- package/dist/eval/llm-openrouter.d.ts.map +1 -0
- package/dist/eval/llm-openrouter.js +171 -0
- package/dist/eval/llm-openrouter.js.map +1 -0
- package/dist/eval/llm.js +1 -1
- package/dist/eval/llm.js.map +1 -1
- package/dist/eval/prune.d.ts +24 -0
- package/dist/eval/prune.d.ts.map +1 -0
- package/dist/eval/prune.js +83 -0
- package/dist/eval/prune.js.map +1 -0
- package/dist/eval/storage.d.ts +3 -0
- package/dist/eval/storage.d.ts.map +1 -1
- package/dist/eval/storage.js +14 -0
- package/dist/eval/storage.js.map +1 -1
- package/dist/frontmatter/parser.d.ts +1 -0
- package/dist/frontmatter/parser.d.ts.map +1 -1
- package/dist/frontmatter/parser.js +12 -0
- package/dist/frontmatter/parser.js.map +1 -1
- package/dist/frontmatter/schema.d.ts.map +1 -1
- package/dist/frontmatter/schema.js +38 -3
- package/dist/frontmatter/schema.js.map +1 -1
- package/dist/frontmatter/types.d.ts +4 -1
- package/dist/frontmatter/types.d.ts.map +1 -1
- package/dist/frontmatter/types.js +8 -0
- package/dist/frontmatter/types.js.map +1 -1
- package/dist/import/index.d.ts.map +1 -1
- package/dist/import/index.js +44 -9
- package/dist/import/index.js.map +1 -1
- package/dist/import/langgraph-store.d.ts +53 -0
- package/dist/import/langgraph-store.d.ts.map +1 -0
- package/dist/import/langgraph-store.js +292 -0
- package/dist/import/langgraph-store.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -18
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/lock.d.ts +9 -1
- package/dist/lifecycle/lock.d.ts.map +1 -1
- package/dist/lifecycle/lock.js +34 -9
- package/dist/lifecycle/lock.js.map +1 -1
- package/dist/okf/export.d.ts +12 -0
- package/dist/okf/export.d.ts.map +1 -0
- package/dist/okf/export.js +115 -0
- package/dist/okf/export.js.map +1 -0
- package/dist/okf/import.d.ts +24 -0
- package/dist/okf/import.d.ts.map +1 -0
- package/dist/okf/import.js +107 -0
- package/dist/okf/import.js.map +1 -0
- package/dist/okf/index.d.ts +2 -0
- package/dist/okf/index.d.ts.map +1 -0
- package/dist/okf/index.js +147 -0
- package/dist/okf/index.js.map +1 -0
- package/dist/okf/map.d.ts +16 -0
- package/dist/okf/map.d.ts.map +1 -0
- package/dist/okf/map.js +149 -0
- package/dist/okf/map.js.map +1 -0
- package/dist/okf/types.d.ts +9 -0
- package/dist/okf/types.d.ts.map +1 -0
- package/dist/okf/types.js +48 -0
- package/dist/okf/types.js.map +1 -0
- package/dist/search/contested.d.ts +18 -0
- package/dist/search/contested.d.ts.map +1 -0
- package/dist/search/contested.js +119 -0
- package/dist/search/contested.js.map +1 -0
- package/dist/search/coverage.d.ts.map +1 -1
- package/dist/search/coverage.js +1 -1
- package/dist/search/coverage.js.map +1 -1
- package/dist/search/hybrid.d.ts +23 -0
- package/dist/search/hybrid.d.ts.map +1 -1
- package/dist/search/hybrid.js +75 -15
- package/dist/search/hybrid.js.map +1 -1
- package/dist/search/reindex.d.ts +1 -0
- package/dist/search/reindex.d.ts.map +1 -1
- package/dist/search/reindex.js +57 -24
- package/dist/search/reindex.js.map +1 -1
- package/dist/search/watcher.d.ts +2 -0
- package/dist/search/watcher.d.ts.map +1 -1
- package/dist/search/watcher.js +23 -12
- package/dist/search/watcher.js.map +1 -1
- package/dist/serve/index.d.ts +36 -0
- package/dist/serve/index.d.ts.map +1 -0
- package/dist/serve/index.js +507 -0
- package/dist/serve/index.js.map +1 -0
- package/dist/server.d.ts +10 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +91 -12
- package/dist/server.js.map +1 -1
- package/dist/sleep/cycle.d.ts +59 -0
- package/dist/sleep/cycle.d.ts.map +1 -0
- package/dist/sleep/cycle.js +127 -0
- package/dist/sleep/cycle.js.map +1 -0
- package/dist/sleep/index.d.ts +5 -0
- package/dist/sleep/index.d.ts.map +1 -0
- package/dist/sleep/index.js +320 -0
- package/dist/sleep/index.js.map +1 -0
- package/dist/sleep/report.d.ts +14 -0
- package/dist/sleep/report.d.ts.map +1 -0
- package/dist/sleep/report.js +139 -0
- package/dist/sleep/report.js.map +1 -0
- package/dist/sleep/tension-scan-state.d.ts +19 -0
- package/dist/sleep/tension-scan-state.d.ts.map +1 -0
- package/dist/sleep/tension-scan-state.js +0 -0
- package/dist/sleep/tension-scan-state.js.map +1 -0
- package/dist/sleep/tension-scan.d.ts +44 -0
- package/dist/sleep/tension-scan.d.ts.map +1 -0
- package/dist/sleep/tension-scan.js +0 -0
- package/dist/sleep/tension-scan.js.map +1 -0
- package/dist/storage/backend.d.ts +12 -0
- package/dist/storage/backend.d.ts.map +1 -0
- package/dist/storage/backend.js +231 -0
- package/dist/storage/backend.js.map +1 -0
- package/dist/storage/backends/fs.d.ts +4 -0
- package/dist/storage/backends/fs.d.ts.map +1 -0
- package/dist/storage/backends/fs.js +99 -0
- package/dist/storage/backends/fs.js.map +1 -0
- package/dist/storage/fs-walk.d.ts +5 -0
- package/dist/storage/fs-walk.d.ts.map +1 -0
- package/dist/storage/fs-walk.js +28 -0
- package/dist/storage/fs-walk.js.map +1 -0
- package/dist/storage/index-db.d.ts +18 -0
- package/dist/storage/index-db.d.ts.map +1 -1
- package/dist/storage/index-db.js +159 -22
- package/dist/storage/index-db.js.map +1 -1
- package/dist/storage/local.d.ts +7 -1
- package/dist/storage/local.d.ts.map +1 -1
- package/dist/storage/local.js +42 -4
- package/dist/storage/local.js.map +1 -1
- package/dist/storage/sync.d.ts +25 -0
- package/dist/storage/sync.d.ts.map +1 -0
- package/dist/storage/sync.js +308 -0
- package/dist/storage/sync.js.map +1 -0
- package/dist/sync/index.d.ts +2 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +136 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/themes/clustering.d.ts +6 -11
- package/dist/themes/clustering.d.ts.map +1 -1
- package/dist/themes/clustering.js +76 -84
- package/dist/themes/clustering.js.map +1 -1
- package/dist/tools/consumes.d.ts +14 -0
- package/dist/tools/consumes.d.ts.map +1 -0
- package/dist/tools/consumes.js +99 -0
- package/dist/tools/consumes.js.map +1 -0
- package/dist/tools/curation.d.ts +2 -0
- package/dist/tools/curation.d.ts.map +1 -1
- package/dist/tools/curation.js +102 -7
- package/dist/tools/curation.js.map +1 -1
- package/dist/tools/edge-staleness.d.ts +28 -0
- package/dist/tools/edge-staleness.d.ts.map +1 -0
- package/dist/tools/edge-staleness.js +205 -0
- package/dist/tools/edge-staleness.js.map +1 -0
- package/dist/tools/edges.d.ts.map +1 -1
- package/dist/tools/edges.js +28 -22
- package/dist/tools/edges.js.map +1 -1
- package/dist/tools/read.d.ts +15 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +144 -31
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/receipt.d.ts +65 -0
- package/dist/tools/receipt.d.ts.map +1 -0
- package/dist/tools/receipt.js +257 -0
- package/dist/tools/receipt.js.map +1 -0
- package/dist/tools/search.d.ts +1 -0
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +186 -12
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/staged-actions.d.ts +3 -0
- package/dist/tools/staged-actions.d.ts.map +1 -1
- package/dist/tools/staged-actions.js +228 -23
- package/dist/tools/staged-actions.js.map +1 -1
- package/dist/tools/themes.d.ts +9 -0
- package/dist/tools/themes.d.ts.map +1 -1
- package/dist/tools/themes.js +333 -133
- package/dist/tools/themes.js.map +1 -1
- package/dist/tools/tier1.d.ts +14 -0
- package/dist/tools/tier1.d.ts.map +1 -0
- package/dist/tools/tier1.js +169 -0
- package/dist/tools/tier1.js.map +1 -0
- package/dist/tools/tier2.d.ts +27 -0
- package/dist/tools/tier2.d.ts.map +1 -0
- package/dist/tools/tier2.js +344 -0
- package/dist/tools/tier2.js.map +1 -0
- package/dist/tools/witness.d.ts +9 -0
- package/dist/tools/witness.d.ts.map +1 -0
- package/dist/tools/witness.js +66 -0
- package/dist/tools/witness.js.map +1 -0
- package/dist/tools/write.d.ts +9 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +593 -59
- package/dist/tools/write.js.map +1 -1
- package/dist/utils/config.d.ts +54 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +420 -4
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +15 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/redos.d.ts +2 -0
- package/dist/utils/redos.d.ts.map +1 -0
- package/dist/utils/redos.js +101 -0
- package/dist/utils/redos.js.map +1 -0
- package/dist/utils/run-id.d.ts +3 -0
- package/dist/utils/run-id.d.ts.map +1 -0
- package/dist/utils/run-id.js +19 -0
- package/dist/utils/run-id.js.map +1 -0
- package/dist/utils/vault-gitignore.d.ts +1 -1
- package/dist/utils/vault-gitignore.d.ts.map +1 -1
- package/dist/utils/vault-gitignore.js +6 -1
- package/dist/utils/vault-gitignore.js.map +1 -1
- package/dist/witness/track-record.d.ts +42 -0
- package/dist/witness/track-record.d.ts.map +1 -0
- package/dist/witness/track-record.js +189 -0
- package/dist/witness/track-record.js.map +1 -0
- package/package.json +27 -2
- package/templates/config.yaml +8 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
// The sync engine (#6, spec Decision 3): pushes the canonical local working
|
|
2
|
+
// copy — markdown tree, .git directory, and durable .daftari state — to a
|
|
3
|
+
// storage backend, and can restore a vault from that backing into an empty
|
|
4
|
+
// directory.
|
|
5
|
+
//
|
|
6
|
+
// Key namespace on the backend:
|
|
7
|
+
// tree/<vault-relative-path> file bytes
|
|
8
|
+
// meta/manifest.json what the backing currently holds
|
|
9
|
+
//
|
|
10
|
+
// The manifest (key → sha256) is the remote source of truth for diffing, so
|
|
11
|
+
// sync is stateless locally and incremental: only changed/new keys upload,
|
|
12
|
+
// removed keys delete. The manifest is written LAST — a crashed sync leaves
|
|
13
|
+
// it understating what was pushed, so the next run re-uploads at worst, never
|
|
14
|
+
// skips.
|
|
15
|
+
//
|
|
16
|
+
// What never syncs: the rebuildable SQLite databases (index.db, locks.db and
|
|
17
|
+
// their journals), the process lock, and transient per-cycle staging files.
|
|
18
|
+
// Durable-but-gitignored audit state (read-log, edges, provenance journals)
|
|
19
|
+
// DOES sync — unlike the index it cannot be rebuilt from the markdown.
|
|
20
|
+
//
|
|
21
|
+
// Concurrency note: sync reads the live tree without taking the process
|
|
22
|
+
// lock, so a write racing the walk can capture a torn snapshot (a ref
|
|
23
|
+
// updated mid-copy). That snapshot is repaired by the next run — acceptable
|
|
24
|
+
// for a backup channel, and the price of syncing while the server serves.
|
|
25
|
+
import { createHash } from "node:crypto";
|
|
26
|
+
import { createReadStream } from "node:fs";
|
|
27
|
+
import { mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
28
|
+
import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
29
|
+
import { err, ok } from "../frontmatter/types.js";
|
|
30
|
+
import { walkFiles } from "./fs-walk.js";
|
|
31
|
+
export const MANIFEST_KEY = "meta/manifest.json";
|
|
32
|
+
const TREE_PREFIX = "tree/";
|
|
33
|
+
const CONCURRENCY = 8;
|
|
34
|
+
// Rebuildable or transient files that must never reach the backing. Everything
|
|
35
|
+
// else under the vault root — including .git and the durable .daftari
|
|
36
|
+
// journals — is part of the backup.
|
|
37
|
+
const SYNC_EXCLUDED = new Set([
|
|
38
|
+
".daftari/process.lock",
|
|
39
|
+
".daftari/index.db",
|
|
40
|
+
".daftari/index.db-journal",
|
|
41
|
+
".daftari/index.db-wal",
|
|
42
|
+
".daftari/index.db-shm",
|
|
43
|
+
".daftari/locks.db",
|
|
44
|
+
".daftari/locks.db-journal",
|
|
45
|
+
".daftari/locks.db-wal",
|
|
46
|
+
".daftari/locks.db-shm",
|
|
47
|
+
".daftari/backfill-plan.jsonl",
|
|
48
|
+
".daftari/wake-queue.jsonl",
|
|
49
|
+
// Its own header calls it "ephemeral cross-session memory … rebuildable:
|
|
50
|
+
// absent OR corrupt ⇒ the empty default" — same class as the wake queue.
|
|
51
|
+
".daftari/consolidate-state.json",
|
|
52
|
+
]);
|
|
53
|
+
function isExcluded(relPath) {
|
|
54
|
+
if (SYNC_EXCLUDED.has(relPath))
|
|
55
|
+
return true;
|
|
56
|
+
// Git EXECUTES what these declare — filter/fsmonitor command lines in
|
|
57
|
+
// config, hook scripts in hooks/ — and a `git clone` deliberately never
|
|
58
|
+
// transmits them from a remote for exactly that reason. Carrying them
|
|
59
|
+
// through the backing would turn backend write access into code execution
|
|
60
|
+
// on the operator's next auto-commit, so they are excluded in BOTH
|
|
61
|
+
// directions; the restore side re-enforces this against a poisoned
|
|
62
|
+
// manifest. After a restore, remotes and local config are re-added by the
|
|
63
|
+
// operator.
|
|
64
|
+
if (relPath === ".git/config" || relPath.startsWith(".git/hooks/"))
|
|
65
|
+
return true;
|
|
66
|
+
// Defensive: a vault should never contain one, but never ship it if it does.
|
|
67
|
+
return relPath.split("/").includes("node_modules");
|
|
68
|
+
}
|
|
69
|
+
// Streaming hash so the walk phase never buffers a whole file — .git is in
|
|
70
|
+
// scope now, and packfiles can dwarf the markdown they version.
|
|
71
|
+
function streamHash(abs) {
|
|
72
|
+
return new Promise((resolveHash, rejectHash) => {
|
|
73
|
+
const digest = createHash("sha256");
|
|
74
|
+
let size = 0;
|
|
75
|
+
const stream = createReadStream(abs);
|
|
76
|
+
stream.on("data", (chunk) => {
|
|
77
|
+
digest.update(chunk);
|
|
78
|
+
size += chunk.length;
|
|
79
|
+
});
|
|
80
|
+
stream.on("error", rejectHash);
|
|
81
|
+
stream.on("end", () => resolveHash({ hash: digest.digest("hex"), size }));
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
// (size, mtime) → hash memo so a periodic sync (`daftari serve`, every N
|
|
85
|
+
// minutes) re-hashes only what actually changed instead of streaming the
|
|
86
|
+
// whole tree — with .git in scope, full-history rehash every tick scales
|
|
87
|
+
// with repo size, not the delta. In-memory on purpose: it lives exactly as
|
|
88
|
+
// long as the serving process, needs no invalidation story across
|
|
89
|
+
// processes, and a one-shot CLI run simply pays the honest full cost.
|
|
90
|
+
const hashMemo = new Map();
|
|
91
|
+
async function hashFile(abs) {
|
|
92
|
+
const s = await stat(abs);
|
|
93
|
+
const memo = hashMemo.get(abs);
|
|
94
|
+
if (memo && memo.size === s.size && memo.mtimeMs === s.mtimeMs) {
|
|
95
|
+
return { hash: memo.hash, size: memo.size };
|
|
96
|
+
}
|
|
97
|
+
const hashed = await streamHash(abs);
|
|
98
|
+
hashMemo.set(abs, { size: hashed.size, mtimeMs: s.mtimeMs, hash: hashed.hash });
|
|
99
|
+
return hashed;
|
|
100
|
+
}
|
|
101
|
+
// Walks the vault tree (dotfiles included — .git is the point), hashing every
|
|
102
|
+
// non-excluded regular file. Symlinks are skipped and counted: an object
|
|
103
|
+
// store has no symlink notion, and following one could escape the vault.
|
|
104
|
+
async function collectLocalState(vaultRoot) {
|
|
105
|
+
const root = resolve(vaultRoot);
|
|
106
|
+
try {
|
|
107
|
+
const walked = await walkFiles(root);
|
|
108
|
+
const candidates = walked.files
|
|
109
|
+
.map((abs) => ({ abs, rel: relative(root, abs).split(sep).join("/") }))
|
|
110
|
+
.filter((c) => !isExcluded(c.rel));
|
|
111
|
+
// Evict memo entries for files that no longer exist under THIS root —
|
|
112
|
+
// without it the memo grows with total churn (git gc repacks, deletes),
|
|
113
|
+
// not live tree size. Scoped to the root so one process syncing several
|
|
114
|
+
// vaults never evicts another vault's entries.
|
|
115
|
+
const live = new Set(candidates.map((c) => c.abs));
|
|
116
|
+
const rootPrefix = root + sep;
|
|
117
|
+
for (const key of hashMemo.keys()) {
|
|
118
|
+
if (key.startsWith(rootPrefix) && !live.has(key))
|
|
119
|
+
hashMemo.delete(key);
|
|
120
|
+
}
|
|
121
|
+
// Hash with the same bounded pool the upload phase uses — the walk now
|
|
122
|
+
// covers .git, and serializing on disk I/O for packfiles wastes time.
|
|
123
|
+
const files = new Array(candidates.length);
|
|
124
|
+
const hashed = await runPool(candidates.map((c, i) => async () => {
|
|
125
|
+
try {
|
|
126
|
+
const { hash, size } = await hashFile(c.abs);
|
|
127
|
+
files[i] = { relPath: c.rel, absPath: c.abs, hash, size };
|
|
128
|
+
return ok(undefined);
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
return err(new Error(`cannot hash ${c.rel}: ${e instanceof Error ? e.message : String(e)}`));
|
|
132
|
+
}
|
|
133
|
+
}));
|
|
134
|
+
if (!hashed.ok)
|
|
135
|
+
return hashed;
|
|
136
|
+
return ok({ files, skippedSymlinks: walked.symlinks });
|
|
137
|
+
}
|
|
138
|
+
catch (e) {
|
|
139
|
+
return err(new Error(`cannot walk vault: ${e instanceof Error ? e.message : String(e)}`));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function readManifest(backend) {
|
|
143
|
+
const raw = await backend.get(MANIFEST_KEY);
|
|
144
|
+
if (!raw.ok)
|
|
145
|
+
return raw;
|
|
146
|
+
if (raw.value === null)
|
|
147
|
+
return ok({ version: 1, files: {} });
|
|
148
|
+
try {
|
|
149
|
+
const parsed = JSON.parse(raw.value.toString("utf-8"));
|
|
150
|
+
if (parsed.version !== 1 || typeof parsed.files !== "object" || parsed.files === null) {
|
|
151
|
+
return err(new Error(`backing manifest at ${MANIFEST_KEY} has an unknown shape`));
|
|
152
|
+
}
|
|
153
|
+
// Null prototype so a file literally named __proto__ (possible in a git
|
|
154
|
+
// object dir? no — but in the tree, yes) round-trips as an own key.
|
|
155
|
+
const files = Object.create(null);
|
|
156
|
+
for (const [k, v] of Object.entries(parsed.files)) {
|
|
157
|
+
if (typeof v === "string")
|
|
158
|
+
files[k] = v;
|
|
159
|
+
}
|
|
160
|
+
return ok({ version: 1, files });
|
|
161
|
+
}
|
|
162
|
+
catch (e) {
|
|
163
|
+
return err(new Error(`backing manifest is not valid JSON: ${e instanceof Error ? e.message : String(e)}`));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Runs `tasks` with a bounded worker pool, stopping at the first error.
|
|
167
|
+
async function runPool(tasks) {
|
|
168
|
+
let index = 0;
|
|
169
|
+
let failure = null;
|
|
170
|
+
async function worker() {
|
|
171
|
+
while (failure === null) {
|
|
172
|
+
const i = index++;
|
|
173
|
+
const task = tasks[i];
|
|
174
|
+
if (!task)
|
|
175
|
+
return;
|
|
176
|
+
const res = await task();
|
|
177
|
+
if (!res.ok && failure === null)
|
|
178
|
+
failure = res.error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
await Promise.all(Array.from({ length: Math.min(CONCURRENCY, tasks.length) }, worker));
|
|
182
|
+
return failure ? err(failure) : ok(undefined);
|
|
183
|
+
}
|
|
184
|
+
// Push the working copy to the backend. Incremental against the remote
|
|
185
|
+
// manifest; writes the updated manifest last.
|
|
186
|
+
export async function syncVault(vaultRoot, backend, options = {}) {
|
|
187
|
+
const local = await collectLocalState(vaultRoot);
|
|
188
|
+
if (!local.ok)
|
|
189
|
+
return local;
|
|
190
|
+
const manifest = await readManifest(backend);
|
|
191
|
+
if (!manifest.ok)
|
|
192
|
+
return manifest;
|
|
193
|
+
const remote = manifest.value.files;
|
|
194
|
+
const localByPath = new Map(local.value.files.map((f) => [f.relPath, f]));
|
|
195
|
+
const toUpload = local.value.files.filter((f) => remote[f.relPath] !== f.hash);
|
|
196
|
+
const toDelete = Object.keys(remote).filter((relPath) => !localByPath.has(relPath));
|
|
197
|
+
const unchanged = local.value.files.length - toUpload.length;
|
|
198
|
+
const summary = {
|
|
199
|
+
uploaded: toUpload.length,
|
|
200
|
+
deleted: toDelete.length,
|
|
201
|
+
unchanged,
|
|
202
|
+
skippedSymlinks: local.value.skippedSymlinks,
|
|
203
|
+
bytesUploaded: toUpload.reduce((n, f) => n + f.size, 0),
|
|
204
|
+
};
|
|
205
|
+
if (options.dryRun)
|
|
206
|
+
return ok(summary);
|
|
207
|
+
const uploads = toUpload.map((f) => async () => {
|
|
208
|
+
// Re-read at upload time: the hash was computed during the walk and the
|
|
209
|
+
// manifest must describe the bytes actually pushed, so hash what we send.
|
|
210
|
+
let bytes;
|
|
211
|
+
try {
|
|
212
|
+
bytes = await readFile(f.absPath);
|
|
213
|
+
}
|
|
214
|
+
catch (e) {
|
|
215
|
+
return err(new Error(`cannot read ${f.relPath}: ${e instanceof Error ? e.message : String(e)}`));
|
|
216
|
+
}
|
|
217
|
+
f.hash = createHash("sha256").update(bytes).digest("hex");
|
|
218
|
+
f.size = bytes.byteLength;
|
|
219
|
+
return backend.put(TREE_PREFIX + f.relPath, bytes);
|
|
220
|
+
});
|
|
221
|
+
const uploaded = await runPool(uploads);
|
|
222
|
+
if (!uploaded.ok)
|
|
223
|
+
return uploaded;
|
|
224
|
+
const deletes = toDelete.map((relPath) => () => backend.delete(TREE_PREFIX + relPath));
|
|
225
|
+
const deleted = await runPool(deletes);
|
|
226
|
+
if (!deleted.ok)
|
|
227
|
+
return deleted;
|
|
228
|
+
const nextManifest = { version: 1, files: {} };
|
|
229
|
+
const nextFiles = Object.create(null);
|
|
230
|
+
for (const f of local.value.files)
|
|
231
|
+
nextFiles[f.relPath] = f.hash;
|
|
232
|
+
nextManifest.files = nextFiles;
|
|
233
|
+
const wrote = await backend.put(MANIFEST_KEY, Buffer.from(JSON.stringify(nextManifest, null, 2), "utf-8"));
|
|
234
|
+
if (!wrote.ok)
|
|
235
|
+
return wrote;
|
|
236
|
+
return ok(summary);
|
|
237
|
+
}
|
|
238
|
+
// Restore a vault from the backing into `vaultRoot`, which must be empty or
|
|
239
|
+
// absent — restore never merges into or overwrites live state. After a
|
|
240
|
+
// restore the caller reindexes (the index was deliberately never synced).
|
|
241
|
+
export async function restoreVault(vaultRoot, backend) {
|
|
242
|
+
const root = resolve(vaultRoot);
|
|
243
|
+
try {
|
|
244
|
+
const existing = await readdir(root);
|
|
245
|
+
if (existing.length > 0) {
|
|
246
|
+
return err(new Error(`refusing to restore into non-empty directory: ${root}`));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
catch (e) {
|
|
250
|
+
if (e.code !== "ENOENT") {
|
|
251
|
+
return err(new Error(`cannot inspect ${root}: ${e instanceof Error ? e.message : String(e)}`));
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const manifest = await readManifest(backend);
|
|
255
|
+
if (!manifest.ok)
|
|
256
|
+
return manifest;
|
|
257
|
+
// The manifest is data from the backing, not trusted input: re-apply the
|
|
258
|
+
// exclusion rules here so a poisoned manifest cannot smuggle in what push
|
|
259
|
+
// would never have uploaded (git config/hooks — code execution on the
|
|
260
|
+
// next auto-commit).
|
|
261
|
+
const allPaths = Object.keys(manifest.value.files);
|
|
262
|
+
const paths = allPaths.filter((p) => !isExcluded(p));
|
|
263
|
+
const skippedExcluded = allPaths.length - paths.length;
|
|
264
|
+
if (allPaths.length === 0) {
|
|
265
|
+
return err(new Error(`backing at ${backend.id} holds no manifest — nothing to restore`));
|
|
266
|
+
}
|
|
267
|
+
let bytesTotal = 0;
|
|
268
|
+
const tasks = paths.map((relPath) => async () => {
|
|
269
|
+
// Confine each manifest path to the restore root — the manifest is data
|
|
270
|
+
// from the backing, not trusted input.
|
|
271
|
+
const target = resolve(root, relPath);
|
|
272
|
+
const rel = relative(root, target);
|
|
273
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
|
|
274
|
+
return err(new Error(`manifest path escapes restore root: ${relPath}`));
|
|
275
|
+
}
|
|
276
|
+
const got = await backend.get(TREE_PREFIX + relPath);
|
|
277
|
+
if (!got.ok)
|
|
278
|
+
return got;
|
|
279
|
+
if (got.value === null) {
|
|
280
|
+
return err(new Error(`backing is missing ${TREE_PREFIX}${relPath} listed in its manifest`));
|
|
281
|
+
}
|
|
282
|
+
// Verify the bytes against the manifest's hash — that is what the hash
|
|
283
|
+
// is FOR. This catches corruption, torn writes, and a push racing the
|
|
284
|
+
// restore; it is not a tamper defense (an attacker who can rewrite
|
|
285
|
+
// objects can rewrite the manifest too).
|
|
286
|
+
const gotHash = createHash("sha256").update(got.value).digest("hex");
|
|
287
|
+
const wantHash = manifest.value.files[relPath];
|
|
288
|
+
if (gotHash !== wantHash) {
|
|
289
|
+
return err(new Error(`backing object ${TREE_PREFIX}${relPath} does not match its manifest hash ` +
|
|
290
|
+
`(got ${gotHash.slice(0, 12)}…, manifest says ${wantHash?.slice(0, 12)}…) — ` +
|
|
291
|
+
"the backing is corrupt or a push is racing this restore"));
|
|
292
|
+
}
|
|
293
|
+
try {
|
|
294
|
+
await mkdir(dirname(target), { recursive: true });
|
|
295
|
+
await writeFile(target, got.value);
|
|
296
|
+
}
|
|
297
|
+
catch (e) {
|
|
298
|
+
return err(new Error(`cannot write ${relPath}: ${e instanceof Error ? e.message : String(e)}`));
|
|
299
|
+
}
|
|
300
|
+
bytesTotal += got.value.byteLength;
|
|
301
|
+
return ok(undefined);
|
|
302
|
+
});
|
|
303
|
+
const ran = await runPool(tasks);
|
|
304
|
+
if (!ran.ok)
|
|
305
|
+
return ran;
|
|
306
|
+
return ok({ restored: paths.length, bytes: bytesTotal, skippedExcluded });
|
|
307
|
+
}
|
|
308
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/storage/sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AA8BA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAwD7D"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// `daftari sync` (#6): push the canonical local vault to its configured
|
|
2
|
+
// storage backing, or restore a vault from the backing into an empty
|
|
3
|
+
// directory. The backing is configured in .daftari/config.yaml (`storage`
|
|
4
|
+
// block); credentials come from the SDKs' standard environment chains.
|
|
5
|
+
import { parseFlag } from "../index.js";
|
|
6
|
+
import { reindexVault, reindexWarnings } from "../search/reindex.js";
|
|
7
|
+
import { createBackend } from "../storage/backend.js";
|
|
8
|
+
import { restoreVault, syncVault } from "../storage/sync.js";
|
|
9
|
+
import { loadConfig } from "../utils/config.js";
|
|
10
|
+
const USAGE = `daftari sync — push a vault to its storage backing, or restore from it.
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
daftari sync --vault <path> [--dry-run] Push the working copy to the backing
|
|
14
|
+
daftari sync --vault <path> --restore Restore into an EMPTY directory, then reindex
|
|
15
|
+
|
|
16
|
+
The backing is the \`storage\` block in .daftari/config.yaml (backends: fs,
|
|
17
|
+
s3 — including MinIO/R2/GCS-interop endpoints — and azure). The local git
|
|
18
|
+
working copy is canonical; the backing is durable backing, not a second
|
|
19
|
+
source of truth. The SQLite index and lock files are never synced. A restore
|
|
20
|
+
has no local config to read yet, so the backing is named with flags using
|
|
21
|
+
the config block's names (--backend s3 --bucket team-vault [--prefix …]).
|
|
22
|
+
|
|
23
|
+
Push reads the live tree without stopping a running server; a write racing
|
|
24
|
+
the walk is repaired by the next sync.
|
|
25
|
+
|
|
26
|
+
Exit codes: 2 config/usage error, 3 runtime error.
|
|
27
|
+
`;
|
|
28
|
+
export async function runSync(argv) {
|
|
29
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
30
|
+
process.stdout.write(USAGE);
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
const vault = parseFlag(argv, "vault");
|
|
34
|
+
if (!vault) {
|
|
35
|
+
process.stderr.write("daftari sync: --vault <path> is required\n\n");
|
|
36
|
+
process.stderr.write(USAGE);
|
|
37
|
+
return 2;
|
|
38
|
+
}
|
|
39
|
+
const restore = argv.includes("--restore");
|
|
40
|
+
const dryRun = argv.includes("--dry-run");
|
|
41
|
+
if (restore && dryRun) {
|
|
42
|
+
process.stderr.write("daftari sync: --restore and --dry-run cannot be combined\n");
|
|
43
|
+
return 2;
|
|
44
|
+
}
|
|
45
|
+
if (restore) {
|
|
46
|
+
return runRestore(vault, argv);
|
|
47
|
+
}
|
|
48
|
+
const config = loadConfig(vault);
|
|
49
|
+
if (!config.ok) {
|
|
50
|
+
process.stderr.write(`daftari sync: ${config.error.message}\n`);
|
|
51
|
+
return 2;
|
|
52
|
+
}
|
|
53
|
+
if (!config.value.storage) {
|
|
54
|
+
process.stderr.write("daftari sync: no storage backing configured — add a `storage` block " +
|
|
55
|
+
"to .daftari/config.yaml (see README: Storage backing)\n");
|
|
56
|
+
return 2;
|
|
57
|
+
}
|
|
58
|
+
const backend = await createBackend(config.value.storage);
|
|
59
|
+
if (!backend.ok) {
|
|
60
|
+
process.stderr.write(`daftari sync: ${backend.error.message}\n`);
|
|
61
|
+
return 2;
|
|
62
|
+
}
|
|
63
|
+
const result = await syncVault(vault, backend.value, { dryRun });
|
|
64
|
+
if (!result.ok) {
|
|
65
|
+
process.stderr.write(`daftari sync: ${result.error.message}\n`);
|
|
66
|
+
return 3;
|
|
67
|
+
}
|
|
68
|
+
const s = result.value;
|
|
69
|
+
process.stdout.write(`${dryRun ? "[dry-run] would push" : "pushed"} to ${backend.value.id}: ` +
|
|
70
|
+
`${s.uploaded} uploaded (${s.bytesUploaded} bytes), ${s.deleted} deleted, ` +
|
|
71
|
+
`${s.unchanged} unchanged` +
|
|
72
|
+
(s.skippedSymlinks > 0 ? `, ${s.skippedSymlinks} symlink(s) skipped` : "") +
|
|
73
|
+
"\n");
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
// Restore cannot read the vault's config (the vault does not exist yet), so
|
|
77
|
+
// the backing is described on the command line with the same names as the
|
|
78
|
+
// config block.
|
|
79
|
+
async function runRestore(vault, argv) {
|
|
80
|
+
const backendName = parseFlag(argv, "backend");
|
|
81
|
+
if (!backendName || !["fs", "s3", "azure"].includes(backendName)) {
|
|
82
|
+
process.stderr.write("daftari sync --restore: --backend <fs|s3|azure> is required " +
|
|
83
|
+
"(plus its target flag: --path, --bucket, or --container)\n");
|
|
84
|
+
return 2;
|
|
85
|
+
}
|
|
86
|
+
const storage = {
|
|
87
|
+
backend: backendName,
|
|
88
|
+
path: parseFlag(argv, "path") ?? undefined,
|
|
89
|
+
bucket: parseFlag(argv, "bucket") ?? undefined,
|
|
90
|
+
container: parseFlag(argv, "container") ?? undefined,
|
|
91
|
+
prefix: parseFlag(argv, "prefix") ?? undefined,
|
|
92
|
+
region: parseFlag(argv, "region") ?? undefined,
|
|
93
|
+
endpoint: parseFlag(argv, "endpoint") ?? undefined,
|
|
94
|
+
forcePathStyle: argv.includes("--force-path-style") ? true : undefined,
|
|
95
|
+
};
|
|
96
|
+
const required = { fs: "path", s3: "bucket", azure: "container" }[storage.backend];
|
|
97
|
+
if (!storage[required]) {
|
|
98
|
+
process.stderr.write(`daftari sync --restore: --${required} is required for ${storage.backend}\n`);
|
|
99
|
+
return 2;
|
|
100
|
+
}
|
|
101
|
+
const backend = await createBackend(storage);
|
|
102
|
+
if (!backend.ok) {
|
|
103
|
+
process.stderr.write(`daftari sync: ${backend.error.message}\n`);
|
|
104
|
+
return 2;
|
|
105
|
+
}
|
|
106
|
+
const restored = await restoreVault(vault, backend.value);
|
|
107
|
+
if (!restored.ok) {
|
|
108
|
+
process.stderr.write(`daftari sync: ${restored.error.message}\n`);
|
|
109
|
+
return 3;
|
|
110
|
+
}
|
|
111
|
+
process.stdout.write(`restored ${restored.value.restored} files (${restored.value.bytes} bytes) ` +
|
|
112
|
+
`from ${backend.value.id} into ${vault}\n`);
|
|
113
|
+
if (restored.value.skippedExcluded > 0) {
|
|
114
|
+
process.stderr.write(`daftari sync: warning: ${restored.value.skippedExcluded} manifest entr(ies) refused by ` +
|
|
115
|
+
"the exclusion rules (git config/hooks or rebuildable state) — the backing was " +
|
|
116
|
+
"written by something other than daftari sync\n");
|
|
117
|
+
}
|
|
118
|
+
process.stderr.write("daftari sync: note: git config and hooks are never synced or restored " +
|
|
119
|
+
"(git executes them; a backup channel must not deliver code) — re-add " +
|
|
120
|
+
"remotes and local git config by hand\n");
|
|
121
|
+
// The index was deliberately never synced — rebuild it so the restored
|
|
122
|
+
// vault is immediately servable.
|
|
123
|
+
const indexed = await reindexVault(vault);
|
|
124
|
+
if (indexed.ok) {
|
|
125
|
+
process.stdout.write(`reindexed ${indexed.value.documentCount} docs\n`);
|
|
126
|
+
for (const line of reindexWarnings(indexed.value)) {
|
|
127
|
+
process.stderr.write(`daftari sync: warning: ${line}\n`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
process.stderr.write(`daftari sync: warning: reindex after restore failed: ${indexed.error.message}\n` +
|
|
132
|
+
" run `daftari --vault <path> --reindex` before serving\n");
|
|
133
|
+
}
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export declare function seededRng(seed: number): () => number;
|
|
2
2
|
export declare function l2Normalize(vec: Float32Array): Float32Array;
|
|
3
|
-
export declare function meanPoolL2(vectors: Float32Array[]): Float32Array | null;
|
|
4
3
|
export declare function kmeansPlusPlusInit(data: Float32Array[], k: number, rng: () => number): number[];
|
|
5
4
|
export interface KMeansResult {
|
|
6
5
|
assignments: number[];
|
|
@@ -16,15 +15,11 @@ export interface PickKResult {
|
|
|
16
15
|
assignments: number[];
|
|
17
16
|
centroids: Float32Array[];
|
|
18
17
|
}
|
|
19
|
-
export declare function
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
export declare function strideSample(n: number, cap: number): number[];
|
|
19
|
+
export declare function pickK(data: Float32Array[], candidates: number[], rng: () => number, maxIter: number, silhouetteCap?: number): PickKResult;
|
|
20
|
+
export interface DocMembership {
|
|
21
|
+
cluster: number;
|
|
22
|
+
weight: number;
|
|
23
23
|
}
|
|
24
|
-
export
|
|
25
|
-
delta: number;
|
|
26
|
-
minSimilarity: number;
|
|
27
|
-
maxPerDoc: number;
|
|
28
|
-
}
|
|
29
|
-
export declare function selectSecondaryMemberships(vectors: Float32Array[], assignments: number[], centroids: Float32Array[], options: SecondaryOptions): Map<number, SecondaryMembership[]>;
|
|
24
|
+
export declare function membershipDistributions(chunkAssignments: number[], chunkDoc: number[], docCount: number, minFraction: number): DocMembership[][];
|
|
30
25
|
//# sourceMappingURL=clustering.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clustering.d.ts","sourceRoot":"","sources":["../../src/themes/clustering.ts"],"names":[],"mappings":"AAwBA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,MAAM,CASpD;AAMD,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,CAa3D;
|
|
1
|
+
{"version":3,"file":"clustering.d.ts","sourceRoot":"","sources":["../../src/themes/clustering.ts"],"names":[],"mappings":"AAwBA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,MAAM,CASpD;AAMD,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,CAa3D;AAoCD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,MAAM,GAAG,MAAM,EAAE,CAoE/F;AAID,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAgB,MAAM,CACpB,IAAI,EAAE,YAAY,EAAE,EACpB,CAAC,EAAE,MAAM,EACT,GAAG,EAAE,MAAM,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,YAAY,CAkFd;AAUD,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CA6CnF;AAQD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAahE;AAID,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAMD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAO7D;AAaD,wBAAgB,KAAK,CACnB,IAAI,EAAE,YAAY,EAAE,EACpB,UAAU,EAAE,MAAM,EAAE,EACpB,GAAG,EAAE,MAAM,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,MAAM,GACrB,WAAW,CA8Bb;AAOD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAgBD,wBAAgB,uBAAuB,CACrC,gBAAgB,EAAE,MAAM,EAAE,EAC1B,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,aAAa,EAAE,EAAE,CA2CnB"}
|