stellavault 0.4.4 → 0.5.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.
Files changed (265) hide show
  1. package/README.md +52 -16
  2. package/SECURITY.md +50 -0
  3. package/dist/stellavault.js +8968 -0
  4. package/package.json +70 -33
  5. package/.env.example +0 -12
  6. package/CHANGELOG.md +0 -106
  7. package/CLAUDE.md +0 -42
  8. package/CONTRIBUTING.md +0 -65
  9. package/index.html +0 -509
  10. package/packages/cli/bin/ekh.js +0 -2
  11. package/packages/cli/bin/stellavault.js +0 -2
  12. package/packages/cli/dist/commands/adr-cmd.d.ts +0 -7
  13. package/packages/cli/dist/commands/adr-cmd.js +0 -45
  14. package/packages/cli/dist/commands/ask-cmd.d.ts +0 -5
  15. package/packages/cli/dist/commands/ask-cmd.js +0 -36
  16. package/packages/cli/dist/commands/autopilot-cmd.d.ts +0 -4
  17. package/packages/cli/dist/commands/autopilot-cmd.js +0 -76
  18. package/packages/cli/dist/commands/brief-cmd.d.ts +0 -2
  19. package/packages/cli/dist/commands/brief-cmd.js +0 -82
  20. package/packages/cli/dist/commands/capture-cmd.d.ts +0 -7
  21. package/packages/cli/dist/commands/capture-cmd.js +0 -31
  22. package/packages/cli/dist/commands/card-cmd.d.ts +0 -4
  23. package/packages/cli/dist/commands/card-cmd.js +0 -26
  24. package/packages/cli/dist/commands/clip-cmd.d.ts +0 -4
  25. package/packages/cli/dist/commands/clip-cmd.js +0 -151
  26. package/packages/cli/dist/commands/cloud-cmd.d.ts +0 -4
  27. package/packages/cli/dist/commands/cloud-cmd.js +0 -64
  28. package/packages/cli/dist/commands/compile-cmd.d.ts +0 -6
  29. package/packages/cli/dist/commands/compile-cmd.js +0 -30
  30. package/packages/cli/dist/commands/contradictions-cmd.d.ts +0 -2
  31. package/packages/cli/dist/commands/contradictions-cmd.js +0 -34
  32. package/packages/cli/dist/commands/decay-cmd.d.ts +0 -2
  33. package/packages/cli/dist/commands/decay-cmd.js +0 -48
  34. package/packages/cli/dist/commands/digest-cmd.d.ts +0 -5
  35. package/packages/cli/dist/commands/digest-cmd.js +0 -136
  36. package/packages/cli/dist/commands/draft-cmd.d.ts +0 -6
  37. package/packages/cli/dist/commands/draft-cmd.js +0 -110
  38. package/packages/cli/dist/commands/duplicates-cmd.d.ts +0 -4
  39. package/packages/cli/dist/commands/duplicates-cmd.js +0 -30
  40. package/packages/cli/dist/commands/federate-cmd.d.ts +0 -5
  41. package/packages/cli/dist/commands/federate-cmd.js +0 -247
  42. package/packages/cli/dist/commands/fleeting-cmd.d.ts +0 -4
  43. package/packages/cli/dist/commands/fleeting-cmd.js +0 -45
  44. package/packages/cli/dist/commands/flush-cmd.d.ts +0 -2
  45. package/packages/cli/dist/commands/flush-cmd.js +0 -58
  46. package/packages/cli/dist/commands/gaps-cmd.d.ts +0 -2
  47. package/packages/cli/dist/commands/gaps-cmd.js +0 -33
  48. package/packages/cli/dist/commands/graph-cmd.d.ts +0 -2
  49. package/packages/cli/dist/commands/graph-cmd.js +0 -89
  50. package/packages/cli/dist/commands/index-cmd.d.ts +0 -2
  51. package/packages/cli/dist/commands/index-cmd.js +0 -57
  52. package/packages/cli/dist/commands/ingest-cmd.d.ts +0 -9
  53. package/packages/cli/dist/commands/ingest-cmd.js +0 -195
  54. package/packages/cli/dist/commands/init-cmd.d.ts +0 -2
  55. package/packages/cli/dist/commands/init-cmd.js +0 -161
  56. package/packages/cli/dist/commands/learn-cmd.d.ts +0 -2
  57. package/packages/cli/dist/commands/learn-cmd.js +0 -48
  58. package/packages/cli/dist/commands/lint-cmd.d.ts +0 -2
  59. package/packages/cli/dist/commands/lint-cmd.js +0 -61
  60. package/packages/cli/dist/commands/pack-cmd.d.ts +0 -15
  61. package/packages/cli/dist/commands/pack-cmd.js +0 -93
  62. package/packages/cli/dist/commands/review-cmd.d.ts +0 -4
  63. package/packages/cli/dist/commands/review-cmd.js +0 -107
  64. package/packages/cli/dist/commands/search-cmd.d.ts +0 -4
  65. package/packages/cli/dist/commands/search-cmd.js +0 -38
  66. package/packages/cli/dist/commands/serve-cmd.d.ts +0 -2
  67. package/packages/cli/dist/commands/serve-cmd.js +0 -14
  68. package/packages/cli/dist/commands/session-cmd.d.ts +0 -7
  69. package/packages/cli/dist/commands/session-cmd.js +0 -95
  70. package/packages/cli/dist/commands/status-cmd.d.ts +0 -2
  71. package/packages/cli/dist/commands/status-cmd.js +0 -33
  72. package/packages/cli/dist/commands/sync-cmd.d.ts +0 -5
  73. package/packages/cli/dist/commands/sync-cmd.js +0 -62
  74. package/packages/cli/dist/commands/vault-cmd.d.ts +0 -10
  75. package/packages/cli/dist/commands/vault-cmd.js +0 -54
  76. package/packages/cli/dist/index.d.ts +0 -2
  77. package/packages/cli/dist/index.js +0 -233
  78. package/packages/cli/package.json +0 -24
  79. package/packages/core/dist/api/dashboard.d.ts +0 -3
  80. package/packages/core/dist/api/dashboard.js +0 -135
  81. package/packages/core/dist/api/graph-data.d.ts +0 -11
  82. package/packages/core/dist/api/graph-data.js +0 -255
  83. package/packages/core/dist/api/pwa.d.ts +0 -3
  84. package/packages/core/dist/api/pwa.js +0 -77
  85. package/packages/core/dist/api/server.d.ts +0 -16
  86. package/packages/core/dist/api/server.js +0 -1122
  87. package/packages/core/dist/capture/voice.d.ts +0 -24
  88. package/packages/core/dist/capture/voice.js +0 -135
  89. package/packages/core/dist/cloud/index.d.ts +0 -3
  90. package/packages/core/dist/cloud/index.js +0 -2
  91. package/packages/core/dist/cloud/sync.d.ts +0 -29
  92. package/packages/core/dist/cloud/sync.js +0 -137
  93. package/packages/core/dist/config.d.ts +0 -35
  94. package/packages/core/dist/config.js +0 -63
  95. package/packages/core/dist/federation/credits.d.ts +0 -26
  96. package/packages/core/dist/federation/credits.js +0 -56
  97. package/packages/core/dist/federation/identity.d.ts +0 -14
  98. package/packages/core/dist/federation/identity.js +0 -74
  99. package/packages/core/dist/federation/index.d.ts +0 -7
  100. package/packages/core/dist/federation/index.js +0 -5
  101. package/packages/core/dist/federation/node.d.ts +0 -31
  102. package/packages/core/dist/federation/node.js +0 -216
  103. package/packages/core/dist/federation/privacy.d.ts +0 -8
  104. package/packages/core/dist/federation/privacy.js +0 -40
  105. package/packages/core/dist/federation/reputation.d.ts +0 -37
  106. package/packages/core/dist/federation/reputation.js +0 -139
  107. package/packages/core/dist/federation/search.d.ts +0 -19
  108. package/packages/core/dist/federation/search.js +0 -101
  109. package/packages/core/dist/federation/sharing.d.ts +0 -72
  110. package/packages/core/dist/federation/sharing.js +0 -246
  111. package/packages/core/dist/federation/trust.d.ts +0 -15
  112. package/packages/core/dist/federation/trust.js +0 -60
  113. package/packages/core/dist/federation/types.d.ts +0 -40
  114. package/packages/core/dist/federation/types.js +0 -3
  115. package/packages/core/dist/i18n/index.d.ts +0 -6
  116. package/packages/core/dist/i18n/index.js +0 -81
  117. package/packages/core/dist/i18n/note-strings.d.ts +0 -5
  118. package/packages/core/dist/i18n/note-strings.js +0 -94
  119. package/packages/core/dist/index.d.ts +0 -123
  120. package/packages/core/dist/index.js +0 -74
  121. package/packages/core/dist/indexer/chunker.d.ts +0 -14
  122. package/packages/core/dist/indexer/chunker.js +0 -148
  123. package/packages/core/dist/indexer/embedder.d.ts +0 -8
  124. package/packages/core/dist/indexer/embedder.js +0 -3
  125. package/packages/core/dist/indexer/index.d.ts +0 -28
  126. package/packages/core/dist/indexer/index.js +0 -74
  127. package/packages/core/dist/indexer/local-embedder.d.ts +0 -3
  128. package/packages/core/dist/indexer/local-embedder.js +0 -29
  129. package/packages/core/dist/indexer/scanner.d.ts +0 -11
  130. package/packages/core/dist/indexer/scanner.js +0 -148
  131. package/packages/core/dist/indexer/watcher.d.ts +0 -19
  132. package/packages/core/dist/indexer/watcher.js +0 -49
  133. package/packages/core/dist/intelligence/ask-engine.d.ts +0 -24
  134. package/packages/core/dist/intelligence/ask-engine.js +0 -142
  135. package/packages/core/dist/intelligence/auto-linker.d.ts +0 -19
  136. package/packages/core/dist/intelligence/auto-linker.js +0 -126
  137. package/packages/core/dist/intelligence/code-linker.d.ts +0 -20
  138. package/packages/core/dist/intelligence/code-linker.js +0 -88
  139. package/packages/core/dist/intelligence/contradiction-detector.d.ts +0 -20
  140. package/packages/core/dist/intelligence/contradiction-detector.js +0 -115
  141. package/packages/core/dist/intelligence/decay-engine.d.ts +0 -27
  142. package/packages/core/dist/intelligence/decay-engine.js +0 -190
  143. package/packages/core/dist/intelligence/draft-generator.d.ts +0 -25
  144. package/packages/core/dist/intelligence/draft-generator.js +0 -277
  145. package/packages/core/dist/intelligence/duplicate-detector.d.ts +0 -20
  146. package/packages/core/dist/intelligence/duplicate-detector.js +0 -55
  147. package/packages/core/dist/intelligence/file-extractors.d.ts +0 -13
  148. package/packages/core/dist/intelligence/file-extractors.js +0 -155
  149. package/packages/core/dist/intelligence/fsrs.d.ts +0 -43
  150. package/packages/core/dist/intelligence/fsrs.js +0 -70
  151. package/packages/core/dist/intelligence/gap-detector.d.ts +0 -25
  152. package/packages/core/dist/intelligence/gap-detector.js +0 -78
  153. package/packages/core/dist/intelligence/ingest-pipeline.d.ts +0 -32
  154. package/packages/core/dist/intelligence/ingest-pipeline.js +0 -245
  155. package/packages/core/dist/intelligence/knowledge-lint.d.ts +0 -27
  156. package/packages/core/dist/intelligence/knowledge-lint.js +0 -132
  157. package/packages/core/dist/intelligence/learning-path.d.ts +0 -31
  158. package/packages/core/dist/intelligence/learning-path.js +0 -53
  159. package/packages/core/dist/intelligence/notifications.d.ts +0 -31
  160. package/packages/core/dist/intelligence/notifications.js +0 -65
  161. package/packages/core/dist/intelligence/predictive-gaps.d.ts +0 -14
  162. package/packages/core/dist/intelligence/predictive-gaps.js +0 -74
  163. package/packages/core/dist/intelligence/semantic-versioning.d.ts +0 -37
  164. package/packages/core/dist/intelligence/semantic-versioning.js +0 -68
  165. package/packages/core/dist/intelligence/types.d.ts +0 -28
  166. package/packages/core/dist/intelligence/types.js +0 -3
  167. package/packages/core/dist/intelligence/wiki-compiler.d.ts +0 -30
  168. package/packages/core/dist/intelligence/wiki-compiler.js +0 -222
  169. package/packages/core/dist/intelligence/youtube-extractor.d.ts +0 -29
  170. package/packages/core/dist/intelligence/youtube-extractor.js +0 -321
  171. package/packages/core/dist/intelligence/zettelkasten.d.ts +0 -59
  172. package/packages/core/dist/intelligence/zettelkasten.js +0 -234
  173. package/packages/core/dist/mcp/custom-tools.d.ts +0 -29
  174. package/packages/core/dist/mcp/custom-tools.js +0 -70
  175. package/packages/core/dist/mcp/index.d.ts +0 -2
  176. package/packages/core/dist/mcp/index.js +0 -2
  177. package/packages/core/dist/mcp/server.d.ts +0 -51
  178. package/packages/core/dist/mcp/server.js +0 -174
  179. package/packages/core/dist/mcp/tools/agentic-graph.d.ts +0 -93
  180. package/packages/core/dist/mcp/tools/agentic-graph.js +0 -116
  181. package/packages/core/dist/mcp/tools/ask.d.ts +0 -29
  182. package/packages/core/dist/mcp/tools/ask.js +0 -43
  183. package/packages/core/dist/mcp/tools/brief.d.ts +0 -31
  184. package/packages/core/dist/mcp/tools/brief.js +0 -39
  185. package/packages/core/dist/mcp/tools/decay.d.ts +0 -33
  186. package/packages/core/dist/mcp/tools/decay.js +0 -32
  187. package/packages/core/dist/mcp/tools/decision-journal.d.ts +0 -78
  188. package/packages/core/dist/mcp/tools/decision-journal.js +0 -79
  189. package/packages/core/dist/mcp/tools/detect-gaps.d.ts +0 -24
  190. package/packages/core/dist/mcp/tools/detect-gaps.js +0 -47
  191. package/packages/core/dist/mcp/tools/export.d.ts +0 -29
  192. package/packages/core/dist/mcp/tools/export.js +0 -60
  193. package/packages/core/dist/mcp/tools/federated-search.d.ts +0 -29
  194. package/packages/core/dist/mcp/tools/federated-search.js +0 -36
  195. package/packages/core/dist/mcp/tools/generate-claude-md.d.ts +0 -35
  196. package/packages/core/dist/mcp/tools/generate-claude-md.js +0 -107
  197. package/packages/core/dist/mcp/tools/generate-draft.d.ts +0 -34
  198. package/packages/core/dist/mcp/tools/generate-draft.js +0 -120
  199. package/packages/core/dist/mcp/tools/get-document.d.ts +0 -35
  200. package/packages/core/dist/mcp/tools/get-document.js +0 -25
  201. package/packages/core/dist/mcp/tools/get-evolution.d.ts +0 -28
  202. package/packages/core/dist/mcp/tools/get-evolution.js +0 -70
  203. package/packages/core/dist/mcp/tools/get-related.d.ts +0 -32
  204. package/packages/core/dist/mcp/tools/get-related.js +0 -33
  205. package/packages/core/dist/mcp/tools/learning-path.d.ts +0 -23
  206. package/packages/core/dist/mcp/tools/learning-path.js +0 -45
  207. package/packages/core/dist/mcp/tools/link-code.d.ts +0 -34
  208. package/packages/core/dist/mcp/tools/link-code.js +0 -44
  209. package/packages/core/dist/mcp/tools/list-topics.d.ts +0 -15
  210. package/packages/core/dist/mcp/tools/list-topics.js +0 -18
  211. package/packages/core/dist/mcp/tools/search.d.ts +0 -39
  212. package/packages/core/dist/mcp/tools/search.js +0 -29
  213. package/packages/core/dist/mcp/tools/snapshot.d.ts +0 -47
  214. package/packages/core/dist/mcp/tools/snapshot.js +0 -84
  215. package/packages/core/dist/multi-vault/index.d.ts +0 -26
  216. package/packages/core/dist/multi-vault/index.js +0 -80
  217. package/packages/core/dist/pack/creator.d.ts +0 -21
  218. package/packages/core/dist/pack/creator.js +0 -105
  219. package/packages/core/dist/pack/exporter.d.ts +0 -4
  220. package/packages/core/dist/pack/exporter.js +0 -18
  221. package/packages/core/dist/pack/importer.d.ts +0 -10
  222. package/packages/core/dist/pack/importer.js +0 -55
  223. package/packages/core/dist/pack/index.d.ts +0 -6
  224. package/packages/core/dist/pack/index.js +0 -5
  225. package/packages/core/dist/pack/marketplace.d.ts +0 -14
  226. package/packages/core/dist/pack/marketplace.js +0 -90
  227. package/packages/core/dist/pack/pii-masker.d.ts +0 -7
  228. package/packages/core/dist/pack/pii-masker.js +0 -29
  229. package/packages/core/dist/pack/types.d.ts +0 -36
  230. package/packages/core/dist/pack/types.js +0 -3
  231. package/packages/core/dist/plugins/index.d.ts +0 -35
  232. package/packages/core/dist/plugins/index.js +0 -57
  233. package/packages/core/dist/plugins/webhooks.d.ts +0 -30
  234. package/packages/core/dist/plugins/webhooks.js +0 -79
  235. package/packages/core/dist/search/adaptive.d.ts +0 -16
  236. package/packages/core/dist/search/adaptive.js +0 -67
  237. package/packages/core/dist/search/bm25.d.ts +0 -4
  238. package/packages/core/dist/search/bm25.js +0 -10
  239. package/packages/core/dist/search/index.d.ts +0 -15
  240. package/packages/core/dist/search/index.js +0 -64
  241. package/packages/core/dist/search/rrf.d.ts +0 -7
  242. package/packages/core/dist/search/rrf.js +0 -21
  243. package/packages/core/dist/search/semantic.d.ts +0 -5
  244. package/packages/core/dist/search/semantic.js +0 -6
  245. package/packages/core/dist/store/index.d.ts +0 -3
  246. package/packages/core/dist/store/index.js +0 -2
  247. package/packages/core/dist/store/sqlite-vec.d.ts +0 -6
  248. package/packages/core/dist/store/sqlite-vec.js +0 -251
  249. package/packages/core/dist/store/types.d.ts +0 -20
  250. package/packages/core/dist/store/types.js +0 -3
  251. package/packages/core/dist/team/index.d.ts +0 -25
  252. package/packages/core/dist/team/index.js +0 -97
  253. package/packages/core/dist/types/chunk.d.ts +0 -23
  254. package/packages/core/dist/types/chunk.js +0 -3
  255. package/packages/core/dist/types/document.d.ts +0 -23
  256. package/packages/core/dist/types/document.js +0 -3
  257. package/packages/core/dist/types/graph.d.ts +0 -39
  258. package/packages/core/dist/types/graph.js +0 -3
  259. package/packages/core/dist/types/index.d.ts +0 -5
  260. package/packages/core/dist/types/index.js +0 -2
  261. package/packages/core/dist/types/search.d.ts +0 -39
  262. package/packages/core/dist/types/search.js +0 -3
  263. package/packages/core/dist/utils/retry.d.ts +0 -25
  264. package/packages/core/dist/utils/retry.js +0 -59
  265. package/packages/core/package.json +0 -67
