@pellux/goodvibes-sdk 0.27.9 → 0.27.11
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 +287 -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 +287 -1
- package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.d.ts +1 -1
- package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.d.ts.map +1 -1
- package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.js +23 -0
- package/dist/_internal/platform/knowledge/home-graph/service.d.ts +1 -0
- package/dist/_internal/platform/knowledge/home-graph/service.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/service.js +18 -1
- package/dist/_internal/platform/knowledge/home-graph/types.d.ts +3 -1
- package/dist/_internal/platform/knowledge/home-graph/types.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/types.js +1 -0
- package/dist/_internal/platform/knowledge/index.d.ts +2 -2
- package/dist/_internal/platform/knowledge/index.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/index.js +1 -1
- package/dist/_internal/platform/knowledge/scheduling.d.ts +1 -0
- package/dist/_internal/platform/knowledge/scheduling.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/scheduling.js +17 -18
- package/dist/_internal/platform/knowledge/semantic/answer.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/semantic/answer.js +38 -6
- package/dist/_internal/platform/knowledge/semantic/fact-quality.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/semantic/fact-quality.js +11 -2
- package/dist/_internal/platform/knowledge/semantic/gap-repair.d.ts +32 -0
- package/dist/_internal/platform/knowledge/semantic/gap-repair.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/semantic/gap-repair.js +148 -0
- package/dist/_internal/platform/knowledge/semantic/index.d.ts +4 -1
- package/dist/_internal/platform/knowledge/semantic/index.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/semantic/index.js +2 -0
- package/dist/_internal/platform/knowledge/semantic/self-improvement.d.ts +10 -0
- package/dist/_internal/platform/knowledge/semantic/self-improvement.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/semantic/self-improvement.js +491 -0
- package/dist/_internal/platform/knowledge/semantic/service.d.ts +9 -2
- package/dist/_internal/platform/knowledge/semantic/service.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/semantic/service.js +124 -2
- package/dist/_internal/platform/knowledge/semantic/types.d.ts +38 -0
- package/dist/_internal/platform/knowledge/semantic/types.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/service.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/service.js +17 -1
- package/dist/_internal/platform/knowledge/types.d.ts +1 -1
- package/dist/_internal/platform/knowledge/types.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/services.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/services.js +5 -1
- package/dist/_internal/platform/version.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduling.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/knowledge/scheduling.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8E,KAAK,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAC3J,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAEvH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAGlE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,CACpB,EAAE,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,EAC1H,SAAS,CAAC,EAAE,MAAM,KACf,IAAI,CAAC;IACV,QAAQ,CAAC,YAAY,EAAE,CACrB,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,EAChC,KAAK,EAAE;QAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KACvE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvC;AAED,qBAAa,wBAAwB;IAKvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgC;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoD;IACnF,OAAO,CAAC,oBAAoB,CAAS;gBAER,OAAO,EAAE,0BAA0B;
|
|
1
|
+
{"version":3,"file":"scheduling.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/knowledge/scheduling.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8E,KAAK,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAC3J,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAEvH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAGlE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,CACpB,EAAE,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,EAC1H,SAAS,CAAC,EAAE,MAAM,KACf,IAAI,CAAC;IACV,QAAQ,CAAC,YAAY,EAAE,CACrB,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,EAChC,KAAK,EAAE;QAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KACvE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvC;AAED,qBAAa,wBAAwB;IAKvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgC;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoD;IACnF,OAAO,CAAC,oBAAoB,CAAS;gBAER,OAAO,EAAE,0BAA0B;IAgBhE,QAAQ,IAAI,SAAS,kBAAkB,EAAE;IAIzC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IAIvC,YAAY,CAAC,KAAK,EAAE;QACxB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,QAAQ,EAAE,4BAA4B,CAAC;QAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC7C,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAqB9B,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAM5C,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;IAiB/F,WAAW,CAAC,KAAK,SAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,qBAAqB,EAAE;IAIpE,MAAM,CACV,EAAE,EAAE,MAAM,EACV,KAAK,GAAE;QACL,QAAQ,CAAC,IAAI,CAAC,EAAE,gBAAgB,CAAC;QACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;KACpB,GACL,OAAO,CAAC,qBAAqB,CAAC;IA6BjC,OAAO,IAAI,IAAI;YAOD,mBAAmB;YAUnB,uBAAuB;IAiBrC,OAAO,CAAC,kBAAkB;YAQZ,kBAAkB;YA6BlB,eAAe;YAmBf,aAAa;CA0D5B"}
|
|
@@ -16,6 +16,7 @@ export class KnowledgeScheduleService {
|
|
|
16
16
|
{ id: 'knowledge-sync-browser-history', kind: 'sync-browser-history', title: 'Sync Browser History', description: 'Index local browser history and bookmarks as metadata-first structured knowledge.', defaultMode: 'background', metadata: { category: 'ingest', localOnly: true } },
|
|
17
17
|
{ id: 'knowledge-rebuild-projections', kind: 'rebuild-projections', title: 'Rebuild Projections', description: 'Render and materialize the major derived markdown/wiki projections.', defaultMode: 'background', metadata: { category: 'projection' } },
|
|
18
18
|
{ id: 'knowledge-semantic-enrichment', kind: 'semantic-enrichment', title: 'Semantic Enrichment', description: 'Extract durable facts, entities, wiki pages, and gaps from indexed sources.', defaultMode: 'background', metadata: { category: 'semantic' } },
|
|
19
|
+
{ id: 'knowledge-semantic-self-improvement', kind: 'semantic-self-improvement', title: 'Semantic Self-Improvement', description: 'Classify semantic gaps and repair eligible concrete subjects with corroborated source-backed ingest.', defaultMode: 'background', metadata: { category: 'semantic' } },
|
|
19
20
|
{ id: 'knowledge-light-consolidation', kind: 'light-consolidation', title: 'Light Consolidation', description: 'Score recent usage, refresh candidate promotions, and write a deterministic consolidation report.', defaultMode: 'background', metadata: { category: 'consolidation' } },
|
|
20
21
|
{ id: 'knowledge-deep-consolidation', kind: 'deep-consolidation', title: 'Deep Consolidation', description: 'Run the full consolidation loop, including high-confidence memory promotion and deterministic reporting.', defaultMode: 'background', metadata: { category: 'consolidation' } },
|
|
21
22
|
];
|
|
@@ -113,26 +114,24 @@ export class KnowledgeScheduleService {
|
|
|
113
114
|
return;
|
|
114
115
|
this.schedulesInitialized = true;
|
|
115
116
|
await this.context.store.init();
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
label: 'Daily Light Consolidation',
|
|
120
|
-
enabled: true,
|
|
121
|
-
schedule: normalizeEverySchedule('24h'),
|
|
122
|
-
nextRunAt: getNextAutomationOccurrence(normalizeEverySchedule('24h'), Date.now(), 'knowledge-light-consolidation'),
|
|
123
|
-
metadata: { bootstrap: true },
|
|
124
|
-
});
|
|
125
|
-
await this.context.store.upsertSchedule({
|
|
126
|
-
jobId: 'knowledge-deep-consolidation',
|
|
127
|
-
label: 'Weekly Deep Consolidation',
|
|
128
|
-
enabled: true,
|
|
129
|
-
schedule: normalizeCronSchedule('15 4 * * 0'),
|
|
130
|
-
nextRunAt: getNextAutomationOccurrence(normalizeCronSchedule('15 4 * * 0'), Date.now(), 'knowledge-deep-consolidation'),
|
|
131
|
-
metadata: { bootstrap: true },
|
|
132
|
-
});
|
|
133
|
-
}
|
|
117
|
+
await this.ensureBootstrapSchedule('knowledge-light-consolidation', 'Daily Light Consolidation', normalizeEverySchedule('24h'));
|
|
118
|
+
await this.ensureBootstrapSchedule('knowledge-deep-consolidation', 'Weekly Deep Consolidation', normalizeCronSchedule('15 4 * * 0'));
|
|
119
|
+
await this.ensureBootstrapSchedule('knowledge-semantic-self-improvement', 'Continuous Semantic Self-Improvement', normalizeEverySchedule('6h'));
|
|
134
120
|
await this.reconcileSchedules();
|
|
135
121
|
}
|
|
122
|
+
async ensureBootstrapSchedule(jobId, label, schedule) {
|
|
123
|
+
const existing = this.context.store.listSchedules(10_000).find((entry) => entry.jobId === jobId && entry.metadata.bootstrap === true);
|
|
124
|
+
if (existing)
|
|
125
|
+
return;
|
|
126
|
+
await this.context.store.upsertSchedule({
|
|
127
|
+
jobId,
|
|
128
|
+
label,
|
|
129
|
+
enabled: true,
|
|
130
|
+
schedule,
|
|
131
|
+
nextRunAt: getNextAutomationOccurrence(schedule, Date.now(), jobId),
|
|
132
|
+
metadata: { bootstrap: true },
|
|
133
|
+
});
|
|
134
|
+
}
|
|
136
135
|
clearScheduleTimer(id) {
|
|
137
136
|
const timer = this.scheduleTimers.get(id);
|
|
138
137
|
if (timer) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"answer.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/answer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAOlD,OAAO,KAAK,EACV,4BAA4B,EAC5B,6BAA6B,EAE7B,oBAAoB,EAErB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"answer.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/answer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAOlD,OAAO,KAAK,EACV,4BAA4B,EAC5B,6BAA6B,EAE7B,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAsBpB,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;CAC5C;AAsCD,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,sBAAsB,EAC/B,KAAK,EAAE,4BAA4B,GAClC,OAAO,CAAC,6BAA6B,CAAC,CAuDxC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
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';
|
|
2
|
+
import { MAX_ANSWER_EVIDENCE_CHARS, clampText, normalizeWhitespace, readRecord, readString, scoreSemanticText, semanticHash, semanticMetadata, sourceSemanticText, splitSentences, tokenizeSemanticQuery, uniqueStrings, } from './utils.js';
|
|
3
3
|
import { hasConcreteFeatureSignal, isLowValueFeatureOrSpecText, isSemanticAnswerLinkedObject, semanticFactText, } from './fact-quality.js';
|
|
4
4
|
const GENERIC_ANSWER_INTENT_TOKENS = new Set([
|
|
5
5
|
'capabilities',
|
|
@@ -58,7 +58,8 @@ export async function answerKnowledgeQuery(context, input) {
|
|
|
58
58
|
.filter(isSemanticAnswerLinkedObject)
|
|
59
59
|
.slice(0, 24);
|
|
60
60
|
const gaps = await persistAnswerGaps(context.store, spaceId, input.query, llmAnswer?.gaps ?? []);
|
|
61
|
-
const
|
|
61
|
+
const featureIntent = hasFeatureIntentForQuery(input.query);
|
|
62
|
+
const text = cleanSynthesizedAnswer(llmAnswer?.answer?.trim() || renderFallbackAnswer(input.query, mode, evidence), featureIntent);
|
|
62
63
|
return {
|
|
63
64
|
ok: true,
|
|
64
65
|
spaceId,
|
|
@@ -172,7 +173,8 @@ async function synthesizeAnswer(llm, query, mode, evidence) {
|
|
|
172
173
|
'You answer questions from a GoodVibes self-improving knowledge wiki.',
|
|
173
174
|
'Use only the supplied evidence. Synthesize the answer for the user intent rather than dumping snippets.',
|
|
174
175
|
'If evidence is insufficient, say what is missing. Prefer concrete features, specs, procedures, and relationships.',
|
|
175
|
-
'For feature or specification questions, ignore manual boilerplate about accessories, cable recommendations, button maps, batteries, cleaning, servicing, safety, and future product changes unless the user asks about those topics.',
|
|
176
|
+
'For feature or specification questions, ignore manual boilerplate about accessories, cable recommendations, USB/HDMI physical-fit guidance, button maps, remote aiming instructions, batteries, cleaning, servicing, safety, furniture, wall mounting, and future product changes unless the user asks about those topics.',
|
|
177
|
+
'Do not mention future features, specifications changing without notice, cable fit, USB extension cables, remote sensor aiming, service personnel, or child-safety/furniture/platform guidance in a feature/spec answer.',
|
|
176
178
|
'Return only JSON with answer, confidence, usedSourceIds, usedNodeIds, and optional gaps.',
|
|
177
179
|
].join(' '),
|
|
178
180
|
prompt: JSON.stringify({
|
|
@@ -277,6 +279,10 @@ function isLowValueFactForQuery(tokens, intent, fact) {
|
|
|
277
279
|
function hasFeatureIntent(intent) {
|
|
278
280
|
return intent.has('feature') || intent.has('capability') || intent.has('specification') || intent.has('compatibility');
|
|
279
281
|
}
|
|
282
|
+
function hasFeatureIntentForQuery(query) {
|
|
283
|
+
const intent = factIntent(tokenizeSemanticQuery(query));
|
|
284
|
+
return Boolean(intent && hasFeatureIntent(intent));
|
|
285
|
+
}
|
|
280
286
|
function compareFactQuality(left, right) {
|
|
281
287
|
return factQuality(right) - factQuality(left) || left.title.localeCompare(right.title);
|
|
282
288
|
}
|
|
@@ -368,6 +374,10 @@ function selectEvidenceExcerpt(query, text, facts) {
|
|
|
368
374
|
}
|
|
369
375
|
function evidenceWindows(text, tokens) {
|
|
370
376
|
const normalized = normalizeWhitespace(text);
|
|
377
|
+
const sentences = splitSentences(normalized, 420);
|
|
378
|
+
const sentenceMatches = sentences.filter((sentence) => scoreSemanticText(sentence, tokens) > 0);
|
|
379
|
+
if (sentenceMatches.length > 0)
|
|
380
|
+
return uniqueStrings(sentenceMatches).slice(0, 12);
|
|
371
381
|
const lower = normalized.toLowerCase();
|
|
372
382
|
const windows = [];
|
|
373
383
|
for (const token of tokens) {
|
|
@@ -376,12 +386,34 @@ function evidenceWindows(text, tokens) {
|
|
|
376
386
|
const index = lower.indexOf(token);
|
|
377
387
|
if (index < 0)
|
|
378
388
|
continue;
|
|
379
|
-
const start = Math.max(0, index -
|
|
380
|
-
const
|
|
381
|
-
|
|
389
|
+
const start = Math.max(0, normalized.lastIndexOf('.', index - 1) + 1, index - 160);
|
|
390
|
+
const nextPeriod = normalized.indexOf('.', index + token.length);
|
|
391
|
+
const end = nextPeriod >= 0 ? Math.min(normalized.length, nextPeriod + 1) : Math.min(normalized.length, index + 360);
|
|
392
|
+
windows.push(`${start > 0 ? '...' : ''}${normalized.slice(start, end).trim()}${end < normalized.length ? '...' : ''}`);
|
|
382
393
|
}
|
|
383
394
|
return uniqueStrings(windows);
|
|
384
395
|
}
|
|
396
|
+
function cleanSynthesizedAnswer(text, featureIntent) {
|
|
397
|
+
if (!featureIntent)
|
|
398
|
+
return text;
|
|
399
|
+
const blocks = text.split(/\n{2,}/).map((block) => block.trim()).filter(Boolean);
|
|
400
|
+
const cleanedBlocks = blocks.map((block) => {
|
|
401
|
+
const lines = block.split(/\n/).map((line) => line.trim()).filter(Boolean);
|
|
402
|
+
const kept = lines.filter((line) => !isLowValueFeatureOrSpecText(line));
|
|
403
|
+
if (kept.length > 0 && kept.length < lines.length)
|
|
404
|
+
return kept.join('\n');
|
|
405
|
+
if (lines.length > 1)
|
|
406
|
+
return kept.join('\n');
|
|
407
|
+
const sentences = splitSentences(block, 600);
|
|
408
|
+
const keptSentences = sentences.filter((sentence) => !isLowValueFeatureOrSpecText(sentence));
|
|
409
|
+
return keptSentences.length > 0 && keptSentences.length < sentences.length
|
|
410
|
+
? keptSentences.join(' ')
|
|
411
|
+
: block;
|
|
412
|
+
}).filter(Boolean);
|
|
413
|
+
return cleanedBlocks.length > 0
|
|
414
|
+
? cleanedBlocks.join('\n\n')
|
|
415
|
+
: 'The available evidence did not contain source-backed feature or specification details after filtering manual boilerplate.';
|
|
416
|
+
}
|
|
385
417
|
function expandQueryTokens(tokens) {
|
|
386
418
|
const expansions = {
|
|
387
419
|
capabilities: ['capability', 'feature', 'features', 'function', 'functions', 'supports', 'specifications'],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fact-quality.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/fact-quality.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAcvD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAK/E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAQlE;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"fact-quality.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/fact-quality.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAcvD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAK/E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAQlE;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAkDjE;AAWD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAa5E"}
|
|
@@ -49,9 +49,18 @@ export function isLowValueFeatureOrSpecText(text) {
|
|
|
49
49
|
if (/\b(fasten|screws?|stand|tip over|overturn|fall over|transporting|move the tv|moving the tv|oils?|lubricants?|cleaning cloth|dry cloth|power cord|electric shock|fire hazard|near water|ventilation|antenna grounding|qualified personnel|qualified service personnel|service personnel|customer service|servicing|repair is required|refer all servicing)\b/.test(lower)) {
|
|
50
50
|
return true;
|
|
51
51
|
}
|
|
52
|
+
if (/\b(platform|cabinet|furniture|supporting furniture|television placement|child safety|proper television placement|wall mount|mounting bracket|stand hole)\b/.test(lower)
|
|
53
|
+
&& /\b(support|supports|safe|safely|recommended|install|installation|place|placement|mount|mounting)\b/.test(lower)) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
52
56
|
if (/\b(infrared light|remote control sensor|point (the )?(magic )?remote|aim (the )?(magic )?remote)\b/.test(lower)) {
|
|
53
57
|
return true;
|
|
54
58
|
}
|
|
59
|
+
if (/\bmagic remote\b/.test(lower)
|
|
60
|
+
&& /\b(compatib|mr20ga|wireless module|bluetooth|separate purchase|sold separately|accessor(y|ies))\b/.test(lower)
|
|
61
|
+
&& !/\b(voice|microphone|cursor|pointer|gesture|motion control|universal control)\b/.test(lower)) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
55
64
|
if (/\bif (the )?device (doesn'?t|does not) support\b/.test(lower) && /\bmay not work properly\b/.test(lower)) {
|
|
56
65
|
return true;
|
|
57
66
|
}
|
|
@@ -61,7 +70,7 @@ export function isLowValueFeatureOrSpecText(text) {
|
|
|
61
70
|
if (/\bbatter(y|ies)\b/.test(lower) && /\b(remote|magic remote|button)\b/.test(lower)) {
|
|
62
71
|
return true;
|
|
63
72
|
}
|
|
64
|
-
if (/\b(bezel|less than \d+(?:\.\d+)?\s*(mm|cm|inches?)|does not fit|will not fit|fit your tv'?s usb port|usb port may not fit)\b/.test(lower)) {
|
|
73
|
+
if (/\b(bezel|less than \d+(?:\.\d+)?\s*(mm|cm|inches?)|does not fit|will not fit|fit your tv'?s usb port|usb port may not fit|usb flash drive does not fit|usb cable does not fit)\b/.test(lower)) {
|
|
65
74
|
return true;
|
|
66
75
|
}
|
|
67
76
|
if (/\b(warning|caution|risk|hazard|do not|never)\b/.test(lower) && !/\b(feature|supports?|hdmi|usb|hdr|remote|bluetooth)\b/.test(lower)) {
|
|
@@ -80,7 +89,7 @@ function isTruncatedManualFragment(value) {
|
|
|
80
89
|
return false;
|
|
81
90
|
}
|
|
82
91
|
export function hasConcreteFeatureSignal(text) {
|
|
83
|
-
return /\b(hdmi|usb|hdr|hdr10|dolby|vision|earc|arc|bluetooth|wi-?fi|ethernet|voice|remote|game|filmmaker|airplay|chromecast|resolution|4k|8k|refresh|ports?|speakers?|audio|display|screen|apps?|streaming|matter|energy monitoring|scheduling|sensor|battery|z-?wave|zigbee|thread|motion|temperature|humidity|camera|recording|lock|garage|local control|api|automation)\b/.test(text.toLowerCase());
|
|
92
|
+
return /\b(hdmi|usb|hdr|hdr10|dolby|vision|earc|arc|bluetooth|wi-?fi|wireless lan|ethernet|voice|remote|game|filmmaker|airplay|chromecast|resolution|4k|8k|refresh|ports?|speakers?|audio|display|screen|apps?|streaming|matter|energy monitoring|scheduling|sensor|battery|z-?wave|zigbee|thread|motion|temperature|humidity|camera|recording|lock|garage|local control|api|automation|atsc|ntsc|qam|tuner|broadcast|rs-?232c|external control)\b/.test(text.toLowerCase());
|
|
84
93
|
}
|
|
85
94
|
export function isUsefulHomeGraphPageFact(fact) {
|
|
86
95
|
if (fact.status === 'stale')
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { WebSearchRequest, WebSearchResponse } from '../../web-search/types.js';
|
|
2
|
+
import type { KnowledgeSourceType } from '../types.js';
|
|
3
|
+
import type { KnowledgeSemanticGapRepairer } from './types.js';
|
|
4
|
+
interface GapRepairSearch {
|
|
5
|
+
search(request: WebSearchRequest): Promise<WebSearchResponse>;
|
|
6
|
+
}
|
|
7
|
+
interface GapRepairIngest {
|
|
8
|
+
ingestUrl(input: {
|
|
9
|
+
readonly url: string;
|
|
10
|
+
readonly title?: string;
|
|
11
|
+
readonly tags?: readonly string[];
|
|
12
|
+
readonly sourceType?: KnowledgeSourceType;
|
|
13
|
+
readonly connectorId?: string;
|
|
14
|
+
readonly allowPrivateHosts?: boolean;
|
|
15
|
+
readonly metadata?: Record<string, unknown>;
|
|
16
|
+
}): Promise<{
|
|
17
|
+
readonly source: {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly status: string;
|
|
20
|
+
};
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
export interface WebGapRepairOptions {
|
|
24
|
+
readonly searchService: GapRepairSearch;
|
|
25
|
+
readonly ingestService: GapRepairIngest;
|
|
26
|
+
readonly maxResults?: number;
|
|
27
|
+
readonly minDistinctDomains?: number;
|
|
28
|
+
readonly maxIngest?: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function createWebKnowledgeGapRepairer(options: WebGapRepairOptions): KnowledgeSemanticGapRepairer;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=gap-repair.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gap-repair.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/gap-repair.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EAElB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EACV,4BAA4B,EAG7B,MAAM,YAAY,CAAC;AAGpB,UAAU,eAAe;IACvB,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC/D;AAED,UAAU,eAAe;IACvB,SAAS,CAAC,KAAK,EAAE;QACf,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,CAAC;QAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;QACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC7C,GAAG,OAAO,CAAC;QAAE,QAAQ,CAAC,MAAM,EAAE;YAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;CACpF;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,aAAa,EAAE,eAAe,CAAC;IACxC,QAAQ,CAAC,aAAa,EAAE,eAAe,CAAC;IACxC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,mBAAmB,GAAG,4BAA4B,CAExG"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { canonicalizeUri } from '../internal.js';
|
|
2
|
+
import { readString, scoreSemanticText, tokenizeSemanticQuery, uniqueStrings } from './utils.js';
|
|
3
|
+
export function createWebKnowledgeGapRepairer(options) {
|
|
4
|
+
return async (request) => repairKnowledgeGapsWithWeb(request, options);
|
|
5
|
+
}
|
|
6
|
+
async function repairKnowledgeGapsWithWeb(request, options) {
|
|
7
|
+
const query = buildGapRepairQuery(request);
|
|
8
|
+
if (!query) {
|
|
9
|
+
return {
|
|
10
|
+
searched: false,
|
|
11
|
+
ingestedSourceIds: [],
|
|
12
|
+
skippedUrls: [],
|
|
13
|
+
reason: 'No concrete subject was available for gap repair.',
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
let response;
|
|
17
|
+
try {
|
|
18
|
+
response = await options.searchService.search({
|
|
19
|
+
query,
|
|
20
|
+
maxResults: Math.max(2, Math.min(12, options.maxResults ?? 6)),
|
|
21
|
+
verbosity: 'snippets',
|
|
22
|
+
safeSearch: 'moderate',
|
|
23
|
+
metadata: {
|
|
24
|
+
purpose: 'knowledge-gap-repair',
|
|
25
|
+
knowledgeSpaceId: request.spaceId,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
return {
|
|
31
|
+
searched: true,
|
|
32
|
+
query,
|
|
33
|
+
ingestedSourceIds: [],
|
|
34
|
+
skippedUrls: [],
|
|
35
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const existing = new Set(request.sources.flatMap((source) => [
|
|
39
|
+
canonicalizeUri(source.canonicalUri ?? ''),
|
|
40
|
+
canonicalizeUri(source.sourceUri ?? ''),
|
|
41
|
+
].filter((value) => Boolean(value))));
|
|
42
|
+
const candidates = selectGapRepairCandidates(response.results, existing, options, query);
|
|
43
|
+
if (candidates.length < Math.max(2, options.minDistinctDomains ?? 2)) {
|
|
44
|
+
return {
|
|
45
|
+
searched: true,
|
|
46
|
+
query,
|
|
47
|
+
ingestedSourceIds: [],
|
|
48
|
+
skippedUrls: response.results.map((result) => result.url),
|
|
49
|
+
reason: 'Fewer than two distinct external sources were found for source-backed gap repair.',
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const ingestedSourceIds = [];
|
|
53
|
+
const skippedUrls = [];
|
|
54
|
+
for (const result of candidates.slice(0, Math.max(2, Math.min(4, options.maxIngest ?? 3)))) {
|
|
55
|
+
try {
|
|
56
|
+
const ingested = await options.ingestService.ingestUrl({
|
|
57
|
+
url: result.url,
|
|
58
|
+
...(result.title ? { title: result.title } : {}),
|
|
59
|
+
sourceType: 'url',
|
|
60
|
+
connectorId: 'semantic-gap-repair',
|
|
61
|
+
tags: ['semantic-gap-repair', 'gap-repair', ...gapRepairTags(request)],
|
|
62
|
+
metadata: {
|
|
63
|
+
knowledgeSpaceId: request.spaceId,
|
|
64
|
+
sourceDiscovery: {
|
|
65
|
+
purpose: 'semantic-gap-repair',
|
|
66
|
+
query,
|
|
67
|
+
providerId: response.providerId,
|
|
68
|
+
gapIds: request.gaps.map((gap) => gap.id),
|
|
69
|
+
gapQuestions: request.gaps.map((gap) => gap.title),
|
|
70
|
+
originalSourceIds: request.sources.map((source) => source.id),
|
|
71
|
+
linkedObjectIds: request.linkedObjects.map((node) => node.id),
|
|
72
|
+
searchedAt: Date.now(),
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
if (ingested.source.status === 'indexed' || ingested.source.status === 'pending') {
|
|
77
|
+
ingestedSourceIds.push(ingested.source.id);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
skippedUrls.push(result.url);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
searched: true,
|
|
86
|
+
query,
|
|
87
|
+
ingestedSourceIds,
|
|
88
|
+
skippedUrls,
|
|
89
|
+
...(ingestedSourceIds.length < 2 ? { reason: 'Gap repair searched but fewer than two sources were ingested.' } : {}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function buildGapRepairQuery(request) {
|
|
93
|
+
const subject = bestSubject(request);
|
|
94
|
+
if (!subject)
|
|
95
|
+
return null;
|
|
96
|
+
const gapTerms = uniqueStrings(request.gaps.flatMap((gap) => [
|
|
97
|
+
gap.title,
|
|
98
|
+
gap.summary,
|
|
99
|
+
readString(gap.metadata.reason),
|
|
100
|
+
])).join(' ');
|
|
101
|
+
return uniqueStrings([
|
|
102
|
+
subject,
|
|
103
|
+
gapTerms,
|
|
104
|
+
'official specifications features',
|
|
105
|
+
]).join(' ');
|
|
106
|
+
}
|
|
107
|
+
function bestSubject(request) {
|
|
108
|
+
const linked = request.linkedObjects[0];
|
|
109
|
+
const source = request.sources[0];
|
|
110
|
+
const metadata = linked?.metadata ?? {};
|
|
111
|
+
return uniqueStrings([
|
|
112
|
+
readString(metadata.manufacturer),
|
|
113
|
+
readString(metadata.model),
|
|
114
|
+
linked?.title,
|
|
115
|
+
source?.title,
|
|
116
|
+
]).join(' ') || null;
|
|
117
|
+
}
|
|
118
|
+
function selectGapRepairCandidates(results, existingCanonicalUris, options, query) {
|
|
119
|
+
const tokens = tokenizeSemanticQuery(query);
|
|
120
|
+
const byDomain = new Map();
|
|
121
|
+
for (const result of results) {
|
|
122
|
+
const canonical = canonicalizeUri(result.url);
|
|
123
|
+
if (!canonical || existingCanonicalUris.has(canonical))
|
|
124
|
+
continue;
|
|
125
|
+
const searchable = [result.title, result.snippet, result.url, result.domain].filter(Boolean).join(' ');
|
|
126
|
+
if (tokens.length > 0 && scoreSemanticText(searchable, tokens) === 0)
|
|
127
|
+
continue;
|
|
128
|
+
const domain = result.domain ?? safeDomain(result.url);
|
|
129
|
+
if (!domain || byDomain.has(domain))
|
|
130
|
+
continue;
|
|
131
|
+
byDomain.set(domain, result);
|
|
132
|
+
}
|
|
133
|
+
return [...byDomain.values()].slice(0, Math.max(2, Math.min(8, options.maxResults ?? 6)));
|
|
134
|
+
}
|
|
135
|
+
function safeDomain(url) {
|
|
136
|
+
try {
|
|
137
|
+
return new URL(url).hostname;
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function gapRepairTags(request) {
|
|
144
|
+
return uniqueStrings([
|
|
145
|
+
...request.linkedObjects.flatMap((node) => [node.kind, node.title]),
|
|
146
|
+
...request.sources.flatMap((source) => source.tags),
|
|
147
|
+
]).slice(0, 12);
|
|
148
|
+
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { createProviderBackedKnowledgeSemanticLlm } from './llm.js';
|
|
2
|
+
export { createWebKnowledgeGapRepairer } from './gap-repair.js';
|
|
2
3
|
export { KnowledgeSemanticService } from './service.js';
|
|
4
|
+
export { runKnowledgeSemanticSelfImprovement } from './self-improvement.js';
|
|
5
|
+
export type { WebGapRepairOptions } from './gap-repair.js';
|
|
3
6
|
export type { KnowledgeSemanticServiceOptions } from './service.js';
|
|
4
|
-
export type { KnowledgeSemanticAnswer, KnowledgeSemanticAnswerInput, KnowledgeSemanticAnswerResult, KnowledgeSemanticEnrichmentResult, KnowledgeSemanticExtraction, KnowledgeSemanticFactInput, KnowledgeSemanticFactKind, KnowledgeSemanticGapInput, KnowledgeSemanticLlm, KnowledgeSemanticLlmAnswer, } from './types.js';
|
|
7
|
+
export type { KnowledgeSemanticAnswer, KnowledgeSemanticAnswerInput, KnowledgeSemanticAnswerResult, KnowledgeSemanticEnrichmentResult, KnowledgeSemanticExtraction, KnowledgeSemanticFactInput, KnowledgeSemanticFactKind, KnowledgeSemanticGapRepairer, KnowledgeSemanticGapRepairRequest, KnowledgeSemanticGapRepairResult, KnowledgeSemanticGapInput, KnowledgeSemanticLlm, KnowledgeSemanticLlmAnswer, KnowledgeSemanticSelfImproveInput, KnowledgeSemanticSelfImproveResult, } from './types.js';
|
|
5
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wCAAwC,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AACpE,YAAY,EACV,uBAAuB,EACvB,4BAA4B,EAC5B,6BAA6B,EAC7B,iCAAiC,EACjC,2BAA2B,EAC3B,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,0BAA0B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wCAAwC,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,mCAAmC,EAAE,MAAM,uBAAuB,CAAC;AAC5E,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,YAAY,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AACpE,YAAY,EACV,uBAAuB,EACvB,4BAA4B,EAC5B,6BAA6B,EAC7B,iCAAiC,EACjC,2BAA2B,EAC3B,0BAA0B,EAC1B,yBAAyB,EACzB,4BAA4B,EAC5B,iCAAiC,EACjC,gCAAgC,EAChC,yBAAyB,EACzB,oBAAoB,EACpB,0BAA0B,EAC1B,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { KnowledgeStore } from '../store.js';
|
|
2
|
+
import type { KnowledgeSemanticGapRepairer, KnowledgeSemanticSelfImproveInput, KnowledgeSemanticSelfImproveResult } from './types.js';
|
|
3
|
+
interface SelfImproveContext {
|
|
4
|
+
readonly store: KnowledgeStore;
|
|
5
|
+
readonly gapRepairer?: KnowledgeSemanticGapRepairer | null;
|
|
6
|
+
readonly activeGapRepairs: Set<string>;
|
|
7
|
+
}
|
|
8
|
+
export declare function runKnowledgeSemanticSelfImprovement(context: SelfImproveContext, input?: KnowledgeSemanticSelfImproveInput): Promise<KnowledgeSemanticSelfImproveResult>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=self-improvement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-improvement.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/self-improvement.ts"],"names":[],"mappings":"AAEA,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;CACxC;AAUD,wBAAsB,mCAAmC,CACvD,OAAO,EAAE,kBAAkB,EAC3B,KAAK,GAAE,iCAAsC,GAC5C,OAAO,CAAC,kCAAkC,CAAC,CAwF7C"}
|