@jungjaehoon/mama-core 1.9.0 → 2.1.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/db/migrations/043-add-tool-trace-failure-code.sql +11 -0
- package/dist/agent-graph/alias-write.js +3 -0
- package/dist/agent-graph/entity-resolve.js +3 -7
- package/dist/agent-graph/graph-query.js +5 -4
- package/dist/agent-graph/types.d.ts +30 -0
- package/dist/cases/store.d.ts +0 -4
- package/dist/cases/store.js +0 -66
- package/dist/cases/wiki-page-index.d.ts +0 -13
- package/dist/cases/wiki-page-index.js +0 -153
- package/dist/connectors/event-index.d.ts +1 -22
- package/dist/connectors/event-index.js +0 -157
- package/dist/context-compile/channel-grant.d.ts +46 -0
- package/dist/context-compile/channel-grant.js +66 -0
- package/dist/context-compile/compiler.js +5 -2
- package/dist/context-compile/index.d.ts +1 -0
- package/dist/context-compile/index.js +1 -0
- package/dist/context-compile/packet-store.d.ts +0 -1
- package/dist/context-compile/packet-store.js +0 -16
- package/dist/context-compile/source-readers.d.ts +1 -0
- package/dist/context-compile/source-readers.js +156 -23
- package/dist/context-compile/types.d.ts +17 -0
- package/dist/context-compile/visibility.js +28 -4
- package/dist/db-adapter/node-sqlite-adapter.js +4 -0
- package/dist/db-manager.d.ts +0 -13
- package/dist/db-manager.js +0 -66
- package/dist/decision-formatter.d.ts +0 -11
- package/dist/decision-formatter.js +0 -122
- package/dist/decision-tracker.d.ts +0 -12
- package/dist/decision-tracker.js +0 -50
- package/dist/edges/ref-validation.d.ts +1 -2
- package/dist/edges/ref-validation.js +33 -13
- package/dist/edges/store.d.ts +1 -3
- package/dist/edges/store.js +0 -214
- package/dist/edges/types.d.ts +10 -0
- package/dist/embedding-client.d.ts +0 -17
- package/dist/embedding-client.js +0 -80
- package/dist/embedding-server/mobile/auth.d.ts +1 -10
- package/dist/embedding-server/mobile/auth.js +0 -15
- package/dist/embeddings.d.ts +0 -12
- package/dist/embeddings.js +0 -68
- package/dist/entities/audit-metrics.d.ts +0 -5
- package/dist/entities/audit-metrics.js +0 -4
- package/dist/entities/candidate-generator.d.ts +1 -2
- package/dist/entities/candidate-generator.js +0 -412
- package/dist/entities/entity-list.d.ts +0 -1
- package/dist/entities/entity-list.js +0 -96
- package/dist/entities/entity-orphan-list.d.ts +0 -9
- package/dist/entities/entity-orphan-list.js +0 -88
- package/dist/entities/entity-search.d.ts +0 -1
- package/dist/entities/entity-search.js +0 -147
- package/dist/entities/errors.d.ts +0 -10
- package/dist/entities/errors.js +1 -25
- package/dist/entities/lineage-store.d.ts +0 -23
- package/dist/entities/lineage-store.js +0 -104
- package/dist/entities/policy-store.d.ts +0 -9
- package/dist/entities/policy-store.js +0 -188
- package/dist/entities/provenance-query.d.ts +0 -1
- package/dist/entities/provenance-query.js +0 -164
- package/dist/entities/resolution-engine.d.ts +1 -8
- package/dist/entities/resolution-engine.js +0 -66
- package/dist/entities/rollback-preview.d.ts +0 -4
- package/dist/entities/rollback-preview.js +0 -232
- package/dist/entities/store.d.ts +1 -10
- package/dist/entities/store.js +0 -49
- package/dist/index.d.ts +15 -31
- package/dist/index.js +4 -46
- package/dist/mama-api.d.ts +19 -1
- package/dist/mama-api.js +97 -2
- package/dist/memory/api.d.ts +8 -0
- package/dist/memory/api.js +55 -2
- package/dist/memory/event-store.d.ts +0 -1
- package/dist/memory/event-store.js +0 -15
- package/dist/memory/finding-store.d.ts +0 -1
- package/dist/memory/finding-store.js +0 -12
- package/dist/memory/scope-backfill.d.ts +0 -3
- package/dist/memory/scope-backfill.js +0 -74
- package/dist/memory/scope-store.d.ts +0 -1
- package/dist/memory/scope-store.js +0 -4
- package/dist/memory/truth-store.d.ts +0 -3
- package/dist/memory/truth-store.js +0 -22
- package/dist/memory/types.d.ts +0 -1
- package/dist/memory/types.js +0 -13
- package/dist/memory-store.d.ts +0 -16
- package/dist/memory-store.js +0 -51
- package/dist/model-runs/tool-trace-store.js +9 -5
- package/dist/model-runs/types.d.ts +3 -0
- package/dist/ollama-client.d.ts +0 -9
- package/dist/ollama-client.js +0 -125
- package/dist/outcome-tracker.d.ts +0 -14
- package/dist/outcome-tracker.js +0 -44
- package/dist/progress-indicator.d.ts +0 -4
- package/dist/progress-indicator.js +0 -7
- package/dist/provenance/source-ref.d.ts +0 -9
- package/dist/provenance/source-ref.js +0 -145
- package/dist/query-intent.d.ts +0 -4
- package/dist/query-intent.js +0 -30
- package/dist/relevance-scorer.d.ts +0 -9
- package/dist/relevance-scorer.js +0 -81
- package/dist/search/feedback-store.d.ts +0 -1
- package/dist/search/feedback-store.js +0 -4
- package/dist/search/ranker-rescore.d.ts +0 -3
- package/dist/search/ranker-rescore.js +0 -27
- package/dist/search/ranker-trainer.d.ts +0 -8
- package/dist/search/ranker-trainer.js +0 -376
- package/dist/tier-validator.d.ts +0 -12
- package/dist/tier-validator.js +0 -56
- package/package.json +1 -10
- package/dist/cases/case-links.d.ts +0 -116
- package/dist/cases/case-links.js +0 -794
- package/dist/cases/composition-overrides.d.ts +0 -90
- package/dist/cases/composition-overrides.js +0 -724
- package/dist/cases/corrections.d.ts +0 -156
- package/dist/cases/corrections.js +0 -1045
- package/dist/cases/freshness.d.ts +0 -57
- package/dist/cases/freshness.js +0 -283
- package/dist/cases/live-state.d.ts +0 -48
- package/dist/cases/live-state.js +0 -256
- package/dist/cases/membership-explain.d.ts +0 -56
- package/dist/cases/membership-explain.js +0 -140
- package/dist/cases/membership-matcher.d.ts +0 -23
- package/dist/cases/membership-matcher.js +0 -193
- package/dist/cases/merge-split.d.ts +0 -61
- package/dist/cases/merge-split.js +0 -368
- package/dist/cases/role-inference.d.ts +0 -10
- package/dist/cases/role-inference.js +0 -85
- package/dist/cases/sqlite-transaction.d.ts +0 -10
- package/dist/cases/sqlite-transaction.js +0 -62
- package/dist/cases/target-ref.d.ts +0 -25
- package/dist/cases/target-ref.js +0 -22
- package/dist/cases/tombstone-sweeper.d.ts +0 -13
- package/dist/cases/tombstone-sweeper.js +0 -128
- package/dist/entities/entity-impact.d.ts +0 -41
- package/dist/entities/entity-impact.js +0 -140
- package/dist/entities/exact-merge-backfill.d.ts +0 -11
- package/dist/entities/exact-merge-backfill.js +0 -161
- package/dist/entities/lineage-backfill.d.ts +0 -12
- package/dist/entities/lineage-backfill.js +0 -101
- package/dist/memory-inject.d.ts +0 -24
- package/dist/memory-inject.js +0 -116
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Migration 043: tool_traces.failure_code — carry the thrower's closed cause.
|
|
2
|
+
--
|
|
3
|
+
-- The failure choke already emits a structured code (envelope_missing,
|
|
4
|
+
-- context_compile_scope_denied, ...) and the sanitizer explicitly preserves
|
|
5
|
+
-- it; the trace INSERT was the one place that dropped it, leaving only
|
|
6
|
+
-- `gateway_tool_failed;sha256=...` digests (measured 2026-07-30: the dominant
|
|
7
|
+
-- digest covered 52% of 2,460 context_compile failures with no name).
|
|
8
|
+
-- Nullable on purpose: a failure without a code stays NULL — labels are
|
|
9
|
+
-- carried, never invented.
|
|
10
|
+
|
|
11
|
+
ALTER TABLE tool_traces ADD COLUMN failure_code TEXT;
|
|
@@ -191,6 +191,9 @@ function attachEntityAliasWithEdge(adapter, input) {
|
|
|
191
191
|
connectors: input.connectors,
|
|
192
192
|
projectRefs: input.project_refs,
|
|
193
193
|
tenantId: input.tenant_id,
|
|
194
|
+
// source_refs are caller-supplied, so this is the surface where naming a raw id from
|
|
195
|
+
// an ungranted channel would bind it to an entity the caller can read back.
|
|
196
|
+
...(input.channels ? { channels: input.channels } : {}),
|
|
194
197
|
};
|
|
195
198
|
const sourceRefs = normalizeSourceRefs(input.source_refs);
|
|
196
199
|
if (sourceRefs.length === 0) {
|
|
@@ -168,13 +168,8 @@ function contextBoost(adapter, entityId, contextRefs, visibility, asOfMs) {
|
|
|
168
168
|
if (!contextRefs || contextRefs.length === 0) {
|
|
169
169
|
return 0;
|
|
170
170
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
connectors: visibility.connectors,
|
|
174
|
-
projectRefs: visibility.projectRefs,
|
|
175
|
-
tenantId: visibility.tenantId,
|
|
176
|
-
asOfMs,
|
|
177
|
-
});
|
|
171
|
+
// Spread rather than re-list: see graph-query's listFilteredEdges.
|
|
172
|
+
const edges = (0, ref_validation_js_1.listVisibleTwinEdgesForRefs)(adapter, contextRefs, { ...visibility, asOfMs });
|
|
178
173
|
return edges.some((edge) => (edge.subject_ref.kind === 'entity' && edge.subject_ref.id === entityId) ||
|
|
179
174
|
(edge.object_ref.kind === 'entity' && edge.object_ref.id === entityId))
|
|
180
175
|
? 0.2
|
|
@@ -189,6 +184,7 @@ function resolveEntity(adapter, input) {
|
|
|
189
184
|
projectRefs: input.project_refs,
|
|
190
185
|
tenantId: input.tenant_id,
|
|
191
186
|
asOfMs: input.as_of_ms,
|
|
187
|
+
...(input.channels ? { channels: input.channels } : {}),
|
|
192
188
|
};
|
|
193
189
|
if (input.context_refs && input.context_refs.length > 0) {
|
|
194
190
|
try {
|
|
@@ -80,11 +80,11 @@ function oppositeRef(edge, current) {
|
|
|
80
80
|
return refs;
|
|
81
81
|
}
|
|
82
82
|
function listFilteredEdges(adapter, refs, input) {
|
|
83
|
+
// Spread, not a field-by-field re-listing. Re-listing is how the channel grant was
|
|
84
|
+
// silently dropped here while every other path enforced it: a new field on the
|
|
85
|
+
// visibility type simply never arrived, and nothing failed to say so.
|
|
83
86
|
return (0, ref_validation_js_1.listVisibleTwinEdgesForRefs)(adapter, refs, {
|
|
84
|
-
|
|
85
|
-
connectors: input.visibility.connectors,
|
|
86
|
-
projectRefs: input.visibility.projectRefs,
|
|
87
|
-
tenantId: input.visibility.tenantId,
|
|
87
|
+
...input.visibility,
|
|
88
88
|
edgeTypes: input.edge_filters?.edge_types,
|
|
89
89
|
asOfMs: input.as_of_ms,
|
|
90
90
|
limit: input.limit,
|
|
@@ -104,6 +104,7 @@ function graphVisibility(input) {
|
|
|
104
104
|
connectors: input.connectors,
|
|
105
105
|
projectRefs: input.project_refs,
|
|
106
106
|
tenantId: input.tenant_id,
|
|
107
|
+
...(input.channels ? { channels: input.channels } : {}),
|
|
107
108
|
};
|
|
108
109
|
}
|
|
109
110
|
function numberMs(value, field, refId) {
|
|
@@ -10,6 +10,12 @@ export interface ResolveEntityInput {
|
|
|
10
10
|
scopes?: TwinScopeRef[];
|
|
11
11
|
connectors?: string[];
|
|
12
12
|
project_refs?: TwinProjectRef[];
|
|
13
|
+
/**
|
|
14
|
+
* Which channels of each connector may be read. Carried on every graph input for the
|
|
15
|
+
* same reason it is carried on the reader's boundary: a raw ref reached through an edge
|
|
16
|
+
* must satisfy the same rule as a row the reader would have returned.
|
|
17
|
+
*/
|
|
18
|
+
channels?: Record<string, readonly string[]>;
|
|
13
19
|
tenant_id?: string | null;
|
|
14
20
|
context_refs?: TwinRef[];
|
|
15
21
|
limit?: number;
|
|
@@ -31,6 +37,12 @@ export interface GraphNeighborhoodInput {
|
|
|
31
37
|
scopes?: TwinScopeRef[];
|
|
32
38
|
connectors?: string[];
|
|
33
39
|
project_refs?: TwinProjectRef[];
|
|
40
|
+
/**
|
|
41
|
+
* Which channels of each connector may be read. Carried on every graph input for the
|
|
42
|
+
* same reason it is carried on the reader's boundary: a raw ref reached through an edge
|
|
43
|
+
* must satisfy the same rule as a row the reader would have returned.
|
|
44
|
+
*/
|
|
45
|
+
channels?: Record<string, readonly string[]>;
|
|
34
46
|
tenant_id?: string | null;
|
|
35
47
|
edge_filters?: AgentGraphEdgeFilters;
|
|
36
48
|
as_of_ms?: number | null;
|
|
@@ -47,6 +59,12 @@ export interface GraphPathsInput {
|
|
|
47
59
|
scopes?: TwinScopeRef[];
|
|
48
60
|
connectors?: string[];
|
|
49
61
|
project_refs?: TwinProjectRef[];
|
|
62
|
+
/**
|
|
63
|
+
* Which channels of each connector may be read. Carried on every graph input for the
|
|
64
|
+
* same reason it is carried on the reader's boundary: a raw ref reached through an edge
|
|
65
|
+
* must satisfy the same rule as a row the reader would have returned.
|
|
66
|
+
*/
|
|
67
|
+
channels?: Record<string, readonly string[]>;
|
|
50
68
|
tenant_id?: string | null;
|
|
51
69
|
edge_filters?: AgentGraphEdgeFilters;
|
|
52
70
|
as_of_ms?: number | null;
|
|
@@ -64,6 +82,12 @@ export interface GraphTimelineInput {
|
|
|
64
82
|
scopes?: TwinScopeRef[];
|
|
65
83
|
connectors?: string[];
|
|
66
84
|
project_refs?: TwinProjectRef[];
|
|
85
|
+
/**
|
|
86
|
+
* Which channels of each connector may be read. Carried on every graph input for the
|
|
87
|
+
* same reason it is carried on the reader's boundary: a raw ref reached through an edge
|
|
88
|
+
* must satisfy the same rule as a row the reader would have returned.
|
|
89
|
+
*/
|
|
90
|
+
channels?: Record<string, readonly string[]>;
|
|
67
91
|
tenant_id?: string | null;
|
|
68
92
|
edge_filters?: AgentGraphEdgeFilters;
|
|
69
93
|
from_ms?: number;
|
|
@@ -153,6 +177,12 @@ export interface AttachEntityAliasWithEdgeInput {
|
|
|
153
177
|
scopes?: TwinScopeRef[];
|
|
154
178
|
connectors?: string[];
|
|
155
179
|
project_refs?: TwinProjectRef[];
|
|
180
|
+
/**
|
|
181
|
+
* Which channels of each connector may be read. Carried on every graph input for the
|
|
182
|
+
* same reason it is carried on the reader's boundary: a raw ref reached through an edge
|
|
183
|
+
* must satisfy the same rule as a row the reader would have returned.
|
|
184
|
+
*/
|
|
185
|
+
channels?: Record<string, readonly string[]>;
|
|
156
186
|
tenant_id?: string | null;
|
|
157
187
|
}
|
|
158
188
|
export interface AttachEntityAliasWithEdgeResult {
|
package/dist/cases/store.d.ts
CHANGED
|
@@ -63,10 +63,6 @@ export interface ListActiveCorrectionsForCaseResult {
|
|
|
63
63
|
*/
|
|
64
64
|
export declare function listActiveCorrectionsForCase(adapter: CaseStoreAdapter, caseId: string): ListActiveCorrectionsForCaseResult;
|
|
65
65
|
export declare function listActiveCorrectionsForCaseChain(adapter: CaseStoreAdapter, caseIds: string[]): CaseCorrectionRecord[];
|
|
66
|
-
export declare function enqueueCaseProposal(adapter: CaseStoreAdapter, input: EnqueueCaseProposalInput): {
|
|
67
|
-
proposal_id: string;
|
|
68
|
-
inserted: boolean;
|
|
69
|
-
};
|
|
70
66
|
export declare function listUnresolvedCaseProposals(adapter: CaseStoreAdapter, project: string): CaseProposalQueueRecord[];
|
|
71
67
|
export declare function assembleCase(caseId: string, options?: AssembleCaseOptions): CaseAssembly;
|
|
72
68
|
export declare function assembleCase(adapter: CaseStoreAdapter, caseId: string, options?: AssembleCaseOptions): CaseAssembly;
|
package/dist/cases/store.js
CHANGED
|
@@ -7,11 +7,8 @@ exports.upsertExplicitCaseMemberships = upsertExplicitCaseMemberships;
|
|
|
7
7
|
exports.listActiveMembershipsForCaseChain = listActiveMembershipsForCaseChain;
|
|
8
8
|
exports.listActiveCorrectionsForCase = listActiveCorrectionsForCase;
|
|
9
9
|
exports.listActiveCorrectionsForCaseChain = listActiveCorrectionsForCaseChain;
|
|
10
|
-
exports.enqueueCaseProposal = enqueueCaseProposal;
|
|
11
10
|
exports.listUnresolvedCaseProposals = listUnresolvedCaseProposals;
|
|
12
11
|
exports.assembleCase = assembleCase;
|
|
13
|
-
const node_crypto_1 = require("node:crypto");
|
|
14
|
-
const canonicalize_js_1 = require("../canonicalize.js");
|
|
15
12
|
const db_manager_js_1 = require("../db-manager.js");
|
|
16
13
|
const errors_js_1 = require("../entities/errors.js");
|
|
17
14
|
function isAdapter(value) {
|
|
@@ -447,69 +444,6 @@ function listActiveCorrectionsForCaseChain(adapter, caseIds) {
|
|
|
447
444
|
.all(...caseIds);
|
|
448
445
|
return rows.map(mapCaseCorrectionRow);
|
|
449
446
|
}
|
|
450
|
-
function isUniqueConstraintError(error) {
|
|
451
|
-
if (!(error instanceof Error)) {
|
|
452
|
-
return false;
|
|
453
|
-
}
|
|
454
|
-
return /UNIQUE constraint|SQLITE_CONSTRAINT_UNIQUE/i.test(error.message);
|
|
455
|
-
}
|
|
456
|
-
function findExistingProposalId(adapter, input, payloadFingerprint) {
|
|
457
|
-
const row = adapter
|
|
458
|
-
.prepare(`
|
|
459
|
-
SELECT proposal_id
|
|
460
|
-
FROM case_proposal_queue
|
|
461
|
-
WHERE project = ?
|
|
462
|
-
AND proposal_kind = ?
|
|
463
|
-
AND COALESCE(conflicting_case_id, '') = ?
|
|
464
|
-
AND payload_fingerprint = ?
|
|
465
|
-
AND resolved_at IS NULL
|
|
466
|
-
LIMIT 1
|
|
467
|
-
`)
|
|
468
|
-
.get(input.project, input.proposal_kind, input.conflicting_case_id ?? '', payloadFingerprint);
|
|
469
|
-
return row?.proposal_id ?? null;
|
|
470
|
-
}
|
|
471
|
-
function enqueueCaseProposal(adapter, input) {
|
|
472
|
-
const canonicalFingerprintInput = (0, canonicalize_js_1.canonicalizeJSON)(input.stable_fingerprint_input);
|
|
473
|
-
const payloadFingerprint = (0, canonicalize_js_1.targetRefHashCanonicalJSON)(canonicalFingerprintInput);
|
|
474
|
-
const proposalId = (0, node_crypto_1.randomUUID)();
|
|
475
|
-
const detectedAt = nowIso();
|
|
476
|
-
return adapter.transaction(() => {
|
|
477
|
-
try {
|
|
478
|
-
adapter
|
|
479
|
-
.prepare(`
|
|
480
|
-
INSERT INTO case_proposal_queue (
|
|
481
|
-
proposal_id, project, proposal_kind, proposed_payload, payload_fingerprint,
|
|
482
|
-
conflicting_case_id, detected_at, resolved_at, resolution, resolution_note
|
|
483
|
-
)
|
|
484
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL)
|
|
485
|
-
`)
|
|
486
|
-
.run(proposalId, input.project, input.proposal_kind, input.proposed_payload, payloadFingerprint, input.conflicting_case_id ?? null, detectedAt);
|
|
487
|
-
return { proposal_id: proposalId, inserted: true };
|
|
488
|
-
}
|
|
489
|
-
catch (error) {
|
|
490
|
-
if (!isUniqueConstraintError(error)) {
|
|
491
|
-
throw error;
|
|
492
|
-
}
|
|
493
|
-
const existingId = findExistingProposalId(adapter, input, payloadFingerprint);
|
|
494
|
-
if (!existingId) {
|
|
495
|
-
throw error;
|
|
496
|
-
}
|
|
497
|
-
// Spec §5.7 L355: re-detection updates detected_at without duplicating.
|
|
498
|
-
// Keeps listUnresolvedCaseProposals ordering (ASC detected_at) honest —
|
|
499
|
-
// recently re-detected rows move to the tail instead of sitting at
|
|
500
|
-
// stale timestamps.
|
|
501
|
-
adapter
|
|
502
|
-
.prepare(`
|
|
503
|
-
UPDATE case_proposal_queue
|
|
504
|
-
SET detected_at = ?
|
|
505
|
-
WHERE proposal_id = ?
|
|
506
|
-
AND resolved_at IS NULL
|
|
507
|
-
`)
|
|
508
|
-
.run(detectedAt, existingId);
|
|
509
|
-
return { proposal_id: existingId, inserted: false };
|
|
510
|
-
}
|
|
511
|
-
});
|
|
512
|
-
}
|
|
513
447
|
function listUnresolvedCaseProposals(adapter, project) {
|
|
514
448
|
const rows = adapter
|
|
515
449
|
.prepare(`
|
|
@@ -32,19 +32,6 @@ export interface UpsertWikiPageIndexInput {
|
|
|
32
32
|
embedding?: Float32Array | null;
|
|
33
33
|
embedding_model?: string;
|
|
34
34
|
}
|
|
35
|
-
export declare function upsertWikiPageIndexEntry(adapter: AdapterLike, input: UpsertWikiPageIndexInput): {
|
|
36
|
-
id: number;
|
|
37
|
-
created: boolean;
|
|
38
|
-
};
|
|
39
|
-
export declare function deleteWikiPageIndexEntry(adapter: AdapterLike, source_locator: string): {
|
|
40
|
-
deleted: boolean;
|
|
41
|
-
};
|
|
42
35
|
export declare function ftsSearchWikiPages(adapter: AdapterLike, query: string, limit: number): WikiPageSearchHit[];
|
|
43
36
|
export declare function vectorSearchWikiPages(adapter: AdapterLike, queryEmbedding: Float32Array, limit: number): WikiPageSearchHit[];
|
|
44
|
-
export declare function searchWikiPages(input: {
|
|
45
|
-
adapter: AdapterLike;
|
|
46
|
-
query: string;
|
|
47
|
-
queryEmbedding?: Float32Array | null;
|
|
48
|
-
limit: number;
|
|
49
|
-
}): WikiPageSearchHit[];
|
|
50
37
|
//# sourceMappingURL=wiki-page-index.d.ts.map
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.upsertWikiPageIndexEntry = upsertWikiPageIndexEntry;
|
|
7
|
-
exports.deleteWikiPageIndexEntry = deleteWikiPageIndexEntry;
|
|
8
3
|
exports.ftsSearchWikiPages = ftsSearchWikiPages;
|
|
9
4
|
exports.vectorSearchWikiPages = vectorSearchWikiPages;
|
|
10
|
-
exports.searchWikiPages = searchWikiPages;
|
|
11
|
-
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
12
5
|
const embeddings_js_1 = require("../embeddings.js");
|
|
13
6
|
function tableColumns(adapter, tableName) {
|
|
14
7
|
const rows = adapter.prepare(`PRAGMA table_info(${tableName})`).all();
|
|
@@ -34,19 +27,12 @@ function readSchema(adapter) {
|
|
|
34
27
|
embeddingHasCreatedAt: embeddingColumns.has('created_at'),
|
|
35
28
|
};
|
|
36
29
|
}
|
|
37
|
-
function nowIso() {
|
|
38
|
-
return new Date().toISOString();
|
|
39
|
-
}
|
|
40
30
|
function normalizeLimit(limit) {
|
|
41
31
|
if (!Number.isFinite(limit)) {
|
|
42
32
|
return 10;
|
|
43
33
|
}
|
|
44
34
|
return Math.max(0, Math.floor(limit));
|
|
45
35
|
}
|
|
46
|
-
function pageIdForSourceLocator(sourceLocator) {
|
|
47
|
-
const digest = node_crypto_1.default.createHash('sha256').update(sourceLocator).digest('hex').slice(0, 24);
|
|
48
|
-
return `wiki_page_${digest}`;
|
|
49
|
-
}
|
|
50
36
|
function parseJsonArray(value) {
|
|
51
37
|
if (value === null || value === undefined || value === '') {
|
|
52
38
|
return [];
|
|
@@ -89,13 +75,6 @@ function rowToRecord(row) {
|
|
|
89
75
|
updated_at: String(row.updated_at ?? row.created_at ?? row.compiled_at ?? ''),
|
|
90
76
|
};
|
|
91
77
|
}
|
|
92
|
-
function selectByLocator(adapter, schema, sourceLocator) {
|
|
93
|
-
const sql = schema.hasIdColumn
|
|
94
|
-
? 'SELECT * FROM wiki_page_index WHERE source_locator = ?'
|
|
95
|
-
: 'SELECT rowid AS id, * FROM wiki_page_index WHERE source_locator = ?';
|
|
96
|
-
const row = adapter.prepare(sql).get(sourceLocator);
|
|
97
|
-
return row ? rowToRecord(row) : null;
|
|
98
|
-
}
|
|
99
78
|
function selectByFtsPageId(adapter, schema, pageId) {
|
|
100
79
|
const sql = schema.hasIdColumn
|
|
101
80
|
? 'SELECT * FROM wiki_page_index WHERE id = ?'
|
|
@@ -104,9 +83,6 @@ function selectByFtsPageId(adapter, schema, pageId) {
|
|
|
104
83
|
const row = adapter.prepare(sql).get(lookup);
|
|
105
84
|
return row ? rowToRecord(row) : null;
|
|
106
85
|
}
|
|
107
|
-
function vectorToBuffer(embedding) {
|
|
108
|
-
return Buffer.from(embedding.buffer, embedding.byteOffset, embedding.byteLength);
|
|
109
|
-
}
|
|
110
86
|
function blobToVector(value) {
|
|
111
87
|
if (!(value instanceof Uint8Array)) {
|
|
112
88
|
return null;
|
|
@@ -118,35 +94,6 @@ function blobToVector(value) {
|
|
|
118
94
|
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
119
95
|
return new Float32Array(arrayBuffer);
|
|
120
96
|
}
|
|
121
|
-
function upsertEmbedding(adapter, schema, record, input) {
|
|
122
|
-
if (!input.embedding) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
const vector = vectorToBuffer(input.embedding);
|
|
126
|
-
const model = input.embedding_model ?? embeddings_js_1.MODEL_NAME;
|
|
127
|
-
const dim = input.embedding.length;
|
|
128
|
-
if (schema.embeddingUsesWikiPageId && schema.embeddingUsesVector) {
|
|
129
|
-
adapter
|
|
130
|
-
.prepare(`
|
|
131
|
-
INSERT INTO wiki_page_embeddings(wiki_page_id, vector, model, dim, created_at)
|
|
132
|
-
VALUES (?, ?, ?, ?, ?)
|
|
133
|
-
ON CONFLICT(wiki_page_id) DO UPDATE SET
|
|
134
|
-
vector = excluded.vector,
|
|
135
|
-
model = excluded.model,
|
|
136
|
-
dim = excluded.dim
|
|
137
|
-
`)
|
|
138
|
-
.run(record.id, vector, model, dim, nowIso());
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
adapter
|
|
142
|
-
.prepare(`
|
|
143
|
-
INSERT INTO wiki_page_embeddings(page_id, embedding)
|
|
144
|
-
VALUES (?, ?)
|
|
145
|
-
ON CONFLICT(page_id) DO UPDATE SET
|
|
146
|
-
embedding = excluded.embedding
|
|
147
|
-
`)
|
|
148
|
-
.run(pageIdForSourceLocator(record.source_locator), vector);
|
|
149
|
-
}
|
|
150
97
|
function buildFtsQuery(query) {
|
|
151
98
|
const tokens = query
|
|
152
99
|
.toLowerCase()
|
|
@@ -173,89 +120,6 @@ function searchTableExists(adapter, tableName) {
|
|
|
173
120
|
.get(tableName);
|
|
174
121
|
return row !== undefined;
|
|
175
122
|
}
|
|
176
|
-
function upsertWikiPageIndexEntry(adapter, input) {
|
|
177
|
-
const schema = readSchema(adapter);
|
|
178
|
-
const existing = selectByLocator(adapter, schema, input.source_locator);
|
|
179
|
-
const updatedAt = nowIso();
|
|
180
|
-
return adapter.transaction(() => {
|
|
181
|
-
if (schema.hasIdColumn) {
|
|
182
|
-
adapter
|
|
183
|
-
.prepare(`
|
|
184
|
-
INSERT INTO wiki_page_index (
|
|
185
|
-
source_locator, page_type, title, content, case_id, source_ids,
|
|
186
|
-
confidence, entity_refs, compiled_at, created_at, updated_at
|
|
187
|
-
)
|
|
188
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
189
|
-
ON CONFLICT(source_locator) DO UPDATE SET
|
|
190
|
-
page_type = excluded.page_type,
|
|
191
|
-
title = excluded.title,
|
|
192
|
-
content = excluded.content,
|
|
193
|
-
case_id = excluded.case_id,
|
|
194
|
-
source_ids = excluded.source_ids,
|
|
195
|
-
confidence = excluded.confidence,
|
|
196
|
-
entity_refs = excluded.entity_refs,
|
|
197
|
-
compiled_at = excluded.compiled_at,
|
|
198
|
-
updated_at = excluded.updated_at
|
|
199
|
-
`)
|
|
200
|
-
.run(input.source_locator, input.page_type, input.title, input.content, input.case_id ?? null, JSON.stringify(input.source_ids), input.confidence, JSON.stringify(input.entity_refs), input.compiled_at, updatedAt, updatedAt);
|
|
201
|
-
}
|
|
202
|
-
else if (schema.hasSourceIdsColumn && schema.hasEntityRefsColumn) {
|
|
203
|
-
adapter
|
|
204
|
-
.prepare(`
|
|
205
|
-
INSERT INTO wiki_page_index (
|
|
206
|
-
page_id, source_type, source_locator, case_id, title, page_type,
|
|
207
|
-
content, confidence, source_ids, entity_refs, compiled_at, updated_at
|
|
208
|
-
)
|
|
209
|
-
VALUES (?, 'wiki_page', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
210
|
-
ON CONFLICT(source_type, source_locator) DO UPDATE SET
|
|
211
|
-
case_id = excluded.case_id,
|
|
212
|
-
title = excluded.title,
|
|
213
|
-
page_type = excluded.page_type,
|
|
214
|
-
content = excluded.content,
|
|
215
|
-
confidence = excluded.confidence,
|
|
216
|
-
source_ids = excluded.source_ids,
|
|
217
|
-
entity_refs = excluded.entity_refs,
|
|
218
|
-
compiled_at = excluded.compiled_at,
|
|
219
|
-
updated_at = excluded.updated_at
|
|
220
|
-
`)
|
|
221
|
-
.run(pageIdForSourceLocator(input.source_locator), input.source_locator, input.case_id ?? null, input.title, input.page_type, input.content, input.confidence, JSON.stringify(input.source_ids), JSON.stringify(input.entity_refs), input.compiled_at, updatedAt);
|
|
222
|
-
}
|
|
223
|
-
else {
|
|
224
|
-
adapter
|
|
225
|
-
.prepare(`
|
|
226
|
-
INSERT INTO wiki_page_index (
|
|
227
|
-
page_id, source_type, source_locator, case_id, title, page_type,
|
|
228
|
-
content, confidence, compiled_at, updated_at
|
|
229
|
-
)
|
|
230
|
-
VALUES (?, 'wiki_page', ?, ?, ?, ?, ?, ?, ?, ?)
|
|
231
|
-
ON CONFLICT(source_type, source_locator) DO UPDATE SET
|
|
232
|
-
case_id = excluded.case_id,
|
|
233
|
-
title = excluded.title,
|
|
234
|
-
page_type = excluded.page_type,
|
|
235
|
-
content = excluded.content,
|
|
236
|
-
confidence = excluded.confidence,
|
|
237
|
-
compiled_at = excluded.compiled_at,
|
|
238
|
-
updated_at = excluded.updated_at
|
|
239
|
-
`)
|
|
240
|
-
.run(pageIdForSourceLocator(input.source_locator), input.source_locator, input.case_id ?? null, input.title, input.page_type, input.content, input.confidence, input.compiled_at, updatedAt);
|
|
241
|
-
}
|
|
242
|
-
const saved = selectByLocator(adapter, schema, input.source_locator);
|
|
243
|
-
if (!saved) {
|
|
244
|
-
throw new Error(`Failed to load wiki_page_index row for ${input.source_locator}.`);
|
|
245
|
-
}
|
|
246
|
-
upsertEmbedding(adapter, schema, saved, input);
|
|
247
|
-
return {
|
|
248
|
-
id: saved.id,
|
|
249
|
-
created: existing === null,
|
|
250
|
-
};
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
function deleteWikiPageIndexEntry(adapter, source_locator) {
|
|
254
|
-
const result = adapter
|
|
255
|
-
.prepare('DELETE FROM wiki_page_index WHERE source_locator = ?')
|
|
256
|
-
.run(source_locator);
|
|
257
|
-
return { deleted: result.changes > 0 };
|
|
258
|
-
}
|
|
259
123
|
function ftsSearchWikiPages(adapter, query, limit) {
|
|
260
124
|
const boundedLimit = normalizeLimit(limit);
|
|
261
125
|
if (boundedLimit === 0 || !query.trim()) {
|
|
@@ -334,21 +198,4 @@ function vectorSearchWikiPages(adapter, queryEmbedding, limit) {
|
|
|
334
198
|
raw_score: entry.score,
|
|
335
199
|
}));
|
|
336
200
|
}
|
|
337
|
-
function searchWikiPages(input) {
|
|
338
|
-
const ftsHits = ftsSearchWikiPages(input.adapter, input.query, input.limit);
|
|
339
|
-
const vectorHits = input.queryEmbedding
|
|
340
|
-
? vectorSearchWikiPages(input.adapter, input.queryEmbedding, input.limit)
|
|
341
|
-
: [];
|
|
342
|
-
const merged = new Map();
|
|
343
|
-
for (const hit of [...ftsHits, ...vectorHits]) {
|
|
344
|
-
const existing = merged.get(hit.record.id);
|
|
345
|
-
if (!existing || hit.raw_score > existing.raw_score) {
|
|
346
|
-
merged.set(hit.record.id, hit);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
return Array.from(merged.values())
|
|
350
|
-
.sort((left, right) => right.raw_score - left.raw_score)
|
|
351
|
-
.slice(0, normalizeLimit(input.limit))
|
|
352
|
-
.map((hit, rank) => ({ ...hit, rank }));
|
|
353
|
-
}
|
|
354
201
|
//# sourceMappingURL=wiki-page-index.js.map
|
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
import type { DatabaseAdapter } from '../db-manager.js';
|
|
2
|
-
import type { ConnectorEventIndexCursorRecord, ConnectorEventIndexRecord,
|
|
2
|
+
import type { ConnectorEventIndexCursorRecord, ConnectorEventIndexRecord, UpsertConnectorEventIndexInput } from './types.js';
|
|
3
3
|
type ConnectorEventIndexAdapter = Pick<DatabaseAdapter, 'prepare' | 'transaction'>;
|
|
4
|
-
interface ListConnectorEventsByDatetimeRangeInput {
|
|
5
|
-
fromMs: number;
|
|
6
|
-
toMs: number;
|
|
7
|
-
limit?: number;
|
|
8
|
-
connectors?: string[];
|
|
9
|
-
order?: 'asc' | 'desc';
|
|
10
|
-
}
|
|
11
|
-
interface SearchConnectorEventsOptions {
|
|
12
|
-
limit?: number;
|
|
13
|
-
connectors?: string[];
|
|
14
|
-
}
|
|
15
4
|
interface DeleteExpiredConnectorEventsInput {
|
|
16
5
|
nowMs: number;
|
|
17
6
|
retentionMs: number;
|
|
18
7
|
connectorName?: string;
|
|
19
8
|
}
|
|
20
|
-
interface StalenessOptions {
|
|
21
|
-
nowMs: number;
|
|
22
|
-
staleAfterMs?: number;
|
|
23
|
-
stalenessWarnAfterMs?: number;
|
|
24
|
-
unhealthyAfterMs?: number;
|
|
25
|
-
}
|
|
26
9
|
export declare function mapConnectorEventIndexRecord(row: Record<string, unknown>): ConnectorEventIndexRecord;
|
|
27
10
|
export declare function connectorEventIndexId(sourceConnector: string, sourceId: string): string;
|
|
28
11
|
export declare function connectorEventContentHash(input: {
|
|
@@ -33,13 +16,9 @@ export declare function connectorEventContentHash(input: {
|
|
|
33
16
|
}): Buffer;
|
|
34
17
|
export declare function upsertConnectorEventIndex(adapter: ConnectorEventIndexAdapter, input: UpsertConnectorEventIndexInput): ConnectorEventIndexRecord;
|
|
35
18
|
export declare function getConnectorEventIndexRecord(adapter: ConnectorEventIndexAdapter, sourceConnector: string, sourceId: string): ConnectorEventIndexRecord | null;
|
|
36
|
-
export declare function listConnectorEventsByDatetimeRange(adapter: ConnectorEventIndexAdapter, input: ListConnectorEventsByDatetimeRangeInput): ConnectorEventIndexRecord[];
|
|
37
|
-
export declare function searchConnectorEventsByFTS(adapter: ConnectorEventIndexAdapter, query: string, options?: SearchConnectorEventsOptions): ConnectorEventSearchHit[];
|
|
38
19
|
export declare function readConnectorCursor(adapter: ConnectorEventIndexAdapter, connectorName: string): ConnectorEventIndexCursorRecord | null;
|
|
39
|
-
export declare function upsertConnectorCursor(adapter: ConnectorEventIndexAdapter, input: UpsertConnectorEventIndexCursorInput): ConnectorEventIndexCursorRecord;
|
|
40
20
|
export declare function deleteExpiredConnectorEvents(adapter: ConnectorEventIndexAdapter, input: DeleteExpiredConnectorEventsInput): {
|
|
41
21
|
rows_deleted: number;
|
|
42
22
|
};
|
|
43
|
-
export declare function computeStalenessStatus(cursor: ConnectorEventIndexCursorRecord | null, options: StalenessOptions): ConnectorEventStalenessStatus;
|
|
44
23
|
export type { ConnectorEventIndexCursorRecord, ConnectorEventIndexRecord, ConnectorEventSearchHit, ConnectorEventStalenessStatus, UpsertConnectorEventIndexCursorInput, UpsertConnectorEventIndexInput, } from './types.js';
|
|
45
24
|
//# sourceMappingURL=event-index.d.ts.map
|