sxng-cli 1.0.5 → 1.0.7

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 (65) hide show
  1. package/README.md +120 -4
  2. package/dist/commands/build-graph.d.ts +8 -0
  3. package/dist/commands/build-graph.d.ts.map +1 -0
  4. package/dist/commands/build-graph.js +70 -0
  5. package/dist/commands/build-graph.js.map +1 -0
  6. package/dist/commands/extract.d.ts +11 -0
  7. package/dist/commands/extract.d.ts.map +1 -0
  8. package/dist/commands/extract.js +88 -0
  9. package/dist/commands/extract.js.map +1 -0
  10. package/dist/commands/graph-add.d.ts +13 -0
  11. package/dist/commands/graph-add.d.ts.map +1 -0
  12. package/dist/commands/graph-add.js +155 -0
  13. package/dist/commands/graph-add.js.map +1 -0
  14. package/dist/commands/query-graph.d.ts +11 -0
  15. package/dist/commands/query-graph.d.ts.map +1 -0
  16. package/dist/commands/query-graph.js +153 -0
  17. package/dist/commands/query-graph.js.map +1 -0
  18. package/dist/commands/raw.d.ts +14 -0
  19. package/dist/commands/raw.d.ts.map +1 -0
  20. package/dist/commands/raw.js +125 -0
  21. package/dist/commands/raw.js.map +1 -0
  22. package/dist/commands/session.d.ts +28 -0
  23. package/dist/commands/session.d.ts.map +1 -0
  24. package/dist/commands/session.js +144 -0
  25. package/dist/commands/session.js.map +1 -0
  26. package/dist/config.d.ts +1 -1
  27. package/dist/config.d.ts.map +1 -1
  28. package/dist/config.js +1 -1
  29. package/dist/config.js.map +1 -1
  30. package/dist/deep/dedupe.d.ts +14 -0
  31. package/dist/deep/dedupe.d.ts.map +1 -0
  32. package/dist/deep/dedupe.js +53 -0
  33. package/dist/deep/dedupe.js.map +1 -0
  34. package/dist/deep/extractor.d.ts +29 -0
  35. package/dist/deep/extractor.d.ts.map +1 -0
  36. package/dist/deep/extractor.js +125 -0
  37. package/dist/deep/extractor.js.map +1 -0
  38. package/dist/deep/graph.d.ts +55 -0
  39. package/dist/deep/graph.d.ts.map +1 -0
  40. package/dist/deep/graph.js +153 -0
  41. package/dist/deep/graph.js.map +1 -0
  42. package/dist/deep/index.d.ts +10 -0
  43. package/dist/deep/index.d.ts.map +1 -0
  44. package/dist/deep/index.js +10 -0
  45. package/dist/deep/index.js.map +1 -0
  46. package/dist/deep/keywords.d.ts +27 -0
  47. package/dist/deep/keywords.d.ts.map +1 -0
  48. package/dist/deep/keywords.js +293 -0
  49. package/dist/deep/keywords.js.map +1 -0
  50. package/dist/deep/rrf.d.ts +13 -0
  51. package/dist/deep/rrf.d.ts.map +1 -0
  52. package/dist/deep/rrf.js +23 -0
  53. package/dist/deep/rrf.js.map +1 -0
  54. package/dist/deep/session.d.ts +69 -0
  55. package/dist/deep/session.d.ts.map +1 -0
  56. package/dist/deep/session.js +206 -0
  57. package/dist/deep/session.js.map +1 -0
  58. package/dist/deep/simhash.d.ts +12 -0
  59. package/dist/deep/simhash.d.ts.map +1 -0
  60. package/dist/deep/simhash.js +56 -0
  61. package/dist/deep/simhash.js.map +1 -0
  62. package/dist/runCli.d.ts.map +1 -1
  63. package/dist/runCli.js +394 -100
  64. package/dist/runCli.js.map +1 -1
  65. package/package.json +6 -2
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Entity extraction using compromise NLP (English) + BM25 bigrams (CJK)
3
+ *
4
+ * English: compromise extracts named entities + noun phrases (POS-aware)
5
+ * CJK: character bigrams with BM25 scoring (compromise doesn't support CJK)
6
+ * Both phases use BM25 cross-document scoring for relevance ranking.
7
+ */
8
+ import nlp from 'compromise';
9
+ // Generic nouns that are not meaningful as entities
10
+ const GENERIC_NOUNS = new Set([
11
+ 'language', 'version', 'time', 'way', 'thing', 'part', 'case', 'point',
12
+ 'fact', 'area', 'end', 'result', 'side', 'kind', 'head', 'house',
13
+ 'hand', 'place', 'week', 'system', 'example', 'article', 'page',
14
+ 'site', 'section', 'number', 'step', 'process', 'method', 'approach',
15
+ 'problem', 'question', 'answer', 'issue', 'error', 'change', 'update',
16
+ 'user', 'data', 'file', 'code', 'program', 'function', 'class',
17
+ 'value', 'name', 'key', 'list', 'set', 'type', 'field', 'table',
18
+ 'model', 'project', 'team', 'group', 'world', 'country', 'city',
19
+ 'year', 'month', 'day', 'today', 'people', 'person', 'work', 'job',
20
+ 'home', 'life', 'right', 'left', 'start', 'stop', 'run', 'test',
21
+ 'line', 'row', 'column', 'cell', 'level', 'stage', 'phase', 'state',
22
+ 'form', 'view', 'link', 'source', 'target', 'content',
23
+ 'support', 'feature', 'option', 'status', 'info', 'detail', 'note',
24
+ 'idea', 'topic', 'subject', 'term', 'word', 'text', 'body', 'title',
25
+ 'header', 'footer', 'input', 'output', 'format', 'style', 'color',
26
+ 'size', 'length', 'width', 'height', 'depth', 'speed', 'rate',
27
+ 'price', 'cost', 'amount', 'total', 'sum', 'diff', 'range', 'limit',
28
+ 'access', 'control', 'rule', 'policy', 'plan', 'goal', 'task', 'action',
29
+ 'event', 'message', 'request', 'response', 'record', 'history', 'log',
30
+ 'report', 'search', 'filter', 'sort', 'order',
31
+ 'performance', 'quality', 'security', 'privacy', 'release',
32
+ 'build', 'deploy', 'config', 'setting', 'flag', 'param', 'arg',
33
+ 'return', 'cause', 'high', 'low', 'also', 'use', 'using', 'used',
34
+ 'need', 'needed', 'give', 'given', 'make', 'made', 'take', 'taken',
35
+ 'include', 'included', 'provide', 'provided', 'allow', 'create', 'created',
36
+ 'crate', 'this', 'software', 'library', 'framework', 'tool', 'guide',
37
+ 'blog', 'post', 'stack', 'overflow', 'github', 'documentation',
38
+ 'download', 'install', 'learn', 'tutorial', 'introduction', 'overview',
39
+ 'summary', 'description', 'index', 'readme', 'repository', 'package',
40
+ ]);
41
+ // Max length for an entity term — longer ones are likely title noise
42
+ const MAX_TERM_LENGTH = 40;
43
+ // CJK stop words for bigram extraction
44
+ const STOP_WORDS_ZH = new Set([
45
+ '的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一',
46
+ '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着',
47
+ '没有', '看', '好', '自己', '这', '他', '她', '它', '们', '那', '些',
48
+ '什么', '怎么', '如何', '可以', '因为', '所以', '但是', '如果', '虽然',
49
+ '已经', '还是', '或者', '而且', '以及', '对于', '通过', '进行', '使用',
50
+ '并', '及', '等', '于', '中', '为', '与', '从', '把', '被', '让',
51
+ '向', '对', '其', '此', '该', '每', '各', '种', '些', '某',
52
+ ]);
53
+ // English stop words for fallback BM25
54
+ const STOP_WORDS_EN = new Set([
55
+ 'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
56
+ 'of', 'with', 'by', 'from', 'as', 'is', 'was', 'are', 'were', 'been',
57
+ 'be', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
58
+ 'should', 'may', 'might', 'shall', 'can', 'need', 'dare', 'ought', 'used',
59
+ 'it', 'its', 'this', 'that', 'these', 'those', 'i', 'me', 'my', 'we',
60
+ 'our', 'you', 'your', 'he', 'him', 'his', 'she', 'her', 'they', 'them',
61
+ 'their', 'what', 'which', 'who', 'whom', 'when', 'where', 'why', 'how',
62
+ 'not', 'no', 'nor', 'if', 'then', 'else', 'so', 'than', 'too', 'very',
63
+ 'just', 'about', 'above', 'after', 'again', 'all', 'also', 'any', 'because',
64
+ 'before', 'below', 'between', 'both', 'each', 'few', 'more', 'most',
65
+ 'other', 'out', 'over', 'own', 'same', 'some', 'such', 'only', 'into',
66
+ 'up', 'down', 'here', 'there', 'once', 'during', 'while', 'through',
67
+ 'being', 'having', 'doing', 'said', 'get', 'got', 'make', 'made',
68
+ 'like', 'well', 'back', 'even', 'still', 'way', 'take', 'come',
69
+ 'many', 'much', 'new', 'old', 'first', 'last', 'long', 'great',
70
+ 'little', 'right', 'good', 'bad', 'big', 'small', 'large', 'next',
71
+ 'early', 'young', 'important', 'different', 'able', 'using', 'based',
72
+ 'via', 'etc', 'e.g', 'i.e', 'one', 'two', 'three', 'per', 'another',
73
+ ]);
74
+ function isPronoun(term) {
75
+ return term.tags != null && term.tags.includes('Pronoun');
76
+ }
77
+ /**
78
+ * Count the ratio of CJK characters in a string.
79
+ * Returns 0-1 where 1 = entirely CJK.
80
+ */
81
+ function cjkRatio(text) {
82
+ let cjk = 0;
83
+ for (const ch of text) {
84
+ const code = ch.codePointAt(0);
85
+ if ((code >= 0x4E00 && code <= 0x9FFF) || // CJK Unified
86
+ (code >= 0x3040 && code <= 0x309F) || // Hiragana
87
+ (code >= 0x30A0 && code <= 0x30FF) || // Katakana
88
+ (code >= 0xAC00 && code <= 0xD7AF)) { // Hangul
89
+ cjk++;
90
+ }
91
+ }
92
+ return text.length > 0 ? cjk / text.length : 0;
93
+ }
94
+ /**
95
+ * Normalize a term: strip punctuation, trim whitespace.
96
+ */
97
+ function normalizeTerm(text) {
98
+ return text.replace(/[.,;:!?'"»«(){}\[\]\/\\|]+$/, '').replace(/^[.,;:!?'"»«(){}\[\]\/\\|]+/, '').trim();
99
+ }
100
+ /**
101
+ * Check if a candidate term is valid as an entity.
102
+ */
103
+ function isValidEntity(term) {
104
+ if (!term || term.length <= 2)
105
+ return false;
106
+ if (term.length > MAX_TERM_LENGTH)
107
+ return false;
108
+ if (GENERIC_NOUNS.has(term.toLowerCase()))
109
+ return false;
110
+ // Reject if mostly CJK — compromise can't parse CJK properly
111
+ if (cjkRatio(term) > 0.3)
112
+ return false;
113
+ // Reject if looks like a URL or path
114
+ if (/^https?:\/\//.test(term))
115
+ return false;
116
+ if (term.split(/[\/\\]/).length > 3)
117
+ return false;
118
+ return true;
119
+ }
120
+ /**
121
+ * Extract English entity candidates from text using compromise NLP.
122
+ */
123
+ function extractEnglishCandidates(text) {
124
+ const doc = nlp(text);
125
+ const seen = new Set();
126
+ const candidates = [];
127
+ // 1. Named entities: people, places, organizations
128
+ const topics = doc.topics().json();
129
+ for (const topic of topics) {
130
+ const term = normalizeTerm(topic.text);
131
+ if (isValidEntity(term) && !seen.has(term)) {
132
+ seen.add(term);
133
+ candidates.push({ term, type: 'named' });
134
+ }
135
+ }
136
+ // 2. Proper nouns not already captured by topics
137
+ const properNouns = doc.match('#ProperNoun+').json();
138
+ for (const pn of properNouns) {
139
+ const term = normalizeTerm(pn.text);
140
+ if (isValidEntity(term) && !seen.has(term)) {
141
+ seen.add(term);
142
+ candidates.push({ term, type: 'proper' });
143
+ }
144
+ }
145
+ // 3. Noun phrases (filtered)
146
+ const nouns = doc.nouns().json();
147
+ for (const noun of nouns) {
148
+ if (noun.terms && noun.terms.length > 0 && isPronoun(noun.terms[0]))
149
+ continue;
150
+ const root = (noun.noun?.root || noun.text || '').replace(/[.,;:!?'"»«]+$/, '').trim();
151
+ if (!isValidEntity(root))
152
+ continue;
153
+ if (!seen.has(root)) {
154
+ seen.add(root);
155
+ candidates.push({ term: root, type: 'phrase' });
156
+ }
157
+ }
158
+ return candidates;
159
+ }
160
+ /**
161
+ * Extract CJK entity candidates using character bigrams with BM25 scoring.
162
+ * Only used for Chinese/Japanese/Korean text segments.
163
+ */
164
+ function extractCjkCandidates(text) {
165
+ const cjkSegments = text.match(/[一-鿿぀-ゟ゠-ヿ가-힯]+/g) || [];
166
+ const tokens = [];
167
+ for (const segment of cjkSegments) {
168
+ if (segment.length <= 2) {
169
+ if (!STOP_WORDS_ZH.has(segment))
170
+ tokens.push(segment);
171
+ continue;
172
+ }
173
+ for (let i = 0; i < segment.length - 1; i++) {
174
+ const bigram = segment.substring(i, i + 2);
175
+ if (!STOP_WORDS_ZH.has(bigram))
176
+ tokens.push(bigram);
177
+ }
178
+ }
179
+ return tokens;
180
+ }
181
+ /**
182
+ * Score candidate terms using BM25-style cross-document frequency.
183
+ */
184
+ function scoreWithBM25(perDocCandidates, topN) {
185
+ const N = perDocCandidates.length;
186
+ if (N === 0)
187
+ return [];
188
+ const docFreq = new Map();
189
+ const termFreqPerDoc = [];
190
+ for (const candidates of perDocCandidates) {
191
+ const tf = new Map();
192
+ for (const c of candidates) {
193
+ tf.set(c.term, (tf.get(c.term) || 0) + 1);
194
+ }
195
+ termFreqPerDoc.push(tf);
196
+ for (const term of tf.keys()) {
197
+ docFreq.set(term, (docFreq.get(term) || 0) + 1);
198
+ }
199
+ }
200
+ const avgDocLen = termFreqPerDoc.reduce((sum, tf) => sum + tf.size, 0) / N;
201
+ const k1 = 1.2;
202
+ const b = 0.75;
203
+ const results = [];
204
+ for (let i = 0; i < N; i++) {
205
+ const tf = termFreqPerDoc[i];
206
+ if (tf.size === 0) {
207
+ results.push([]);
208
+ continue;
209
+ }
210
+ const typeMap = new Map();
211
+ for (const c of perDocCandidates[i]) {
212
+ if (!typeMap.has(c.term))
213
+ typeMap.set(c.term, c.type);
214
+ }
215
+ const scored = [];
216
+ for (const [term, freq] of tf) {
217
+ const df = docFreq.get(term) || 1;
218
+ if (df > N * 0.9)
219
+ continue;
220
+ const idf = Math.log((N - df + 0.5) / (df + 0.5) + 1);
221
+ const docLen = tf.size;
222
+ const tfNorm = (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * docLen / avgDocLen));
223
+ let score = tfNorm * idf;
224
+ const type = typeMap.get(term) || 'phrase';
225
+ if (type === 'named')
226
+ score *= 2.0;
227
+ else if (type === 'proper')
228
+ score *= 1.5;
229
+ if (score > 0) {
230
+ scored.push({ term, score, type });
231
+ }
232
+ }
233
+ scored.sort((a, b) => b.score - a.score);
234
+ results.push(scored.slice(0, topN));
235
+ }
236
+ return results;
237
+ }
238
+ /**
239
+ * Extract keywords from a collection of documents.
240
+ *
241
+ * English: compromise for POS-aware candidate extraction (named entities,
242
+ * proper nouns, noun phrases), filtered for validity.
243
+ * CJK: character bigrams with stop word filtering.
244
+ * Both: BM25 cross-document scoring for relevance ranking.
245
+ */
246
+ export function extractKeywords(documents, topN = 5) {
247
+ const N = documents.length;
248
+ if (N === 0)
249
+ return [];
250
+ const perDocCandidates = documents.map(doc => {
251
+ const candidates = [];
252
+ // English candidates via compromise
253
+ candidates.push(...extractEnglishCandidates(doc));
254
+ // CJK candidates via bigrams (as 'phrase' type)
255
+ const cjkTerms = extractCjkCandidates(doc);
256
+ const seen = new Set(candidates.map(c => c.term));
257
+ for (const term of cjkTerms) {
258
+ if (!seen.has(term)) {
259
+ seen.add(term);
260
+ candidates.push({ term, type: 'phrase' });
261
+ }
262
+ }
263
+ return candidates;
264
+ });
265
+ return scoreWithBM25(perDocCandidates, topN);
266
+ }
267
+ /**
268
+ * Extract global keywords across all documents.
269
+ * Aggregates scores and boosts terms appearing in multiple documents.
270
+ */
271
+ export function extractGlobalKeywords(documents, topN = 20) {
272
+ const perDoc = extractKeywords(documents, 100);
273
+ const aggregated = new Map();
274
+ const docCount = new Map();
275
+ const typeMap = new Map();
276
+ for (const keywords of perDoc) {
277
+ for (const kw of keywords) {
278
+ aggregated.set(kw.term, (aggregated.get(kw.term) || 0) + kw.score);
279
+ docCount.set(kw.term, (docCount.get(kw.term) || 0) + 1);
280
+ if (!typeMap.has(kw.term))
281
+ typeMap.set(kw.term, kw.type);
282
+ }
283
+ }
284
+ const results = [];
285
+ for (const [term, score] of aggregated) {
286
+ const docs = docCount.get(term) || 1;
287
+ const boosted = score * (1 + Math.log(docs));
288
+ results.push({ term, score: boosted, type: typeMap.get(term) || 'phrase' });
289
+ }
290
+ results.sort((a, b) => b.score - a.score);
291
+ return results.slice(0, topN);
292
+ }
293
+ //# sourceMappingURL=keywords.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keywords.js","sourceRoot":"","sources":["../../src/deep/keywords.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * RRF (Reciprocal Rank Fusion) - Merge multiple ranked lists
3
+ */
4
+ export interface RrfInputItem {
5
+ id: string;
6
+ [key: string]: unknown;
7
+ }
8
+ export interface RrfOutputItem {
9
+ id: string;
10
+ score: number;
11
+ }
12
+ export declare function rrf(rankings: Array<Array<RrfInputItem>>, k?: number): Array<RrfOutputItem>;
13
+ //# sourceMappingURL=rrf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rrf.d.ts","sourceRoot":"","sources":["../../src/deep/rrf.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,GAAG,CACf,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EACpC,CAAC,GAAE,MAAW,GACf,KAAK,CAAC,aAAa,CAAC,CAkBtB"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * RRF (Reciprocal Rank Fusion) - Merge multiple ranked lists
3
+ */
4
+ export function rrf(rankings, k = 60) {
5
+ if (k <= 0)
6
+ throw new Error(`RRF parameter k must be positive, got: ${k}`);
7
+ if (rankings.length === 0)
8
+ return [];
9
+ const scores = new Map();
10
+ for (const ranking of rankings) {
11
+ for (let i = 0; i < ranking.length; i++) {
12
+ const doc = ranking[i];
13
+ if (!doc.id)
14
+ continue;
15
+ const score = 1 / (k + i + 1);
16
+ scores.set(doc.id, (scores.get(doc.id) || 0) + score);
17
+ }
18
+ }
19
+ return Array.from(scores.entries())
20
+ .map(([id, score]) => ({ id, score }))
21
+ .sort((a, b) => b.score - a.score);
22
+ }
23
+ //# sourceMappingURL=rrf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rrf.js","sourceRoot":"","sources":["../../src/deep/rrf.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,MAAM,UAAU,GAAG,CACf,QAAoC,EACpC,IAAY,EAAE;IAEd,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,EAAE,CAAC,CAAC;IAC3E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,SAAS;YACtB,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;QAC1D,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;SAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;SACrC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Session management for multi-round search accumulation
3
+ *
4
+ * A session directory contains:
5
+ * - results.json: Accumulated search result pool (deduped by URL)
6
+ * - graph.json: graphology knowledge graph (structural + semantic layers)
7
+ */
8
+ import { DirectedGraph } from 'graphology';
9
+ import { GraphNodeAttrs, GraphEdgeAttrs } from './graph.js';
10
+ export interface SessionResult {
11
+ url: string;
12
+ title: string;
13
+ content?: string;
14
+ engine?: string;
15
+ category?: string;
16
+ score?: number;
17
+ publishedDate?: string;
18
+ [key: string]: unknown;
19
+ }
20
+ export interface SessionResultsFile {
21
+ status: 'ok';
22
+ data: {
23
+ results: SessionResult[];
24
+ rounds: number;
25
+ };
26
+ }
27
+ /** Resolve session path. Supports:
28
+ * - "new": auto-create under default root with unique name
29
+ * - pure name (no separators): resolve to ~/.sxng/sessions/<name>
30
+ * - full path: return as-is
31
+ */
32
+ export declare function resolveSessionPath(sessionValue: string): string;
33
+ /** Ensure session directory exists and write initial meta */
34
+ export declare function initSessionDir(sessionDir: string, owner?: string, description?: string, query?: string): void;
35
+ /** Load accumulated results from session, or return empty */
36
+ export declare function loadSessionResults(sessionDir: string): SessionResult[];
37
+ /** Append new results to session results (dedup by URL) */
38
+ export declare function appendSessionResults(sessionDir: string, newResults: SessionResult[]): {
39
+ added: number;
40
+ total: number;
41
+ };
42
+ /** Load graph from session, or create empty */
43
+ export declare function loadSessionGraph(sessionDir: string): DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>;
44
+ /** Save graph to session */
45
+ export declare function saveSessionGraph(sessionDir: string, graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>): void;
46
+ /** Update session graph with new search results (structural layer) */
47
+ export declare function updateSessionGraph(sessionDir: string, query: string, results: Array<{
48
+ url: string;
49
+ title: string;
50
+ rank?: number;
51
+ }>, round?: number): {
52
+ nodesAdded: number;
53
+ edgesAdded: number;
54
+ };
55
+ /** Merge extracted content into session results (update content field by URL match) */
56
+ export declare function mergeExtractedContent(sessionDir: string, extracted: Array<{
57
+ url: string;
58
+ content: string;
59
+ title?: string;
60
+ excerpt?: string;
61
+ byline?: string;
62
+ siteName?: string;
63
+ length?: number;
64
+ error?: string;
65
+ }>): {
66
+ updated: number;
67
+ total: number;
68
+ };
69
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/deep/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAsE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIhI,MAAM,WAAW,aAAa;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,IAAI,CAAC;IACb,IAAI,EAAE;QACF,OAAO,EAAE,aAAa,EAAE,CAAC;QACzB,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;CACL;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAe/D;AAED,6DAA6D;AAC7D,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAqB7G;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,EAAE,CActE;AAED,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAiCtH;AAED,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC,CAiBlG;AAED,4BAA4B;AAC5B,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC,GAAG,IAAI,CAY/G;AAED,sEAAsE;AACtE,wBAAgB,kBAAkB,CAC9B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7D,KAAK,CAAC,EAAE,MAAM,GACf;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAY5C;AAED,uFAAuF;AACvF,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAmCvP"}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Session management for multi-round search accumulation
3
+ *
4
+ * A session directory contains:
5
+ * - results.json: Accumulated search result pool (deduped by URL)
6
+ * - graph.json: graphology knowledge graph (structural + semantic layers)
7
+ */
8
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
9
+ import { join } from 'path';
10
+ import { homedir } from 'os';
11
+ import { DirectedGraph } from 'graphology';
12
+ import { deserializeGraph, serializeGraph, graphStats, buildStructuralEdges } from './graph.js';
13
+ import { normalizeUrl } from './dedupe.js';
14
+ import { loadSessionMeta } from '../commands/session.js';
15
+ /** Resolve session path. Supports:
16
+ * - "new": auto-create under default root with unique name
17
+ * - pure name (no separators): resolve to ~/.sxng/sessions/<name>
18
+ * - full path: return as-is
19
+ */
20
+ export function resolveSessionPath(sessionValue) {
21
+ if (sessionValue === 'new') {
22
+ const root = join(homedir(), '.sxng', 'sessions');
23
+ if (!existsSync(root)) {
24
+ mkdirSync(root, { recursive: true });
25
+ }
26
+ const name = `ds_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
27
+ return join(root, name);
28
+ }
29
+ // Pure name without path separators: resolve to default sessions dir
30
+ if (!sessionValue.includes('/') && !sessionValue.includes('\\')) {
31
+ const root = join(homedir(), '.sxng', 'sessions');
32
+ return join(root, sessionValue);
33
+ }
34
+ return sessionValue;
35
+ }
36
+ /** Ensure session directory exists and write initial meta */
37
+ export function initSessionDir(sessionDir, owner, description, query) {
38
+ if (!existsSync(sessionDir)) {
39
+ mkdirSync(sessionDir, { recursive: true });
40
+ }
41
+ // Write or update meta.json
42
+ const metaFile = join(sessionDir, 'meta.json');
43
+ const existing = loadSessionMeta(sessionDir);
44
+ const now = Date.now();
45
+ const meta = {
46
+ owner: owner || existing?.owner || '',
47
+ description: description || existing?.description || '',
48
+ createdAt: existing?.createdAt || now,
49
+ updatedAt: now,
50
+ query: query || existing?.query || '',
51
+ };
52
+ try {
53
+ writeFileSync(metaFile, JSON.stringify(meta, null, 2), 'utf-8');
54
+ }
55
+ catch { /* meta write failure is non-critical */ }
56
+ }
57
+ /** Load accumulated results from session, or return empty */
58
+ export function loadSessionResults(sessionDir) {
59
+ const file = join(sessionDir, 'results.json');
60
+ if (!existsSync(file))
61
+ return [];
62
+ try {
63
+ const raw = readFileSync(file, 'utf-8');
64
+ const parsed = JSON.parse(raw);
65
+ if (parsed.status === 'ok' && parsed.data?.results) {
66
+ return parsed.data.results;
67
+ }
68
+ return [];
69
+ }
70
+ catch {
71
+ return [];
72
+ }
73
+ }
74
+ /** Append new results to session results (dedup by URL) */
75
+ export function appendSessionResults(sessionDir, newResults) {
76
+ const existing = loadSessionResults(sessionDir);
77
+ const urlMap = new Map();
78
+ // Index existing results by normalized URL
79
+ for (const r of existing) {
80
+ urlMap.set(normalizeUrl(r.url), r);
81
+ }
82
+ // Add new results (dedup: keep first occurrence)
83
+ let added = 0;
84
+ for (const r of newResults) {
85
+ const norm = normalizeUrl(r.url);
86
+ if (!urlMap.has(norm)) {
87
+ urlMap.set(norm, r);
88
+ added++;
89
+ }
90
+ }
91
+ const all = Array.from(urlMap.values());
92
+ const rounds = Math.max(1, (loadSessionRounds(sessionDir) || 0) + 1);
93
+ const file = join(sessionDir, 'results.json');
94
+ try {
95
+ writeFileSync(file, JSON.stringify({
96
+ status: 'ok',
97
+ data: { results: all, rounds },
98
+ }, null, 2), 'utf-8');
99
+ }
100
+ catch (e) {
101
+ throw new Error(`Failed to write session results to ${file}: ${e instanceof Error ? e.message : String(e)}`);
102
+ }
103
+ return { added, total: all.length };
104
+ }
105
+ /** Load graph from session, or create empty */
106
+ export function loadSessionGraph(sessionDir) {
107
+ const file = join(sessionDir, 'graph.json');
108
+ if (!existsSync(file))
109
+ return new DirectedGraph();
110
+ try {
111
+ const raw = readFileSync(file, 'utf-8');
112
+ const parsed = JSON.parse(raw);
113
+ const graphData = parsed.status === 'ok' && parsed.data?.graph
114
+ ? parsed.data.graph
115
+ : (parsed.nodes && parsed.edges ? parsed : null);
116
+ if (graphData) {
117
+ return deserializeGraph(graphData);
118
+ }
119
+ return new DirectedGraph();
120
+ }
121
+ catch {
122
+ return new DirectedGraph();
123
+ }
124
+ }
125
+ /** Save graph to session */
126
+ export function saveSessionGraph(sessionDir, graph) {
127
+ const serialized = serializeGraph(graph);
128
+ const stats = graphStats(graph);
129
+ const file = join(sessionDir, 'graph.json');
130
+ try {
131
+ writeFileSync(file, JSON.stringify({
132
+ status: 'ok',
133
+ data: { graph: serialized, stats },
134
+ }, null, 2), 'utf-8');
135
+ }
136
+ catch (e) {
137
+ throw new Error(`Failed to write session graph to ${file}: ${e instanceof Error ? e.message : String(e)}`);
138
+ }
139
+ }
140
+ /** Update session graph with new search results (structural layer) */
141
+ export function updateSessionGraph(sessionDir, query, results, round) {
142
+ const graph = loadSessionGraph(sessionDir);
143
+ const beforeNodes = graph.order;
144
+ const beforeEdges = graph.size;
145
+ buildStructuralEdges(graph, query, results, round);
146
+ saveSessionGraph(sessionDir, graph);
147
+ return {
148
+ nodesAdded: graph.order - beforeNodes,
149
+ edgesAdded: graph.size - beforeEdges,
150
+ };
151
+ }
152
+ /** Merge extracted content into session results (update content field by URL match) */
153
+ export function mergeExtractedContent(sessionDir, extracted) {
154
+ const results = loadSessionResults(sessionDir);
155
+ const urlMap = new Map();
156
+ for (const r of results) {
157
+ urlMap.set(normalizeUrl(r.url), r);
158
+ }
159
+ let updated = 0;
160
+ for (const ex of extracted) {
161
+ if (ex.error)
162
+ continue;
163
+ const norm = normalizeUrl(ex.url);
164
+ const existing = urlMap.get(norm);
165
+ if (existing) {
166
+ existing.content = ex.content;
167
+ if (ex.excerpt)
168
+ existing.excerpt = ex.excerpt;
169
+ if (ex.byline)
170
+ existing.byline = ex.byline;
171
+ if (ex.siteName)
172
+ existing.siteName = ex.siteName;
173
+ if (ex.length)
174
+ existing.contentLength = ex.length;
175
+ updated++;
176
+ }
177
+ }
178
+ const all = Array.from(urlMap.values());
179
+ const file = join(sessionDir, 'results.json');
180
+ const rounds = loadSessionRounds(sessionDir) || results.length;
181
+ try {
182
+ writeFileSync(file, JSON.stringify({
183
+ status: 'ok',
184
+ data: { results: all, rounds },
185
+ }, null, 2), 'utf-8');
186
+ }
187
+ catch (e) {
188
+ throw new Error(`Failed to write session results to ${file}: ${e instanceof Error ? e.message : String(e)}`);
189
+ }
190
+ return { updated, total: all.length };
191
+ }
192
+ /** Get current round number from results file */
193
+ function loadSessionRounds(sessionDir) {
194
+ const file = join(sessionDir, 'results.json');
195
+ if (!existsSync(file))
196
+ return 0;
197
+ try {
198
+ const raw = readFileSync(file, 'utf-8');
199
+ const parsed = JSON.parse(raw);
200
+ return parsed.data?.rounds || 0;
201
+ }
202
+ catch {
203
+ return 0;
204
+ }
205
+ }
206
+ //# sourceMappingURL=session.js.map