@pellux/goodvibes-sdk 0.26.9 → 0.26.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 +1563 -118
- package/dist/_internal/contracts/generated/foundation-metadata.d.ts +2 -2
- package/dist/_internal/contracts/generated/foundation-metadata.js +2 -2
- package/dist/_internal/contracts/generated/operator-contract.d.ts.map +1 -1
- package/dist/_internal/contracts/generated/operator-contract.js +1563 -118
- package/dist/_internal/contracts/generated/operator-method-ids.d.ts +1 -1
- package/dist/_internal/contracts/generated/operator-method-ids.d.ts.map +1 -1
- package/dist/_internal/contracts/generated/operator-method-ids.js +3 -0
- package/dist/_internal/daemon/context.d.ts +1 -0
- package/dist/_internal/daemon/context.d.ts.map +1 -1
- package/dist/_internal/daemon/knowledge-route-types.d.ts +2 -1
- package/dist/_internal/daemon/knowledge-route-types.d.ts.map +1 -1
- package/dist/_internal/daemon/knowledge-routes.d.ts +1 -1
- package/dist/_internal/daemon/knowledge-routes.d.ts.map +1 -1
- package/dist/_internal/daemon/knowledge-routes.js +19 -3
- package/dist/_internal/daemon/operator.d.ts +1 -1
- package/dist/_internal/daemon/operator.d.ts.map +1 -1
- package/dist/_internal/daemon/operator.js +2 -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 +22 -2
- package/dist/_internal/platform/control-plane/method-catalog-knowledge.d.ts.map +1 -1
- package/dist/_internal/platform/control-plane/method-catalog-knowledge.js +16 -1
- package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.d.ts +3 -0
- 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 +57 -2
- package/dist/_internal/platform/control-plane/routes/operator.d.ts +1 -1
- package/dist/_internal/platform/control-plane/routes/operator.d.ts.map +1 -1
- package/dist/_internal/platform/control-plane/routes/operator.js +2 -0
- package/dist/_internal/platform/daemon/http/home-graph-routes.d.ts.map +1 -1
- package/dist/_internal/platform/daemon/http/home-graph-routes.js +24 -0
- package/dist/_internal/platform/daemon/http/router-route-contexts.d.ts.map +1 -1
- package/dist/_internal/platform/daemon/http/router-route-contexts.js +1 -0
- package/dist/_internal/platform/knowledge/extractors.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/extractors.js +73 -1
- package/dist/_internal/platform/knowledge/generated-projections.d.ts +38 -0
- package/dist/_internal/platform/knowledge/generated-projections.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/generated-projections.js +106 -0
- package/dist/_internal/platform/knowledge/home-graph/generated-pages.d.ts +29 -0
- package/dist/_internal/platform/knowledge/home-graph/generated-pages.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/home-graph/generated-pages.js +296 -0
- package/dist/_internal/platform/knowledge/home-graph/helpers.d.ts +2 -1
- package/dist/_internal/platform/knowledge/home-graph/helpers.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/helpers.js +4 -0
- package/dist/_internal/platform/knowledge/home-graph/index.d.ts +1 -1
- package/dist/_internal/platform/knowledge/home-graph/index.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/reindex.d.ts +12 -0
- package/dist/_internal/platform/knowledge/home-graph/reindex.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/home-graph/reindex.js +35 -0
- package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts +5 -0
- package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/rendering.js +32 -11
- package/dist/_internal/platform/knowledge/home-graph/search.d.ts +2 -0
- package/dist/_internal/platform/knowledge/home-graph/search.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/search.js +135 -7
- package/dist/_internal/platform/knowledge/home-graph/service.d.ts +4 -2
- package/dist/_internal/platform/knowledge/home-graph/service.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/service.js +79 -91
- package/dist/_internal/platform/knowledge/home-graph/types.d.ts +46 -2
- package/dist/_internal/platform/knowledge/home-graph/types.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/home-graph/types.js +2 -0
- package/dist/_internal/platform/knowledge/index.d.ts +6 -2
- package/dist/_internal/platform/knowledge/index.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/index.js +2 -0
- package/dist/_internal/platform/knowledge/ingest-compile.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/ingest-compile.js +26 -1
- package/dist/_internal/platform/knowledge/knowledge-api.d.ts +2 -0
- package/dist/_internal/platform/knowledge/knowledge-api.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/knowledge-api.js +1 -0
- package/dist/_internal/platform/knowledge/map.d.ts +18 -0
- package/dist/_internal/platform/knowledge/map.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/map.js +235 -0
- package/dist/_internal/platform/knowledge/projection-utils.d.ts +16 -0
- package/dist/_internal/platform/knowledge/projection-utils.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/projection-utils.js +48 -0
- package/dist/_internal/platform/knowledge/projections.d.ts +1 -0
- package/dist/_internal/platform/knowledge/projections.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/projections.js +52 -58
- package/dist/_internal/platform/knowledge/service.d.ts +7 -1
- package/dist/_internal/platform/knowledge/service.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/service.js +11 -0
- package/dist/_internal/platform/knowledge/types.d.ts +35 -0
- package/dist/_internal/platform/knowledge/types.d.ts.map +1 -1
- package/dist/_internal/platform/version.js +1 -1
- package/package.json +2 -1
|
@@ -33,12 +33,30 @@ export class HomeGraphRoutes {
|
|
|
33
33
|
limit: readLimit(url, 250),
|
|
34
34
|
}));
|
|
35
35
|
}
|
|
36
|
+
if (url.pathname === '/api/homeassistant/home-graph/map' && req.method === 'GET') {
|
|
37
|
+
const result = await this.context.homeGraphService.map({
|
|
38
|
+
...readSpaceFromUrl(url),
|
|
39
|
+
limit: readLimit(url, 500),
|
|
40
|
+
includeSources: readBoolean(url, 'includeSources', true),
|
|
41
|
+
});
|
|
42
|
+
if (url.searchParams.get('format') === 'svg') {
|
|
43
|
+
return new Response(result.svg, {
|
|
44
|
+
headers: {
|
|
45
|
+
'content-type': 'image/svg+xml; charset=utf-8',
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return Response.json(result);
|
|
50
|
+
}
|
|
36
51
|
if (url.pathname === '/api/homeassistant/home-graph/export' && req.method === 'POST') {
|
|
37
52
|
return Response.json(await this.context.homeGraphService.exportSpace(await this.readOptionalBody(req)));
|
|
38
53
|
}
|
|
39
54
|
if (url.pathname === '/api/homeassistant/home-graph/ask' && req.method === 'POST') {
|
|
40
55
|
return Response.json(await this.context.homeGraphService.ask(await this.readBody(req)));
|
|
41
56
|
}
|
|
57
|
+
if (url.pathname === '/api/homeassistant/home-graph/reindex' && req.method === 'POST') {
|
|
58
|
+
return await this.admin(req, async () => Response.json(await this.context.homeGraphService.reindex(await this.readOptionalBody(req))));
|
|
59
|
+
}
|
|
42
60
|
if (url.pathname === '/api/homeassistant/home-graph/sync' && req.method === 'POST') {
|
|
43
61
|
return await this.admin(req, async () => Response.json(await this.context.homeGraphService.syncSnapshot(await this.readBody(req))));
|
|
44
62
|
}
|
|
@@ -118,3 +136,9 @@ function readLimit(url, fallback) {
|
|
|
118
136
|
const parsed = Number(url.searchParams.get('limit') ?? fallback);
|
|
119
137
|
return Number.isFinite(parsed) ? Math.max(1, Math.trunc(parsed)) : fallback;
|
|
120
138
|
}
|
|
139
|
+
function readBoolean(url, key, fallback) {
|
|
140
|
+
const value = url.searchParams.get(key);
|
|
141
|
+
if (value === null)
|
|
142
|
+
return fallback;
|
|
143
|
+
return !['0', 'false', 'no', 'off'].includes(value.trim().toLowerCase());
|
|
144
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-route-contexts.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/daemon/http/router-route-contexts.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"router-route-contexts.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/daemon/http/router-route-contexts.ts"],"names":[],"mappings":"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"}
|
|
@@ -132,6 +132,7 @@ export function buildKnowledgeRouteContext(input) {
|
|
|
132
132
|
setScheduleEnabled: (id, enabled) => input.knowledgeService.setScheduleEnabled(id, enabled),
|
|
133
133
|
renderProjection: (projection) => input.knowledgeService.renderProjection(projection),
|
|
134
134
|
materializeProjection: (projection) => input.knowledgeService.materializeProjection(projection),
|
|
135
|
+
map: (mapInput) => input.knowledgeService.map(mapInput),
|
|
135
136
|
},
|
|
136
137
|
knowledgeGraphqlService: input.knowledgeGraphqlService,
|
|
137
138
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractors.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/knowledge/extractors.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAsB,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGhF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAI5D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,yBAAyB,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC5C;
|
|
1
|
+
{"version":3,"file":"extractors.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/knowledge/extractors.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAsB,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGhF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAI5D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,yBAAyB,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC5C;AAmmBD,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,GAAG,UAAU,GAAG,UAAU,CAAC,EAC9D,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,yBAAyB,CAAC,CA4CpC"}
|
|
@@ -306,7 +306,79 @@ function extractYaml(buffer) {
|
|
|
306
306
|
metadata: {},
|
|
307
307
|
};
|
|
308
308
|
}
|
|
309
|
-
function extractPdf(buffer) {
|
|
309
|
+
async function extractPdf(buffer) {
|
|
310
|
+
const parsed = await extractPdfWithPdfJs(buffer);
|
|
311
|
+
if (parsed)
|
|
312
|
+
return parsed;
|
|
313
|
+
return extractPdfRawStreams(buffer);
|
|
314
|
+
}
|
|
315
|
+
async function extractPdfWithPdfJs(buffer) {
|
|
316
|
+
try {
|
|
317
|
+
const pdfjs = await import('pdfjs-dist/legacy/build/pdf.mjs');
|
|
318
|
+
const loadingTask = pdfjs.getDocument({
|
|
319
|
+
data: new Uint8Array(buffer),
|
|
320
|
+
useSystemFonts: true,
|
|
321
|
+
});
|
|
322
|
+
const document = await loadingTask.promise;
|
|
323
|
+
const pageCount = document.numPages;
|
|
324
|
+
const pageTexts = [];
|
|
325
|
+
for (let pageNumber = 1; pageNumber <= pageCount; pageNumber += 1) {
|
|
326
|
+
const page = await document.getPage(pageNumber);
|
|
327
|
+
const content = await page.getTextContent();
|
|
328
|
+
const lines = textContentItemsToLines(content.items);
|
|
329
|
+
if (lines.length > 0)
|
|
330
|
+
pageTexts.push(lines.join('\n'));
|
|
331
|
+
page.cleanup();
|
|
332
|
+
}
|
|
333
|
+
await document.destroy();
|
|
334
|
+
const text = cleanText(pageTexts.join('\n\n'));
|
|
335
|
+
if (!text)
|
|
336
|
+
return undefined;
|
|
337
|
+
const searchText = searchTextPayload(text);
|
|
338
|
+
return {
|
|
339
|
+
extractorId: 'pdfjs',
|
|
340
|
+
format: 'pdf',
|
|
341
|
+
title: firstNonEmptyLine(text) ?? 'PDF document',
|
|
342
|
+
summary: summarizeText(text) ?? 'PDF document.',
|
|
343
|
+
excerpt: excerptText(text),
|
|
344
|
+
sections: uniqueStrings(text.split(/\n+/), 24),
|
|
345
|
+
links: uniqueStrings(Array.from(text.matchAll(/\bhttps?:\/\/[^\s)]+/g), (match) => match[0]), 50),
|
|
346
|
+
estimatedTokens: estimateTokens(text),
|
|
347
|
+
structure: {
|
|
348
|
+
pageCount,
|
|
349
|
+
extractedTextChars: text.length,
|
|
350
|
+
...(searchText ? { searchText } : {}),
|
|
351
|
+
},
|
|
352
|
+
metadata: {
|
|
353
|
+
limitations: ['PDF text extraction does not perform OCR for scanned images.'],
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
return undefined;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
function textContentItemsToLines(items) {
|
|
362
|
+
const lines = [];
|
|
363
|
+
let current = '';
|
|
364
|
+
for (const item of items) {
|
|
365
|
+
const record = unknownRecord(item);
|
|
366
|
+
const text = typeof record.str === 'string' ? cleanText(record.str) : '';
|
|
367
|
+
if (text)
|
|
368
|
+
current = current ? `${current} ${text}` : text;
|
|
369
|
+
if (record.hasEOL === true && current) {
|
|
370
|
+
lines.push(current);
|
|
371
|
+
current = '';
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (current)
|
|
375
|
+
lines.push(current);
|
|
376
|
+
return lines;
|
|
377
|
+
}
|
|
378
|
+
function unknownRecord(value) {
|
|
379
|
+
return value && typeof value === 'object' ? value : {};
|
|
380
|
+
}
|
|
381
|
+
function extractPdfRawStreams(buffer) {
|
|
310
382
|
const body = buffer.toString('latin1');
|
|
311
383
|
const texts = [];
|
|
312
384
|
const streamRe = /stream\r?\n([\s\S]*?)\r?\nendstream/g;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ArtifactDescriptor } from '../artifacts/types.js';
|
|
2
|
+
import type { ArtifactStore } from '../artifacts/index.js';
|
|
3
|
+
import type { KnowledgeStore } from './store.js';
|
|
4
|
+
import type { KnowledgeEdgeRecord, KnowledgeReferenceKind, KnowledgeSourceRecord, KnowledgeSourceType } from './types.js';
|
|
5
|
+
export interface GeneratedKnowledgeProjectionInput {
|
|
6
|
+
readonly store: KnowledgeStore;
|
|
7
|
+
readonly artifactStore: ArtifactStore;
|
|
8
|
+
readonly connectorId: string;
|
|
9
|
+
readonly sourceId: string;
|
|
10
|
+
readonly sourceType?: KnowledgeSourceType;
|
|
11
|
+
readonly canonicalUri: string;
|
|
12
|
+
readonly title: string;
|
|
13
|
+
readonly summary?: string;
|
|
14
|
+
readonly tags?: readonly string[];
|
|
15
|
+
readonly filename: string;
|
|
16
|
+
readonly markdown: string;
|
|
17
|
+
readonly projectionKind: string;
|
|
18
|
+
readonly metadata?: Record<string, unknown>;
|
|
19
|
+
readonly sourceMetadata?: Record<string, unknown>;
|
|
20
|
+
readonly artifactMetadata?: Record<string, unknown>;
|
|
21
|
+
readonly edgeMetadata?: Record<string, unknown>;
|
|
22
|
+
readonly target?: {
|
|
23
|
+
readonly kind: KnowledgeReferenceKind;
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly relation?: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface GeneratedKnowledgeProjectionResult {
|
|
29
|
+
readonly artifact: ArtifactDescriptor;
|
|
30
|
+
readonly source: KnowledgeSourceRecord;
|
|
31
|
+
readonly linked?: KnowledgeEdgeRecord;
|
|
32
|
+
readonly artifactCreated: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function generatedKnowledgeSourceId(kind: string, value: string): string;
|
|
35
|
+
export declare function generatedKnowledgeCanonicalUri(kind: string, value: string): string;
|
|
36
|
+
export declare function isGeneratedKnowledgeSource(source: KnowledgeSourceRecord): boolean;
|
|
37
|
+
export declare function materializeGeneratedKnowledgeProjection(input: GeneratedKnowledgeProjectionInput): Promise<GeneratedKnowledgeProjectionResult>;
|
|
38
|
+
//# sourceMappingURL=generated-projections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generated-projections.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/knowledge/generated-projections.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EACV,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,CAAC;IAC1C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;QACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;CACH;AAED,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;CACnC;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAElF;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAKjF;AAED,wBAAsB,uCAAuC,CAC3D,KAAK,EAAE,iCAAiC,GACvC,OAAO,CAAC,kCAAkC,CAAC,CA+D7C"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
export function generatedKnowledgeSourceId(kind, value) {
|
|
3
|
+
return `kg-gen-${stableHash(`${kind}:${value}`)}`;
|
|
4
|
+
}
|
|
5
|
+
export function generatedKnowledgeCanonicalUri(kind, value) {
|
|
6
|
+
return `knowledge://generated/${encodeURIComponent(kind)}/${stableHash(value, 20)}`;
|
|
7
|
+
}
|
|
8
|
+
export function isGeneratedKnowledgeSource(source) {
|
|
9
|
+
return source.metadata.generatedKnowledgePage === true
|
|
10
|
+
|| source.metadata.generatedProjection === true
|
|
11
|
+
|| source.metadata.homeGraphGeneratedPage === true
|
|
12
|
+
|| source.metadata.homeGraphSourceKind === 'generated-page';
|
|
13
|
+
}
|
|
14
|
+
export async function materializeGeneratedKnowledgeProjection(input) {
|
|
15
|
+
const generatedAt = Date.now();
|
|
16
|
+
const projectionMetadata = {
|
|
17
|
+
generatedKnowledgePage: true,
|
|
18
|
+
generatedProjection: true,
|
|
19
|
+
projectionKind: input.projectionKind,
|
|
20
|
+
generatedAt,
|
|
21
|
+
pageEditable: true,
|
|
22
|
+
...(input.metadata ?? {}),
|
|
23
|
+
};
|
|
24
|
+
const existing = input.store.getSource(input.sourceId);
|
|
25
|
+
const reusedArtifact = await findReusableGeneratedArtifact(input.artifactStore, existing, input.markdown);
|
|
26
|
+
const artifact = reusedArtifact ?? await input.artifactStore.create({
|
|
27
|
+
kind: 'document',
|
|
28
|
+
mimeType: 'text/markdown',
|
|
29
|
+
filename: input.filename,
|
|
30
|
+
text: input.markdown,
|
|
31
|
+
retentionMs: 0,
|
|
32
|
+
metadata: {
|
|
33
|
+
...projectionMetadata,
|
|
34
|
+
...(input.artifactMetadata ?? {}),
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
const source = await input.store.upsertSource({
|
|
38
|
+
id: input.sourceId,
|
|
39
|
+
connectorId: input.connectorId,
|
|
40
|
+
sourceType: input.sourceType ?? 'document',
|
|
41
|
+
title: input.title,
|
|
42
|
+
sourceUri: input.canonicalUri,
|
|
43
|
+
canonicalUri: input.canonicalUri,
|
|
44
|
+
...(input.summary ? { summary: input.summary } : {}),
|
|
45
|
+
tags: uniqueStrings(input.tags ?? []),
|
|
46
|
+
status: 'indexed',
|
|
47
|
+
artifactId: artifact.id,
|
|
48
|
+
lastCrawledAt: generatedAt,
|
|
49
|
+
metadata: {
|
|
50
|
+
...projectionMetadata,
|
|
51
|
+
artifactId: artifact.id,
|
|
52
|
+
filename: artifact.filename,
|
|
53
|
+
...(input.sourceMetadata ?? {}),
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
const linked = input.target
|
|
57
|
+
? await input.store.upsertEdge({
|
|
58
|
+
fromKind: 'source',
|
|
59
|
+
fromId: source.id,
|
|
60
|
+
toKind: input.target.kind,
|
|
61
|
+
toId: input.target.id,
|
|
62
|
+
relation: input.target.relation ?? 'source_for',
|
|
63
|
+
metadata: {
|
|
64
|
+
generatedKnowledgePage: true,
|
|
65
|
+
generatedProjection: true,
|
|
66
|
+
projectionKind: input.projectionKind,
|
|
67
|
+
...(input.edgeMetadata ?? {}),
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
: undefined;
|
|
71
|
+
return {
|
|
72
|
+
artifact,
|
|
73
|
+
source,
|
|
74
|
+
...(linked ? { linked } : {}),
|
|
75
|
+
artifactCreated: !reusedArtifact,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async function findReusableGeneratedArtifact(artifactStore, source, markdown) {
|
|
79
|
+
if (!source?.artifactId)
|
|
80
|
+
return undefined;
|
|
81
|
+
const artifact = artifactStore.get(source.artifactId);
|
|
82
|
+
if (!artifact)
|
|
83
|
+
return undefined;
|
|
84
|
+
try {
|
|
85
|
+
const { buffer } = await artifactStore.readContent(artifact.id);
|
|
86
|
+
return buffer.toString('utf-8') === markdown ? artifact : undefined;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function stableHash(value, length = 24) {
|
|
93
|
+
return createHash('sha256').update(value).digest('hex').slice(0, length);
|
|
94
|
+
}
|
|
95
|
+
function uniqueStrings(values) {
|
|
96
|
+
const seen = new Set();
|
|
97
|
+
const result = [];
|
|
98
|
+
for (const value of values) {
|
|
99
|
+
const trimmed = typeof value === 'string' ? value.trim() : '';
|
|
100
|
+
if (!trimmed || seen.has(trimmed))
|
|
101
|
+
continue;
|
|
102
|
+
seen.add(trimmed);
|
|
103
|
+
result.push(trimmed);
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ArtifactStore } from '../../artifacts/index.js';
|
|
2
|
+
import type { KnowledgeStore } from '../store.js';
|
|
3
|
+
import type { HomeGraphDevicePassportResult, HomeGraphGeneratedPagesSummary, HomeGraphProjectionInput, HomeGraphProjectionResult, HomeGraphSnapshotInput } from './types.js';
|
|
4
|
+
interface HomeGraphPageContext {
|
|
5
|
+
readonly store: KnowledgeStore;
|
|
6
|
+
readonly artifactStore: ArtifactStore;
|
|
7
|
+
readonly spaceId: string;
|
|
8
|
+
readonly installationId: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function generateAutomaticHomeGraphPages(context: HomeGraphPageContext & {
|
|
11
|
+
readonly input: HomeGraphSnapshotInput;
|
|
12
|
+
}): Promise<HomeGraphGeneratedPagesSummary>;
|
|
13
|
+
export declare function refreshHomeGraphDevicePassport(context: HomeGraphPageContext & {
|
|
14
|
+
readonly input: HomeGraphProjectionInput;
|
|
15
|
+
}): Promise<HomeGraphDevicePassportResult & {
|
|
16
|
+
readonly artifactCreated: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
export declare function generateHomeGraphRoomPage(context: HomeGraphPageContext & {
|
|
19
|
+
readonly input: HomeGraphProjectionInput;
|
|
20
|
+
}): Promise<HomeGraphProjectionResult & {
|
|
21
|
+
readonly artifactCreated: boolean;
|
|
22
|
+
}>;
|
|
23
|
+
export declare function generateHomeGraphPacket(context: HomeGraphPageContext & {
|
|
24
|
+
readonly input: HomeGraphProjectionInput;
|
|
25
|
+
}): Promise<HomeGraphProjectionResult & {
|
|
26
|
+
readonly artifactCreated: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=generated-pages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generated-pages.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/home-graph/generated-pages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAK9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA8BlD,OAAO,KAAK,EACV,6BAA6B,EAC7B,8BAA8B,EAC9B,wBAAwB,EACxB,yBAAyB,EACzB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,oBAAoB,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAA;CAAE,GACzE,OAAO,CAAC,8BAA8B,CAAC,CAoEzC;AAED,wBAAsB,8BAA8B,CAClD,OAAO,EAAE,oBAAoB,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAA;CAAE,GAC3E,OAAO,CAAC,6BAA6B,GAAG;IAAE,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAAC,CA0EhF;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,oBAAoB,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAA;CAAE,GAC3E,OAAO,CAAC,yBAAyB,GAAG;IAAE,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAAC,CAsC5E;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,oBAAoB,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAA;CAAE,GAC3E,OAAO,CAAC,yBAAyB,GAAG;IAAE,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAAC,CAyB5E"}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { materializeGeneratedKnowledgeProjection, } from '../generated-projections.js';
|
|
2
|
+
import { HOME_GRAPH_CONNECTOR_ID, buildHomeGraphMetadata, edgeIsActive, homeGraphNodeId, homeGraphSourceId, isGeneratedPageSource, namespacedCanonicalUri, readRecord, uniqueStrings, } from './helpers.js';
|
|
3
|
+
import { findHomeAssistantNode, missingDevicePassportFields, readHomeGraphState, renderHomeGraphState, safeHomeGraphFilename, sourcesLinkedToNode, } from './state.js';
|
|
4
|
+
import { renderDevicePassportPage, renderPacketPage, renderRoomPage, } from './rendering.js';
|
|
5
|
+
export async function generateAutomaticHomeGraphPages(context) {
|
|
6
|
+
const options = context.input.pageAutomation ?? {};
|
|
7
|
+
const summary = createGeneratedPagesSummary();
|
|
8
|
+
if (options.enabled === false)
|
|
9
|
+
return summary;
|
|
10
|
+
const state = readHomeGraphState(context.store, context.spaceId);
|
|
11
|
+
if (options.devicePassports !== false) {
|
|
12
|
+
const devices = limitRecords(state.nodes.filter((node) => node.kind === 'ha_device' && node.status !== 'stale').sort(compareByTitle), options.maxDevicePassports);
|
|
13
|
+
for (const device of devices) {
|
|
14
|
+
const deviceId = readHomeAssistantObjectId(device, 'objectId', 'deviceId') ?? device.id;
|
|
15
|
+
try {
|
|
16
|
+
const page = await refreshHomeGraphDevicePassport({
|
|
17
|
+
...context,
|
|
18
|
+
input: {
|
|
19
|
+
knowledgeSpaceId: context.spaceId,
|
|
20
|
+
deviceId,
|
|
21
|
+
metadata: { automation: 'snapshot-sync' },
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
summary.devicePassports += 1;
|
|
25
|
+
if (page.artifactCreated)
|
|
26
|
+
summary.artifacts += 1;
|
|
27
|
+
if (page.source)
|
|
28
|
+
summary.sources += 1;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
summary.errors.push({
|
|
32
|
+
kind: 'device-passport',
|
|
33
|
+
targetId: deviceId,
|
|
34
|
+
error: error instanceof Error ? error.message : String(error),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (options.roomPages !== false) {
|
|
40
|
+
const rooms = limitRecords(state.nodes
|
|
41
|
+
.filter((node) => (node.kind === 'ha_area' || node.kind === 'ha_room') && node.status !== 'stale')
|
|
42
|
+
.sort(compareByTitle), options.maxRoomPages);
|
|
43
|
+
for (const room of rooms) {
|
|
44
|
+
const areaId = readHomeAssistantObjectId(room, 'objectId', 'areaId') ?? room.id;
|
|
45
|
+
try {
|
|
46
|
+
const page = await generateHomeGraphRoomPage({
|
|
47
|
+
...context,
|
|
48
|
+
input: {
|
|
49
|
+
knowledgeSpaceId: context.spaceId,
|
|
50
|
+
areaId,
|
|
51
|
+
title: room.title,
|
|
52
|
+
metadata: { automation: 'snapshot-sync' },
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
summary.roomPages += 1;
|
|
56
|
+
if (page.artifactCreated)
|
|
57
|
+
summary.artifacts += 1;
|
|
58
|
+
if (page.source)
|
|
59
|
+
summary.sources += 1;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
summary.errors.push({
|
|
63
|
+
kind: 'room-page',
|
|
64
|
+
targetId: areaId,
|
|
65
|
+
error: error instanceof Error ? error.message : String(error),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return summary;
|
|
71
|
+
}
|
|
72
|
+
export async function refreshHomeGraphDevicePassport(context) {
|
|
73
|
+
const { store, artifactStore, spaceId, installationId, input } = context;
|
|
74
|
+
if (!input.deviceId)
|
|
75
|
+
throw new Error('refreshDevicePassport requires deviceId.');
|
|
76
|
+
const state = readHomeGraphState(store, spaceId);
|
|
77
|
+
const device = findHomeAssistantNode(state.nodes, 'ha_device', input.deviceId);
|
|
78
|
+
if (!device)
|
|
79
|
+
throw new Error(`Unknown Home Assistant device: ${input.deviceId}`);
|
|
80
|
+
const entities = state.nodes.filter((node) => (node.kind === 'ha_entity' && state.edges.some((edge) => (edgeIsActive(edge)
|
|
81
|
+
&& edge.fromKind === 'node'
|
|
82
|
+
&& edge.fromId === node.id
|
|
83
|
+
&& edge.toKind === 'node'
|
|
84
|
+
&& edge.toId === device.id
|
|
85
|
+
&& edge.relation === 'belongs_to_device'))));
|
|
86
|
+
const sources = sourcesLinkedToNode(device.id, state).filter((source) => !isGeneratedPageSource(source));
|
|
87
|
+
const issues = state.issues.filter((issue) => issue.nodeId === device.id);
|
|
88
|
+
const missingFields = missingDevicePassportFields(device, sources);
|
|
89
|
+
const passport = await store.upsertNode({
|
|
90
|
+
id: homeGraphNodeId(spaceId, 'ha_device_passport', input.deviceId),
|
|
91
|
+
kind: 'ha_device_passport',
|
|
92
|
+
slug: `${device.slug}-passport`,
|
|
93
|
+
title: `${device.title} passport`,
|
|
94
|
+
summary: `Living device profile for ${device.title}.`,
|
|
95
|
+
aliases: [`${device.title} passport`],
|
|
96
|
+
confidence: 80,
|
|
97
|
+
metadata: buildHomeGraphMetadata(spaceId, installationId, {
|
|
98
|
+
homeAssistant: { installationId, objectKind: 'device_passport', objectId: input.deviceId },
|
|
99
|
+
deviceId: input.deviceId,
|
|
100
|
+
missingFields,
|
|
101
|
+
refreshedAt: Date.now(),
|
|
102
|
+
}),
|
|
103
|
+
});
|
|
104
|
+
await store.upsertEdge({
|
|
105
|
+
fromKind: 'node',
|
|
106
|
+
fromId: passport.id,
|
|
107
|
+
toKind: 'node',
|
|
108
|
+
toId: device.id,
|
|
109
|
+
relation: 'source_for',
|
|
110
|
+
metadata: buildHomeGraphMetadata(spaceId, installationId),
|
|
111
|
+
});
|
|
112
|
+
const markdown = renderDevicePassportPage({ spaceId, device, entities, sources, issues, missingFields });
|
|
113
|
+
const generated = await materializeGeneratedMarkdown({
|
|
114
|
+
store,
|
|
115
|
+
artifactStore,
|
|
116
|
+
spaceId,
|
|
117
|
+
installationId,
|
|
118
|
+
filename: `${safeHomeGraphFilename(device.title)}-passport.md`,
|
|
119
|
+
markdown,
|
|
120
|
+
projectionKind: 'device-passport',
|
|
121
|
+
canonicalValue: `device-passport:${input.deviceId}`,
|
|
122
|
+
title: `${device.title} passport`,
|
|
123
|
+
summary: `Living device profile for ${device.title}.`,
|
|
124
|
+
tags: ['homeassistant', 'home-graph', 'generated-page', 'device-passport'],
|
|
125
|
+
targetNodeId: passport.id,
|
|
126
|
+
metadata: {
|
|
127
|
+
...(input.metadata ?? {}),
|
|
128
|
+
deviceId: input.deviceId,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
return {
|
|
132
|
+
ok: true,
|
|
133
|
+
spaceId,
|
|
134
|
+
title: `${device.title} passport`,
|
|
135
|
+
markdown,
|
|
136
|
+
artifact: generated.artifact,
|
|
137
|
+
source: generated.source,
|
|
138
|
+
...(generated.linked ? { linked: generated.linked } : {}),
|
|
139
|
+
device,
|
|
140
|
+
passport,
|
|
141
|
+
missingFields,
|
|
142
|
+
artifactCreated: generated.artifactCreated,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export async function generateHomeGraphRoomPage(context) {
|
|
146
|
+
const { store, artifactStore, spaceId, installationId, input } = context;
|
|
147
|
+
const state = readHomeGraphState(store, spaceId);
|
|
148
|
+
const areaId = input.areaId ?? input.roomId;
|
|
149
|
+
const title = input.title ?? resolveRoomTitle(state.nodes, areaId) ?? 'Home Graph Room';
|
|
150
|
+
const markdown = renderRoomPage({ ...state, title }, areaId);
|
|
151
|
+
const filename = `${safeHomeGraphFilename(title)}.md`;
|
|
152
|
+
const targetNode = areaId
|
|
153
|
+
? findHomeAssistantNode(state.nodes, 'ha_area', areaId) ?? findHomeAssistantNode(state.nodes, 'ha_room', areaId)
|
|
154
|
+
: undefined;
|
|
155
|
+
const generated = await materializeGeneratedMarkdown({
|
|
156
|
+
store,
|
|
157
|
+
artifactStore,
|
|
158
|
+
spaceId,
|
|
159
|
+
installationId,
|
|
160
|
+
filename,
|
|
161
|
+
markdown,
|
|
162
|
+
projectionKind: 'room-page',
|
|
163
|
+
canonicalValue: `room-page:${areaId ?? 'home'}`,
|
|
164
|
+
title,
|
|
165
|
+
summary: `Living Home Graph room page for ${title}.`,
|
|
166
|
+
tags: ['homeassistant', 'home-graph', 'generated-page', 'room-page'],
|
|
167
|
+
...(targetNode ? { targetNodeId: targetNode.id } : {}),
|
|
168
|
+
metadata: {
|
|
169
|
+
...(input.metadata ?? {}),
|
|
170
|
+
...(areaId ? { areaId } : {}),
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
return {
|
|
174
|
+
ok: true,
|
|
175
|
+
spaceId,
|
|
176
|
+
title,
|
|
177
|
+
markdown,
|
|
178
|
+
artifact: generated.artifact,
|
|
179
|
+
source: generated.source,
|
|
180
|
+
...(generated.linked ? { linked: generated.linked } : {}),
|
|
181
|
+
artifactCreated: generated.artifactCreated,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
export async function generateHomeGraphPacket(context) {
|
|
185
|
+
const { store, artifactStore, spaceId, installationId, input } = context;
|
|
186
|
+
const title = input.title ?? `${input.packetKind ?? 'home'} packet`;
|
|
187
|
+
const markdown = renderPacketPage(renderHomeGraphState(store, spaceId, title), input);
|
|
188
|
+
const generated = await materializeGeneratedMarkdown({
|
|
189
|
+
store,
|
|
190
|
+
artifactStore,
|
|
191
|
+
spaceId,
|
|
192
|
+
installationId,
|
|
193
|
+
filename: `${safeHomeGraphFilename(title)}.md`,
|
|
194
|
+
markdown,
|
|
195
|
+
projectionKind: 'packet',
|
|
196
|
+
canonicalValue: `packet:${input.packetKind ?? 'home'}:${input.sharingProfile ?? 'default'}`,
|
|
197
|
+
title,
|
|
198
|
+
summary: `Generated ${title} packet for ${input.sharingProfile ?? 'default'} sharing.`,
|
|
199
|
+
tags: ['homeassistant', 'home-graph', 'generated-page', 'packet'],
|
|
200
|
+
metadata: {
|
|
201
|
+
...(input.metadata ?? {}),
|
|
202
|
+
packetKind: input.packetKind ?? 'home',
|
|
203
|
+
sharingProfile: input.sharingProfile ?? 'default',
|
|
204
|
+
includeFields: input.includeFields ? [...input.includeFields] : [],
|
|
205
|
+
excludeFields: input.excludeFields ? [...input.excludeFields] : [],
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
return { ok: true, spaceId, title, markdown, artifact: generated.artifact, source: generated.source, artifactCreated: generated.artifactCreated };
|
|
209
|
+
}
|
|
210
|
+
async function materializeGeneratedMarkdown(input) {
|
|
211
|
+
const generatedAt = Date.now();
|
|
212
|
+
const regeneration = readRecord(input.metadata).automation === 'snapshot-sync' ? 'automatic' : 'manual';
|
|
213
|
+
const metadata = {
|
|
214
|
+
...(input.metadata ?? {}),
|
|
215
|
+
homeGraphSourceKind: 'generated-page',
|
|
216
|
+
homeGraphGeneratedPage: true,
|
|
217
|
+
projectionKind: input.projectionKind,
|
|
218
|
+
generatedAt,
|
|
219
|
+
pageEditable: true,
|
|
220
|
+
regeneration,
|
|
221
|
+
};
|
|
222
|
+
const homeGraphMetadata = buildHomeGraphMetadata(input.spaceId, input.installationId, metadata);
|
|
223
|
+
const generated = await materializeGeneratedKnowledgeProjection({
|
|
224
|
+
store: input.store,
|
|
225
|
+
artifactStore: input.artifactStore,
|
|
226
|
+
connectorId: HOME_GRAPH_CONNECTOR_ID,
|
|
227
|
+
sourceId: homeGraphSourceId(input.spaceId, 'generated-page', input.canonicalValue),
|
|
228
|
+
sourceType: 'document',
|
|
229
|
+
canonicalUri: namespacedCanonicalUri(input.spaceId, 'generated-page', input.canonicalValue),
|
|
230
|
+
title: input.title,
|
|
231
|
+
summary: input.summary,
|
|
232
|
+
tags: uniqueStrings(input.tags),
|
|
233
|
+
filename: input.filename,
|
|
234
|
+
markdown: input.markdown,
|
|
235
|
+
projectionKind: input.projectionKind,
|
|
236
|
+
metadata: homeGraphMetadata,
|
|
237
|
+
sourceMetadata: homeGraphMetadata,
|
|
238
|
+
artifactMetadata: homeGraphMetadata,
|
|
239
|
+
edgeMetadata: buildHomeGraphMetadata(input.spaceId, input.installationId, {
|
|
240
|
+
homeGraphGeneratedPage: true,
|
|
241
|
+
projectionKind: input.projectionKind,
|
|
242
|
+
}),
|
|
243
|
+
...(input.targetNodeId
|
|
244
|
+
? { target: { kind: 'node', id: input.targetNodeId, relation: input.relation ?? 'source_for' } }
|
|
245
|
+
: {}),
|
|
246
|
+
});
|
|
247
|
+
return {
|
|
248
|
+
artifact: projectionArtifact(generated.artifact),
|
|
249
|
+
source: generated.source,
|
|
250
|
+
...(generated.linked ? { linked: generated.linked } : {}),
|
|
251
|
+
artifactCreated: generated.artifactCreated,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function projectionArtifact(artifact) {
|
|
255
|
+
return {
|
|
256
|
+
id: artifact.id,
|
|
257
|
+
mimeType: artifact.mimeType,
|
|
258
|
+
filename: artifact.filename,
|
|
259
|
+
createdAt: artifact.createdAt,
|
|
260
|
+
metadata: artifact.metadata,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
function createGeneratedPagesSummary() {
|
|
264
|
+
return {
|
|
265
|
+
devicePassports: 0,
|
|
266
|
+
roomPages: 0,
|
|
267
|
+
artifacts: 0,
|
|
268
|
+
sources: 0,
|
|
269
|
+
errors: [],
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
function compareByTitle(left, right) {
|
|
273
|
+
return left.title.localeCompare(right.title) || left.id.localeCompare(right.id);
|
|
274
|
+
}
|
|
275
|
+
function limitRecords(records, limit) {
|
|
276
|
+
if (typeof limit !== 'number')
|
|
277
|
+
return records;
|
|
278
|
+
if (!Number.isFinite(limit))
|
|
279
|
+
return records;
|
|
280
|
+
return records.slice(0, Math.max(0, Math.trunc(limit)));
|
|
281
|
+
}
|
|
282
|
+
function readHomeAssistantObjectId(node, ...keys) {
|
|
283
|
+
const homeAssistant = readRecord(node.metadata.homeAssistant);
|
|
284
|
+
for (const key of keys) {
|
|
285
|
+
const value = homeAssistant[key];
|
|
286
|
+
if (typeof value === 'string' && value.trim())
|
|
287
|
+
return value.trim();
|
|
288
|
+
}
|
|
289
|
+
return undefined;
|
|
290
|
+
}
|
|
291
|
+
function resolveRoomTitle(nodes, areaId) {
|
|
292
|
+
if (!areaId)
|
|
293
|
+
return undefined;
|
|
294
|
+
return (findHomeAssistantNode(nodes, 'ha_area', areaId)
|
|
295
|
+
?? findHomeAssistantNode(nodes, 'ha_room', areaId))?.title;
|
|
296
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { KnowledgeEdgeRecord, KnowledgeNodeKind, KnowledgeReferenceKind, KnowledgeIssueUpsertInput } from '../types.js';
|
|
1
|
+
import type { KnowledgeEdgeRecord, KnowledgeNodeKind, KnowledgeSourceRecord, KnowledgeReferenceKind, KnowledgeIssueUpsertInput } from '../types.js';
|
|
2
2
|
import type { HomeGraphKnowledgeTarget, HomeGraphNodeKind, HomeGraphObjectInput, HomeGraphObjectKind, HomeGraphSpaceInput } from './types.js';
|
|
3
3
|
export declare const HOME_GRAPH_CONNECTOR_ID = "homeassistant";
|
|
4
4
|
export declare function resolveHomeGraphSpace(input?: HomeGraphSpaceInput): {
|
|
@@ -23,6 +23,7 @@ export declare function buildHomeGraphNodeInput(spaceId: string, installationId:
|
|
|
23
23
|
readonly metadata: Record<string, unknown>;
|
|
24
24
|
};
|
|
25
25
|
export declare function edgeIsActive(edge: KnowledgeEdgeRecord): boolean;
|
|
26
|
+
export declare function isGeneratedPageSource(source: KnowledgeSourceRecord): boolean;
|
|
26
27
|
export declare function belongsToSpace(record: {
|
|
27
28
|
readonly metadata?: Record<string, unknown>;
|
|
28
29
|
} | undefined | null, spaceId: string): boolean;
|