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.
- package/README.md +52 -16
- package/SECURITY.md +50 -0
- package/dist/stellavault.js +8968 -0
- package/package.json +70 -33
- package/.env.example +0 -12
- package/CHANGELOG.md +0 -106
- package/CLAUDE.md +0 -42
- package/CONTRIBUTING.md +0 -65
- package/index.html +0 -509
- package/packages/cli/bin/ekh.js +0 -2
- package/packages/cli/bin/stellavault.js +0 -2
- package/packages/cli/dist/commands/adr-cmd.d.ts +0 -7
- package/packages/cli/dist/commands/adr-cmd.js +0 -45
- package/packages/cli/dist/commands/ask-cmd.d.ts +0 -5
- package/packages/cli/dist/commands/ask-cmd.js +0 -36
- package/packages/cli/dist/commands/autopilot-cmd.d.ts +0 -4
- package/packages/cli/dist/commands/autopilot-cmd.js +0 -76
- package/packages/cli/dist/commands/brief-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/brief-cmd.js +0 -82
- package/packages/cli/dist/commands/capture-cmd.d.ts +0 -7
- package/packages/cli/dist/commands/capture-cmd.js +0 -31
- package/packages/cli/dist/commands/card-cmd.d.ts +0 -4
- package/packages/cli/dist/commands/card-cmd.js +0 -26
- package/packages/cli/dist/commands/clip-cmd.d.ts +0 -4
- package/packages/cli/dist/commands/clip-cmd.js +0 -151
- package/packages/cli/dist/commands/cloud-cmd.d.ts +0 -4
- package/packages/cli/dist/commands/cloud-cmd.js +0 -64
- package/packages/cli/dist/commands/compile-cmd.d.ts +0 -6
- package/packages/cli/dist/commands/compile-cmd.js +0 -30
- package/packages/cli/dist/commands/contradictions-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/contradictions-cmd.js +0 -34
- package/packages/cli/dist/commands/decay-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/decay-cmd.js +0 -48
- package/packages/cli/dist/commands/digest-cmd.d.ts +0 -5
- package/packages/cli/dist/commands/digest-cmd.js +0 -136
- package/packages/cli/dist/commands/draft-cmd.d.ts +0 -6
- package/packages/cli/dist/commands/draft-cmd.js +0 -110
- package/packages/cli/dist/commands/duplicates-cmd.d.ts +0 -4
- package/packages/cli/dist/commands/duplicates-cmd.js +0 -30
- package/packages/cli/dist/commands/federate-cmd.d.ts +0 -5
- package/packages/cli/dist/commands/federate-cmd.js +0 -247
- package/packages/cli/dist/commands/fleeting-cmd.d.ts +0 -4
- package/packages/cli/dist/commands/fleeting-cmd.js +0 -45
- package/packages/cli/dist/commands/flush-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/flush-cmd.js +0 -58
- package/packages/cli/dist/commands/gaps-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/gaps-cmd.js +0 -33
- package/packages/cli/dist/commands/graph-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/graph-cmd.js +0 -89
- package/packages/cli/dist/commands/index-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/index-cmd.js +0 -57
- package/packages/cli/dist/commands/ingest-cmd.d.ts +0 -9
- package/packages/cli/dist/commands/ingest-cmd.js +0 -195
- package/packages/cli/dist/commands/init-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/init-cmd.js +0 -161
- package/packages/cli/dist/commands/learn-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/learn-cmd.js +0 -48
- package/packages/cli/dist/commands/lint-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/lint-cmd.js +0 -61
- package/packages/cli/dist/commands/pack-cmd.d.ts +0 -15
- package/packages/cli/dist/commands/pack-cmd.js +0 -93
- package/packages/cli/dist/commands/review-cmd.d.ts +0 -4
- package/packages/cli/dist/commands/review-cmd.js +0 -107
- package/packages/cli/dist/commands/search-cmd.d.ts +0 -4
- package/packages/cli/dist/commands/search-cmd.js +0 -38
- package/packages/cli/dist/commands/serve-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/serve-cmd.js +0 -14
- package/packages/cli/dist/commands/session-cmd.d.ts +0 -7
- package/packages/cli/dist/commands/session-cmd.js +0 -95
- package/packages/cli/dist/commands/status-cmd.d.ts +0 -2
- package/packages/cli/dist/commands/status-cmd.js +0 -33
- package/packages/cli/dist/commands/sync-cmd.d.ts +0 -5
- package/packages/cli/dist/commands/sync-cmd.js +0 -62
- package/packages/cli/dist/commands/vault-cmd.d.ts +0 -10
- package/packages/cli/dist/commands/vault-cmd.js +0 -54
- package/packages/cli/dist/index.d.ts +0 -2
- package/packages/cli/dist/index.js +0 -233
- package/packages/cli/package.json +0 -24
- package/packages/core/dist/api/dashboard.d.ts +0 -3
- package/packages/core/dist/api/dashboard.js +0 -135
- package/packages/core/dist/api/graph-data.d.ts +0 -11
- package/packages/core/dist/api/graph-data.js +0 -255
- package/packages/core/dist/api/pwa.d.ts +0 -3
- package/packages/core/dist/api/pwa.js +0 -77
- package/packages/core/dist/api/server.d.ts +0 -16
- package/packages/core/dist/api/server.js +0 -1122
- package/packages/core/dist/capture/voice.d.ts +0 -24
- package/packages/core/dist/capture/voice.js +0 -135
- package/packages/core/dist/cloud/index.d.ts +0 -3
- package/packages/core/dist/cloud/index.js +0 -2
- package/packages/core/dist/cloud/sync.d.ts +0 -29
- package/packages/core/dist/cloud/sync.js +0 -137
- package/packages/core/dist/config.d.ts +0 -35
- package/packages/core/dist/config.js +0 -63
- package/packages/core/dist/federation/credits.d.ts +0 -26
- package/packages/core/dist/federation/credits.js +0 -56
- package/packages/core/dist/federation/identity.d.ts +0 -14
- package/packages/core/dist/federation/identity.js +0 -74
- package/packages/core/dist/federation/index.d.ts +0 -7
- package/packages/core/dist/federation/index.js +0 -5
- package/packages/core/dist/federation/node.d.ts +0 -31
- package/packages/core/dist/federation/node.js +0 -216
- package/packages/core/dist/federation/privacy.d.ts +0 -8
- package/packages/core/dist/federation/privacy.js +0 -40
- package/packages/core/dist/federation/reputation.d.ts +0 -37
- package/packages/core/dist/federation/reputation.js +0 -139
- package/packages/core/dist/federation/search.d.ts +0 -19
- package/packages/core/dist/federation/search.js +0 -101
- package/packages/core/dist/federation/sharing.d.ts +0 -72
- package/packages/core/dist/federation/sharing.js +0 -246
- package/packages/core/dist/federation/trust.d.ts +0 -15
- package/packages/core/dist/federation/trust.js +0 -60
- package/packages/core/dist/federation/types.d.ts +0 -40
- package/packages/core/dist/federation/types.js +0 -3
- package/packages/core/dist/i18n/index.d.ts +0 -6
- package/packages/core/dist/i18n/index.js +0 -81
- package/packages/core/dist/i18n/note-strings.d.ts +0 -5
- package/packages/core/dist/i18n/note-strings.js +0 -94
- package/packages/core/dist/index.d.ts +0 -123
- package/packages/core/dist/index.js +0 -74
- package/packages/core/dist/indexer/chunker.d.ts +0 -14
- package/packages/core/dist/indexer/chunker.js +0 -148
- package/packages/core/dist/indexer/embedder.d.ts +0 -8
- package/packages/core/dist/indexer/embedder.js +0 -3
- package/packages/core/dist/indexer/index.d.ts +0 -28
- package/packages/core/dist/indexer/index.js +0 -74
- package/packages/core/dist/indexer/local-embedder.d.ts +0 -3
- package/packages/core/dist/indexer/local-embedder.js +0 -29
- package/packages/core/dist/indexer/scanner.d.ts +0 -11
- package/packages/core/dist/indexer/scanner.js +0 -148
- package/packages/core/dist/indexer/watcher.d.ts +0 -19
- package/packages/core/dist/indexer/watcher.js +0 -49
- package/packages/core/dist/intelligence/ask-engine.d.ts +0 -24
- package/packages/core/dist/intelligence/ask-engine.js +0 -142
- package/packages/core/dist/intelligence/auto-linker.d.ts +0 -19
- package/packages/core/dist/intelligence/auto-linker.js +0 -126
- package/packages/core/dist/intelligence/code-linker.d.ts +0 -20
- package/packages/core/dist/intelligence/code-linker.js +0 -88
- package/packages/core/dist/intelligence/contradiction-detector.d.ts +0 -20
- package/packages/core/dist/intelligence/contradiction-detector.js +0 -115
- package/packages/core/dist/intelligence/decay-engine.d.ts +0 -27
- package/packages/core/dist/intelligence/decay-engine.js +0 -190
- package/packages/core/dist/intelligence/draft-generator.d.ts +0 -25
- package/packages/core/dist/intelligence/draft-generator.js +0 -277
- package/packages/core/dist/intelligence/duplicate-detector.d.ts +0 -20
- package/packages/core/dist/intelligence/duplicate-detector.js +0 -55
- package/packages/core/dist/intelligence/file-extractors.d.ts +0 -13
- package/packages/core/dist/intelligence/file-extractors.js +0 -155
- package/packages/core/dist/intelligence/fsrs.d.ts +0 -43
- package/packages/core/dist/intelligence/fsrs.js +0 -70
- package/packages/core/dist/intelligence/gap-detector.d.ts +0 -25
- package/packages/core/dist/intelligence/gap-detector.js +0 -78
- package/packages/core/dist/intelligence/ingest-pipeline.d.ts +0 -32
- package/packages/core/dist/intelligence/ingest-pipeline.js +0 -245
- package/packages/core/dist/intelligence/knowledge-lint.d.ts +0 -27
- package/packages/core/dist/intelligence/knowledge-lint.js +0 -132
- package/packages/core/dist/intelligence/learning-path.d.ts +0 -31
- package/packages/core/dist/intelligence/learning-path.js +0 -53
- package/packages/core/dist/intelligence/notifications.d.ts +0 -31
- package/packages/core/dist/intelligence/notifications.js +0 -65
- package/packages/core/dist/intelligence/predictive-gaps.d.ts +0 -14
- package/packages/core/dist/intelligence/predictive-gaps.js +0 -74
- package/packages/core/dist/intelligence/semantic-versioning.d.ts +0 -37
- package/packages/core/dist/intelligence/semantic-versioning.js +0 -68
- package/packages/core/dist/intelligence/types.d.ts +0 -28
- package/packages/core/dist/intelligence/types.js +0 -3
- package/packages/core/dist/intelligence/wiki-compiler.d.ts +0 -30
- package/packages/core/dist/intelligence/wiki-compiler.js +0 -222
- package/packages/core/dist/intelligence/youtube-extractor.d.ts +0 -29
- package/packages/core/dist/intelligence/youtube-extractor.js +0 -321
- package/packages/core/dist/intelligence/zettelkasten.d.ts +0 -59
- package/packages/core/dist/intelligence/zettelkasten.js +0 -234
- package/packages/core/dist/mcp/custom-tools.d.ts +0 -29
- package/packages/core/dist/mcp/custom-tools.js +0 -70
- package/packages/core/dist/mcp/index.d.ts +0 -2
- package/packages/core/dist/mcp/index.js +0 -2
- package/packages/core/dist/mcp/server.d.ts +0 -51
- package/packages/core/dist/mcp/server.js +0 -174
- package/packages/core/dist/mcp/tools/agentic-graph.d.ts +0 -93
- package/packages/core/dist/mcp/tools/agentic-graph.js +0 -116
- package/packages/core/dist/mcp/tools/ask.d.ts +0 -29
- package/packages/core/dist/mcp/tools/ask.js +0 -43
- package/packages/core/dist/mcp/tools/brief.d.ts +0 -31
- package/packages/core/dist/mcp/tools/brief.js +0 -39
- package/packages/core/dist/mcp/tools/decay.d.ts +0 -33
- package/packages/core/dist/mcp/tools/decay.js +0 -32
- package/packages/core/dist/mcp/tools/decision-journal.d.ts +0 -78
- package/packages/core/dist/mcp/tools/decision-journal.js +0 -79
- package/packages/core/dist/mcp/tools/detect-gaps.d.ts +0 -24
- package/packages/core/dist/mcp/tools/detect-gaps.js +0 -47
- package/packages/core/dist/mcp/tools/export.d.ts +0 -29
- package/packages/core/dist/mcp/tools/export.js +0 -60
- package/packages/core/dist/mcp/tools/federated-search.d.ts +0 -29
- package/packages/core/dist/mcp/tools/federated-search.js +0 -36
- package/packages/core/dist/mcp/tools/generate-claude-md.d.ts +0 -35
- package/packages/core/dist/mcp/tools/generate-claude-md.js +0 -107
- package/packages/core/dist/mcp/tools/generate-draft.d.ts +0 -34
- package/packages/core/dist/mcp/tools/generate-draft.js +0 -120
- package/packages/core/dist/mcp/tools/get-document.d.ts +0 -35
- package/packages/core/dist/mcp/tools/get-document.js +0 -25
- package/packages/core/dist/mcp/tools/get-evolution.d.ts +0 -28
- package/packages/core/dist/mcp/tools/get-evolution.js +0 -70
- package/packages/core/dist/mcp/tools/get-related.d.ts +0 -32
- package/packages/core/dist/mcp/tools/get-related.js +0 -33
- package/packages/core/dist/mcp/tools/learning-path.d.ts +0 -23
- package/packages/core/dist/mcp/tools/learning-path.js +0 -45
- package/packages/core/dist/mcp/tools/link-code.d.ts +0 -34
- package/packages/core/dist/mcp/tools/link-code.js +0 -44
- package/packages/core/dist/mcp/tools/list-topics.d.ts +0 -15
- package/packages/core/dist/mcp/tools/list-topics.js +0 -18
- package/packages/core/dist/mcp/tools/search.d.ts +0 -39
- package/packages/core/dist/mcp/tools/search.js +0 -29
- package/packages/core/dist/mcp/tools/snapshot.d.ts +0 -47
- package/packages/core/dist/mcp/tools/snapshot.js +0 -84
- package/packages/core/dist/multi-vault/index.d.ts +0 -26
- package/packages/core/dist/multi-vault/index.js +0 -80
- package/packages/core/dist/pack/creator.d.ts +0 -21
- package/packages/core/dist/pack/creator.js +0 -105
- package/packages/core/dist/pack/exporter.d.ts +0 -4
- package/packages/core/dist/pack/exporter.js +0 -18
- package/packages/core/dist/pack/importer.d.ts +0 -10
- package/packages/core/dist/pack/importer.js +0 -55
- package/packages/core/dist/pack/index.d.ts +0 -6
- package/packages/core/dist/pack/index.js +0 -5
- package/packages/core/dist/pack/marketplace.d.ts +0 -14
- package/packages/core/dist/pack/marketplace.js +0 -90
- package/packages/core/dist/pack/pii-masker.d.ts +0 -7
- package/packages/core/dist/pack/pii-masker.js +0 -29
- package/packages/core/dist/pack/types.d.ts +0 -36
- package/packages/core/dist/pack/types.js +0 -3
- package/packages/core/dist/plugins/index.d.ts +0 -35
- package/packages/core/dist/plugins/index.js +0 -57
- package/packages/core/dist/plugins/webhooks.d.ts +0 -30
- package/packages/core/dist/plugins/webhooks.js +0 -79
- package/packages/core/dist/search/adaptive.d.ts +0 -16
- package/packages/core/dist/search/adaptive.js +0 -67
- package/packages/core/dist/search/bm25.d.ts +0 -4
- package/packages/core/dist/search/bm25.js +0 -10
- package/packages/core/dist/search/index.d.ts +0 -15
- package/packages/core/dist/search/index.js +0 -64
- package/packages/core/dist/search/rrf.d.ts +0 -7
- package/packages/core/dist/search/rrf.js +0 -21
- package/packages/core/dist/search/semantic.d.ts +0 -5
- package/packages/core/dist/search/semantic.js +0 -6
- package/packages/core/dist/store/index.d.ts +0 -3
- package/packages/core/dist/store/index.js +0 -2
- package/packages/core/dist/store/sqlite-vec.d.ts +0 -6
- package/packages/core/dist/store/sqlite-vec.js +0 -251
- package/packages/core/dist/store/types.d.ts +0 -20
- package/packages/core/dist/store/types.js +0 -3
- package/packages/core/dist/team/index.d.ts +0 -25
- package/packages/core/dist/team/index.js +0 -97
- package/packages/core/dist/types/chunk.d.ts +0 -23
- package/packages/core/dist/types/chunk.js +0 -3
- package/packages/core/dist/types/document.d.ts +0 -23
- package/packages/core/dist/types/document.js +0 -3
- package/packages/core/dist/types/graph.d.ts +0 -39
- package/packages/core/dist/types/graph.js +0 -3
- package/packages/core/dist/types/index.d.ts +0 -5
- package/packages/core/dist/types/index.js +0 -2
- package/packages/core/dist/types/search.d.ts +0 -39
- package/packages/core/dist/types/search.js +0 -3
- package/packages/core/dist/utils/retry.d.ts +0 -25
- package/packages/core/dist/utils/retry.js +0 -59
- package/packages/core/package.json +0 -67
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// Design Ref: stellavault gaps — 지식 갭 탐지 CLI
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { loadConfig, createKnowledgeHub, detectKnowledgeGaps } from '@stellavault/core';
|
|
4
|
-
export async function gapsCommand() {
|
|
5
|
-
const config = loadConfig();
|
|
6
|
-
const hub = createKnowledgeHub(config);
|
|
7
|
-
console.error(chalk.dim('⏳ Analyzing knowledge gaps...'));
|
|
8
|
-
await hub.store.initialize();
|
|
9
|
-
await hub.embedder.initialize();
|
|
10
|
-
const report = await detectKnowledgeGaps(hub.store);
|
|
11
|
-
console.log(chalk.green('\n🕳️ Knowledge Gap Report'));
|
|
12
|
-
console.log(chalk.dim('─'.repeat(50)));
|
|
13
|
-
console.log(` 클러스터: ${report.totalClusters}개`);
|
|
14
|
-
console.log(` 갭: ${chalk.yellow(String(report.totalGaps))}개 (High+Medium)`);
|
|
15
|
-
console.log(` 고립 노드: ${report.isolatedNodes.length}개`);
|
|
16
|
-
console.log(chalk.dim('─'.repeat(50)));
|
|
17
|
-
if (report.gaps.length > 0) {
|
|
18
|
-
console.log(chalk.yellow('\n📊 클러스터 간 갭:'));
|
|
19
|
-
for (const gap of report.gaps) {
|
|
20
|
-
const icon = gap.severity === 'high' ? '🔴' : gap.severity === 'medium' ? '🟡' : '🟢';
|
|
21
|
-
console.log(` ${icon} ${gap.clusterA} ↔ ${gap.clusterB}`);
|
|
22
|
-
console.log(` 연결: ${gap.bridgeCount}개 | 제안: ${chalk.cyan(gap.suggestedTopic)}`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
if (report.isolatedNodes.length > 0) {
|
|
26
|
-
console.log(chalk.dim('\n🏝️ 고립된 노트 (연결 ≤1):'));
|
|
27
|
-
for (const n of report.isolatedNodes.slice(0, 10)) {
|
|
28
|
-
console.log(` • ${n.title} (${n.connections}개 연결)`);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
console.log(chalk.dim('\n💡 갭 영역의 지식을 보강하면 지식 그래프가 더 촘촘해집니다'));
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=gaps-cmd.js.map
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
// Design Ref: §11.1 — CLI graph-cmd
|
|
2
|
-
// Plan SC: SC-04 — stellavault graph → 브라우저 3초
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import { loadConfig, createKnowledgeHub, createApiServer } from '@stellavault/core';
|
|
5
|
-
import { spawn } from 'node:child_process';
|
|
6
|
-
import { resolve } from 'node:path';
|
|
7
|
-
import { existsSync } from 'node:fs';
|
|
8
|
-
export async function graphCommand() {
|
|
9
|
-
const config = loadConfig();
|
|
10
|
-
const hub = createKnowledgeHub(config);
|
|
11
|
-
console.error(chalk.dim('⏳ Initializing...'));
|
|
12
|
-
await hub.store.initialize();
|
|
13
|
-
await hub.embedder.initialize();
|
|
14
|
-
const stats = await hub.store.getStats();
|
|
15
|
-
if (stats.documentCount === 0) {
|
|
16
|
-
console.error(chalk.yellow('⚠ No documents indexed. Run `stellavault index <vault-path>` first.'));
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
// API 서버 시작
|
|
20
|
-
const port = config.mcp.port || 3333;
|
|
21
|
-
// vault 이름 추출 (경로의 마지막 디렉토리명)
|
|
22
|
-
const vaultName = config.vaultPath
|
|
23
|
-
? config.vaultPath.replace(/\\/g, '/').replace(/\/$/, '').split('/').pop() ?? ''
|
|
24
|
-
: '';
|
|
25
|
-
const api = createApiServer({
|
|
26
|
-
store: hub.store,
|
|
27
|
-
searchEngine: hub.searchEngine,
|
|
28
|
-
port,
|
|
29
|
-
vaultName,
|
|
30
|
-
vaultPath: config.vaultPath,
|
|
31
|
-
});
|
|
32
|
-
try {
|
|
33
|
-
await api.start();
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
if (err?.code === 'EADDRINUSE') {
|
|
37
|
-
console.error(chalk.red(`Port ${port} is already in use.`));
|
|
38
|
-
console.error(chalk.dim(`Stop the other process or use a different port:`));
|
|
39
|
-
console.error(chalk.dim(` Edit .stellavault.json: { "mcp": { "port": ${port + 1} } }`));
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
throw err;
|
|
43
|
-
}
|
|
44
|
-
console.error(chalk.green('🧠 Stellavault — Neural Knowledge Graph'));
|
|
45
|
-
console.error(` 📚 ${stats.documentCount} documents | ${stats.chunkCount} chunks`);
|
|
46
|
-
console.error(` 🌐 API: http://127.0.0.1:${port}`);
|
|
47
|
-
// Vite dev 서버 시작 시도
|
|
48
|
-
const graphDir = resolve(process.cwd(), 'packages/graph');
|
|
49
|
-
const hasGraph = existsSync(resolve(graphDir, 'package.json'));
|
|
50
|
-
if (hasGraph) {
|
|
51
|
-
console.error(chalk.dim(' 🚀 Starting Vite dev server...'));
|
|
52
|
-
const vite = spawn('npx', ['vite', '--host'], {
|
|
53
|
-
cwd: graphDir,
|
|
54
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
55
|
-
shell: true,
|
|
56
|
-
});
|
|
57
|
-
vite.stderr.on('data', (data) => {
|
|
58
|
-
const line = data.toString();
|
|
59
|
-
// Vite ready 메시지 감지 → 브라우저 열기
|
|
60
|
-
if (line.includes('Local:')) {
|
|
61
|
-
const match = line.match(/http:\/\/localhost:\d+/);
|
|
62
|
-
const url = match?.[0] ?? 'http://localhost:5173';
|
|
63
|
-
console.error(chalk.green(` 🔮 Graph: ${url}`));
|
|
64
|
-
openBrowser(url);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
vite.on('close', () => {
|
|
68
|
-
console.error(chalk.dim(' Vite server stopped'));
|
|
69
|
-
});
|
|
70
|
-
process.on('SIGINT', () => {
|
|
71
|
-
vite.kill();
|
|
72
|
-
process.exit(0);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
console.error(chalk.dim(' 💡 Graph UI not found. Open http://127.0.0.1:' + port + '/api/graph'));
|
|
77
|
-
}
|
|
78
|
-
console.error(chalk.dim(' Press Ctrl+C to stop'));
|
|
79
|
-
}
|
|
80
|
-
async function openBrowser(url) {
|
|
81
|
-
try {
|
|
82
|
-
const open = await import('open');
|
|
83
|
-
await open.default(url);
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
// open 패키지 없으면 무시
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
//# sourceMappingURL=graph-cmd.js.map
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import ora from 'ora';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { createHash } from 'node:crypto';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import { homedir } from 'node:os';
|
|
6
|
-
import { mkdirSync } from 'node:fs';
|
|
7
|
-
import { loadConfig, createSqliteVecStore, createLocalEmbedder, indexVault, addVault, listVaults } from '@stellavault/core';
|
|
8
|
-
// vault 경로 → 고유 DB 경로 생성
|
|
9
|
-
function getVaultDbPath(vaultPath) {
|
|
10
|
-
const hash = createHash('sha256').update(vaultPath).digest('hex').slice(0, 8);
|
|
11
|
-
const dir = join(homedir(), '.stellavault', 'vaults');
|
|
12
|
-
mkdirSync(dir, { recursive: true });
|
|
13
|
-
return join(dir, `${hash}.db`);
|
|
14
|
-
}
|
|
15
|
-
export async function indexCommand(vaultPath) {
|
|
16
|
-
const config = loadConfig();
|
|
17
|
-
const vault = vaultPath ?? config.vaultPath;
|
|
18
|
-
if (!vault) {
|
|
19
|
-
console.error(chalk.red('Error: vault 경로가 필요합니다. stellavault index <path> 또는 .stellavault.json에 vaultPath 설정'));
|
|
20
|
-
process.exit(1);
|
|
21
|
-
}
|
|
22
|
-
// vault별 고유 DB 경로 (multi-vault 지원)
|
|
23
|
-
const dbPath = vaultPath ? getVaultDbPath(vault) : config.dbPath;
|
|
24
|
-
// Cross-Vault에 자동 등록
|
|
25
|
-
const existingVaults = listVaults();
|
|
26
|
-
const vaultName = vault.split(/[/\\]/).filter(Boolean).pop() ?? 'vault';
|
|
27
|
-
if (!existingVaults.some(v => v.path === vault)) {
|
|
28
|
-
try {
|
|
29
|
-
addVault(vaultName.toLowerCase(), vaultName, vault, dbPath);
|
|
30
|
-
console.log(chalk.dim(` Auto-registered vault: ${vaultName} (${dbPath})`));
|
|
31
|
-
}
|
|
32
|
-
catch { /* 이미 등록됨 */ }
|
|
33
|
-
}
|
|
34
|
-
const spinner = ora('초기화 중...').start();
|
|
35
|
-
const store = createSqliteVecStore(dbPath);
|
|
36
|
-
await store.initialize();
|
|
37
|
-
spinner.text = '임베딩 모델 로딩 중...';
|
|
38
|
-
const embedder = createLocalEmbedder(config.embedding.localModel);
|
|
39
|
-
await embedder.initialize();
|
|
40
|
-
spinner.text = '인덱싱 시작...';
|
|
41
|
-
const result = await indexVault(vault, {
|
|
42
|
-
store,
|
|
43
|
-
embedder,
|
|
44
|
-
chunkOptions: config.chunking,
|
|
45
|
-
onProgress(current, total, doc) {
|
|
46
|
-
spinner.text = `[${current}/${total}] ${doc.title}`;
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
await store.close();
|
|
50
|
-
spinner.stop();
|
|
51
|
-
console.log('');
|
|
52
|
-
console.log(chalk.green('✅ 인덱싱 완료'));
|
|
53
|
-
console.log(` 📄 인덱싱: ${result.indexed}건 | ⏭️ 스킵: ${result.skipped}건 | 🗑️ 삭제: ${result.deleted}건${result.failed ? ` | ❌ 실패: ${result.failed}건` : ''}`);
|
|
54
|
-
console.log(` 🧩 청크: ${result.totalChunks}개 | ⏱ ${(result.elapsedMs / 1000).toFixed(1)}초`);
|
|
55
|
-
console.log(` 💾 DB: ${dbPath}`);
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=index-cmd.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export declare function ingestCommand(input: string, options: {
|
|
2
|
-
tags?: string;
|
|
3
|
-
stage?: string;
|
|
4
|
-
title?: string;
|
|
5
|
-
}): Promise<void>;
|
|
6
|
-
export declare function promoteCommand(filePath: string, options: {
|
|
7
|
-
to: string;
|
|
8
|
-
}): Promise<void>;
|
|
9
|
-
//# sourceMappingURL=ingest-cmd.d.ts.map
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
// stellavault ingest — 통합 인제스트 (URL, 텍스트, 파일 → 자동 분류 저장)
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { loadConfig, ingest, promoteNote } from '@stellavault/core';
|
|
4
|
-
import { readFileSync, existsSync, readdirSync, statSync } from 'node:fs';
|
|
5
|
-
import { extname, resolve, join } from 'node:path';
|
|
6
|
-
export async function ingestCommand(input, options) {
|
|
7
|
-
if (!input) {
|
|
8
|
-
console.error(chalk.yellow('Usage: stellavault ingest <url|file|text|folder/> [--tags t1,t2]'));
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
// 배치 모드: 폴더 경로이면 내부 파일 전부 처리
|
|
12
|
-
if (existsSync(input) && statSync(input).isDirectory()) {
|
|
13
|
-
const files = readdirSync(input)
|
|
14
|
-
.filter(f => /\.(md|txt|pdf|docx|pptx|xlsx|xls|csv)$/i.test(f))
|
|
15
|
-
.map(f => join(input, f));
|
|
16
|
-
if (files.length === 0) {
|
|
17
|
-
console.error(chalk.yellow(`No supported files found in ${input}`));
|
|
18
|
-
process.exit(1);
|
|
19
|
-
}
|
|
20
|
-
console.log(chalk.dim(`Batch ingest: ${files.length} files from ${input}\n`));
|
|
21
|
-
let success = 0;
|
|
22
|
-
const failed = [];
|
|
23
|
-
for (let i = 0; i < files.length; i++) {
|
|
24
|
-
const file = files[i];
|
|
25
|
-
const name = file.split(/[/\\]/).pop() ?? file;
|
|
26
|
-
const progress = `[${i + 1}/${files.length}]`;
|
|
27
|
-
process.stderr.write(`\r${chalk.dim(progress)} ${name}...`);
|
|
28
|
-
try {
|
|
29
|
-
await ingestCommand(file, { ...options, title: undefined });
|
|
30
|
-
success++;
|
|
31
|
-
}
|
|
32
|
-
catch (err) {
|
|
33
|
-
failed.push(`${name}: ${err instanceof Error ? err.message : 'error'}`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
process.stderr.write('\r' + ' '.repeat(80) + '\r');
|
|
37
|
-
console.log(chalk.green(`Batch complete: ${success}/${files.length} files ingested`));
|
|
38
|
-
if (failed.length > 0) {
|
|
39
|
-
console.log(chalk.yellow(`\nFailed (${failed.length}):`));
|
|
40
|
-
for (const f of failed)
|
|
41
|
-
console.log(chalk.yellow(` - ${f}`));
|
|
42
|
-
}
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const config = loadConfig();
|
|
46
|
-
const tags = options.tags?.split(',').map(t => t.trim()) ?? [];
|
|
47
|
-
const stage = (options.stage ?? 'fleeting');
|
|
48
|
-
// 입력 타입 감지
|
|
49
|
-
let ingestInput;
|
|
50
|
-
if (/^https?:\/\//.test(input)) {
|
|
51
|
-
// URL
|
|
52
|
-
const isYouTube = /youtube\.com\/watch|youtu\.be\//.test(input);
|
|
53
|
-
// SSRF 방지: private IP 차단
|
|
54
|
-
try {
|
|
55
|
-
const url = new URL(input);
|
|
56
|
-
const host = url.hostname;
|
|
57
|
-
if (/^(127\.|10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.|0\.|localhost|::1)/i.test(host)) {
|
|
58
|
-
console.error(chalk.yellow('Private/local URLs are not allowed for security.'));
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
catch { /* invalid URL, will fail at fetch */ }
|
|
63
|
-
if (isYouTube) {
|
|
64
|
-
// YouTube: 전용 추출기 사용 (메타데이터 + 자막 + 타임스탬프)
|
|
65
|
-
try {
|
|
66
|
-
const { extractYouTubeContent, formatYouTubeNote } = await import('@stellavault/core/intelligence/youtube-extractor');
|
|
67
|
-
const ytContent = await extractYouTubeContent(input);
|
|
68
|
-
const body = formatYouTubeNote(ytContent);
|
|
69
|
-
ingestInput = {
|
|
70
|
-
type: 'youtube',
|
|
71
|
-
content: input + '\n' + body,
|
|
72
|
-
tags: [...tags, ...ytContent.tags.filter((t) => !tags.includes(t))],
|
|
73
|
-
stage: stage === 'fleeting' ? 'literature' : stage, // YouTube는 literature로 자동 승격
|
|
74
|
-
title: options.title ?? ytContent.title,
|
|
75
|
-
source: input,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
catch (err) {
|
|
79
|
-
console.error(chalk.yellow(`YouTube extraction failed, falling back to basic URL. (${err instanceof Error ? err.message : 'error'})`));
|
|
80
|
-
ingestInput = {
|
|
81
|
-
type: 'youtube',
|
|
82
|
-
content: input + '\n',
|
|
83
|
-
tags,
|
|
84
|
-
stage,
|
|
85
|
-
title: options.title,
|
|
86
|
-
source: input,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
// 일반 URL: HTML → 텍스트 변환
|
|
92
|
-
let content = input + '\n';
|
|
93
|
-
try {
|
|
94
|
-
const resp = await fetch(input);
|
|
95
|
-
const html = await resp.text();
|
|
96
|
-
const text = html
|
|
97
|
-
.replace(/<script[\s\S]*?<\/script>/gi, '')
|
|
98
|
-
.replace(/<style[\s\S]*?<\/style>/gi, '')
|
|
99
|
-
.replace(/<[^>]+>/g, ' ')
|
|
100
|
-
.replace(/ /g, ' ')
|
|
101
|
-
.replace(/\s+/g, ' ')
|
|
102
|
-
.trim()
|
|
103
|
-
.slice(0, 5000);
|
|
104
|
-
content += text;
|
|
105
|
-
}
|
|
106
|
-
catch (err) {
|
|
107
|
-
console.error(chalk.yellow(`Web fetch failed: saving URL only. (${err instanceof Error ? err.message : 'network error'})`));
|
|
108
|
-
}
|
|
109
|
-
ingestInput = {
|
|
110
|
-
type: 'url',
|
|
111
|
-
content,
|
|
112
|
-
tags,
|
|
113
|
-
stage,
|
|
114
|
-
title: options.title,
|
|
115
|
-
source: input,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
else if (existsSync(input)) {
|
|
120
|
-
// 파일
|
|
121
|
-
const ext = extname(input).toLowerCase();
|
|
122
|
-
const binaryExts = new Set(['.pdf', '.docx', '.pptx', '.xlsx', '.xls']);
|
|
123
|
-
if (binaryExts.has(ext)) {
|
|
124
|
-
// 바이너리 파일: 전용 파서로 텍스트 추출
|
|
125
|
-
try {
|
|
126
|
-
const { extractFileContent } = await import('@stellavault/core/intelligence/file-extractors');
|
|
127
|
-
const extracted = await extractFileContent(resolve(input));
|
|
128
|
-
console.log(chalk.dim(` Extracted ${extracted.metadata.wordCount} words from ${ext} file`));
|
|
129
|
-
ingestInput = {
|
|
130
|
-
type: extracted.sourceFormat,
|
|
131
|
-
content: extracted.text,
|
|
132
|
-
tags: [...tags, extracted.sourceFormat],
|
|
133
|
-
stage, // 제텔카스텐: 모든 인풋은 fleeting에서 시작
|
|
134
|
-
title: options.title ?? extracted.metadata.title,
|
|
135
|
-
source: input,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
catch (err) {
|
|
139
|
-
console.error(chalk.yellow(`Binary file extraction failed, saving as-is. (${err instanceof Error ? err.message : 'error'})`));
|
|
140
|
-
ingestInput = {
|
|
141
|
-
type: 'file',
|
|
142
|
-
content: readFileSync(input, 'utf-8'),
|
|
143
|
-
tags,
|
|
144
|
-
stage,
|
|
145
|
-
title: options.title,
|
|
146
|
-
source: input,
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
// 텍스트 파일: 기존 동작
|
|
152
|
-
const fileContent = readFileSync(input, 'utf-8');
|
|
153
|
-
ingestInput = {
|
|
154
|
-
type: 'file',
|
|
155
|
-
content: fileContent,
|
|
156
|
-
tags,
|
|
157
|
-
stage,
|
|
158
|
-
title: options.title,
|
|
159
|
-
source: input,
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
// 플레인 텍스트
|
|
165
|
-
ingestInput = {
|
|
166
|
-
type: 'text',
|
|
167
|
-
content: input,
|
|
168
|
-
tags,
|
|
169
|
-
stage,
|
|
170
|
-
title: options.title,
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
const result = ingest(config.vaultPath, ingestInput);
|
|
174
|
-
console.log(chalk.green(`Ingested: ${result.title}`));
|
|
175
|
-
console.log(chalk.dim(` Stage: ${result.stage}`));
|
|
176
|
-
console.log(chalk.dim(` Saved: ${result.savedTo}`));
|
|
177
|
-
console.log(chalk.dim(` Words: ${result.wordCount}`));
|
|
178
|
-
if (result.indexCode)
|
|
179
|
-
console.log(chalk.dim(` Index: ${result.indexCode}`));
|
|
180
|
-
if (result.tags.length > 0)
|
|
181
|
-
console.log(chalk.dim(` Tags: ${result.tags.join(', ')}`));
|
|
182
|
-
console.log(chalk.dim(' Wiki: auto-compiled'));
|
|
183
|
-
console.log('');
|
|
184
|
-
}
|
|
185
|
-
export async function promoteCommand(filePath, options) {
|
|
186
|
-
const config = loadConfig();
|
|
187
|
-
const target = options.to;
|
|
188
|
-
if (!['fleeting', 'literature', 'permanent'].includes(target)) {
|
|
189
|
-
console.error(chalk.red('--to must be: fleeting, literature, or permanent'));
|
|
190
|
-
process.exit(1);
|
|
191
|
-
}
|
|
192
|
-
const newPath = promoteNote(config.vaultPath, filePath, target);
|
|
193
|
-
console.log(chalk.green(`Promoted to ${target}: ${newPath}`));
|
|
194
|
-
}
|
|
195
|
-
//# sourceMappingURL=ingest-cmd.js.map
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
// stellavault init — 인터랙티브 온보딩 위저드 (F-A01)
|
|
2
|
-
import { createInterface } from 'node:readline';
|
|
3
|
-
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import { homedir } from 'node:os';
|
|
6
|
-
import ora from 'ora';
|
|
7
|
-
import chalk from 'chalk';
|
|
8
|
-
import { createSqliteVecStore, createLocalEmbedder, indexVault, createSearchEngine } from '@stellavault/core';
|
|
9
|
-
function ask(rl, question, defaultVal) {
|
|
10
|
-
const suffix = defaultVal ? ` ${chalk.dim(`(${defaultVal})`)}` : '';
|
|
11
|
-
return new Promise((resolve) => {
|
|
12
|
-
rl.question(`${question}${suffix}: `, (answer) => {
|
|
13
|
-
resolve(answer.trim() || defaultVal || '');
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
export async function initCommand() {
|
|
18
|
-
console.log('');
|
|
19
|
-
console.log(chalk.bold(' ✦ Stellavault Setup Wizard'));
|
|
20
|
-
console.log(chalk.dim(' Notes die in folders. Let\'s bring yours to life.\n'));
|
|
21
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
22
|
-
try {
|
|
23
|
-
// Step 1: Vault Path
|
|
24
|
-
console.log(chalk.cyan(' Step 1/3') + ' — Where is your Obsidian vault?');
|
|
25
|
-
console.log(chalk.dim(' This is the folder containing your .md files.\n'));
|
|
26
|
-
let vaultPath = '';
|
|
27
|
-
while (!vaultPath) {
|
|
28
|
-
const input = await ask(rl, ' Vault path');
|
|
29
|
-
if (!input) {
|
|
30
|
-
console.log(chalk.yellow(' Please enter your vault path.'));
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
const resolved = input.replace(/^~/, homedir());
|
|
34
|
-
if (!existsSync(resolved)) {
|
|
35
|
-
console.log(chalk.yellow(` Path not found: ${resolved}`));
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
vaultPath = resolved;
|
|
39
|
-
}
|
|
40
|
-
console.log(chalk.green(` ✓ Vault: ${vaultPath}\n`));
|
|
41
|
-
// Save config
|
|
42
|
-
const configDir = join(homedir(), '.stellavault');
|
|
43
|
-
mkdirSync(configDir, { recursive: true });
|
|
44
|
-
const dbPath = join(configDir, 'index.db');
|
|
45
|
-
const configData = {
|
|
46
|
-
vaultPath,
|
|
47
|
-
dbPath,
|
|
48
|
-
embedding: { model: 'local', localModel: 'all-MiniLM-L6-v2' },
|
|
49
|
-
chunking: { maxTokens: 300, overlap: 50, minTokens: 50 },
|
|
50
|
-
search: { defaultLimit: 10, rrfK: 60 },
|
|
51
|
-
mcp: { mode: 'stdio', port: 3333 },
|
|
52
|
-
};
|
|
53
|
-
writeFileSync(join(homedir(), '.stellavault.json'), JSON.stringify(configData, null, 2), 'utf-8');
|
|
54
|
-
console.log(chalk.dim(` Config saved: ~/.stellavault.json`));
|
|
55
|
-
// Step 2: Indexing
|
|
56
|
-
console.log('');
|
|
57
|
-
console.log(chalk.cyan(' Step 2/3') + ' — Indexing your vault');
|
|
58
|
-
console.log(chalk.dim(' Vectorizing notes with local AI (no data leaves your machine).\n'));
|
|
59
|
-
const spinner = ora({ text: ' Loading embedding model (first run downloads ~30MB, please wait)...', indent: 2 }).start();
|
|
60
|
-
const store = createSqliteVecStore(dbPath);
|
|
61
|
-
await store.initialize();
|
|
62
|
-
const embedder = createLocalEmbedder('all-MiniLM-L6-v2');
|
|
63
|
-
await embedder.initialize();
|
|
64
|
-
spinner.text = ' Scanning vault...';
|
|
65
|
-
const result = await indexVault(vaultPath, {
|
|
66
|
-
store,
|
|
67
|
-
embedder,
|
|
68
|
-
chunkOptions: { maxTokens: 300, overlap: 50, minTokens: 50 },
|
|
69
|
-
onProgress(current, total, doc) {
|
|
70
|
-
const pct = Math.round((current / total) * 100);
|
|
71
|
-
const bar = '█'.repeat(Math.floor(pct / 4)) + '░'.repeat(25 - Math.floor(pct / 4));
|
|
72
|
-
spinner.text = ` [${bar}] ${pct}% (${current}/${total}) ${doc.title.slice(0, 30)}`;
|
|
73
|
-
},
|
|
74
|
-
});
|
|
75
|
-
spinner.succeed(chalk.green(` Indexed ${result.indexed} docs, ${result.totalChunks} chunks (${(result.elapsedMs / 1000).toFixed(1)}s)`));
|
|
76
|
-
// Step 3: First Search
|
|
77
|
-
console.log('');
|
|
78
|
-
console.log(chalk.cyan(' Step 3/3') + ' — Try your first search');
|
|
79
|
-
console.log(chalk.dim(' Type a topic you know about. Stellavault finds connections.\n'));
|
|
80
|
-
const searchEngine = createSearchEngine({ store, embedder, rrfK: 60 });
|
|
81
|
-
let searchDone = false;
|
|
82
|
-
while (!searchDone) {
|
|
83
|
-
const query = await ask(rl, ' Search');
|
|
84
|
-
if (!query) {
|
|
85
|
-
console.log(chalk.dim(' Type something, or press Ctrl+C to skip.'));
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
const searchSpinner = ora({ text: ' Searching...', indent: 2 }).start();
|
|
89
|
-
const results = await searchEngine.search({ query, limit: 5 });
|
|
90
|
-
searchSpinner.stop();
|
|
91
|
-
if (results.length === 0) {
|
|
92
|
-
console.log(chalk.yellow(' No results. Try a different topic.'));
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
console.log('');
|
|
96
|
-
for (const r of results) {
|
|
97
|
-
const score = Math.round(r.score * 100);
|
|
98
|
-
const bar = score >= 70 ? chalk.green('●') : score >= 40 ? chalk.yellow('●') : chalk.dim('●');
|
|
99
|
-
console.log(` ${bar} ${chalk.bold(r.document.title)} ${chalk.dim(`(${score}%)`)}`);
|
|
100
|
-
if (r.highlights[0]) {
|
|
101
|
-
console.log(` ${chalk.dim(r.highlights[0].slice(0, 80))}...`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
console.log('');
|
|
105
|
-
searchDone = true;
|
|
106
|
-
}
|
|
107
|
-
await store.close();
|
|
108
|
-
// Done!
|
|
109
|
-
console.log(chalk.bold.green(' ✦ Setup complete!\n'));
|
|
110
|
-
console.log(' What\'s next:');
|
|
111
|
-
console.log(` ${chalk.cyan('stellavault graph')} Launch 3D knowledge graph`);
|
|
112
|
-
console.log(` ${chalk.cyan('stellavault decay')} See what knowledge is fading`);
|
|
113
|
-
console.log(` ${chalk.cyan('stellavault brief')} Get your daily knowledge briefing`);
|
|
114
|
-
console.log(` ${chalk.cyan('stellavault serve')} Connect AI agents via MCP`);
|
|
115
|
-
console.log('');
|
|
116
|
-
// Day 2 Experience — 습관화 제안
|
|
117
|
-
console.log(chalk.cyan(' ─── Build a habit ───\n'));
|
|
118
|
-
const setupCron = await ask(rl, ' Auto-run daily briefing? (adds cron job) [Y/n]', 'Y');
|
|
119
|
-
if (setupCron.toLowerCase() !== 'n') {
|
|
120
|
-
const cronLine = `0 9 * * * cd "${vaultPath}" && stellavault brief >> ~/.stellavault/daily.log 2>&1`;
|
|
121
|
-
const platform = process.platform;
|
|
122
|
-
if (platform === 'win32') {
|
|
123
|
-
console.log(chalk.dim('\n Windows: Add this to Task Scheduler:'));
|
|
124
|
-
console.log(chalk.dim(` Action: stellavault brief`));
|
|
125
|
-
console.log(chalk.dim(` Trigger: Daily at 9:00 AM`));
|
|
126
|
-
console.log(chalk.dim(` Start in: ${vaultPath}\n`));
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
console.log(chalk.dim('\n Add this to your crontab (crontab -e):'));
|
|
130
|
-
console.log(chalk.dim(` ${cronLine}\n`));
|
|
131
|
-
const autoAdd = await ask(rl, ' Add to crontab now? [Y/n]', 'Y');
|
|
132
|
-
if (autoAdd.toLowerCase() !== 'n') {
|
|
133
|
-
try {
|
|
134
|
-
const { execSync } = await import('node:child_process');
|
|
135
|
-
const existing = execSync('crontab -l 2>/dev/null || true', { encoding: 'utf-8' });
|
|
136
|
-
if (!existing.includes('stellavault brief')) {
|
|
137
|
-
execSync(`(crontab -l 2>/dev/null; echo "${cronLine}") | crontab -`, { encoding: 'utf-8' });
|
|
138
|
-
console.log(chalk.green(' ✓ Daily briefing scheduled at 9:00 AM\n'));
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
console.log(chalk.dim(' Already scheduled.\n'));
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
catch {
|
|
145
|
-
console.log(chalk.yellow(' Could not auto-add. Please add manually.\n'));
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
console.log(chalk.dim(' Tomorrow morning, run:'));
|
|
151
|
-
console.log(` ${chalk.cyan('stellavault brief')} See what changed overnight`);
|
|
152
|
-
console.log(` ${chalk.cyan('stellavault decay')} Review fading knowledge`);
|
|
153
|
-
console.log('');
|
|
154
|
-
console.log(chalk.dim(' Your knowledge is now alive. ✦'));
|
|
155
|
-
console.log('');
|
|
156
|
-
}
|
|
157
|
-
finally {
|
|
158
|
-
rl.close();
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
//# sourceMappingURL=init-cmd.js.map
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
// stellavault learn — AI learning path recommendations (F-A11)
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { loadConfig, createKnowledgeHub, DecayEngine, detectKnowledgeGaps, generateLearningPath } from '@stellavault/core';
|
|
4
|
-
export async function learnCommand(_opts, cmd) {
|
|
5
|
-
const globalOpts = cmd?.parent?.opts?.() ?? {};
|
|
6
|
-
const jsonMode = globalOpts.json;
|
|
7
|
-
const config = loadConfig();
|
|
8
|
-
const hub = createKnowledgeHub(config);
|
|
9
|
-
await hub.store.initialize();
|
|
10
|
-
await hub.embedder.initialize();
|
|
11
|
-
const db = hub.store.getDb();
|
|
12
|
-
if (!db) {
|
|
13
|
-
console.error(chalk.red('Cannot access database'));
|
|
14
|
-
process.exit(1);
|
|
15
|
-
}
|
|
16
|
-
const decayEngine = new DecayEngine(db);
|
|
17
|
-
const decayReport = await decayEngine.computeAll();
|
|
18
|
-
let gaps = [];
|
|
19
|
-
try {
|
|
20
|
-
const gapReport = await detectKnowledgeGaps(hub.store);
|
|
21
|
-
gaps = gapReport.gaps ?? [];
|
|
22
|
-
}
|
|
23
|
-
catch { /* gaps may fail without enough data */ }
|
|
24
|
-
const path = generateLearningPath({ decayReport, gaps }, 15);
|
|
25
|
-
await hub.store.close();
|
|
26
|
-
if (jsonMode) {
|
|
27
|
-
console.log(JSON.stringify(path, null, 2));
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
console.log('');
|
|
31
|
-
console.log(chalk.bold(' 🎯 Your Learning Path'));
|
|
32
|
-
console.log(chalk.dim(` ${path.summary.reviewCount} to review · ${path.summary.bridgeCount} gaps to bridge · ~${path.summary.estimatedMinutes}min`));
|
|
33
|
-
console.log('');
|
|
34
|
-
for (const item of path.items) {
|
|
35
|
-
const icon = item.category === 'review' ? '📖' : item.category === 'bridge' ? '🌉' : '🔭';
|
|
36
|
-
const prioColor = item.priority === 'critical' ? chalk.red : item.priority === 'important' ? chalk.yellow : chalk.dim;
|
|
37
|
-
const prioLabel = prioColor(item.priority.toUpperCase());
|
|
38
|
-
console.log(` ${icon} ${prioLabel} ${chalk.bold(item.title)} ${chalk.dim(`(${item.score}pt)`)}`);
|
|
39
|
-
console.log(` ${chalk.dim(item.reason)}`);
|
|
40
|
-
}
|
|
41
|
-
if (path.items.length === 0) {
|
|
42
|
-
console.log(chalk.green(' All clear! Your knowledge is in great shape.'));
|
|
43
|
-
}
|
|
44
|
-
console.log('');
|
|
45
|
-
console.log(chalk.dim(' 💡 stellavault review — start reviewing decaying notes'));
|
|
46
|
-
console.log('');
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=learn-cmd.js.map
|