sxng-cli 1.0.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/commands/graph-add.d.ts.map +1 -1
  2. package/dist/commands/graph-add.js +9 -1
  3. package/dist/commands/graph-add.js.map +1 -1
  4. package/dist/commands/graph-drill.d.ts +11 -0
  5. package/dist/commands/graph-drill.d.ts.map +1 -0
  6. package/dist/commands/graph-drill.js +26 -0
  7. package/dist/commands/graph-drill.js.map +1 -0
  8. package/dist/commands/graph-explore.d.ts +10 -0
  9. package/dist/commands/graph-explore.d.ts.map +1 -0
  10. package/dist/commands/graph-explore.js +32 -0
  11. package/dist/commands/graph-explore.js.map +1 -0
  12. package/dist/commands/graph-obfuscate.d.ts +17 -0
  13. package/dist/commands/graph-obfuscate.d.ts.map +1 -0
  14. package/dist/commands/graph-obfuscate.js +110 -0
  15. package/dist/commands/graph-obfuscate.js.map +1 -0
  16. package/dist/commands/graph-search.d.ts +11 -0
  17. package/dist/commands/graph-search.d.ts.map +1 -0
  18. package/dist/commands/graph-search.js +19 -0
  19. package/dist/commands/graph-search.js.map +1 -0
  20. package/dist/commands/graph-traverse.d.ts +10 -0
  21. package/dist/commands/graph-traverse.d.ts.map +1 -0
  22. package/dist/commands/graph-traverse.js +39 -0
  23. package/dist/commands/graph-traverse.js.map +1 -0
  24. package/dist/commands/query-graph.d.ts +2 -0
  25. package/dist/commands/query-graph.d.ts.map +1 -1
  26. package/dist/commands/query-graph.js +66 -0
  27. package/dist/commands/query-graph.js.map +1 -1
  28. package/dist/deep/co-occurrence.d.ts +50 -0
  29. package/dist/deep/co-occurrence.d.ts.map +1 -0
  30. package/dist/deep/co-occurrence.js +95 -0
  31. package/dist/deep/co-occurrence.js.map +1 -0
  32. package/dist/deep/degree-utils.d.ts +39 -0
  33. package/dist/deep/degree-utils.d.ts.map +1 -0
  34. package/dist/deep/degree-utils.js +42 -0
  35. package/dist/deep/degree-utils.js.map +1 -0
  36. package/dist/deep/extractor.d.ts +7 -2
  37. package/dist/deep/extractor.d.ts.map +1 -1
  38. package/dist/deep/extractor.js +143 -78
  39. package/dist/deep/extractor.js.map +1 -1
  40. package/dist/deep/graph-explore.d.ts +115 -0
  41. package/dist/deep/graph-explore.d.ts.map +1 -0
  42. package/dist/deep/graph-explore.js +586 -0
  43. package/dist/deep/graph-explore.js.map +1 -0
  44. package/dist/deep/graph-obfuscate.d.ts +51 -0
  45. package/dist/deep/graph-obfuscate.d.ts.map +1 -0
  46. package/dist/deep/graph-obfuscate.js +226 -0
  47. package/dist/deep/graph-obfuscate.js.map +1 -0
  48. package/dist/deep/graph-preprocess.d.ts +41 -0
  49. package/dist/deep/graph-preprocess.d.ts.map +1 -0
  50. package/dist/deep/graph-preprocess.js +32 -0
  51. package/dist/deep/graph-preprocess.js.map +1 -0
  52. package/dist/deep/graph-sampling.d.ts +51 -0
  53. package/dist/deep/graph-sampling.d.ts.map +1 -0
  54. package/dist/deep/graph-sampling.js +409 -0
  55. package/dist/deep/graph-sampling.js.map +1 -0
  56. package/dist/deep/graph.d.ts +24 -1
  57. package/dist/deep/graph.d.ts.map +1 -1
  58. package/dist/deep/graph.js +42 -1
  59. package/dist/deep/graph.js.map +1 -1
  60. package/dist/deep/iteration-data.d.ts +38 -0
  61. package/dist/deep/iteration-data.d.ts.map +1 -0
  62. package/dist/deep/iteration-data.js +48 -0
  63. package/dist/deep/iteration-data.js.map +1 -0
  64. package/dist/deep/path-extraction.d.ts +53 -0
  65. package/dist/deep/path-extraction.d.ts.map +1 -0
  66. package/dist/deep/path-extraction.js +229 -0
  67. package/dist/deep/path-extraction.js.map +1 -0
  68. package/dist/deep/quality-assess.d.ts +45 -0
  69. package/dist/deep/quality-assess.d.ts.map +1 -0
  70. package/dist/deep/quality-assess.js +125 -0
  71. package/dist/deep/quality-assess.js.map +1 -0
  72. package/dist/deep/query-redundancy.d.ts +39 -0
  73. package/dist/deep/query-redundancy.d.ts.map +1 -0
  74. package/dist/deep/query-redundancy.js +109 -0
  75. package/dist/deep/query-redundancy.js.map +1 -0
  76. package/dist/deep/query-suggest.d.ts +35 -0
  77. package/dist/deep/query-suggest.d.ts.map +1 -0
  78. package/dist/deep/query-suggest.js +98 -0
  79. package/dist/deep/query-suggest.js.map +1 -0
  80. package/dist/deep/recovery-analysis.d.ts +61 -0
  81. package/dist/deep/recovery-analysis.d.ts.map +1 -0
  82. package/dist/deep/recovery-analysis.js +188 -0
  83. package/dist/deep/recovery-analysis.js.map +1 -0
  84. package/dist/deep/search-strategy.d.ts +37 -0
  85. package/dist/deep/search-strategy.d.ts.map +1 -0
  86. package/dist/deep/search-strategy.js +99 -0
  87. package/dist/deep/search-strategy.js.map +1 -0
  88. package/dist/deep/session.d.ts +2 -0
  89. package/dist/deep/session.d.ts.map +1 -1
  90. package/dist/deep/session.js +1 -1
  91. package/dist/deep/session.js.map +1 -1
  92. package/dist/deep/simhash.d.ts +5 -0
  93. package/dist/deep/simhash.d.ts.map +1 -1
  94. package/dist/deep/simhash.js +16 -0
  95. package/dist/deep/simhash.js.map +1 -1
  96. package/dist/deep/tfidf.d.ts +38 -0
  97. package/dist/deep/tfidf.d.ts.map +1 -0
  98. package/dist/deep/tfidf.js +103 -0
  99. package/dist/deep/tfidf.js.map +1 -0
  100. package/dist/runCli.d.ts +3 -1
  101. package/dist/runCli.d.ts.map +1 -1
  102. package/dist/runCli.js +762 -307
  103. package/dist/runCli.js.map +1 -1
  104. package/package.json +17 -4
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Co-occurrence matrix and cross-results frequency statistics.
3
+ *
4
+ * Co-occurrence: word pairs that appear within the same result.
5
+ * Frequency: how many results contain each term.
6
+ * Both derived from TF-IDF tokenization output.
7
+ */
8
+ import { tokenize } from './tfidf.js';
9
+ import { getEntityDegree } from './degree-utils.js';
10
+ const MAX_TERMS_FOR_CO_OCCURRENCE = 50;
11
+ const DEFAULT_THRESHOLD = 2;
12
+ /** Build co-occurrence matrix from results.
13
+ * Only results with `content` are processed.
14
+ * If unique terms > maxTerms, take the top by frequency and set truncated=true.
15
+ */
16
+ export function buildCoOccurrence(results, opts) {
17
+ const threshold = opts?.threshold ?? DEFAULT_THRESHOLD;
18
+ const maxTerms = opts?.maxTerms ?? MAX_TERMS_FOR_CO_OCCURRENCE;
19
+ const withContent = results.filter(r => r.content);
20
+ // Per-result term sets
21
+ const perResultTermSets = [];
22
+ const globalFreq = new Map(); // term → # results containing it
23
+ for (const result of withContent) {
24
+ const text = `${result.title || ''} ${result.content || ''}`;
25
+ const tokens = tokenize(text);
26
+ const termSet = new Set(tokens);
27
+ perResultTermSets.push(termSet);
28
+ for (const term of termSet) {
29
+ globalFreq.set(term, (globalFreq.get(term) || 0) + 1);
30
+ }
31
+ }
32
+ // Truncate to top maxTerms by frequency
33
+ const sortedTerms = Array.from(globalFreq.entries())
34
+ .sort((a, b) => b[1] - a[1])
35
+ .slice(0, maxTerms)
36
+ .map(([term]) => term);
37
+ const truncated = globalFreq.size > maxTerms;
38
+ const termIndex = new Set(sortedTerms);
39
+ // Count co-occurrences
40
+ const pairCounts = new Map();
41
+ for (const termSet of perResultTermSets) {
42
+ const filtered = sortedTerms.filter(t => termSet.has(t));
43
+ for (let i = 0; i < filtered.length; i++) {
44
+ for (let j = i + 1; j < filtered.length; j++) {
45
+ const key = filtered[i] < filtered[j]
46
+ ? `${filtered[i]}|${filtered[j]}`
47
+ : `${filtered[j]}|${filtered[i]}`;
48
+ pairCounts.set(key, (pairCounts.get(key) || 0) + 1);
49
+ }
50
+ }
51
+ }
52
+ const pairs = [];
53
+ for (const [key, count] of pairCounts) {
54
+ if (count >= threshold) {
55
+ const [term1, term2] = key.split('|');
56
+ pairs.push({ term1, term2, count });
57
+ }
58
+ }
59
+ pairs.sort((a, b) => b.count - a.count);
60
+ return { pairs, truncated, maxTerms };
61
+ }
62
+ /** Count how many results contain each term. */
63
+ export function computeCrossResultFrequency(results, opts) {
64
+ const top = opts?.top ?? 50;
65
+ const withContent = results.filter(r => r.content);
66
+ const freq = new Map();
67
+ for (const result of withContent) {
68
+ const text = `${result.title || ''} ${result.content || ''}`;
69
+ const tokens = tokenize(text);
70
+ const seen = new Set(tokens);
71
+ for (const term of seen) {
72
+ freq.set(term, (freq.get(term) || 0) + 1);
73
+ }
74
+ }
75
+ return Array.from(freq.entries())
76
+ .map(([term, count]) => ({ term, count }))
77
+ .sort((a, b) => b.count - a.count)
78
+ .slice(0, top);
79
+ }
80
+ /** Get existing entity nodes from the graph with their on-demand degree. */
81
+ export function getExistingEntityContext(graph) {
82
+ const entities = [];
83
+ graph.forEachNode((node, attrs) => {
84
+ if (attrs.type === 'entity') {
85
+ entities.push({
86
+ id: node,
87
+ label: attrs.label,
88
+ degree: getEntityDegree(graph, node),
89
+ entityType: attrs.entityType,
90
+ });
91
+ }
92
+ });
93
+ return entities.sort((a, b) => b.degree - a.degree);
94
+ }
95
+ //# sourceMappingURL=co-occurrence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"co-occurrence.js","sourceRoot":"","sources":["../../src/deep/co-occurrence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * On-demand degree computation for entity nodes.
3
+ *
4
+ * Degree is NOT stored in node attributes — it's computed on-the-fly
5
+ * from the graph topology using graphology's O(1) inDegree/outDegree.
6
+ * This ensures degree is always consistent with the current graph state.
7
+ */
8
+ import { DirectedGraph } from 'graphology';
9
+ import { GraphNodeAttrs, GraphEdgeAttrs } from './graph.js';
10
+ /** Get the total degree (in + out) for a single node. O(1) via graphology. */
11
+ export declare function getEntityDegree(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, nodeId: string): number;
12
+ /** Get degree for all entity nodes (type === 'entity') in the graph. */
13
+ export declare function getEntitiesWithDegrees(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>): Array<{
14
+ id: string;
15
+ degree: number;
16
+ label: string;
17
+ }>;
18
+ /** Compute adaptive degree range for filtering entity nodes.
19
+ * - d_max = min(50, floor(graph.order / 5))
20
+ * - d_min = 1 by default
21
+ * Small graphs auto-shrink: 30 nodes → d_max=6, 100 nodes → d_max=20
22
+ */
23
+ export declare function adaptiveDegreeRange(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, opts?: {
24
+ minDegree?: number;
25
+ maxDegreeCap?: number;
26
+ }): {
27
+ min: number;
28
+ max: number;
29
+ };
30
+ /** Filter entity nodes within the adaptive degree range. */
31
+ export declare function filterEntitiesByDegree(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, opts?: {
32
+ minDegree?: number;
33
+ maxDegreeCap?: number;
34
+ }): Array<{
35
+ id: string;
36
+ degree: number;
37
+ label: string;
38
+ }>;
39
+ //# sourceMappingURL=degree-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"degree-utils.d.ts","sourceRoot":"","sources":["../../src/deep/degree-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE5G;AAED,wEAAwE;AACxE,wBAAgB,sBAAsB,CAClC,KAAK,EAAE,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC,GACrD,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAYtD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAC/B,KAAK,EAAE,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC,EACpD,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAK9B;AAED,4DAA4D;AAC5D,wBAAgB,sBAAsB,CAClC,KAAK,EAAE,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC,EACpD,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GACrD,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAGtD"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * On-demand degree computation for entity nodes.
3
+ *
4
+ * Degree is NOT stored in node attributes — it's computed on-the-fly
5
+ * from the graph topology using graphology's O(1) inDegree/outDegree.
6
+ * This ensures degree is always consistent with the current graph state.
7
+ */
8
+ /** Get the total degree (in + out) for a single node. O(1) via graphology. */
9
+ export function getEntityDegree(graph, nodeId) {
10
+ return graph.inDegree(nodeId) + graph.outDegree(nodeId);
11
+ }
12
+ /** Get degree for all entity nodes (type === 'entity') in the graph. */
13
+ export function getEntitiesWithDegrees(graph) {
14
+ const result = [];
15
+ graph.forEachNode((node, attrs) => {
16
+ if (attrs.type === 'entity') {
17
+ result.push({
18
+ id: node,
19
+ degree: getEntityDegree(graph, node),
20
+ label: attrs.label,
21
+ });
22
+ }
23
+ });
24
+ return result.sort((a, b) => b.degree - a.degree);
25
+ }
26
+ /** Compute adaptive degree range for filtering entity nodes.
27
+ * - d_max = min(50, floor(graph.order / 5))
28
+ * - d_min = 1 by default
29
+ * Small graphs auto-shrink: 30 nodes → d_max=6, 100 nodes → d_max=20
30
+ */
31
+ export function adaptiveDegreeRange(graph, opts) {
32
+ const dMin = opts?.minDegree ?? 1;
33
+ const cap = opts?.maxDegreeCap ?? 50;
34
+ const dMax = Math.min(cap, Math.floor(graph.order / 5));
35
+ return { min: dMin, max: Math.max(dMax, dMin) };
36
+ }
37
+ /** Filter entity nodes within the adaptive degree range. */
38
+ export function filterEntitiesByDegree(graph, opts) {
39
+ const range = adaptiveDegreeRange(graph, opts);
40
+ return getEntitiesWithDegrees(graph).filter(e => e.degree >= range.min && e.degree <= range.max);
41
+ }
42
+ //# sourceMappingURL=degree-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"degree-utils.js","sourceRoot":"","sources":["../../src/deep/degree-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,8EAA8E;AAC9E,MAAM,UAAU,eAAe,CAAC,KAAoD,EAAE,MAAc;IAChG,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAC5D,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,sBAAsB,CAClC,KAAoD;IAEpD,MAAM,MAAM,GAAyD,EAAE,CAAC;IACxE,KAAK,CAAC,WAAW,CAAC,CAAC,IAAY,EAAE,KAAqB,EAAE,EAAE;QACtD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC;gBACR,EAAE,EAAE,IAAI;gBACR,MAAM,EAAE,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC;gBACpC,KAAK,EAAE,KAAK,CAAC,KAAK;aACrB,CAAC,CAAC;QACP,CAAC;IACL,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAC/B,KAAoD,EACpD,IAAoD;IAEpD,MAAM,IAAI,GAAG,IAAI,EAAE,SAAS,IAAI,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,EAAE,YAAY,IAAI,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;AACpD,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,sBAAsB,CAClC,KAAoD,EACpD,IAAoD;IAEpD,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC/C,OAAO,sBAAsB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;AACrG,CAAC"}
@@ -1,10 +1,11 @@
1
1
  /**
2
- * Content extraction using linkedom + @mozilla/readability
2
+ * Content extraction: Defuddle (linkedom) Playwright fallback
3
3
  */