@@ -1,233 +0,0 @@
1
- import { Command } from 'commander';
2
- import { indexCommand } from './commands/index-cmd.js';
3
- import { searchCommand } from './commands/search-cmd.js';
4
- import { serveCommand } from './commands/serve-cmd.js';
5
- import { statusCommand } from './commands/status-cmd.js';
6
- import { graphCommand } from './commands/graph-cmd.js';
7
- import { cardCommand } from './commands/card-cmd.js';
8
- import { packCreateCommand, packExportCommand, packImportCommand, packListCommand, packInfoCommand } from './commands/pack-cmd.js';
9
- import { decayCommand } from './commands/decay-cmd.js';
10
- import { syncCommand } from './commands/sync-cmd.js';
11
- import { reviewCommand } from './commands/review-cmd.js';
12
- import { duplicatesCommand } from './commands/duplicates-cmd.js';
13
- import { gapsCommand } from './commands/gaps-cmd.js';
14
- import { clipCommand } from './commands/clip-cmd.js';
15
- import { briefCommand } from './commands/brief-cmd.js';
16
- import { digestCommand } from './commands/digest-cmd.js';
17
- import { initCommand } from './commands/init-cmd.js';
18
- import { learnCommand } from './commands/learn-cmd.js';
19
- import { contradictionsCommand } from './commands/contradictions-cmd.js';
20
- import { federateJoinCommand, federateStatusCommand } from './commands/federate-cmd.js';
21
- import { cloudSyncCommand, cloudRestoreCommand, cloudStatusCommand } from './commands/cloud-cmd.js';
22
- import { vaultAddCommand, vaultListCommand, vaultRemoveCommand, vaultSearchAllCommand } from './commands/vault-cmd.js';
23
- import { captureCommand } from './commands/capture-cmd.js';
24
- import { askCommand } from './commands/ask-cmd.js';
25
- import { compileCommand } from './commands/compile-cmd.js';
26
- import { draftCommand } from './commands/draft-cmd.js';
27
- import { sessionSaveCommand } from './commands/session-cmd.js';
28
- import { flushCommand } from './commands/flush-cmd.js';
29
- import { adrCommand } from './commands/adr-cmd.js';
30
- import { lintCommand } from './commands/lint-cmd.js';
31
- import { fleetingCommand } from './commands/fleeting-cmd.js';
32
- import { ingestCommand, promoteCommand } from './commands/ingest-cmd.js';
33
- import { autopilotCommand } from './commands/autopilot-cmd.js';
34
- const program = new Command();
35
- program
36
- .name('stellavault')
37
- .description('Stellavault — Turn your Obsidian vault into a 3D neural knowledge graph')
38
- .version('0.3.0')
39
- .option('--json', 'Output in JSON format (for scripting)')
40
- .option('--quiet', 'Suppress non-essential output');
41
- program
42
- .command('init')
43
- .description('Interactive setup wizard — get started in 3 minutes')
44
- .action(initCommand);
45
- program
46
- .command('index [vault-path]')
47
- .description('Obsidian vault를 벡터화하여 인덱싱합니다')
48
- .action(indexCommand);
49
- program
50
- .command('search <query>')
51
- .description('지식 베이스에서 검색합니다')
52
- .option('-l, --limit <n>', '결과 수', '5')
53
- .action(searchCommand);
54
- program
55
- .command('serve')
56
- .description('MCP 서버를 시작합니다 (Claude Code 연동)')
57
- .action(serveCommand);
58
- program
59
- .command('status')
60
- .description('인덱스 상태를 확인합니다')
61
- .action(statusCommand);
62
- program
63
- .command('graph')
64
- .description('3D Knowledge Graph API 서버를 시작합니다')
65
- .action(graphCommand);
66
- program
67
- .command('card')
68
- .description('SVG 프로필 카드를 생성합니다')
69
- .option('-o, --output <path>', '출력 파일 경로', 'knowledge-card.svg')
70
- .action(cardCommand);
71
- program
72
- .command('learn')
73
- .description('AI learning path — personalized recommendations based on decay + gaps')
74
- .action(learnCommand);
75
- program
76
- .command('contradictions')
77
- .description('Detect contradicting statements across your notes')
78
- .action(contradictionsCommand);
79
- program
80
- .command('decay')
81
- .description('지식 감쇠 리포트를 출력합니다 (잊어가는 노트 확인)')
82
- .action(decayCommand);
83
- program
84
- .command('brief')
85
- .description('오늘의 지식 브리핑 (감쇠 + 갭 + 활동 요약)')
86
- .action(briefCommand);
87
- program
88
- .command('digest')
89
- .description('주간 지식 활동 리포트')
90
- .option('-d, --days <n>', '기간 (일)', '7')
91
- .option('-v, --visual', 'Save as .md with Mermaid charts for Obsidian')
92
- .action(digestCommand);
93
- program
94
- .command('clip <url>')
95
- .description('웹 페이지/YouTube를 Obsidian에 클리핑')
96
- .option('-f, --folder <path>', 'vault 내 저장 폴더', '06_Research/clips')
97
- .action(clipCommand);
98
- program
99
- .command('gaps')
100
- .description('지식 갭을 탐지합니다 (클러스터 간 연결 부족 영역)')
101
- .action(gapsCommand);
102
- program
103
- .command('duplicates')
104
- .description('중복/유사 노트를 탐지합니다')
105
- .option('-t, --threshold <n>', '유사도 임계값 (0~1)', '0.88')
106
- .action(duplicatesCommand);
107
- program
108
- .command('review')
109
- .description('일일 지식 리뷰 — 잊어가는 노트를 Obsidian에서 열어 리뷰')
110
- .option('-n, --count <n>', '리뷰할 노트 수', '5')
111
- .action(reviewCommand);
112
- program
113
- .command('sync')
114
- .description('Notion → Obsidian 동기화')
115
- .option('--upload', 'PDCA 문서를 Notion에 업로드')
116
- .option('--watch', '5분 간격 자동 동기화')
117
- .action(syncCommand);
118
- const federate = program.command('federate').description('Federation — P2P knowledge network');
119
- federate.command('join')
120
- .description('Join the federation network (interactive mode)')
121
- .option('-n, --name <name>', 'Display name for this node')
122
- .action(federateJoinCommand);
123
- federate.command('status')
124
- .description('Show federation identity and status')
125
- .action(federateStatusCommand);
126
- program
127
- .command('capture <audio-file>')
128
- .description('Voice capture — transcribe audio to knowledge note (requires Whisper)')
129
- .option('-m, --model <model>', 'Whisper model (tiny/base/small/medium/large)', 'base')
130
- .option('-l, --language <lang>', 'Language (auto-detect if omitted)')
131
- .option('-t, --tags <tags>', 'Comma-separated tags')
132
- .option('-f, --folder <folder>', 'Vault subfolder', '01_Knowledge/voice')
133
- .action(captureCommand);
134
- program
135
- .command('ask <question>')
136
- .description('Ask a question about your knowledge base — search, compose answer, optionally save')
137
- .option('-s, --save', 'Save answer as a new note in your vault')
138
- .option('-q, --quotes', 'Show direct quotes from sources (Insight Extraction mode)')
139
- .action((question, opts) => askCommand(question, opts));
140
- program
141
- .command('compile')
142
- .description('Compile raw/ documents into a structured wiki')
143
- .option('-r, --raw <dir>', 'Raw documents directory (default: raw/)')
144
- .option('-w, --wiki <dir>', 'Wiki output directory (default: _wiki/)')
145
- .option('-f, --force', 'Overwrite existing wiki files')
146
- .action((opts) => compileCommand(opts));
147
- program
148
- .command('draft [topic]')
149
- .description('Express: Generate draft from knowledge (blog/report/outline/instagram/thread/script)')
150
- .option('--format <type>', 'Output format: blog, report, outline, instagram, thread, script')
151
- .option('--ai', 'Use Claude API for AI-enhanced draft (requires ANTHROPIC_API_KEY)')
152
- .option('--blueprint <spec>', 'Chapter structure: "Ch1:tag1,tag2; Ch2:tag3"')
153
- .action((topic, opts) => draftCommand(topic, opts));
154
- program
155
- .command('session-save')
156
- .description('Save session summary to daily log (used by Claude Code hooks)')
157
- .option('-s, --summary <text>', 'Session summary text (or pipe via stdin)')
158
- .option('-d, --decisions <text>', 'Key decisions made')
159
- .option('-l, --lessons <text>', 'Lessons learned')
160
- .option('-a, --actions <text>', 'Action items')
161
- .action((opts) => sessionSaveCommand(opts));
162
- program
163
- .command('flush')
164
- .description('Flush daily logs → wiki: extract concepts, rebuild connections (Karpathy compile)')
165
- .action(() => flushCommand());
166
- program
167
- .command('adr <title>')
168
- .description('Create an Architecture Decision Record (structured decision log)')
169
- .option('--context <text>', 'Why is this decision needed?')
170
- .option('--options <text>', 'What alternatives were considered?')
171
- .option('--decision <text>', 'What was decided and why?')
172
- .option('--consequences <text>', 'What are the implications?')
173
- .action((title, opts) => adrCommand(title, opts));
174
- program
175
- .command('lint')
176
- .description('Knowledge health check — find gaps, duplicates, contradictions, stale notes')
177
- .action(() => lintCommand());
178
- program
179
- .command('fleeting <text>')
180
- .description('Capture a fleeting idea instantly to raw/ folder')
181
- .option('-t, --tags <tags>', 'Comma-separated tags')
182
- .action((text, opts) => fleetingCommand(text, opts));
183
- program
184
- .command('ingest <input>')
185
- .description('Ingest any input (URL, file, text) into your knowledge base')
186
- .option('-t, --tags <tags>', 'Comma-separated tags')
187
- .option('-s, --stage <stage>', 'Note stage: fleeting, literature, permanent', 'fleeting')
188
- .option('--title <title>', 'Override title')
189
- .action((input, opts) => ingestCommand(input, opts));
190
- program
191
- .command('promote <file>')
192
- .description('Promote a note: fleeting → literature → permanent')
193
- .requiredOption('--to <stage>', 'Target stage: literature or permanent')
194
- .action((file, opts) => promoteCommand(file, opts));
195
- program
196
- .command('autopilot')
197
- .description('Run the full knowledge flywheel: inbox → compile → lint')
198
- .option('--once', 'Run once (default)')
199
- .action((opts) => autopilotCommand(opts));
200
- const vault = program.command('vault').description('Multi-Vault — manage and search across vaults');
201
- vault.command('add <id> <path>').description('Register a vault').option('-n, --name <name>', 'Display name').option('-s, --shared', 'Allow federation sharing').action(vaultAddCommand);
202
- vault.command('list').description('List registered vaults').action(vaultListCommand);
203
- vault.command('remove <id>').description('Unregister a vault').action(vaultRemoveCommand);
204
- vault.command('search-all <query>').description('Search across all registered vaults').option('-l, --limit <n>', 'Max results', '10').action(vaultSearchAllCommand);
205
- const cloud = program.command('cloud').description('Cloud — E2E encrypted backup');
206
- cloud.command('sync').description('Upload encrypted DB to cloud').action(cloudSyncCommand);
207
- cloud.command('restore').description('Download and decrypt DB from cloud').action(cloudRestoreCommand);
208
- cloud.command('status').description('Show last sync status').action(cloudStatusCommand);
209
- const pack = program.command('pack').description('Knowledge Pack 관리');
210
- pack.command('create <name>')
211
- .description('검색/클러스터 기반 Knowledge Pack 생성')
212
- .option('--from-search <query>', '검색 쿼리에서 생성')
213
- .option('--from-cluster <id>', '클러스터 ID에서 생성')
214
- .option('--author <name>', '작성자', 'anonymous')
215
- .option('--license <license>', '라이선스', 'CC-BY-4.0')
216
- .option('--description <desc>', '설명')
217
- .option('--limit <n>', '최대 청크 수', '100')
218
- .action(packCreateCommand);
219
- pack.command('export <name>')
220
- .description('.sv-pack 파일로 내보내기')
221
- .option('-o, --output <path>', '출력 경로')
222
- .action(packExportCommand);
223
- pack.command('import <file>')
224
- .description('.sv-pack 파일 가져오기 → 벡터 DB 병합')
225
- .action(packImportCommand);
226
- pack.command('list')
227
- .description('설치된 팩 목록')
228
- .action(packListCommand);
229
- pack.command('info <name>')
230
- .description('팩 상세 정보')
231
- .action(packInfoCommand);
232
- program.parse();
233
- //# sourceMappingURL=index.js.map
@@ -1,24 +0,0 @@
1
- {
2
- "name": "@stellavault/cli",
3
- "version": "0.4.0",
4
- "description": "Stellavault CLI — stellavault index, search, serve, graph",
5
- "type": "module",
6
- "bin": {
7
- "stellavault": "./bin/stellavault.js",
8
- "sv": "./bin/stellavault.js"
9
- },
10
- "scripts": {
11
- "build": "tsc"
12
- },
13
- "dependencies": {
14
- "@stellavault/core": "*",
15
- "chalk": "^5.6.2",
16
- "commander": "^14.0.3",
17
- "open": "^11.0.0",
18
- "ora": "^9.3.0"
19
- },
20
- "devDependencies": {
21
- "@types/node": "^25.5.0",
22
- "typescript": "^5.7.0"
23
- }
24
- }
@@ -1,3 +0,0 @@
1
- import type { Express } from 'express';
2
- export declare function mountDashboard(app: Express): void;
3
- //# sourceMappingURL=dashboard.d.ts.map
@@ -1,135 +0,0 @@
1
- // Web Dashboard (P3-F26) — Express에 HTML 대시보드 추가
2
- // http://localhost:3333/dashboard
3
- export function mountDashboard(app) {
4
- app.get('/dashboard', (_req, res) => {
5
- res.setHeader('Content-Type', 'text/html');
6
- res.send(getDashboardHTML());
7
- });
8
- }
9
- function getDashboardHTML() {
10
- return `<!DOCTYPE html>
11
- <html lang="en">
12
- <head>
13
- <meta charset="UTF-8">
14
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
15
- <title>Stellavault Dashboard</title>
16
- <style>
17
- * { margin: 0; padding: 0; box-sizing: border-box; }
18
- body { font-family: system-ui, -apple-system, sans-serif; background: #050510; color: #c0c0f0; min-height: 100vh; }
19
- .header { padding: 16px 24px; border-bottom: 1px solid rgba(100,120,255,0.1); display: flex; align-items: center; gap: 12px; }
20
- .header h1 { font-size: 18px; font-weight: 600; }
21
- .header .subtitle { color: #556; font-size: 12px; }
22
- .container { max-width: 1200px; margin: 0 auto; padding: 24px; }
23
- .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; margin-bottom: 24px; }
24
- .card { background: rgba(100,120,255,0.04); border: 1px solid rgba(100,120,255,0.1); border-radius: 12px; padding: 16px; }
25
- .card h3 { font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: #556; margin-bottom: 8px; }
26
- .card .value { font-size: 28px; font-weight: 700; }
27
- .card .sub { font-size: 11px; color: #556; margin-top: 4px; }
28
- .search-box { width: 100%; padding: 10px 16px; background: rgba(100,120,255,0.06); border: 1px solid rgba(100,120,255,0.15); border-radius: 8px; color: #c0c0f0; font-size: 14px; outline: none; margin-bottom: 16px; }
29
- .search-box::placeholder { color: #445; }
30
- .results { display: flex; flex-direction: column; gap: 8px; }
31
- .result { padding: 12px; background: rgba(255,255,255,0.02); border-radius: 8px; cursor: pointer; }
32
- .result:hover { background: rgba(100,120,255,0.06); }
33
- .result .title { font-weight: 600; font-size: 13px; }
34
- .result .meta { font-size: 11px; color: #556; margin-top: 4px; }
35
- .section { margin-bottom: 24px; }
36
- .section h2 { font-size: 14px; margin-bottom: 12px; color: #88aaff; }
37
- .bar { height: 6px; background: rgba(100,120,255,0.1); border-radius: 3px; overflow: hidden; margin-top: 6px; }
38
- .bar-fill { height: 100%; border-radius: 3px; transition: width 0.3s; }
39
- .links { display: flex; gap: 12px; margin-top: 16px; }
40
- .links a { color: #88aaff; text-decoration: none; font-size: 12px; padding: 6px 12px; border: 1px solid rgba(100,120,255,0.15); border-radius: 6px; }
41
- .links a:hover { background: rgba(100,120,255,0.1); }
42
- #loading { color: #556; font-size: 12px; }
43
- </style>
44
- </head>
45
- <body>
46
- <div class="header">
47
- <h1>Stellavault</h1>
48
- <span class="subtitle">Dashboard</span>
49
- <div style="margin-left:auto" class="links">
50
- <a href="/api/stats" target="_blank">API Stats</a>
51
- <a href="http://localhost:5173" target="_blank">3D Graph</a>
52
- </div>
53
- </div>
54
-
55
- <div class="container">
56
- <!-- Stats -->
57
- <div class="grid" id="stats-grid">
58
- <div class="card"><h3>Documents</h3><div class="value" id="doc-count">-</div></div>
59
- <div class="card"><h3>Chunks</h3><div class="value" id="chunk-count">-</div></div>
60
- <div class="card"><h3>Health Score</h3><div class="value" id="health-score">-</div><div class="bar"><div class="bar-fill" id="health-bar" style="width:0%;background:#10b981"></div></div></div>
61
- <div class="card"><h3>Knowledge Gaps</h3><div class="value" id="gap-count">-</div></div>
62
- </div>
63
-
64
- <!-- Search -->
65
- <div class="section">
66
- <h2>Search</h2>
67
- <input class="search-box" id="search-input" placeholder="Search your knowledge..." />
68
- <div class="results" id="search-results"></div>
69
- </div>
70
-
71
- <!-- Decay -->
72
- <div class="section">
73
- <h2>Fading Knowledge</h2>
74
- <div id="decay-list"><span id="loading">Loading...</span></div>
75
- </div>
76
- </div>
77
-
78
- <script>
79
- const API = '/api';
80
- // HIGH-06: XSS 방지 — HTML 이스케이프
81
- function esc(s) { const d = document.createElement('div'); d.textContent = s; return d.innerHTML; }
82
-
83
- async function loadStats() {
84
- try {
85
- const [stats, health] = await Promise.all([
86
- fetch(API + '/stats').then(r => r.json()),
87
- fetch(API + '/health').then(r => r.json()).catch(() => null),
88
- ]);
89
- document.getElementById('doc-count').textContent = stats.documentCount ?? 0;
90
- document.getElementById('chunk-count').textContent = stats.chunkCount ?? 0;
91
- if (health) {
92
- const score = health.decay?.averageR ? Math.round(health.decay.averageR * 100) : 100;
93
- document.getElementById('health-score').textContent = score + '%';
94
- document.getElementById('health-bar').style.width = score + '%';
95
- document.getElementById('health-bar').style.background = score > 70 ? '#10b981' : score > 40 ? '#f59e0b' : '#ef4444';
96
- document.getElementById('gap-count').textContent = health.gaps?.gapCount ?? 0;
97
-
98
- // Decay list
99
- const decayEl = document.getElementById('decay-list');
100
- if (health.decay?.topDecaying?.length) {
101
- decayEl.innerHTML = health.decay.topDecaying.slice(0, 8).map(d => {
102
- const r = Math.round((d.retrievability ?? 0) * 100);
103
- const color = r > 50 ? '#10b981' : r > 30 ? '#f59e0b' : '#ef4444';
104
- return '<div class="result"><div class="title">' + esc(d.title) + '</div><div class="bar"><div class="bar-fill" style="width:' + r + '%;background:' + color + '"></div></div><div class="meta">' + r + '% retrievability</div></div>';
105
- }).join('');
106
- } else {
107
- decayEl.innerHTML = '<div style="color:#556;font-size:12px">All knowledge healthy!</div>';
108
- }
109
- }
110
- } catch (e) { console.error(e); }
111
- }
112
-
113
- let searchTimer;
114
- document.getElementById('search-input').addEventListener('input', (e) => {
115
- clearTimeout(searchTimer);
116
- searchTimer = setTimeout(async () => {
117
- const q = e.target.value.trim();
118
- const el = document.getElementById('search-results');
119
- if (!q) { el.innerHTML = ''; return; }
120
- try {
121
- const res = await fetch(API + '/search?q=' + encodeURIComponent(q) + '&limit=10').then(r => r.json());
122
- el.innerHTML = (res.results || []).map(r =>
123
- '<div class="result"><div class="title">' + esc(r.title) + ' <span style="color:#556;font-size:11px">(' + Math.round(r.score * 100) + '%)</span></div>' +
124
- '<div class="meta">' + esc((r.highlights?.[0] || '').slice(0, 100)) + '</div></div>'
125
- ).join('') || '<div style="color:#556;font-size:12px">No results</div>';
126
- } catch { el.innerHTML = '<div style="color:#ef4444;font-size:12px">Search error</div>'; }
127
- }, 300);
128
- });
129
-
130
- loadStats();
131
- </script>
132
- </body>
133
- </html>`;
134
- }
135
- //# sourceMappingURL=dashboard.js.map
@@ -1,11 +0,0 @@
1
- import type { VectorStore } from '../store/types.js';
2
- import type { GraphData } from '../types/graph.js';
3
- export type GraphMode = 'semantic' | 'folder';
4
- export interface BuildGraphOptions {
5
- mode?: GraphMode;
6
- edgeThreshold?: number;
7
- maxEdgesPerNode?: number;
8
- clusterCount?: number;
9
- }
10
- export declare function buildGraphData(store: VectorStore, options?: BuildGraphOptions): Promise<GraphData>;
11
- //# sourceMappingURL=graph-data.d.ts.map
@@ -1,255 +0,0 @@
1
- // Design Ref: §4.2 — Graph Data 생성 알고리즘
2
- // Design Ref: §6.2 — K-Means 클러스터링
3
- import { createHash } from 'node:crypto';
4
- const CLUSTER_COLORS = [
5
- '#6366f1', '#ec4899', '#f59e0b', '#10b981', '#3b82f6',
6
- '#8b5cf6', '#ef4444', '#14b8a6', '#f97316', '#06b6d4',
7
- '#84cc16', '#e879f9', '#22d3ee', '#a3e635', '#fb923c',
8
- ];
9
- export async function buildGraphData(store, options = {}) {
10
- const { edgeThreshold = 0.15, maxEdgesPerNode = 5, } = options;
11
- // 1. 모든 문서 + 임베딩 로드
12
- const [docs, embeddings] = await Promise.all([
13
- store.getAllDocuments(),
14
- store.getDocumentEmbeddings(),
15
- ]);
16
- // 2. k-NN으로 엣지 생성
17
- const edges = [];
18
- const edgeCounts = new Map();
19
- for (const doc of docs) {
20
- const vec = embeddings.get(doc.id);
21
- if (!vec)
22
- continue;
23
- // 모든 다른 문서와 코사인 유사도 계산
24
- const similarities = [];
25
- for (const other of docs) {
26
- if (other.id === doc.id)
27
- continue;
28
- const otherVec = embeddings.get(other.id);
29
- if (!otherVec)
30
- continue;
31
- const sim = cosineSimilarity(vec, otherVec);
32
- if (sim >= edgeThreshold) {
33
- similarities.push({ id: other.id, sim });
34
- }
35
- }
36
- // 상위 k개만
37
- similarities.sort((a, b) => b.sim - a.sim);
38
- const topK = similarities.slice(0, maxEdgesPerNode);
39
- for (const { id: targetId, sim } of topK) {
40
- // 중복 엣지 방지 (A→B, B→A)
41
- const edgeKey = [doc.id, targetId].sort().join(':');
42
- if (!edgeCounts.has(edgeKey)) {
43
- edges.push({ source: doc.id, target: targetId, weight: sim });
44
- edgeCounts.set(edgeKey, 1);
45
- }
46
- }
47
- }
48
- // 3. 클러스터링 — 모드에 따라 분기
49
- const mode = options.mode ?? 'semantic';
50
- let assignmentMap;
51
- let clusters;
52
- if (mode === 'folder') {
53
- // 폴더 기반: 최상위 폴더를 클러스터로 사용
54
- const folderMap = new Map();
55
- const folderNames = [];
56
- for (const doc of docs) {
57
- const topFolder = doc.filePath.split('/')[0] ?? 'root';
58
- if (!folderMap.has(topFolder)) {
59
- folderMap.set(topFolder, folderNames.length);
60
- folderNames.push(topFolder);
61
- }
62
- }
63
- assignmentMap = new Map();
64
- for (const doc of docs) {
65
- const topFolder = doc.filePath.split('/')[0] ?? 'root';
66
- assignmentMap.set(doc.id, folderMap.get(topFolder));
67
- }
68
- // 폴더별 클러스터
69
- const folderCounts = new Map();
70
- for (const [, cId] of assignmentMap) {
71
- folderCounts.set(cId, (folderCounts.get(cId) ?? 0) + 1);
72
- }
73
- clusters = folderNames.map((name, i) => ({
74
- id: i,
75
- label: name.replace(/^\d+_/, ''), // "04_Projects" → "Projects"
76
- color: CLUSTER_COLORS[i % CLUSTER_COLORS.length],
77
- nodeCount: folderCounts.get(i) ?? 0,
78
- }));
79
- }
80
- else {
81
- // 시맨틱 기반: K-means
82
- const docIds = docs.filter(d => embeddings.has(d.id)).map(d => d.id);
83
- const vectors = docIds.map(id => embeddings.get(id));
84
- const k = Math.min(Math.max(5, Math.round(Math.sqrt(docIds.length / 5))), 10);
85
- const assignments = kMeans(vectors, k);
86
- // 클러스터별 문서 수집 (id + title)
87
- const clusterDocInfos = new Map();
88
- for (let i = 0; i < docIds.length; i++) {
89
- const cId = assignments[i];
90
- if (!clusterDocInfos.has(cId))
91
- clusterDocInfos.set(cId, []);
92
- const doc = docs.find(d => d.id === docIds[i]);
93
- if (doc)
94
- clusterDocInfos.get(cId).push({ id: doc.id, title: doc.title });
95
- }
96
- // 엣지 기반 연결 수 계산 (대표 노드 선정용)
97
- const connCounts = new Map();
98
- for (const e of edges) {
99
- connCounts.set(e.source, (connCounts.get(e.source) ?? 0) + 1);
100
- connCounts.set(e.target, (connCounts.get(e.target) ?? 0) + 1);
101
- }
102
- clusters = [];
103
- for (const [cId, docInfos] of clusterDocInfos) {
104
- // 가장 연결이 많은 노드 = 대표 노드
105
- const sorted = [...docInfos].sort((a, b) => (connCounts.get(b.id) ?? 0) - (connCounts.get(a.id) ?? 0));
106
- const representative = sorted[0]?.title ?? 'Cluster';
107
- clusters.push({
108
- id: cId,
109
- label: `${representative} (${docInfos.length})`,
110
- color: CLUSTER_COLORS[cId % CLUSTER_COLORS.length],
111
- nodeCount: docInfos.length,
112
- });
113
- }
114
- assignmentMap = new Map();
115
- for (let i = 0; i < docIds.length; i++) {
116
- assignmentMap.set(docIds[i], assignments[i]);
117
- }
118
- }
119
- // 4. 노드 생성
120
- const connectionCounts = new Map();
121
- for (const edge of edges) {
122
- connectionCounts.set(edge.source, (connectionCounts.get(edge.source) ?? 0) + 1);
123
- connectionCounts.set(edge.target, (connectionCounts.get(edge.target) ?? 0) + 1);
124
- }
125
- const maxConnections = Math.max(1, ...connectionCounts.values());
126
- const nodes = docs.map(doc => {
127
- const conns = connectionCounts.get(doc.id) ?? 0;
128
- const ratio = conns / maxConnections; // 0~1
129
- // 지수 스케일: 상위 노드만 극적으로 커짐 (ratio^0.5 → 중심부 강조)
130
- const size = 1 + 6 * Math.pow(ratio, 0.5);
131
- return {
132
- id: doc.id,
133
- label: doc.title.replace(/&#39;/g, "'").replace(/&#x27;/g, "'").replace(/&quot;/g, '"').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/\s*-\s*YouTube$/, '').slice(0, 40),
134
- filePath: doc.filePath,
135
- tags: doc.tags,
136
- clusterId: assignmentMap.get(doc.id) ?? 0,
137
- size,
138
- source: doc.source ?? 'local',
139
- type: doc.type ?? 'note',
140
- lastModified: doc.lastModified,
141
- };
142
- });
143
- // 5. cache key
144
- const cacheKey = createHash('md5')
145
- .update(JSON.stringify({ nodeCount: nodes.length, edgeCount: edges.length }))
146
- .digest('hex')
147
- .slice(0, 8);
148
- return {
149
- nodes,
150
- edges,
151
- clusters,
152
- stats: {
153
- nodeCount: nodes.length,
154
- edgeCount: edges.length,
155
- clusterCount: clusters.length,
156
- },
157
- };
158
- }
159
- // --- 유틸리티 ---
160
- function cosineSimilarity(a, b) {
161
- let dot = 0, normA = 0, normB = 0;
162
- for (let i = 0; i < a.length; i++) {
163
- dot += a[i] * b[i];
164
- normA += a[i] * a[i];
165
- normB += b[i] * b[i];
166
- }
167
- const denom = Math.sqrt(normA) * Math.sqrt(normB);
168
- return denom === 0 ? 0 : dot / denom;
169
- }
170
- function kMeans(vectors, k, maxIter = 50) {
171
- if (vectors.length === 0)
172
- return [];
173
- const dims = vectors[0].length;
174
- // K-means++ 초기화
175
- const centroids = [vectors[Math.floor(Math.random() * vectors.length)].slice()];
176
- for (let c = 1; c < k; c++) {
177
- const dists = vectors.map(v => {
178
- let minD = Infinity;
179
- for (const cent of centroids) {
180
- const d = euclideanDist(v, cent);
181
- if (d < minD)
182
- minD = d;
183
- }
184
- return minD;
185
- });
186
- const totalDist = dists.reduce((a, b) => a + b, 0);
187
- let r = Math.random() * totalDist;
188
- for (let i = 0; i < dists.length; i++) {
189
- r -= dists[i];
190
- if (r <= 0) {
191
- centroids.push(vectors[i].slice());
192
- break;
193
- }
194
- }
195
- if (centroids.length <= c)
196
- centroids.push(vectors[Math.floor(Math.random() * vectors.length)].slice());
197
- }
198
- const assignments = new Array(vectors.length).fill(0);
199
- for (let iter = 0; iter < maxIter; iter++) {
200
- let changed = false;
201
- // Assign
202
- for (let i = 0; i < vectors.length; i++) {
203
- let bestC = 0, bestD = Infinity;
204
- for (let c = 0; c < k; c++) {
205
- const d = euclideanDist(vectors[i], centroids[c]);
206
- if (d < bestD) {
207
- bestD = d;
208
- bestC = c;
209
- }
210
- }
211
- if (assignments[i] !== bestC) {
212
- assignments[i] = bestC;
213
- changed = true;
214
- }
215
- }
216
- if (!changed)
217
- break;
218
- // Update centroids
219
- for (let c = 0; c < k; c++) {
220
- const members = vectors.filter((_, i) => assignments[i] === c);
221
- if (members.length === 0)
222
- continue;
223
- for (let d = 0; d < dims; d++) {
224
- centroids[c][d] = members.reduce((sum, v) => sum + v[d], 0) / members.length;
225
- }
226
- }
227
- }
228
- return assignments;
229
- }
230
- function euclideanDist(a, b) {
231
- let sum = 0;
232
- for (let i = 0; i < a.length; i++) {
233
- const diff = a[i] - b[i];
234
- sum += diff * diff;
235
- }
236
- return Math.sqrt(sum);
237
- }
238
- function extractClusterLabel(titles) {
239
- // 제목에서 빈출 단어 추출 (2글자 이상)
240
- const wordCounts = new Map();
241
- const stopWords = new Set(['the', 'a', 'an', 'in', 'on', 'at', 'to', 'for', 'of', 'and', 'or', 'is', 'are', 'was', 'be']);
242
- for (const title of titles) {
243
- const words = title.replace(/[^\w가-힣\s]/g, '').split(/\s+/).filter(w => w.length >= 2 && !stopWords.has(w.toLowerCase()));
244
- const seen = new Set();
245
- for (const w of words) {
246
- if (!seen.has(w)) {
247
- wordCounts.set(w, (wordCounts.get(w) ?? 0) + 1);
248
- seen.add(w);
249
- }
250
- }
251
- }
252
- const sorted = [...wordCounts.entries()].sort((a, b) => b[1] - a[1]);
253
- return sorted.slice(0, 3).map(([w]) => w).join(', ') || `Cluster`;
254
- }
255
- //# sourceMappingURL=graph-data.js.map
@@ -1,3 +0,0 @@
1
- import type { Express } from 'express';
2
- export declare function mountPWA(app: Express): void;
3
- //# sourceMappingURL=pwa.d.ts.map