@pellux/goodvibes-sdk 0.28.15 → 0.28.17

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 (65) 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/generated-pages.d.ts.map +1 -1
  17. package/dist/_internal/platform/knowledge/home-graph/generated-pages.js +89 -20
  18. package/dist/_internal/platform/knowledge/home-graph/map-view.d.ts.map +1 -1
  19. package/dist/_internal/platform/knowledge/home-graph/map-view.js +11 -0
  20. package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts +0 -1
  21. package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts.map +1 -1
  22. package/dist/_internal/platform/knowledge/home-graph/rendering.js +0 -12
  23. package/dist/_internal/platform/knowledge/home-graph/reset.d.ts +2 -1
  24. package/dist/_internal/platform/knowledge/home-graph/reset.d.ts.map +1 -1
  25. package/dist/_internal/platform/knowledge/home-graph/reset.js +35 -2
  26. package/dist/_internal/platform/knowledge/home-graph/search.d.ts.map +1 -1
  27. package/dist/_internal/platform/knowledge/home-graph/search.js +2 -18
  28. package/dist/_internal/platform/knowledge/home-graph/service.d.ts +1 -1
  29. package/dist/_internal/platform/knowledge/home-graph/service.d.ts.map +1 -1
  30. package/dist/_internal/platform/knowledge/home-graph/service.js +15 -5
  31. package/dist/_internal/platform/knowledge/home-graph/source-links.d.ts +3 -0
  32. package/dist/_internal/platform/knowledge/home-graph/source-links.d.ts.map +1 -0
  33. package/dist/_internal/platform/knowledge/home-graph/source-links.js +30 -0
  34. package/dist/_internal/platform/knowledge/home-graph/state.d.ts.map +1 -1
  35. package/dist/_internal/platform/knowledge/home-graph/state.js +43 -1
  36. package/dist/_internal/platform/knowledge/home-graph/types.d.ts +14 -1
  37. package/dist/_internal/platform/knowledge/home-graph/types.d.ts.map +1 -1
  38. package/dist/_internal/platform/knowledge/ingest-compile.js +1 -1
  39. package/dist/_internal/platform/knowledge/pdf-extractor.d.ts.map +1 -1
  40. package/dist/_internal/platform/knowledge/pdf-extractor.js +8 -3
  41. package/dist/_internal/platform/knowledge/semantic/answer-fallback.d.ts.map +1 -1
  42. package/dist/_internal/platform/knowledge/semantic/answer-fallback.js +11 -16
  43. package/dist/_internal/platform/knowledge/semantic/answer-source-ranking.d.ts +7 -0
  44. package/dist/_internal/platform/knowledge/semantic/answer-source-ranking.d.ts.map +1 -0
  45. package/dist/_internal/platform/knowledge/semantic/answer-source-ranking.js +55 -0
  46. package/dist/_internal/platform/knowledge/semantic/answer.d.ts.map +1 -1
  47. package/dist/_internal/platform/knowledge/semantic/answer.js +62 -7
  48. package/dist/_internal/platform/knowledge/semantic/fact-quality.d.ts +0 -1
  49. package/dist/_internal/platform/knowledge/semantic/fact-quality.d.ts.map +1 -1
  50. package/dist/_internal/platform/knowledge/semantic/fact-quality.js +6 -18
  51. package/dist/_internal/platform/knowledge/semantic/gap-repair.js +11 -4
  52. package/dist/_internal/platform/knowledge/semantic/homeassistant-scope.d.ts.map +1 -1
  53. package/dist/_internal/platform/knowledge/semantic/homeassistant-scope.js +63 -5
  54. package/dist/_internal/platform/knowledge/semantic/repair-profile.d.ts +16 -0
  55. package/dist/_internal/platform/knowledge/semantic/repair-profile.d.ts.map +1 -0
  56. package/dist/_internal/platform/knowledge/semantic/repair-profile.js +152 -0
  57. package/dist/_internal/platform/knowledge/semantic/self-improvement-promotion.d.ts +1 -1
  58. package/dist/_internal/platform/knowledge/semantic/self-improvement-promotion.d.ts.map +1 -1
  59. package/dist/_internal/platform/knowledge/semantic/self-improvement-promotion.js +101 -53
  60. package/dist/_internal/platform/knowledge/semantic/self-improvement.d.ts.map +1 -1
  61. package/dist/_internal/platform/knowledge/semantic/self-improvement.js +15 -7
  62. package/dist/_internal/platform/knowledge/semantic/service.d.ts.map +1 -1
  63. package/dist/_internal/platform/knowledge/semantic/service.js +51 -8
  64. package/dist/_internal/platform/version.js +1 -1
  65. package/package.json +2 -1
