@jungjaehoon/mama-core 2.3.0 → 2.4.1
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/067-add-connector-event-source-entity-id.sql +14 -0
- package/db/migrations/068-tool-trace-diagnostics.sql +13 -0
- package/dist/connectors/event-index.js +8 -7
- package/dist/connectors/raw-query.d.ts +24 -2
- package/dist/connectors/raw-query.js +108 -1
- package/dist/connectors/types.d.ts +6 -0
- package/dist/db-adapter/node-sqlite-adapter.d.ts +4 -0
- package/dist/db-adapter/node-sqlite-adapter.js +130 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -3
- package/dist/mama-api.d.ts +4 -2
- package/dist/mama-api.js +5 -1
- package/dist/model-runs/tool-trace-store.d.ts +5 -1
- package/dist/model-runs/tool-trace-store.js +110 -5
- package/dist/model-runs/types.d.ts +31 -0
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
-- Migration 067: give connector_event_index a first-class source_entity_id so an agent can read an
|
|
2
|
+
-- entity's change history (the revisions save() preserves) through the same grant-bounded core index
|
|
3
|
+
-- it already searches. Previously sourceEntityId lived only inside metadata_json, with no by-entity
|
|
4
|
+
-- query. Additive and backward-compatible: existing rows are backfilled from metadata_json.
|
|
5
|
+
ALTER TABLE connector_event_index ADD COLUMN source_entity_id TEXT;
|
|
6
|
+
|
|
7
|
+
UPDATE connector_event_index
|
|
8
|
+
SET source_entity_id = json_extract(metadata_json, '$.sourceEntityId')
|
|
9
|
+
WHERE source_entity_id IS NULL
|
|
10
|
+
AND metadata_json IS NOT NULL
|
|
11
|
+
AND json_extract(metadata_json, '$.sourceEntityId') IS NOT NULL;
|
|
12
|
+
|
|
13
|
+
CREATE INDEX IF NOT EXISTS idx_connector_event_source_entity
|
|
14
|
+
ON connector_event_index(source_connector, source_entity_id);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- TG-03/04/05: additive diagnostic evidence, scoped by host metadata.
|
|
2
|
+
-- The migration runner reconciles existing MetricsStore scope columns idempotently.
|
|
3
|
+
-- NULL scope preserves legacy records without granting discovery access.
|
|
4
|
+
ALTER TABLE tool_traces ADD COLUMN diagnostic_json TEXT;
|
|
5
|
+
ALTER TABLE tool_traces ADD COLUMN evidence_json TEXT;
|
|
6
|
+
ALTER TABLE tool_traces ADD COLUMN catalog_revision TEXT;
|
|
7
|
+
ALTER TABLE tool_traces ADD COLUMN owner_scope TEXT;
|
|
8
|
+
ALTER TABLE tool_traces ADD COLUMN project_id TEXT;
|
|
9
|
+
ALTER TABLE tool_traces ADD COLUMN channel_id TEXT;
|
|
10
|
+
CREATE INDEX IF NOT EXISTS idx_tool_traces_scope_recency
|
|
11
|
+
ON tool_traces(owner_scope, project_id, created_at DESC, trace_id DESC);
|
|
12
|
+
CREATE INDEX IF NOT EXISTS idx_tool_traces_channel_recency
|
|
13
|
+
ON tool_traces(owner_scope, project_id, channel_id, created_at DESC, trace_id DESC);
|
|
@@ -135,15 +135,16 @@ function upsertConnectorEventIndex(adapter, input) {
|
|
|
135
135
|
adapter
|
|
136
136
|
.prepare(`
|
|
137
137
|
INSERT INTO connector_event_index (
|
|
138
|
-
event_index_id, source_connector, source_type, source_id,
|
|
139
|
-
channel, author, title, content, event_datetime, event_date,
|
|
140
|
-
source_cursor, tenant_id, project_id, memory_scope_kind,
|
|
141
|
-
metadata_json, artifact_locator, artifact_title, content_hash,
|
|
142
|
-
expires_at
|
|
138
|
+
event_index_id, source_connector, source_type, source_id, source_entity_id,
|
|
139
|
+
source_locator, channel, author, title, content, event_datetime, event_date,
|
|
140
|
+
source_timestamp_ms, source_cursor, tenant_id, project_id, memory_scope_kind,
|
|
141
|
+
memory_scope_id, metadata_json, artifact_locator, artifact_title, content_hash,
|
|
142
|
+
indexed_at, updated_at, expires_at
|
|
143
143
|
)
|
|
144
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
144
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
145
145
|
ON CONFLICT(source_connector, source_id) DO UPDATE SET
|
|
146
146
|
source_type = excluded.source_type,
|
|
147
|
+
source_entity_id = excluded.source_entity_id,
|
|
147
148
|
source_locator = excluded.source_locator,
|
|
148
149
|
channel = excluded.channel,
|
|
149
150
|
author = excluded.author,
|
|
@@ -182,7 +183,7 @@ function upsertConnectorEventIndex(adapter, input) {
|
|
|
182
183
|
ELSE connector_event_index.operator_observation_seq
|
|
183
184
|
END
|
|
184
185
|
`)
|
|
185
|
-
.run(eventIndexId, input.source_connector, input.source_type, input.source_id, input.source_locator ?? null, input.channel ?? null, input.author ?? null, input.title ?? null, input.content, eventDatetime, eventDate, sourceTimestampMs, input.source_cursor ?? null, input.tenant_id ?? null, input.project_id ?? null, input.memory_scope_kind ?? null, input.memory_scope_id ?? null, metadataJson, input.artifact_locator ?? null, input.artifact_title ?? null, contentHash, input.indexed_at ?? timestamp, timestamp, input.expires_at ?? null);
|
|
186
|
+
.run(eventIndexId, input.source_connector, input.source_type, input.source_id, input.source_entity_id ?? input.source_id, input.source_locator ?? null, input.channel ?? null, input.author ?? null, input.title ?? null, input.content, eventDatetime, eventDate, sourceTimestampMs, input.source_cursor ?? null, input.tenant_id ?? null, input.project_id ?? null, input.memory_scope_kind ?? null, input.memory_scope_id ?? null, metadataJson, input.artifact_locator ?? null, input.artifact_title ?? null, contentHash, input.indexed_at ?? timestamp, timestamp, input.expires_at ?? null);
|
|
186
187
|
const saved = getConnectorEventIndexRecord(adapter, input.source_connector, input.source_id);
|
|
187
188
|
if (!saved) {
|
|
188
189
|
throw new Error(`Failed to read connector_event_index row after upsert: ${input.source_connector}/${input.source_id}`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DatabaseAdapter } from '../db-manager.js';
|
|
2
|
-
import type { RawSearchHit, RawSearchInput, RawSearchResult, RawSearchScopeFilter } from './types.js';
|
|
2
|
+
import type { RawSearchHit, RawDocument, RawSearchInput, RawSearchResult, RawSearchScopeFilter } from './types.js';
|
|
3
3
|
type RawQueryAdapter = Pick<DatabaseAdapter, 'prepare'>;
|
|
4
4
|
interface RawWindowInput {
|
|
5
5
|
connectors?: string[];
|
|
@@ -9,10 +9,32 @@ interface RawWindowInput {
|
|
|
9
9
|
}
|
|
10
10
|
export declare function searchRaw(adapter: RawQueryAdapter, input: RawSearchInput): RawSearchResult;
|
|
11
11
|
export declare function searchAllRaw(adapter: RawQueryAdapter, input: RawSearchInput): RawSearchResult;
|
|
12
|
-
export declare function getRawById(adapter: RawQueryAdapter, rawId: string, visibility: Pick<RawSearchInput, 'connectors' | 'scopes'>):
|
|
12
|
+
export declare function getRawById(adapter: RawQueryAdapter, rawId: string, visibility: Pick<RawSearchInput, 'connectors' | 'scopes'>): RawDocument | null;
|
|
13
13
|
export declare function getRawWindow(adapter: RawQueryAdapter, rawId: string, input: RawWindowInput): {
|
|
14
14
|
target: RawSearchHit;
|
|
15
15
|
items: RawSearchHit[];
|
|
16
16
|
} | null;
|
|
17
|
+
export interface RawHistoryInput {
|
|
18
|
+
/** The entity whose revisions to read. Provide this OR `rawId`. */
|
|
19
|
+
entityId?: string;
|
|
20
|
+
/**
|
|
21
|
+
* A raw event id (event_index_id) to anchor on: its entity is resolved under the SAME
|
|
22
|
+
* visibility, then that entity's revisions are returned. An anchor the caller may not see
|
|
23
|
+
* resolves to nothing, so a rawId cannot widen what the caller can read.
|
|
24
|
+
*/
|
|
25
|
+
rawId?: string;
|
|
26
|
+
connectors?: string[];
|
|
27
|
+
scopes?: RawSearchScopeFilter[];
|
|
28
|
+
fromMs?: number;
|
|
29
|
+
toMs?: number;
|
|
30
|
+
limit?: number;
|
|
31
|
+
cursor?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Chronological change history of one upstream entity (rows sharing source_entity_id), bounded by
|
|
35
|
+
* the SAME connector/scope visibility as search - a citation must not out-read reading. Oldest first,
|
|
36
|
+
* cursor-paged. Rows with a NULL source_entity_id (no revision grouping) never match an entity query.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getRawHistory(adapter: RawQueryAdapter, input: RawHistoryInput): RawSearchResult;
|
|
17
39
|
export type { RawSearchHit, RawSearchInput, RawSearchResult, RawSearchScopeFilter, } from './types.js';
|
|
18
40
|
//# sourceMappingURL=raw-query.d.ts.map
|
|
@@ -4,6 +4,7 @@ exports.searchRaw = searchRaw;
|
|
|
4
4
|
exports.searchAllRaw = searchAllRaw;
|
|
5
5
|
exports.getRawById = getRawById;
|
|
6
6
|
exports.getRawWindow = getRawWindow;
|
|
7
|
+
exports.getRawHistory = getRawHistory;
|
|
7
8
|
const types_js_1 = require("../memory/types.js");
|
|
8
9
|
const event_index_js_1 = require("./event-index.js");
|
|
9
10
|
const DEFAULT_RAW_LIMIT = 25;
|
|
@@ -220,7 +221,7 @@ function getRawById(adapter, rawId, visibility) {
|
|
|
220
221
|
LIMIT 1
|
|
221
222
|
`)
|
|
222
223
|
.get(...params);
|
|
223
|
-
return row ? toRawHit(row) : null;
|
|
224
|
+
return row ? { ...toRawHit(row), content: String(row.content) } : null;
|
|
224
225
|
}
|
|
225
226
|
function getRawWindow(adapter, rawId, input) {
|
|
226
227
|
const targetParams = [rawId];
|
|
@@ -302,4 +303,110 @@ function afterWindowRows(adapter, target, input, limit) {
|
|
|
302
303
|
`)
|
|
303
304
|
.all(...params, limit);
|
|
304
305
|
}
|
|
306
|
+
// The entity a raw event belongs to, plus its connector. source_entity_id is unique only WITHIN a
|
|
307
|
+
// connector, so history must carry the connector too or two connectors sharing an id would merge.
|
|
308
|
+
function resolveEntityAnchor(adapter, rawId, visibility) {
|
|
309
|
+
const clauses = ['e.event_index_id = ?'];
|
|
310
|
+
const params = [rawId];
|
|
311
|
+
appendFilters(clauses, params, { query: '*', ...visibility });
|
|
312
|
+
const row = adapter
|
|
313
|
+
.prepare(`SELECT source_entity_id, source_connector FROM connector_event_index e WHERE ${clauses.join(' AND ')} LIMIT 1`)
|
|
314
|
+
.get(...params);
|
|
315
|
+
return row &&
|
|
316
|
+
typeof row.source_entity_id === 'string' &&
|
|
317
|
+
row.source_entity_id.length > 0 &&
|
|
318
|
+
typeof row.source_connector === 'string' &&
|
|
319
|
+
row.source_connector.length > 0
|
|
320
|
+
? { entityId: row.source_entity_id, connector: row.source_connector }
|
|
321
|
+
: null;
|
|
322
|
+
}
|
|
323
|
+
function singleConnector(connectors) {
|
|
324
|
+
const normalized = normalizeConnectors(connectors);
|
|
325
|
+
return normalized.length === 1 ? normalized[0] : null;
|
|
326
|
+
}
|
|
327
|
+
function encodeHistoryCursor(row) {
|
|
328
|
+
return Buffer.from(JSON.stringify({ timestampMs: row.source_timestamp_ms, rawId: row.event_index_id }), 'utf8').toString('base64url');
|
|
329
|
+
}
|
|
330
|
+
function decodeHistoryCursor(cursor) {
|
|
331
|
+
if (!cursor) {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
try {
|
|
335
|
+
const parsed = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8'));
|
|
336
|
+
if (typeof parsed.timestampMs !== 'number' ||
|
|
337
|
+
!Number.isFinite(parsed.timestampMs) ||
|
|
338
|
+
typeof parsed.rawId !== 'string' ||
|
|
339
|
+
parsed.rawId.length === 0) {
|
|
340
|
+
throw new Error('invalid shape');
|
|
341
|
+
}
|
|
342
|
+
return { timestampMs: parsed.timestampMs, rawId: parsed.rawId };
|
|
343
|
+
}
|
|
344
|
+
catch (err) {
|
|
345
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
346
|
+
throw new Error(`Invalid raw history cursor: ${message}`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Chronological change history of one upstream entity (rows sharing source_entity_id), bounded by
|
|
351
|
+
* the SAME connector/scope visibility as search - a citation must not out-read reading. Oldest first,
|
|
352
|
+
* cursor-paged. Rows with a NULL source_entity_id (no revision grouping) never match an entity query.
|
|
353
|
+
*/
|
|
354
|
+
function getRawHistory(adapter, input) {
|
|
355
|
+
// Revision identity is connector-scoped. The rawId path takes the anchor's own connector; the
|
|
356
|
+
// entityId path requires the caller to name exactly one connector, since an entity id alone is
|
|
357
|
+
// ambiguous across connectors.
|
|
358
|
+
const trimmedEntityId = input.entityId?.trim() ?? '';
|
|
359
|
+
const anchor = trimmedEntityId.length > 0
|
|
360
|
+
? (() => {
|
|
361
|
+
const connector = singleConnector(input.connectors);
|
|
362
|
+
return connector ? { entityId: trimmedEntityId, connector } : null;
|
|
363
|
+
})()
|
|
364
|
+
: input.rawId && input.rawId.trim().length > 0
|
|
365
|
+
? resolveEntityAnchor(adapter, input.rawId.trim(), {
|
|
366
|
+
connectors: input.connectors,
|
|
367
|
+
scopes: input.scopes,
|
|
368
|
+
})
|
|
369
|
+
: null;
|
|
370
|
+
if (!anchor) {
|
|
371
|
+
return { hits: [], next_cursor: null };
|
|
372
|
+
}
|
|
373
|
+
const limit = normalizeLimit(input.limit);
|
|
374
|
+
if (limit === 0) {
|
|
375
|
+
return { hits: [], next_cursor: null };
|
|
376
|
+
}
|
|
377
|
+
const clauses = ['e.source_entity_id = ?'];
|
|
378
|
+
const params = [anchor.entityId];
|
|
379
|
+
appendFilters(clauses, params, {
|
|
380
|
+
query: '*',
|
|
381
|
+
connectors: [anchor.connector],
|
|
382
|
+
scopes: input.scopes,
|
|
383
|
+
fromMs: input.fromMs,
|
|
384
|
+
toMs: input.toMs,
|
|
385
|
+
});
|
|
386
|
+
const cursor = decodeHistoryCursor(input.cursor);
|
|
387
|
+
if (cursor) {
|
|
388
|
+
clauses.push('(e.source_timestamp_ms > ? OR (e.source_timestamp_ms = ? AND e.event_index_id > ?))');
|
|
389
|
+
params.push(cursor.timestampMs, cursor.timestampMs, cursor.rawId);
|
|
390
|
+
}
|
|
391
|
+
const rows = adapter
|
|
392
|
+
.prepare(`
|
|
393
|
+
SELECT e.*, 0 AS rank
|
|
394
|
+
FROM connector_event_index e
|
|
395
|
+
WHERE ${clauses.join(' AND ')}
|
|
396
|
+
ORDER BY e.source_timestamp_ms ASC, e.event_index_id ASC
|
|
397
|
+
LIMIT ?
|
|
398
|
+
`)
|
|
399
|
+
.all(...params, limit + 1);
|
|
400
|
+
const pageRows = rows.slice(0, limit);
|
|
401
|
+
const nextRow = rows.length > limit ? pageRows[pageRows.length - 1] : undefined;
|
|
402
|
+
return {
|
|
403
|
+
hits: pageRows.map(toRawHit),
|
|
404
|
+
next_cursor: nextRow
|
|
405
|
+
? encodeHistoryCursor({
|
|
406
|
+
source_timestamp_ms: Number(nextRow.source_timestamp_ms),
|
|
407
|
+
event_index_id: String(nextRow.event_index_id),
|
|
408
|
+
})
|
|
409
|
+
: null,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
305
412
|
//# sourceMappingURL=raw-query.js.map
|
|
@@ -32,6 +32,8 @@ export interface UpsertConnectorEventIndexInput {
|
|
|
32
32
|
source_connector: string;
|
|
33
33
|
source_type: string;
|
|
34
34
|
source_id: string;
|
|
35
|
+
/** Stable upstream entity across revisions; enables grant-bounded change-history reads. */
|
|
36
|
+
source_entity_id?: string | null;
|
|
35
37
|
source_locator?: string | null;
|
|
36
38
|
channel?: string | null;
|
|
37
39
|
author?: string | null;
|
|
@@ -103,6 +105,10 @@ export interface RawSearchHit {
|
|
|
103
105
|
source_ref: string | null;
|
|
104
106
|
metadata: Record<string, unknown>;
|
|
105
107
|
}
|
|
108
|
+
/** Explicit detail access includes the complete source; search results remain bounded previews. */
|
|
109
|
+
export interface RawDocument extends RawSearchHit {
|
|
110
|
+
content: string;
|
|
111
|
+
}
|
|
106
112
|
export interface RawSearchResult {
|
|
107
113
|
hits: RawSearchHit[];
|
|
108
114
|
next_cursor: string | null;
|
|
@@ -66,10 +66,14 @@ export declare class NodeSQLiteAdapter extends DatabaseAdapter {
|
|
|
66
66
|
private hasOperatorMemoryCommitIntentClaimInvariant;
|
|
67
67
|
private assertMigration040BaseComplete;
|
|
68
68
|
private assertMigration041Complete;
|
|
69
|
+
private needsToolTraceDiagnosticsRepair068;
|
|
70
|
+
private recoverToolTraceDiagnosticsMigration068;
|
|
69
71
|
private recoverMemoryProvenanceMigration032;
|
|
70
72
|
private assertMigration032Complete;
|
|
71
73
|
private recoverConnectorEventScopeMigration034;
|
|
72
74
|
private assertMigration034Complete;
|
|
75
|
+
private recoverConnectorEventSourceEntityIdMigration067;
|
|
76
|
+
private assertMigration067Complete;
|
|
73
77
|
private recoverConnectorEventOperatorSeqMigration039;
|
|
74
78
|
private assertMigration039Complete;
|
|
75
79
|
private recoverConnectorEventSequencesMigration062;
|
|
@@ -376,6 +376,18 @@ class NodeSQLiteAdapter extends base_adapter_js_1.DatabaseAdapter {
|
|
|
376
376
|
if (version <= currentVersion) {
|
|
377
377
|
continue;
|
|
378
378
|
}
|
|
379
|
+
// Runtime MetricsStore may already own project_id/channel_id. Reconcile
|
|
380
|
+
// this additive migration atomically instead of accepting a duplicate skip.
|
|
381
|
+
if (version === 68) {
|
|
382
|
+
if (!this.tableExists('tool_traces')) {
|
|
383
|
+
// Legacy version ledgers can have skipped 033; the structural repair
|
|
384
|
+
// below creates its table before reconciling 068. Do not stamp it yet.
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
this.recoverToolTraceDiagnosticsMigration068();
|
|
388
|
+
(0, debug_logger_js_1.info)(`[node-sqlite-adapter] Migration ${file} reconciled successfully`);
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
379
391
|
const migrationPath = path_1.default.join(migrationsDir, file);
|
|
380
392
|
const migrationSQL = fs_1.default.readFileSync(migrationPath, 'utf8');
|
|
381
393
|
(0, debug_logger_js_1.info)(`[node-sqlite-adapter] Applying migration: ${file}`);
|
|
@@ -409,6 +421,11 @@ class NodeSQLiteAdapter extends base_adapter_js_1.DatabaseAdapter {
|
|
|
409
421
|
(0, debug_logger_js_1.info)(`[node-sqlite-adapter] Migration ${file} recovered successfully`);
|
|
410
422
|
continue;
|
|
411
423
|
}
|
|
424
|
+
if (message.includes('duplicate column') && version === 67) {
|
|
425
|
+
this.recoverConnectorEventSourceEntityIdMigration067();
|
|
426
|
+
(0, debug_logger_js_1.info)(`[node-sqlite-adapter] Migration ${file} recovered successfully`);
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
412
429
|
if (message.includes('no such column') && version === 62) {
|
|
413
430
|
(0, debug_logger_js_1.warn)(`[node-sqlite-adapter] Migration ${file} deferred until connector structure recovery (${message})`);
|
|
414
431
|
continue;
|
|
@@ -418,6 +435,11 @@ class NodeSQLiteAdapter extends base_adapter_js_1.DatabaseAdapter {
|
|
|
418
435
|
(0, debug_logger_js_1.warn)(`[node-sqlite-adapter] Migration ${file} deferred until connector structure recovery (${message})`);
|
|
419
436
|
continue;
|
|
420
437
|
}
|
|
438
|
+
if (version === 67 &&
|
|
439
|
+
(message.includes('no such column') || message.includes('no such table'))) {
|
|
440
|
+
(0, debug_logger_js_1.warn)(`[node-sqlite-adapter] Migration ${file} deferred until connector structure recovery (${message})`);
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
421
443
|
if (message.includes('duplicate column')) {
|
|
422
444
|
(0, debug_logger_js_1.warn)(`[node-sqlite-adapter] Migration ${file} skipped (duplicate column - already applied)`);
|
|
423
445
|
this.prepare('INSERT OR IGNORE INTO schema_version (version) VALUES (?)').run(version);
|
|
@@ -469,6 +491,14 @@ class NodeSQLiteAdapter extends base_adapter_js_1.DatabaseAdapter {
|
|
|
469
491
|
if (!this.tableExists('model_runs') || !this.tableExists('tool_traces')) {
|
|
470
492
|
this.applyRepairMigration(migrationsDir, '033-create-model-runs-and-tool-traces.sql', 'model run provenance');
|
|
471
493
|
}
|
|
494
|
+
// Also repairs databases already stamped 68 by the former generic duplicate
|
|
495
|
+
// skip, which rolled back the new columns before advancing schema_version.
|
|
496
|
+
// Only enter the recovery transaction when something is actually missing —
|
|
497
|
+
// a complete database must not take the write path on every runMigrations().
|
|
498
|
+
if (fs_1.default.existsSync(path_1.default.join(migrationsDir, '068-tool-trace-diagnostics.sql')) &&
|
|
499
|
+
this.needsToolTraceDiagnosticsRepair068()) {
|
|
500
|
+
this.recoverToolTraceDiagnosticsMigration068();
|
|
501
|
+
}
|
|
472
502
|
if (this.tableExists('connector_event_index')) {
|
|
473
503
|
const connectorColumns = this.tableColumns('connector_event_index');
|
|
474
504
|
const hasMissingConnectorScopeColumn = [
|
|
@@ -515,6 +545,13 @@ class NodeSQLiteAdapter extends base_adapter_js_1.DatabaseAdapter {
|
|
|
515
545
|
(0, debug_logger_js_1.info)('[node-sqlite-adapter] Repaired skipped legacy connector event refresh migration');
|
|
516
546
|
}
|
|
517
547
|
}
|
|
548
|
+
const hasMissingSourceEntityIdFeature = !this.tableColumns('connector_event_index').has('source_entity_id') ||
|
|
549
|
+
!this.indexExists('idx_connector_event_source_entity') ||
|
|
550
|
+
!this.schemaVersionExists(67);
|
|
551
|
+
if (hasMissingSourceEntityIdFeature) {
|
|
552
|
+
this.recoverConnectorEventSourceEntityIdMigration067();
|
|
553
|
+
(0, debug_logger_js_1.info)('[node-sqlite-adapter] Repaired skipped connector event source_entity_id migration');
|
|
554
|
+
}
|
|
518
555
|
}
|
|
519
556
|
if (!this.tableExists('twin_edges')) {
|
|
520
557
|
this.applyRepairMigration(migrationsDir, '035-create-twin-edges.sql', 'twin edge ledger');
|
|
@@ -630,6 +667,65 @@ class NodeSQLiteAdapter extends base_adapter_js_1.DatabaseAdapter {
|
|
|
630
667
|
throw new Error('Migration 041 recovery failed: incompatible operator_memory_commit_intents table definition missing claim invariant');
|
|
631
668
|
}
|
|
632
669
|
}
|
|
670
|
+
needsToolTraceDiagnosticsRepair068() {
|
|
671
|
+
if (!this.tableExists('tool_traces')) {
|
|
672
|
+
// The table itself is missing: let the recovery helper fail loudly.
|
|
673
|
+
return true;
|
|
674
|
+
}
|
|
675
|
+
const columns = this.tableColumns('tool_traces');
|
|
676
|
+
const hasMissingColumn = [
|
|
677
|
+
'diagnostic_json',
|
|
678
|
+
'evidence_json',
|
|
679
|
+
'catalog_revision',
|
|
680
|
+
'owner_scope',
|
|
681
|
+
'project_id',
|
|
682
|
+
'channel_id',
|
|
683
|
+
].some((column) => !columns.has(column));
|
|
684
|
+
const hasMissingIndex = [
|
|
685
|
+
'idx_tool_traces_scope_recency',
|
|
686
|
+
'idx_tool_traces_channel_recency',
|
|
687
|
+
].some((indexName) => !this.indexExists(indexName));
|
|
688
|
+
return hasMissingColumn || hasMissingIndex || !this.schemaVersionExists(68);
|
|
689
|
+
}
|
|
690
|
+
recoverToolTraceDiagnosticsMigration068() {
|
|
691
|
+
this.transaction(() => {
|
|
692
|
+
if (!this.tableExists('tool_traces')) {
|
|
693
|
+
throw new Error('Migration 068 recovery failed: missing table tool_traces');
|
|
694
|
+
}
|
|
695
|
+
const expectedColumns = [
|
|
696
|
+
'diagnostic_json',
|
|
697
|
+
'evidence_json',
|
|
698
|
+
'catalog_revision',
|
|
699
|
+
'owner_scope',
|
|
700
|
+
'project_id',
|
|
701
|
+
'channel_id',
|
|
702
|
+
];
|
|
703
|
+
const columns = this.tableColumns('tool_traces');
|
|
704
|
+
for (const column of expectedColumns) {
|
|
705
|
+
if (!columns.has(column)) {
|
|
706
|
+
this.exec(`ALTER TABLE tool_traces ADD COLUMN ${column} TEXT`);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
this.exec(`
|
|
710
|
+
CREATE INDEX IF NOT EXISTS idx_tool_traces_scope_recency
|
|
711
|
+
ON tool_traces(owner_scope, project_id, created_at DESC, trace_id DESC);
|
|
712
|
+
CREATE INDEX IF NOT EXISTS idx_tool_traces_channel_recency
|
|
713
|
+
ON tool_traces(owner_scope, project_id, channel_id, created_at DESC, trace_id DESC);
|
|
714
|
+
`);
|
|
715
|
+
const actualColumns = this.tableColumns('tool_traces');
|
|
716
|
+
for (const column of expectedColumns) {
|
|
717
|
+
if (!actualColumns.has(column)) {
|
|
718
|
+
throw new Error(`Migration 068 recovery failed: missing tool_traces.${column}`);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
for (const index of ['idx_tool_traces_scope_recency', 'idx_tool_traces_channel_recency']) {
|
|
722
|
+
if (!this.indexExists(index)) {
|
|
723
|
+
throw new Error(`Migration 068 recovery failed: missing index ${index}`);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
this.prepare('INSERT OR IGNORE INTO schema_version (version) VALUES (?)').run(68);
|
|
727
|
+
});
|
|
728
|
+
}
|
|
633
729
|
recoverMemoryProvenanceMigration032() {
|
|
634
730
|
this.transaction(() => {
|
|
635
731
|
const expectedDecisionColumns = [
|
|
@@ -743,6 +839,40 @@ class NodeSQLiteAdapter extends base_adapter_js_1.DatabaseAdapter {
|
|
|
743
839
|
}
|
|
744
840
|
}
|
|
745
841
|
}
|
|
842
|
+
recoverConnectorEventSourceEntityIdMigration067() {
|
|
843
|
+
this.transaction(() => {
|
|
844
|
+
const columns = this.tableColumns('connector_event_index');
|
|
845
|
+
if (!columns.has('source_entity_id')) {
|
|
846
|
+
this.exec('ALTER TABLE connector_event_index ADD COLUMN source_entity_id TEXT');
|
|
847
|
+
}
|
|
848
|
+
// Backfill only when metadata_json exists; a legacy/minimal table rebuilt by the repair path
|
|
849
|
+
// may not have it yet. New rows carry source_entity_id at write time regardless.
|
|
850
|
+
if (columns.has('metadata_json')) {
|
|
851
|
+
this.exec(`
|
|
852
|
+
UPDATE connector_event_index
|
|
853
|
+
SET source_entity_id = json_extract(metadata_json, '$.sourceEntityId')
|
|
854
|
+
WHERE source_entity_id IS NULL
|
|
855
|
+
AND metadata_json IS NOT NULL
|
|
856
|
+
AND json_extract(metadata_json, '$.sourceEntityId') IS NOT NULL
|
|
857
|
+
`);
|
|
858
|
+
}
|
|
859
|
+
this.exec(`
|
|
860
|
+
CREATE INDEX IF NOT EXISTS idx_connector_event_source_entity
|
|
861
|
+
ON connector_event_index(source_connector, source_entity_id)
|
|
862
|
+
`);
|
|
863
|
+
this.assertMigration067Complete();
|
|
864
|
+
this.prepare('INSERT OR IGNORE INTO schema_version (version, description) VALUES (?, ?)').run(67, 'Add connector_event_index source_entity_id');
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
assertMigration067Complete() {
|
|
868
|
+
const columns = this.tableColumns('connector_event_index');
|
|
869
|
+
if (!columns.has('source_entity_id')) {
|
|
870
|
+
throw new Error('Migration 067 recovery failed: missing connector_event_index.source_entity_id');
|
|
871
|
+
}
|
|
872
|
+
if (!this.indexExists('idx_connector_event_source_entity')) {
|
|
873
|
+
throw new Error('Migration 067 recovery failed: missing index idx_connector_event_source_entity');
|
|
874
|
+
}
|
|
875
|
+
}
|
|
746
876
|
recoverConnectorEventOperatorSeqMigration039() {
|
|
747
877
|
this.transaction(() => {
|
|
748
878
|
const columns = this.tableColumns('connector_event_index');
|
package/dist/index.d.ts
CHANGED
|
@@ -25,9 +25,9 @@ export { createTrustedProvenanceCapability, assertTrustedProvenanceCapability, t
|
|
|
25
25
|
export { getMemoryProvenance, listMemoriesByEnvelopeHash, listMemoriesByGatewayCallId, listMemoriesByModelRunId, } from './memory/provenance-query.js';
|
|
26
26
|
export { type BackfillResult, type ConnectorEventScopeBackfillInput, } from './memory/scope-backfill.js';
|
|
27
27
|
export { getMemoryProvenanceAudit, listMemoryProvenanceAudit, type MemoryProvenanceAuditRecord, type MemoryProvenanceAuditListOptions, } from './memory/provenance-audit.js';
|
|
28
|
-
export { MODEL_RUN_STATUSES, type ModelRunStatus, type BeginModelRunInput, type ModelRunRecord, type AppendToolTraceInput, type ToolTraceRecord, } from './model-runs/types.js';
|
|
28
|
+
export { MODEL_RUN_STATUSES, type ModelRunStatus, type BeginModelRunInput, type ModelRunRecord, type AppendToolTraceInput, type ToolTraceRecord, type ToolTraceScope, type ListToolTracesInput, type ToolTracePage, } from './model-runs/types.js';
|
|
29
29
|
export { beginModelRun, beginModelRunInAdapter, commitModelRun, commitModelRunInAdapter, failModelRun, failModelRunInAdapter, getModelRun, getModelRunInAdapter, } from './model-runs/store.js';
|
|
30
|
-
export { appendToolTrace, listToolTracesForRun } from './model-runs/tool-trace-store.js';
|
|
30
|
+
export { appendToolTrace, listToolTracesForRun, listToolTraces, readToolTrace, } from './model-runs/tool-trace-store.js';
|
|
31
31
|
export { TWIN_EDGE_SOURCES, TWIN_EDGE_TYPES, TWIN_REF_KINDS, type InsertTwinEdgeInput, type ListVisibleTwinEdgesOptions, type TwinEdgeRecord, type TwinEdgeSource, type TwinEdgeType, type TwinRef, type TwinRefKind, type TwinScopeRef, } from './edges/types.js';
|
|
32
32
|
export { getTwinEdge, listTwinEdgesForRefs, mapTwinEdgeRow } from './edges/store.js';
|
|
33
33
|
export { listVisibleTwinEdgesForRefs } from './edges/ref-validation.js';
|
package/dist/index.js
CHANGED
|
@@ -27,9 +27,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
exports.createAuditAck = exports.buildMemoryBootstrap = exports.evolveMemory = exports.ingestWithTrustedProvenance = exports.ingestMemory = exports.buildProfile = exports.recallMemory = exports.promoteMemoryStatus = exports.saveMemoryWithTrustedProvenance = exports.saveMemory = exports.createEmptyRecallBundle = exports.MEMORY_EDGE_TYPES = exports.MEMORY_STATUSES = exports.MEMORY_KINDS = exports.MEMORY_SCOPE_KINDS = exports.mama = exports.DEFAULT_DB_PATH = exports.LEGACY_DB_PATH = exports.DB_DIR = exports.DB_PATH = exports.traverseDecisionChain = exports.SQLiteAdapter = exports.DatabaseAdapter = exports.createAdapter = exports.fts5Search = exports.getDbPath = exports.getPreparedStmt = exports.updateDecisionOutcome = exports.querySemanticEdges = exports.queryDecisionGraph = exports.insertDecisionWithEmbedding = exports.queryVectorSearch = exports.vectorSearch = exports.insertEmbedding = exports.closeDB = exports.getAdapter = exports.getDB = exports.initDB = exports.TIMEOUT_MS = exports.HOST = exports.DEFAULT_PORT = exports.getServerPort = exports.EmbeddingCache = exports.EMBEDDING_PREFIX_SCHEME = exports.MODEL_NAME = exports.EMBEDDING_DIM = exports.embeddingCache = exports.cosineSimilarity = exports.generateEnhancedEmbedding = exports.generateEmbedding = void 0;
|
|
30
|
-
exports.
|
|
31
|
-
exports.
|
|
32
|
-
exports.notifyInsight = exports.FALLBACK_MODEL = exports.DEFAULT_MODEL = exports.listModels = exports.isAvailable = exports.generate = exports.analyzeIntent = exports.RECENT_WINDOW_MS = exports.PARTIAL_INDICATORS = exports.SUCCESS_INDICATORS = exports.FAILURE_INDICATORS = exports.markOutcome = exports.getEvidenceImpact = exports.calculateDurationDays = exports.getRecentDecision = exports.extractFailureReason = exports.matchesPartialIndicators = exports.matchesSuccessIndicators = exports.matchesFailureIndicators = exports.analyzeOutcome = exports.extractCodeExample = exports.extractQuickAnswer = exports.estimateTokens = exports.ensureTokenBudget = void 0;
|
|
30
|
+
exports.getCacheDir = exports.getEmbeddingDim = exports.getModelName = exports.loadConfig = exports.CanonicalizeError = exports.targetRefHash = exports.canonicalizeJSON = exports.listVisibleTwinEdgesForRefs = exports.mapTwinEdgeRow = exports.listTwinEdgesForRefs = exports.getTwinEdge = exports.TWIN_REF_KINDS = exports.TWIN_EDGE_TYPES = exports.TWIN_EDGE_SOURCES = exports.readToolTrace = exports.listToolTraces = exports.listToolTracesForRun = exports.appendToolTrace = exports.getModelRunInAdapter = exports.getModelRun = exports.failModelRunInAdapter = exports.failModelRun = exports.commitModelRunInAdapter = exports.commitModelRun = exports.beginModelRunInAdapter = exports.beginModelRun = exports.MODEL_RUN_STATUSES = exports.listMemoryProvenanceAudit = exports.getMemoryProvenanceAudit = exports.listMemoriesByModelRunId = exports.listMemoriesByGatewayCallId = exports.listMemoriesByEnvelopeHash = exports.getMemoryProvenance = exports.assertTrustedProvenanceCapability = exports.createTrustedProvenanceCapability = exports.listRecentMemoryEvents = exports.listMemoryEventsForMemory = exports.insertMemoryEventInTransaction = exports.appendMemoryEvent = exports.listOpenAuditFindings = exports.createAuditFinding = exports.queryRelevantTruth = exports.parseExtractionResponse = exports.buildExtractionPrompt = exports.getChannelSummary = exports.upsertChannelSummary = exports.setExtractionFn = exports.ingestConversationWithTrustedProvenance = exports.ingestConversation = exports.recordMemoryAudit = void 0;
|
|
31
|
+
exports.formatRecall = exports.formatLegacyContext = exports.formatContext = exports.isMAMAError = exports.wrapError = exports.ErrorCodes = exports.TimeoutError = exports.RateLimitError = exports.LinkError = exports.ConfigurationError = exports.EmbeddingError = exports.DatabaseError = exports.ValidationError = exports.NotFoundError = exports.MAMAError = exports.formatTimeAgo = exports.DebugLogger = exports.error = exports.warn = exports.info = exports.debug = exports.logSearching = exports.logLoading = exports.logError = exports.logFailed = exports.logComplete = exports.logProgress = exports.getTierDescription = exports.checkDatabase = exports.checkEmbeddings = exports.checkSQLite = exports.checkNodeVersion = exports.VALID_EDGE_TYPES = exports.updateConfidence = exports.createEdgesFromReasoning = exports.parseReasoningForRelationships = exports.detectRefinement = exports.calculateCombinedConfidence = exports.markSuperseded = exports.createSupersedesEdge = exports.createEdge = exports.getPreviousDecision = exports.generateDecisionId = exports.learnDecision = exports.formatTopNContext = exports.selectTopDecisions = exports.calculateRelevance = exports.DEFAULT_CONFIG = exports.getConfigPath = exports.updateConfig = void 0;
|
|
32
|
+
exports.notifyInsight = exports.FALLBACK_MODEL = exports.DEFAULT_MODEL = exports.listModels = exports.isAvailable = exports.generate = exports.analyzeIntent = exports.RECENT_WINDOW_MS = exports.PARTIAL_INDICATORS = exports.SUCCESS_INDICATORS = exports.FAILURE_INDICATORS = exports.markOutcome = exports.getEvidenceImpact = exports.calculateDurationDays = exports.getRecentDecision = exports.extractFailureReason = exports.matchesPartialIndicators = exports.matchesSuccessIndicators = exports.matchesFailureIndicators = exports.analyzeOutcome = exports.extractCodeExample = exports.extractQuickAnswer = exports.estimateTokens = exports.ensureTokenBudget = exports.formatTrustContext = exports.formatList = void 0;
|
|
33
33
|
var embeddings_js_1 = require("./embeddings.js");
|
|
34
34
|
Object.defineProperty(exports, "generateEmbedding", { enumerable: true, get: function () { return embeddings_js_1.generateEmbedding; } });
|
|
35
35
|
Object.defineProperty(exports, "generateEnhancedEmbedding", { enumerable: true, get: function () { return embeddings_js_1.generateEnhancedEmbedding; } });
|
|
@@ -133,6 +133,8 @@ Object.defineProperty(exports, "getModelRunInAdapter", { enumerable: true, get:
|
|
|
133
133
|
var tool_trace_store_js_1 = require("./model-runs/tool-trace-store.js");
|
|
134
134
|
Object.defineProperty(exports, "appendToolTrace", { enumerable: true, get: function () { return tool_trace_store_js_1.appendToolTrace; } });
|
|
135
135
|
Object.defineProperty(exports, "listToolTracesForRun", { enumerable: true, get: function () { return tool_trace_store_js_1.listToolTracesForRun; } });
|
|
136
|
+
Object.defineProperty(exports, "listToolTraces", { enumerable: true, get: function () { return tool_trace_store_js_1.listToolTraces; } });
|
|
137
|
+
Object.defineProperty(exports, "readToolTrace", { enumerable: true, get: function () { return tool_trace_store_js_1.readToolTrace; } });
|
|
136
138
|
var types_js_3 = require("./edges/types.js");
|
|
137
139
|
Object.defineProperty(exports, "TWIN_EDGE_SOURCES", { enumerable: true, get: function () { return types_js_3.TWIN_EDGE_SOURCES; } });
|
|
138
140
|
Object.defineProperty(exports, "TWIN_EDGE_TYPES", { enumerable: true, get: function () { return types_js_3.TWIN_EDGE_TYPES; } });
|
package/dist/mama-api.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ import { listMemoryEventsForMemory, listRecentMemoryEvents } from './memory/even
|
|
|
25
25
|
import type { TrustedMemoryWriteOptions } from './memory/provenance.js';
|
|
26
26
|
import { getMemoryProvenance, listMemoriesByEnvelopeHash, listMemoriesByGatewayCallId, listMemoriesByModelRunId } from './memory/provenance-query.js';
|
|
27
27
|
import { beginModelRun, beginModelRunInAdapter, commitModelRun, commitModelRunInAdapter, failModelRun, failModelRunInAdapter, getModelRun, getModelRunInAdapter } from './model-runs/store.js';
|
|
28
|
-
import { appendToolTrace, listToolTracesForRun } from './model-runs/tool-trace-store.js';
|
|
28
|
+
import { appendToolTrace, listToolTracesForRun, listToolTraces, readToolTrace } from './model-runs/tool-trace-store.js';
|
|
29
29
|
import { type SearchHitDiagnostics, type SearchQualityOptions } from './search/search-quality.js';
|
|
30
30
|
/**
|
|
31
31
|
* Parameters for mama.save()
|
|
@@ -1083,6 +1083,8 @@ declare const mama: {
|
|
|
1083
1083
|
getModelRunInAdapter: typeof getModelRunInAdapter;
|
|
1084
1084
|
appendToolTrace: typeof appendToolTrace;
|
|
1085
1085
|
listToolTracesForRun: typeof listToolTracesForRun;
|
|
1086
|
+
listToolTraces: typeof listToolTraces;
|
|
1087
|
+
readToolTrace: typeof readToolTrace;
|
|
1086
1088
|
saveCheckpoint: typeof saveCheckpoint;
|
|
1087
1089
|
loadCheckpoint: typeof loadCheckpoint;
|
|
1088
1090
|
recall: typeof recall;
|
|
@@ -1107,6 +1109,6 @@ declare const mama: {
|
|
|
1107
1109
|
validateCleanupResult: typeof validateCleanupResult;
|
|
1108
1110
|
expandWithGraph: typeof expandWithGraph;
|
|
1109
1111
|
};
|
|
1110
|
-
export { save, saveWithTrustedProvenance, suggest, annotateTopicCurrency, saveMemory, saveMemoryWithTrustedProvenance, recallMemory, listDecisions as list, listCheckpoints, updateOutcome, buildProfile, ingestMemory, ingestWithTrustedProvenance, ingestConversation, ingestConversationWithTrustedProvenance, evolveMemory, buildMemoryBootstrap, createAuditAck, recordMemoryAudit, upsertChannelSummary, getChannelSummary, listOpenAuditFindings, createAuditFinding, getMemoryProvenance, listMemoriesByEnvelopeHash, listMemoriesByGatewayCallId, listMemoriesByModelRunId, listMemoryEventsForMemory, listRecentMemoryEvents, beginModelRun, beginModelRunInAdapter, commitModelRun, commitModelRunInAdapter, failModelRun, failModelRunInAdapter, getModelRun, getModelRunInAdapter, appendToolTrace, listToolTracesForRun, saveCheckpoint, loadCheckpoint, recall, proposeLink, approveLink, rejectLink, getPendingLinks, deprecateAutoLinks, calculateCoverage, calculateQuality, generateQualityReport, logRestartAttempt, calculateRestartSuccessRate, calculateRestartLatency, getRestartMetrics, scanAutoLinks, createLinkBackup, generatePreCleanupReport, restoreLinkBackup, verifyBackupExists, deleteAutoLinks, validateCleanupResult, expandWithGraph, };
|
|
1112
|
+
export { save, saveWithTrustedProvenance, suggest, annotateTopicCurrency, saveMemory, saveMemoryWithTrustedProvenance, recallMemory, listDecisions as list, listCheckpoints, updateOutcome, buildProfile, ingestMemory, ingestWithTrustedProvenance, ingestConversation, ingestConversationWithTrustedProvenance, evolveMemory, buildMemoryBootstrap, createAuditAck, recordMemoryAudit, upsertChannelSummary, getChannelSummary, listOpenAuditFindings, createAuditFinding, getMemoryProvenance, listMemoriesByEnvelopeHash, listMemoriesByGatewayCallId, listMemoriesByModelRunId, listMemoryEventsForMemory, listRecentMemoryEvents, beginModelRun, beginModelRunInAdapter, commitModelRun, commitModelRunInAdapter, failModelRun, failModelRunInAdapter, getModelRun, getModelRunInAdapter, appendToolTrace, listToolTracesForRun, listToolTraces, readToolTrace, saveCheckpoint, loadCheckpoint, recall, proposeLink, approveLink, rejectLink, getPendingLinks, deprecateAutoLinks, calculateCoverage, calculateQuality, generateQualityReport, logRestartAttempt, calculateRestartSuccessRate, calculateRestartLatency, getRestartMetrics, scanAutoLinks, createLinkBackup, generatePreCleanupReport, restoreLinkBackup, verifyBackupExists, deleteAutoLinks, validateCleanupResult, expandWithGraph, };
|
|
1111
1113
|
export default mama;
|
|
1112
1114
|
//# sourceMappingURL=mama-api.d.ts.map
|
package/dist/mama-api.js
CHANGED
|
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.listToolTracesForRun = exports.appendToolTrace = exports.getModelRunInAdapter = exports.getModelRun = exports.failModelRunInAdapter = exports.failModelRun = exports.commitModelRunInAdapter = exports.commitModelRun = exports.beginModelRunInAdapter = exports.beginModelRun = exports.listRecentMemoryEvents = exports.listMemoryEventsForMemory = exports.listMemoriesByModelRunId = exports.listMemoriesByGatewayCallId = exports.listMemoriesByEnvelopeHash = exports.getMemoryProvenance = exports.createAuditFinding = exports.listOpenAuditFindings = exports.getChannelSummary = exports.upsertChannelSummary = exports.recordMemoryAudit = exports.createAuditAck = exports.buildMemoryBootstrap = exports.evolveMemory = exports.ingestConversationWithTrustedProvenance = exports.ingestConversation = exports.ingestWithTrustedProvenance = exports.ingestMemory = exports.buildProfile = exports.recallMemory = exports.saveMemoryWithTrustedProvenance = exports.saveMemory = void 0;
|
|
25
|
+
exports.readToolTrace = exports.listToolTraces = exports.listToolTracesForRun = exports.appendToolTrace = exports.getModelRunInAdapter = exports.getModelRun = exports.failModelRunInAdapter = exports.failModelRun = exports.commitModelRunInAdapter = exports.commitModelRun = exports.beginModelRunInAdapter = exports.beginModelRun = exports.listRecentMemoryEvents = exports.listMemoryEventsForMemory = exports.listMemoriesByModelRunId = exports.listMemoriesByGatewayCallId = exports.listMemoriesByEnvelopeHash = exports.getMemoryProvenance = exports.createAuditFinding = exports.listOpenAuditFindings = exports.getChannelSummary = exports.upsertChannelSummary = exports.recordMemoryAudit = exports.createAuditAck = exports.buildMemoryBootstrap = exports.evolveMemory = exports.ingestConversationWithTrustedProvenance = exports.ingestConversation = exports.ingestWithTrustedProvenance = exports.ingestMemory = exports.buildProfile = exports.recallMemory = exports.saveMemoryWithTrustedProvenance = exports.saveMemory = void 0;
|
|
26
26
|
exports.save = save;
|
|
27
27
|
exports.saveWithTrustedProvenance = saveWithTrustedProvenance;
|
|
28
28
|
exports.suggest = suggest;
|
|
@@ -106,6 +106,8 @@ Object.defineProperty(exports, "getModelRunInAdapter", { enumerable: true, get:
|
|
|
106
106
|
const tool_trace_store_js_1 = require("./model-runs/tool-trace-store.js");
|
|
107
107
|
Object.defineProperty(exports, "appendToolTrace", { enumerable: true, get: function () { return tool_trace_store_js_1.appendToolTrace; } });
|
|
108
108
|
Object.defineProperty(exports, "listToolTracesForRun", { enumerable: true, get: function () { return tool_trace_store_js_1.listToolTracesForRun; } });
|
|
109
|
+
Object.defineProperty(exports, "listToolTraces", { enumerable: true, get: function () { return tool_trace_store_js_1.listToolTraces; } });
|
|
110
|
+
Object.defineProperty(exports, "readToolTrace", { enumerable: true, get: function () { return tool_trace_store_js_1.readToolTrace; } });
|
|
109
111
|
const search_rollup_js_1 = require("./cases/search-rollup.js");
|
|
110
112
|
const ranker_rescore_js_1 = require("./search/ranker-rescore.js");
|
|
111
113
|
const ranker_features_js_1 = require("./search/ranker-features.js");
|
|
@@ -2832,6 +2834,8 @@ const mama = {
|
|
|
2832
2834
|
getModelRunInAdapter: store_js_1.getModelRunInAdapter,
|
|
2833
2835
|
appendToolTrace: tool_trace_store_js_1.appendToolTrace,
|
|
2834
2836
|
listToolTracesForRun: tool_trace_store_js_1.listToolTracesForRun,
|
|
2837
|
+
listToolTraces: tool_trace_store_js_1.listToolTraces,
|
|
2838
|
+
readToolTrace: tool_trace_store_js_1.readToolTrace,
|
|
2835
2839
|
saveCheckpoint,
|
|
2836
2840
|
loadCheckpoint,
|
|
2837
2841
|
// Legacy functions (retained for internal use, not exposed via MCP)
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type { AppendToolTraceInput, ToolTraceRecord } from './types.js';
|
|
1
|
+
import type { AppendToolTraceInput, ToolTraceRecord, ToolTraceScope, ListToolTracesInput, ToolTracePage } from './types.js';
|
|
2
2
|
export declare function appendToolTrace(input: AppendToolTraceInput): Promise<ToolTraceRecord>;
|
|
3
3
|
export declare function listToolTracesForRun(modelRunId: string): Promise<ToolTraceRecord[]>;
|
|
4
|
+
/** Access is exact host-derived scope; knowing a trace ID never grants access. */
|
|
5
|
+
export declare function readToolTrace(traceId: string, scope: ToolTraceScope): Promise<ToolTraceRecord | null>;
|
|
6
|
+
/** Bounded metadata discovery; detailed evidence is read explicitly by trace ID. */
|
|
7
|
+
export declare function listToolTraces(input: ListToolTracesInput): Promise<ToolTracePage>;
|
|
4
8
|
//# sourceMappingURL=tool-trace-store.d.ts.map
|
|
@@ -5,6 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.appendToolTrace = appendToolTrace;
|
|
7
7
|
exports.listToolTracesForRun = listToolTracesForRun;
|
|
8
|
+
exports.readToolTrace = readToolTrace;
|
|
9
|
+
exports.listToolTraces = listToolTraces;
|
|
8
10
|
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
9
11
|
const db_manager_js_1 = require("../db-manager.js");
|
|
10
12
|
function traceId() {
|
|
@@ -47,8 +49,33 @@ function requiredNonNegativeInteger(value, field) {
|
|
|
47
49
|
}
|
|
48
50
|
return normalized;
|
|
49
51
|
}
|
|
52
|
+
function nullableJsonObject(value, field) {
|
|
53
|
+
if (value === undefined || value === null) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
if (typeof value !== 'string') {
|
|
57
|
+
throw new Error(`tool_traces.${field} must be a JSON object string`);
|
|
58
|
+
}
|
|
59
|
+
let parsed;
|
|
60
|
+
try {
|
|
61
|
+
parsed = JSON.parse(value);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
throw new Error(`tool_traces.${field} contains malformed JSON`);
|
|
65
|
+
}
|
|
66
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
67
|
+
throw new Error(`tool_traces.${field} must contain a JSON object`);
|
|
68
|
+
}
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
50
71
|
function mapToolTraceRow(row) {
|
|
51
72
|
return {
|
|
73
|
+
diagnostic_json: nullableJsonObject(row.diagnostic_json, 'diagnostic_json'),
|
|
74
|
+
evidence_json: nullableJsonObject(row.evidence_json, 'evidence_json'),
|
|
75
|
+
catalog_revision: nullableString(row.catalog_revision),
|
|
76
|
+
owner_scope: nullableString(row.owner_scope),
|
|
77
|
+
project_id: nullableString(row.project_id),
|
|
78
|
+
channel_id: nullableString(row.channel_id),
|
|
52
79
|
trace_id: requiredString(row.trace_id, 'trace_id'),
|
|
53
80
|
model_run_id: requiredString(row.model_run_id, 'model_run_id'),
|
|
54
81
|
gateway_call_id: nullableString(row.gateway_call_id),
|
|
@@ -72,7 +99,7 @@ function selectToolTrace(adapter, id) {
|
|
|
72
99
|
SELECT
|
|
73
100
|
trace_id, model_run_id, gateway_call_id, tool_name, input_summary,
|
|
74
101
|
output_summary, execution_status, duration_ms, envelope_hash, failure_code,
|
|
75
|
-
created_at
|
|
102
|
+
created_at, diagnostic_json, evidence_json, catalog_revision, owner_scope, project_id, channel_id
|
|
76
103
|
FROM tool_traces
|
|
77
104
|
WHERE trace_id = ?
|
|
78
105
|
`)
|
|
@@ -92,11 +119,11 @@ async function appendToolTrace(input) {
|
|
|
92
119
|
INSERT INTO tool_traces (
|
|
93
120
|
trace_id, model_run_id, gateway_call_id, tool_name, input_summary,
|
|
94
121
|
output_summary, execution_status, duration_ms, envelope_hash, failure_code,
|
|
95
|
-
created_at
|
|
122
|
+
created_at, diagnostic_json, evidence_json, catalog_revision, owner_scope, project_id, channel_id
|
|
96
123
|
)
|
|
97
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
124
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
98
125
|
`)
|
|
99
|
-
.run(id, modelRunId, nullableString(input.gateway_call_id), toolName, nullableString(input.input_summary), nullableString(input.output_summary), nullableString(input.execution_status), normalizeDuration(input.duration_ms), nullableString(input.envelope_hash), nullableString(input.failure_code), normalizeTimestamp(input.created_at));
|
|
126
|
+
.run(id, modelRunId, nullableString(input.gateway_call_id), toolName, nullableString(input.input_summary), nullableString(input.output_summary), nullableString(input.execution_status), normalizeDuration(input.duration_ms), nullableString(input.envelope_hash), nullableString(input.failure_code), normalizeTimestamp(input.created_at), nullableJsonObject(input.diagnostic_json, 'diagnostic_json'), nullableJsonObject(input.evidence_json, 'evidence_json'), nullableString(input.catalog_revision), nullableString(input.owner_scope), nullableString(input.project_id), nullableString(input.channel_id));
|
|
100
127
|
return selectToolTrace(adapter, id);
|
|
101
128
|
}
|
|
102
129
|
async function listToolTracesForRun(modelRunId) {
|
|
@@ -107,7 +134,7 @@ async function listToolTracesForRun(modelRunId) {
|
|
|
107
134
|
SELECT
|
|
108
135
|
trace_id, model_run_id, gateway_call_id, tool_name, input_summary,
|
|
109
136
|
output_summary, execution_status, duration_ms, envelope_hash, failure_code,
|
|
110
|
-
created_at
|
|
137
|
+
created_at, diagnostic_json, evidence_json, catalog_revision, owner_scope, project_id, channel_id
|
|
111
138
|
FROM tool_traces
|
|
112
139
|
WHERE model_run_id = ?
|
|
113
140
|
ORDER BY created_at DESC, rowid DESC
|
|
@@ -115,4 +142,82 @@ async function listToolTracesForRun(modelRunId) {
|
|
|
115
142
|
.all(id);
|
|
116
143
|
return rows.map(mapToolTraceRow);
|
|
117
144
|
}
|
|
145
|
+
function scopedWhere(scope) {
|
|
146
|
+
const clauses = ['owner_scope = ?', 'project_id = ?'];
|
|
147
|
+
const values = [
|
|
148
|
+
requiredString(scope.owner_scope, 'owner_scope'),
|
|
149
|
+
requiredString(scope.project_id, 'project_id'),
|
|
150
|
+
];
|
|
151
|
+
if (scope.channel_id !== undefined) {
|
|
152
|
+
clauses.push('channel_id = ?');
|
|
153
|
+
values.push(requiredString(scope.channel_id, 'channel_id'));
|
|
154
|
+
}
|
|
155
|
+
return { clauses, values };
|
|
156
|
+
}
|
|
157
|
+
/** Access is exact host-derived scope; knowing a trace ID never grants access. */
|
|
158
|
+
async function readToolTrace(traceId, scope) {
|
|
159
|
+
const { clauses, values } = scopedWhere(scope);
|
|
160
|
+
clauses.push('trace_id = ?');
|
|
161
|
+
values.push(requiredString(traceId, 'trace_id'));
|
|
162
|
+
const adapter = await initializedAdapter();
|
|
163
|
+
const row = adapter
|
|
164
|
+
.prepare(`SELECT * FROM tool_traces WHERE ${clauses.join(' AND ')}`)
|
|
165
|
+
.get(...values);
|
|
166
|
+
return row ? mapToolTraceRow(row) : null;
|
|
167
|
+
}
|
|
168
|
+
/** Bounded metadata discovery; detailed evidence is read explicitly by trace ID. */
|
|
169
|
+
async function listToolTraces(input) {
|
|
170
|
+
const { clauses, values } = scopedWhere(input);
|
|
171
|
+
if (input.evidence_only !== undefined && typeof input.evidence_only !== 'boolean') {
|
|
172
|
+
throw new Error('tool_traces.evidence_only must be a boolean');
|
|
173
|
+
}
|
|
174
|
+
if (input.evidence_only === true) {
|
|
175
|
+
clauses.push('evidence_json IS NOT NULL');
|
|
176
|
+
}
|
|
177
|
+
const limit = input.limit ?? 20;
|
|
178
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
|
|
179
|
+
throw new Error('tool_traces.limit must be an integer between 1 and 100');
|
|
180
|
+
}
|
|
181
|
+
for (const field of ['model_run_id', 'tool_name']) {
|
|
182
|
+
if (input[field] !== undefined) {
|
|
183
|
+
clauses.push(`${field} = ?`);
|
|
184
|
+
values.push(requiredString(input[field], field));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (input.cursor !== undefined) {
|
|
188
|
+
let cursor;
|
|
189
|
+
try {
|
|
190
|
+
cursor = JSON.parse(Buffer.from(input.cursor, 'base64url').toString('utf8'));
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
throw new Error('tool_traces.cursor is malformed');
|
|
194
|
+
}
|
|
195
|
+
if (!Array.isArray(cursor) || cursor.length !== 2) {
|
|
196
|
+
throw new Error('tool_traces.cursor is malformed');
|
|
197
|
+
}
|
|
198
|
+
const [cursorCreatedAt, cursorTraceId] = cursor;
|
|
199
|
+
if (typeof cursorCreatedAt !== 'number' ||
|
|
200
|
+
!Number.isSafeInteger(cursorCreatedAt) ||
|
|
201
|
+
typeof cursorTraceId !== 'string' ||
|
|
202
|
+
cursorTraceId.length === 0) {
|
|
203
|
+
throw new Error('tool_traces.cursor is malformed');
|
|
204
|
+
}
|
|
205
|
+
clauses.push('(created_at < ? OR (created_at = ? AND trace_id < ?))');
|
|
206
|
+
values.push(cursorCreatedAt, cursorCreatedAt, cursorTraceId);
|
|
207
|
+
}
|
|
208
|
+
const adapter = await initializedAdapter();
|
|
209
|
+
const rows = adapter
|
|
210
|
+
.prepare(`SELECT trace_id, model_run_id, gateway_call_id, tool_name,
|
|
211
|
+
input_summary, output_summary, execution_status, duration_ms, envelope_hash, failure_code,
|
|
212
|
+
created_at, diagnostic_json, NULL AS evidence_json, catalog_revision, owner_scope, project_id, channel_id
|
|
213
|
+
FROM tool_traces WHERE ${clauses.join(' AND ')}
|
|
214
|
+
ORDER BY created_at DESC, trace_id DESC LIMIT ?`)
|
|
215
|
+
.all(...values, limit + 1);
|
|
216
|
+
const traces = rows.slice(0, limit).map(mapToolTraceRow);
|
|
217
|
+
const last = traces.at(-1);
|
|
218
|
+
const next_cursor = rows.length > limit && last
|
|
219
|
+
? Buffer.from(JSON.stringify([last.created_at, last.trace_id])).toString('base64url')
|
|
220
|
+
: null;
|
|
221
|
+
return { traces, next_cursor };
|
|
222
|
+
}
|
|
118
223
|
//# sourceMappingURL=tool-trace-store.js.map
|
|
@@ -43,6 +43,13 @@ export interface ModelRunRecord {
|
|
|
43
43
|
completed_at: number | null;
|
|
44
44
|
}
|
|
45
45
|
export interface AppendToolTraceInput {
|
|
46
|
+
/** Host-derived access scope; legacy rows remain unscoped. */
|
|
47
|
+
owner_scope?: string | null;
|
|
48
|
+
project_id?: string | null;
|
|
49
|
+
channel_id?: string | null;
|
|
50
|
+
diagnostic_json?: string | null;
|
|
51
|
+
evidence_json?: string | null;
|
|
52
|
+
catalog_revision?: string | null;
|
|
46
53
|
trace_id?: string;
|
|
47
54
|
model_run_id: string;
|
|
48
55
|
gateway_call_id?: string | null;
|
|
@@ -57,6 +64,13 @@ export interface AppendToolTraceInput {
|
|
|
57
64
|
created_at?: number;
|
|
58
65
|
}
|
|
59
66
|
export interface ToolTraceRecord {
|
|
67
|
+
/** Host-derived access scope; legacy rows remain unscoped. */
|
|
68
|
+
owner_scope?: string | null;
|
|
69
|
+
project_id?: string | null;
|
|
70
|
+
channel_id?: string | null;
|
|
71
|
+
diagnostic_json?: string | null;
|
|
72
|
+
evidence_json?: string | null;
|
|
73
|
+
catalog_revision?: string | null;
|
|
60
74
|
trace_id: string;
|
|
61
75
|
model_run_id: string;
|
|
62
76
|
gateway_call_id: string | null;
|
|
@@ -69,4 +83,21 @@ export interface ToolTraceRecord {
|
|
|
69
83
|
failure_code: string | null;
|
|
70
84
|
created_at: number;
|
|
71
85
|
}
|
|
86
|
+
export interface ToolTraceScope {
|
|
87
|
+
owner_scope: string;
|
|
88
|
+
project_id: string;
|
|
89
|
+
channel_id?: string;
|
|
90
|
+
}
|
|
91
|
+
export interface ListToolTracesInput extends ToolTraceScope {
|
|
92
|
+
evidence_only?: boolean;
|
|
93
|
+
model_run_id?: string;
|
|
94
|
+
tool_name?: string;
|
|
95
|
+
cursor?: string;
|
|
96
|
+
limit?: number;
|
|
97
|
+
}
|
|
98
|
+
export interface ToolTracePage {
|
|
99
|
+
/** Metadata only: evidence_json is null. Read a scoped trace for details. */
|
|
100
|
+
traces: ToolTraceRecord[];
|
|
101
|
+
next_cursor: string | null;
|
|
102
|
+
}
|
|
72
103
|
//# sourceMappingURL=types.d.ts.map
|