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.
- package/README.md +120 -4
- package/dist/commands/build-graph.d.ts +8 -0
- package/dist/commands/build-graph.d.ts.map +1 -0
- package/dist/commands/build-graph.js +70 -0
- package/dist/commands/build-graph.js.map +1 -0
- package/dist/commands/extract.d.ts +11 -0
- package/dist/commands/extract.d.ts.map +1 -0
- package/dist/commands/extract.js +88 -0
- package/dist/commands/extract.js.map +1 -0
- package/dist/commands/graph-add.d.ts +13 -0
- package/dist/commands/graph-add.d.ts.map +1 -0
- package/dist/commands/graph-add.js +155 -0
- package/dist/commands/graph-add.js.map +1 -0
- package/dist/commands/query-graph.d.ts +11 -0
- package/dist/commands/query-graph.d.ts.map +1 -0
- package/dist/commands/query-graph.js +153 -0
- package/dist/commands/query-graph.js.map +1 -0
- package/dist/commands/raw.d.ts +14 -0
- package/dist/commands/raw.d.ts.map +1 -0
- package/dist/commands/raw.js +125 -0
- package/dist/commands/raw.js.map +1 -0
- package/dist/commands/session.d.ts +28 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +144 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/deep/dedupe.d.ts +14 -0
- package/dist/deep/dedupe.d.ts.map +1 -0
- package/dist/deep/dedupe.js +53 -0
- package/dist/deep/dedupe.js.map +1 -0
- package/dist/deep/extractor.d.ts +29 -0
- package/dist/deep/extractor.d.ts.map +1 -0
- package/dist/deep/extractor.js +125 -0
- package/dist/deep/extractor.js.map +1 -0
- package/dist/deep/graph.d.ts +55 -0
- package/dist/deep/graph.d.ts.map +1 -0
- package/dist/deep/graph.js +153 -0
- package/dist/deep/graph.js.map +1 -0
- package/dist/deep/index.d.ts +10 -0
- package/dist/deep/index.d.ts.map +1 -0
- package/dist/deep/index.js +10 -0
- package/dist/deep/index.js.map +1 -0
- package/dist/deep/keywords.d.ts +27 -0
- package/dist/deep/keywords.d.ts.map +1 -0
- package/dist/deep/keywords.js +293 -0
- package/dist/deep/keywords.js.map +1 -0
- package/dist/deep/rrf.d.ts +13 -0
- package/dist/deep/rrf.d.ts.map +1 -0
- package/dist/deep/rrf.js +23 -0
- package/dist/deep/rrf.js.map +1 -0
- package/dist/deep/session.d.ts +69 -0
- package/dist/deep/session.d.ts.map +1 -0
- package/dist/deep/session.js +206 -0
- package/dist/deep/session.js.map +1 -0
- package/dist/deep/simhash.d.ts +12 -0
- package/dist/deep/simhash.d.ts.map +1 -0
- package/dist/deep/simhash.js +56 -0
- package/dist/deep/simhash.js.map +1 -0
- package/dist/runCli.d.ts.map +1 -1
- package/dist/runCli.js +394 -100
- package/dist/runCli.js.map +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SearXNG CLI
|
|
2
2
|
|
|
3
|
-
A command-line interface for searching with SearXNG, a privacy-respecting meta search engine.
|
|
3
|
+
A command-line interface for searching with SearXNG, a privacy-respecting meta search engine. Supports deep multi-round search with knowledge graph, session accumulation, and content extraction.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -34,13 +34,15 @@ sxng "your search query"
|
|
|
34
34
|
|
|
35
35
|
Configuration can be provided via:
|
|
36
36
|
1. Environment variables (highest priority)
|
|
37
|
-
2. Config file: `./searxng.config.json`
|
|
37
|
+
2. Config file: `./searxng.config.json` or `~/.sxng/config.json`
|
|
38
38
|
3. Default values (lowest priority)
|
|
39
39
|
|
|
40
40
|
See `searxng.config.example.json` for an example configuration.
|
|
41
41
|
|
|
42
42
|
## Usage
|
|
43
43
|
|
|
44
|
+
### Basic Search
|
|
45
|
+
|
|
44
46
|
```bash
|
|
45
47
|
# Simple search
|
|
46
48
|
sxng "TypeScript tutorial"
|
|
@@ -57,8 +59,8 @@ sxng --categories it,science "machine learning"
|
|
|
57
59
|
# Recent results only
|
|
58
60
|
sxng --time week "latest news"
|
|
59
61
|
|
|
60
|
-
# Output as
|
|
61
|
-
sxng "docker tutorial"
|
|
62
|
+
# Output as JSON
|
|
63
|
+
sxng -f json "docker tutorial"
|
|
62
64
|
|
|
63
65
|
# Check server health
|
|
64
66
|
sxng --health
|
|
@@ -70,6 +72,120 @@ sxng --engines-list
|
|
|
70
72
|
sxng --categories-list
|
|
71
73
|
```
|
|
72
74
|
|
|
75
|
+
### Multi-Query Search
|
|
76
|
+
|
|
77
|
+
Run multiple queries with RRF (Reciprocal Rank Fusion) result fusion and deduplication:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
sxng --queries "tokio tutorial,rust async basics,tokio vs async-std"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Content Extraction
|
|
84
|
+
|
|
85
|
+
Extract full article content from web pages:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Extract from specific URLs
|
|
89
|
+
sxng extract --urls "https://example.com/article1,https://example.com/article2"
|
|
90
|
+
|
|
91
|
+
# Extract from search results JSON file
|
|
92
|
+
sxng extract --from-json search-results.json
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Deep Search
|
|
96
|
+
|
|
97
|
+
Deep search enables multi-round iterative research with session accumulation and knowledge graph building.
|
|
98
|
+
|
|
99
|
+
### Session Management
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Create a new session with auto-generated name
|
|
103
|
+
sxng --session new --owner "research-agent" --desc "Rust async research" "rust async ecosystem"
|
|
104
|
+
|
|
105
|
+
# List all sessions
|
|
106
|
+
sxng session-list
|
|
107
|
+
|
|
108
|
+
# Delete a specific session
|
|
109
|
+
sxng session-delete <session-name>
|
|
110
|
+
|
|
111
|
+
# Delete sessions older than N hours
|
|
112
|
+
sxng session-delete --older 24
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Deep Search Workflow
|
|
116
|
+
|
|
117
|
+
The deep search flow follows an iterative loop: search → extract → analyze → build graph → decide.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Round 1: Create session and search
|
|
121
|
+
sxng --session new --owner "agent-1" --desc "async ecosystem research" "rust async ecosystem"
|
|
122
|
+
# Note the returned session path, e.g., ~/.sxng/sessions/<session-name>
|
|
123
|
+
|
|
124
|
+
# Extract content from results
|
|
125
|
+
sxng extract --session ~/.sxng/sessions/<session-name>
|
|
126
|
+
|
|
127
|
+
# Add entities and relationships to knowledge graph
|
|
128
|
+
sxng graph-add ~/.sxng/sessions/<session-name> --data '{
|
|
129
|
+
"entities": [
|
|
130
|
+
{"label": "tokio", "entityType": "runtime", "score": 0.95},
|
|
131
|
+
{"label": "async-std", "entityType": "runtime", "score": 0.85}
|
|
132
|
+
],
|
|
133
|
+
"edges": [
|
|
134
|
+
{"source": "e:tokio", "target": "e:async_std", "relation": "alternative_to", "weight": 0.9}
|
|
135
|
+
]
|
|
136
|
+
}'
|
|
137
|
+
|
|
138
|
+
# Query the knowledge graph
|
|
139
|
+
sxng query-graph ~/.sxng/sessions/<session-name> --seeds "tokio" --depth 2
|
|
140
|
+
|
|
141
|
+
# Round 2: Search with multiple queries (results accumulate in session)
|
|
142
|
+
sxng --session ~/.sxng/sessions/<session-name> --queries "tokio vs async-std comparison,rust async benchmark 2024"
|
|
143
|
+
|
|
144
|
+
# Extract again and continue the loop...
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Session Data Structure
|
|
148
|
+
|
|
149
|
+
Each session stores three files in `~/.sxng/sessions/<session-name>/`:
|
|
150
|
+
|
|
151
|
+
- **`results.json`** — Accumulated search result pool (URL dedup, multi-round accumulation)
|
|
152
|
+
- **`graph.json`** — Knowledge graph (structural + semantic layers)
|
|
153
|
+
- **`meta.json`** — Session metadata (owner, description, timestamps)
|
|
154
|
+
|
|
155
|
+
### Knowledge Graph
|
|
156
|
+
|
|
157
|
+
The graph has two layers:
|
|
158
|
+
|
|
159
|
+
**Structural Layer** (auto-built by CLI every search):
|
|
160
|
+
|
|
161
|
+
| Node type | Prefix | Attributes |
|
|
162
|
+
|-----------|--------|------------|
|
|
163
|
+
| query | `q:` | label, query, round |
|
|
164
|
+
| result | `r:` | label, url, title, rank |
|
|
165
|
+
| domain | `d:` | label, domain |
|
|
166
|
+
|
|
167
|
+
**Semantic Layer** (added via `graph-add`):
|
|
168
|
+
|
|
169
|
+
| Node type | Prefix | Attributes |
|
|
170
|
+
|-----------|--------|------------|
|
|
171
|
+
| entity | `e:` | label, entityType, score |
|
|
172
|
+
|
|
173
|
+
## Options Reference
|
|
174
|
+
|
|
175
|
+
| Option | Short | Description | Example |
|
|
176
|
+
|--------|-------|-------------|---------|
|
|
177
|
+
| `--limit` | `-l` | Max results | `-l 20` |
|
|
178
|
+
| `--engines` | `-e` | Specific search engines | `-e google,github` |
|
|
179
|
+
| `--categories` | `-c` | Filter by category | `-c it,science` |
|
|
180
|
+
| `--page` | `-p` | Pagination | `-p 2` |
|
|
181
|
+
| `--lang` | | Result language | `--lang zh` |
|
|
182
|
+
| `--time` | | Time filter | `--time week` |
|
|
183
|
+
| `--format` | `-f` | Output format | `-f json` |
|
|
184
|
+
| `--queries` | | Multi-query with RRF fusion | `--queries "q1,q2,q3"` |
|
|
185
|
+
| `--session` | | Session directory or "new" | `--session new` |
|
|
186
|
+
| `--owner` | | Session owner identifier | `--owner "agent-1"` |
|
|
187
|
+
| `--desc` | | Session description | `--desc "research topic"` |
|
|
188
|
+
|
|
73
189
|
## Environment Variables
|
|
74
190
|
|
|
75
191
|
| Variable | Description | Default |
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build-graph subcommand - construct knowledge graph from search results
|
|
3
|
+
*/
|
|
4
|
+
export interface BuildGraphOptions {
|
|
5
|
+
inputs: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function runBuildGraph(options: BuildGraphOptions): Promise<number>;
|
|
8
|
+
//# sourceMappingURL=build-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-graph.d.ts","sourceRoot":"","sources":["../../src/commands/build-graph.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAC;CACpB;AA0BD,wBAAsB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsD/E"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build-graph subcommand - construct knowledge graph from search results
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync } from 'fs';
|
|
5
|
+
import { buildGraphFromResults, serializeGraph, graphStats } from '../deep/graph.js';
|
|
6
|
+
import { createSuccessEnvelope, createErrorEnvelope } from '../protocol.js';
|
|
7
|
+
function loadResultsFromFiles(files) {
|
|
8
|
+
const allResults = [];
|
|
9
|
+
for (const file of files) {
|
|
10
|
+
try {
|
|
11
|
+
const raw = readFileSync(file, 'utf-8');
|
|
12
|
+
const parsed = JSON.parse(raw);
|
|
13
|
+
// Handle envelope format
|
|
14
|
+
let data = parsed;
|
|
15
|
+
if (parsed.status === 'ok' && parsed.data) {
|
|
16
|
+
data = parsed.data;
|
|
17
|
+
}
|
|
18
|
+
const results = data.results || [];
|
|
19
|
+
allResults.push(...results);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Skip invalid files silently
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return allResults;
|
|
26
|
+
}
|
|
27
|
+
export async function runBuildGraph(options) {
|
|
28
|
+
if (options.inputs.length === 0) {
|
|
29
|
+
const envelope = createErrorEnvelope('MISSING_INPUT', 'No input files provided for graph building', { hint: 'Use: sxng build-graph --inputs file1.json,file2.json' });
|
|
30
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
const allResults = loadResultsFromFiles(options.inputs);
|
|
34
|
+
if (allResults.length === 0) {
|
|
35
|
+
const envelope = createErrorEnvelope('NO_RESULTS', 'No search results found in input files', { hint: 'Ensure input files contain valid search results with a results array' });
|
|
36
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
// Collect all queries from input files
|
|
40
|
+
const allQueries = [];
|
|
41
|
+
for (const file of options.inputs) {
|
|
42
|
+
try {
|
|
43
|
+
const raw = readFileSync(file, 'utf-8');
|
|
44
|
+
const parsed = JSON.parse(raw);
|
|
45
|
+
let data = parsed;
|
|
46
|
+
if (parsed.status === 'ok' && parsed.data) {
|
|
47
|
+
data = parsed.data;
|
|
48
|
+
}
|
|
49
|
+
if (data.queries) {
|
|
50
|
+
allQueries.push(...data.queries);
|
|
51
|
+
}
|
|
52
|
+
else if (data.query) {
|
|
53
|
+
allQueries.push(data.query);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Skip
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const graph = buildGraphFromResults(allResults, allQueries);
|
|
61
|
+
const serialized = serializeGraph(graph);
|
|
62
|
+
const stats = graphStats(graph);
|
|
63
|
+
const envelope = createSuccessEnvelope({
|
|
64
|
+
stats,
|
|
65
|
+
graph: serialized,
|
|
66
|
+
});
|
|
67
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=build-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-graph.js","sourceRoot":"","sources":["../../src/commands/build-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract subcommand - content extraction from URLs or search results
|
|
3
|
+
*/
|
|
4
|
+
import { ContentExtractor } from '../deep/extractor.js';
|
|
5
|
+
export interface ExtractOptions {
|
|
6
|
+
urls?: string[];
|
|
7
|
+
fromJson?: string;
|
|
8
|
+
session?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function runExtract(extractor: ContentExtractor, options: ExtractOptions): Promise<number>;
|
|
11
|
+
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAoB,MAAM,sBAAsB,CAAC;AAK1E,MAAM,WAAW,cAAc;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD,wBAAsB,UAAU,CAC5B,SAAS,EAAE,gBAAgB,EAC3B,OAAO,EAAE,cAAc,GACxB,OAAO,CAAC,MAAM,CAAC,CAyGjB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract subcommand - content extraction from URLs or search results
|
|
3
|
+
*/
|
|
4
|
+
import { createSuccessEnvelope, createErrorEnvelope } from '../protocol.js';
|
|
5
|
+
import { readFileSync } from 'fs';
|
|
6
|
+
import { loadSessionResults, mergeExtractedContent, resolveSessionPath } from '../deep/session.js';
|
|
7
|
+
export async function runExtract(extractor, options) {
|
|
8
|
+
let urls = [];
|
|
9
|
+
// Resolve session path if provided
|
|
10
|
+
if (options.session) {
|
|
11
|
+
options.session = resolveSessionPath(options.session);
|
|
12
|
+
}
|
|
13
|
+
if (options.urls && options.urls.length > 0) {
|
|
14
|
+
urls = options.urls;
|
|
15
|
+
}
|
|
16
|
+
else if (options.session) {
|
|
17
|
+
// Read URLs from session results
|
|
18
|
+
const results = loadSessionResults(options.session);
|
|
19
|
+
if (results.length === 0) {
|
|
20
|
+
const envelope = createErrorEnvelope('SESSION_EMPTY', `Session has no results: ${options.session}`, { hint: 'Run a search with --session first to accumulate results' });
|
|
21
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
22
|
+
return 1;
|
|
23
|
+
}
|
|
24
|
+
urls = results.map(r => r.url).filter(u => typeof u === 'string' && u.length > 0);
|
|
25
|
+
}
|
|
26
|
+
else if (options.fromJson) {
|
|
27
|
+
try {
|
|
28
|
+
const raw = readFileSync(options.fromJson, 'utf-8');
|
|
29
|
+
const parsed = JSON.parse(raw);
|
|
30
|
+
// Handle envelope format
|
|
31
|
+
let data = parsed;
|
|
32
|
+
if (parsed.status === 'ok' && parsed.data) {
|
|
33
|
+
data = parsed.data;
|
|
34
|
+
}
|
|
35
|
+
// Extract URLs from results array
|
|
36
|
+
const results = data.results || [];
|
|
37
|
+
urls = results
|
|
38
|
+
.map((r) => r.url)
|
|
39
|
+
.filter((u) => typeof u === 'string' && u.length > 0);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
const envelope = createErrorEnvelope('FILE_READ_FAILED', `Failed to read or parse file: ${options.fromJson}`, { hint: 'Ensure the file exists and contains valid JSON with a results array' });
|
|
43
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
44
|
+
return 1;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
const envelope = createErrorEnvelope('MISSING_INPUT', 'No URLs or input file provided for extraction', { hint: 'Use: sxng extract --urls "url1,url2" or sxng extract --from-json results.json or sxng extract --session /tmp/s' });
|
|
49
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
50
|
+
return 1;
|
|
51
|
+
}
|
|
52
|
+
if (urls.length === 0) {
|
|
53
|
+
const envelope = createErrorEnvelope('NO_URLS', 'No URLs found to extract', { hint: 'Provide URLs directly or ensure the JSON/session contains results with URLs' });
|
|
54
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const contents = await extractor.extractBatch(urls);
|
|
59
|
+
const extracted = contents.filter(c => !c.error && c.content.length > 100);
|
|
60
|
+
const failed = contents.filter(c => c.error || c.content.length <= 100).map(c => c.url);
|
|
61
|
+
// Merge extracted content into session if --session provided
|
|
62
|
+
let sessionMerge = null;
|
|
63
|
+
if (options.session) {
|
|
64
|
+
sessionMerge = mergeExtractedContent(options.session, contents);
|
|
65
|
+
}
|
|
66
|
+
const output = {
|
|
67
|
+
extracted,
|
|
68
|
+
failed,
|
|
69
|
+
stats: {
|
|
70
|
+
total: urls.length,
|
|
71
|
+
success: extracted.length,
|
|
72
|
+
failed: failed.length,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
const envelope = createSuccessEnvelope({
|
|
76
|
+
...output,
|
|
77
|
+
...(sessionMerge ? { session: sessionMerge } : {}),
|
|
78
|
+
});
|
|
79
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
const envelope = createErrorEnvelope('EXTRACT_FAILED', error instanceof Error ? error.message : 'Content extraction failed', { retryable: true });
|
|
84
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
85
|
+
return 1;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* graph-add subcommand - Add entities and edges to an entity-centric knowledge graph
|
|
3
|
+
*
|
|
4
|
+
* Agent (LLM) extracts entities from search results and sends them here.
|
|
5
|
+
* Each entity is connected to its source result via "mentions" edges.
|
|
6
|
+
* Result nodes store lightweight metadata (title, url, rank).
|
|
7
|
+
*/
|
|
8
|
+
export interface GraphAddOptions {
|
|
9
|
+
graphFile: string;
|
|
10
|
+
data: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function runGraphAdd(options: GraphAddOptions): Promise<number>;
|
|
13
|
+
//# sourceMappingURL=graph-add.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-add.d.ts","sourceRoot":"","sources":["../../src/commands/graph-add.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA2BH,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CAChB;AAsBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAoJ3E"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* graph-add subcommand - Add entities and edges to an entity-centric knowledge graph
|
|
3
|
+
*
|
|
4
|
+
* Agent (LLM) extracts entities from search results and sends them here.
|
|
5
|
+
* Each entity is connected to its source result via "mentions" edges.
|
|
6
|
+
* Result nodes store lightweight metadata (title, url, rank).
|
|
7
|
+
*/
|
|
8
|
+
import { readFileSync, writeFileSync, existsSync, statSync } from 'fs';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
import { homedir } from 'os';
|
|
11
|
+
import { deserializeGraph, serializeGraph, graphStats, entityId, resultId } from '../deep/graph.js';
|
|
12
|
+
import { DirectedGraph } from 'graphology';
|
|
13
|
+
import { createSuccessEnvelope, createErrorEnvelope } from '../protocol.js';
|
|
14
|
+
/** Resolve graph file path — if directory (session), use graph.json inside it.
|
|
15
|
+
* Pure name (no separators) is resolved to ~/.sxng/sessions/<name>
|
|
16
|
+
*/
|
|
17
|
+
function resolveGraphFile(path) {
|
|
18
|
+
// Pure name without path separators: resolve to default sessions dir
|
|
19
|
+
if (!path.includes('/') && !path.includes('\\')) {
|
|
20
|
+
path = join(homedir(), '.sxng', 'sessions', path);
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
if (statSync(path).isDirectory()) {
|
|
24
|
+
return join(path, 'graph.json');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Not a file/dir, return as-is
|
|
29
|
+
}
|
|
30
|
+
return path;
|
|
31
|
+
}
|
|
32
|
+
export async function runGraphAdd(options) {
|
|
33
|
+
const graphFile = resolveGraphFile(options.graphFile);
|
|
34
|
+
if (!graphFile) {
|
|
35
|
+
const envelope = createErrorEnvelope('MISSING_GRAPH_FILE', 'No graph file specified', { hint: 'Use: sxng graph-add graph.json --data \'...\'' });
|
|
36
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
// Parse input data
|
|
40
|
+
let parsed;
|
|
41
|
+
try {
|
|
42
|
+
parsed = JSON.parse(options.data);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
const envelope = createErrorEnvelope('INVALID_JSON', 'Failed to parse --data JSON', { hint: 'Ensure --data contains valid JSON with "entities", "results", and/or "edges" arrays' });
|
|
46
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
47
|
+
return 1;
|
|
48
|
+
}
|
|
49
|
+
// Load or create graph
|
|
50
|
+
let graph;
|
|
51
|
+
if (existsSync(graphFile)) {
|
|
52
|
+
try {
|
|
53
|
+
const raw = readFileSync(graphFile, 'utf-8');
|
|
54
|
+
const fileParsed = JSON.parse(raw);
|
|
55
|
+
const graphData = fileParsed.status === 'ok' && fileParsed.data?.graph
|
|
56
|
+
? fileParsed.data.graph
|
|
57
|
+
: (fileParsed.nodes && fileParsed.edges ? fileParsed : null);
|
|
58
|
+
graph = graphData
|
|
59
|
+
? deserializeGraph(graphData)
|
|
60
|
+
: new DirectedGraph();
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
const envelope = createErrorEnvelope('GRAPH_LOAD_FAILED', `Failed to load graph from: ${graphFile}`, { hint: 'Ensure the file contains a valid graphology graph' });
|
|
64
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
graph = new DirectedGraph();
|
|
70
|
+
}
|
|
71
|
+
let entitiesAdded = 0;
|
|
72
|
+
let resultsAdded = 0;
|
|
73
|
+
let edgesAdded = 0;
|
|
74
|
+
// Add entity nodes
|
|
75
|
+
for (const entity of parsed.entities || []) {
|
|
76
|
+
const id = entity.id || entityId(entity.label);
|
|
77
|
+
if (!graph.hasNode(id)) {
|
|
78
|
+
graph.mergeNode(id, {
|
|
79
|
+
type: 'entity',
|
|
80
|
+
label: entity.label,
|
|
81
|
+
entityType: entity.entityType,
|
|
82
|
+
score: entity.score,
|
|
83
|
+
});
|
|
84
|
+
entitiesAdded++;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// Update existing entity
|
|
88
|
+
const existing = graph.getNodeAttributes(id);
|
|
89
|
+
graph.mergeNode(id, {
|
|
90
|
+
...existing,
|
|
91
|
+
label: entity.label,
|
|
92
|
+
entityType: entity.entityType ?? existing.entityType,
|
|
93
|
+
score: entity.score ?? existing.score,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Add result metadata nodes
|
|
98
|
+
for (const result of parsed.results || []) {
|
|
99
|
+
const id = resultId(result.url);
|
|
100
|
+
if (!graph.hasNode(id)) {
|
|
101
|
+
graph.mergeNode(id, {
|
|
102
|
+
type: 'result',
|
|
103
|
+
label: result.title,
|
|
104
|
+
url: result.url,
|
|
105
|
+
title: result.title,
|
|
106
|
+
rank: result.rank,
|
|
107
|
+
});
|
|
108
|
+
resultsAdded++;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// Update rank if better
|
|
112
|
+
const existing = graph.getNodeAttributes(id);
|
|
113
|
+
if (result.rank !== undefined) {
|
|
114
|
+
graph.mergeNode(id, {
|
|
115
|
+
...existing,
|
|
116
|
+
rank: result.rank < (existing.rank ?? Infinity) ? result.rank : existing.rank,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Add edges (entity-entity and entity-result relationships)
|
|
122
|
+
const skippedEdges = [];
|
|
123
|
+
for (const edge of parsed.edges || []) {
|
|
124
|
+
if (!graph.hasNode(edge.source) || !graph.hasNode(edge.target)) {
|
|
125
|
+
skippedEdges.push({ source: edge.source, target: edge.target, relation: edge.relation });
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
graph.mergeEdge(edge.source, edge.target, {
|
|
129
|
+
relation: edge.relation,
|
|
130
|
+
weight: edge.weight ?? 1,
|
|
131
|
+
});
|
|
132
|
+
edgesAdded++;
|
|
133
|
+
}
|
|
134
|
+
// Save graph
|
|
135
|
+
const serialized = serializeGraph(graph);
|
|
136
|
+
const stats = graphStats(graph);
|
|
137
|
+
try {
|
|
138
|
+
writeFileSync(graphFile, JSON.stringify({ status: 'ok', data: { graph: serialized, stats } }, null, 2), 'utf-8');
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
const envelope = createErrorEnvelope('GRAPH_WRITE_FAILED', `Failed to write graph to: ${graphFile}`, { hint: 'Check directory permissions and disk space', details: { error: e instanceof Error ? e.message : String(e) } });
|
|
142
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
143
|
+
return 1;
|
|
144
|
+
}
|
|
145
|
+
const envelope = createSuccessEnvelope({
|
|
146
|
+
entitiesAdded,
|
|
147
|
+
resultsAdded,
|
|
148
|
+
edgesAdded,
|
|
149
|
+
skippedEdges,
|
|
150
|
+
stats,
|
|
151
|
+
});
|
|
152
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=graph-add.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-add.js","sourceRoot":"","sources":["../../src/commands/graph-add.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query-graph subcommand - BFS subgraph extraction from knowledge graph
|
|
3
|
+
*/
|
|
4
|
+
export interface QueryGraphOptions {
|
|
5
|
+
graphFile: string;
|
|
6
|
+
seeds: string[];
|
|
7
|
+
depth: number;
|
|
8
|
+
format?: 'json' | 'md';
|
|
9
|
+
}
|
|
10
|
+
export declare function runQueryGraph(options: QueryGraphOptions): Promise<number>;
|
|
11
|
+
//# sourceMappingURL=query-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-graph.d.ts","sourceRoot":"","sources":["../../src/commands/query-graph.ts"],"names":[],"mappings":"AAAA;;GAEG;AA2CH,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsI/E"}
|