@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.
- package/dist/_internal/contracts/artifacts/operator-contract.json +70 -1
- package/dist/_internal/contracts/generated/foundation-metadata.d.ts +1 -1
- package/dist/_internal/contracts/generated/foundation-metadata.js +1 -1
- package/dist/_internal/contracts/generated/operator-contract.d.ts.map +1 -1
- package/dist/_internal/contracts/generated/operator-contract.js +70 -1
- package/dist/_internal/platform/artifacts/store.d.ts +2 -0
- package/dist/_internal/platform/artifacts/store.d.ts.map +1 -1
- package/dist/_internal/platform/artifacts/store.js +20 -0
- package/dist/_internal/platform/control-plane/method-catalog-homegraph.d.ts.map +1 -1
- package/dist/_internal/platform/control-plane/method-catalog-homegraph.js +9 -0
- package/dist/_internal/platform/control-plane/operator-contract-schemas-homegraph.d.ts.map +1 -1
- package/dist/_internal/platform/control-plane/operator-contract-schemas-homegraph.js +15 -1
- package/dist/_internal/platform/knowledge/home-graph/ask-page-refresh.d.ts +11 -0
- package/dist/_internal/platform/knowledge/home-graph/ask-page-refresh.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/home-graph/ask-page-refresh.js +31 -0
- package/dist/_internal/platform/knowledge/home-graph/ask.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/ask.js +24 -1
- package/dist/_internal/platform/knowledge/home-graph/generated-pages.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/generated-pages.js +92 -20
- package/dist/_internal/platform/knowledge/home-graph/map-view.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/map-view.js +14 -0
- package/dist/_internal/platform/knowledge/home-graph/pages.d.ts +3 -1
- package/dist/_internal/platform/knowledge/home-graph/pages.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/pages.js +104 -1
- package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts +0 -1
- package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/rendering.js +0 -12
- package/dist/_internal/platform/knowledge/home-graph/reset.d.ts +2 -1
- package/dist/_internal/platform/knowledge/home-graph/reset.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/reset.js +35 -2
- package/dist/_internal/platform/knowledge/home-graph/search.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/search.js +2 -18
- package/dist/_internal/platform/knowledge/home-graph/service.d.ts +1 -1
- package/dist/_internal/platform/knowledge/home-graph/service.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/service.js +17 -5
- package/dist/_internal/platform/knowledge/home-graph/source-links.d.ts +3 -0
- package/dist/_internal/platform/knowledge/home-graph/source-links.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/home-graph/source-links.js +30 -0
- package/dist/_internal/platform/knowledge/home-graph/state.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/state.js +43 -1
- package/dist/_internal/platform/knowledge/home-graph/types.d.ts +39 -1
- package/dist/_internal/platform/knowledge/home-graph/types.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/ingest-compile.js +1 -1
- package/dist/_internal/platform/knowledge/pdf-extractor.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/pdf-extractor.js +8 -3
- package/dist/_internal/platform/knowledge/semantic/answer-fallback.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/semantic/answer-fallback.js +21 -16
- package/dist/_internal/platform/knowledge/semantic/answer-source-ranking.d.ts +7 -0
- package/dist/_internal/platform/knowledge/semantic/answer-source-ranking.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/semantic/answer-source-ranking.js +57 -0
- package/dist/_internal/platform/knowledge/semantic/answer.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/semantic/answer.js +76 -9
- package/dist/_internal/platform/knowledge/semantic/fact-quality.d.ts +0 -1
- package/dist/_internal/platform/knowledge/semantic/fact-quality.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/semantic/fact-quality.js +18 -18
- package/dist/_internal/platform/knowledge/semantic/homeassistant-scope.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/semantic/homeassistant-scope.js +63 -5
- package/dist/_internal/platform/knowledge/semantic/repair-profile.d.ts +16 -0
- package/dist/_internal/platform/knowledge/semantic/repair-profile.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/semantic/repair-profile.js +152 -0
- package/dist/_internal/platform/knowledge/semantic/repair-subjects.d.ts +16 -0
- package/dist/_internal/platform/knowledge/semantic/repair-subjects.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/semantic/repair-subjects.js +52 -0
- package/dist/_internal/platform/knowledge/semantic/self-improvement-promotion.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/semantic/self-improvement-promotion.js +122 -57
- package/dist/_internal/platform/knowledge/semantic/self-improvement.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/semantic/self-improvement.js +40 -13
- package/dist/_internal/platform/knowledge/semantic/service.js +1 -1
- package/dist/_internal/platform/version.js +1 -1
- 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;
|
|
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
|
|
65
|
+
text,
|
|
44
66
|
});
|
|
45
|
-
for (const
|
|
67
|
+
for (const sentence of sentences) {
|
|
46
68
|
const classification = classifyRepairFact(sentence);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
54
|
-
|
|
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
|
|
106
|
-
if (
|
|
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
|
-
|
|
211
|
-
|
|
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) =>
|
|
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;
|
|
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
|
|
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,
|
|
30
|
-
|
|
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 =
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
.
|
|
393
|
-
|
|
394
|
-
|
|
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 =
|
|
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
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
let version = '0.28.
|
|
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.
|
|
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",
|