@@ -1,6 +1,7 @@
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';
6
7
  import { clampText, normalizeWhitespace, readRecord, readString, semanticHash, semanticMetadata, semanticSlug, sourceSemanticText, splitSentences, uniqueStrings, } from './utils.js';
@@ -17,10 +18,14 @@ export async function promoteRepairSources(context, spaceId, gap, sourceIds, tas
17
18
  }
18
19
  const promotedFactCount = await promoteRepairEvidenceFacts(context.store, spaceId, gap, sourceIds);
19
20
  await linkPromotedFactsToRepairSubjects(context.store, spaceId, gap, sourceIds);
21
+ const usableFactCount = promotedFactCount > 0
22
+ ? promotedFactCount
23
+ : countUsableRepairFacts(context.store, spaceId, sourceIds);
20
24
  await updateRefinementTask(context.store, context.store.getRefinementTask(task.id) ?? task, 'verified', 'Accepted repair sources were semantically enriched.', {
21
25
  promotedSourceIds: sourceIds,
22
- promotedFactCount,
26
+ promotedFactCount: usableFactCount,
23
27
  });
28
+ return usableFactCount;
24
29
  }
25
30
  async function promoteRepairEvidenceFacts(store, spaceId, gap, sourceIds) {
26
31
  const subjects = linkedRepairSubjects(store, spaceId, gap);
@@ -33,70 +38,104 @@ async function promoteRepairEvidenceFacts(store, spaceId, gap, sourceIds) {
33
38
  continue;
34
39
  const extraction = store.getExtractionBySourceId(source.id);
35
40
  const authority = sourceAuthority(source);
41
+ const text = sourceSemanticText(source, extraction);
42
+ const profileFacts = deriveRepairProfileFacts({
43
+ query: gap.title,
44
+ source,
45
+ text,
46
+ });
47
+ for (const profileFact of profileFacts) {
48
+ promoted += await upsertPromotedRepairFact({
49
+ store,
50
+ spaceId,
51
+ gap,
52
+ source,
53
+ subjects,
54
+ authority,
55
+ title: profileFact.title,
56
+ summary: profileFact.summary,
57
+ classification: profileFact,
58
+ evidence: profileFact.evidence,
59
+ });
60
+ }
36
61
  const sentences = selectRepairFactSentences({
37
62
  query: gap.title,
38
63
  source,
39
- text: sourceSemanticText(source, extraction),
64
+ text,
40
65
  });
41
- for (const [index, sentence] of sentences.entries()) {
66
+ for (const sentence of sentences) {
42
67
  const classification = classifyRepairFact(sentence);
43
- const fact = await store.upsertNode({
44
- id: `sem-fact-${semanticHash(spaceId, source.id, gap.id, classification.title, sentence)}`,
45
- kind: 'fact',
46
- slug: semanticSlug(`${spaceId}-${classification.title}-${source.id}-${index}`),
68
+ promoted += await upsertPromotedRepairFact({
69
+ store,
70
+ spaceId,
71
+ gap,
72
+ source,
73
+ subjects,
74
+ authority,
47
75
  title: classification.title,
48
76
  summary: sentence,
49
- aliases: classification.aliases,
50
- status: 'active',
51
- confidence: authority === 'official-vendor' ? 88 : 76,
52
- sourceId: source.id,
53
- metadata: semanticMetadata(spaceId, {
54
- semanticKind: 'fact',
55
- factKind: classification.kind,
56
- value: classification.value,
57
- evidence: sentence,
58
- labels: classification.labels,
59
- sourceId: source.id,
60
- gapId: gap.id,
61
- linkedObjectIds: subjects.map((subject) => subject.id),
62
- extractor: 'repair-promotion',
63
- sourceAuthority: authority,
64
- sourceDiscovery: readRecord(source.metadata.sourceDiscovery),
65
- }),
66
- });
67
- await store.upsertEdge({
68
- fromKind: 'source',
69
- fromId: source.id,
70
- toKind: 'node',
71
- toId: fact.id,
72
- relation: 'supports_fact',
73
- weight: authority === 'official-vendor' ? 0.95 : 0.84,
74
- metadata: semanticMetadata(spaceId, {
75
- linkedBy: 'semantic-gap-repair',
76
- gapId: gap.id,
77
- }),
77
+ classification,
78
+ evidence: sentence,
78
79
  });
79
- for (const subject of subjects) {
80
- await store.upsertEdge({
81
- fromKind: 'node',
82
- fromId: fact.id,
83
- toKind: 'node',
84
- toId: subject.id,
85
- relation: 'describes',
86
- weight: authority === 'official-vendor' ? 0.94 : 0.82,
87
- metadata: semanticMetadata(spaceId, {
88
- linkedBy: 'semantic-gap-repair',
89
- repairedAt: Date.now(),
90
- sourceId: source.id,
91
- gapId: gap.id,
92
- }),
93
- });
94
- }
95
- promoted += 1;
96
80
  }
97
81
  }
98
82
  return promoted;
99
83
  }
84
+ async function upsertPromotedRepairFact(input) {
85
+ const fact = await input.store.upsertNode({
86
+ id: `sem-fact-${semanticHash(input.spaceId, input.source.id, input.gap.id, input.title, input.summary)}`,
87
+ kind: 'fact',
88
+ slug: semanticSlug(`${input.spaceId}-${input.title}-${input.source.id}`),
89
+ title: input.title,
90
+ summary: input.summary,
91
+ aliases: input.classification.aliases,
92
+ status: 'active',
93
+ confidence: input.authority === 'official-vendor' ? 90 : input.authority === 'vendor' ? 82 : 76,
94
+ sourceId: input.source.id,
95
+ metadata: semanticMetadata(input.spaceId, {
96
+ semanticKind: 'fact',
97
+ factKind: input.classification.kind,
98
+ value: input.classification.value,
99
+ evidence: input.evidence,
100
+ labels: input.classification.labels,
101
+ sourceId: input.source.id,
102
+ gapId: input.gap.id,
103
+ linkedObjectIds: input.subjects.map((subject) => subject.id),
104
+ extractor: 'repair-promotion',
105
+ sourceAuthority: input.authority,
106
+ sourceDiscovery: readRecord(input.source.metadata.sourceDiscovery),
107
+ }),
108
+ });
109
+ await input.store.upsertEdge({
110
+ fromKind: 'source',
111
+ fromId: input.source.id,
112
+ toKind: 'node',
113
+ toId: fact.id,
114
+ relation: 'supports_fact',
115
+ weight: input.authority === 'official-vendor' ? 0.96 : 0.84,
116
+ metadata: semanticMetadata(input.spaceId, {
117
+ linkedBy: 'semantic-gap-repair',
118
+ gapId: input.gap.id,
119
+ }),
120
+ });
121
+ for (const subject of input.subjects) {
122
+ await input.store.upsertEdge({
123
+ fromKind: 'node',
124
+ fromId: fact.id,
125
+ toKind: 'node',
126
+ toId: subject.id,
127
+ relation: 'describes',
128
+ weight: input.authority === 'official-vendor' ? 0.95 : 0.82,
129
+ metadata: semanticMetadata(input.spaceId, {
130
+ linkedBy: 'semantic-gap-repair',
131
+ repairedAt: Date.now(),
132
+ sourceId: input.source.id,
133
+ gapId: input.gap.id,
134
+ }),
135
+ });
136
+ }
137
+ return 1;
138
+ }
100
139
  async function linkPromotedFactsToRepairSubjects(store, spaceId, gap, sourceIds) {
101
140
  const linkedObjectIds = readStringArray(gap.metadata.linkedObjectIds).filter((nodeId) => Boolean(store.getNode(nodeId)));
102
141
  if (linkedObjectIds.length === 0)
@@ -225,6 +264,15 @@ function sourceAuthority(source) {
225
264
  return 'vendor';
226
265
  return 'secondary';
227
266
  }
267
+ function countUsableRepairFacts(store, spaceId, sourceIds) {
268
+ const sources = new Set(sourceIds);
269
+ return store.listNodes(10_000)
270
+ .filter((node) => node.kind === 'fact' && node.status !== 'stale')
271
+ .filter((node) => getKnowledgeSpaceId(node) === spaceId)
272
+ .filter((node) => node.sourceId && sources.has(node.sourceId))
273
+ .filter((node) => ['feature', 'capability', 'specification', 'compatibility', 'configuration'].includes(readString(node.metadata.factKind) ?? ''))
274
+ .length;
275
+ }
228
276
  function uniqueById(items) {
229
277
  const seen = new Set();
230
278
  const result = [];
@@ -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,CA2N7C"}
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,CA+N7C"}
@@ -23,11 +23,12 @@ export async function runKnowledgeSemanticSelfImprovement(context, input = {}) {
23
23
  const createdGaps = await discoverIntrinsicGaps(context.store, spaceId, sourceIdFilter);
24
24
  const candidates = collectCandidateGaps(context.store, spaceId, sourceIdFilter, gapIdFilter);
25
25
  const requestedLimit = Math.max(1, input.limit ?? DEFAULT_REFINEMENT_LIMIT);
26
- const effectiveLimit = Math.min(requestedLimit, MAX_REFINEMENT_LIMIT);
26
+ const cappedLimit = Math.min(requestedLimit, MAX_REFINEMENT_LIMIT);
27
27
  const maxRunMs = Math.min(MAX_REFINEMENT_RUN_MS, Math.max(5_000, input.maxRunMs ?? DEFAULT_REFINEMENT_RUN_MS));
28
28
  const startedAt = Date.now();
29
- const gaps = candidates.slice(0, effectiveLimit);
30
- let truncated = candidates.length > gaps.length || requestedLimit > effectiveLimit;
29
+ const gaps = candidates.slice(0, cappedLimit);
30
+ const effectiveLimit = gaps.length;
31
+ let truncated = candidates.length > gaps.length || requestedLimit > cappedLimit;
31
32
  let budgetExhausted = false;
32
33
  let processedGaps = 0;
33
34
  let repairableGaps = 0;
@@ -145,7 +146,7 @@ export async function runKnowledgeSemanticSelfImprovement(context, input = {}) {
145
146
  ingestedSources += result?.ingestedSourceIds.length ?? 0;
146
147
  ingestedSourceIds.push(...(result?.ingestedSourceIds ?? []));
147
148
  const acceptedSourceIds = uniqueStrings([...(result?.acceptedSourceIds ?? []), ...(result?.ingestedSourceIds ?? [])]);
148
- const evidenceSufficient = result?.evidenceSufficient !== false && acceptedSourceIds.length > 0;
149
+ let promotedFactCount = 0;
149
150
  task = await updateRefinementTask(context.store, task, 'evaluating', result?.reason ?? 'Source discovery completed.', {
150
151
  query: result?.query ?? gap.title,
151
152
  sourceAssessments: result?.sourceAssessments ?? [],
@@ -158,8 +159,9 @@ export async function runKnowledgeSemanticSelfImprovement(context, input = {}) {
158
159
  }
159
160
  linkedRepairs += await linkRepairSources(context.store, spaceId, gap, acceptedSourceIds, result?.query ?? gap.title);
160
161
  if (acceptedSourceIds.length > 0) {
161
- await promoteRepairSources(context, spaceId, gap, acceptedSourceIds, task, startedAt + maxRunMs);
162
+ promotedFactCount = await promoteRepairSources(context, spaceId, gap, acceptedSourceIds, task, startedAt + maxRunMs);
162
163
  }
164
+ const evidenceSufficient = result?.evidenceSufficient !== false && acceptedSourceIds.length > 0 && promotedFactCount > 0;
163
165
  await markGapRepairAttempt(context.store, gap, spaceId, {
164
166
  status: evidenceSufficient ? 'repaired' : acceptedSourceIds.length ? 'deferred' : 'searched_no_sources',
165
167
  reason: result?.reason,
@@ -170,12 +172,14 @@ export async function runKnowledgeSemanticSelfImprovement(context, input = {}) {
170
172
  await updateRefinementTask(context.store, task, 'closed', 'Repair sources were accepted and linked to the gap.', {
171
173
  acceptedSourceIds,
172
174
  ingestedSourceIds: result?.ingestedSourceIds ?? [],
175
+ promotedFactCount,
173
176
  });
174
177
  }
175
178
  else if (acceptedSourceIds.length) {
176
179
  blockedGaps += 1;
177
180
  await updateRefinementTask(context.store, task, 'blocked', result?.reason ?? 'Accepted source evidence was linked, but the gap still needs corroboration.', {
178
181
  acceptedSourceIds,
182
+ promotedFactCount,
179
183
  retryable: true,
180
184
  nextRepairAttemptAt: Date.now() + RETRY_DELAY_MS,
181
185
  });
@@ -413,8 +417,8 @@ function classifyGap(context, force) {
413
417
  return { action: 'skip', reason: 'Gap already has linked repair sources.', status: 'repaired' };
414
418
  if (!force && nextAttemptAt && nextAttemptAt > Date.now())
415
419
  return { action: 'skip', reason: 'Gap repair retry window has not elapsed.', status: 'retry_wait', markAttempt: true };
416
- if (hasRepairEdge(context))
417
- return { action: 'skip', reason: 'Gap already has a repair source.', status: 'already_repaired' };
420
+ if (!force && hasRepairEdge(context) && hasRepairFactEvidence(context))
421
+ return { action: 'skip', reason: 'Gap already has promoted repair facts.', status: 'already_repaired' };
418
422
  if (isNotApplicableGap(context))
419
423
  return { action: 'suppress', reason: 'The gap is not applicable to the linked subject.' };
420
424
  if (!hasConcreteSubject(context)) {
@@ -428,6 +432,10 @@ function classifyGap(context, force) {
428
432
  function hasRepairEdge(context) {
429
433
  return context.repairSourceIds.length > 0;
430
434
  }
435
+ function hasRepairFactEvidence(context) {
436
+ const repairSourceIds = new Set(context.repairSourceIds);
437
+ return context.facts.some((fact) => fact.sourceId && repairSourceIds.has(fact.sourceId) && readString(fact.metadata.extractor) === 'repair-promotion');
438
+ }
431
439
  function isNotApplicableGap(context) {
432
440
  const text = `${context.gap.title} ${context.gap.summary ?? ''}`.toLowerCase();
433
441
  if (text.includes('battery')) {
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/semantic/service.ts"],"names":[],"mappings":"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"}
@@ -101,11 +101,26 @@ export class KnowledgeSemanticService {
101
101
  }
102
102
  async answer(input) {
103
103
  await this.store.init();
104
- const answer = await answerKnowledgeQuery({ store: this.store, llm: this.options.llm }, input);
104
+ let answer = await answerKnowledgeQuery({ store: this.store, llm: this.options.llm }, input);
105
105
  if (input.autoRepairGaps === false)
106
106
  return answer;
107
107
  if (this.options.gapRepairer && answer.answer.gaps.length > 0) {
108
108
  const repairSpaceId = answerRepairSpaceId(answer);
109
+ const foregroundBudgetMs = foregroundAnswerRepairBudget(input, answer);
110
+ const foregroundTaskIds = [];
111
+ if (foregroundBudgetMs > 0) {
112
+ const repaired = await this.repairAnswerGaps({
113
+ answer,
114
+ maxRunMs: foregroundBudgetMs,
115
+ limit: Math.min(5, answer.answer.gaps.length),
116
+ });
117
+ foregroundTaskIds.push(...repaired.taskIds);
118
+ if (repaired.closedGaps > 0 || repaired.linkedRepairs > 0) {
119
+ answer = withRefinementTaskIds(await answerKnowledgeQuery({ store: this.store, llm: this.options.llm }, input), foregroundTaskIds);
120
+ if (answer.answer.gaps.length === 0 || answerHasUsableEvidence(answer))
121
+ return answer;
122
+ }
123
+ }
109
124
  const refinement = await this.selfImprove({
110
125
  knowledgeSpaceId: repairSpaceId,
111
126
  gapIds: answer.answer.gaps.map((gap) => gap.id),
@@ -115,17 +130,12 @@ export class KnowledgeSemanticService {
115
130
  });
116
131
  this.runAnswerRefinementInBackground(repairSpaceId, answer.answer.gaps.map((gap) => gap.id));
117
132
  const taskIds = uniqueStrings([
133
+ ...foregroundTaskIds,
118
134
  ...refinement.taskIds,
119
135
  ...this.taskIdsForGaps(repairSpaceId, answer.answer.gaps.map((gap) => gap.id)),
120
136
  ]);
121
137
  if (taskIds.length > 0) {
122
- return {
123
- ...answer,
124
- answer: {
125
- ...answer.answer,
126
- refinementTaskIds: taskIds,
127
- },
128
- };
138
+ return withRefinementTaskIds(answer, taskIds);
129
139
  }
130
140
  }
131
141
  return answer;
@@ -239,12 +249,45 @@ function answerRepairSpaceId(answer) {
239
249
  }
240
250
  return answer.spaceId;
241
251
  }
252
+ function foregroundAnswerRepairBudget(input, answer) {
253
+ if (!answerNeedsForegroundRepair(input, answer))
254
+ return 0;
255
+ const requested = typeof input.timeoutMs === 'number' && Number.isFinite(input.timeoutMs)
256
+ ? input.timeoutMs
257
+ : 45_000;
258
+ if (requested < 15_000)
259
+ return 0;
260
+ return Math.max(5_000, Math.min(35_000, requested - 5_000));
261
+ }
262
+ function answerNeedsForegroundRepair(input, answer) {
263
+ const repairSpaceId = answerRepairSpaceId(answer);
264
+ const homeAssistantScoped = repairSpaceId === 'homeassistant' || repairSpaceId.startsWith('homeassistant:');
265
+ if (!input.strictCandidates && !homeAssistantScoped)
266
+ return false;
267
+ return answer.answer.facts.length === 0 || answer.answer.sources.length === 0 || answer.answer.confidence < 50;
268
+ }
269
+ function answerHasUsableEvidence(answer) {
270
+ return answer.answer.facts.length > 0 && answer.answer.sources.length > 0 && answer.answer.confidence >= 50;
271
+ }
272
+ function withRefinementTaskIds(answer, taskIds) {
273
+ const ids = uniqueStrings([...(answer.answer.refinementTaskIds ?? []), ...taskIds]);
274
+ if (ids.length === 0)
275
+ return answer;
276
+ return {
277
+ ...answer,
278
+ answer: {
279
+ ...answer.answer,
280
+ refinementTaskIds: ids,
281
+ },
282
+ };
283
+ }
242
284
  function activeSelfImproveResult(input) {
243
285
  const requestedLimit = Math.max(1, input.limit ?? 1);
244
286
  return {
245
287
  ...emptySelfImproveResult(),
246
288
  skippedGaps: 1,
247
289
  requestedLimit,
290
+ effectiveLimit: 0,
248
291
  truncated: true,
249
292
  budgetExhausted: true,
250
293
  };
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
- let version = '0.28.15';
3
+ let version = '0.28.17';
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.15",
3
+ "version": "0.28.17",
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",