sxng-cli 1.2.6 → 1.2.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 +63 -46
- package/dist/claims/deterministic-checks.d.ts +1 -0
- package/dist/claims/deterministic-checks.d.ts.map +1 -1
- package/dist/claims/deterministic-checks.js +3 -4
- package/dist/claims/deterministic-checks.js.map +1 -1
- package/dist/claims/store.d.ts +6 -0
- package/dist/claims/store.d.ts.map +1 -1
- package/dist/claims/store.js +31 -6
- package/dist/claims/store.js.map +1 -1
- package/dist/claims/types.d.ts +7 -2
- package/dist/claims/types.d.ts.map +1 -1
- package/dist/commands/claim.d.ts +3 -3
- package/dist/commands/claim.d.ts.map +1 -1
- package/dist/commands/claim.js +70 -60
- package/dist/commands/claim.js.map +1 -1
- package/dist/commands/evidence.d.ts +3 -4
- package/dist/commands/evidence.d.ts.map +1 -1
- package/dist/commands/evidence.js +164 -144
- package/dist/commands/evidence.js.map +1 -1
- package/dist/commands/extract.d.ts +3 -3
- package/dist/commands/extract.d.ts.map +1 -1
- package/dist/commands/extract.js +58 -62
- package/dist/commands/extract.js.map +1 -1
- package/dist/commands/graph-add.d.ts +3 -13
- package/dist/commands/graph-add.d.ts.map +1 -1
- package/dist/commands/graph-add.js +78 -138
- package/dist/commands/graph-add.js.map +1 -1
- package/dist/commands/json-input.d.ts +18 -0
- package/dist/commands/json-input.d.ts.map +1 -0
- package/dist/commands/json-input.js +50 -0
- package/dist/commands/json-input.js.map +1 -0
- package/dist/commands/results-add.d.ts +5 -9
- package/dist/commands/results-add.d.ts.map +1 -1
- package/dist/commands/results-add.js +66 -32
- package/dist/commands/results-add.js.map +1 -1
- package/dist/commands/review.d.ts +1 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +63 -55
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/verdict.d.ts.map +1 -1
- package/dist/commands/verdict.js +13 -2
- package/dist/commands/verdict.js.map +1 -1
- package/dist/deep/dedupe.js +1 -1
- package/dist/deep/dedupe.js.map +1 -1
- package/dist/deep/extractor.d.ts +3 -1
- package/dist/deep/extractor.d.ts.map +1 -1
- package/dist/deep/extractor.js +74 -19
- package/dist/deep/extractor.js.map +1 -1
- package/dist/deep/graph-explore.d.ts +1 -1
- package/dist/deep/graph-explore.d.ts.map +1 -1
- package/dist/deep/graph-explore.js +14 -12
- package/dist/deep/graph-explore.js.map +1 -1
- package/dist/deep/graph-preprocess.d.ts +2 -1
- package/dist/deep/graph-preprocess.d.ts.map +1 -1
- package/dist/deep/graph-preprocess.js +10 -10
- package/dist/deep/graph-preprocess.js.map +1 -1
- package/dist/deep/graph-sampling.d.ts.map +1 -1
- package/dist/deep/graph-sampling.js +3 -2
- package/dist/deep/graph-sampling.js.map +1 -1
- package/dist/deep/graph.d.ts +9 -2
- package/dist/deep/graph.d.ts.map +1 -1
- package/dist/deep/graph.js +7 -6
- package/dist/deep/graph.js.map +1 -1
- package/dist/deep/local-doc/indexer.d.ts.map +1 -1
- package/dist/deep/local-doc/indexer.js +34 -1
- package/dist/deep/local-doc/indexer.js.map +1 -1
- package/dist/deep/local-doc/searcher.d.ts +4 -2
- package/dist/deep/local-doc/searcher.d.ts.map +1 -1
- package/dist/deep/local-doc/searcher.js +18 -4
- package/dist/deep/local-doc/searcher.js.map +1 -1
- package/dist/deep/path-extraction.js +2 -2
- package/dist/deep/path-extraction.js.map +1 -1
- package/dist/deep/quality-assess.d.ts +4 -4
- package/dist/deep/quality-assess.d.ts.map +1 -1
- package/dist/deep/quality-assess.js +11 -11
- package/dist/deep/quality-assess.js.map +1 -1
- package/dist/deep/quality-assess.sync-conflict-20260728-195206-JAULAPO.d.ts +46 -0
- package/dist/deep/quality-assess.sync-conflict-20260728-195206-JAULAPO.d.ts.map +1 -0
- package/dist/deep/quality-assess.sync-conflict-20260728-195206-JAULAPO.js +122 -0
- package/dist/deep/quality-assess.sync-conflict-20260728-195206-JAULAPO.js.map +1 -0
- package/dist/deep/search-strategy.d.ts.map +1 -1
- package/dist/deep/search-strategy.js +13 -6
- package/dist/deep/search-strategy.js.map +1 -1
- package/dist/deep/session.d.ts +115 -56
- package/dist/deep/session.d.ts.map +1 -1
- package/dist/deep/session.js +554 -253
- package/dist/deep/session.js.map +1 -1
- package/dist/runCli.d.ts.map +1 -1
- package/dist/runCli.js +111 -44
- package/dist/runCli.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extract subcommand - content extraction from URLs or search results
|
|
3
|
-
*/
|
|
1
|
+
/** Extract bodies. Session convenience mode never revisits extracted/skipped records. */
|
|
4
2
|
import { ContentExtractor } from '../deep/extractor.js';
|
|
5
3
|
export interface ExtractOptions {
|
|
6
4
|
urls?: string[];
|
|
7
5
|
session?: string;
|
|
6
|
+
jina?: boolean;
|
|
7
|
+
obscura?: boolean;
|
|
8
8
|
}
|
|
9
9
|
export declare function runExtract(extractor: ContentExtractor, options: ExtractOptions): Promise<number>;
|
|
10
10
|
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"AAAA,yFAAyF;AAEzF,OAAO,EAAE,gBAAgB,EAAoB,MAAM,sBAAsB,CAAC;AAK1E,MAAM,WAAW,cAAc;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAQD,wBAAsB,UAAU,CAAC,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAwEtG"}
|
package/dist/commands/extract.js
CHANGED
|
@@ -1,80 +1,76 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { createSuccessEnvelope, createErrorEnvelope } from '../protocol.js';
|
|
5
|
-
import { loadSessionResults, mergeExtractedContent, resolveSessionPath } from '../deep/session.js';
|
|
1
|
+
/** Extract bodies. Session convenience mode never revisits extracted/skipped records. */
|
|
2
|
+
import { createErrorEnvelope, createSuccessEnvelope } from '../protocol.js';
|
|
3
|
+
import { getPendingExtractionResults, loadSessionResults, recordExtractionOutcome, resolveSessionPath } from '../deep/session.js';
|
|
6
4
|
import { dedupe } from '../deep/dedupe.js';
|
|
5
|
+
function failureFrom(content) {
|
|
6
|
+
if (content.error)
|
|
7
|
+
return { code: 'tool', message: content.error, retryAfterMs: content.retryAfterMs, retryAt: content.retryAt };
|
|
8
|
+
if (!content.content?.trim())
|
|
9
|
+
return { code: 'empty', message: 'Extractor returned blank content' };
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
7
12
|
export async function runExtract(extractor, options) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
options.session = resolveSessionPath(options.session);
|
|
12
|
-
}
|
|
13
|
-
if (options.urls && options.urls.length > 0) {
|
|
14
|
-
urls = options.urls;
|
|
13
|
+
if ((options.jina || options.obscura) && !options.urls?.length) {
|
|
14
|
+
console.log(JSON.stringify(createErrorEnvelope('SPECIAL_EXTRACTOR_REQUIRES_URLS', 'Jina and Obscura require explicit session URLs so the Agent controls special extraction'), null, 2));
|
|
15
|
+
return 1;
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
const sessionDir = options.session ? resolveSessionPath(options.session) : undefined;
|
|
18
|
+
let urls = options.urls ?? [];
|
|
19
|
+
if (sessionDir && options.urls?.length) {
|
|
20
|
+
const known = new Set(loadSessionResults(sessionDir).map(result => result.url));
|
|
21
|
+
const unknown = options.urls.find(url => !known.has(url));
|
|
22
|
+
if (unknown) {
|
|
23
|
+
console.log(JSON.stringify(createErrorEnvelope('UNKNOWN_SESSION_URL', `URL is not a result in this session: ${unknown}`), null, 2));
|
|
22
24
|
return 1;
|
|
23
25
|
}
|
|
24
|
-
urls = results.map(r => r.url)
|
|
25
|
-
.filter(u => typeof u === 'string' && u.length > 0 && !u.startsWith('file://'));
|
|
26
26
|
}
|
|
27
|
-
else {
|
|
28
|
-
|
|
29
|
-
console.log(JSON.stringify(envelope, null, 2));
|
|
30
|
-
return 1;
|
|
27
|
+
else if (sessionDir) {
|
|
28
|
+
urls = getPendingExtractionResults(sessionDir).map(result => result.url).filter(url => !url.startsWith('file:'));
|
|
31
29
|
}
|
|
32
|
-
if (urls.length
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
if (!urls.length) {
|
|
31
|
+
if (sessionDir && options.urls === undefined) {
|
|
32
|
+
console.log(JSON.stringify(createErrorEnvelope('NO_URLS', 'No unextracted session URLs are eligible for extraction'), null, 2));
|
|
33
|
+
return 1;
|
|
34
|
+
}
|
|
35
|
+
console.log(JSON.stringify(createSuccessEnvelope({ extracted: [], failed: [], skipped: [], stats: { total: 0, success: 0, failed: 0 } }), null, 2));
|
|
36
|
+
return 0;
|
|
36
37
|
}
|
|
37
38
|
try {
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
39
|
+
const responses = await extractor.extractBatch(urls);
|
|
40
|
+
const valid = responses.filter(response => !failureFrom(response));
|
|
41
|
+
const extracted = dedupe(valid);
|
|
42
|
+
const retained = new Set(extracted.map(response => response.url));
|
|
43
|
+
const outcomes = responses.map(response => {
|
|
44
|
+
const failure = failureFrom(response) ?? (retained.has(response.url) ? undefined : { code: 'tool', message: 'Duplicate extracted body' });
|
|
45
|
+
return failure ? { url: response.url, failure } : { ...response, extractor: options.jina ? 'jina' : options.obscura ? 'obscura' : 'default' };
|
|
46
|
+
});
|
|
47
|
+
const session = sessionDir ? recordExtractionOutcome(sessionDir, outcomes) : undefined;
|
|
48
|
+
const failures = outcomes.filter((outcome) => 'failure' in outcome);
|
|
49
|
+
const failed = failures.map(outcome => outcome.url);
|
|
50
|
+
const rateLimited = failures.find(outcome => outcome.failure.retryAfterMs !== undefined);
|
|
51
|
+
if (rateLimited) {
|
|
52
|
+
console.log(JSON.stringify(createErrorEnvelope('JINA_RATE_LIMITED', rateLimited.failure.message, {
|
|
53
|
+
retryable: true,
|
|
54
|
+
details: {
|
|
55
|
+
failed,
|
|
56
|
+
session,
|
|
57
|
+
retryAfterMs: rateLimited.failure.retryAfterMs,
|
|
58
|
+
retryAt: rateLimited.failure.retryAt,
|
|
59
|
+
},
|
|
60
|
+
}), null, 2));
|
|
61
|
+
return 1;
|
|
58
62
|
}
|
|
59
|
-
|
|
63
|
+
console.log(JSON.stringify(createSuccessEnvelope({
|
|
60
64
|
extracted,
|
|
61
65
|
failed,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
const envelope = createSuccessEnvelope({
|
|
69
|
-
...output,
|
|
70
|
-
...(sessionMerge ? { session: sessionMerge } : {}),
|
|
71
|
-
});
|
|
72
|
-
console.log(JSON.stringify(envelope, null, 2));
|
|
66
|
+
skipped: [],
|
|
67
|
+
stats: { total: urls.length, success: extracted.length, failed: failed.length },
|
|
68
|
+
...(session ? { session } : {}),
|
|
69
|
+
}), null, 2));
|
|
73
70
|
return 0;
|
|
74
71
|
}
|
|
75
72
|
catch (error) {
|
|
76
|
-
|
|
77
|
-
console.log(JSON.stringify(envelope, null, 2));
|
|
73
|
+
console.log(JSON.stringify(createErrorEnvelope('EXTRACT_FAILED', error instanceof Error ? error.message : 'Content extraction failed', { retryable: true }), null, 2));
|
|
78
74
|
return 1;
|
|
79
75
|
}
|
|
80
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"AAAA,yFAAyF;AAGzF,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAClI,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAS3C,SAAS,WAAW,CAAC,OAAyB;IAC1C,IAAI,OAAO,CAAC,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IACjI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,kCAAkC,EAAE,CAAC;IACpG,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,SAA2B,EAAE,OAAuB;IACjF,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAC1C,iCAAiC,EACjC,yFAAyF,CAC5F,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACb,OAAO,CAAC,CAAC;IACb,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;IAC9B,IAAI,UAAU,IAAI,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChF,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,IAAI,OAAO,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,qBAAqB,EAAE,wCAAwC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACpI,OAAO,CAAC,CAAC;QACb,CAAC;IACL,CAAC;SAAM,IAAI,UAAU,EAAE,CAAC;QACpB,IAAI,GAAG,2BAA2B,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IACrH,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACf,IAAI,UAAU,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,SAAS,EAAE,yDAAyD,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAChI,OAAO,CAAC,CAAC;QACb,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,qBAAqB,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACpJ,OAAO,CAAC,CAAC;IACb,CAAC;IAED,IAAI,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnE,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YACtC,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,CAAC;YACnJ,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;QAClJ,CAAC,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,uBAAuB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACvF,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAoF,EAAE,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC;QACtJ,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC;QACzF,IAAI,WAAW,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAC1C,mBAAmB,EACnB,WAAW,CAAC,OAAO,CAAC,OAAO,EAC3B;gBACI,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE;oBACL,MAAM;oBACN,OAAO;oBACP,YAAY,EAAE,WAAW,CAAC,OAAO,CAAC,YAAY;oBAC9C,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO;iBACvC;aACJ,CACJ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACb,OAAO,CAAC,CAAC;QACb,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,qBAAqB,CAAC;YAC7C,SAAS;YACT,MAAM;YACN,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;YAC/E,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACd,OAAO,CAAC,CAAC;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,gBAAgB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,2BAA2B,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACvK,OAAO,CAAC,CAAC;IACb,CAAC;AACL,CAAC"}
|
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* graph-add subcommand - Add entities and edges to knowledge graph.
|
|
3
|
-
*
|
|
4
|
-
* This command receives entities and edges AFTER results have been approved
|
|
5
|
-
* via --quality --approve. Results must already exist as graph nodes before
|
|
6
|
-
* referencing them in edges.
|
|
7
|
-
*
|
|
8
|
-
* - Entities are added immediately (semantic layer)
|
|
9
|
-
* - Edges can reference existing result, entity, domain, or query nodes
|
|
10
|
-
* - Does NOT accept results — use `sxng results-add` for external results
|
|
11
|
-
*/
|
|
1
|
+
/** Persist Agent-authored semantic graph data against approved session results. */
|
|
12
2
|
export interface GraphAddOptions {
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
session: string;
|
|
4
|
+
dataFile?: string;
|
|
15
5
|
}
|
|
16
6
|
export declare function runGraphAdd(options: GraphAddOptions): Promise<number>;
|
|
17
7
|
//# sourceMappingURL=graph-add.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-add.d.ts","sourceRoot":"","sources":["../../src/commands/graph-add.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"graph-add.d.ts","sourceRoot":"","sources":["../../src/commands/graph-add.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAOnF,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AA4BD,wBAAsB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAkF3E"}
|
|
@@ -1,153 +1,93 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*/
|
|
12
|
-
import { readFileSync, writeFileSync, existsSync, statSync } from 'fs';
|
|
13
|
-
import { join } from 'path';
|
|
14
|
-
import { deserializeGraph, serializeGraph, graphStats, entityId } from '../deep/graph.js';
|
|
15
|
-
import { DirectedGraph } from 'graphology';
|
|
16
|
-
import { createSuccessEnvelope, createErrorEnvelope } from '../protocol.js';
|
|
17
|
-
import { getDefaultSessionRoot } from './session.js';
|
|
18
|
-
/** Resolve graph file path — if directory (session), use graph.json inside it.
|
|
19
|
-
* Pure name (no separators) is resolved to the default session root.
|
|
20
|
-
*/
|
|
21
|
-
function resolveGraphFile(path) {
|
|
22
|
-
// Pure name without path separators: resolve to default sessions dir
|
|
23
|
-
if (!path.includes('/') && !path.includes('\\')) {
|
|
24
|
-
path = join(getDefaultSessionRoot(), path);
|
|
25
|
-
}
|
|
26
|
-
try {
|
|
27
|
-
if (statSync(path).isDirectory()) {
|
|
28
|
-
return join(path, 'graph.json');
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
// Not a file/dir, return as-is
|
|
33
|
-
}
|
|
34
|
-
return path;
|
|
1
|
+
/** Persist Agent-authored semantic graph data against approved session results. */
|
|
2
|
+
import { createErrorEnvelope, createSuccessEnvelope } from '../protocol.js';
|
|
3
|
+
import { entityId } from '../deep/graph.js';
|
|
4
|
+
import { initSessionDir, mutateSessionGraph, resolveSessionPath } from '../deep/session.js';
|
|
5
|
+
import { isJsonObject, readSessionJsonInput } from './json-input.js';
|
|
6
|
+
function sourceIdsAreApproved(ids, approved) {
|
|
7
|
+
return Array.isArray(ids) && ids.length > 0 && ids.every(id => typeof id === 'string' && approved.has(id));
|
|
8
|
+
}
|
|
9
|
+
function mergeIds(left, right) {
|
|
10
|
+
return [...new Set([...(left ?? []), ...right])].sort();
|
|
35
11
|
}
|
|
36
12
|
export async function runGraphAdd(options) {
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
13
|
+
const sessionDir = resolveSessionPath(options.session);
|
|
14
|
+
initSessionDir(sessionDir);
|
|
15
|
+
const input = readSessionJsonInput(sessionDir, [{ option: '--data-file', value: options.dataFile, file: true }]);
|
|
16
|
+
if (!input.ok) {
|
|
17
|
+
console.log(JSON.stringify(createErrorEnvelope(input.code, input.message), null, 2));
|
|
41
18
|
return 1;
|
|
42
19
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
parsed = JSON.parse(options.data);
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
const envelope = createErrorEnvelope('INVALID_JSON', 'Failed to parse --data JSON', { hint: 'Ensure --data contains valid JSON with "entities" and/or "edges" arrays' });
|
|
50
|
-
console.log(JSON.stringify(envelope, null, 2));
|
|
20
|
+
if (!isJsonObject(input.value)) {
|
|
21
|
+
console.log(JSON.stringify(createErrorEnvelope('INVALID_GRAPH_DATA', 'Graph input must be an object with entities and/or edges arrays'), null, 2));
|
|
51
22
|
return 1;
|
|
52
23
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
try {
|
|
57
|
-
const raw = readFileSync(graphFile, 'utf-8');
|
|
58
|
-
const fileParsed = JSON.parse(raw);
|
|
59
|
-
const graphData = fileParsed.status === 'ok' && fileParsed.data?.graph
|
|
60
|
-
? fileParsed.data.graph
|
|
61
|
-
: (fileParsed.nodes && fileParsed.edges ? fileParsed : null);
|
|
62
|
-
graph = graphData
|
|
63
|
-
? deserializeGraph(graphData)
|
|
64
|
-
: new DirectedGraph();
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
const envelope = createErrorEnvelope('GRAPH_LOAD_FAILED', `Failed to load graph from: ${graphFile}`, { hint: 'Ensure the file contains a valid graphology graph' });
|
|
68
|
-
console.log(JSON.stringify(envelope, null, 2));
|
|
69
|
-
return 1;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
graph = new DirectedGraph();
|
|
74
|
-
}
|
|
75
|
-
const invalidProvenance = (parsed.entities || []).find(entity => {
|
|
76
|
-
if (graph.hasNode(entity.id || entityId(entity.label)))
|
|
77
|
-
return false;
|
|
78
|
-
return !Array.isArray(entity.sourceRounds)
|
|
79
|
-
|| entity.sourceRounds.length === 0
|
|
80
|
-
|| entity.sourceRounds.some(round => !Number.isSafeInteger(round) || round < 1);
|
|
81
|
-
});
|
|
82
|
-
if (invalidProvenance) {
|
|
83
|
-
const envelope = createErrorEnvelope('MISSING_ENTITY_PROVENANCE', 'Each new entity requires one or more sourceRounds from graph-preprocess resultProvenance', { hint: 'Set sourceRounds from the rounds of the results that support the entity.' });
|
|
84
|
-
console.log(JSON.stringify(envelope, null, 2));
|
|
24
|
+
const parsed = input.value;
|
|
25
|
+
if (!(parsed.entities?.length || parsed.edges?.length)) {
|
|
26
|
+
console.log(JSON.stringify(createErrorEnvelope('INVALID_GRAPH_DATA', 'Graph input must contain at least one entity or edge'), null, 2));
|
|
85
27
|
return 1;
|
|
86
28
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
29
|
+
const mutation = mutateSessionGraph(sessionDir, (graph, approved) => {
|
|
30
|
+
const approvedIds = new Set(approved.map(result => result.id));
|
|
31
|
+
const invalidEntity = (parsed.entities ?? []).find(entity => !entity.label || !sourceIdsAreApproved(entity.sourceResultIds, approvedIds));
|
|
32
|
+
const invalidEdge = (parsed.edges ?? []).find(edge => !edge.source || !edge.target || !edge.relation || !sourceIdsAreApproved(edge.sourceResultIds, approvedIds));
|
|
33
|
+
if (invalidEntity || invalidEdge)
|
|
34
|
+
return { invalidProvenance: true };
|
|
35
|
+
let entitiesAdded = 0;
|
|
36
|
+
for (const entity of parsed.entities ?? []) {
|
|
37
|
+
const id = entity.id || entityId(entity.label);
|
|
38
|
+
if (!graph.hasNode(id)) {
|
|
39
|
+
graph.addNode(id, {
|
|
40
|
+
type: 'entity', label: entity.label, entityType: entity.entityType, score: entity.score,
|
|
41
|
+
obfuscatedLabel: entity.obfuscatedLabel, frequency: entity.frequency,
|
|
42
|
+
sourceResultIds: entity.sourceResultIds,
|
|
43
|
+
});
|
|
44
|
+
entitiesAdded++;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const previous = graph.getNodeAttributes(id);
|
|
48
|
+
graph.mergeNodeAttributes(id, {
|
|
49
|
+
...previous, label: entity.label, entityType: entity.entityType ?? previous.entityType,
|
|
50
|
+
score: entity.score ?? previous.score, obfuscatedLabel: entity.obfuscatedLabel ?? previous.obfuscatedLabel,
|
|
51
|
+
frequency: entity.frequency ?? previous.frequency,
|
|
52
|
+
sourceResultIds: mergeIds(previous.sourceResultIds, entity.sourceResultIds),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
103
55
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
graph.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
56
|
+
let edgesAdded = 0;
|
|
57
|
+
const skippedEdges = [];
|
|
58
|
+
for (const edge of parsed.edges ?? []) {
|
|
59
|
+
if (!graph.hasNode(edge.source) || !graph.hasNode(edge.target)) {
|
|
60
|
+
skippedEdges.push(edge);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const sourceType = graph.getNodeAttribute(edge.source, 'type');
|
|
64
|
+
const targetType = graph.getNodeAttribute(edge.target, 'type');
|
|
65
|
+
const endpointOk = (sourceType === 'entity' && targetType === 'entity')
|
|
66
|
+
|| (sourceType === 'result' && targetType === 'entity')
|
|
67
|
+
|| (sourceType === 'entity' && targetType === 'result');
|
|
68
|
+
const resultEndpoint = sourceType === 'result' ? edge.source : targetType === 'result' ? edge.target : undefined;
|
|
69
|
+
if (!endpointOk || (resultEndpoint && !edge.sourceResultIds.includes(resultEndpoint))) {
|
|
70
|
+
skippedEdges.push(edge);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const matching = graph.findEdge(edge.source, edge.target, (_key, attrs) => attrs.relation === edge.relation);
|
|
74
|
+
if (matching) {
|
|
75
|
+
const previous = graph.getEdgeAttributes(matching);
|
|
76
|
+
graph.replaceEdgeAttributes(matching, { ...previous, sourceResultIds: mergeIds(previous.sourceResultIds, edge.sourceResultIds) });
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
graph.addEdge(edge.source, edge.target, { relation: edge.relation, weight: edge.weight ?? 1, sourceResultIds: edge.sourceResultIds });
|
|
80
|
+
edgesAdded++;
|
|
81
|
+
}
|
|
117
82
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (!graph.hasNode(edge.source) || !graph.hasNode(edge.target)) {
|
|
123
|
-
skippedEdges.push({ source: edge.source, target: edge.target, relation: edge.relation });
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
graph.mergeEdge(edge.source, edge.target, {
|
|
127
|
-
relation: edge.relation,
|
|
128
|
-
weight: edge.weight ?? 1,
|
|
129
|
-
});
|
|
130
|
-
edgesAdded++;
|
|
131
|
-
}
|
|
132
|
-
// Save graph
|
|
133
|
-
const serialized = serializeGraph(graph);
|
|
134
|
-
const stats = graphStats(graph);
|
|
135
|
-
try {
|
|
136
|
-
writeFileSync(graphFile, JSON.stringify({ status: 'ok', data: { graph: serialized, stats } }, null, 2), 'utf-8');
|
|
137
|
-
}
|
|
138
|
-
catch (e) {
|
|
139
|
-
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) } });
|
|
140
|
-
console.log(JSON.stringify(envelope, null, 2));
|
|
83
|
+
return { entitiesAdded, edgesAdded, skippedEdges };
|
|
84
|
+
}, { reconcileStructural: true });
|
|
85
|
+
if ('invalidProvenance' in mutation) {
|
|
86
|
+
console.log(JSON.stringify(createErrorEnvelope('INVALID_RESULT_PROVENANCE', 'Every semantic entity and edge requires one or more currently approved extracted sourceResultIds'), null, 2));
|
|
141
87
|
return 1;
|
|
142
88
|
}
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
edgesAdded,
|
|
146
|
-
skippedEdges: skippedEdges.length > 0 ? skippedEdges : undefined,
|
|
147
|
-
...(skippedEdges.length > 0 ? { hint: `${skippedEdges.length} edge(s) skipped — target nodes not found in graph.` } : {}),
|
|
148
|
-
stats,
|
|
149
|
-
});
|
|
150
|
-
console.log(JSON.stringify(envelope, null, 2));
|
|
89
|
+
const { entitiesAdded, edgesAdded, skippedEdges } = mutation;
|
|
90
|
+
console.log(JSON.stringify(createSuccessEnvelope({ entitiesAdded, edgesAdded, skippedEdges: skippedEdges.length ? skippedEdges : undefined }), null, 2));
|
|
151
91
|
return 0;
|
|
152
92
|
}
|
|
153
93
|
//# sourceMappingURL=graph-add.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-add.js","sourceRoot":"","sources":["../../src/commands/graph-add.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"graph-add.js","sourceRoot":"","sources":["../../src/commands/graph-add.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface JsonInputSource {
|
|
2
|
+
option: string;
|
|
3
|
+
value?: string;
|
|
4
|
+
file?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export type JsonInputResult = {
|
|
7
|
+
ok: true;
|
|
8
|
+
source: string;
|
|
9
|
+
value: unknown;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
code: 'MISSING_JSON_INPUT' | 'MULTIPLE_JSON_INPUTS' | 'JSON_FILE_OUTSIDE_SESSION' | 'JSON_FILE_READ_FAILED' | 'UNSUPPORTED_JSON_ENCODING' | 'INVALID_JSON';
|
|
13
|
+
message: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function isJsonObject(value: unknown): value is Record<string, unknown>;
|
|
16
|
+
/** Read exactly one UTF-8 JSON file, scoped to the owning session. */
|
|
17
|
+
export declare function readSessionJsonInput(sessionDir: string, sources: JsonInputSource[]): JsonInputResult;
|
|
18
|
+
//# sourceMappingURL=json-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-input.d.ts","sourceRoot":"","sources":["../../src/commands/json-input.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,eAAe,GACrB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC5C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,oBAAoB,GAAG,sBAAsB,GAAG,2BAA2B,GAAG,uBAAuB,GAAG,2BAA2B,GAAG,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjM,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE7E;AAUD,sEAAsE;AACtE,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,eAAe,CAqCpG"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { validateSessionInputFile } from '../deep/session.js';
|
|
3
|
+
export function isJsonObject(value) {
|
|
4
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function parseJson(raw, source) {
|
|
7
|
+
try {
|
|
8
|
+
return { ok: true, source, value: JSON.parse(raw) };
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return { ok: false, code: 'INVALID_JSON', message: `${source} must contain valid JSON` };
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** Read exactly one UTF-8 JSON file, scoped to the owning session. */
|
|
15
|
+
export function readSessionJsonInput(sessionDir, sources) {
|
|
16
|
+
const supplied = sources.filter(source => source.value !== undefined);
|
|
17
|
+
if (supplied.length === 0) {
|
|
18
|
+
return { ok: false, code: 'MISSING_JSON_INPUT', message: `Provide exactly one of: ${sources.map(source => source.option).join(', ')}` };
|
|
19
|
+
}
|
|
20
|
+
if (supplied.length > 1) {
|
|
21
|
+
return { ok: false, code: 'MULTIPLE_JSON_INPUTS', message: `Use only one of: ${sources.map(source => source.option).join(', ')}` };
|
|
22
|
+
}
|
|
23
|
+
const source = supplied[0];
|
|
24
|
+
if (!source.file) {
|
|
25
|
+
return { ok: false, code: 'JSON_FILE_OUTSIDE_SESSION', message: `${source.option} is not supported; write UTF-8 JSON under ${sessionDir}\\agent-inputs and pass its file option` };
|
|
26
|
+
}
|
|
27
|
+
const file = validateSessionInputFile(sessionDir, source.value);
|
|
28
|
+
if (!file) {
|
|
29
|
+
return { ok: false, code: 'JSON_FILE_OUTSIDE_SESSION', message: `${source.option} must point inside ${sessionDir}\\agent-inputs` };
|
|
30
|
+
}
|
|
31
|
+
let raw;
|
|
32
|
+
try {
|
|
33
|
+
raw = readFileSync(file);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return { ok: false, code: 'JSON_FILE_READ_FAILED', message: `Cannot read JSON file from ${source.option}: ${source.value}` };
|
|
37
|
+
}
|
|
38
|
+
if ((raw[0] === 0xff && raw[1] === 0xfe) || (raw[0] === 0xfe && raw[1] === 0xff)) {
|
|
39
|
+
return { ok: false, code: 'UNSUPPORTED_JSON_ENCODING', message: `${source.option} must reference a UTF-8 JSON file` };
|
|
40
|
+
}
|
|
41
|
+
let text;
|
|
42
|
+
try {
|
|
43
|
+
text = new TextDecoder('utf-8', { fatal: true }).decode(raw).replace(/^\uFEFF/, '');
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return { ok: false, code: 'UNSUPPORTED_JSON_ENCODING', message: `${source.option} must reference a UTF-8 JSON file` };
|
|
47
|
+
}
|
|
48
|
+
return parseJson(text, source.option);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=json-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-input.js","sourceRoot":"","sources":["../../src/commands/json-input.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* results-add subcommand - Append external search results to session as pending.
|
|
3
|
-
*
|
|
4
|
-
* Use this to inject results from other search tools (tavily, exa, etc.)
|
|
5
|
-
* into the session pipeline. Results go through the same pending → approve
|
|
6
|
-
* → graph injection flow as sxng-native results.
|
|
7
|
-
*/
|
|
1
|
+
/** Import Agent-provided discovery records or extracted bodies into one session. */
|
|
8
2
|
export interface ResultsAddOptions {
|
|
9
3
|
session: string;
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
kind: 'search' | 'extracted';
|
|
5
|
+
dataFile?: string;
|
|
6
|
+
query?: string;
|
|
7
|
+
tool?: string;
|
|
12
8
|
}
|
|
13
9
|
export declare function runResultsAdd(options: ResultsAddOptions): Promise<number>;
|
|
14
10
|
//# sourceMappingURL=results-add.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"results-add.d.ts","sourceRoot":"","sources":["../../src/commands/results-add.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"results-add.d.ts","sourceRoot":"","sources":["../../src/commands/results-add.ts"],"names":[],"mappings":"AAAA,oFAAoF;AAMpF,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAUD,wBAAsB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkE/E"}
|