sxng-cli 1.1.6 → 1.1.8

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 (29) hide show
  1. package/dist/commands/graph-add.d.ts.sync-conflict-20260629-232900-2SGIW5T.map +1 -0
  2. package/dist/commands/graph-add.js.sync-conflict-20260629-232916-2SGIW5T.map +1 -0
  3. package/dist/commands/graph-add.sync-conflict-20260629-232853-2SGIW5T.js +163 -0
  4. package/dist/deep/extractor.d.sync-conflict-20260629-232902-2SGIW5T.ts +37 -0
  5. package/dist/deep/extractor.d.ts +4 -2
  6. package/dist/deep/extractor.d.ts.map +1 -1
  7. package/dist/deep/extractor.d.ts.sync-conflict-20260629-232921-2SGIW5T.map +1 -0
  8. package/dist/deep/extractor.js +149 -20
  9. package/dist/deep/extractor.js.map +1 -1
  10. package/dist/deep/extractor.js.sync-conflict-20260629-232921-2SGIW5T.map +1 -0
  11. package/dist/deep/extractor.sync-conflict-20260629-232903-2SGIW5T.js +203 -0
  12. package/dist/deep/graph.d.sync-conflict-20260629-232917-2SGIW5T.ts +78 -0
  13. package/dist/deep/graph.d.ts.sync-conflict-20260629-232911-2SGIW5T.map +1 -0
  14. package/dist/deep/graph.js.sync-conflict-20260629-232855-2SGIW5T.map +1 -0
  15. package/dist/deep/graph.sync-conflict-20260629-232907-2SGIW5T.js +194 -0
  16. package/dist/deep/session.d.sync-conflict-20260629-232917-2SGIW5T.ts +71 -0
  17. package/dist/deep/session.d.ts.sync-conflict-20260629-232921-2SGIW5T.map +1 -0
  18. package/dist/deep/session.js.sync-conflict-20260629-232854-2SGIW5T.map +1 -0
  19. package/dist/runCli.d.ts.map +1 -1
  20. package/dist/runCli.d.ts.sync-conflict-20260629-232854-2SGIW5T.map +1 -0
  21. package/dist/runCli.js +6 -4
  22. package/dist/runCli.js.map +1 -1
  23. package/dist/runCli.js.sync-conflict-20260629-232857-2SGIW5T.map +1 -0
  24. package/dist/runCli.sync-conflict-20260629-232915-2SGIW5T.js +1109 -0
  25. package/dist/runCli.sync-conflict-20260629-233530-JAULAPO.d.ts +8 -0
  26. package/dist/runCli.sync-conflict-20260629-233530-JAULAPO.d.ts.map +1 -0
  27. package/dist/runCli.sync-conflict-20260629-233530-JAULAPO.js +1111 -0
  28. package/dist/runCli.sync-conflict-20260629-233530-JAULAPO.js.map +1 -0
  29. package/package.json +1 -1
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Content extraction: Defuddle (linkedom) → Obscura fallback
3
+ */
4
+ import { parseHTML } from 'linkedom';
5
+ import { Defuddle } from 'defuddle/node';
6
+ import { execFile } from 'child_process';
7
+ import { promisify } from 'util';
8
+ import { homedir } from 'os';
9
+ import { join } from 'path';
10
+ const execFileAsync = promisify(execFile);
11
+ const DEFAULT_TIMEOUT_MS = 10_000;
12
+ const DEFAULT_CONCURRENCY = 3;
13
+ const MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
14
+ const MIN_CONTENT_LENGTH = 100;
15
+ const OBSCURA_THRESHOLD = 50;
16
+ const OBSCURA_SEARCH_PATHS = [
17
+ 'obscura',
18
+ join(homedir(), '.local/bin/obscura'),
19
+ '/usr/local/bin/obscura',
20
+ ];
21
+ let _obscuraAvailable = null;
22
+ async function findObscura(path) {
23
+ const candidates = path ? [path] : OBSCURA_SEARCH_PATHS;
24
+ for (const candidate of candidates) {
25
+ try {
26
+ await execFileAsync(candidate, ['--version'], { timeout: 5_000 });
27
+ return candidate;
28
+ }
29
+ catch {
30
+ continue;
31
+ }
32
+ }
33
+ return null;
34
+ }
35
+ async function isObscuraAvailable(path) {
36
+ if (_obscuraAvailable !== null && !path)
37
+ return _obscuraAvailable;
38
+ const found = await findObscura(path);
39
+ const available = found !== null;
40
+ if (!path)
41
+ _obscuraAvailable = available;
42
+ return available;
43
+ }
44
+ async function defuddleExtract(html, url) {
45
+ try {
46
+ const { document } = parseHTML(html);
47
+ const result = await Defuddle(document, url, {
48
+ markdown: true,
49
+ useAsync: false,
50
+ });
51
+ const content = (result.content || '').trim();
52
+ if (!content) {
53
+ return {
54
+ title: result.title || '',
55
+ content: '',
56
+ excerpt: result.description || '',
57
+ url,
58
+ byline: result.author || undefined,
59
+ siteName: result.site || undefined,
60
+ length: 0,
61
+ extractedAt: Date.now(),
62
+ method: 'defuddle',
63
+ error: 'Defuddle could not extract content',
64
+ };
65
+ }
66
+ return {
67
+ title: result.title || '',
68
+ content,
69
+ excerpt: result.description || '',
70
+ url,
71
+ byline: result.author || undefined,
72
+ siteName: result.site || undefined,
73
+ length: result.wordCount || content.length,
74
+ extractedAt: Date.now(),
75
+ method: 'defuddle',
76
+ };
77
+ }
78
+ catch (error) {
79
+ return {
80
+ title: '',
81
+ content: '',
82
+ excerpt: '',
83
+ url,
84
+ length: 0,
85
+ extractedAt: Date.now(),
86
+ method: 'defuddle',
87
+ error: error instanceof Error ? error.message : 'Defuddle parsing failed',
88
+ };
89
+ }
90
+ }
91
+ async function obscuraExtract(url, options) {
92
+ const obscuraBin = await findObscura(options.obscuraPath);
93
+ if (!obscuraBin)
94
+ return null;
95
+ try {
96
+ const dumpFormat = options.dumpFormat ?? 'html';
97
+ const timeoutSec = Math.ceil(options.timeoutMs / 1000);
98
+ const { stdout } = await execFileAsync(obscuraBin, ['fetch', url, '--dump', dumpFormat, '--timeout', String(timeoutSec)], { timeout: options.timeoutMs + 5_000, maxBuffer: 10 * 1024 * 1024 });
99
+ if (!stdout || !stdout.trim())
100
+ return null;
101
+ if (dumpFormat === 'markdown') {
102
+ return {
103
+ title: '',
104
+ content: stdout.trim(),
105
+ excerpt: '',
106
+ url,
107
+ length: stdout.trim().length,
108
+ extractedAt: Date.now(),
109
+ method: 'obscura',
110
+ };
111
+ }
112
+ const html = stdout.trim();
113
+ const result = await defuddleExtract(html, url);
114
+ result.method = 'obscura';
115
+ return result;
116
+ }
117
+ catch {
118
+ return null;
119
+ }
120
+ }
121
+ export class ContentExtractor {
122
+ timeoutMs;
123
+ concurrency;
124
+ maxResponseBytes;
125
+ useObscura;
126
+ obscuraPath;
127
+ obscuraDumpFormat;
128
+ constructor(options) {
129
+ this.timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
130
+ this.concurrency = options?.concurrency ?? DEFAULT_CONCURRENCY;
131
+ this.maxResponseBytes = options?.maxResponseBytes ?? MAX_RESPONSE_BYTES;
132
+ this.useObscura = options?.obscura ?? false;
133
+ this.obscuraPath = options?.obscuraPath;
134
+ this.obscuraDumpFormat = options?.obscuraDumpFormat ?? 'html';
135
+ }
136
+ async extract(url) {
137
+ try {
138
+ const html = await this.fetchHtml(url);
139
+ const result = await defuddleExtract(html, url);
140
+ if (result.content.length >= MIN_CONTENT_LENGTH)
141
+ return result;
142
+ // Defuddle insufficient → Obscura fallback
143
+ if (this.useObscura && result.content.length < OBSCURA_THRESHOLD) {
144
+ const obsResult = await obscuraExtract(url, {
145
+ timeoutMs: this.timeoutMs,
146
+ obscuraPath: this.obscuraPath,
147
+ dumpFormat: this.obscuraDumpFormat,
148
+ });
149
+ if (obsResult && obsResult.content.length > result.content.length)
150
+ return obsResult;
151
+ }
152
+ if (result.content.length < MIN_CONTENT_LENGTH && !result.error) {
153
+ result.error = 'Extracted content too short';
154
+ }
155
+ return result;
156
+ }
157
+ catch (error) {
158
+ return {
159
+ title: '',
160
+ content: '',
161
+ excerpt: '',
162
+ url,
163
+ length: 0,
164
+ extractedAt: Date.now(),
165
+ error: error instanceof Error ? error.message : String(error),
166
+ };
167
+ }
168
+ }
169
+ async fetchHtml(url) {
170
+ const response = await fetch(url, {
171
+ headers: {
172
+ 'User-Agent': 'Mozilla/5.0 (compatible; SxngDeepSearch/1.0)',
173
+ 'Accept': 'text/html,application/xhtml+xml',
174
+ },
175
+ signal: AbortSignal.timeout(this.timeoutMs),
176
+ });
177
+ if (!response.ok) {
178
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
179
+ }
180
+ const contentLength = response.headers.get('content-length');
181
+ if (contentLength && parseInt(contentLength, 10) > this.maxResponseBytes) {
182
+ throw new Error(`Response too large: ${contentLength} bytes (max ${this.maxResponseBytes})`);
183
+ }
184
+ const html = await response.text();
185
+ if (html.length > this.maxResponseBytes) {
186
+ throw new Error(`Response too large: ${html.length} bytes (max ${this.maxResponseBytes})`);
187
+ }
188
+ return html;
189
+ }
190
+ async extractFromHtml(html, url) {
191
+ return defuddleExtract(html, url);
192
+ }
193
+ async extractBatch(urls) {
194
+ const results = [];
195
+ for (let i = 0; i < urls.length; i += this.concurrency) {
196
+ const batch = urls.slice(i, i + this.concurrency);
197
+ const batchResults = await Promise.all(batch.map(u => this.extract(u)));
198
+ results.push(...batchResults);
199
+ }
200
+ return results;
201
+ }
202
+ }
203
+ //# sourceMappingURL=extractor.js.map
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Entity-centric knowledge graph using graphology
3
+ *
4
+ * The graph stores entities and their relationships.
5
+ * Search results are stored as lightweight metadata nodes (title, url, rank)
6
+ * connected to entities via "mentions" edges.
7
+ *
8
+ * Entity extraction is done by the Agent (LLM), not by the CLI.
9
+ * The CLI only stores what the Agent sends via graph-add.
10
+ */
11
+ import { DirectedGraph } from 'graphology';
12
+ /** Semantic edge relation types */
13
+ export declare const EDGE_RELATIONS: {
14
+ readonly yields: "yields";
15
+ readonly belongs_to: "belongs_to";
16
+ readonly mentions: "mentions";
17
+ readonly alternative_to: "alternative_to";
18
+ readonly depends_on: "depends_on";
19
+ readonly co_occurs_with: "co_occurs_with";
20
+ readonly mentioned_in: "mentioned_in";
21
+ readonly includes: "includes";
22
+ };
23
+ export type PathType = 'composition_chain' | 'conjunction' | 'augmented_chain' | 'community_core_path' | 'dual_core_bridge';
24
+ export interface GraphNodeAttrs {
25
+ type: 'entity' | 'result' | 'query' | 'domain' | 'path';
26
+ label: string;
27
+ entityType?: string;
28
+ score?: number;
29
+ reasoningPaths?: string[];
30
+ sourceRounds?: number[];
31
+ frequency?: number;
32
+ obfuscatedLabel?: string;
33
+ url?: string;
34
+ rank?: number;
35
+ title?: string;
36
+ query?: string;
37
+ round?: number;
38
+ domain?: string;
39
+ pathType?: PathType;
40
+ hops?: number;
41
+ entities?: string[];
42
+ }
43
+ export interface GraphEdgeAttrs {
44
+ relation: string;
45
+ weight: number;
46
+ }
47
+ /** Create an empty entity-centric knowledge graph */
48
+ export declare function createGraph(): DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>;
49
+ /** Generate a node ID for an entity */
50
+ export declare function entityId(label: string): string;
51
+ /** Generate a node ID for a result */
52
+ export declare function resultId(url: string): string;
53
+ /** Generate a node ID for a query */
54
+ export declare function queryId(query: string): string;
55
+ /** Generate a node ID for a domain */
56
+ export declare function domainId(domain: string): string;
57
+ /** Generate the next path node ID for a given path type.
58
+ * Scans existing graph nodes to find the current max counter. */
59
+ export declare function nextPathId(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, pathType: PathType): string;
60
+ /** Auto-build structural edges: query→result→domain */
61
+ export declare function buildStructuralEdges(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, query: string, results: Array<{
62
+ url: string;
63
+ title: string;
64
+ rank?: number;
65
+ }>, round?: number): void;
66
+ export declare function bfsSubgraph(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, seeds: string[], depth?: number): DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>;
67
+ export declare function serializeGraph(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>): object;
68
+ export declare function deserializeGraph(data: any): DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>;
69
+ export declare function graphStats(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>): {
70
+ nodes: number;
71
+ edges: number;
72
+ entities: number;
73
+ results: number;
74
+ queries: number;
75
+ domains: number;
76
+ paths: number;
77
+ };
78
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/deep/graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/deep/graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Entity-centric knowledge graph using graphology
3
+ *
4
+ * The graph stores entities and their relationships.
5
+ * Search results are stored as lightweight metadata nodes (title, url, rank)
6
+ * connected to entities via "mentions" edges.
7
+ *
8
+ * Entity extraction is done by the Agent (LLM), not by the CLI.
9
+ * The CLI only stores what the Agent sends via graph-add.
10
+ */
11
+ import { DirectedGraph } from 'graphology';
12
+ /** Semantic edge relation types */
13
+ export const EDGE_RELATIONS = {
14
+ yields: 'yields', // query → result
15
+ belongs_to: 'belongs_to', // result → domain
16
+ mentions: 'mentions', // result → entity
17
+ alternative_to: 'alternative_to', // entity ↔ entity
18
+ depends_on: 'depends_on', // entity → entity
19
+ co_occurs_with: 'co_occurs_with', // entity ↔ entity
20
+ mentioned_in: 'mentioned_in', // entity → result
21
+ includes: 'includes', // path → entity
22
+ };
23
+ function generateId(prefix, value) {
24
+ return `${prefix}:${value.toLowerCase().replace(/[^\w]+/g, '_').slice(0, 60)}`;
25
+ }
26
+ /** Create an empty entity-centric knowledge graph */
27
+ export function createGraph() {
28
+ return new DirectedGraph();
29
+ }
30
+ /** Generate a node ID for an entity */
31
+ export function entityId(label) {
32
+ return generateId('e', label);
33
+ }
34
+ /** Generate a node ID for a result */
35
+ export function resultId(url) {
36
+ return generateId('r', url);
37
+ }
38
+ /** Generate a node ID for a query */
39
+ export function queryId(query) {
40
+ return generateId('q', query);
41
+ }
42
+ /** Generate a node ID for a domain */
43
+ export function domainId(domain) {
44
+ return generateId('d', domain);
45
+ }
46
+ /** Map from PathType to ID prefix */
47
+ const PATH_TYPE_PREFIX = {
48
+ composition_chain: 'chain',
49
+ conjunction: 'conj',
50
+ augmented_chain: 'aug',
51
+ community_core_path: 'core',
52
+ dual_core_bridge: 'bridge',
53
+ };
54
+ /** Generate the next path node ID for a given path type.
55
+ * Scans existing graph nodes to find the current max counter. */
56
+ export function nextPathId(graph, pathType) {
57
+ const prefix = PATH_TYPE_PREFIX[pathType];
58
+ let maxCounter = 0;
59
+ graph.forEachNode((node, attrs) => {
60
+ if (attrs.type === 'path' && attrs.pathType === pathType) {
61
+ // Extract counter from node ID: p:<prefix>_NNN
62
+ const match = node.match(new RegExp(`^p:${prefix}_(\\d+)$`));
63
+ if (match) {
64
+ const counter = parseInt(match[1], 10);
65
+ if (counter > maxCounter)
66
+ maxCounter = counter;
67
+ }
68
+ }
69
+ });
70
+ const next = maxCounter + 1;
71
+ return `p:${prefix}_${String(next).padStart(3, '0')}`;
72
+ }
73
+ /** Extract domain from URL */
74
+ function extractDomain(url) {
75
+ try {
76
+ return new URL(url).hostname;
77
+ }
78
+ catch {
79
+ return url;
80
+ }
81
+ }
82
+ /** Auto-build structural edges: query→result→domain */
83
+ export function buildStructuralEdges(graph, query, results, round) {
84
+ const qId = queryId(query);
85
+ // Ensure query node exists
86
+ if (!graph.hasNode(qId)) {
87
+ graph.mergeNode(qId, {
88
+ type: 'query',
89
+ label: query,
90
+ query,
91
+ round,
92
+ });
93
+ }
94
+ for (let i = 0; i < results.length; i++) {
95
+ const r = results[i];
96
+ const rId = resultId(r.url);
97
+ // Ensure result node exists
98
+ if (!graph.hasNode(rId)) {
99
+ graph.mergeNode(rId, {
100
+ type: 'result',
101
+ label: r.title,
102
+ url: r.url,
103
+ title: r.title,
104
+ rank: r.rank ?? i + 1,
105
+ });
106
+ }
107
+ // query→result edge
108
+ if (!graph.hasEdge(qId, rId)) {
109
+ graph.addEdge(qId, rId, {
110
+ relation: 'yields',
111
+ weight: 1 / (i + 1),
112
+ });
113
+ }
114
+ // domain node and result→domain edge
115
+ const domain = extractDomain(r.url);
116
+ if (domain) {
117
+ const dId = domainId(domain);
118
+ if (!graph.hasNode(dId)) {
119
+ graph.mergeNode(dId, {
120
+ type: 'domain',
121
+ label: domain,
122
+ domain,
123
+ });
124
+ }
125
+ if (!graph.hasEdge(rId, dId)) {
126
+ graph.addEdge(rId, dId, {
127
+ relation: 'belongs_to',
128
+ weight: 1,
129
+ });
130
+ }
131
+ }
132
+ }
133
+ }
134
+ export function bfsSubgraph(graph, seeds, depth = 2) {
135
+ const visited = new Set();
136
+ const queue = seeds
137
+ .filter(id => graph.hasNode(id))
138
+ .map(id => ({ id, depth: 0 }));
139
+ while (queue.length > 0) {
140
+ const { id, depth: d } = queue.shift();
141
+ if (d > depth || visited.has(id))
142
+ continue;
143
+ visited.add(id);
144
+ graph.forEachNeighbor(id, (neighbor) => {
145
+ if (!visited.has(neighbor)) {
146
+ queue.push({ id: neighbor, depth: d + 1 });
147
+ }
148
+ });
149
+ }
150
+ const subgraph = new DirectedGraph();
151
+ for (const nodeId of visited) {
152
+ const attrs = graph.getNodeAttributes(nodeId);
153
+ subgraph.mergeNode(nodeId, attrs);
154
+ }
155
+ graph.forEachEdge((edge, attrs, source, target) => {
156
+ if (visited.has(source) && visited.has(target)) {
157
+ subgraph.mergeEdge(source, target, attrs);
158
+ }
159
+ });
160
+ return subgraph;
161
+ }
162
+ export function serializeGraph(graph) {
163
+ return graph.export();
164
+ }
165
+ export function deserializeGraph(data) {
166
+ const graph = new DirectedGraph();
167
+ graph.import(data);
168
+ return graph;
169
+ }
170
+ export function graphStats(graph) {
171
+ let entities = 0, results = 0, queries = 0, domains = 0, paths = 0;
172
+ graph.forEachNode((node, attrs) => {
173
+ if (attrs.type === 'entity')
174
+ entities++;
175
+ else if (attrs.type === 'result')
176
+ results++;
177
+ else if (attrs.type === 'query')
178
+ queries++;
179
+ else if (attrs.type === 'domain')
180
+ domains++;
181
+ else if (attrs.type === 'path')
182
+ paths++;
183
+ });
184
+ return {
185
+ nodes: graph.order,
186
+ edges: graph.size,
187
+ entities,
188
+ results,
189
+ queries,
190
+ domains,
191
+ paths,
192
+ };
193
+ }
194
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1,71 @@
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-cli/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
+ /** Get current round number from results file */
70
+ export declare function loadSessionRounds(sessionDir: string): number;
71
+ //# 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;AAED,iDAAiD;AACjD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAW5D"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/deep/session.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"runCli.d.ts","sourceRoot":"","sources":["../src/runCli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,OAAO,EAAE,cAAc,EAA+C,MAAM,cAAc,CAAC;AAutB3F,wBAAgB,aAAa,IAAI,OAAO,CAwWvC;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoK5F"}
1
+ {"version":3,"file":"runCli.d.ts","sourceRoot":"","sources":["../src/runCli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,OAAO,EAAE,cAAc,EAA+C,MAAM,cAAc,CAAC;AAutB3F,wBAAgB,aAAa,IAAI,OAAO,CA0WvC;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoK5F"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runCli.d.ts","sourceRoot":"","sources":["../src/runCli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,OAAO,EAAE,cAAc,EAA+C,MAAM,cAAc,CAAC;AAutB3F,wBAAgB,aAAa,IAAI,OAAO,CAwWvC;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoK5F"}
package/dist/runCli.js CHANGED
@@ -657,7 +657,7 @@ export function createProgram() {
657
657
  .option('-f, --format <fmt>', 'Output format: md (default), json')
658
658
  .option('--queries <q1,q2,q3>', 'Multi-query with RRF fusion')
659
659
  .option('--merge <file>', 'Merge new results with previous search JSON')
660
- .option('--search-session <dir|new>', 'Session dir, or "new" to auto-create')
660
+ .option('--session <dir|new>', 'Session dir, or "new" to auto-create')
661
661
  .option('--owner <name>', 'Session owner (stored in meta.json)')
662
662
  .option('--desc <text>', 'Session description (stored in meta.json)')
663
663
  .option('--graph <file>', 'Save search result metadata to knowledge graph file')
@@ -684,11 +684,13 @@ export function createProgram() {
684
684
  .option('--obscura', 'Use Obscura as fallback for JS-heavy pages')
685
685
  .option('--obscura-path <path>', 'Path to Obscura binary')
686
686
  .option('--obscura-dump <format>', 'Obscura dump format: html, markdown', 'html')
687
+ .option('--jina', 'Use Jina Reader (r.jina.ai) as fallback')
687
688
  .action(async (opts) => {
688
689
  const extractor = new ContentExtractor({
689
690
  obscura: opts.obscura ?? false,
690
691
  obscuraPath: opts.obscuraPath,
691
692
  obscuraDumpFormat: opts.obscuraDump === 'markdown' ? 'markdown' : 'html',
693
+ jina: opts.jina ?? false,
692
694
  });
693
695
  const extractOptions = {
694
696
  urls: opts.urls?.split(',').map((u) => u.trim()).filter(Boolean),
@@ -1002,13 +1004,13 @@ export async function runCli(args, service) {
1002
1004
  return;
1003
1005
  }
1004
1006
  if (opts.quality) {
1005
- if (!opts.searchSession) {
1007
+ if (!opts.session) {
1006
1008
  const envelope = createErrorEnvelope('QUALITY_NO_SESSION', '--quality requires --session', { hint: 'Use: sxng --session <name> --quality' });
1007
1009
  console.log(JSON.stringify(envelope, null, 2));
1008
1010
  process.exit(1);
1009
1011
  return;
1010
1012
  }
1011
- const sessionDir = resolveSessionPath(opts.searchSession);
1013
+ const sessionDir = resolveSessionPath(opts.session);
1012
1014
  const sessionResults = loadSessionResults(sessionDir);
1013
1015
  const sessionGraph = loadSessionGraph(sessionDir);
1014
1016
  let thresholdOverride;
@@ -1085,7 +1087,7 @@ export async function runCli(args, service) {
1085
1087
  language: opts.lang,
1086
1088
  timeRange: opts.time,
1087
1089
  format: opts.format,
1088
- session: opts.searchSession,
1090
+ session: opts.session,
1089
1091
  owner: opts.owner,
1090
1092
  desc: opts.desc,
1091
1093
  graph: opts.graph,