4
4
  export interface ExtractorOptions {
5
5
  timeoutMs?: number;
6
6
  concurrency?: number;
7
7
  maxResponseBytes?: number;
8
+ playwright?: boolean;
8
9
  }
9
10
  export interface ExtractedContent {
10
11
  title: string;
@@ -16,14 +17,18 @@ export interface ExtractedContent {
16
17
  length: number;
17
18
  extractedAt: number;
18
19
  error?: string;
20
+ method?: 'defuddle' | 'playwright';
19
21
  }
20
22
  export declare class ContentExtractor {
21
23
  private timeoutMs;
22
24
  private concurrency;
23
25
  private maxResponseBytes;
26
+ private usePlaywright;
24
27
  constructor(options?: ExtractorOptions);
25
28
  extract(url: string): Promise<ExtractedContent>;
26
- extractFromHtml(html: string, url: string): ExtractedContent;
29
+ private fetchHtml;
30
+ extractFromHtml(html: string, url: string): Promise<ExtractedContent>;
31
+ private playwrightExtract;
27
32
  extractBatch(urls: string[]): Promise<ExtractedContent[]>;
28
33
  }
29
34
  //# sourceMappingURL=extractor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/deep/extractor.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,MAAM,WAAW,gBAAgB;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,gBAAgB;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAS;gBAErB,OAAO,CAAC,EAAE,gBAAgB;IAMhC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA8DrD,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB;IAyCtD,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CASlE"}
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/deep/extractor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH,MAAM,WAAW,gBAAgB;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;CACtC;AA8ED,qBAAa,gBAAgB;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,aAAa,CAAU;gBAEnB,OAAO,CAAC,EAAE,gBAAgB;IAOhC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;YA8BvC,SAAS;IA2BjB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;YAI7D,iBAAiB;IA2BzB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAUlE"}
@@ -1,65 +1,116 @@
1
1
  /**
2
- * Content extraction using linkedom + @mozilla/readability
2
+ * Content extraction: Defuddle (linkedom) Playwright fallback
3
3
  */
4
4
  import { parseHTML } from 'linkedom';
5
- import { Readability } from '@mozilla/readability';
5
+ import { Defuddle } from 'defuddle/node';
6
6
  const DEFAULT_TIMEOUT_MS = 10_000;
7
7
  const DEFAULT_CONCURRENCY = 3;
8
- const MAX_RESPONSE_BYTES = 5 * 1024 * 1024; // 5MB
8
+ const MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
9
+ const MIN_CONTENT_LENGTH = 100;
10
+ const PW_THRESHOLD = 50;
11
+ let _browser = null;
12
+ let _pwModule = null;
13
+ async function loadPlaywright() {
14
+ if (_pwModule)
15
+ return _pwModule;
16
+ try {
17
+ // @ts-ignore — playwright is an optional peer dependency
18
+ _pwModule = await import('playwright');
19
+ return _pwModule;
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
25
+ async function getBrowser() {
26
+ if (_browser)
27
+ return _browser;
28
+ const pw = await loadPlaywright();
29
+ if (!pw)
30
+ return null;
31
+ _browser = await pw.chromium.launch({ headless: true });
32
+ return _browser;
33
+ }
34
+ async function closeBrowser() {
35
+ if (_browser) {
36
+ await _browser.close();
37
+ _browser = null;
38
+ }
39
+ }
40
+ async function defuddleExtract(html, url) {
41
+ try {
42
+ const { document } = parseHTML(html);
43
+ const result = await Defuddle(document, url, {
44
+ markdown: true,
45
+ useAsync: false,
46
+ });
47
+ const content = (result.content || '').trim();
48
+ if (!content) {
49
+ return {
50
+ title: result.title || '',
51
+ content: '',
52
+ excerpt: result.description || '',
53
+ url,
54
+ byline: result.author || undefined,
55
+ siteName: result.site || undefined,
56
+ length: 0,
57
+ extractedAt: Date.now(),
58
+ method: 'defuddle',
59
+ error: 'Defuddle could not extract content',
60
+ };
61
+ }
62
+ return {
63
+ title: result.title || '',
64
+ content,
65
+ excerpt: result.description || '',
66
+ url,
67
+ byline: result.author || undefined,
68
+ siteName: result.site || undefined,
69
+ length: result.wordCount || content.length,
70
+ extractedAt: Date.now(),
71
+ method: 'defuddle',
72
+ };
73
+ }
74
+ catch (error) {
75
+ return {
76
+ title: '',
77
+ content: '',
78
+ excerpt: '',
79
+ url,
80
+ length: 0,
81
+ extractedAt: Date.now(),
82
+ method: 'defuddle',
83
+ error: error instanceof Error ? error.message : 'Defuddle parsing failed',
84
+ };
85
+ }
86
+ }
9
87
  export class ContentExtractor {
10
88
  timeoutMs;
11
89
  concurrency;
12
90
  maxResponseBytes;
91
+ usePlaywright;
13
92
  constructor(options) {
14
93
  this.timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
15
94
  this.concurrency = options?.concurrency ?? DEFAULT_CONCURRENCY;
16
95
  this.maxResponseBytes = options?.maxResponseBytes ?? MAX_RESPONSE_BYTES;
96
+ this.usePlaywright = options?.playwright ?? false;
17
97
  }
18
98
  async extract(url) {
19
99
  try {
20
- const response = await fetch(url, {
21
- headers: {
22
- 'User-Agent': 'Mozilla/5.0 (compatible; SxngDeepSearch/1.0)',
23
- 'Accept': 'text/html,application/xhtml+xml',
24
- },
25
- signal: AbortSignal.timeout(this.timeoutMs),
26
- });
27
- if (!response.ok) {
28
- return {
29
- title: '',
30
- content: '',
31
- excerpt: '',
32
- url,
33
- length: 0,
34
- extractedAt: Date.now(),
35
- error: `HTTP ${response.status}: ${response.statusText}`,
36
- };
100
+ const html = await this.fetchHtml(url);
101
+ const result = await defuddleExtract(html, url);
102
+ if (result.content.length >= MIN_CONTENT_LENGTH)
103
+ return result;
104
+ // Defuddle insufficient → Playwright fallback
105
+ if (this.usePlaywright && result.content.length < PW_THRESHOLD) {
106
+ const pwResult = await this.playwrightExtract(url);
107
+ if (pwResult && pwResult.content.length > result.content.length)
108
+ return pwResult;
37
109
  }
38
- const contentLength = response.headers.get('content-length');
39
- if (contentLength && parseInt(contentLength, 10) > this.maxResponseBytes) {
40
- return {
41
- title: '',
42
- content: '',
43
- excerpt: '',
44
- url,
45
- length: 0,
46
- extractedAt: Date.now(),
47
- error: `Response too large: ${contentLength} bytes (max ${this.maxResponseBytes})`,
48
- };
110
+ if (result.content.length < MIN_CONTENT_LENGTH && !result.error) {
111
+ result.error = 'Extracted content too short';
49
112
  }
50
- const html = await response.text();
51
- if (html.length > this.maxResponseBytes) {
52
- return {
53
- title: '',
54
- content: '',
55
- excerpt: '',
56
- url,
57
- length: 0,
58
- extractedAt: Date.now(),
59
- error: `Response too large: ${html.length} bytes (max ${this.maxResponseBytes})`,
60
- };
61
- }
62
- return this.extractFromHtml(html, url);
113
+ return result;
63
114
  }
64
115
  catch (error) {
65
116
  return {
@@ -73,43 +124,56 @@ export class ContentExtractor {
73
124
  };
74
125
  }
75
126
  }
76
- extractFromHtml(html, url) {
127
+ async fetchHtml(url) {
128
+ const response = await fetch(url, {
129
+ headers: {
130
+ 'User-Agent': 'Mozilla/5.0 (compatible; SxngDeepSearch/1.0)',
131
+ 'Accept': 'text/html,application/xhtml+xml',
132
+ },
133
+ signal: AbortSignal.timeout(this.timeoutMs),
134
+ });
135
+ if (!response.ok) {
136
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
137
+ }
138
+ const contentLength = response.headers.get('content-length');
139
+ if (contentLength && parseInt(contentLength, 10) > this.maxResponseBytes) {
140
+ throw new Error(`Response too large: ${contentLength} bytes (max ${this.maxResponseBytes})`);
141
+ }
142
+ const html = await response.text();
143
+ if (html.length > this.maxResponseBytes) {
144
+ throw new Error(`Response too large: ${html.length} bytes (max ${this.maxResponseBytes})`);
145
+ }
146
+ return html;
147
+ }
148
+ // Sync wrapper for backward compat — uses Defuddle with useAsync:false
149
+ // Note: still async internally because defuddle/node export is async
150
+ async extractFromHtml(html, url) {
151
+ return defuddleExtract(html, url);
152
+ }
153
+ async playwrightExtract(url) {
154
+ const browser = await getBrowser();
155
+ if (!browser)
156
+ return null;
77
157
  try {
78
- const { document } = parseHTML(html);
79
- const reader = new Readability(document, { charThreshold: 100 });
80
- const article = reader.parse();
81
- if (!article || !article.textContent) {
82
- return {
83
- title: '',
84
- content: '',
85
- excerpt: '',
86
- url,
87
- length: 0,
88
- extractedAt: Date.now(),
89
- error: 'Readability could not extract content',
90
- };
158
+ const page = await browser.newPage();
159
+ await page.setExtraHTTPHeaders({ 'User-Agent': 'Mozilla/5.0 (compatible; SxngDeepSearch/1.0)' });
160
+ const response = await page.goto(url, {
161
+ waitUntil: 'networkidle',
162
+ timeout: this.timeoutMs,
163
+ });
164
+ if (!response || !response.ok()) {
165
+ await page.close();
166
+ return null;
91
167
  }
92
- return {
93
- title: article.title || '',
94
- content: article.textContent.replace(/\n{3,}/g, '\n\n').trim(),
95
- excerpt: article.excerpt || '',
96
- url,
97
- byline: article.byline || undefined,
98
- siteName: article.siteName || undefined,
99
- length: article.length || article.textContent.length,
100
- extractedAt: Date.now(),
101
- };
168
+ await page.waitForTimeout(1000);
169
+ const html = await page.content();
170
+ await page.close();
171
+ const result = await defuddleExtract(html, url);
172
+ result.method = 'playwright';
173
+ return result;
102
174
  }
103
- catch (error) {
104
- return {
105
- title: '',
106
- content: '',
107
- excerpt: '',
108
- url,
109
- length: 0,
110
- extractedAt: Date.now(),
111
- error: error instanceof Error ? error.message : 'HTML parsing failed',
112
- };
175
+ catch {
176
+ return null;
113
177
  }
114
178
  }
115
179
  async extractBatch(urls) {
@@ -119,6 +183,7 @@ export class ContentExtractor {
119
183
  const batchResults = await Promise.all(batch.map(u => this.extract(u)));
120
184
  results.push(...batchResults);
121
185
  }
186
+ await closeBrowser();
122
187
  return results;
123
188
  }
124
189
  }
@@ -1 +1 @@
1
- {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/deep/extractor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/deep/extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Agent-style knowledge graph exploration.
3
+ *
4
+ * Two-step interaction model:
5
+ * graph-explore: inspect all relations around a seed entity (summary view)
6
+ * graph-drill: follow specific relations from an entity (targeted retrieval)
7
+ *
8
+ * Also includes dead-end detection and alternative path suggestion.
9
+ */
10
+ import { DirectedGraph } from 'graphology';
11
+ import { GraphNodeAttrs, GraphEdgeAttrs } from './graph.js';
12
+ export interface RelationTarget {
13
+ nodeId: string;
14
+ label: string;
15
+ type: string;
16
+ weight: number;
17
+ }
18
+ export interface RelationGroup {
19
+ relation: string;
20
+ targets: RelationTarget[];
21
+ }
22
+ export interface ExploreResult {
23
+ entity: {
24
+ id: string;
25
+ label: string;
26
+ type: string;
27
+ score?: number;
28
+ degree: number;
29
+ };
30
+ outgoingRelations: RelationGroup[];
31
+ incomingRelations: RelationGroup[];
32
+ suggestedNextSteps: string[];
33
+ }
34
+ export interface DrillResult {
35
+ seed: string;
36
+ relations: string[];
37
+ triples: Array<{
38
+ source: string;
39
+ sourceLabel: string;
40
+ relation: string;
41
+ target: string;
42
+ targetLabel: string;
43
+ weight: number;
44
+ }>;
45
+ nextSteps: string[];
46
+ }
47
+ export interface DeadEndInfo {
48
+ entityId: string;
49
+ reason: 'low_degree' | 'only_mentioned_in' | 'already_visited';
50
+ alternativePaths: Array<{
51
+ fromEntity: string;
52
+ fromLabel: string;
53
+ relation: string;
54
+ toEntity: string;
55
+ toLabel: string;
56
+ score: number;
57
+ }>;
58
+ }
59
+ export interface EntitySuggestion {
60
+ id: string;
61
+ label: string;
62
+ distance: number;
63
+ }
64
+ /** Explore all relations around a seed entity. */
65
+ export declare function exploreSeedEntity(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, seedLabel: string): ExploreResult | {
66
+ error: string;
67
+ suggestions: EntitySuggestion[];
68
+ };
69
+ /** Follow specific relations from a seed entity. */
70
+ export declare function drillByRelations(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, seedLabel: string, relations: string[]): DrillResult | {
71
+ error: string;
72
+ suggestions: EntitySuggestion[];
73
+ };
74
+ /** Detect if an entity is a dead end and suggest alternatives. */
75
+ export declare function detectDeadEnd(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, entityId: string, visited?: Set<string>): DeadEndInfo | null;
76
+ export interface TraverseResult {
77
+ pathId: string;
78
+ pathType: string;
79
+ label: string;
80
+ hops: Array<{
81
+ index: number;
82
+ entityId: string;
83
+ entityLabel: string;
84
+ entityType: string;
85
+ relation?: string;
86
+ }>;
87
+ sources: {
88
+ resultCount: number;
89
+ domains: string[];
90
+ rounds: number[];
91
+ };
92
+ }
93
+ /** Traverse a path: node and return the ordered reasoning chain. */
94
+ export declare function traversePath(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, pathId: string): TraverseResult | {
95
+ error: string;
96
+ availablePaths: string[];
97
+ };
98
+ export interface SearchResult {
99
+ id: string;
100
+ label: string;
101
+ score: number;
102
+ }
103
+ /** Keyword search across entity labels. Returns entity IDs ranked by score × degree. */
104
+ export declare function searchEntities(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, keyword: string, limit?: number): SearchResult[];
105
+ /** Format explore result as Markdown. */
106
+ export declare function formatExploreAsMarkdown(result: ExploreResult): string;
107
+ /** Format drill result as Markdown. */
108
+ export declare function formatDrillAsMarkdown(result: DrillResult): string;
109
+ /** Format dead-end info as Markdown. */
110
+ export declare function formatDeadEndAsMarkdown(info: DeadEndInfo): string;
111
+ /** Format traverse result as Markdown. */
112
+ export declare function formatTraverseAsMarkdown(result: TraverseResult): string;
113
+ /** Format search results as Markdown. */
114
+ export declare function formatSearchAsMarkdown(results: SearchResult[], keyword: string): string;
115
+ //# sourceMappingURL=graph-explore.d.ts.map