stellavault 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/core/dist/api/dashboard.d.ts +3 -0
- package/packages/core/{src/api/dashboard.ts → dist/api/dashboard.js} +8 -11
- package/packages/core/dist/api/graph-data.d.ts +11 -0
- package/packages/core/dist/api/graph-data.js +255 -0
- package/packages/core/dist/api/pwa.d.ts +3 -0
- package/packages/core/{src/api/pwa.ts → dist/api/pwa.js} +27 -32
- package/packages/core/dist/api/server.d.ts +16 -0
- package/packages/core/dist/api/server.js +647 -0
- package/packages/core/dist/capture/voice.d.ts +24 -0
- package/packages/core/dist/capture/voice.js +135 -0
- package/packages/core/{src/cloud/index.ts → dist/cloud/index.d.ts} +1 -0
- package/packages/core/dist/cloud/index.js +2 -0
- package/packages/core/dist/cloud/sync.d.ts +29 -0
- package/packages/core/dist/cloud/sync.js +137 -0
- package/packages/core/dist/config.d.ts +27 -0
- package/packages/core/dist/config.js +55 -0
- package/packages/core/dist/federation/credits.d.ts +26 -0
- package/packages/core/dist/federation/credits.js +56 -0
- package/packages/core/dist/federation/identity.d.ts +14 -0
- package/packages/core/dist/federation/identity.js +74 -0
- package/packages/core/{src/federation/index.ts → dist/federation/index.d.ts} +1 -2
- package/packages/core/dist/federation/index.js +5 -0
- package/packages/core/dist/federation/node.d.ts +31 -0
- package/packages/core/dist/federation/node.js +216 -0
- package/packages/core/dist/federation/privacy.d.ts +8 -0
- package/packages/core/dist/federation/privacy.js +40 -0
- package/packages/core/dist/federation/reputation.d.ts +37 -0
- package/packages/core/dist/federation/reputation.js +139 -0
- package/packages/core/dist/federation/search.d.ts +19 -0
- package/packages/core/dist/federation/search.js +101 -0
- package/packages/core/dist/federation/sharing.d.ts +72 -0
- package/packages/core/dist/federation/sharing.js +246 -0
- package/packages/core/dist/federation/trust.d.ts +15 -0
- package/packages/core/dist/federation/trust.js +60 -0
- package/packages/core/dist/federation/types.d.ts +40 -0
- package/packages/core/dist/federation/types.js +3 -0
- package/packages/core/dist/i18n/index.d.ts +6 -0
- package/packages/core/dist/i18n/index.js +81 -0
- package/packages/core/{src/index.ts → dist/index.d.ts} +46 -65
- package/packages/core/dist/index.js +69 -0
- package/packages/core/dist/indexer/chunker.d.ts +14 -0
- package/packages/core/dist/indexer/chunker.js +148 -0
- package/packages/core/dist/indexer/embedder.d.ts +8 -0
- package/packages/core/dist/indexer/embedder.js +3 -0
- package/packages/core/dist/indexer/index.d.ts +28 -0
- package/packages/core/dist/indexer/index.js +74 -0
- package/packages/core/dist/indexer/local-embedder.d.ts +3 -0
- package/packages/core/dist/indexer/local-embedder.js +29 -0
- package/packages/core/dist/indexer/scanner.d.ts +11 -0
- package/packages/core/dist/indexer/scanner.js +137 -0
- package/packages/core/dist/indexer/watcher.d.ts +19 -0
- package/packages/core/dist/indexer/watcher.js +49 -0
- package/packages/core/dist/intelligence/contradiction-detector.d.ts +20 -0
- package/packages/core/dist/intelligence/contradiction-detector.js +115 -0
- package/packages/core/dist/intelligence/decay-engine.d.ts +27 -0
- package/packages/core/dist/intelligence/decay-engine.js +190 -0
- package/packages/core/dist/intelligence/duplicate-detector.d.ts +20 -0
- package/packages/core/dist/intelligence/duplicate-detector.js +55 -0
- package/packages/core/dist/intelligence/fsrs.d.ts +43 -0
- package/packages/core/dist/intelligence/fsrs.js +70 -0
- package/packages/core/dist/intelligence/gap-detector.d.ts +25 -0
- package/packages/core/dist/intelligence/gap-detector.js +78 -0
- package/packages/core/dist/intelligence/learning-path.d.ts +31 -0
- package/packages/core/dist/intelligence/learning-path.js +53 -0
- package/packages/core/dist/intelligence/notifications.d.ts +31 -0
- package/packages/core/dist/intelligence/notifications.js +65 -0
- package/packages/core/dist/intelligence/predictive-gaps.d.ts +14 -0
- package/packages/core/dist/intelligence/predictive-gaps.js +74 -0
- package/packages/core/dist/intelligence/semantic-versioning.d.ts +37 -0
- package/packages/core/dist/intelligence/semantic-versioning.js +68 -0
- package/packages/core/dist/intelligence/types.d.ts +28 -0
- package/packages/core/dist/intelligence/types.js +3 -0
- package/packages/core/dist/mcp/custom-tools.d.ts +29 -0
- package/packages/core/dist/mcp/custom-tools.js +70 -0
- package/packages/core/{src/mcp/index.ts → dist/mcp/index.d.ts} +1 -0
- package/packages/core/dist/mcp/index.js +2 -0
- package/packages/core/dist/mcp/server.d.ts +49 -0
- package/packages/core/dist/mcp/server.js +133 -0
- package/packages/core/dist/mcp/tools/agentic-graph.d.ts +87 -0
- package/packages/core/dist/mcp/tools/agentic-graph.js +88 -0
- package/packages/core/dist/mcp/tools/brief.d.ts +31 -0
- package/packages/core/dist/mcp/tools/brief.js +39 -0
- package/packages/core/dist/mcp/tools/decay.d.ts +33 -0
- package/packages/core/dist/mcp/tools/decay.js +32 -0
- package/packages/core/dist/mcp/tools/decision-journal.d.ts +78 -0
- package/packages/core/dist/mcp/tools/decision-journal.js +79 -0
- package/packages/core/dist/mcp/tools/export.d.ts +29 -0
- package/packages/core/dist/mcp/tools/export.js +60 -0
- package/packages/core/dist/mcp/tools/federated-search.d.ts +29 -0
- package/packages/core/dist/mcp/tools/federated-search.js +36 -0
- package/packages/core/dist/mcp/tools/generate-claude-md.d.ts +35 -0
- package/packages/core/dist/mcp/tools/generate-claude-md.js +107 -0
- package/packages/core/dist/mcp/tools/get-document.d.ts +35 -0
- package/packages/core/dist/mcp/tools/get-document.js +25 -0
- package/packages/core/dist/mcp/tools/get-related.d.ts +32 -0
- package/packages/core/dist/mcp/tools/get-related.js +33 -0
- package/packages/core/dist/mcp/tools/learning-path.d.ts +23 -0
- package/packages/core/dist/mcp/tools/learning-path.js +45 -0
- package/packages/core/dist/mcp/tools/list-topics.d.ts +15 -0
- package/packages/core/dist/mcp/tools/list-topics.js +18 -0
- package/packages/core/dist/mcp/tools/search.d.ts +39 -0
- package/packages/core/dist/mcp/tools/search.js +29 -0
- package/packages/core/dist/mcp/tools/snapshot.d.ts +47 -0
- package/packages/core/dist/mcp/tools/snapshot.js +84 -0
- package/packages/core/dist/multi-vault/index.d.ts +26 -0
- package/packages/core/dist/multi-vault/index.js +80 -0
- package/packages/core/dist/pack/creator.d.ts +21 -0
- package/packages/core/dist/pack/creator.js +105 -0
- package/packages/core/dist/pack/exporter.d.ts +4 -0
- package/packages/core/dist/pack/exporter.js +18 -0
- package/packages/core/dist/pack/importer.d.ts +10 -0
- package/packages/core/dist/pack/importer.js +55 -0
- package/packages/core/{src/pack/index.ts → dist/pack/index.d.ts} +1 -0
- package/packages/core/dist/pack/index.js +5 -0
- package/packages/core/dist/pack/marketplace.d.ts +14 -0
- package/packages/core/dist/pack/marketplace.js +90 -0
- package/packages/core/dist/pack/pii-masker.d.ts +7 -0
- package/packages/core/dist/pack/pii-masker.js +29 -0
- package/packages/core/dist/pack/types.d.ts +36 -0
- package/packages/core/dist/pack/types.js +3 -0
- package/packages/core/dist/plugins/index.d.ts +35 -0
- package/packages/core/dist/plugins/index.js +57 -0
- package/packages/core/dist/plugins/webhooks.d.ts +30 -0
- package/packages/core/dist/plugins/webhooks.js +79 -0
- package/packages/core/dist/search/bm25.d.ts +4 -0
- package/packages/core/dist/search/bm25.js +10 -0
- package/packages/core/dist/search/index.d.ts +13 -0
- package/packages/core/dist/search/index.js +63 -0
- package/packages/core/dist/search/rrf.d.ts +7 -0
- package/packages/core/dist/search/rrf.js +21 -0
- package/packages/core/dist/search/semantic.d.ts +5 -0
- package/packages/core/dist/search/semantic.js +6 -0
- package/packages/core/{src/store/index.ts → dist/store/index.d.ts} +1 -0
- package/packages/core/dist/store/index.js +2 -0
- package/packages/core/dist/store/sqlite-vec.d.ts +6 -0
- package/packages/core/dist/store/sqlite-vec.js +251 -0
- package/packages/core/dist/store/types.d.ts +20 -0
- package/packages/core/dist/store/types.js +3 -0
- package/packages/core/dist/team/index.d.ts +25 -0
- package/packages/core/dist/team/index.js +97 -0
- package/packages/core/dist/types/chunk.d.ts +23 -0
- package/packages/core/dist/types/chunk.js +3 -0
- package/packages/core/dist/types/document.d.ts +23 -0
- package/packages/core/dist/types/document.js +3 -0
- package/packages/core/dist/types/graph.d.ts +39 -0
- package/packages/core/dist/types/graph.js +3 -0
- package/packages/core/dist/types/index.d.ts +5 -0
- package/packages/core/dist/types/index.js +2 -0
- package/packages/core/dist/types/search.d.ts +39 -0
- package/packages/core/dist/types/search.js +3 -0
- package/packages/core/dist/utils/retry.d.ts +25 -0
- package/packages/core/dist/utils/retry.js +59 -0
- package/.github/workflows/pages.yml +0 -37
- package/memory/MEMORY.md +0 -25
- package/packages/cli/dist/commands/brief-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/brief-cmd.js.map +0 -1
- package/packages/cli/dist/commands/capture-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/capture-cmd.js.map +0 -1
- package/packages/cli/dist/commands/card-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/card-cmd.js.map +0 -1
- package/packages/cli/dist/commands/clip-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/clip-cmd.js.map +0 -1
- package/packages/cli/dist/commands/cloud-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/cloud-cmd.js.map +0 -1
- package/packages/cli/dist/commands/contradictions-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/contradictions-cmd.js.map +0 -1
- package/packages/cli/dist/commands/decay-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/decay-cmd.js.map +0 -1
- package/packages/cli/dist/commands/digest-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/digest-cmd.js.map +0 -1
- package/packages/cli/dist/commands/duplicates-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/duplicates-cmd.js.map +0 -1
- package/packages/cli/dist/commands/federate-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/federate-cmd.js.map +0 -1
- package/packages/cli/dist/commands/gaps-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/gaps-cmd.js.map +0 -1
- package/packages/cli/dist/commands/graph-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/graph-cmd.js.map +0 -1
- package/packages/cli/dist/commands/index-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/index-cmd.js.map +0 -1
- package/packages/cli/dist/commands/init-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/init-cmd.js.map +0 -1
- package/packages/cli/dist/commands/learn-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/learn-cmd.js.map +0 -1
- package/packages/cli/dist/commands/pack-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/pack-cmd.js.map +0 -1
- package/packages/cli/dist/commands/review-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/review-cmd.js.map +0 -1
- package/packages/cli/dist/commands/search-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/search-cmd.js.map +0 -1
- package/packages/cli/dist/commands/serve-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/serve-cmd.js.map +0 -1
- package/packages/cli/dist/commands/status-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/status-cmd.js.map +0 -1
- package/packages/cli/dist/commands/sync-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/sync-cmd.js.map +0 -1
- package/packages/cli/dist/commands/vault-cmd.d.ts.map +0 -1
- package/packages/cli/dist/commands/vault-cmd.js.map +0 -1
- package/packages/cli/dist/index.d.ts.map +0 -1
- package/packages/cli/dist/index.js.map +0 -1
- package/packages/cli/src/commands/brief-cmd.ts +0 -87
- package/packages/cli/src/commands/capture-cmd.ts +0 -34
- package/packages/cli/src/commands/card-cmd.ts +0 -29
- package/packages/cli/src/commands/clip-cmd.ts +0 -172
- package/packages/cli/src/commands/cloud-cmd.ts +0 -75
- package/packages/cli/src/commands/contradictions-cmd.ts +0 -41
- package/packages/cli/src/commands/decay-cmd.ts +0 -57
- package/packages/cli/src/commands/digest-cmd.ts +0 -89
- package/packages/cli/src/commands/duplicates-cmd.ts +0 -38
- package/packages/cli/src/commands/federate-cmd.ts +0 -256
- package/packages/cli/src/commands/gaps-cmd.ts +0 -40
- package/packages/cli/src/commands/graph-cmd.ts +0 -88
- package/packages/cli/src/commands/index-cmd.ts +0 -65
- package/packages/cli/src/commands/init-cmd.ts +0 -145
- package/packages/cli/src/commands/learn-cmd.ts +0 -56
- package/packages/cli/src/commands/pack-cmd.ts +0 -121
- package/packages/cli/src/commands/review-cmd.ts +0 -125
- package/packages/cli/src/commands/search-cmd.ts +0 -45
- package/packages/cli/src/commands/serve-cmd.ts +0 -17
- package/packages/cli/src/commands/status-cmd.ts +0 -37
- package/packages/cli/src/commands/sync-cmd.ts +0 -68
- package/packages/cli/src/commands/vault-cmd.ts +0 -64
- package/packages/cli/src/index.ts +0 -187
- package/packages/core/src/api/graph-data.ts +0 -286
- package/packages/core/src/api/server.ts +0 -660
- package/packages/core/src/capture/voice.ts +0 -168
- package/packages/core/src/cloud/sync.ts +0 -167
- package/packages/core/src/config.ts +0 -82
- package/packages/core/src/federation/credits.ts +0 -80
- package/packages/core/src/federation/hyperswarm.d.ts +0 -19
- package/packages/core/src/federation/identity.ts +0 -90
- package/packages/core/src/federation/node.ts +0 -235
- package/packages/core/src/federation/privacy.ts +0 -52
- package/packages/core/src/federation/reputation.ts +0 -202
- package/packages/core/src/federation/search.ts +0 -129
- package/packages/core/src/federation/sharing.ts +0 -315
- package/packages/core/src/federation/trust.ts +0 -76
- package/packages/core/src/federation/types.ts +0 -25
- package/packages/core/src/i18n/index.ts +0 -85
- package/packages/core/src/indexer/chunker.ts +0 -180
- package/packages/core/src/indexer/embedder.ts +0 -9
- package/packages/core/src/indexer/index.ts +0 -113
- package/packages/core/src/indexer/local-embedder.ts +0 -35
- package/packages/core/src/indexer/scanner.ts +0 -142
- package/packages/core/src/indexer/watcher.ts +0 -62
- package/packages/core/src/intelligence/contradiction-detector.ts +0 -134
- package/packages/core/src/intelligence/decay-engine.ts +0 -229
- package/packages/core/src/intelligence/duplicate-detector.ts +0 -71
- package/packages/core/src/intelligence/fsrs.ts +0 -79
- package/packages/core/src/intelligence/gap-detector.ts +0 -109
- package/packages/core/src/intelligence/learning-path.ts +0 -86
- package/packages/core/src/intelligence/notifications.ts +0 -106
- package/packages/core/src/intelligence/predictive-gaps.ts +0 -94
- package/packages/core/src/intelligence/semantic-versioning.ts +0 -97
- package/packages/core/src/intelligence/types.ts +0 -28
- package/packages/core/src/mcp/custom-tools.ts +0 -97
- package/packages/core/src/mcp/server.ts +0 -142
- package/packages/core/src/mcp/tools/agentic-graph.ts +0 -96
- package/packages/core/src/mcp/tools/brief.ts +0 -49
- package/packages/core/src/mcp/tools/decay.ts +0 -40
- package/packages/core/src/mcp/tools/decision-journal.ts +0 -95
- package/packages/core/src/mcp/tools/export.ts +0 -72
- package/packages/core/src/mcp/tools/federated-search.ts +0 -43
- package/packages/core/src/mcp/tools/generate-claude-md.ts +0 -130
- package/packages/core/src/mcp/tools/get-document.ts +0 -26
- package/packages/core/src/mcp/tools/get-related.ts +0 -41
- package/packages/core/src/mcp/tools/learning-path.ts +0 -52
- package/packages/core/src/mcp/tools/list-topics.ts +0 -20
- package/packages/core/src/mcp/tools/search.ts +0 -35
- package/packages/core/src/mcp/tools/snapshot.ts +0 -98
- package/packages/core/src/multi-vault/index.ts +0 -118
- package/packages/core/src/pack/creator.ts +0 -127
- package/packages/core/src/pack/exporter.ts +0 -21
- package/packages/core/src/pack/importer.ts +0 -82
- package/packages/core/src/pack/marketplace.ts +0 -103
- package/packages/core/src/pack/pii-masker.ts +0 -38
- package/packages/core/src/pack/types.ts +0 -39
- package/packages/core/src/plugins/index.ts +0 -100
- package/packages/core/src/plugins/webhooks.ts +0 -110
- package/packages/core/src/search/bm25.ts +0 -16
- package/packages/core/src/search/index.ts +0 -83
- package/packages/core/src/search/rrf.ts +0 -31
- package/packages/core/src/search/semantic.ts +0 -15
- package/packages/core/src/store/sqlite-vec.ts +0 -290
- package/packages/core/src/store/types.ts +0 -22
- package/packages/core/src/team/index.ts +0 -126
- package/packages/core/src/types/chunk.ts +0 -25
- package/packages/core/src/types/document.ts +0 -24
- package/packages/core/src/types/graph.ts +0 -44
- package/packages/core/src/types/index.ts +0 -15
- package/packages/core/src/types/search.ts +0 -38
- package/packages/core/src/utils/retry.ts +0 -85
- package/packages/core/tests/api-card.test.ts +0 -60
- package/packages/core/tests/api-routes.test.ts +0 -98
- package/packages/core/tests/bm25.test.ts +0 -87
- package/packages/core/tests/chunker.test.ts +0 -48
- package/packages/core/tests/cluster.test.ts +0 -75
- package/packages/core/tests/constellation.test.ts +0 -77
- package/packages/core/tests/export-utils.test.ts +0 -97
- package/packages/core/tests/fsrs.test.ts +0 -96
- package/packages/core/tests/gesture-detector.test.ts +0 -45
- package/packages/core/tests/graph-data.test.ts +0 -87
- package/packages/core/tests/layout.test.ts +0 -83
- package/packages/core/tests/mcp.test.ts +0 -148
- package/packages/core/tests/pack.test.ts +0 -127
- package/packages/core/tests/pii-masker.test.ts +0 -42
- package/packages/core/tests/profile-card.test.ts +0 -62
- package/packages/core/tests/rrf.test.ts +0 -29
- package/packages/core/tests/search-integration.test.ts +0 -139
- package/packages/core/tests/store.test.ts +0 -80
- package/packages/graph/click-result.png +0 -0
- package/packages/graph/dist/assets/camera_utils-BMxqtvoZ.js +0 -1
- package/packages/graph/dist/assets/hands-DXA01_mx.js +0 -18
- package/packages/graph/dist/assets/index-DMEe2diW.js +0 -4192
- package/packages/graph/dist/assets/layout.worker-DbKCEFTz.js +0 -1
- package/packages/graph/dist/index.html +0 -17
- package/packages/graph/index.html +0 -17
- package/packages/graph/package.json +0 -32
- package/packages/graph/src/App.tsx +0 -7
- package/packages/graph/src/api/client.ts +0 -39
- package/packages/graph/src/components/ClusterFilter.tsx +0 -73
- package/packages/graph/src/components/ConstellationView.tsx +0 -232
- package/packages/graph/src/components/ExportPanel.tsx +0 -177
- package/packages/graph/src/components/Graph3D.tsx +0 -230
- package/packages/graph/src/components/GraphEdges.tsx +0 -100
- package/packages/graph/src/components/GraphNodes.tsx +0 -386
- package/packages/graph/src/components/HealthDashboard.tsx +0 -173
- package/packages/graph/src/components/Layout.tsx +0 -214
- package/packages/graph/src/components/MotionOverlay.tsx +0 -81
- package/packages/graph/src/components/MotionToggle.tsx +0 -33
- package/packages/graph/src/components/MultiverseView.tsx +0 -286
- package/packages/graph/src/components/NodeDetail.tsx +0 -232
- package/packages/graph/src/components/PulseParticle.tsx +0 -232
- package/packages/graph/src/components/SearchBar.tsx +0 -107
- package/packages/graph/src/components/StarField.tsx +0 -197
- package/packages/graph/src/components/StatusBar.tsx +0 -53
- package/packages/graph/src/components/Timeline.tsx +0 -148
- package/packages/graph/src/components/ToolsPanel.tsx +0 -512
- package/packages/graph/src/components/Tooltip.tsx +0 -100
- package/packages/graph/src/components/TypeFilter.tsx +0 -131
- package/packages/graph/src/embed/EmbedGraph.tsx +0 -144
- package/packages/graph/src/hooks/useConstellationLOD.ts +0 -76
- package/packages/graph/src/hooks/useDecay.ts +0 -37
- package/packages/graph/src/hooks/useExport.ts +0 -165
- package/packages/graph/src/hooks/useGraph.ts +0 -69
- package/packages/graph/src/hooks/useKeyboardNav.ts +0 -122
- package/packages/graph/src/hooks/useLayout.ts +0 -45
- package/packages/graph/src/hooks/useMotion.ts +0 -120
- package/packages/graph/src/hooks/usePulse.ts +0 -58
- package/packages/graph/src/hooks/useSearch.ts +0 -71
- package/packages/graph/src/lib/constellation.ts +0 -107
- package/packages/graph/src/lib/export-utils.ts +0 -48
- package/packages/graph/src/lib/gesture-detector.ts +0 -123
- package/packages/graph/src/lib/layout.worker.ts +0 -153
- package/packages/graph/src/lib/motion-controller.ts +0 -83
- package/packages/graph/src/lib/profile-card.ts +0 -122
- package/packages/graph/src/main.tsx +0 -4
- package/packages/graph/src/stores/graph-store.ts +0 -155
- package/packages/graph/success.png +0 -0
- package/packages/graph/test-click.mjs +0 -49
- package/packages/graph/test-explore.mjs +0 -102
- package/packages/graph/test-final.mjs +0 -61
- package/packages/graph/test-graph.mjs +0 -139
- package/packages/graph/test-hover.mjs +0 -48
- package/packages/graph/test-pulse.mjs +0 -68
- package/packages/graph/test-screenshot.mjs +0 -56
- package/packages/graph/test-v2.mjs +0 -97
- package/packages/graph/tsconfig.tsbuildinfo +0 -1
- package/packages/graph/vite.config.ts +0 -15
- package/packages/sync/.env.example +0 -11
- package/packages/sync/.sync-state.json +0 -317
- package/packages/sync/.upload-state.json +0 -1009
- package/packages/sync/create-stella-network-notion.mjs +0 -151
- package/packages/sync/create-stellavault-project-notion.mjs +0 -322
- package/packages/sync/logs/sync-2026-03-28.log +0 -6
- package/packages/sync/logs/sync-2026-03-29.log +0 -12
- package/packages/sync/logs/sync-2026-03-30.log +0 -6
- package/packages/sync/logs/sync-2026-03-31.log +0 -6
- package/packages/sync/logs/sync-2026-04-01.log +0 -6
- package/packages/sync/logs/sync-2026-04-02.log +0 -6
- package/packages/sync/package-lock.json +0 -373
- package/packages/sync/package.json +0 -16
- package/packages/sync/run-sync.bat +0 -18
- package/packages/sync/run-sync.mjs +0 -46
- package/packages/sync/setup-scheduler.mjs +0 -119
- package/packages/sync/structured-sync.mjs +0 -187
- package/packages/sync/sync-to-obsidian.mjs +0 -264
- package/packages/sync/upload-pdca-to-notion.mjs +0 -495
- package/tsconfig.base.json +0 -18
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// Voice Knowledge Capture (P3-F25)
|
|
2
|
+
// 음성 파일 → 텍스트 → 자동 분류 → vault 저장 → 인덱싱
|
|
3
|
+
import { execFileSync, execSync } from 'node:child_process';
|
|
4
|
+
import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
5
|
+
import { join, basename } from 'node:path';
|
|
6
|
+
// CRIT-03: 화이트리스트 검증
|
|
7
|
+
const ALLOWED_MODELS = ['tiny', 'base', 'small', 'medium', 'large'];
|
|
8
|
+
const ALLOWED_LANGUAGES = ['auto', 'en', 'ko', 'ja', 'zh', 'es', 'fr', 'de', 'it', 'pt', 'ru', 'ar', 'hi'];
|
|
9
|
+
function validateModel(model) {
|
|
10
|
+
if (!ALLOWED_MODELS.includes(model))
|
|
11
|
+
throw new Error(`Invalid model: ${model}. Allowed: ${ALLOWED_MODELS.join(', ')}`);
|
|
12
|
+
return model;
|
|
13
|
+
}
|
|
14
|
+
function validateLanguage(lang) {
|
|
15
|
+
if (!ALLOWED_LANGUAGES.includes(lang))
|
|
16
|
+
throw new Error(`Invalid language: ${lang}. Allowed: ${ALLOWED_LANGUAGES.join(', ')}`);
|
|
17
|
+
return lang;
|
|
18
|
+
}
|
|
19
|
+
// Whisper CLI가 설치되어 있는지 확인
|
|
20
|
+
export function isWhisperAvailable() {
|
|
21
|
+
try {
|
|
22
|
+
execSync('whisper --help', { stdio: 'ignore' });
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// 음성 파일 → 텍스트 변환 (Whisper CLI)
|
|
30
|
+
export async function transcribeAudio(audioPath, options = {}) {
|
|
31
|
+
const { model = 'base', language } = options;
|
|
32
|
+
if (!existsSync(audioPath)) {
|
|
33
|
+
throw new Error(`Audio file not found: ${audioPath}`);
|
|
34
|
+
}
|
|
35
|
+
// CRIT-03 fix: execFileSync + 화이트리스트 검증 (command injection 방지)
|
|
36
|
+
if (isWhisperAvailable()) {
|
|
37
|
+
const safeModel = validateModel(model);
|
|
38
|
+
const args = [audioPath, '--model', safeModel, '--output_format', 'txt', '--output_dir', '/tmp/sv-whisper'];
|
|
39
|
+
if (language)
|
|
40
|
+
args.push('--language', validateLanguage(language));
|
|
41
|
+
mkdirSync('/tmp/sv-whisper', { recursive: true });
|
|
42
|
+
try {
|
|
43
|
+
execFileSync('whisper', args, { stdio: 'pipe', timeout: 300000 });
|
|
44
|
+
const outputName = basename(audioPath).replace(/\.[^.]+$/, '.txt');
|
|
45
|
+
const { readFileSync } = await import('node:fs');
|
|
46
|
+
return readFileSync(join('/tmp/sv-whisper', outputName), 'utf-8').trim();
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
throw new Error(`Whisper failed: ${err instanceof Error ? err.message : err}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Whisper 없으면 에러
|
|
53
|
+
throw new Error('Whisper not installed. Install: pip install openai-whisper');
|
|
54
|
+
}
|
|
55
|
+
// 트랜스크립트에서 자동 태그 추출 (간단한 키워드 매칭)
|
|
56
|
+
function autoTag(text) {
|
|
57
|
+
const tags = [];
|
|
58
|
+
const lower = text.toLowerCase();
|
|
59
|
+
const keywords = {
|
|
60
|
+
'meeting': ['meeting', 'discuss', '미팅', '회의'],
|
|
61
|
+
'decision': ['decide', 'agreed', '결정', '합의'],
|
|
62
|
+
'idea': ['idea', 'thought', '아이디어', '생각'],
|
|
63
|
+
'todo': ['todo', 'task', 'action item', '할 일'],
|
|
64
|
+
'bug': ['bug', 'error', 'fix', '버그', '에러'],
|
|
65
|
+
'architecture': ['architecture', 'design', 'system', '아키텍처', '설계'],
|
|
66
|
+
};
|
|
67
|
+
for (const [tag, words] of Object.entries(keywords)) {
|
|
68
|
+
if (words.some(w => lower.includes(w)))
|
|
69
|
+
tags.push(tag);
|
|
70
|
+
}
|
|
71
|
+
return tags;
|
|
72
|
+
}
|
|
73
|
+
// 음성 → vault 노트 생성
|
|
74
|
+
export async function captureVoice(audioPath, options) {
|
|
75
|
+
const { vaultPath, folder = '01_Knowledge/voice', type = 'note', tags: userTags = [] } = options;
|
|
76
|
+
try {
|
|
77
|
+
// 1. 음성→텍스트
|
|
78
|
+
const transcript = await transcribeAudio(audioPath, {
|
|
79
|
+
model: options.model,
|
|
80
|
+
language: options.language,
|
|
81
|
+
});
|
|
82
|
+
if (!transcript) {
|
|
83
|
+
return { title: '', filePath: '', transcript: '', tags: [], success: false, error: 'Empty transcript' };
|
|
84
|
+
}
|
|
85
|
+
// 2. 제목 생성 (첫 문장 또는 첫 30자)
|
|
86
|
+
const firstLine = transcript.split(/[.\n!?]/)[0]?.trim() || transcript.slice(0, 30);
|
|
87
|
+
const title = firstLine.slice(0, 60);
|
|
88
|
+
const safeTitle = title.replace(/[<>:"/\\|?*]/g, '').replace(/\s+/g, ' ').trim();
|
|
89
|
+
// 3. 자동 태그
|
|
90
|
+
const autoTags = autoTag(transcript);
|
|
91
|
+
const allTags = [...new Set([...userTags, ...autoTags, 'voice'])];
|
|
92
|
+
// 4. frontmatter + 마크다운 생성
|
|
93
|
+
const date = new Date().toISOString();
|
|
94
|
+
const content = [
|
|
95
|
+
'---',
|
|
96
|
+
`title: "${safeTitle}"`,
|
|
97
|
+
`source: voice`,
|
|
98
|
+
`type: ${type}`,
|
|
99
|
+
`tags: [${allTags.map(t => `"${t}"`).join(', ')}]`,
|
|
100
|
+
`captured: ${date}`,
|
|
101
|
+
`audio: ${basename(audioPath)}`,
|
|
102
|
+
'---',
|
|
103
|
+
'',
|
|
104
|
+
`# ${safeTitle}`,
|
|
105
|
+
'',
|
|
106
|
+
`> Voice capture: ${date.slice(0, 10)}`,
|
|
107
|
+
'',
|
|
108
|
+
transcript,
|
|
109
|
+
'',
|
|
110
|
+
].join('\n');
|
|
111
|
+
// 5. vault에 저장
|
|
112
|
+
const dir = join(vaultPath, folder);
|
|
113
|
+
mkdirSync(dir, { recursive: true });
|
|
114
|
+
const filePath = join(dir, `${date.slice(0, 10)} ${safeTitle}.md`);
|
|
115
|
+
writeFileSync(filePath, content, 'utf-8');
|
|
116
|
+
return {
|
|
117
|
+
title: safeTitle,
|
|
118
|
+
filePath,
|
|
119
|
+
transcript,
|
|
120
|
+
tags: allTags,
|
|
121
|
+
success: true,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
return {
|
|
126
|
+
title: '',
|
|
127
|
+
filePath: '',
|
|
128
|
+
transcript: '',
|
|
129
|
+
tags: [],
|
|
130
|
+
success: false,
|
|
131
|
+
error: err instanceof Error ? err.message : String(err),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=voice.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface CloudConfig {
|
|
2
|
+
endpoint: string;
|
|
3
|
+
bucket: string;
|
|
4
|
+
accessKeyId: string;
|
|
5
|
+
secretAccessKey: string;
|
|
6
|
+
encryptionKey?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface SyncResult {
|
|
9
|
+
action: 'upload' | 'download';
|
|
10
|
+
dbSize: number;
|
|
11
|
+
encryptedSize: number;
|
|
12
|
+
timestamp: string;
|
|
13
|
+
success: boolean;
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function encrypt(data: Buffer, key: Buffer): {
|
|
17
|
+
encrypted: Buffer;
|
|
18
|
+
iv: Buffer;
|
|
19
|
+
tag: Buffer;
|
|
20
|
+
};
|
|
21
|
+
export declare function decrypt(encrypted: Buffer, key: Buffer, iv: Buffer, tag: Buffer): Buffer;
|
|
22
|
+
export declare function getOrCreateEncryptionKey(userKey?: string): Buffer;
|
|
23
|
+
export declare function syncToCloud(dbPath: string, config: CloudConfig): Promise<SyncResult>;
|
|
24
|
+
export declare function restoreFromCloud(dbPath: string, config: CloudConfig): Promise<SyncResult>;
|
|
25
|
+
export declare function getSyncState(): {
|
|
26
|
+
lastSync: string;
|
|
27
|
+
dbSize: number;
|
|
28
|
+
} | null;
|
|
29
|
+
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// Cloud Sync (F-A04) — E2E encrypted SQLite backup
|
|
2
|
+
// 서버리스: S3-compatible API로 직접 업로드 (R2, S3, MinIO)
|
|
3
|
+
// Design Ref: PRD §7.1 Tier 2
|
|
4
|
+
import { createCipheriv, createDecipheriv, randomBytes, createHash } from 'node:crypto';
|
|
5
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, chmodSync } from 'node:fs';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
const CLOUD_DIR = join(homedir(), '.stellavault', 'cloud');
|
|
9
|
+
const KEY_FILE = join(CLOUD_DIR, 'encryption.key');
|
|
10
|
+
const SYNC_STATE_FILE = join(CLOUD_DIR, 'sync-state.json');
|
|
11
|
+
// AES-256-GCM 암호화
|
|
12
|
+
export function encrypt(data, key) {
|
|
13
|
+
const iv = randomBytes(16);
|
|
14
|
+
const cipher = createCipheriv('aes-256-gcm', key, iv);
|
|
15
|
+
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
16
|
+
const tag = cipher.getAuthTag();
|
|
17
|
+
return { encrypted, iv, tag };
|
|
18
|
+
}
|
|
19
|
+
export function decrypt(encrypted, key, iv, tag) {
|
|
20
|
+
const decipher = createDecipheriv('aes-256-gcm', key, iv);
|
|
21
|
+
decipher.setAuthTag(tag);
|
|
22
|
+
return Buffer.concat([decipher.update(encrypted), decipher.final()]);
|
|
23
|
+
}
|
|
24
|
+
// 암호화 키 관리
|
|
25
|
+
export function getOrCreateEncryptionKey(userKey) {
|
|
26
|
+
mkdirSync(CLOUD_DIR, { recursive: true });
|
|
27
|
+
if (userKey) {
|
|
28
|
+
const key = createHash('sha256').update(userKey).digest();
|
|
29
|
+
writeFileSync(KEY_FILE, key.toString('hex'), 'utf-8');
|
|
30
|
+
return key;
|
|
31
|
+
}
|
|
32
|
+
if (existsSync(KEY_FILE)) {
|
|
33
|
+
return Buffer.from(readFileSync(KEY_FILE, 'utf-8').trim(), 'hex');
|
|
34
|
+
}
|
|
35
|
+
const key = randomBytes(32);
|
|
36
|
+
writeFileSync(KEY_FILE, key.toString('hex'), { encoding: 'utf-8', mode: 0o600 });
|
|
37
|
+
try {
|
|
38
|
+
chmodSync(KEY_FILE, 0o600);
|
|
39
|
+
}
|
|
40
|
+
catch { /* Windows may not support */ }
|
|
41
|
+
return key;
|
|
42
|
+
}
|
|
43
|
+
// S3-compatible upload (presigned 불필요 — 직접 PUT)
|
|
44
|
+
async function s3Put(config, objectKey, data, contentType = 'application/octet-stream') {
|
|
45
|
+
const { endpoint, bucket, accessKeyId, secretAccessKey } = config;
|
|
46
|
+
// HIGH-05: endpoint 검증
|
|
47
|
+
try {
|
|
48
|
+
const parsed = new URL(endpoint);
|
|
49
|
+
if (!['http:', 'https:'].includes(parsed.protocol))
|
|
50
|
+
throw new Error('Invalid protocol');
|
|
51
|
+
if (parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1')
|
|
52
|
+
throw new Error('Local endpoint');
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
throw new Error(`Invalid cloud endpoint: ${endpoint}. ${e instanceof Error ? e.message : ''}`);
|
|
56
|
+
}
|
|
57
|
+
const url = `${endpoint}/${bucket}/${objectKey}`;
|
|
58
|
+
const date = new Date().toISOString().replace(/[-:]/g, '').slice(0, 15) + 'Z';
|
|
59
|
+
const res = await fetch(url, {
|
|
60
|
+
method: 'PUT',
|
|
61
|
+
headers: {
|
|
62
|
+
'Content-Type': contentType,
|
|
63
|
+
'Content-Length': String(data.length),
|
|
64
|
+
'x-amz-date': date,
|
|
65
|
+
'x-amz-content-sha256': createHash('sha256').update(data).digest('hex'),
|
|
66
|
+
// R2는 Bearer token 지원
|
|
67
|
+
'Authorization': `Bearer ${secretAccessKey}`,
|
|
68
|
+
},
|
|
69
|
+
body: data,
|
|
70
|
+
});
|
|
71
|
+
return res.ok;
|
|
72
|
+
}
|
|
73
|
+
async function s3Get(config, objectKey) {
|
|
74
|
+
const url = `${config.endpoint}/${config.bucket}/${objectKey}`;
|
|
75
|
+
const res = await fetch(url, {
|
|
76
|
+
headers: { 'Authorization': `Bearer ${config.secretAccessKey}` },
|
|
77
|
+
});
|
|
78
|
+
if (!res.ok)
|
|
79
|
+
return null;
|
|
80
|
+
return Buffer.from(await res.arrayBuffer());
|
|
81
|
+
}
|
|
82
|
+
// Sync: 로컬 DB → 암호화 → 업로드
|
|
83
|
+
export async function syncToCloud(dbPath, config) {
|
|
84
|
+
const timestamp = new Date().toISOString();
|
|
85
|
+
try {
|
|
86
|
+
if (!existsSync(dbPath)) {
|
|
87
|
+
return { action: 'upload', dbSize: 0, encryptedSize: 0, timestamp, success: false, error: 'DB not found' };
|
|
88
|
+
}
|
|
89
|
+
const dbData = readFileSync(dbPath);
|
|
90
|
+
const key = getOrCreateEncryptionKey(config.encryptionKey);
|
|
91
|
+
const { encrypted, iv, tag } = encrypt(dbData, key);
|
|
92
|
+
// 패키징: [iv(16)] + [tag(16)] + [encrypted data]
|
|
93
|
+
const payload = Buffer.concat([iv, tag, encrypted]);
|
|
94
|
+
const objectKey = `stellavault/index.db.enc`;
|
|
95
|
+
const success = await s3Put(config, objectKey, payload);
|
|
96
|
+
// 동기화 상태 저장
|
|
97
|
+
const state = { lastSync: timestamp, dbSize: dbData.length, encryptedSize: payload.length, objectKey };
|
|
98
|
+
mkdirSync(CLOUD_DIR, { recursive: true });
|
|
99
|
+
writeFileSync(SYNC_STATE_FILE, JSON.stringify(state, null, 2), 'utf-8');
|
|
100
|
+
return { action: 'upload', dbSize: dbData.length, encryptedSize: payload.length, timestamp, success };
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
return { action: 'upload', dbSize: 0, encryptedSize: 0, timestamp, success: false, error: err instanceof Error ? err.message : String(err) };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Restore: 다운로드 → 복호화 → 로컬 DB 덮어쓰기
|
|
107
|
+
export async function restoreFromCloud(dbPath, config) {
|
|
108
|
+
const timestamp = new Date().toISOString();
|
|
109
|
+
try {
|
|
110
|
+
const objectKey = `stellavault/index.db.enc`;
|
|
111
|
+
const payload = await s3Get(config, objectKey);
|
|
112
|
+
if (!payload) {
|
|
113
|
+
return { action: 'download', dbSize: 0, encryptedSize: 0, timestamp, success: false, error: 'No backup found in cloud' };
|
|
114
|
+
}
|
|
115
|
+
const key = getOrCreateEncryptionKey(config.encryptionKey);
|
|
116
|
+
const iv = payload.subarray(0, 16);
|
|
117
|
+
const tag = payload.subarray(16, 32);
|
|
118
|
+
const encrypted = payload.subarray(32);
|
|
119
|
+
const dbData = decrypt(encrypted, key, iv, tag);
|
|
120
|
+
// 백업 후 덮어쓰기
|
|
121
|
+
if (existsSync(dbPath)) {
|
|
122
|
+
writeFileSync(dbPath + '.backup', readFileSync(dbPath));
|
|
123
|
+
}
|
|
124
|
+
writeFileSync(dbPath, dbData);
|
|
125
|
+
return { action: 'download', dbSize: dbData.length, encryptedSize: payload.length, timestamp, success: true };
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
return { action: 'download', dbSize: 0, encryptedSize: 0, timestamp, success: false, error: err instanceof Error ? err.message : String(err) };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// 동기화 상태 조회
|
|
132
|
+
export function getSyncState() {
|
|
133
|
+
if (!existsSync(SYNC_STATE_FILE))
|
|
134
|
+
return null;
|
|
135
|
+
return JSON.parse(readFileSync(SYNC_STATE_FILE, 'utf-8'));
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface StellavaultConfig {
|
|
2
|
+
vaultPath: string;
|
|
3
|
+
dbPath: string;
|
|
4
|
+
embedding: {
|
|
5
|
+
model: 'local' | 'openai';
|
|
6
|
+
localModel: string;
|
|
7
|
+
};
|
|
8
|
+
chunking: {
|
|
9
|
+
maxTokens: number;
|
|
10
|
+
overlap: number;
|
|
11
|
+
minTokens: number;
|
|
12
|
+
};
|
|
13
|
+
search: {
|
|
14
|
+
defaultLimit: number;
|
|
15
|
+
rrfK: number;
|
|
16
|
+
};
|
|
17
|
+
mcp: {
|
|
18
|
+
mode: 'stdio' | 'sse';
|
|
19
|
+
port: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* .stellavault.json 파일을 찾아 로드합니다.
|
|
24
|
+
* 탐색 순서: cwd → home directory → defaults
|
|
25
|
+
*/
|
|
26
|
+
export declare function loadConfig(configPath?: string): StellavaultConfig;
|
|
27
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Design Ref: §10.2 — 설정 파일 구조 (.stellavault.json 로더)
|
|
2
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
const DEFAULT_CONFIG = {
|
|
6
|
+
vaultPath: '',
|
|
7
|
+
dbPath: join(homedir(), '.stellavault', 'index.db'),
|
|
8
|
+
embedding: {
|
|
9
|
+
model: 'local',
|
|
10
|
+
localModel: 'all-MiniLM-L6-v2',
|
|
11
|
+
},
|
|
12
|
+
chunking: {
|
|
13
|
+
maxTokens: 300,
|
|
14
|
+
overlap: 50,
|
|
15
|
+
minTokens: 50,
|
|
16
|
+
},
|
|
17
|
+
search: {
|
|
18
|
+
defaultLimit: 10,
|
|
19
|
+
rrfK: 60,
|
|
20
|
+
},
|
|
21
|
+
mcp: {
|
|
22
|
+
mode: 'stdio',
|
|
23
|
+
port: 3333,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* .stellavault.json 파일을 찾아 로드합니다.
|
|
28
|
+
* 탐색 순서: cwd → home directory → defaults
|
|
29
|
+
*/
|
|
30
|
+
export function loadConfig(configPath) {
|
|
31
|
+
const paths = configPath
|
|
32
|
+
? [resolve(configPath)]
|
|
33
|
+
: [
|
|
34
|
+
resolve(process.cwd(), '.stellavault.json'),
|
|
35
|
+
join(homedir(), '.stellavault.json'),
|
|
36
|
+
];
|
|
37
|
+
for (const p of paths) {
|
|
38
|
+
if (existsSync(p)) {
|
|
39
|
+
const raw = JSON.parse(readFileSync(p, 'utf-8'));
|
|
40
|
+
return mergeConfig(DEFAULT_CONFIG, raw);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { ...DEFAULT_CONFIG };
|
|
44
|
+
}
|
|
45
|
+
function mergeConfig(defaults, overrides) {
|
|
46
|
+
return {
|
|
47
|
+
vaultPath: overrides.vaultPath ?? defaults.vaultPath,
|
|
48
|
+
dbPath: overrides.dbPath ?? defaults.dbPath,
|
|
49
|
+
embedding: { ...defaults.embedding, ...overrides.embedding },
|
|
50
|
+
chunking: { ...defaults.chunking, ...overrides.chunking },
|
|
51
|
+
search: { ...defaults.search, ...overrides.search },
|
|
52
|
+
mcp: { ...defaults.mcp, ...overrides.mcp },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface CreditAccount {
|
|
2
|
+
balance: number;
|
|
3
|
+
totalEarned: number;
|
|
4
|
+
totalSpent: number;
|
|
5
|
+
transactions: CreditTransaction[];
|
|
6
|
+
}
|
|
7
|
+
export interface CreditTransaction {
|
|
8
|
+
type: 'earn' | 'spend';
|
|
9
|
+
amount: number;
|
|
10
|
+
reason: string;
|
|
11
|
+
timestamp: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function getBalance(): number;
|
|
14
|
+
export declare function getAccount(): CreditAccount;
|
|
15
|
+
export declare function earn(amount: number, reason: string): number;
|
|
16
|
+
export declare function spend(amount: number, reason: string): {
|
|
17
|
+
success: boolean;
|
|
18
|
+
balance: number;
|
|
19
|
+
};
|
|
20
|
+
export declare function earnForSearchResponse(peerId: string): number;
|
|
21
|
+
export declare function spendForSearch(peerCount: number): {
|
|
22
|
+
success: boolean;
|
|
23
|
+
balance: number;
|
|
24
|
+
};
|
|
25
|
+
export declare function getRecentTransactions(limit?: number): CreditTransaction[];
|
|
26
|
+
//# sourceMappingURL=credits.d.ts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Federation Phase 2: Search Credits
|
|
2
|
+
// 지식 공유 = 크레딧 획득, 연합 검색 = 크레딧 소모
|
|
3
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
const CREDITS_FILE = join(homedir(), '.stellavault', 'federation', 'credits.json');
|
|
7
|
+
const INITIAL_BALANCE = 100;
|
|
8
|
+
const EARN_PER_SEARCH_RESPONSE = 10; // 검색 응답 시 획득
|
|
9
|
+
const COST_PER_SEARCH = 1; // 검색 요청 시 소모
|
|
10
|
+
function loadAccount() {
|
|
11
|
+
if (existsSync(CREDITS_FILE)) {
|
|
12
|
+
return JSON.parse(readFileSync(CREDITS_FILE, 'utf-8'));
|
|
13
|
+
}
|
|
14
|
+
return { balance: INITIAL_BALANCE, totalEarned: 0, totalSpent: 0, transactions: [] };
|
|
15
|
+
}
|
|
16
|
+
function saveAccount(account) {
|
|
17
|
+
mkdirSync(join(homedir(), '.stellavault', 'federation'), { recursive: true });
|
|
18
|
+
// 최근 100개 트랜잭션만 유지
|
|
19
|
+
account.transactions = account.transactions.slice(-100);
|
|
20
|
+
writeFileSync(CREDITS_FILE, JSON.stringify(account, null, 2), 'utf-8');
|
|
21
|
+
}
|
|
22
|
+
export function getBalance() {
|
|
23
|
+
return loadAccount().balance;
|
|
24
|
+
}
|
|
25
|
+
export function getAccount() {
|
|
26
|
+
return loadAccount();
|
|
27
|
+
}
|
|
28
|
+
export function earn(amount, reason) {
|
|
29
|
+
const account = loadAccount();
|
|
30
|
+
account.balance += amount;
|
|
31
|
+
account.totalEarned += amount;
|
|
32
|
+
account.transactions.push({ type: 'earn', amount, reason, timestamp: new Date().toISOString() });
|
|
33
|
+
saveAccount(account);
|
|
34
|
+
return account.balance;
|
|
35
|
+
}
|
|
36
|
+
export function spend(amount, reason) {
|
|
37
|
+
const account = loadAccount();
|
|
38
|
+
if (account.balance < amount) {
|
|
39
|
+
return { success: false, balance: account.balance };
|
|
40
|
+
}
|
|
41
|
+
account.balance -= amount;
|
|
42
|
+
account.totalSpent += amount;
|
|
43
|
+
account.transactions.push({ type: 'spend', amount, reason, timestamp: new Date().toISOString() });
|
|
44
|
+
saveAccount(account);
|
|
45
|
+
return { success: true, balance: account.balance };
|
|
46
|
+
}
|
|
47
|
+
export function earnForSearchResponse(peerId) {
|
|
48
|
+
return earn(EARN_PER_SEARCH_RESPONSE, `Search response to ${peerId}`);
|
|
49
|
+
}
|
|
50
|
+
export function spendForSearch(peerCount) {
|
|
51
|
+
return spend(COST_PER_SEARCH * peerCount, `Search across ${peerCount} peers`);
|
|
52
|
+
}
|
|
53
|
+
export function getRecentTransactions(limit = 20) {
|
|
54
|
+
return loadAccount().transactions.slice(-limit).reverse();
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=credits.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface NodeIdentity {
|
|
2
|
+
peerId: string;
|
|
3
|
+
publicKey: Buffer;
|
|
4
|
+
secretKey: Buffer;
|
|
5
|
+
displayName: string;
|
|
6
|
+
createdAt: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function getOrCreateIdentity(displayName?: string): NodeIdentity;
|
|
9
|
+
export declare function signMessage(secretKey: Buffer, message: Buffer): Buffer;
|
|
10
|
+
export declare function verifySignature(publicKey: Buffer, secretKey: Buffer, message: Buffer, signature: Buffer): boolean;
|
|
11
|
+
export declare function createChallenge(): Buffer;
|
|
12
|
+
export declare function respondToChallenge(secretKey: Buffer, challenge: Buffer): Buffer;
|
|
13
|
+
export declare function verifyChallenge(secretKey: Buffer, challenge: Buffer, response: Buffer): boolean;
|
|
14
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Federation: Node Identity (HMAC-SHA256 signing)
|
|
2
|
+
// CRIT-01 fix: 실제 서명 검증 구현 (placeholder 제거)
|
|
3
|
+
// CRIT-04 fix: 키 파일 권한 0o600
|
|
4
|
+
import { randomBytes, createHash, createHmac } from 'node:crypto';
|
|
5
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, chmodSync } from 'node:fs';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
const IDENTITY_DIR = join(homedir(), '.stellavault', 'federation');
|
|
9
|
+
const IDENTITY_FILE = join(IDENTITY_DIR, 'identity.json');
|
|
10
|
+
export function getOrCreateIdentity(displayName) {
|
|
11
|
+
if (existsSync(IDENTITY_FILE)) {
|
|
12
|
+
const raw = JSON.parse(readFileSync(IDENTITY_FILE, 'utf-8'));
|
|
13
|
+
return {
|
|
14
|
+
peerId: raw.peerId,
|
|
15
|
+
publicKey: Buffer.from(raw.publicKey, 'hex'),
|
|
16
|
+
secretKey: Buffer.from(raw.secretKey, 'hex'),
|
|
17
|
+
displayName: raw.displayName,
|
|
18
|
+
createdAt: raw.createdAt,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const secretKey = randomBytes(32);
|
|
22
|
+
const publicKey = createHash('sha256').update(secretKey).digest();
|
|
23
|
+
const peerId = createHash('sha256').update(publicKey).digest('hex').slice(0, 16);
|
|
24
|
+
const identity = {
|
|
25
|
+
peerId,
|
|
26
|
+
publicKey,
|
|
27
|
+
secretKey,
|
|
28
|
+
displayName: displayName ?? `node-${peerId.slice(0, 6)}`,
|
|
29
|
+
createdAt: new Date().toISOString(),
|
|
30
|
+
};
|
|
31
|
+
mkdirSync(IDENTITY_DIR, { recursive: true });
|
|
32
|
+
const content = JSON.stringify({
|
|
33
|
+
peerId: identity.peerId,
|
|
34
|
+
publicKey: publicKey.toString('hex'),
|
|
35
|
+
secretKey: secretKey.toString('hex'),
|
|
36
|
+
displayName: identity.displayName,
|
|
37
|
+
createdAt: identity.createdAt,
|
|
38
|
+
}, null, 2);
|
|
39
|
+
writeFileSync(IDENTITY_FILE, content, { encoding: 'utf-8', mode: 0o600 });
|
|
40
|
+
try {
|
|
41
|
+
chmodSync(IDENTITY_FILE, 0o600);
|
|
42
|
+
}
|
|
43
|
+
catch { /* Windows may not support */ }
|
|
44
|
+
return identity;
|
|
45
|
+
}
|
|
46
|
+
// CRIT-01 fix: 실제 HMAC-SHA256 서명
|
|
47
|
+
export function signMessage(secretKey, message) {
|
|
48
|
+
return createHmac('sha256', secretKey).update(message).digest();
|
|
49
|
+
}
|
|
50
|
+
// CRIT-01 fix: 실제 HMAC-SHA256 검증
|
|
51
|
+
export function verifySignature(publicKey, secretKey, message, signature) {
|
|
52
|
+
const expected = createHmac('sha256', secretKey).update(message).digest();
|
|
53
|
+
if (expected.length !== signature.length)
|
|
54
|
+
return false;
|
|
55
|
+
// Timing-safe comparison
|
|
56
|
+
let diff = 0;
|
|
57
|
+
for (let i = 0; i < expected.length; i++) {
|
|
58
|
+
diff |= expected[i] ^ signature[i];
|
|
59
|
+
}
|
|
60
|
+
return diff === 0;
|
|
61
|
+
}
|
|
62
|
+
// Challenge-response 인증용 nonce 생성
|
|
63
|
+
export function createChallenge() {
|
|
64
|
+
return randomBytes(32);
|
|
65
|
+
}
|
|
66
|
+
// Challenge에 대한 응답 생성
|
|
67
|
+
export function respondToChallenge(secretKey, challenge) {
|
|
68
|
+
return signMessage(secretKey, challenge);
|
|
69
|
+
}
|
|
70
|
+
// Challenge 응답 검증
|
|
71
|
+
export function verifyChallenge(secretKey, challenge, response) {
|
|
72
|
+
return verifySignature(Buffer.alloc(0), secretKey, challenge, response);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
// Design Ref: §2.3 — Federation Public API
|
|
2
|
-
|
|
3
1
|
export { FederationNode } from './node.js';
|
|
4
2
|
export { FederatedSearch } from './search.js';
|
|
5
3
|
export type { FederatedSearchOptions } from './search.js';
|
|
6
4
|
export { getOrCreateIdentity } from './identity.js';
|
|
7
5
|
export type { NodeIdentity } from './identity.js';
|
|
8
6
|
export type { PeerInfo, FederatedSearchResult, FederationMessage } from './types.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { PeerInfo } from './types.js';
|
|
3
|
+
export declare class FederationNode extends EventEmitter {
|
|
4
|
+
private swarm;
|
|
5
|
+
private identity;
|
|
6
|
+
private peers;
|
|
7
|
+
private running;
|
|
8
|
+
private documentCount;
|
|
9
|
+
private topTopics;
|
|
10
|
+
constructor(displayName?: string);
|
|
11
|
+
get peerId(): string;
|
|
12
|
+
get displayName(): string;
|
|
13
|
+
get peerCount(): number;
|
|
14
|
+
get isRunning(): boolean;
|
|
15
|
+
setLocalStats(documentCount: number, topTopics: string[]): void;
|
|
16
|
+
join(): Promise<void>;
|
|
17
|
+
joinDirect(host: string, port: number): Promise<void>;
|
|
18
|
+
leave(): Promise<void>;
|
|
19
|
+
getPeers(): PeerInfo[];
|
|
20
|
+
sendSearchQuery(peerId: string, queryId: string, embedding: number[], limit: number): void;
|
|
21
|
+
sendSearchResult(peerId: string, queryId: string, results: Array<{
|
|
22
|
+
title: string;
|
|
23
|
+
similarity: number;
|
|
24
|
+
snippet: string;
|
|
25
|
+
}>): void;
|
|
26
|
+
private handleConnection;
|
|
27
|
+
private validateMessage;
|
|
28
|
+
private handleMessage;
|
|
29
|
+
private sendMessage;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=node.d.ts.map
|