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,55 +0,0 @@
|
|
|
1
|
-
// Design Ref: 중복/유사 노트 탐지
|
|
2
|
-
// 기존 벡터 임베딩의 cosine similarity 활용
|
|
3
|
-
/**
|
|
4
|
-
* 벡터 유사도 기반 중복 노트 탐지.
|
|
5
|
-
* 문서별 평균 임베딩을 비교하여 threshold 이상인 쌍을 반환.
|
|
6
|
-
*/
|
|
7
|
-
export async function detectDuplicates(store, threshold = 0.88, limit = 20) {
|
|
8
|
-
const docs = await store.getAllDocuments();
|
|
9
|
-
const embeddings = await store.getDocumentEmbeddings();
|
|
10
|
-
if (docs.length < 2)
|
|
11
|
-
return [];
|
|
12
|
-
// 문서별 평균 임베딩 계산
|
|
13
|
-
const docVecs = new Map();
|
|
14
|
-
for (const doc of docs) {
|
|
15
|
-
const vec = embeddings.get(doc.id);
|
|
16
|
-
if (!vec || vec.length === 0)
|
|
17
|
-
continue;
|
|
18
|
-
docVecs.set(doc.id, { vec: Array.from(vec), title: doc.title, filePath: doc.filePath });
|
|
19
|
-
}
|
|
20
|
-
const ids = [...docVecs.keys()];
|
|
21
|
-
const pairs = [];
|
|
22
|
-
// O(n²) — 1,200 문서면 ~720K 비교, 수 초 이내
|
|
23
|
-
for (let i = 0; i < ids.length; i++) {
|
|
24
|
-
for (let j = i + 1; j < ids.length; j++) {
|
|
25
|
-
const a = docVecs.get(ids[i]);
|
|
26
|
-
const b = docVecs.get(ids[j]);
|
|
27
|
-
const sim = cosineSimilarity(a.vec, b.vec);
|
|
28
|
-
if (sim >= threshold) {
|
|
29
|
-
pairs.push({
|
|
30
|
-
docA: { id: ids[i], title: a.title, filePath: a.filePath },
|
|
31
|
-
docB: { id: ids[j], title: b.title, filePath: b.filePath },
|
|
32
|
-
similarity: Math.round(sim * 1000) / 1000,
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
if (pairs.length >= limit * 2)
|
|
37
|
-
break; // 충분히 찾으면 중단
|
|
38
|
-
}
|
|
39
|
-
return pairs
|
|
40
|
-
.sort((a, b) => b.similarity - a.similarity)
|
|
41
|
-
.slice(0, limit);
|
|
42
|
-
}
|
|
43
|
-
function cosineSimilarity(a, b) {
|
|
44
|
-
if (a.length !== b.length)
|
|
45
|
-
return 0;
|
|
46
|
-
let dot = 0, normA = 0, normB = 0;
|
|
47
|
-
for (let i = 0; i < a.length; i++) {
|
|
48
|
-
dot += a[i] * b[i];
|
|
49
|
-
normA += a[i] * a[i];
|
|
50
|
-
normB += b[i] * b[i];
|
|
51
|
-
}
|
|
52
|
-
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
53
|
-
return denom === 0 ? 0 : dot / denom;
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=duplicate-detector.js.map
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export interface ExtractedContent {
|
|
2
|
-
text: string;
|
|
3
|
-
metadata: {
|
|
4
|
-
title?: string;
|
|
5
|
-
author?: string;
|
|
6
|
-
pageCount?: number;
|
|
7
|
-
wordCount: number;
|
|
8
|
-
};
|
|
9
|
-
sourceFormat: 'pdf' | 'docx' | 'pptx' | 'xlsx' | 'xls' | 'text';
|
|
10
|
-
}
|
|
11
|
-
export declare function isBinaryFormat(filePath: string): boolean;
|
|
12
|
-
export declare function extractFileContent(filePath: string): Promise<ExtractedContent>;
|
|
13
|
-
//# sourceMappingURL=file-extractors.d.ts.map
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
// Design Ref: §file-ingest-v2 — Binary file text extraction dispatchers
|
|
2
|
-
// Plan SC: SC1-SC5 (format-specific extraction + fallback)
|
|
3
|
-
import { readFileSync, statSync } from 'node:fs';
|
|
4
|
-
import { extname, basename } from 'node:path';
|
|
5
|
-
const BINARY_EXTS = new Set(['.pdf', '.docx', '.pptx', '.xlsx', '.xls']);
|
|
6
|
-
export function isBinaryFormat(filePath) {
|
|
7
|
-
return BINARY_EXTS.has(extname(filePath).toLowerCase());
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* 파일 경로에서 텍스트 추출. 확장자 기반 파서 디스패치.
|
|
11
|
-
* 지원: .pdf, .docx, .pptx, .xlsx, .xls
|
|
12
|
-
* 미지원 확장자: utf-8 텍스트로 읽기
|
|
13
|
-
*/
|
|
14
|
-
const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB
|
|
15
|
-
export async function extractFileContent(filePath) {
|
|
16
|
-
const ext = extname(filePath).toLowerCase();
|
|
17
|
-
const { size } = statSync(filePath);
|
|
18
|
-
if (size > MAX_FILE_SIZE) {
|
|
19
|
-
throw new Error(`File too large (${Math.round(size / 1024 / 1024)}MB > 50MB limit)`);
|
|
20
|
-
}
|
|
21
|
-
const buffer = readFileSync(filePath);
|
|
22
|
-
switch (ext) {
|
|
23
|
-
case '.pdf': return extractPdf(buffer, filePath);
|
|
24
|
-
case '.docx': return extractDocx(buffer, filePath);
|
|
25
|
-
case '.pptx': return extractPptx(buffer, filePath);
|
|
26
|
-
case '.xlsx': return extractXlsx(buffer, filePath);
|
|
27
|
-
case '.xls': return extractXlsx(buffer, filePath);
|
|
28
|
-
default: return extractText(filePath);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
async function extractPdf(buffer, filePath) {
|
|
32
|
-
try {
|
|
33
|
-
const { extractText } = await import('unpdf');
|
|
34
|
-
const result = await extractText(new Uint8Array(buffer));
|
|
35
|
-
const text = Array.isArray(result.text) ? result.text.join('\n\n') : (result.text ?? '');
|
|
36
|
-
return {
|
|
37
|
-
text,
|
|
38
|
-
metadata: {
|
|
39
|
-
title: basename(filePath, '.pdf'),
|
|
40
|
-
pageCount: result.totalPages,
|
|
41
|
-
wordCount: text.split(/\s+/).filter(Boolean).length,
|
|
42
|
-
},
|
|
43
|
-
sourceFormat: 'pdf',
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
catch (err) {
|
|
47
|
-
console.error(`PDF extraction failed: ${err instanceof Error ? err.message : 'unknown'}`);
|
|
48
|
-
return fallback(filePath, 'pdf');
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
async function extractDocx(buffer, filePath) {
|
|
52
|
-
try {
|
|
53
|
-
const mammoth = await import('mammoth');
|
|
54
|
-
const result = await mammoth.default.extractRawText({ buffer });
|
|
55
|
-
const text = result.value ?? '';
|
|
56
|
-
return {
|
|
57
|
-
text,
|
|
58
|
-
metadata: {
|
|
59
|
-
title: basename(filePath, '.docx'),
|
|
60
|
-
wordCount: text.split(/\s+/).filter(Boolean).length,
|
|
61
|
-
},
|
|
62
|
-
sourceFormat: 'docx',
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
catch (err) {
|
|
66
|
-
console.error(`DOCX extraction failed: ${err instanceof Error ? err.message : 'unknown'}`);
|
|
67
|
-
return fallback(filePath, 'docx');
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
async function extractPptx(buffer, filePath) {
|
|
71
|
-
try {
|
|
72
|
-
const officeparser = await import('officeparser');
|
|
73
|
-
const text = String(await officeparser.default.parseOffice(buffer));
|
|
74
|
-
return {
|
|
75
|
-
text: text ?? '',
|
|
76
|
-
metadata: {
|
|
77
|
-
title: basename(filePath, '.pptx'),
|
|
78
|
-
wordCount: (text ?? '').split(/\s+/).filter(Boolean).length,
|
|
79
|
-
},
|
|
80
|
-
sourceFormat: 'pptx',
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
catch (err) {
|
|
84
|
-
console.error(`PPTX extraction failed: ${err instanceof Error ? err.message : 'unknown'}`);
|
|
85
|
-
return fallback(filePath, 'pptx');
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
async function extractXlsx(buffer, filePath) {
|
|
89
|
-
const ext = extname(filePath).toLowerCase();
|
|
90
|
-
const format = ext === '.xls' ? 'xls' : 'xlsx';
|
|
91
|
-
try {
|
|
92
|
-
const XLSX = await import('xlsx');
|
|
93
|
-
const workbook = XLSX.read(buffer);
|
|
94
|
-
const parts = [];
|
|
95
|
-
for (const name of workbook.SheetNames) {
|
|
96
|
-
const sheet = workbook.Sheets[name];
|
|
97
|
-
// 마크다운 테이블 형식 (헤더-값 구조 보존)
|
|
98
|
-
const rows = XLSX.utils.sheet_to_json(sheet, { header: 1 });
|
|
99
|
-
if (rows.length === 0)
|
|
100
|
-
continue;
|
|
101
|
-
parts.push(`## ${name}\n`);
|
|
102
|
-
const headers = rows[0].map((h) => String(h ?? ''));
|
|
103
|
-
parts.push(`| ${headers.join(' | ')} |`);
|
|
104
|
-
parts.push(`| ${headers.map(() => '---').join(' | ')} |`);
|
|
105
|
-
for (const row of rows.slice(1)) {
|
|
106
|
-
const cells = headers.map((_, i) => String(row[i] ?? ''));
|
|
107
|
-
parts.push(`| ${cells.join(' | ')} |`);
|
|
108
|
-
}
|
|
109
|
-
parts.push('');
|
|
110
|
-
// JSON 구조도 포함 (AI 검색/ask에서 수치 활용 가능)
|
|
111
|
-
if (rows.length <= 100) {
|
|
112
|
-
const jsonRows = XLSX.utils.sheet_to_json(sheet);
|
|
113
|
-
if (jsonRows.length > 0) {
|
|
114
|
-
parts.push(`<details><summary>Structured Data (${jsonRows.length} rows)</summary>\n`);
|
|
115
|
-
parts.push('```json');
|
|
116
|
-
parts.push(JSON.stringify(jsonRows.slice(0, 50), null, 2));
|
|
117
|
-
parts.push('```');
|
|
118
|
-
parts.push('</details>\n');
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
const text = parts.join('\n');
|
|
123
|
-
return {
|
|
124
|
-
text,
|
|
125
|
-
metadata: {
|
|
126
|
-
title: basename(filePath, ext),
|
|
127
|
-
wordCount: text.split(/\s+/).filter(Boolean).length,
|
|
128
|
-
},
|
|
129
|
-
sourceFormat: format,
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
catch (err) {
|
|
133
|
-
console.error(`XLSX extraction failed: ${err instanceof Error ? err.message : 'unknown'}`);
|
|
134
|
-
return fallback(filePath, format);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
function extractText(filePath) {
|
|
138
|
-
const text = readFileSync(filePath, 'utf-8');
|
|
139
|
-
return {
|
|
140
|
-
text,
|
|
141
|
-
metadata: {
|
|
142
|
-
title: basename(filePath),
|
|
143
|
-
wordCount: text.split(/\s+/).filter(Boolean).length,
|
|
144
|
-
},
|
|
145
|
-
sourceFormat: 'text',
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
function fallback(filePath, format) {
|
|
149
|
-
return {
|
|
150
|
-
text: `[Failed to extract text from ${basename(filePath)}. Install required parser or convert to a text format.]`,
|
|
151
|
-
metadata: { title: basename(filePath), wordCount: 0 },
|
|
152
|
-
sourceFormat: format,
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
//# sourceMappingURL=file-extractors.js.map
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FSRS parameters tuned for knowledge notes (not flashcards).
|
|
3
|
-
* Knowledge notes have longer natural retention than flashcards.
|
|
4
|
-
*/
|
|
5
|
-
export declare const FSRS_PARAMS: {
|
|
6
|
-
readonly initialStability: 7;
|
|
7
|
-
readonly difficulty: 5;
|
|
8
|
-
readonly a: 0.4;
|
|
9
|
-
readonly b: 0.6;
|
|
10
|
-
readonly c: 0.2;
|
|
11
|
-
readonly d: 1;
|
|
12
|
-
readonly sizeFactor: 0.5;
|
|
13
|
-
readonly connectionFactor: 1;
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* Compute retrievability R(t) using FSRS power forgetting curve.
|
|
17
|
-
* R(t) = (1 + t / (9 * S))^(-1)
|
|
18
|
-
*
|
|
19
|
-
* @param stabilityDays - Stability S (days until R drops to ~0.9)
|
|
20
|
-
* @param elapsedDays - Days since last access
|
|
21
|
-
* @returns Retrievability 0~1
|
|
22
|
-
*/
|
|
23
|
-
export declare function computeRetrievability(stabilityDays: number, elapsedDays: number): number;
|
|
24
|
-
/**
|
|
25
|
-
* Update stability after an access event (successful recall).
|
|
26
|
-
* S' = S * (1 + a * D^(-b) * S^(-c) * (e^(d*(1-R)) - 1))
|
|
27
|
-
*
|
|
28
|
-
* @param currentS - Current stability
|
|
29
|
-
* @param difficulty - Note difficulty (1~10)
|
|
30
|
-
* @param currentR - Retrievability at access time
|
|
31
|
-
* @returns New stability (always >= currentS)
|
|
32
|
-
*/
|
|
33
|
-
export declare function updateStability(currentS: number, difficulty: number, currentR: number): number;
|
|
34
|
-
/**
|
|
35
|
-
* Estimate initial stability based on note characteristics.
|
|
36
|
-
* Longer notes and more connected notes are more stable.
|
|
37
|
-
*/
|
|
38
|
-
export declare function estimateInitialStability(contentLength: number, connectionCount: number): number;
|
|
39
|
-
/**
|
|
40
|
-
* Compute elapsed days between two ISO timestamps.
|
|
41
|
-
*/
|
|
42
|
-
export declare function elapsedDays(from: string, to?: string): number;
|
|
43
|
-
//# sourceMappingURL=fsrs.d.ts.map
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
// Design Ref: §1 — FSRS-6 알고리즘 (순수 함수)
|
|
2
|
-
// Plan SC: SC-01 (R값 계산), SC-02 (stability 업데이트)
|
|
3
|
-
/**
|
|
4
|
-
* FSRS parameters tuned for knowledge notes (not flashcards).
|
|
5
|
-
* Knowledge notes have longer natural retention than flashcards.
|
|
6
|
-
*/
|
|
7
|
-
export const FSRS_PARAMS = {
|
|
8
|
-
initialStability: 7.0, // 7 days for new notes
|
|
9
|
-
difficulty: 5.0, // default difficulty (1~10)
|
|
10
|
-
// Stability growth factors
|
|
11
|
-
a: 0.4,
|
|
12
|
-
b: 0.6,
|
|
13
|
-
c: 0.2,
|
|
14
|
-
d: 1.0,
|
|
15
|
-
// Stability bonus for large/connected notes
|
|
16
|
-
sizeFactor: 0.5, // additional days per 1000 chars
|
|
17
|
-
connectionFactor: 1.0, // additional days per connection
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* Compute retrievability R(t) using FSRS power forgetting curve.
|
|
21
|
-
* R(t) = (1 + t / (9 * S))^(-1)
|
|
22
|
-
*
|
|
23
|
-
* @param stabilityDays - Stability S (days until R drops to ~0.9)
|
|
24
|
-
* @param elapsedDays - Days since last access
|
|
25
|
-
* @returns Retrievability 0~1
|
|
26
|
-
*/
|
|
27
|
-
export function computeRetrievability(stabilityDays, elapsedDays) {
|
|
28
|
-
if (elapsedDays <= 0)
|
|
29
|
-
return 1.0;
|
|
30
|
-
if (stabilityDays <= 0)
|
|
31
|
-
return 0.0;
|
|
32
|
-
return Math.pow(1 + elapsedDays / (9 * stabilityDays), -1);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Update stability after an access event (successful recall).
|
|
36
|
-
* S' = S * (1 + a * D^(-b) * S^(-c) * (e^(d*(1-R)) - 1))
|
|
37
|
-
*
|
|
38
|
-
* @param currentS - Current stability
|
|
39
|
-
* @param difficulty - Note difficulty (1~10)
|
|
40
|
-
* @param currentR - Retrievability at access time
|
|
41
|
-
* @returns New stability (always >= currentS)
|
|
42
|
-
*/
|
|
43
|
-
export function updateStability(currentS, difficulty, currentR) {
|
|
44
|
-
const { a, b, c, d } = FSRS_PARAMS;
|
|
45
|
-
const growth = a
|
|
46
|
-
* Math.pow(difficulty, -b)
|
|
47
|
-
* Math.pow(currentS, -c)
|
|
48
|
-
* (Math.exp(d * (1 - currentR)) - 1);
|
|
49
|
-
const newS = currentS * (1 + Math.max(0, growth));
|
|
50
|
-
// Cap at 365 days (1 year max stability)
|
|
51
|
-
return Math.min(newS, 365);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Estimate initial stability based on note characteristics.
|
|
55
|
-
* Longer notes and more connected notes are more stable.
|
|
56
|
-
*/
|
|
57
|
-
export function estimateInitialStability(contentLength, connectionCount) {
|
|
58
|
-
const base = FSRS_PARAMS.initialStability;
|
|
59
|
-
const sizeBonus = Math.min(contentLength / 1000, 10) * FSRS_PARAMS.sizeFactor;
|
|
60
|
-
const connBonus = Math.min(connectionCount, 10) * FSRS_PARAMS.connectionFactor;
|
|
61
|
-
return base + sizeBonus + connBonus;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Compute elapsed days between two ISO timestamps.
|
|
65
|
-
*/
|
|
66
|
-
export function elapsedDays(from, to = new Date().toISOString()) {
|
|
67
|
-
const msPerDay = 86400000;
|
|
68
|
-
return Math.max(0, (new Date(to).getTime() - new Date(from).getTime()) / msPerDay);
|
|
69
|
-
}
|
|
70
|
-
//# sourceMappingURL=fsrs.js.map
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { VectorStore } from '../store/types.js';
|
|
2
|
-
export interface KnowledgeGap {
|
|
3
|
-
clusterA: string;
|
|
4
|
-
clusterB: string;
|
|
5
|
-
bridgeCount: number;
|
|
6
|
-
suggestedTopic: string;
|
|
7
|
-
severity: 'high' | 'medium' | 'low';
|
|
8
|
-
}
|
|
9
|
-
export interface GapReport {
|
|
10
|
-
totalClusters: number;
|
|
11
|
-
totalGaps: number;
|
|
12
|
-
gaps: KnowledgeGap[];
|
|
13
|
-
isolatedNodes: Array<{
|
|
14
|
-
id: string;
|
|
15
|
-
title: string;
|
|
16
|
-
connections: number;
|
|
17
|
-
}>;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* 그래프 데이터에서 지식 갭을 탐지.
|
|
21
|
-
* - 클러스터 간 연결이 약한 영역
|
|
22
|
-
* - 고립된 노드 (연결 0~1개)
|
|
23
|
-
*/
|
|
24
|
-
export declare function detectKnowledgeGaps(store: VectorStore, graphData?: any): Promise<GapReport>;
|
|
25
|
-
//# sourceMappingURL=gap-detector.d.ts.map
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// Design Ref: F01 — 지식 갭 탐지기
|
|
2
|
-
// 클러스터 간 브릿지 노드 부족 영역 식별
|
|
3
|
-
/**
|
|
4
|
-
* 그래프 데이터에서 지식 갭을 탐지.
|
|
5
|
-
* - 클러스터 간 연결이 약한 영역
|
|
6
|
-
* - 고립된 노드 (연결 0~1개)
|
|
7
|
-
*/
|
|
8
|
-
export async function detectKnowledgeGaps(store, graphData) {
|
|
9
|
-
const docs = await store.getAllDocuments();
|
|
10
|
-
const embeddings = await store.getDocumentEmbeddings();
|
|
11
|
-
// 그래프 데이터가 없으면 간단히 계산
|
|
12
|
-
if (!graphData) {
|
|
13
|
-
const { buildGraphData } = await import('../api/graph-data.js');
|
|
14
|
-
graphData = await buildGraphData(store);
|
|
15
|
-
}
|
|
16
|
-
const { nodes, edges, clusters } = graphData;
|
|
17
|
-
// 1. 클러스터 간 연결 수 매트릭스
|
|
18
|
-
const clusterEdges = new Map();
|
|
19
|
-
for (const edge of edges) {
|
|
20
|
-
const nodeA = nodes.find((n) => n.id === edge.source);
|
|
21
|
-
const nodeB = nodes.find((n) => n.id === edge.target);
|
|
22
|
-
if (!nodeA || !nodeB || nodeA.clusterId === nodeB.clusterId)
|
|
23
|
-
continue;
|
|
24
|
-
const key = [
|
|
25
|
-
Math.min(nodeA.clusterId, nodeB.clusterId),
|
|
26
|
-
Math.max(nodeA.clusterId, nodeB.clusterId),
|
|
27
|
-
].join('-');
|
|
28
|
-
clusterEdges.set(key, (clusterEdges.get(key) ?? 0) + 1);
|
|
29
|
-
}
|
|
30
|
-
// 2. 갭 식별 (클러스터 쌍 중 연결이 적은 것)
|
|
31
|
-
const gaps = [];
|
|
32
|
-
const clusterLabels = new Map(clusters.map((c) => [c.id, c.label]));
|
|
33
|
-
for (let i = 0; i < clusters.length; i++) {
|
|
34
|
-
for (let j = i + 1; j < clusters.length; j++) {
|
|
35
|
-
const key = `${Math.min(clusters[i].id, clusters[j].id)}-${Math.max(clusters[i].id, clusters[j].id)}`;
|
|
36
|
-
const bridgeCount = clusterEdges.get(key) ?? 0;
|
|
37
|
-
// 연결이 3개 미만이면 갭
|
|
38
|
-
if (bridgeCount < 3) {
|
|
39
|
-
const labelA = clusterLabels.get(clusters[i].id) ?? `Cluster ${clusters[i].id}`;
|
|
40
|
-
const labelB = clusterLabels.get(clusters[j].id) ?? `Cluster ${clusters[j].id}`;
|
|
41
|
-
// 제안 주제: 두 클러스터 이름에서 추출
|
|
42
|
-
const nameA = labelA.replace(/\s*\(\d+\)$/, '');
|
|
43
|
-
const nameB = labelB.replace(/\s*\(\d+\)$/, '');
|
|
44
|
-
gaps.push({
|
|
45
|
-
clusterA: labelA,
|
|
46
|
-
clusterB: labelB,
|
|
47
|
-
bridgeCount,
|
|
48
|
-
suggestedTopic: `${nameA} + ${nameB} 연결 지식`,
|
|
49
|
-
severity: bridgeCount === 0 ? 'high' : bridgeCount < 2 ? 'medium' : 'low',
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// 3. 고립 노드 (연결 1개 이하)
|
|
55
|
-
const connectionCounts = new Map();
|
|
56
|
-
for (const edge of edges) {
|
|
57
|
-
connectionCounts.set(edge.source, (connectionCounts.get(edge.source) ?? 0) + 1);
|
|
58
|
-
connectionCounts.set(edge.target, (connectionCounts.get(edge.target) ?? 0) + 1);
|
|
59
|
-
}
|
|
60
|
-
const isolatedNodes = nodes
|
|
61
|
-
.filter((n) => (connectionCounts.get(n.id) ?? 0) <= 1)
|
|
62
|
-
.map((n) => ({
|
|
63
|
-
id: n.id,
|
|
64
|
-
title: n.label,
|
|
65
|
-
connections: connectionCounts.get(n.id) ?? 0,
|
|
66
|
-
}))
|
|
67
|
-
.slice(0, 20);
|
|
68
|
-
return {
|
|
69
|
-
totalClusters: clusters.length,
|
|
70
|
-
totalGaps: gaps.filter(g => g.severity !== 'low').length,
|
|
71
|
-
gaps: gaps.sort((a, b) => {
|
|
72
|
-
const sev = { high: 0, medium: 1, low: 2 };
|
|
73
|
-
return sev[a.severity] - sev[b.severity];
|
|
74
|
-
}).slice(0, 15),
|
|
75
|
-
isolatedNodes,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
//# sourceMappingURL=gap-detector.js.map
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { type FolderNames } from '../config.js';
|
|
2
|
-
export type NoteStage = 'fleeting' | 'literature' | 'permanent';
|
|
3
|
-
export interface IngestInput {
|
|
4
|
-
type: 'url' | 'text' | 'file' | 'youtube' | 'pdf-text' | 'pdf' | 'docx' | 'pptx' | 'xlsx' | 'xls';
|
|
5
|
-
content: string;
|
|
6
|
-
title?: string;
|
|
7
|
-
tags?: string[];
|
|
8
|
-
source?: string;
|
|
9
|
-
stage?: NoteStage;
|
|
10
|
-
}
|
|
11
|
-
export interface IngestResult {
|
|
12
|
-
savedTo: string;
|
|
13
|
-
stage: NoteStage;
|
|
14
|
-
title: string;
|
|
15
|
-
indexCode?: string;
|
|
16
|
-
tags: string[];
|
|
17
|
-
wordCount: number;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* 어떤 입력이든 Stellavault 표준 포맷으로 변환하여 저장.
|
|
21
|
-
*/
|
|
22
|
-
export declare function ingest(vaultPath: string, input: IngestInput, folders?: FolderNames): IngestResult;
|
|
23
|
-
/**
|
|
24
|
-
* 여러 입력을 배치 처리.
|
|
25
|
-
*/
|
|
26
|
-
export declare function ingestBatch(vaultPath: string, inputs: IngestInput[]): IngestResult[];
|
|
27
|
-
/**
|
|
28
|
-
* 노트 승격: fleeting → literature → permanent.
|
|
29
|
-
* 내용이 충분히 정제되면 다음 단계로 이동.
|
|
30
|
-
*/
|
|
31
|
-
export declare function promoteNote(vaultPath: string, filePath: string, targetStage: NoteStage, folders?: FolderNames): string;
|
|
32
|
-
//# sourceMappingURL=ingest-pipeline.d.ts.map
|