@pellux/goodvibes-sdk 0.27.2 → 0.27.4

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 (100) hide show
  1. package/dist/_internal/contracts/artifacts/operator-contract.json +845 -4
  2. package/dist/_internal/contracts/generated/foundation-metadata.d.ts +2 -2
  3. package/dist/_internal/contracts/generated/foundation-metadata.js +2 -2
  4. package/dist/_internal/contracts/generated/operator-contract.d.ts.map +1 -1
  5. package/dist/_internal/contracts/generated/operator-contract.js +845 -4
  6. package/dist/_internal/contracts/generated/operator-method-ids.d.ts +1 -1
  7. package/dist/_internal/contracts/generated/operator-method-ids.d.ts.map +1 -1
  8. package/dist/_internal/contracts/generated/operator-method-ids.js +2 -0
  9. package/dist/_internal/daemon/context.d.ts +1 -0
  10. package/dist/_internal/daemon/context.d.ts.map +1 -1
  11. package/dist/_internal/daemon/knowledge-route-types.d.ts +1 -0
  12. package/dist/_internal/daemon/knowledge-route-types.d.ts.map +1 -1
  13. package/dist/_internal/daemon/knowledge-routes.d.ts +1 -1
  14. package/dist/_internal/daemon/knowledge-routes.d.ts.map +1 -1
  15. package/dist/_internal/daemon/knowledge-routes.js +18 -0
  16. package/dist/_internal/daemon/operator.d.ts +1 -1
  17. package/dist/_internal/daemon/operator.d.ts.map +1 -1
  18. package/dist/_internal/daemon/operator.js +2 -0
  19. package/dist/_internal/platform/control-plane/method-catalog-homegraph.d.ts.map +1 -1
  20. package/dist/_internal/platform/control-plane/method-catalog-homegraph.js +10 -1
  21. package/dist/_internal/platform/control-plane/method-catalog-knowledge.d.ts.map +1 -1
  22. package/dist/_internal/platform/control-plane/method-catalog-knowledge.js +20 -1
  23. package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.d.ts +2 -0
  24. package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.d.ts.map +1 -1
  25. package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.js +23 -0
  26. package/dist/_internal/platform/control-plane/routes/operator.d.ts +1 -1
  27. package/dist/_internal/platform/control-plane/routes/operator.d.ts.map +1 -1
  28. package/dist/_internal/platform/control-plane/routes/operator.js +2 -0
  29. package/dist/_internal/platform/daemon/http/home-graph-routes.d.ts.map +1 -1
  30. package/dist/_internal/platform/daemon/http/home-graph-routes.js +7 -0
  31. package/dist/_internal/platform/daemon/http/router-route-contexts.d.ts.map +1 -1
  32. package/dist/_internal/platform/daemon/http/router-route-contexts.js +1 -0
  33. package/dist/_internal/platform/knowledge/extractors.d.ts.map +1 -1
  34. package/dist/_internal/platform/knowledge/extractors.js +1 -116
  35. package/dist/_internal/platform/knowledge/home-graph/ask.d.ts +13 -0
  36. package/dist/_internal/platform/knowledge/home-graph/ask.d.ts.map +1 -0
  37. package/dist/_internal/platform/knowledge/home-graph/ask.js +65 -0
  38. package/dist/_internal/platform/knowledge/home-graph/auto-link.d.ts +27 -0
  39. package/dist/_internal/platform/knowledge/home-graph/auto-link.d.ts.map +1 -0
  40. package/dist/_internal/platform/knowledge/home-graph/auto-link.js +236 -0
  41. package/dist/_internal/platform/knowledge/home-graph/generated-pages.d.ts +1 -0
  42. package/dist/_internal/platform/knowledge/home-graph/generated-pages.d.ts.map +1 -1
  43. package/dist/_internal/platform/knowledge/home-graph/generated-pages.js +24 -8
  44. package/dist/_internal/platform/knowledge/home-graph/index.d.ts +1 -1
  45. package/dist/_internal/platform/knowledge/home-graph/index.d.ts.map +1 -1
  46. package/dist/_internal/platform/knowledge/home-graph/pages.d.ts +11 -0
  47. package/dist/_internal/platform/knowledge/home-graph/pages.d.ts.map +1 -0
  48. package/dist/_internal/platform/knowledge/home-graph/pages.js +44 -0
  49. package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts +4 -1
  50. package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts.map +1 -1
  51. package/dist/_internal/platform/knowledge/home-graph/rendering.js +215 -4
  52. package/dist/_internal/platform/knowledge/home-graph/service.d.ts +12 -2
  53. package/dist/_internal/platform/knowledge/home-graph/service.d.ts.map +1 -1
  54. package/dist/_internal/platform/knowledge/home-graph/service.js +78 -21
  55. package/dist/_internal/platform/knowledge/home-graph/types.d.ts +31 -1
  56. package/dist/_internal/platform/knowledge/home-graph/types.d.ts.map +1 -1
  57. package/dist/_internal/platform/knowledge/home-graph/types.js +2 -0
  58. package/dist/_internal/platform/knowledge/index.d.ts +3 -1
  59. package/dist/_internal/platform/knowledge/index.d.ts.map +1 -1
  60. package/dist/_internal/platform/knowledge/index.js +1 -0
  61. package/dist/_internal/platform/knowledge/ingest-compile.d.ts.map +1 -1
  62. package/dist/_internal/platform/knowledge/ingest-compile.js +5 -0
  63. package/dist/_internal/platform/knowledge/ingest-context.d.ts +1 -0
  64. package/dist/_internal/platform/knowledge/ingest-context.d.ts.map +1 -1
  65. package/dist/_internal/platform/knowledge/map.js +15 -1
  66. package/dist/_internal/platform/knowledge/pdf-extractor.d.ts +3 -0
  67. package/dist/_internal/platform/knowledge/pdf-extractor.d.ts.map +1 -0
  68. package/dist/_internal/platform/knowledge/pdf-extractor.js +346 -0
  69. package/dist/_internal/platform/knowledge/scheduling.d.ts.map +1 -1
  70. package/dist/_internal/platform/knowledge/scheduling.js +1 -0
  71. package/dist/_internal/platform/knowledge/semantic/answer.d.ts +9 -0
  72. package/dist/_internal/platform/knowledge/semantic/answer.d.ts.map +1 -0
  73. package/dist/_internal/platform/knowledge/semantic/answer.js +407 -0
  74. package/dist/_internal/platform/knowledge/semantic/enrichment.d.ts +23 -0
  75. package/dist/_internal/platform/knowledge/semantic/enrichment.d.ts.map +1 -0
  76. package/dist/_internal/platform/knowledge/semantic/enrichment.js +491 -0
  77. package/dist/_internal/platform/knowledge/semantic/index.d.ts +5 -0
  78. package/dist/_internal/platform/knowledge/semantic/index.d.ts.map +1 -0
  79. package/dist/_internal/platform/knowledge/semantic/index.js +2 -0
  80. package/dist/_internal/platform/knowledge/semantic/llm.d.ts +4 -0
  81. package/dist/_internal/platform/knowledge/semantic/llm.d.ts.map +1 -0
  82. package/dist/_internal/platform/knowledge/semantic/llm.js +34 -0
  83. package/dist/_internal/platform/knowledge/semantic/service.d.ts +37 -0
  84. package/dist/_internal/platform/knowledge/semantic/service.d.ts.map +1 -0
  85. package/dist/_internal/platform/knowledge/semantic/service.js +55 -0
  86. package/dist/_internal/platform/knowledge/semantic/types.d.ts +107 -0
  87. package/dist/_internal/platform/knowledge/semantic/types.d.ts.map +1 -0
  88. package/dist/_internal/platform/knowledge/semantic/types.js +1 -0
  89. package/dist/_internal/platform/knowledge/semantic/utils.d.ts +39 -0
  90. package/dist/_internal/platform/knowledge/semantic/utils.d.ts.map +1 -0
  91. package/dist/_internal/platform/knowledge/semantic/utils.js +189 -0
  92. package/dist/_internal/platform/knowledge/service.d.ts +12 -0
  93. package/dist/_internal/platform/knowledge/service.d.ts.map +1 -1
  94. package/dist/_internal/platform/knowledge/service.js +14 -0
  95. package/dist/_internal/platform/knowledge/types.d.ts +2 -2
  96. package/dist/_internal/platform/knowledge/types.d.ts.map +1 -1
  97. package/dist/_internal/platform/runtime/services.d.ts.map +1 -1
  98. package/dist/_internal/platform/runtime/services.js +8 -2
  99. package/dist/_internal/platform/version.js +1 -1
  100. package/package.json +1 -1
