@pellux/goodvibes-sdk 1.2.0 → 1.3.0
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/contracts/artifacts/operator-contract.json +26 -2
- package/dist/platform/companion/companion-chat-manager.d.ts +6 -12
- package/dist/platform/companion/companion-chat-manager.d.ts.map +1 -1
- package/dist/platform/companion/companion-chat-manager.js +8 -2
- package/dist/platform/config/index.d.ts +2 -1
- package/dist/platform/config/index.d.ts.map +1 -1
- package/dist/platform/config/index.js +1 -0
- package/dist/platform/config/manager.d.ts +35 -0
- package/dist/platform/config/manager.d.ts.map +1 -1
- package/dist/platform/config/manager.js +98 -2
- package/dist/platform/config/shared-config-tier.d.ts +51 -0
- package/dist/platform/config/shared-config-tier.d.ts.map +1 -0
- package/dist/platform/config/shared-config-tier.js +127 -0
- package/dist/platform/control-plane/operator-contract-schemas-knowledge.d.ts.map +1 -1
- package/dist/platform/control-plane/operator-contract-schemas-knowledge.js +6 -1
- package/dist/platform/control-plane/operator-contract-schemas-runtime.d.ts.map +1 -1
- package/dist/platform/control-plane/operator-contract-schemas-runtime.js +2 -1
- package/dist/platform/daemon/facade-composition.d.ts.map +1 -1
- package/dist/platform/daemon/facade-composition.js +1 -0
- package/dist/platform/daemon/homeassistant-chat.d.ts +4 -1
- package/dist/platform/daemon/homeassistant-chat.d.ts.map +1 -1
- package/dist/platform/daemon/homeassistant-chat.js +1 -1
- package/dist/platform/daemon/http/homeassistant-routes.d.ts.map +1 -1
- package/dist/platform/daemon/http/homeassistant-routes.js +28 -2
- package/dist/platform/integrations/webhooks.d.ts +15 -0
- package/dist/platform/integrations/webhooks.d.ts.map +1 -1
- package/dist/platform/integrations/webhooks.js +18 -0
- package/dist/platform/knowledge/extraction-policy.d.ts +12 -1
- package/dist/platform/knowledge/extraction-policy.d.ts.map +1 -1
- package/dist/platform/knowledge/extraction-policy.js +19 -1
- package/dist/platform/knowledge/graphql-schema.d.ts +1 -1
- package/dist/platform/knowledge/graphql-schema.d.ts.map +1 -1
- package/dist/platform/knowledge/graphql-schema.js +5 -0
- package/dist/platform/knowledge/home-graph/index.d.ts.map +1 -1
- package/dist/platform/knowledge/home-graph/index.js +4 -0
- package/dist/platform/knowledge/home-graph/link.d.ts +2 -2
- package/dist/platform/knowledge/home-graph/link.d.ts.map +1 -1
- package/dist/platform/knowledge/home-graph/link.js +60 -9
- package/dist/platform/knowledge/home-graph/refinement.d.ts +14 -9
- package/dist/platform/knowledge/home-graph/refinement.d.ts.map +1 -1
- package/dist/platform/knowledge/home-graph/refinement.js +18 -3
- package/dist/platform/knowledge/home-graph/reset.js +21 -4
- package/dist/platform/knowledge/home-graph/service.d.ts +10 -11
- package/dist/platform/knowledge/home-graph/service.d.ts.map +1 -1
- package/dist/platform/knowledge/home-graph/triage.d.ts +103 -0
- package/dist/platform/knowledge/home-graph/triage.d.ts.map +1 -0
- package/dist/platform/knowledge/home-graph/triage.js +362 -0
- package/dist/platform/knowledge/home-graph/types.d.ts +15 -0
- package/dist/platform/knowledge/home-graph/types.d.ts.map +1 -1
- package/dist/platform/knowledge/knowledge-api.d.ts +6 -0
- package/dist/platform/knowledge/knowledge-api.d.ts.map +1 -1
- package/dist/platform/knowledge/knowledge-api.js +5 -0
- package/dist/platform/knowledge/knowledge-history-types.d.ts +56 -0
- package/dist/platform/knowledge/knowledge-history-types.d.ts.map +1 -0
- package/dist/platform/knowledge/knowledge-history-types.js +1 -0
- package/dist/platform/knowledge/packet.d.ts.map +1 -1
- package/dist/platform/knowledge/packet.js +27 -3
- package/dist/platform/knowledge/scope-records.js +4 -2
- package/dist/platform/knowledge/semantic/answer-gaps.d.ts +8 -0
- package/dist/platform/knowledge/semantic/answer-gaps.d.ts.map +1 -1
- package/dist/platform/knowledge/semantic/answer-gaps.js +26 -6
- package/dist/platform/knowledge/semantic/enrichment.d.ts.map +1 -1
- package/dist/platform/knowledge/semantic/enrichment.js +15 -13
- package/dist/platform/knowledge/semantic/graph-index.d.ts.map +1 -1
- package/dist/platform/knowledge/semantic/graph-index.js +3 -1
- package/dist/platform/knowledge/semantic/service.d.ts +7 -0
- package/dist/platform/knowledge/semantic/service.d.ts.map +1 -1
- package/dist/platform/knowledge/semantic/service.js +10 -1
- package/dist/platform/knowledge/service-node-admin.d.ts +46 -0
- package/dist/platform/knowledge/service-node-admin.d.ts.map +1 -0
- package/dist/platform/knowledge/service-node-admin.js +72 -0
- package/dist/platform/knowledge/service.d.ts +24 -20
- package/dist/platform/knowledge/service.d.ts.map +1 -1
- package/dist/platform/knowledge/service.js +23 -47
- package/dist/platform/knowledge/store-config.d.ts +34 -0
- package/dist/platform/knowledge/store-config.d.ts.map +1 -1
- package/dist/platform/knowledge/store-config.js +23 -0
- package/dist/platform/knowledge/store-load.d.ts +3 -1
- package/dist/platform/knowledge/store-load.d.ts.map +1 -1
- package/dist/platform/knowledge/store-load.js +3 -1
- package/dist/platform/knowledge/store-node-history.d.ts +49 -0
- package/dist/platform/knowledge/store-node-history.d.ts.map +1 -0
- package/dist/platform/knowledge/store-node-history.js +331 -0
- package/dist/platform/knowledge/store-record-delete.d.ts +25 -0
- package/dist/platform/knowledge/store-record-delete.d.ts.map +1 -0
- package/dist/platform/knowledge/store-record-delete.js +84 -0
- package/dist/platform/knowledge/store-schema.d.ts +3 -1
- package/dist/platform/knowledge/store-schema.d.ts.map +1 -1
- package/dist/platform/knowledge/store-schema.js +66 -0
- package/dist/platform/knowledge/store.d.ts +19 -1
- package/dist/platform/knowledge/store.d.ts.map +1 -1
- package/dist/platform/knowledge/store.js +69 -108
- package/dist/platform/knowledge/types.d.ts +18 -0
- package/dist/platform/knowledge/types.d.ts.map +1 -1
- package/dist/platform/providers/registry.d.ts +18 -0
- package/dist/platform/providers/registry.d.ts.map +1 -1
- package/dist/platform/providers/registry.js +49 -3
- package/dist/platform/providers/runtime-snapshot.d.ts.map +1 -1
- package/dist/platform/providers/runtime-snapshot.js +14 -2
- package/dist/platform/runtime/memory-spine/client.d.ts +12 -0
- package/dist/platform/runtime/memory-spine/client.d.ts.map +1 -1
- package/dist/platform/runtime/memory-spine/client.js +14 -4
- package/dist/platform/runtime/memory-spine/index.d.ts +1 -0
- package/dist/platform/runtime/memory-spine/index.d.ts.map +1 -1
- package/dist/platform/runtime/memory-spine/index.js +1 -0
- package/dist/platform/runtime/memory-spine/recall-snapshot.d.ts.map +1 -1
- package/dist/platform/runtime/memory-spine/recall-snapshot.js +16 -3
- package/dist/platform/runtime/memory-spine/wire-verb-availability.d.ts +59 -0
- package/dist/platform/runtime/memory-spine/wire-verb-availability.d.ts.map +1 -0
- package/dist/platform/runtime/memory-spine/wire-verb-availability.js +114 -0
- package/dist/platform/runtime/services.d.ts.map +1 -1
- package/dist/platform/runtime/services.js +3 -12
- package/dist/platform/state/memory-recall-contract.d.ts +7 -0
- package/dist/platform/state/memory-recall-contract.d.ts.map +1 -1
- package/dist/platform/state/memory-recall-contract.js +2 -0
- package/dist/platform/utils/notify.d.ts +25 -1
- package/dist/platform/utils/notify.d.ts.map +1 -1
- package/dist/platform/utils/notify.js +29 -1
- package/dist/platform/version.js +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { nowMs } from './store-schema.js';
|
|
2
|
+
import { DEFAULT_NODE_AUTO_ACCEPT_CONFIDENCE } from './store-config.js';
|
|
3
|
+
export function writeKnowledgeNodeRow(sqlite, record) {
|
|
4
|
+
sqlite.run(`
|
|
5
|
+
INSERT OR REPLACE INTO knowledge_nodes (
|
|
6
|
+
id, kind, slug, title, summary, aliases, status, confidence, source_id, metadata, created_at, updated_at
|
|
7
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
8
|
+
`, [
|
|
9
|
+
record.id,
|
|
10
|
+
record.kind,
|
|
11
|
+
record.slug,
|
|
12
|
+
record.title,
|
|
13
|
+
record.summary ?? null,
|
|
14
|
+
JSON.stringify([...record.aliases]),
|
|
15
|
+
record.status,
|
|
16
|
+
record.confidence,
|
|
17
|
+
record.sourceId ?? null,
|
|
18
|
+
JSON.stringify(record.metadata),
|
|
19
|
+
record.createdAt,
|
|
20
|
+
record.updatedAt,
|
|
21
|
+
]);
|
|
22
|
+
}
|
|
23
|
+
export function clampConfidence(value) {
|
|
24
|
+
// A non-finite value (NaN/Infinity — slips past a `??` guard, which only catches
|
|
25
|
+
// null/undefined) resolves to the auto-accept default rather than poisoning the
|
|
26
|
+
// gate with `NaN >= threshold === false` and silently drafting the node forever.
|
|
27
|
+
if (!Number.isFinite(value))
|
|
28
|
+
return DEFAULT_NODE_AUTO_ACCEPT_CONFIDENCE;
|
|
29
|
+
// Confidence is a 0-100 score everywhere. A fractional value below 1 (e.g. 0.9) is
|
|
30
|
+
// almost certainly a 0-1 probability a producer/LLM emitted despite that contract —
|
|
31
|
+
// scale it up so 0.9 → 90 instead of Math.round truncating it to a draft-holding 1.
|
|
32
|
+
const scaled = value > 0 && value < 1 ? value * 100 : value;
|
|
33
|
+
return Math.max(0, Math.min(100, Math.round(scaled)));
|
|
34
|
+
}
|
|
35
|
+
function isPlainRecord(value) {
|
|
36
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
37
|
+
}
|
|
38
|
+
function readNodeReviewer(metadata) {
|
|
39
|
+
const review = metadata.review;
|
|
40
|
+
if (!isPlainRecord(review))
|
|
41
|
+
return undefined;
|
|
42
|
+
const reviewer = review.reviewer;
|
|
43
|
+
return typeof reviewer === 'string' && reviewer.trim().length > 0 ? reviewer.trim() : 'knowledge-review';
|
|
44
|
+
}
|
|
45
|
+
function readNodeProvenanceState(metadata) {
|
|
46
|
+
const provenance = metadata.reviewProvenance;
|
|
47
|
+
if (!isPlainRecord(provenance))
|
|
48
|
+
return undefined;
|
|
49
|
+
return typeof provenance.state === 'string' ? provenance.state : undefined;
|
|
50
|
+
}
|
|
51
|
+
function stampNodeProvenance(metadata, provenance) {
|
|
52
|
+
return { ...metadata, reviewProvenance: provenance };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Decide a node's effective status and stamp honest review provenance so a node is
|
|
56
|
+
* never silently active. (Invariants 2 & 4.)
|
|
57
|
+
* - An explicit producer status (or a review that applied facts) is honored and
|
|
58
|
+
* labelled 'explicit'/'reviewed'.
|
|
59
|
+
* - An already-active node stays active; if it predates the gate it is labelled
|
|
60
|
+
* 'pre-gate' (folds/migrations never get downgraded).
|
|
61
|
+
* - A new/draft node auto-accepts at/above the configured confidence threshold
|
|
62
|
+
* (labelled 'auto-accepted') or is held as 'draft' pending review otherwise.
|
|
63
|
+
*/
|
|
64
|
+
export function resolveNodeActivation(args) {
|
|
65
|
+
const { input, existing, confidence, metadata, now, autoAcceptConfidence } = args;
|
|
66
|
+
const reviewer = readNodeReviewer(metadata);
|
|
67
|
+
const reviewedByFacts = reviewer !== undefined;
|
|
68
|
+
if (input.status) {
|
|
69
|
+
const state = reviewedByFacts ? 'reviewed' : 'explicit';
|
|
70
|
+
return {
|
|
71
|
+
status: input.status,
|
|
72
|
+
metadata: stampNodeProvenance(metadata, {
|
|
73
|
+
state,
|
|
74
|
+
reason: reviewedByFacts
|
|
75
|
+
? `reviewed: status set to '${input.status}' by ${reviewer}`
|
|
76
|
+
: `explicit: producer set status '${input.status}'`,
|
|
77
|
+
decidedAt: now,
|
|
78
|
+
...(reviewer !== undefined ? { reviewer } : {}),
|
|
79
|
+
}),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (reviewedByFacts && existing) {
|
|
83
|
+
return {
|
|
84
|
+
status: existing.status,
|
|
85
|
+
metadata: stampNodeProvenance(metadata, {
|
|
86
|
+
state: 'reviewed',
|
|
87
|
+
reason: `reviewed by ${reviewer}`,
|
|
88
|
+
decidedAt: now,
|
|
89
|
+
reviewer,
|
|
90
|
+
}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (existing && existing.status === 'active') {
|
|
94
|
+
if (readNodeProvenanceState(metadata))
|
|
95
|
+
return { status: 'active', metadata };
|
|
96
|
+
return {
|
|
97
|
+
status: 'active',
|
|
98
|
+
metadata: stampNodeProvenance(metadata, {
|
|
99
|
+
state: 'pre-gate',
|
|
100
|
+
reason: 'pre-gate: node was active before the review gate; left active',
|
|
101
|
+
decidedAt: now,
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (confidence >= autoAcceptConfidence) {
|
|
106
|
+
return {
|
|
107
|
+
status: 'active',
|
|
108
|
+
metadata: stampNodeProvenance(metadata, {
|
|
109
|
+
state: 'auto-accepted',
|
|
110
|
+
reason: `auto-accepted: confidence ${confidence} >= auto-accept threshold ${autoAcceptConfidence}`,
|
|
111
|
+
decidedAt: now,
|
|
112
|
+
threshold: autoAcceptConfidence,
|
|
113
|
+
}),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
status: 'draft',
|
|
118
|
+
metadata: stampNodeProvenance(metadata, {
|
|
119
|
+
state: 'pending-review',
|
|
120
|
+
reason: `pending review: confidence ${confidence} < auto-accept threshold ${autoAcceptConfidence}`,
|
|
121
|
+
decidedAt: now,
|
|
122
|
+
threshold: autoAcceptConfidence,
|
|
123
|
+
}),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Record an append-only revision on a content-changing upsert: preserve the
|
|
128
|
+
* overwritten prior content and note what changed. (Invariant 8.)
|
|
129
|
+
*/
|
|
130
|
+
export function recordKnowledgeNodeRevisions(sqlite, nodeRevisions, record, existing, now) {
|
|
131
|
+
const list = nodeRevisions.get(record.id) ?? [];
|
|
132
|
+
if (existing) {
|
|
133
|
+
const changedFields = diffKnowledgeNodeFields(existing, record);
|
|
134
|
+
if (changedFields.length === 0)
|
|
135
|
+
return; // idempotent re-upsert (e.g. a provenance-only restamp)
|
|
136
|
+
if (list.length === 0) {
|
|
137
|
+
// First tracked change to a pre-existing node: preserve the overwritten prior
|
|
138
|
+
// content as the baseline revision so it is never lost.
|
|
139
|
+
appendNodeRevision(sqlite, list, existing, 'create', [], now);
|
|
140
|
+
}
|
|
141
|
+
appendNodeRevision(sqlite, list, record, 'update', changedFields, now);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
appendNodeRevision(sqlite, list, record, 'create', [], now);
|
|
145
|
+
}
|
|
146
|
+
nodeRevisions.set(record.id, list);
|
|
147
|
+
}
|
|
148
|
+
export function listKnowledgeNodeRevisions(nodeRevisions, nodeId) {
|
|
149
|
+
return [...(nodeRevisions.get(nodeId) ?? [])].sort((a, b) => a.revision - b.revision);
|
|
150
|
+
}
|
|
151
|
+
function appendNodeRevision(sqlite, list, snapshot, changeKind, changedFields, now) {
|
|
152
|
+
const revision = (list[list.length - 1]?.revision ?? 0) + 1;
|
|
153
|
+
const rev = {
|
|
154
|
+
id: `noderev-${snapshot.id}-${revision}`,
|
|
155
|
+
nodeId: snapshot.id,
|
|
156
|
+
revision,
|
|
157
|
+
changeKind,
|
|
158
|
+
changedFields: [...changedFields],
|
|
159
|
+
kind: snapshot.kind,
|
|
160
|
+
slug: snapshot.slug,
|
|
161
|
+
title: snapshot.title,
|
|
162
|
+
...(snapshot.summary ? { summary: snapshot.summary } : {}),
|
|
163
|
+
aliases: [...snapshot.aliases],
|
|
164
|
+
status: snapshot.status,
|
|
165
|
+
confidence: snapshot.confidence,
|
|
166
|
+
...(snapshot.sourceId ? { sourceId: snapshot.sourceId } : {}),
|
|
167
|
+
metadata: snapshot.metadata,
|
|
168
|
+
nodeCreatedAt: snapshot.createdAt,
|
|
169
|
+
nodeUpdatedAt: snapshot.updatedAt,
|
|
170
|
+
recordedAt: now,
|
|
171
|
+
};
|
|
172
|
+
sqlite.run(`
|
|
173
|
+
INSERT OR REPLACE INTO knowledge_node_revisions (
|
|
174
|
+
id, node_id, revision, change_kind, changed_fields, kind, slug, title, summary,
|
|
175
|
+
aliases, status, confidence, source_id, metadata, node_created_at, node_updated_at, recorded_at
|
|
176
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
177
|
+
`, [
|
|
178
|
+
rev.id,
|
|
179
|
+
rev.nodeId,
|
|
180
|
+
rev.revision,
|
|
181
|
+
rev.changeKind,
|
|
182
|
+
JSON.stringify(rev.changedFields),
|
|
183
|
+
rev.kind,
|
|
184
|
+
rev.slug,
|
|
185
|
+
rev.title,
|
|
186
|
+
rev.summary ?? null,
|
|
187
|
+
JSON.stringify([...rev.aliases]),
|
|
188
|
+
rev.status,
|
|
189
|
+
rev.confidence,
|
|
190
|
+
rev.sourceId ?? null,
|
|
191
|
+
JSON.stringify(rev.metadata),
|
|
192
|
+
rev.nodeCreatedAt,
|
|
193
|
+
rev.nodeUpdatedAt,
|
|
194
|
+
rev.recordedAt,
|
|
195
|
+
]);
|
|
196
|
+
list.push(rev);
|
|
197
|
+
}
|
|
198
|
+
function diffKnowledgeNodeFields(prev, next) {
|
|
199
|
+
const changed = [];
|
|
200
|
+
// Identity fields are tracked: an id-based upsert that changes ONLY the kind or
|
|
201
|
+
// slug (all other fields identical) is still a real content change and must
|
|
202
|
+
// record a revision — otherwise `changedFields` is empty, the early return in
|
|
203
|
+
// recordKnowledgeNodeRevisions fires, and the prior slug/kind is lost from
|
|
204
|
+
// history with no trace.
|
|
205
|
+
if (prev.kind !== next.kind)
|
|
206
|
+
changed.push('kind');
|
|
207
|
+
if (prev.slug !== next.slug)
|
|
208
|
+
changed.push('slug');
|
|
209
|
+
if (prev.title !== next.title)
|
|
210
|
+
changed.push('title');
|
|
211
|
+
if ((prev.summary ?? '') !== (next.summary ?? ''))
|
|
212
|
+
changed.push('summary');
|
|
213
|
+
if (prev.status !== next.status)
|
|
214
|
+
changed.push('status');
|
|
215
|
+
if (prev.confidence !== next.confidence)
|
|
216
|
+
changed.push('confidence');
|
|
217
|
+
if ((prev.sourceId ?? '') !== (next.sourceId ?? ''))
|
|
218
|
+
changed.push('sourceId');
|
|
219
|
+
if (!sameStringSet(prev.aliases, next.aliases))
|
|
220
|
+
changed.push('aliases');
|
|
221
|
+
if (stableMetadataForDiff(prev.metadata) !== stableMetadataForDiff(next.metadata))
|
|
222
|
+
changed.push('metadata');
|
|
223
|
+
return changed;
|
|
224
|
+
}
|
|
225
|
+
function sameStringSet(a, b) {
|
|
226
|
+
if (a.length !== b.length)
|
|
227
|
+
return false;
|
|
228
|
+
const set = new Set(a);
|
|
229
|
+
return b.every((entry) => set.has(entry));
|
|
230
|
+
}
|
|
231
|
+
// Compare metadata for revision purposes ignoring the volatile review-provenance
|
|
232
|
+
// stamp (its decidedAt changes on every write); a provenance-only restamp must not
|
|
233
|
+
// count as a content change.
|
|
234
|
+
function stableMetadataForDiff(metadata) {
|
|
235
|
+
const { reviewProvenance: _reviewProvenance, ...rest } = metadata;
|
|
236
|
+
return stableStringify(rest);
|
|
237
|
+
}
|
|
238
|
+
function stableStringify(value) {
|
|
239
|
+
if (Array.isArray(value))
|
|
240
|
+
return `[${value.map((entry) => stableStringify(entry)).join(',')}]`;
|
|
241
|
+
if (isPlainRecord(value)) {
|
|
242
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`).join(',')}}`;
|
|
243
|
+
}
|
|
244
|
+
return JSON.stringify(value ?? null);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Merge one node into another: re-point every edge that referenced the loser onto
|
|
248
|
+
* the winner (deduping and dropping self-loops), record a `merged_into` edge, and
|
|
249
|
+
* mark the loser 'stale' with a `mergedInto` stamp. Keeps cross-references live on
|
|
250
|
+
* the surviving node. (Invariant 7.)
|
|
251
|
+
*/
|
|
252
|
+
export async function mergeKnowledgeNodes(store, loserId, winnerId) {
|
|
253
|
+
if (loserId === winnerId)
|
|
254
|
+
return { merged: false, repointedEdges: 0 };
|
|
255
|
+
const loser = store.getNode(loserId);
|
|
256
|
+
const winner = store.getNode(winnerId);
|
|
257
|
+
if (!loser || !winner)
|
|
258
|
+
return { merged: false, repointedEdges: 0 };
|
|
259
|
+
const mergedAt = nowMs();
|
|
260
|
+
let repointedEdges = 0;
|
|
261
|
+
await store.batch(async () => {
|
|
262
|
+
for (const edge of store.listEdges()) {
|
|
263
|
+
const fromMatch = edge.fromKind === 'node' && edge.fromId === loserId;
|
|
264
|
+
const toMatch = edge.toKind === 'node' && edge.toId === loserId;
|
|
265
|
+
if (!fromMatch && !toMatch)
|
|
266
|
+
continue;
|
|
267
|
+
const newFromId = fromMatch ? winnerId : edge.fromId;
|
|
268
|
+
const newToId = toMatch ? winnerId : edge.toId;
|
|
269
|
+
await store.deleteEdge(edge.id);
|
|
270
|
+
if (newFromId === newToId && edge.fromKind === edge.toKind)
|
|
271
|
+
continue;
|
|
272
|
+
await store.upsertEdge({
|
|
273
|
+
fromKind: edge.fromKind,
|
|
274
|
+
fromId: newFromId,
|
|
275
|
+
toKind: edge.toKind,
|
|
276
|
+
toId: newToId,
|
|
277
|
+
relation: edge.relation,
|
|
278
|
+
weight: edge.weight,
|
|
279
|
+
metadata: { ...edge.metadata, repointedFromNodeId: loserId, repointedAt: mergedAt },
|
|
280
|
+
});
|
|
281
|
+
repointedEdges += 1;
|
|
282
|
+
}
|
|
283
|
+
await store.upsertEdge({
|
|
284
|
+
fromKind: 'node',
|
|
285
|
+
fromId: loserId,
|
|
286
|
+
toKind: 'node',
|
|
287
|
+
toId: winnerId,
|
|
288
|
+
relation: 'merged_into',
|
|
289
|
+
metadata: { mergedAt },
|
|
290
|
+
});
|
|
291
|
+
await store.upsertNode({
|
|
292
|
+
id: loser.id,
|
|
293
|
+
kind: loser.kind,
|
|
294
|
+
slug: loser.slug,
|
|
295
|
+
title: loser.title,
|
|
296
|
+
...(loser.summary ? { summary: loser.summary } : {}),
|
|
297
|
+
aliases: [...loser.aliases],
|
|
298
|
+
status: 'stale',
|
|
299
|
+
confidence: loser.confidence,
|
|
300
|
+
...(loser.sourceId ? { sourceId: loser.sourceId } : {}),
|
|
301
|
+
metadata: { ...loser.metadata, mergedInto: winnerId, mergedAt },
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
return { merged: true, repointedEdges };
|
|
305
|
+
}
|
|
306
|
+
export function upsertKnowledgeSemanticEnrichmentState(sqlite, states, input) {
|
|
307
|
+
const existing = states.get(input.sourceId);
|
|
308
|
+
const now = nowMs();
|
|
309
|
+
const record = {
|
|
310
|
+
sourceId: input.sourceId,
|
|
311
|
+
...(input.textHash ? { textHash: input.textHash } : {}),
|
|
312
|
+
...(typeof input.enrichedAt === 'number' ? { enrichedAt: input.enrichedAt } : {}),
|
|
313
|
+
metadata: input.metadata ?? {},
|
|
314
|
+
createdAt: existing?.createdAt ?? now,
|
|
315
|
+
updatedAt: now,
|
|
316
|
+
};
|
|
317
|
+
sqlite.run(`
|
|
318
|
+
INSERT OR REPLACE INTO knowledge_semantic_enrichment_state (
|
|
319
|
+
source_id, text_hash, enriched_at, metadata, created_at, updated_at
|
|
320
|
+
) VALUES (?, ?, ?, ?, ?, ?)
|
|
321
|
+
`, [
|
|
322
|
+
record.sourceId,
|
|
323
|
+
record.textHash ?? null,
|
|
324
|
+
record.enrichedAt ?? null,
|
|
325
|
+
JSON.stringify(record.metadata),
|
|
326
|
+
record.createdAt,
|
|
327
|
+
record.updatedAt,
|
|
328
|
+
]);
|
|
329
|
+
states.set(record.sourceId, record);
|
|
330
|
+
return record;
|
|
331
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SQLiteStore } from '../state/sqlite-store.js';
|
|
2
|
+
import type { KnowledgeConsolidationCandidateRecord, KnowledgeEdgeRecord, KnowledgeExtractionRecord, KnowledgeIssueRecord, KnowledgeNodeRecord, KnowledgeNodeRevisionRecord, KnowledgeRefinementTaskRecord, KnowledgeSemanticEnrichmentStateRecord, KnowledgeSourceRecord, KnowledgeUsageRecord } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* The store internals needed to cascade a single-record hard delete. Both node and
|
|
5
|
+
* source deletes cascade edges, issues, usage records, consolidation candidates and
|
|
6
|
+
* refinement tasks (Defect 7 closed the refinement-task gap); node delete also
|
|
7
|
+
* purges revision history and source delete purges derived extraction/enrichment
|
|
8
|
+
* rows. Honest hard delete — no soft-hide. (Defect 6.)
|
|
9
|
+
*/
|
|
10
|
+
export interface KnowledgeRecordDeleteView {
|
|
11
|
+
readonly sqlite: SQLiteStore;
|
|
12
|
+
readonly sources: Map<string, KnowledgeSourceRecord>;
|
|
13
|
+
readonly nodes: Map<string, KnowledgeNodeRecord>;
|
|
14
|
+
readonly edges: Map<string, KnowledgeEdgeRecord>;
|
|
15
|
+
readonly issues: Map<string, KnowledgeIssueRecord>;
|
|
16
|
+
readonly extractions: Map<string, KnowledgeExtractionRecord>;
|
|
17
|
+
readonly usageRecords: Map<string, KnowledgeUsageRecord>;
|
|
18
|
+
readonly consolidationCandidates: Map<string, KnowledgeConsolidationCandidateRecord>;
|
|
19
|
+
readonly refinementTasks: Map<string, KnowledgeRefinementTaskRecord>;
|
|
20
|
+
readonly nodeRevisions: Map<string, KnowledgeNodeRevisionRecord[]>;
|
|
21
|
+
readonly semanticEnrichmentStates: Map<string, KnowledgeSemanticEnrichmentStateRecord>;
|
|
22
|
+
}
|
|
23
|
+
export declare function deleteKnowledgeNodeRecord(view: KnowledgeRecordDeleteView, id: string): boolean;
|
|
24
|
+
export declare function deleteKnowledgeSourceRecord(view: KnowledgeRecordDeleteView, id: string): boolean;
|
|
25
|
+
//# sourceMappingURL=store-record-delete.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-record-delete.d.ts","sourceRoot":"","sources":["../../../src/platform/knowledge/store-record-delete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EACV,qCAAqC,EACrC,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,mBAAmB,EACnB,2BAA2B,EAC3B,6BAA6B,EAC7B,sCAAsC,EACtC,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IACnD,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IAC7D,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IACzD,QAAQ,CAAC,uBAAuB,EAAE,GAAG,CAAC,MAAM,EAAE,qCAAqC,CAAC,CAAC;IACrF,QAAQ,CAAC,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,6BAA6B,CAAC,CAAC;IACrE,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,2BAA2B,EAAE,CAAC,CAAC;IACnE,QAAQ,CAAC,wBAAwB,EAAE,GAAG,CAAC,MAAM,EAAE,sCAAsC,CAAC,CAAC;CACxF;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,yBAAyB,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAqC9F;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,yBAAyB,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CA2ChG"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export function deleteKnowledgeNodeRecord(view, id) {
|
|
2
|
+
if (!view.nodes.has(id))
|
|
3
|
+
return false;
|
|
4
|
+
for (const [edgeId, edge] of [...view.edges.entries()]) {
|
|
5
|
+
if ((edge.fromKind === 'node' && edge.fromId === id) || (edge.toKind === 'node' && edge.toId === id)) {
|
|
6
|
+
view.sqlite.run('DELETE FROM knowledge_edges WHERE id = ?', [edgeId]);
|
|
7
|
+
view.edges.delete(edgeId);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
for (const [issueId, issue] of [...view.issues.entries()]) {
|
|
11
|
+
if (issue.nodeId === id) {
|
|
12
|
+
view.sqlite.run('DELETE FROM knowledge_issues WHERE id = ?', [issueId]);
|
|
13
|
+
view.issues.delete(issueId);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
for (const [usageId, usage] of [...view.usageRecords.entries()]) {
|
|
17
|
+
if (usage.targetKind === 'node' && usage.targetId === id) {
|
|
18
|
+
view.sqlite.run('DELETE FROM knowledge_usage_records WHERE id = ?', [usageId]);
|
|
19
|
+
view.usageRecords.delete(usageId);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
for (const [candidateId, candidate] of [...view.consolidationCandidates.entries()]) {
|
|
23
|
+
if (candidate.subjectKind === 'node' && candidate.subjectId === id) {
|
|
24
|
+
view.sqlite.run('DELETE FROM knowledge_consolidation_candidates WHERE id = ?', [candidateId]);
|
|
25
|
+
view.consolidationCandidates.delete(candidateId);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
for (const [taskId, task] of [...view.refinementTasks.entries()]) {
|
|
29
|
+
if ((task.subjectKind === 'node' && task.subjectId === id) || task.gapId === id) {
|
|
30
|
+
view.sqlite.run('DELETE FROM knowledge_refinement_tasks WHERE id = ?', [taskId]);
|
|
31
|
+
view.refinementTasks.delete(taskId);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
view.sqlite.run('DELETE FROM knowledge_node_revisions WHERE node_id = ?', [id]);
|
|
35
|
+
view.nodeRevisions.delete(id);
|
|
36
|
+
view.sqlite.run('DELETE FROM knowledge_nodes WHERE id = ?', [id]);
|
|
37
|
+
view.nodes.delete(id);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
export function deleteKnowledgeSourceRecord(view, id) {
|
|
41
|
+
if (!view.sources.has(id))
|
|
42
|
+
return false;
|
|
43
|
+
for (const [edgeId, edge] of [...view.edges.entries()]) {
|
|
44
|
+
if ((edge.fromKind === 'source' && edge.fromId === id) || (edge.toKind === 'source' && edge.toId === id)) {
|
|
45
|
+
view.sqlite.run('DELETE FROM knowledge_edges WHERE id = ?', [edgeId]);
|
|
46
|
+
view.edges.delete(edgeId);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
for (const [extractionId, extraction] of [...view.extractions.entries()]) {
|
|
50
|
+
if (extraction.sourceId === id) {
|
|
51
|
+
view.sqlite.run('DELETE FROM knowledge_extractions WHERE id = ?', [extractionId]);
|
|
52
|
+
view.extractions.delete(extractionId);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
for (const [issueId, issue] of [...view.issues.entries()]) {
|
|
56
|
+
if (issue.sourceId === id) {
|
|
57
|
+
view.sqlite.run('DELETE FROM knowledge_issues WHERE id = ?', [issueId]);
|
|
58
|
+
view.issues.delete(issueId);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const [usageId, usage] of [...view.usageRecords.entries()]) {
|
|
62
|
+
if (usage.targetKind === 'source' && usage.targetId === id) {
|
|
63
|
+
view.sqlite.run('DELETE FROM knowledge_usage_records WHERE id = ?', [usageId]);
|
|
64
|
+
view.usageRecords.delete(usageId);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
for (const [candidateId, candidate] of [...view.consolidationCandidates.entries()]) {
|
|
68
|
+
if (candidate.subjectKind === 'source' && candidate.subjectId === id) {
|
|
69
|
+
view.sqlite.run('DELETE FROM knowledge_consolidation_candidates WHERE id = ?', [candidateId]);
|
|
70
|
+
view.consolidationCandidates.delete(candidateId);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const [taskId, task] of [...view.refinementTasks.entries()]) {
|
|
74
|
+
if (task.subjectKind === 'source' && task.subjectId === id) {
|
|
75
|
+
view.sqlite.run('DELETE FROM knowledge_refinement_tasks WHERE id = ?', [taskId]);
|
|
76
|
+
view.refinementTasks.delete(taskId);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
view.sqlite.run('DELETE FROM knowledge_semantic_enrichment_state WHERE source_id = ?', [id]);
|
|
80
|
+
view.semanticEnrichmentStates.delete(id);
|
|
81
|
+
view.sqlite.run('DELETE FROM knowledge_sources WHERE id = ?', [id]);
|
|
82
|
+
view.sources.delete(id);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { KnowledgeConsolidationCandidateRecord, KnowledgeConsolidationReportRecord, KnowledgeEdgeRecord, KnowledgeExtractionRecord, KnowledgeIssueRecord, KnowledgeIssueUpsertInput, KnowledgeJobRunRecord, KnowledgeNodeRecord, KnowledgeScheduleRecord, KnowledgeSourceRecord, KnowledgeRefinementTaskRecord, KnowledgeUsageRecord } from './types.js';
|
|
1
|
+
import type { KnowledgeConsolidationCandidateRecord, KnowledgeConsolidationReportRecord, KnowledgeEdgeRecord, KnowledgeExtractionRecord, KnowledgeIssueRecord, KnowledgeIssueUpsertInput, KnowledgeJobRunRecord, KnowledgeNodeRecord, KnowledgeScheduleRecord, KnowledgeSourceRecord, KnowledgeNodeRevisionRecord, KnowledgeSemanticEnrichmentStateRecord, KnowledgeRefinementTaskRecord, KnowledgeUsageRecord } from './types.js';
|
|
2
2
|
export declare const DEFAULT_KNOWLEDGE_DB_FILE = "knowledge-wiki.sqlite";
|
|
3
3
|
export declare function resolveKnowledgeDbPathFromControlPlaneDir(controlPlaneDir: string, dbFileName?: string): string;
|
|
4
4
|
export declare function nowMs(): number;
|
|
@@ -21,5 +21,7 @@ export declare function mapRefinementTaskRow(columns: string[], values: unknown[
|
|
|
21
21
|
export declare function mapUsageRow(columns: string[], values: unknown[]): KnowledgeUsageRecord;
|
|
22
22
|
export declare function mapCandidateRow(columns: string[], values: unknown[]): KnowledgeConsolidationCandidateRecord;
|
|
23
23
|
export declare function mapReportRow(columns: string[], values: unknown[]): KnowledgeConsolidationReportRecord;
|
|
24
|
+
export declare function mapNodeRevisionRow(columns: string[], values: unknown[]): KnowledgeNodeRevisionRecord;
|
|
25
|
+
export declare function mapSemanticEnrichmentStateRow(columns: string[], values: unknown[]): KnowledgeSemanticEnrichmentStateRecord;
|
|
24
26
|
export declare function mapScheduleRow(columns: string[], values: unknown[]): KnowledgeScheduleRecord;
|
|
25
27
|
//# sourceMappingURL=store-schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-schema.d.ts","sourceRoot":"","sources":["../../../src/platform/knowledge/store-schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,qCAAqC,EACrC,kCAAkC,EAClC,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"store-schema.d.ts","sourceRoot":"","sources":["../../../src/platform/knowledge/store-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -249,6 +249,39 @@ export function createSchema(db) {
|
|
|
249
249
|
)
|
|
250
250
|
`);
|
|
251
251
|
db.run(`CREATE INDEX IF NOT EXISTS idx_knowledge_schedules_job_id ON knowledge_schedules(job_id)`);
|
|
252
|
+
db.run(`
|
|
253
|
+
CREATE TABLE IF NOT EXISTS knowledge_node_revisions (
|
|
254
|
+
id TEXT PRIMARY KEY,
|
|
255
|
+
node_id TEXT NOT NULL,
|
|
256
|
+
revision INTEGER NOT NULL,
|
|
257
|
+
change_kind TEXT NOT NULL,
|
|
258
|
+
changed_fields TEXT NOT NULL DEFAULT '[]',
|
|
259
|
+
kind TEXT NOT NULL,
|
|
260
|
+
slug TEXT NOT NULL,
|
|
261
|
+
title TEXT NOT NULL,
|
|
262
|
+
summary TEXT,
|
|
263
|
+
aliases TEXT NOT NULL DEFAULT '[]',
|
|
264
|
+
status TEXT NOT NULL,
|
|
265
|
+
confidence INTEGER NOT NULL,
|
|
266
|
+
source_id TEXT,
|
|
267
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
268
|
+
node_created_at INTEGER NOT NULL,
|
|
269
|
+
node_updated_at INTEGER NOT NULL,
|
|
270
|
+
recorded_at INTEGER NOT NULL
|
|
271
|
+
)
|
|
272
|
+
`);
|
|
273
|
+
db.run(`CREATE UNIQUE INDEX IF NOT EXISTS idx_knowledge_node_revisions_unique ON knowledge_node_revisions(node_id, revision)`);
|
|
274
|
+
db.run(`CREATE INDEX IF NOT EXISTS idx_knowledge_node_revisions_node ON knowledge_node_revisions(node_id)`);
|
|
275
|
+
db.run(`
|
|
276
|
+
CREATE TABLE IF NOT EXISTS knowledge_semantic_enrichment_state (
|
|
277
|
+
source_id TEXT PRIMARY KEY,
|
|
278
|
+
text_hash TEXT,
|
|
279
|
+
enriched_at INTEGER,
|
|
280
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
281
|
+
created_at INTEGER NOT NULL,
|
|
282
|
+
updated_at INTEGER NOT NULL
|
|
283
|
+
)
|
|
284
|
+
`);
|
|
252
285
|
}
|
|
253
286
|
export function getKnowledgeSchemaStatements() {
|
|
254
287
|
const statements = [];
|
|
@@ -485,6 +518,39 @@ export function mapReportRow(columns, values) {
|
|
|
485
518
|
updatedAt: Number(row.updated_at),
|
|
486
519
|
};
|
|
487
520
|
}
|
|
521
|
+
export function mapNodeRevisionRow(columns, values) {
|
|
522
|
+
const row = rowObject(columns, values);
|
|
523
|
+
return {
|
|
524
|
+
id: String(row.id),
|
|
525
|
+
nodeId: String(row.node_id),
|
|
526
|
+
revision: Number(row.revision),
|
|
527
|
+
changeKind: String(row.change_kind),
|
|
528
|
+
changedFields: parseJsonValue(row.changed_fields, []),
|
|
529
|
+
kind: String(row.kind),
|
|
530
|
+
slug: String(row.slug),
|
|
531
|
+
title: String(row.title),
|
|
532
|
+
...(stableText(row.summary) ? { summary: String(row.summary) } : {}),
|
|
533
|
+
aliases: parseJsonValue(row.aliases, []),
|
|
534
|
+
status: String(row.status),
|
|
535
|
+
confidence: Number(row.confidence),
|
|
536
|
+
...(stableText(row.source_id) ? { sourceId: String(row.source_id) } : {}),
|
|
537
|
+
metadata: parseJsonValue(row.metadata, {}),
|
|
538
|
+
nodeCreatedAt: Number(row.node_created_at),
|
|
539
|
+
nodeUpdatedAt: Number(row.node_updated_at),
|
|
540
|
+
recordedAt: Number(row.recorded_at),
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
export function mapSemanticEnrichmentStateRow(columns, values) {
|
|
544
|
+
const row = rowObject(columns, values);
|
|
545
|
+
return {
|
|
546
|
+
sourceId: String(row.source_id),
|
|
547
|
+
...(stableText(row.text_hash) ? { textHash: String(row.text_hash) } : {}),
|
|
548
|
+
...(typeof row.enriched_at === 'number' ? { enrichedAt: Number(row.enriched_at) } : {}),
|
|
549
|
+
metadata: parseJsonValue(row.metadata, {}),
|
|
550
|
+
createdAt: Number(row.created_at),
|
|
551
|
+
updatedAt: Number(row.updated_at),
|
|
552
|
+
};
|
|
553
|
+
}
|
|
488
554
|
export function mapScheduleRow(columns, values) {
|
|
489
555
|
const row = rowObject(columns, values);
|
|
490
556
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { KnowledgeConsolidationCandidateRecord, KnowledgeConsolidationCandidateUpsertInput, KnowledgeConsolidationReportRecord, KnowledgeConsolidationReportUpsertInput, KnowledgeEdgeRecord, KnowledgeEdgeUpsertInput, KnowledgeExtractionRecord, KnowledgeExtractionUpsertInput, KnowledgeIssueRecord, KnowledgeIssueUpsertInput, KnowledgeItemView, KnowledgeJobRunRecord, KnowledgeJobRunUpsertInput, KnowledgeRefinementTaskFilter, KnowledgeRefinementTaskRecord, KnowledgeRefinementTaskUpsertInput, KnowledgeNodeRecord, KnowledgeNodeUpsertInput, KnowledgeScheduleRecord, KnowledgeScheduleUpsertInput, KnowledgeSourceRecord, KnowledgeSourceUpsertInput, KnowledgeStatus, KnowledgeUsageRecord, KnowledgeUsageUpsertInput } from './types.js';
|
|
1
|
+
import type { KnowledgeConsolidationCandidateRecord, KnowledgeConsolidationCandidateUpsertInput, KnowledgeConsolidationReportRecord, KnowledgeConsolidationReportUpsertInput, KnowledgeEdgeRecord, KnowledgeEdgeUpsertInput, KnowledgeExtractionRecord, KnowledgeExtractionUpsertInput, KnowledgeIssueRecord, KnowledgeIssueUpsertInput, KnowledgeItemView, KnowledgeJobRunRecord, KnowledgeJobRunUpsertInput, KnowledgeRefinementTaskFilter, KnowledgeRefinementTaskRecord, KnowledgeRefinementTaskUpsertInput, KnowledgeNodeRecord, KnowledgeNodeRevisionRecord, KnowledgeNodeUpsertInput, KnowledgeScheduleRecord, KnowledgeScheduleUpsertInput, KnowledgeSemanticEnrichmentStateRecord, KnowledgeSourceRecord, KnowledgeSourceUpsertInput, KnowledgeStatus, KnowledgeUsageRecord, KnowledgeUsageUpsertInput } from './types.js';
|
|
2
2
|
import { type KnowledgeStoreConfig } from './store-config.js';
|
|
3
3
|
import { type KnowledgeSpaceDeleteResult } from './store-space-delete.js';
|
|
4
4
|
export declare class KnowledgeStore {
|
|
@@ -17,6 +17,9 @@ export declare class KnowledgeStore {
|
|
|
17
17
|
private readonly consolidationCandidates;
|
|
18
18
|
private readonly consolidationReports;
|
|
19
19
|
private readonly schedules;
|
|
20
|
+
private readonly nodeRevisions;
|
|
21
|
+
private readonly semanticEnrichmentStates;
|
|
22
|
+
private readonly nodeAutoAcceptConfidence;
|
|
20
23
|
constructor(config: KnowledgeStoreConfig);
|
|
21
24
|
get isReady(): boolean;
|
|
22
25
|
get storagePath(): string;
|
|
@@ -66,10 +69,25 @@ export declare class KnowledgeStore {
|
|
|
66
69
|
getItem(id: string): KnowledgeItemView | null;
|
|
67
70
|
upsertSource(input: KnowledgeSourceUpsertInput): Promise<KnowledgeSourceRecord>;
|
|
68
71
|
deleteSource(id: string): Promise<boolean>;
|
|
72
|
+
private asRecordDeleteView;
|
|
69
73
|
replaceSourceRecord(record: KnowledgeSourceRecord): Promise<void>;
|
|
70
74
|
upsertNode(input: KnowledgeNodeUpsertInput): Promise<KnowledgeNodeRecord>;
|
|
75
|
+
/** Read a node's append-only revision history, oldest first. (Invariant 8.) */
|
|
76
|
+
listNodeRevisions(nodeId: string): KnowledgeNodeRevisionRecord[];
|
|
71
77
|
deleteNode(id: string): Promise<boolean>;
|
|
72
78
|
replaceNodeRecord(record: KnowledgeNodeRecord): Promise<void>;
|
|
79
|
+
/** Merge one node into another, re-pointing cross-reference edges. (Invariant 7.) */
|
|
80
|
+
mergeNodes(loserId: string, winnerId: string): Promise<{
|
|
81
|
+
merged: boolean;
|
|
82
|
+
repointedEdges: number;
|
|
83
|
+
}>;
|
|
84
|
+
getSemanticEnrichmentState(sourceId: string): KnowledgeSemanticEnrichmentStateRecord | null;
|
|
85
|
+
upsertSemanticEnrichmentState(input: {
|
|
86
|
+
readonly sourceId: string;
|
|
87
|
+
readonly textHash?: string | undefined;
|
|
88
|
+
readonly enrichedAt?: number | undefined;
|
|
89
|
+
readonly metadata?: Record<string, unknown> | undefined;
|
|
90
|
+
}): Promise<KnowledgeSemanticEnrichmentStateRecord>;
|
|
73
91
|
upsertEdge(input: KnowledgeEdgeUpsertInput): Promise<KnowledgeEdgeRecord>;
|
|
74
92
|
deleteEdge(id: string): Promise<boolean>;
|
|
75
93
|
replaceEdgeRecord(record: KnowledgeEdgeRecord): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/platform/knowledge/store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,qCAAqC,EACrC,0CAA0C,EAC1C,kCAAkC,EAClC,uCAAuC,EACvC,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,oBAAoB,EACpB,yBAAyB,EACzB,iBAAiB,EACjB,qBAAqB,EACrB,0BAA0B,EAC1B,6BAA6B,EAC7B,6BAA6B,EAC7B,kCAAkC,EAClC,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,EACvB,4BAA4B,EAC5B,qBAAqB,EACrB,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EACpB,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAOpB,OAAO,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/platform/knowledge/store.ts"],"names":[],"mappings":"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"}
|