@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
package/dist/edges/store.js
CHANGED
|
@@ -3,31 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.mapTwinEdgeRow = mapTwinEdgeRow;
|
|
4
4
|
exports.getTwinEdge = getTwinEdge;
|
|
5
5
|
exports.listTwinEdgesForRefs = listTwinEdgesForRefs;
|
|
6
|
-
exports.insertTwinEdge = insertTwinEdge;
|
|
7
|
-
const node_crypto_1 = require("node:crypto");
|
|
8
|
-
const canonicalize_js_1 = require("../canonicalize.js");
|
|
9
6
|
const types_js_1 = require("./types.js");
|
|
10
7
|
const EDGE_TYPE_SET = new Set(types_js_1.TWIN_EDGE_TYPES);
|
|
11
8
|
const REF_KIND_SET = new Set(types_js_1.TWIN_REF_KINDS);
|
|
12
9
|
const SOURCE_SET = new Set(types_js_1.TWIN_EDGE_SOURCES);
|
|
13
|
-
const HUMAN_ACTOR_ROLES = new Set(['commander', 'configurator_elevated']);
|
|
14
|
-
const HUMAN_REASON_CLASSIFICATIONS = new Set([
|
|
15
|
-
'factual_correction',
|
|
16
|
-
'agent_inference_wrong',
|
|
17
|
-
'privacy_redaction',
|
|
18
|
-
'duplicate_merge',
|
|
19
|
-
'state_override',
|
|
20
|
-
'other',
|
|
21
|
-
]);
|
|
22
|
-
function sha256Hex(input) {
|
|
23
|
-
return (0, node_crypto_1.createHash)('sha256').update(input, 'utf8').digest('hex');
|
|
24
|
-
}
|
|
25
|
-
function sha256Buffer(input) {
|
|
26
|
-
return (0, node_crypto_1.createHash)('sha256').update(input, 'utf8').digest();
|
|
27
|
-
}
|
|
28
|
-
function generatedEdgeId() {
|
|
29
|
-
return `edge_${(0, node_crypto_1.randomUUID)().replace(/-/g, '')}`;
|
|
30
|
-
}
|
|
31
10
|
function nullableString(value) {
|
|
32
11
|
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
33
12
|
}
|
|
@@ -61,68 +40,6 @@ function normalizeRef(ref, field) {
|
|
|
61
40
|
id: requireNonEmptyString(ref.id, `${field}.id`),
|
|
62
41
|
};
|
|
63
42
|
}
|
|
64
|
-
function assertSubjectKindAllowed(ref) {
|
|
65
|
-
if (ref.kind === 'raw') {
|
|
66
|
-
throw new Error('twin_edges.subject_ref.kind cannot be raw');
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
function normalizeConfidence(value) {
|
|
70
|
-
if (value === undefined || value === null) {
|
|
71
|
-
return 1;
|
|
72
|
-
}
|
|
73
|
-
if (typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= 1) {
|
|
74
|
-
return value;
|
|
75
|
-
}
|
|
76
|
-
throw new Error(`twin_edges.confidence must be between 0 and 1: ${String(value)}`);
|
|
77
|
-
}
|
|
78
|
-
function hasDeterministicRule(value) {
|
|
79
|
-
return (value !== null &&
|
|
80
|
-
typeof value === 'object' &&
|
|
81
|
-
!Array.isArray(value) &&
|
|
82
|
-
typeof value.deterministic_rule === 'string' &&
|
|
83
|
-
value.deterministic_rule.length > 0);
|
|
84
|
-
}
|
|
85
|
-
function validateSourceMetadata(input, source) {
|
|
86
|
-
if (source === 'agent') {
|
|
87
|
-
requireNonEmptyString(input.agent_id, 'agent_id');
|
|
88
|
-
requireNonEmptyString(input.model_run_id, 'model_run_id');
|
|
89
|
-
requireNonEmptyString(input.envelope_hash, 'envelope_hash');
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
if (source === 'human') {
|
|
93
|
-
requireNonEmptyString(input.human_actor_id, 'human_actor_id');
|
|
94
|
-
const role = requireNonEmptyString(input.human_actor_role, 'human_actor_role');
|
|
95
|
-
if (!HUMAN_ACTOR_ROLES.has(role)) {
|
|
96
|
-
throw new Error(`Unsupported twin_edges.human_actor_role: ${role}`);
|
|
97
|
-
}
|
|
98
|
-
if (input.authority_scope_json === undefined || input.authority_scope_json === null) {
|
|
99
|
-
throw new Error('twin_edges.authority_scope_json is required for human edges');
|
|
100
|
-
}
|
|
101
|
-
const classification = requireNonEmptyString(input.reason_classification, 'reason_classification');
|
|
102
|
-
if (!HUMAN_REASON_CLASSIFICATIONS.has(classification)) {
|
|
103
|
-
throw new Error(`Unsupported twin_edges.reason_classification: ${classification}`);
|
|
104
|
-
}
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
if (!nullableString(input.reason_text) && !hasDeterministicRule(input.relation_attrs)) {
|
|
108
|
-
throw new Error('twin_edges.reason_text or relation_attrs.deterministic_rule is required for code edges');
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
function jsonField(value, field) {
|
|
112
|
-
if (value === undefined || value === null) {
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
try {
|
|
116
|
-
if (typeof value === 'string') {
|
|
117
|
-
return (0, canonicalize_js_1.canonicalizeJSON)(JSON.parse(value));
|
|
118
|
-
}
|
|
119
|
-
return (0, canonicalize_js_1.canonicalizeJSON)(value);
|
|
120
|
-
}
|
|
121
|
-
catch (error) {
|
|
122
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
123
|
-
throw new Error(`Invalid twin_edges.${field}: ${message}`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
43
|
function parseJsonField(value, field, edgeId) {
|
|
127
44
|
if (value === null || value === undefined) {
|
|
128
45
|
return null;
|
|
@@ -148,62 +65,6 @@ function toBuffer(value) {
|
|
|
148
65
|
}
|
|
149
66
|
throw new Error('twin_edges.content_hash must be a 32-byte Buffer');
|
|
150
67
|
}
|
|
151
|
-
function exists(adapter, table, column, id) {
|
|
152
|
-
const row = adapter
|
|
153
|
-
.prepare(`SELECT 1 AS ok FROM ${table} WHERE ${column} = ? LIMIT 1`)
|
|
154
|
-
.get(id);
|
|
155
|
-
return Boolean(row?.ok);
|
|
156
|
-
}
|
|
157
|
-
function validateRefExists(adapter, ref, field) {
|
|
158
|
-
if (ref.kind === 'report') {
|
|
159
|
-
throw new Error(`${field} ${ref.kind}:${ref.id} is not supported by twin_edges yet`);
|
|
160
|
-
}
|
|
161
|
-
const found = (ref.kind === 'memory' && exists(adapter, 'decisions', 'id', ref.id)) ||
|
|
162
|
-
(ref.kind === 'case' && exists(adapter, 'case_truth', 'case_id', ref.id)) ||
|
|
163
|
-
(ref.kind === 'entity' && exists(adapter, 'entity_nodes', 'id', ref.id)) ||
|
|
164
|
-
(ref.kind === 'edge' && exists(adapter, 'twin_edges', 'edge_id', ref.id)) ||
|
|
165
|
-
(ref.kind === 'raw' && exists(adapter, 'connector_event_index', 'event_index_id', ref.id));
|
|
166
|
-
if (!found) {
|
|
167
|
-
throw new Error(`${field} not found: ${ref.kind}:${ref.id}`);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
function contentHashInput(input) {
|
|
171
|
-
return (0, canonicalize_js_1.canonicalizeJSON)(input);
|
|
172
|
-
}
|
|
173
|
-
function deriveEdgeIdempotencyKey(requestIdempotencyKey, contentHash) {
|
|
174
|
-
return `reqedge_${sha256Hex((0, canonicalize_js_1.canonicalizeJSON)({
|
|
175
|
-
request_idempotency_key: requestIdempotencyKey,
|
|
176
|
-
content_hash: contentHash.toString('hex'),
|
|
177
|
-
})).slice(0, 40)}`;
|
|
178
|
-
}
|
|
179
|
-
function selectByIdempotency(adapter, modelRunId, edgeIdempotencyKey) {
|
|
180
|
-
if (!edgeIdempotencyKey) {
|
|
181
|
-
return null;
|
|
182
|
-
}
|
|
183
|
-
if (!modelRunId) {
|
|
184
|
-
const row = adapter
|
|
185
|
-
.prepare(`
|
|
186
|
-
SELECT *
|
|
187
|
-
FROM twin_edges
|
|
188
|
-
WHERE model_run_id IS NULL
|
|
189
|
-
AND edge_idempotency_key = ?
|
|
190
|
-
ORDER BY created_at ASC, edge_id ASC
|
|
191
|
-
LIMIT 1
|
|
192
|
-
`)
|
|
193
|
-
.get(edgeIdempotencyKey);
|
|
194
|
-
return row ? mapTwinEdgeRow(row) : null;
|
|
195
|
-
}
|
|
196
|
-
const row = adapter
|
|
197
|
-
.prepare(`
|
|
198
|
-
SELECT *
|
|
199
|
-
FROM twin_edges
|
|
200
|
-
WHERE model_run_id = ?
|
|
201
|
-
AND edge_idempotency_key = ?
|
|
202
|
-
LIMIT 1
|
|
203
|
-
`)
|
|
204
|
-
.get(modelRunId, edgeIdempotencyKey);
|
|
205
|
-
return row ? mapTwinEdgeRow(row) : null;
|
|
206
|
-
}
|
|
207
68
|
function mapTwinEdgeRow(row) {
|
|
208
69
|
const edgeId = String(row.edge_id);
|
|
209
70
|
return {
|
|
@@ -265,79 +126,4 @@ function listTwinEdgesForRefs(adapter, refs) {
|
|
|
265
126
|
.all(...params);
|
|
266
127
|
return rows.map(mapTwinEdgeRow);
|
|
267
128
|
}
|
|
268
|
-
function insertTwinEdge(adapter, input) {
|
|
269
|
-
const edgeType = normalizeEdgeType(input.edge_type);
|
|
270
|
-
const subjectRef = normalizeRef(input.subject_ref, 'subject_ref');
|
|
271
|
-
const objectRef = normalizeRef(input.object_ref, 'object_ref');
|
|
272
|
-
assertSubjectKindAllowed(subjectRef);
|
|
273
|
-
const source = normalizeSource(input.source);
|
|
274
|
-
const confidence = normalizeConfidence(input.confidence);
|
|
275
|
-
validateSourceMetadata(input, source);
|
|
276
|
-
validateRefExists(adapter, subjectRef, 'subject_ref');
|
|
277
|
-
validateRefExists(adapter, objectRef, 'object_ref');
|
|
278
|
-
const relationAttrsJson = jsonField(input.relation_attrs, 'relation_attrs_json');
|
|
279
|
-
const evidenceRefsJson = jsonField(input.evidence_refs, 'evidence_refs_json');
|
|
280
|
-
const authorityScopeJson = jsonField(input.authority_scope_json, 'authority_scope_json');
|
|
281
|
-
const agentId = nullableString(input.agent_id);
|
|
282
|
-
const reasonText = nullableString(input.reason_text);
|
|
283
|
-
const envelopeHash = nullableString(input.envelope_hash);
|
|
284
|
-
const humanActorId = nullableString(input.human_actor_id);
|
|
285
|
-
const humanActorRole = nullableString(input.human_actor_role);
|
|
286
|
-
const reasonClassification = nullableString(input.reason_classification);
|
|
287
|
-
const requestIdempotencyKey = nullableString(input.request_idempotency_key);
|
|
288
|
-
const modelRunId = nullableString(input.model_run_id);
|
|
289
|
-
const contentHash = sha256Buffer(contentHashInput({
|
|
290
|
-
edge_type: edgeType,
|
|
291
|
-
subject_ref: subjectRef,
|
|
292
|
-
object_ref: objectRef,
|
|
293
|
-
relation_attrs_json: relationAttrsJson,
|
|
294
|
-
confidence,
|
|
295
|
-
source,
|
|
296
|
-
agent_id: agentId,
|
|
297
|
-
model_run_id: modelRunId,
|
|
298
|
-
envelope_hash: envelopeHash,
|
|
299
|
-
human_actor_id: humanActorId,
|
|
300
|
-
human_actor_role: humanActorRole,
|
|
301
|
-
authority_scope_json: authorityScopeJson,
|
|
302
|
-
reason_classification: reasonClassification,
|
|
303
|
-
reason_text: reasonText,
|
|
304
|
-
evidence_refs_json: evidenceRefsJson,
|
|
305
|
-
}));
|
|
306
|
-
const edgeIdempotencyKey = nullableString(input.edge_idempotency_key) ??
|
|
307
|
-
(requestIdempotencyKey ? deriveEdgeIdempotencyKey(requestIdempotencyKey, contentHash) : null);
|
|
308
|
-
const existing = selectByIdempotency(adapter, modelRunId, edgeIdempotencyKey);
|
|
309
|
-
if (existing) {
|
|
310
|
-
return existing;
|
|
311
|
-
}
|
|
312
|
-
const edgeId = nullableString(input.edge_id) ?? generatedEdgeId();
|
|
313
|
-
const createdAt = Date.now();
|
|
314
|
-
try {
|
|
315
|
-
return adapter.transaction(() => {
|
|
316
|
-
adapter
|
|
317
|
-
.prepare(`
|
|
318
|
-
INSERT INTO twin_edges (
|
|
319
|
-
edge_id, edge_type, subject_kind, subject_id, object_kind, object_id,
|
|
320
|
-
relation_attrs_json, confidence, source, agent_id, model_run_id, envelope_hash,
|
|
321
|
-
human_actor_id, human_actor_role, authority_scope_json, reason_classification,
|
|
322
|
-
reason_text, evidence_refs_json, request_idempotency_key, edge_idempotency_key,
|
|
323
|
-
content_hash, created_at
|
|
324
|
-
)
|
|
325
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
326
|
-
`)
|
|
327
|
-
.run(edgeId, edgeType, subjectRef.kind, subjectRef.id, objectRef.kind, objectRef.id, relationAttrsJson, confidence, source, agentId, modelRunId, envelopeHash, humanActorId, humanActorRole, authorityScopeJson, reasonClassification, reasonText, evidenceRefsJson, requestIdempotencyKey, edgeIdempotencyKey, contentHash, createdAt);
|
|
328
|
-
const inserted = getTwinEdge(adapter, edgeId);
|
|
329
|
-
if (!inserted) {
|
|
330
|
-
throw new Error(`Failed to load inserted twin edge: ${edgeId}`);
|
|
331
|
-
}
|
|
332
|
-
return inserted;
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
|
-
catch (error) {
|
|
336
|
-
const duplicate = selectByIdempotency(adapter, modelRunId, edgeIdempotencyKey);
|
|
337
|
-
if (duplicate) {
|
|
338
|
-
return duplicate;
|
|
339
|
-
}
|
|
340
|
-
throw error;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
129
|
//# sourceMappingURL=store.js.map
|
package/dist/edges/types.d.ts
CHANGED
|
@@ -29,6 +29,13 @@ export interface TwinVisibility {
|
|
|
29
29
|
tenantId?: string | null;
|
|
30
30
|
startMs?: number | null;
|
|
31
31
|
asOfMs?: number | null;
|
|
32
|
+
/**
|
|
33
|
+
* Which channels of each connector may be read. When present it DECIDES raw visibility
|
|
34
|
+
* here exactly as it does in the reader, so a ref reached through an edge or named as a
|
|
35
|
+
* seed satisfies the same rule as a row the reader would have returned. Without it a
|
|
36
|
+
* caller could reach past the read path by citing what it could not have read.
|
|
37
|
+
*/
|
|
38
|
+
channels?: Record<string, readonly string[]>;
|
|
32
39
|
}
|
|
33
40
|
export interface InsertTwinEdgeInput {
|
|
34
41
|
edge_id?: string;
|
|
@@ -84,5 +91,8 @@ export interface ListVisibleTwinEdgesOptions {
|
|
|
84
91
|
startMs?: number | null;
|
|
85
92
|
asOfMs?: number | null;
|
|
86
93
|
limit?: number;
|
|
94
|
+
/** Forwarded to the raw visibility rule. Declared so an injected implementation
|
|
95
|
+
* cannot silently drop the grant - it crossed this seam as an undeclared property. */
|
|
96
|
+
channels?: Record<string, readonly string[]>;
|
|
87
97
|
}
|
|
88
98
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @module embedding-client
|
|
13
13
|
*/
|
|
14
|
-
import type { EmbeddingRole } from './embeddings.js';
|
|
15
14
|
export declare const DEFAULT_PORT: number;
|
|
16
15
|
export declare const HOST = "127.0.0.1";
|
|
17
16
|
export declare const TIMEOUT_MS = 500;
|
|
@@ -26,20 +25,4 @@ export interface ServerStatus {
|
|
|
26
25
|
* Get server port from port file or default
|
|
27
26
|
*/
|
|
28
27
|
export declare function getServerPort(): number;
|
|
29
|
-
/**
|
|
30
|
-
* Check if embedding server is running
|
|
31
|
-
*/
|
|
32
|
-
export declare function isServerRunning(): Promise<boolean>;
|
|
33
|
-
/**
|
|
34
|
-
* Generate embedding via HTTP server
|
|
35
|
-
*
|
|
36
|
-
* @param text - Text to embed
|
|
37
|
-
* @param role - e5 role: 'passage' (default, stored text) or 'query' (search)
|
|
38
|
-
* @returns Embedding or null if failed
|
|
39
|
-
*/
|
|
40
|
-
export declare function getEmbeddingFromServer(text: string, role?: EmbeddingRole): Promise<Float32Array | null>;
|
|
41
|
-
/**
|
|
42
|
-
* Get server status
|
|
43
|
-
*/
|
|
44
|
-
export declare function getServerStatus(): Promise<ServerStatus | null>;
|
|
45
28
|
//# sourceMappingURL=embedding-client.d.ts.map
|
package/dist/embedding-client.js
CHANGED
|
@@ -18,12 +18,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.PORT_FILE = exports.TIMEOUT_MS = exports.HOST = exports.DEFAULT_PORT = void 0;
|
|
20
20
|
exports.getServerPort = getServerPort;
|
|
21
|
-
exports.isServerRunning = isServerRunning;
|
|
22
|
-
exports.getEmbeddingFromServer = getEmbeddingFromServer;
|
|
23
|
-
exports.getServerStatus = getServerStatus;
|
|
24
21
|
const fs_1 = __importDefault(require("fs"));
|
|
25
22
|
const path_1 = __importDefault(require("path"));
|
|
26
|
-
const debug_logger_js_1 = require("./debug-logger.js");
|
|
27
23
|
function resolveConfiguredPort() {
|
|
28
24
|
const rawPort = process.env.MAMA_EMBEDDING_PORT || process.env.MAMA_HTTP_PORT || '';
|
|
29
25
|
const parsedPort = parseInt(rawPort, 10);
|
|
@@ -54,80 +50,4 @@ function getServerPort() {
|
|
|
54
50
|
}
|
|
55
51
|
return exports.DEFAULT_PORT;
|
|
56
52
|
}
|
|
57
|
-
/**
|
|
58
|
-
* Check if embedding server is running
|
|
59
|
-
*/
|
|
60
|
-
async function isServerRunning() {
|
|
61
|
-
const port = getServerPort();
|
|
62
|
-
try {
|
|
63
|
-
const controller = new AbortController();
|
|
64
|
-
const timeout = setTimeout(() => controller.abort(), 200);
|
|
65
|
-
const response = await fetch(`http://${exports.HOST}:${port}/health`, {
|
|
66
|
-
signal: controller.signal,
|
|
67
|
-
});
|
|
68
|
-
clearTimeout(timeout);
|
|
69
|
-
return response.ok;
|
|
70
|
-
}
|
|
71
|
-
catch {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Generate embedding via HTTP server
|
|
77
|
-
*
|
|
78
|
-
* @param text - Text to embed
|
|
79
|
-
* @param role - e5 role: 'passage' (default, stored text) or 'query' (search)
|
|
80
|
-
* @returns Embedding or null if failed
|
|
81
|
-
*/
|
|
82
|
-
async function getEmbeddingFromServer(text, role = 'passage') {
|
|
83
|
-
const port = getServerPort();
|
|
84
|
-
try {
|
|
85
|
-
const controller = new AbortController();
|
|
86
|
-
const timeout = setTimeout(() => controller.abort(), exports.TIMEOUT_MS);
|
|
87
|
-
const response = await fetch(`http://${exports.HOST}:${port}/embed`, {
|
|
88
|
-
method: 'POST',
|
|
89
|
-
headers: { 'Content-Type': 'application/json' },
|
|
90
|
-
body: JSON.stringify({ text, role }),
|
|
91
|
-
signal: controller.signal,
|
|
92
|
-
});
|
|
93
|
-
clearTimeout(timeout);
|
|
94
|
-
if (!response.ok) {
|
|
95
|
-
const error = (await response.json());
|
|
96
|
-
throw new Error(error.error || 'Server error');
|
|
97
|
-
}
|
|
98
|
-
const result = (await response.json());
|
|
99
|
-
(0, debug_logger_js_1.info)(`[EmbeddingClient] Got embedding in ${result.latency}ms from server`);
|
|
100
|
-
return new Float32Array(result.embedding);
|
|
101
|
-
}
|
|
102
|
-
catch (error) {
|
|
103
|
-
if (error instanceof Error && error.name === 'AbortError') {
|
|
104
|
-
(0, debug_logger_js_1.warn)('[EmbeddingClient] Server timeout, will use fallback');
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
108
|
-
(0, debug_logger_js_1.warn)(`[EmbeddingClient] Server error: ${message}`);
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Get server status
|
|
114
|
-
*/
|
|
115
|
-
async function getServerStatus() {
|
|
116
|
-
const port = getServerPort();
|
|
117
|
-
try {
|
|
118
|
-
const controller = new AbortController();
|
|
119
|
-
const timeout = setTimeout(() => controller.abort(), 200);
|
|
120
|
-
const response = await fetch(`http://${exports.HOST}:${port}/health`, {
|
|
121
|
-
signal: controller.signal,
|
|
122
|
-
});
|
|
123
|
-
clearTimeout(timeout);
|
|
124
|
-
if (response.ok) {
|
|
125
|
-
return (await response.json());
|
|
126
|
-
}
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
catch {
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
53
|
//# sourceMappingURL=embedding-client.js.map
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* res.end('Unauthorized');
|
|
14
14
|
* }
|
|
15
15
|
*/
|
|
16
|
-
import type { IncomingMessage
|
|
16
|
+
import type { IncomingMessage } from 'http';
|
|
17
17
|
interface WebSocketLike {
|
|
18
18
|
close(code?: number, reason?: string): void;
|
|
19
19
|
}
|
|
@@ -40,14 +40,5 @@ export declare function authenticate(req: IncomingMessage): boolean;
|
|
|
40
40
|
* @returns True if authenticated, closes ws if not
|
|
41
41
|
*/
|
|
42
42
|
export declare function authenticateWebSocket(req: IncomingMessage, ws: WebSocketLike): boolean;
|
|
43
|
-
/**
|
|
44
|
-
* Middleware function type
|
|
45
|
-
*/
|
|
46
|
-
type MiddlewareNext = () => void;
|
|
47
|
-
/**
|
|
48
|
-
* Create authentication middleware for HTTP routes
|
|
49
|
-
* @returns Middleware function
|
|
50
|
-
*/
|
|
51
|
-
export declare function createAuthMiddleware(): (req: IncomingMessage, res: ServerResponse, next: MiddlewareNext) => void;
|
|
52
43
|
export {};
|
|
53
44
|
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -19,7 +19,6 @@ exports.AUTH_TOKEN = void 0;
|
|
|
19
19
|
exports.isLocalhost = isLocalhost;
|
|
20
20
|
exports.authenticate = authenticate;
|
|
21
21
|
exports.authenticateWebSocket = authenticateWebSocket;
|
|
22
|
-
exports.createAuthMiddleware = createAuthMiddleware;
|
|
23
22
|
const node_crypto_1 = require("node:crypto");
|
|
24
23
|
/**
|
|
25
24
|
* Environment variable for auth token
|
|
@@ -148,18 +147,4 @@ function authenticateWebSocket(req, ws) {
|
|
|
148
147
|
}
|
|
149
148
|
return true;
|
|
150
149
|
}
|
|
151
|
-
/**
|
|
152
|
-
* Create authentication middleware for HTTP routes
|
|
153
|
-
* @returns Middleware function
|
|
154
|
-
*/
|
|
155
|
-
function createAuthMiddleware() {
|
|
156
|
-
return (req, res, next) => {
|
|
157
|
-
if (!authenticate(req)) {
|
|
158
|
-
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
159
|
-
res.end(JSON.stringify({ error: 'Unauthorized' }));
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
next();
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
150
|
//# sourceMappingURL=auth.js.map
|
package/dist/embeddings.d.ts
CHANGED
|
@@ -51,18 +51,6 @@ export declare function generateEmbedding(text: string, role?: EmbeddingRole): P
|
|
|
51
51
|
* @returns 1024-dim enhanced embedding
|
|
52
52
|
*/
|
|
53
53
|
export declare function generateEnhancedEmbedding(decision: DecisionForEmbedding, role?: EmbeddingRole): Promise<Float32Array>;
|
|
54
|
-
/**
|
|
55
|
-
* Batch generate embeddings (optimized)
|
|
56
|
-
*
|
|
57
|
-
* Task 1: Implement Batch Embedding Generation
|
|
58
|
-
* AC #3: Target - 30ms for 10 embeddings (vs 300ms sequential)
|
|
59
|
-
*
|
|
60
|
-
* Strategy: Use native transformer batch processing for parallel inference
|
|
61
|
-
*
|
|
62
|
-
* @param texts - Array of texts to embed (max 10 per batch)
|
|
63
|
-
* @returns Array of embeddings
|
|
64
|
-
*/
|
|
65
|
-
export declare function generateBatchEmbeddings(texts: string[], role?: EmbeddingRole): Promise<Float32Array[]>;
|
|
66
54
|
/**
|
|
67
55
|
* Calculate cosine similarity between two embeddings
|
|
68
56
|
*
|
package/dist/embeddings.js
CHANGED
|
@@ -18,7 +18,6 @@ exports.getQuantized = exports.getEmbeddingDim = exports.getModelName = exports.
|
|
|
18
18
|
exports.prepareEmbeddingText = prepareEmbeddingText;
|
|
19
19
|
exports.generateEmbedding = generateEmbedding;
|
|
20
20
|
exports.generateEnhancedEmbedding = generateEnhancedEmbedding;
|
|
21
|
-
exports.generateBatchEmbeddings = generateBatchEmbeddings;
|
|
22
21
|
exports.cosineSimilarity = cosineSimilarity;
|
|
23
22
|
const os_1 = __importDefault(require("os"));
|
|
24
23
|
const path_1 = __importDefault(require("path"));
|
|
@@ -214,73 +213,6 @@ async function generateEnhancedEmbedding(decision, role = 'passage') {
|
|
|
214
213
|
const enrichedText = parts.join('\n').trim();
|
|
215
214
|
return generateEmbedding(enrichedText, role);
|
|
216
215
|
}
|
|
217
|
-
/**
|
|
218
|
-
* Batch generate embeddings (optimized)
|
|
219
|
-
*
|
|
220
|
-
* Task 1: Implement Batch Embedding Generation
|
|
221
|
-
* AC #3: Target - 30ms for 10 embeddings (vs 300ms sequential)
|
|
222
|
-
*
|
|
223
|
-
* Strategy: Use native transformer batch processing for parallel inference
|
|
224
|
-
*
|
|
225
|
-
* @param texts - Array of texts to embed (max 10 per batch)
|
|
226
|
-
* @returns Array of embeddings
|
|
227
|
-
*/
|
|
228
|
-
async function generateBatchEmbeddings(texts, role = 'passage') {
|
|
229
|
-
if (!Array.isArray(texts) || texts.length === 0) {
|
|
230
|
-
throw new Error('Texts must be a non-empty array');
|
|
231
|
-
}
|
|
232
|
-
for (const text of texts) {
|
|
233
|
-
if (typeof text !== 'string' || text.trim().length === 0) {
|
|
234
|
-
throw new Error('All texts must be non-empty strings');
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
assertEmbeddingsEnabled();
|
|
238
|
-
const preparedTexts = texts.map((text) => prepareEmbeddingText(text));
|
|
239
|
-
for (const text of preparedTexts) {
|
|
240
|
-
if (!text || text.length === 0) {
|
|
241
|
-
throw new Error('All texts must be non-empty strings');
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
const modelInputs = preparedTexts.map((t) => applyRolePrefix(t, role));
|
|
245
|
-
const startTime = Date.now();
|
|
246
|
-
try {
|
|
247
|
-
const model = await loadModel();
|
|
248
|
-
const expectedDim = (0, config_loader_js_1.getEmbeddingDim)();
|
|
249
|
-
// Native batch processing - single model forward pass
|
|
250
|
-
// This is significantly faster than sequential calls
|
|
251
|
-
const outputs = await model(modelInputs, {
|
|
252
|
-
pooling: 'mean',
|
|
253
|
-
normalize: true,
|
|
254
|
-
truncation: true,
|
|
255
|
-
max_length: exports.EMBEDDING_MODEL_MAX_LENGTH,
|
|
256
|
-
});
|
|
257
|
-
// Extract embeddings from batch output
|
|
258
|
-
const embeddings = [];
|
|
259
|
-
const batchSize = texts.length;
|
|
260
|
-
for (let i = 0; i < batchSize; i++) {
|
|
261
|
-
// Each embedding is expectedDim consecutive elements
|
|
262
|
-
const start = i * expectedDim;
|
|
263
|
-
const end = start + expectedDim;
|
|
264
|
-
const embedding = outputs.data.slice(start, end);
|
|
265
|
-
// Verify dimensions
|
|
266
|
-
if (embedding.length !== expectedDim) {
|
|
267
|
-
throw new Error(`Expected ${expectedDim}-dim, got ${embedding.length}-dim at index ${i}`);
|
|
268
|
-
}
|
|
269
|
-
embeddings.push(embedding);
|
|
270
|
-
}
|
|
271
|
-
const latency = Date.now() - startTime;
|
|
272
|
-
const avgLatency = latency / batchSize;
|
|
273
|
-
// Log for performance tracking
|
|
274
|
-
if (process.env.MAMA_DEBUG) {
|
|
275
|
-
(0, debug_logger_js_1.info)(`[MAMA] Batch(${batchSize}) embeddings: ${latency}ms total (${avgLatency.toFixed(1)}ms avg)`);
|
|
276
|
-
}
|
|
277
|
-
return embeddings;
|
|
278
|
-
}
|
|
279
|
-
catch (error) {
|
|
280
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
281
|
-
throw new Error(`Failed to generate batch embeddings: ${message}`);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
216
|
/**
|
|
285
217
|
* Calculate cosine similarity between two embeddings
|
|
286
218
|
*
|
|
@@ -56,11 +56,6 @@ export declare function computeCrossLanguageRecallAtK(goldPairs: AuditGoldPair[]
|
|
|
56
56
|
numerator: number;
|
|
57
57
|
denominator: number;
|
|
58
58
|
};
|
|
59
|
-
export declare function computeCrossLanguageRecallAt5(goldPairs: AuditGoldPair[], matches: AuditCandidateGoldLink[]): {
|
|
60
|
-
recall: number;
|
|
61
|
-
numerator: number;
|
|
62
|
-
denominator: number;
|
|
63
|
-
};
|
|
64
59
|
export declare function computeCrossLanguageRecallAt10(goldPairs: AuditGoldPair[], matches: AuditCandidateGoldLink[]): {
|
|
65
60
|
recall: number;
|
|
66
61
|
numerator: number;
|
|
@@ -10,7 +10,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.FALSE_MERGE_HARD_CEILING = void 0;
|
|
11
11
|
exports.computeFalseMergeRate = computeFalseMergeRate;
|
|
12
12
|
exports.computeCrossLanguageRecallAtK = computeCrossLanguageRecallAtK;
|
|
13
|
-
exports.computeCrossLanguageRecallAt5 = computeCrossLanguageRecallAt5;
|
|
14
13
|
exports.computeCrossLanguageRecallAt10 = computeCrossLanguageRecallAt10;
|
|
15
14
|
exports.computeOntologyViolationCount = computeOntologyViolationCount;
|
|
16
15
|
exports.computeProjectionFragmentationRate = computeProjectionFragmentationRate;
|
|
@@ -56,9 +55,6 @@ function computeCrossLanguageRecallAtK(goldPairs, matches, k) {
|
|
|
56
55
|
}
|
|
57
56
|
return { recall: numerator / denominator, numerator, denominator };
|
|
58
57
|
}
|
|
59
|
-
function computeCrossLanguageRecallAt5(goldPairs, matches) {
|
|
60
|
-
return computeCrossLanguageRecallAtK(goldPairs, matches, 5);
|
|
61
|
-
}
|
|
62
58
|
function computeCrossLanguageRecallAt10(goldPairs, matches) {
|
|
63
59
|
return computeCrossLanguageRecallAtK(goldPairs, matches, 10);
|
|
64
60
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type { EntityObservation
|
|
1
|
+
import type { EntityObservation } from './types.js';
|
|
2
2
|
export declare const ENTITY_EMBEDDING_TOPN = 50;
|
|
3
3
|
export interface CandidateGeneratorOptions {
|
|
4
4
|
embeddingScorer?: (left: EntityObservation, right: EntityObservation) => Promise<number>;
|
|
5
5
|
topN?: number;
|
|
6
6
|
}
|
|
7
7
|
export declare function dedupeObservationsBySource(observations: EntityObservation[]): EntityObservation[];
|
|
8
|
-
export declare function generateResolutionCandidates(observations: EntityObservation[], options?: CandidateGeneratorOptions): Promise<EntityResolutionCandidate[]>;
|
|
9
8
|
//# sourceMappingURL=candidate-generator.d.ts.map
|