@@ -0,0 +1,407 @@
1
+ import { getKnowledgeSpaceId, isInKnowledgeSpace, normalizeKnowledgeSpaceId } from '../spaces.js';
2
+ import { MAX_ANSWER_EVIDENCE_CHARS, clampText, normalizeWhitespace, readRecord, readString, scoreSemanticText, semanticHash, semanticMetadata, sourceSemanticText, tokenizeSemanticQuery, uniqueStrings, } from './utils.js';
3
+ export async function answerKnowledgeQuery(context, input) {
4
+ const spaceId = normalizeKnowledgeSpaceId(input.knowledgeSpaceId);
5
+ const mode = input.mode ?? 'standard';
6
+ const limit = Math.max(1, input.limit ?? 8);
7
+ const evidence = collectAnswerEvidence(context.store, input, spaceId, limit);
8
+ if (evidence.length === 0) {
9
+ const gap = await persistAnswerGap(context.store, spaceId, input.query, 'No indexed evidence matched the question.');
10
+ return {
11
+ ok: true,
12
+ spaceId,
13
+ query: input.query,
14
+ answer: {
15
+ text: input.noMatchMessage ?? `No knowledge matched "${input.query}".`,
16
+ mode,
17
+ confidence: 0,
18
+ sources: [],
19
+ linkedObjects: input.includeLinkedObjects === false ? [] : [...input.linkedObjects ?? []],
20
+ facts: [],
21
+ gaps: [gap],
22
+ synthesized: false,
23
+ },
24
+ results: [],
25
+ };
26
+ }
27
+ const llmAnswer = await synthesizeAnswer(context.llm ?? null, input.query, mode, evidence);
28
+ const facts = uniqueNodes(evidence.flatMap((item) => item.facts)).slice(0, 24);
29
+ const sources = uniqueSources(evidence.flatMap((item) => item.source ? [item.source] : [])).slice(0, limit);
30
+ const linkedObjects = input.includeLinkedObjects === false
31
+ ? []
32
+ : uniqueNodes([...(input.linkedObjects ?? []), ...evidence.flatMap((item) => item.node ? [item.node] : [])]).slice(0, 24);
33
+ const gaps = await persistAnswerGaps(context.store, spaceId, input.query, llmAnswer?.gaps ?? []);
34
+ const text = llmAnswer?.answer?.trim() || renderFallbackAnswer(input.query, mode, evidence);
35
+ return {
36
+ ok: true,
37
+ spaceId,
38
+ query: input.query,
39
+ answer: {
40
+ text,
41
+ mode,
42
+ confidence: input.includeConfidence === false ? 0 : answerConfidence(llmAnswer, evidence),
43
+ sources: input.includeSources === false ? [] : sources,
44
+ linkedObjects,
45
+ facts,
46
+ gaps,
47
+ synthesized: Boolean(llmAnswer?.answer),
48
+ },
49
+ results: evidence.map(toSearchResult),
50
+ };
51
+ }
52
+ function collectAnswerEvidence(store, input, spaceId, limit) {
53
+ const tokens = expandQueryTokens(tokenizeSemanticQuery(input.query));
54
+ if (tokens.length === 0)
55
+ return [];
56
+ const candidateSourceIds = new Set(input.candidateSourceIds ?? []);
57
+ const candidateNodeIds = new Set(input.candidateNodeIds ?? []);
58
+ const linkedObjectIds = new Set((input.linkedObjects ?? []).map((node) => node.id));
59
+ const sourceFacts = buildSourceFactIndex(store, spaceId);
60
+ const linkedSourceIds = sourceIdsLinkedToNodes(store, new Set([...candidateNodeIds, ...linkedObjectIds]), spaceId);
61
+ const sourceItems = store.listSources(10_000)
62
+ .filter((source) => belongsToAnswerSpace(source, spaceId))
63
+ .map((source) => {
64
+ const extraction = store.getExtractionBySourceId(source.id);
65
+ const facts = sourceFacts.get(source.id) ?? [];
66
+ const text = sourceSemanticText(source, extraction);
67
+ const baseScore = scoreSemanticText([
68
+ source.title,
69
+ source.summary,
70
+ source.description,
71
+ source.tags.join(' '),
72
+ text,
73
+ facts.map(renderFactForScoring).join(' '),
74
+ ].join('\n'), tokens);
75
+ const candidateBoost = candidateSourceIds.has(source.id) ? 220 : 0;
76
+ const linkedBoost = linkedSourceIds.has(source.id) ? 160 : 0;
77
+ const score = baseScore + candidateBoost + linkedBoost + Math.min(60, facts.length * 6);
78
+ return {
79
+ kind: 'source',
80
+ id: source.id,
81
+ title: source.title ?? source.canonicalUri ?? source.sourceUri ?? source.id,
82
+ score,
83
+ source,
84
+ excerpt: selectEvidenceExcerpt(input.query, text, facts),
85
+ facts,
86
+ };
87
+ });
88
+ const nodeItems = store.listNodes(10_000)
89
+ .filter((node) => belongsToAnswerSpace(node, spaceId))
90
+ .map((node) => {
91
+ const score = scoreSemanticText([
92
+ node.title,
93
+ node.summary,
94
+ node.aliases.join(' '),
95
+ JSON.stringify(node.metadata),
96
+ ].join('\n'), tokens) + (candidateNodeIds.has(node.id) || linkedObjectIds.has(node.id) ? 120 : 0) + semanticKindBoost(node);
97
+ return {
98
+ kind: 'node',
99
+ id: node.id,
100
+ title: node.title,
101
+ score,
102
+ node,
103
+ excerpt: renderNodeEvidence(node),
104
+ facts: node.metadata.semanticKind === 'fact' ? [node] : [],
105
+ };
106
+ });
107
+ const items = [...sourceItems, ...nodeItems]
108
+ .filter((item) => item.score > 0)
109
+ .sort((left, right) => right.score - left.score || left.id.localeCompare(right.id));
110
+ return pruneEvidence(items, limit);
111
+ }
112
+ async function synthesizeAnswer(llm, query, mode, evidence) {
113
+ if (!llm)
114
+ return null;
115
+ const response = await llm.completeJson({
116
+ purpose: 'knowledge-answer-synthesis',
117
+ maxTokens: mode === 'detailed' ? 2200 : mode === 'concise' ? 700 : 1400,
118
+ systemPrompt: [
119
+ 'You answer questions from a GoodVibes self-improving knowledge wiki.',
120
+ 'Use only the supplied evidence. Synthesize the answer for the user intent rather than dumping snippets.',
121
+ 'If evidence is insufficient, say what is missing. Prefer concrete features, specs, procedures, and relationships.',
122
+ 'Return only JSON with answer, confidence, usedSourceIds, usedNodeIds, and optional gaps.',
123
+ ].join(' '),
124
+ prompt: JSON.stringify({
125
+ query,
126
+ mode,
127
+ evidence: renderEvidenceForPrompt(evidence),
128
+ outputShape: {
129
+ answer: 'source-backed natural language answer',
130
+ confidence: 0,
131
+ usedSourceIds: ['source ids used'],
132
+ usedNodeIds: ['node ids used'],
133
+ gaps: [{ question: 'unanswered follow-up gap', reason: 'missing evidence', severity: 'info' }],
134
+ },
135
+ }),
136
+ });
137
+ return normalizeLlmAnswer(response);
138
+ }
139
+ function renderEvidenceForPrompt(evidence) {
140
+ let budget = MAX_ANSWER_EVIDENCE_CHARS;
141
+ const rendered = [];
142
+ for (const item of evidence.slice(0, 12)) {
143
+ if (budget <= 0)
144
+ break;
145
+ const factText = item.facts.slice(0, 16).map(renderFactForPrompt).join('\n');
146
+ const excerpt = clampText(item.excerpt, Math.min(1600, budget));
147
+ const record = {
148
+ kind: item.kind,
149
+ id: item.id,
150
+ title: item.title,
151
+ sourceId: item.source?.id,
152
+ nodeId: item.node?.id,
153
+ sourceType: item.source?.sourceType,
154
+ nodeKind: item.node?.kind,
155
+ excerpt,
156
+ facts: factText,
157
+ };
158
+ budget -= JSON.stringify(record).length;
159
+ rendered.push(record);
160
+ }
161
+ return rendered;
162
+ }
163
+ function renderFallbackAnswer(query, mode, evidence) {
164
+ const facts = uniqueNodes(evidence.flatMap((item) => item.facts));
165
+ const factLines = facts
166
+ .filter((fact) => fact.metadata.semanticKind === 'fact')
167
+ .slice(0, mode === 'detailed' ? 12 : mode === 'concise' ? 3 : 6)
168
+ .map((fact) => {
169
+ const value = readString(fact.metadata.value);
170
+ const summary = fact.summary ?? readString(fact.metadata.evidence);
171
+ return `- ${fact.title}${value ? `: ${value}` : ''}${summary ? ` - ${summary}` : ''}`;
172
+ });
173
+ if (factLines.length > 0)
174
+ return factLines.join('\n');
175
+ const lines = evidence.slice(0, mode === 'detailed' ? 8 : mode === 'concise' ? 1 : 4)
176
+ .map((item) => `- ${item.title}${item.excerpt ? `: ${clampText(item.excerpt, 360)}` : ''}`);
177
+ return lines.length > 0 ? lines.join('\n') : `No knowledge matched "${query}".`;
178
+ }
179
+ async function persistAnswerGap(store, spaceId, query, reason) {
180
+ const node = await store.upsertNode({
181
+ id: `sem-answer-gap-${semanticHash(spaceId, query)}`,
182
+ kind: 'knowledge_gap',
183
+ slug: `answer-gap-${semanticHash(spaceId, query)}`,
184
+ title: query,
185
+ summary: reason,
186
+ confidence: 70,
187
+ metadata: semanticMetadata(spaceId, {
188
+ semanticKind: 'gap',
189
+ gapKind: 'answer',
190
+ query,
191
+ reason,
192
+ }),
193
+ });
194
+ await store.upsertIssue({
195
+ id: `sem-answer-gap-issue-${semanticHash(spaceId, query)}`,
196
+ severity: 'info',
197
+ code: 'knowledge.answer_gap',
198
+ message: `No knowledge answer available for: ${query}`,
199
+ status: 'open',
200
+ nodeId: node.id,
201
+ metadata: semanticMetadata(spaceId, {
202
+ namespace: `knowledge:${spaceId}:answers`,
203
+ query,
204
+ reason,
205
+ }),
206
+ });
207
+ return node;
208
+ }
209
+ async function persistAnswerGaps(store, spaceId, query, gaps) {
210
+ const nodes = [];
211
+ for (const gap of gaps.slice(0, 8)) {
212
+ nodes.push(await persistAnswerGap(store, spaceId, gap.question || query, gap.reason ?? 'Answer synthesis identified a missing knowledge gap.'));
213
+ }
214
+ return nodes;
215
+ }
216
+ function buildSourceFactIndex(store, spaceId) {
217
+ const facts = store.listNodes(10_000).filter((node) => (node.metadata.semanticKind === 'fact' && belongsToAnswerSpace(node, spaceId)));
218
+ const bySource = new Map();
219
+ for (const fact of facts) {
220
+ const sourceId = readString(fact.metadata.sourceId) ?? fact.sourceId;
221
+ if (!sourceId)
222
+ continue;
223
+ bySource.set(sourceId, [...(bySource.get(sourceId) ?? []), fact]);
224
+ }
225
+ return bySource;
226
+ }
227
+ function sourceIdsLinkedToNodes(store, nodeIds, spaceId) {
228
+ const sourceIds = new Set();
229
+ if (nodeIds.size === 0)
230
+ return sourceIds;
231
+ for (const edge of store.listEdges()) {
232
+ if (!belongsToAnswerSpace(edge, spaceId))
233
+ continue;
234
+ if (edge.fromKind === 'source' && edge.toKind === 'node' && nodeIds.has(edge.toId))
235
+ sourceIds.add(edge.fromId);
236
+ if (edge.fromKind === 'node' && nodeIds.has(edge.fromId) && edge.toKind === 'source')
237
+ sourceIds.add(edge.toId);
238
+ }
239
+ return sourceIds;
240
+ }
241
+ function selectEvidenceExcerpt(query, text, facts) {
242
+ const tokens = expandQueryTokens(tokenizeSemanticQuery(query));
243
+ const factLines = facts
244
+ .map(renderFactForPrompt)
245
+ .filter((line) => scoreSemanticText(line, tokens) > 0)
246
+ .slice(0, 12);
247
+ const windows = evidenceWindows(text, tokens).slice(0, 4);
248
+ return uniqueStrings([...factLines, ...windows, clampText(text, 720)]).join('\n');
249
+ }
250
+ function evidenceWindows(text, tokens) {
251
+ const normalized = normalizeWhitespace(text);
252
+ const lower = normalized.toLowerCase();
253
+ const windows = [];
254
+ for (const token of tokens) {
255
+ if (token.length < 3)
256
+ continue;
257
+ const index = lower.indexOf(token);
258
+ if (index < 0)
259
+ continue;
260
+ const start = Math.max(0, index - 220);
261
+ const end = Math.min(normalized.length, index + 620);
262
+ windows.push(`${start > 0 ? '...' : ''}${normalized.slice(start, end)}${end < normalized.length ? '...' : ''}`);
263
+ }
264
+ return uniqueStrings(windows);
265
+ }
266
+ function expandQueryTokens(tokens) {
267
+ const expansions = {
268
+ capabilities: ['capability', 'feature', 'features', 'function', 'functions', 'supports', 'specifications'],
269
+ capability: ['capabilities', 'feature', 'features', 'function', 'functions', 'supports', 'specifications'],
270
+ feature: ['features', 'capability', 'capabilities', 'function', 'functions', 'supports', 'specifications'],
271
+ features: ['feature', 'capability', 'capabilities', 'function', 'functions', 'supports', 'specifications'],
272
+ settings: ['configuration', 'configure', 'options'],
273
+ setup: ['install', 'configure', 'pair'],
274
+ };
275
+ return uniqueStrings(tokens.flatMap((token) => [token, ...(expansions[token] ?? [])]));
276
+ }
277
+ function pruneEvidence(items, limit) {
278
+ const sourceSeen = new Set();
279
+ const nodeSeen = new Set();
280
+ const out = [];
281
+ for (const item of items) {
282
+ if (item.kind === 'source') {
283
+ if (sourceSeen.has(item.id))
284
+ continue;
285
+ sourceSeen.add(item.id);
286
+ }
287
+ else {
288
+ if (nodeSeen.has(item.id))
289
+ continue;
290
+ nodeSeen.add(item.id);
291
+ }
292
+ out.push(item);
293
+ if (out.length >= Math.max(1, limit))
294
+ break;
295
+ }
296
+ return out;
297
+ }
298
+ function toSearchResult(item) {
299
+ return {
300
+ kind: item.kind,
301
+ id: item.id,
302
+ score: item.score,
303
+ reason: 'semantic evidence match',
304
+ ...(item.source ? { source: item.source } : {}),
305
+ ...(item.node ? { node: item.node } : {}),
306
+ };
307
+ }
308
+ function normalizeLlmAnswer(value) {
309
+ const record = readRecord(value);
310
+ const answer = readString(record.answer);
311
+ if (!answer)
312
+ return null;
313
+ return {
314
+ answer,
315
+ ...(typeof record.confidence === 'number' ? { confidence: Math.max(0, Math.min(100, Math.round(record.confidence))) } : {}),
316
+ usedSourceIds: readStringArray(record.usedSourceIds),
317
+ usedNodeIds: readStringArray(record.usedNodeIds),
318
+ gaps: readGapArray(record.gaps),
319
+ };
320
+ }
321
+ function answerConfidence(answer, evidence) {
322
+ if (typeof answer?.confidence === 'number')
323
+ return answer.confidence;
324
+ const top = evidence[0]?.score ?? 0;
325
+ const factBoost = Math.min(35, uniqueNodes(evidence.flatMap((item) => item.facts)).length * 4);
326
+ return Math.max(10, Math.min(92, Math.round(top / 5) + factBoost));
327
+ }
328
+ function renderFactForScoring(fact) {
329
+ return [
330
+ fact.title,
331
+ fact.summary,
332
+ readString(fact.metadata.value),
333
+ readString(fact.metadata.evidence),
334
+ Array.isArray(fact.metadata.labels) ? fact.metadata.labels.join(' ') : '',
335
+ ].filter(Boolean).join(' ');
336
+ }
337
+ function renderFactForPrompt(fact) {
338
+ const kind = readString(fact.metadata.factKind) ?? 'fact';
339
+ const value = readString(fact.metadata.value);
340
+ const evidence = readString(fact.metadata.evidence);
341
+ return `${kind}: ${fact.title}${value ? ` = ${value}` : ''}${fact.summary ? ` - ${fact.summary}` : ''}${evidence ? ` Evidence: ${evidence}` : ''}`;
342
+ }
343
+ function renderNodeEvidence(node) {
344
+ if (node.metadata.semanticKind === 'fact')
345
+ return renderFactForPrompt(node);
346
+ if (node.metadata.semanticKind === 'wiki_page')
347
+ return readString(node.metadata.markdown) ?? node.summary ?? '';
348
+ return [node.summary, node.aliases.join(', ')].filter(Boolean).join('\n');
349
+ }
350
+ function semanticKindBoost(node) {
351
+ if (node.metadata.semanticKind === 'fact')
352
+ return 45;
353
+ if (node.metadata.semanticKind === 'wiki_page')
354
+ return 24;
355
+ if (node.metadata.semanticKind === 'entity')
356
+ return 18;
357
+ return 0;
358
+ }
359
+ function belongsToAnswerSpace(record, spaceId) {
360
+ return normalizeKnowledgeSpaceId(spaceId) === 'default'
361
+ ? normalizeKnowledgeSpaceId(getKnowledgeSpaceId(record)) === 'default'
362
+ : isInKnowledgeSpace(record, spaceId);
363
+ }
364
+ function uniqueNodes(nodes) {
365
+ const seen = new Set();
366
+ const out = [];
367
+ for (const node of nodes) {
368
+ if (seen.has(node.id))
369
+ continue;
370
+ seen.add(node.id);
371
+ out.push(node);
372
+ }
373
+ return out;
374
+ }
375
+ function uniqueSources(sources) {
376
+ const seen = new Set();
377
+ const out = [];
378
+ for (const source of sources) {
379
+ if (seen.has(source.id))
380
+ continue;
381
+ seen.add(source.id);
382
+ out.push(source);
383
+ }
384
+ return out;
385
+ }
386
+ function readStringArray(value) {
387
+ return Array.isArray(value)
388
+ ? uniqueStrings(value.map((entry) => typeof entry === 'string' ? entry : undefined))
389
+ : [];
390
+ }
391
+ function readGapArray(value) {
392
+ if (!Array.isArray(value))
393
+ return [];
394
+ return value.flatMap((entry) => {
395
+ const record = readRecord(entry);
396
+ const question = readString(record.question);
397
+ if (!question)
398
+ return [];
399
+ const severity = readString(record.severity);
400
+ return [{
401
+ question,
402
+ ...(readString(record.reason) ? { reason: readString(record.reason) } : {}),
403
+ ...(readString(record.subject) ? { subject: readString(record.subject) } : {}),
404
+ severity: severity === 'warning' || severity === 'error' ? severity : 'info',
405
+ }];
406
+ });
407
+ }
@@ -0,0 +1,23 @@
1
+ import type { KnowledgeStore } from '../store.js';
2
+ import type { KnowledgeNodeRecord, KnowledgeSourceRecord } from '../types.js';
3
+ import type { KnowledgeSemanticLlm } from './types.js';
4
+ export interface KnowledgeSemanticEnrichmentContext {
5
+ readonly store: KnowledgeStore;
6
+ readonly llm?: KnowledgeSemanticLlm | null;
7
+ }
8
+ export interface EnrichKnowledgeSourceOptions {
9
+ readonly force?: boolean;
10
+ readonly knowledgeSpaceId?: string;
11
+ }
12
+ export interface PersistedSemanticExtraction {
13
+ readonly source: KnowledgeSourceRecord;
14
+ readonly skipped: boolean;
15
+ readonly reason?: string;
16
+ readonly extractor?: 'llm' | 'deterministic';
17
+ readonly facts: readonly KnowledgeNodeRecord[];
18
+ readonly entities: readonly KnowledgeNodeRecord[];
19
+ readonly wikiPage?: KnowledgeNodeRecord;
20
+ readonly gaps: readonly KnowledgeNodeRecord[];
21
+ }
22
+ export declare function enrichKnowledgeSource(context: KnowledgeSemanticEnrichmentContext, source: KnowledgeSourceRecord, options?: EnrichKnowledgeSourceOptions): Promise<PersistedSemanticExtraction>;
23
+ //# sourceMappingURL=enrichment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichment.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/enrichment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAEV,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAKV,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAkBpB,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,GAAG,eAAe,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IACxC,QAAQ,CAAC,IAAI,EAAE,SAAS,mBAAmB,EAAE,CAAC;CAC/C;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,kCAAkC,EAC3C,MAAM,EAAE,qBAAqB,EAC7B,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,2BAA2B,CAAC,CA6BtC"}