@pellux/goodvibes-sdk 0.28.16 → 0.28.18

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 (70) hide show
  1. package/dist/_internal/contracts/artifacts/operator-contract.json +70 -1
  2. package/dist/_internal/contracts/generated/foundation-metadata.d.ts +1 -1
  3. package/dist/_internal/contracts/generated/foundation-metadata.js +1 -1
  4. package/dist/_internal/contracts/generated/operator-contract.d.ts.map +1 -1
  5. package/dist/_internal/contracts/generated/operator-contract.js +70 -1
  6. package/dist/_internal/platform/artifacts/store.d.ts +2 -0
  7. package/dist/_internal/platform/artifacts/store.d.ts.map +1 -1
  8. package/dist/_internal/platform/artifacts/store.js +20 -0
  9. package/dist/_internal/platform/control-plane/method-catalog-homegraph.d.ts.map +1 -1
  10. package/dist/_internal/platform/control-plane/method-catalog-homegraph.js +9 -0
  11. package/dist/_internal/platform/control-plane/operator-contract-schemas-homegraph.d.ts.map +1 -1
  12. package/dist/_internal/platform/control-plane/operator-contract-schemas-homegraph.js +15 -1
  13. package/dist/_internal/platform/knowledge/home-graph/ask-page-refresh.d.ts +11 -0
  14. package/dist/_internal/platform/knowledge/home-graph/ask-page-refresh.d.ts.map +1 -0
  15. package/dist/_internal/platform/knowledge/home-graph/ask-page-refresh.js +31 -0
  16. package/dist/_internal/platform/knowledge/home-graph/ask.d.ts.map +1 -1
  17. package/dist/_internal/platform/knowledge/home-graph/ask.js +24 -1
  18. package/dist/_internal/platform/knowledge/home-graph/generated-pages.d.ts.map +1 -1
  19. package/dist/_internal/platform/knowledge/home-graph/generated-pages.js +92 -20
  20. package/dist/_internal/platform/knowledge/home-graph/map-view.d.ts.map +1 -1
  21. package/dist/_internal/platform/knowledge/home-graph/map-view.js +14 -0
  22. package/dist/_internal/platform/knowledge/home-graph/pages.d.ts +3 -1
  23. package/dist/_internal/platform/knowledge/home-graph/pages.d.ts.map +1 -1
  24. package/dist/_internal/platform/knowledge/home-graph/pages.js +104 -1
  25. package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts +0 -1
  26. package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts.map +1 -1
  27. package/dist/_internal/platform/knowledge/home-graph/rendering.js +0 -12
  28. package/dist/_internal/platform/knowledge/home-graph/reset.d.ts +2 -1
  29. package/dist/_internal/platform/knowledge/home-graph/reset.d.ts.map +1 -1
  30. package/dist/_internal/platform/knowledge/home-graph/reset.js +35 -2
  31. package/dist/_internal/platform/knowledge/home-graph/search.d.ts.map +1 -1
  32. package/dist/_internal/platform/knowledge/home-graph/search.js +2 -18
  33. package/dist/_internal/platform/knowledge/home-graph/service.d.ts +1 -1
  34. package/dist/_internal/platform/knowledge/home-graph/service.d.ts.map +1 -1
  35. package/dist/_internal/platform/knowledge/home-graph/service.js +17 -5
  36. package/dist/_internal/platform/knowledge/home-graph/source-links.d.ts +3 -0
  37. package/dist/_internal/platform/knowledge/home-graph/source-links.d.ts.map +1 -0
  38. package/dist/_internal/platform/knowledge/home-graph/source-links.js +30 -0
  39. package/dist/_internal/platform/knowledge/home-graph/state.d.ts.map +1 -1
  40. package/dist/_internal/platform/knowledge/home-graph/state.js +43 -1
  41. package/dist/_internal/platform/knowledge/home-graph/types.d.ts +39 -1
  42. package/dist/_internal/platform/knowledge/home-graph/types.d.ts.map +1 -1
  43. package/dist/_internal/platform/knowledge/ingest-compile.js +1 -1
  44. package/dist/_internal/platform/knowledge/pdf-extractor.d.ts.map +1 -1
  45. package/dist/_internal/platform/knowledge/pdf-extractor.js +8 -3
  46. package/dist/_internal/platform/knowledge/semantic/answer-fallback.d.ts.map +1 -1
  47. package/dist/_internal/platform/knowledge/semantic/answer-fallback.js +21 -16
  48. package/dist/_internal/platform/knowledge/semantic/answer-source-ranking.d.ts +7 -0
  49. package/dist/_internal/platform/knowledge/semantic/answer-source-ranking.d.ts.map +1 -0
  50. package/dist/_internal/platform/knowledge/semantic/answer-source-ranking.js +57 -0
  51. package/dist/_internal/platform/knowledge/semantic/answer.d.ts.map +1 -1
  52. package/dist/_internal/platform/knowledge/semantic/answer.js +76 -9
  53. package/dist/_internal/platform/knowledge/semantic/fact-quality.d.ts +0 -1
  54. package/dist/_internal/platform/knowledge/semantic/fact-quality.d.ts.map +1 -1
  55. package/dist/_internal/platform/knowledge/semantic/fact-quality.js +18 -18
  56. package/dist/_internal/platform/knowledge/semantic/homeassistant-scope.d.ts.map +1 -1
  57. package/dist/_internal/platform/knowledge/semantic/homeassistant-scope.js +63 -5
  58. package/dist/_internal/platform/knowledge/semantic/repair-profile.d.ts +16 -0
  59. package/dist/_internal/platform/knowledge/semantic/repair-profile.d.ts.map +1 -0
  60. package/dist/_internal/platform/knowledge/semantic/repair-profile.js +152 -0
  61. package/dist/_internal/platform/knowledge/semantic/repair-subjects.d.ts +16 -0
  62. package/dist/_internal/platform/knowledge/semantic/repair-subjects.d.ts.map +1 -0
  63. package/dist/_internal/platform/knowledge/semantic/repair-subjects.js +52 -0
  64. package/dist/_internal/platform/knowledge/semantic/self-improvement-promotion.d.ts.map +1 -1
  65. package/dist/_internal/platform/knowledge/semantic/self-improvement-promotion.js +122 -57
  66. package/dist/_internal/platform/knowledge/semantic/self-improvement.d.ts.map +1 -1
  67. package/dist/_internal/platform/knowledge/semantic/self-improvement.js +40 -13
  68. package/dist/_internal/platform/knowledge/semantic/service.js +1 -1
  69. package/dist/_internal/platform/version.js +1 -1
  70. package/package.json +2 -1
@@ -0,0 +1,152 @@
1
+ import { hasConcreteFeatureSignal, isLowValueFeatureOrSpecText } from './fact-quality.js';
2
+ import { clampText, normalizeWhitespace, uniqueStrings } from './utils.js';
3
+ const PROFILE_RULES = [
4
+ {
5
+ title: 'Display and picture specifications',
6
+ kind: 'specification',
7
+ labels: ['display', 'picture'],
8
+ aliases: ['display', 'picture', 'screen'],
9
+ intent: /\b(display|screen|resolution|picture|panel|hdr|refresh|hz|dolby vision|nanocell|lcd|led|oled)\b/,
10
+ minimumMatches: 2,
11
+ terms: [
12
+ ['86-inch class screen', /\b86(?:\.0)?\s*(?:inch|inches|in\.|")\b|\b86nano/i],
13
+ ['4K UHD resolution', /\b4k\b|\buhd\b|\b3840\s*(?:x|×)\s*2160\b/i],
14
+ ['NanoCell display technology', /\bnanocell\b/i],
15
+ ['LCD/LED display', /\blcd\b|\bled\b/i],
16
+ ['100/120 Hz refresh-rate evidence', /\b(?:100|120)\s*hz\b|\btrumotion\s*240\b/i],
17
+ ['HDR10', /\bhdr10\b/i],
18
+ ['Dolby Vision', /\bdolby vision\b/i],
19
+ ['HLG', /\bhlg\b/i],
20
+ ],
21
+ },
22
+ {
23
+ title: 'Input and output ports',
24
+ kind: 'specification',
25
+ labels: ['ports', 'connectivity'],
26
+ aliases: ['ports', 'inputs', 'outputs', 'connectivity'],
27
+ intent: /\b(port|ports|input|output|i\/o|hdmi|usb|optical|rf|antenna|ethernet|rs-?232|composite|component|earc|arc)\b/,
28
+ minimumMatches: 2,
29
+ terms: [
30
+ ['HDMI inputs', /\bhdmi\b/i],
31
+ ['HDMI ARC/eARC', /\bearc\b|\barc\b/i],
32
+ ['USB ports', /\busb\b/i],
33
+ ['Ethernet', /\bethernet\b|\brj-?45\b/i],
34
+ ['Optical audio output', /\boptical\b|\btoslink\b/i],
35
+ ['RF antenna input', /\brf\b|\bantenna\b/i],
36
+ ['Composite/component video', /\bcomposite\b|\bcomponent\b/i],
37
+ ['RS-232C/external control', /\brs-?232c?\b|\bexternal control\b/i],
38
+ ],
39
+ },
40
+ {
41
+ title: 'Smart TV platform and integrations',
42
+ kind: 'feature',
43
+ labels: ['smart-tv', 'apps'],
44
+ aliases: ['smart tv', 'apps', 'platform'],
45
+ intent: /\b(smart|webos|apps?|streaming|airplay|homekit|thinq|voice|assistant|alexa|google assistant)\b/,
46
+ minimumMatches: 1,
47
+ terms: [
48
+ ['webOS smart TV platform', /\bwebos\b/i],
49
+ ['LG ThinQ AI', /\bthinq\b/i],
50
+ ['Apple AirPlay 2', /\bairplay\s*2?\b/i],
51
+ ['Apple HomeKit', /\bhomekit\b/i],
52
+ ['voice assistant support', /\bvoice\b|\balexa\b|\bgoogle assistant\b/i],
53
+ ['streaming app support', /\bapps?\b|\bstreaming\b/i],
54
+ ],
55
+ },
56
+ {
57
+ title: 'Network and wireless capabilities',
58
+ kind: 'capability',
59
+ labels: ['network', 'wireless'],
60
+ aliases: ['network', 'wireless', 'bluetooth', 'wi-fi'],
61
+ intent: /\b(wi-?fi|wireless|bluetooth|ethernet|network|lan)\b/,
62
+ minimumMatches: 1,
63
+ terms: [
64
+ ['Wi-Fi/wireless LAN', /\bwi-?fi\b|\bwireless lan\b/i],
65
+ ['Bluetooth', /\bbluetooth\b/i],
66
+ ['Ethernet/LAN', /\bethernet\b|\blan\b/i],
67
+ ],
68
+ },
69
+ {
70
+ title: 'Gaming and HDMI features',
71
+ kind: 'feature',
72
+ labels: ['gaming', 'hdmi'],
73
+ aliases: ['gaming', 'game mode', 'hdmi 2.1'],
74
+ intent: /\b(game|gaming|vrr|allm|freesync|g-?sync|low latency|hdmi\s*2\.1|4k\s*120)\b/,
75
+ minimumMatches: 1,
76
+ terms: [
77
+ ['FreeSync/VRR evidence', /\bfreesync\b|\bvrr\b/i],
78
+ ['ALLM/low latency evidence', /\ballm\b|\blow latency\b/i],
79
+ ['Game Optimizer/game mode', /\bgame optimizer\b|\bgame mode\b|\bgaming\b/i],
80
+ ['HDMI 2.1/high-bandwidth HDMI evidence', /\bhdmi\s*2\.1\b|\b4k\s*(?:at|@)?\s*120\b|\b120\s*hz\b/i],
81
+ ],
82
+ },
83
+ {
84
+ title: 'Audio capabilities',
85
+ kind: 'specification',
86
+ labels: ['audio'],
87
+ aliases: ['audio', 'speakers', 'sound'],
88
+ intent: /\b(audio|speaker|sound|dolby atmos|dolby digital|earc|arc|watts?|channels?)\b/,
89
+ minimumMatches: 1,
90
+ terms: [
91
+ ['speaker/audio output evidence', /\bspeakers?\b|\b(?:10|20|40)\s*w\b|\b2(?:\.0)?\s*ch\b/i],
92
+ ['Dolby audio formats', /\bdolby atmos\b|\bdolby digital\b|\bdolby audio\b/i],
93
+ ['HDMI ARC/eARC audio', /\bearc\b|\barc\b/i],
94
+ ['supported audio formats', /\bsupported audio formats?\b|\bpcm\b|\btruehd\b/i],
95
+ ],
96
+ },
97
+ {
98
+ title: 'Tuner and broadcast support',
99
+ kind: 'specification',
100
+ labels: ['tuner', 'broadcast'],
101
+ aliases: ['tuner', 'broadcast', 'antenna'],
102
+ intent: /\b(tuner|atsc|ntsc|qam|broadcast|clear qam|antenna)\b/,
103
+ minimumMatches: 1,
104
+ terms: [
105
+ ['ATSC tuner support', /\batsc\b/i],
106
+ ['NTSC analog tuner support', /\bntsc\b/i],
107
+ ['Clear QAM support', /\bqam\b|\bclear qam\b/i],
108
+ ['RF/antenna input', /\brf\b|\bantenna\b/i],
109
+ ],
110
+ },
111
+ ];
112
+ export function deriveRepairProfileFacts(input) {
113
+ const text = normalizeWhitespace([
114
+ input.source.title,
115
+ input.source.summary,
116
+ input.source.description,
117
+ input.source.sourceUri,
118
+ input.source.canonicalUri,
119
+ input.text,
120
+ ].filter(Boolean).join(' '));
121
+ if (!hasConcreteFeatureSignal(text))
122
+ return [];
123
+ const query = input.query.toLowerCase();
124
+ const broadProfileIntent = /\b(features?|specifications?|profile|capabilities)\b/.test(query);
125
+ return PROFILE_RULES.flatMap((rule) => {
126
+ const values = uniqueStrings(rule.terms
127
+ .filter(([, pattern]) => pattern.test(text))
128
+ .map(([label]) => label));
129
+ const wanted = broadProfileIntent || rule.intent.test(query);
130
+ if (values.length < (wanted ? 1 : rule.minimumMatches))
131
+ return [];
132
+ const summary = `${rule.title} evidence includes ${joinValues(values)}.`;
133
+ if (isLowValueFeatureOrSpecText(summary))
134
+ return [];
135
+ return [{
136
+ kind: rule.kind,
137
+ title: rule.title,
138
+ value: values.join(', '),
139
+ summary,
140
+ evidence: clampText(summary, 360),
141
+ labels: rule.labels,
142
+ aliases: rule.aliases,
143
+ }];
144
+ }).slice(0, 10);
145
+ }
146
+ function joinValues(values) {
147
+ if (values.length <= 1)
148
+ return values[0] ?? '';
149
+ if (values.length === 2)
150
+ return `${values[0]} and ${values[1]}`;
151
+ return `${values.slice(0, -1).join(', ')}, and ${values[values.length - 1]}`;
152
+ }
@@ -0,0 +1,16 @@
1
+ import type { KnowledgeNodeRecord } from '../types.js';
2
+ export interface RepairSubjectHint {
3
+ readonly id: string;
4
+ readonly kind: string;
5
+ readonly title: string;
6
+ }
7
+ export declare function canonicalRepairSubjectNodes(input: {
8
+ readonly nodes: readonly (KnowledgeNodeRecord | undefined)[];
9
+ readonly text?: string;
10
+ }): KnowledgeNodeRecord[];
11
+ export declare function repairSubjectIds(input: {
12
+ readonly nodes: readonly (KnowledgeNodeRecord | undefined)[];
13
+ readonly text?: string;
14
+ }): string[];
15
+ export declare function repairSubjectHints(subjects: readonly KnowledgeNodeRecord[]): RepairSubjectHint[];
16
+ //# sourceMappingURL=repair-subjects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repair-subjects.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/repair-subjects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGvD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IACjD,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,mBAAmB,GAAG,SAAS,CAAC,EAAE,CAAC;IAC7D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,mBAAmB,EAAE,CAgBxB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,mBAAmB,GAAG,SAAS,CAAC,EAAE,CAAC;IAC7D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,EAAE,CAEX;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS,mBAAmB,EAAE,GAAG,iBAAiB,EAAE,CAMhG"}
@@ -0,0 +1,52 @@
1
+ import { readString } from './utils.js';
2
+ export function canonicalRepairSubjectNodes(input) {
3
+ const usable = uniqueNodes(input.nodes)
4
+ .filter((node) => node.status !== 'stale')
5
+ .filter((node) => !readString(node.metadata.semanticKind))
6
+ .filter((node) => !['fact', 'wiki_page', 'knowledge_gap', 'ha_device_passport'].includes(node.kind));
7
+ const devices = usable.filter((node) => node.kind === 'ha_device');
8
+ if (devices.length > 0)
9
+ return devices;
10
+ const entities = usable.filter((node) => node.kind === 'ha_entity');
11
+ if (entities.length > 0)
12
+ return entities;
13
+ const concreteKnowledge = usable.filter((node) => node.kind === 'knowledge_entity' && hasConcreteProductIdentity(node));
14
+ if (concreteKnowledge.length > 0)
15
+ return concreteKnowledge;
16
+ const nonIntegration = usable.filter((node) => node.kind !== 'ha_integration');
17
+ if (nonIntegration.length > 0)
18
+ return nonIntegration;
19
+ const integrationIntent = /\b(integration|platform|add-?on|addon|plugin|service|api|setup|configure|configuration|auth|credential|rate limit)\b/i.test(input.text ?? '');
20
+ const integrations = usable.filter((node) => node.kind === 'ha_integration');
21
+ return integrationIntent ? integrations : [];
22
+ }
23
+ export function repairSubjectIds(input) {
24
+ return canonicalRepairSubjectNodes(input).map((node) => node.id);
25
+ }
26
+ export function repairSubjectHints(subjects) {
27
+ return subjects.map((subject) => ({
28
+ id: subject.id,
29
+ kind: subject.kind,
30
+ title: subject.title,
31
+ }));
32
+ }
33
+ function hasConcreteProductIdentity(node) {
34
+ const entityKind = readString(node.metadata.entityKind)?.toLowerCase() ?? '';
35
+ if (/\b(device|product|appliance|controller|hardware|phone|tv|printer|router|sensor|hub|bridge)\b/.test(entityKind))
36
+ return true;
37
+ if (readString(node.metadata.model))
38
+ return true;
39
+ const text = `${node.title} ${node.summary ?? ''} ${node.aliases.join(' ')}`;
40
+ return /\b[A-Z]{2,}[-_ ]?[0-9][A-Z0-9._-]{2,}\b/.test(text);
41
+ }
42
+ function uniqueNodes(nodes) {
43
+ const seen = new Set();
44
+ const result = [];
45
+ for (const node of nodes) {
46
+ if (!node || seen.has(node.id))
47
+ continue;
48
+ seen.add(node.id);
49
+ result.push(node);
50
+ }
51
+ return result;
52
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"self-improvement-promotion.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/self-improvement-promotion.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAEV,mBAAmB,EACnB,6BAA6B,EAE9B,MAAM,aAAa,CAAC;AAiBrB,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3I;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,EACpC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,mBAAmB,EACxB,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,IAAI,EAAE,6BAA6B,EACnC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAwBjB"}
1
+ {"version":3,"file":"self-improvement-promotion.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/self-improvement-promotion.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAEV,mBAAmB,EACnB,6BAA6B,EAE9B,MAAM,aAAa,CAAC;AAmBrB,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3I;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,EACpC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,mBAAmB,EACxB,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,IAAI,EAAE,6BAA6B,EACnC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAwBjB"}
@@ -1,8 +1,10 @@
1
1
  import { yieldEvery, yieldToEventLoop } from '../cooperative.js';
2
2
  import { getKnowledgeSpaceId } from '../spaces.js';
3
3
  import { hasConcreteFeatureSignal, isLowValueFeatureOrSpecText } from './fact-quality.js';
4
+ import { deriveRepairProfileFacts } from './repair-profile.js';
4
5
  import { updateRefinementTask } from './self-improvement-tasks.js';
5
6
  import { withTimeout } from './timeouts.js';
7
+ import { canonicalRepairSubjectNodes, repairSubjectHints } from './repair-subjects.js';
6
8
  import { clampText, normalizeWhitespace, readRecord, readString, semanticHash, semanticMetadata, semanticSlug, sourceSemanticText, splitSentences, uniqueStrings, } from './utils.js';
7
9
  export async function promoteRepairSources(context, spaceId, gap, sourceIds, task, deadlineAt) {
8
10
  if (context.enrichSource) {
@@ -37,74 +39,112 @@ async function promoteRepairEvidenceFacts(store, spaceId, gap, sourceIds) {
37
39
  continue;
38
40
  const extraction = store.getExtractionBySourceId(source.id);
39
41
  const authority = sourceAuthority(source);
42
+ const text = sourceSemanticText(source, extraction);
43
+ const profileFacts = deriveRepairProfileFacts({
44
+ query: gap.title,
45
+ source,
46
+ text,
47
+ });
48
+ for (const profileFact of profileFacts) {
49
+ promoted += await upsertPromotedRepairFact({
50
+ store,
51
+ spaceId,
52
+ gap,
53
+ source,
54
+ subjects,
55
+ authority,
56
+ title: profileFact.title,
57
+ summary: profileFact.summary,
58
+ classification: profileFact,
59
+ evidence: profileFact.evidence,
60
+ });
61
+ }
40
62
  const sentences = selectRepairFactSentences({
41
63
  query: gap.title,
42
64
  source,
43
- text: sourceSemanticText(source, extraction),
65
+ text,
44
66
  });
45
- for (const [index, sentence] of sentences.entries()) {
67
+ for (const sentence of sentences) {
46
68
  const classification = classifyRepairFact(sentence);
47
- const fact = await store.upsertNode({
48
- id: `sem-fact-${semanticHash(spaceId, source.id, gap.id, classification.title, sentence)}`,
49
- kind: 'fact',
50
- slug: semanticSlug(`${spaceId}-${classification.title}-${source.id}-${index}`),
69
+ promoted += await upsertPromotedRepairFact({
70
+ store,
71
+ spaceId,
72
+ gap,
73
+ source,
74
+ subjects,
75
+ authority,
51
76
  title: classification.title,
52
77
  summary: sentence,
53
- aliases: classification.aliases,
54
- status: 'active',
55
- confidence: authority === 'official-vendor' ? 88 : 76,
56
- sourceId: source.id,
57
- metadata: semanticMetadata(spaceId, {
58
- semanticKind: 'fact',
59
- factKind: classification.kind,
60
- value: classification.value,
61
- evidence: sentence,
62
- labels: classification.labels,
63
- sourceId: source.id,
64
- gapId: gap.id,
65
- linkedObjectIds: subjects.map((subject) => subject.id),
66
- extractor: 'repair-promotion',
67
- sourceAuthority: authority,
68
- sourceDiscovery: readRecord(source.metadata.sourceDiscovery),
69
- }),
70
- });
71
- await store.upsertEdge({
72
- fromKind: 'source',
73
- fromId: source.id,
74
- toKind: 'node',
75
- toId: fact.id,
76
- relation: 'supports_fact',
77
- weight: authority === 'official-vendor' ? 0.95 : 0.84,
78
- metadata: semanticMetadata(spaceId, {
79
- linkedBy: 'semantic-gap-repair',
80
- gapId: gap.id,
81
- }),
78
+ classification,
79
+ evidence: sentence,
82
80
  });
83
- for (const subject of subjects) {
84
- await store.upsertEdge({
85
- fromKind: 'node',
86
- fromId: fact.id,
87
- toKind: 'node',
88
- toId: subject.id,
89
- relation: 'describes',
90
- weight: authority === 'official-vendor' ? 0.94 : 0.82,
91
- metadata: semanticMetadata(spaceId, {
92
- linkedBy: 'semantic-gap-repair',
93
- repairedAt: Date.now(),
94
- sourceId: source.id,
95
- gapId: gap.id,
96
- }),
97
- });
98
- }
99
- promoted += 1;
100
81
  }
101
82
  }
102
83
  return promoted;
103
84
  }
85
+ async function upsertPromotedRepairFact(input) {
86
+ const fact = await input.store.upsertNode({
87
+ id: `sem-fact-${semanticHash(input.spaceId, input.source.id, input.gap.id, input.title, input.summary)}`,
88
+ kind: 'fact',
89
+ slug: semanticSlug(`${input.spaceId}-${input.title}-${input.source.id}`),
90
+ title: input.title,
91
+ summary: input.summary,
92
+ aliases: input.classification.aliases,
93
+ status: 'active',
94
+ confidence: input.authority === 'official-vendor' ? 90 : input.authority === 'vendor' ? 82 : 76,
95
+ sourceId: input.source.id,
96
+ metadata: semanticMetadata(input.spaceId, {
97
+ semanticKind: 'fact',
98
+ factKind: input.classification.kind,
99
+ value: input.classification.value,
100
+ evidence: input.evidence,
101
+ labels: input.classification.labels,
102
+ sourceId: input.source.id,
103
+ gapId: input.gap.id,
104
+ subject: input.subjects[0]?.title,
105
+ subjectIds: input.subjects.map((subject) => subject.id),
106
+ targetHints: repairSubjectHints(input.subjects),
107
+ linkedObjectIds: input.subjects.map((subject) => subject.id),
108
+ extractor: 'repair-promotion',
109
+ sourceAuthority: input.authority,
110
+ sourceDiscovery: readRecord(input.source.metadata.sourceDiscovery),
111
+ }),
112
+ });
113
+ await input.store.upsertEdge({
114
+ fromKind: 'source',
115
+ fromId: input.source.id,
116
+ toKind: 'node',
117
+ toId: fact.id,
118
+ relation: 'supports_fact',
119
+ weight: input.authority === 'official-vendor' ? 0.96 : 0.84,
120
+ metadata: semanticMetadata(input.spaceId, {
121
+ linkedBy: 'semantic-gap-repair',
122
+ gapId: input.gap.id,
123
+ }),
124
+ });
125
+ for (const subject of input.subjects) {
126
+ await input.store.upsertEdge({
127
+ fromKind: 'node',
128
+ fromId: fact.id,
129
+ toKind: 'node',
130
+ toId: subject.id,
131
+ relation: 'describes',
132
+ weight: input.authority === 'official-vendor' ? 0.95 : 0.82,
133
+ metadata: semanticMetadata(input.spaceId, {
134
+ linkedBy: 'semantic-gap-repair',
135
+ repairedAt: Date.now(),
136
+ sourceId: input.source.id,
137
+ gapId: input.gap.id,
138
+ }),
139
+ });
140
+ }
141
+ return 1;
142
+ }
104
143
  async function linkPromotedFactsToRepairSubjects(store, spaceId, gap, sourceIds) {
105
- const linkedObjectIds = readStringArray(gap.metadata.linkedObjectIds).filter((nodeId) => Boolean(store.getNode(nodeId)));
106
- if (linkedObjectIds.length === 0)
144
+ const subjects = linkedRepairSubjects(store, spaceId, gap);
145
+ if (subjects.length === 0)
107
146
  return;
147
+ const linkedObjectIds = subjects.map((subject) => subject.id);
108
148
  const edges = store.listEdges();
109
149
  const nodesById = new Map(store.listNodes(10_000).filter((node) => getKnowledgeSpaceId(node) === spaceId).map((node) => [node.id, node]));
110
150
  for (const sourceId of sourceIds) {
@@ -207,10 +247,35 @@ function repairIntentPatterns(query) {
207
247
  return patterns;
208
248
  }
209
249
  function linkedRepairSubjects(store, spaceId, gap) {
210
- return uniqueById(readStringArray(gap.metadata.linkedObjectIds)
211
- .map((id) => store.getNode(id))
250
+ const edges = store.listEdges();
251
+ const nodesById = new Map(store.listNodes(10_000)
252
+ .filter((node) => getKnowledgeSpaceId(node) === spaceId)
253
+ .map((node) => [node.id, node]));
254
+ const sourceIds = uniqueStrings([
255
+ gap.sourceId,
256
+ ...readStringArray(gap.metadata.sourceIds),
257
+ ...edges
258
+ .filter((edge) => edge.toKind === 'node' && edge.toId === gap.id && edge.fromKind === 'source')
259
+ .map((edge) => edge.fromId),
260
+ ]);
261
+ return canonicalRepairSubjectNodes({
262
+ text: `${gap.title} ${gap.summary ?? ''}`,
263
+ nodes: [
264
+ ...readStringArray(gap.metadata.linkedObjectIds).map((id) => nodesById.get(id)),
265
+ ...edges
266
+ .filter((edge) => edge.fromKind === 'node' && edge.toKind === 'node' && edge.toId === gap.id)
267
+ .map((edge) => nodesById.get(edge.fromId)),
268
+ ...sourceIds.flatMap((sourceId) => linkedObjectsForSource(sourceId, edges, nodesById)),
269
+ ],
270
+ });
271
+ }
272
+ function linkedObjectsForSource(sourceId, edges, nodesById) {
273
+ return uniqueById(edges
274
+ .filter((edge) => edge.fromKind === 'source' && edge.fromId === sourceId && edge.toKind === 'node')
275
+ .map((edge) => nodesById.get(edge.toId))
212
276
  .filter((node) => Boolean(node))
213
- .filter((node) => getKnowledgeSpaceId(node) === spaceId && node.status !== 'stale'));
277
+ .filter((node) => node.status !== 'stale')
278
+ .filter((node) => node.metadata.semanticKind !== 'fact' && node.metadata.semanticKind !== 'gap' && node.kind !== 'wiki_page'));
214
279
  }
215
280
  function factsForSource(sourceId, edges, nodesById) {
216
281
  return uniqueById(edges
@@ -1 +1 @@
1
- {"version":3,"file":"self-improvement.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/self-improvement.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAOlD,OAAO,KAAK,EACV,4BAA4B,EAC5B,iCAAiC,EACjC,kCAAkC,EACnC,MAAM,YAAY,CAAC;AAapB,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,4BAA4B,GAAG,IAAI,CAAC;IAC3D,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3I;AAUD,wBAAsB,mCAAmC,CACvD,OAAO,EAAE,kBAAkB,EAC3B,KAAK,GAAE,iCAAsC,GAC5C,OAAO,CAAC,kCAAkC,CAAC,CA8N7C"}
1
+ {"version":3,"file":"self-improvement.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/self-improvement.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAOlD,OAAO,KAAK,EACV,4BAA4B,EAC5B,iCAAiC,EACjC,kCAAkC,EACnC,MAAM,YAAY,CAAC;AAcpB,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,4BAA4B,GAAG,IAAI,CAAC;IAC3D,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3I;AAUD,wBAAsB,mCAAmC,CACvD,OAAO,EAAE,kBAAkB,EAC3B,KAAK,GAAE,iCAAsC,GAC5C,OAAO,CAAC,kCAAkC,CAAC,CA+N7C"}
@@ -6,6 +6,7 @@ import { readRecord, readString, semanticHash, semanticMetadata, semanticSlug, s
6
6
  import { withTimeout } from './timeouts.js';
7
7
  import { updateRefinementTask, upsertRefinementTaskForGap } from './self-improvement-tasks.js';
8
8
  import { promoteRepairSources } from './self-improvement-promotion.js';
9
+ import { canonicalRepairSubjectNodes, repairSubjectIds } from './repair-subjects.js';
9
10
  const RETRY_DELAY_MS = 6 * 60 * 60 * 1000;
10
11
  const DEFAULT_REFINEMENT_LIMIT = 12;
11
12
  const MAX_REFINEMENT_LIMIT = 24;
@@ -23,11 +24,12 @@ export async function runKnowledgeSemanticSelfImprovement(context, input = {}) {
23
24
  const createdGaps = await discoverIntrinsicGaps(context.store, spaceId, sourceIdFilter);
24
25
  const candidates = collectCandidateGaps(context.store, spaceId, sourceIdFilter, gapIdFilter);
25
26
  const requestedLimit = Math.max(1, input.limit ?? DEFAULT_REFINEMENT_LIMIT);
26
- const effectiveLimit = Math.min(requestedLimit, MAX_REFINEMENT_LIMIT);
27
+ const cappedLimit = Math.min(requestedLimit, MAX_REFINEMENT_LIMIT);
27
28
  const maxRunMs = Math.min(MAX_REFINEMENT_RUN_MS, Math.max(5_000, input.maxRunMs ?? DEFAULT_REFINEMENT_RUN_MS));
28
29
  const startedAt = Date.now();
29
- const gaps = candidates.slice(0, effectiveLimit);
30
- let truncated = candidates.length > gaps.length || requestedLimit > effectiveLimit;
30
+ const gaps = candidates.slice(0, cappedLimit);
31
+ const effectiveLimit = gaps.length;
32
+ let truncated = candidates.length > gaps.length || requestedLimit > cappedLimit;
31
33
  let budgetExhausted = false;
32
34
  let processedGaps = 0;
33
35
  let repairableGaps = 0;
@@ -385,14 +387,17 @@ function buildGapContext(store, spaceId, gap) {
385
387
  .map((edge) => edge.fromId),
386
388
  ]);
387
389
  const directSources = sourceIds.map((id) => sourcesById.get(id)).filter((source) => Boolean(source));
388
- const linkedObjects = uniqueById([
389
- ...readStringArray(gap.metadata.linkedObjectIds).map((id) => nodesById.get(id)).filter((node) => Boolean(node)),
390
- ...sourceIds.flatMap((sourceId) => linkedObjectsForSource(sourceId, edges, nodesById)),
391
- ...edges
392
- .filter((edge) => edge.fromKind === 'node' && edge.toKind === 'node' && edge.toId === gap.id)
393
- .map((edge) => nodesById.get(edge.fromId))
394
- .filter((node) => Boolean(node)),
395
- ]);
390
+ const linkedObjects = canonicalRepairSubjectNodes({
391
+ text: `${gap.title} ${gap.summary ?? ''}`,
392
+ nodes: [
393
+ ...readStringArray(gap.metadata.linkedObjectIds).map((id) => nodesById.get(id)).filter((node) => Boolean(node)),
394
+ ...sourceIds.flatMap((sourceId) => linkedObjectsForSource(sourceId, edges, nodesById)),
395
+ ...edges
396
+ .filter((edge) => edge.fromKind === 'node' && edge.toKind === 'node' && edge.toId === gap.id)
397
+ .map((edge) => nodesById.get(edge.fromId))
398
+ .filter((node) => Boolean(node)),
399
+ ],
400
+ });
396
401
  const sources = uniqueById([
397
402
  ...directSources,
398
403
  ...linkedObjects.flatMap((object) => sourcesForObject(object.id, edges, sourcesById)),
@@ -502,8 +507,7 @@ async function markGapRepairAttempt(store, gap, spaceId, details) {
502
507
  }
503
508
  async function linkRepairSources(store, spaceId, gap, sourceIds, query) {
504
509
  let linked = 0;
505
- const linkedObjectIds = readStringArray(gap.metadata.linkedObjectIds)
506
- .filter((nodeId) => Boolean(store.getNode(nodeId)));
510
+ const linkedObjectIds = repairSubjectIdsForGap(store, spaceId, gap);
507
511
  for (const sourceId of sourceIds) {
508
512
  if (!store.getSource(sourceId))
509
513
  continue;
@@ -538,6 +542,29 @@ async function linkRepairSources(store, spaceId, gap, sourceIds, query) {
538
542
  }
539
543
  return linked;
540
544
  }
545
+ function repairSubjectIdsForGap(store, spaceId, gap) {
546
+ const edges = store.listEdges();
547
+ const nodesById = new Map(store.listNodes(10_000)
548
+ .filter((node) => getKnowledgeSpaceId(node) === spaceId)
549
+ .map((node) => [node.id, node]));
550
+ const sourceIds = uniqueStrings([
551
+ gap.sourceId,
552
+ ...readStringArray(gap.metadata.sourceIds),
553
+ ...edges
554
+ .filter((edge) => edge.toKind === 'node' && edge.toId === gap.id && edge.fromKind === 'source')
555
+ .map((edge) => edge.fromId),
556
+ ]);
557
+ return repairSubjectIds({
558
+ text: `${gap.title} ${gap.summary ?? ''}`,
559
+ nodes: [
560
+ ...readStringArray(gap.metadata.linkedObjectIds).map((nodeId) => nodesById.get(nodeId)),
561
+ ...edges
562
+ .filter((edge) => edge.fromKind === 'node' && edge.toKind === 'node' && edge.toId === gap.id)
563
+ .map((edge) => nodesById.get(edge.fromId)),
564
+ ...sourceIds.flatMap((sourceId) => linkedObjectsForSource(sourceId, edges, nodesById)),
565
+ ],
566
+ });
567
+ }
541
568
  function isBudgetError(message) {
542
569
  return /\b(timeout|timed out|budget|deadline|exceeded)\b/i.test(message);
543
570
  }
@@ -287,7 +287,7 @@ function activeSelfImproveResult(input) {
287
287
  ...emptySelfImproveResult(),
288
288
  skippedGaps: 1,
289
289
  requestedLimit,
290
- effectiveLimit: requestedLimit,
290
+ effectiveLimit: 0,
291
291
  truncated: true,
292
292
  budgetExhausted: true,
293
293
  };
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
- let version = '0.28.16';
3
+ let version = '0.28.18';
4
4
  try {
5
5
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', '..', 'package.json'), 'utf-8'));
6
6
  version = pkg.version ?? version;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-sdk",
3
- "version": "0.28.16",
3
+ "version": "0.28.18",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/mgd34msu/goodvibes-sdk.git"
@@ -13,6 +13,7 @@
13
13
  "@ast-grep/napi": "^0.42.0",
14
14
  "@aws/bedrock-token-generator": "^1.1.0",
15
15
  "@mozilla/readability": "^0.6.0",
16
+ "@smithy/util-retry": "4.3.6",
16
17
  "bash-language-server": "file:vendor/bash-language-server",
17
18
  "bplist-parser": "^0.3.2",
18
19
  "cloudflare": "5.2.0",