@rohirik/openltm-core 2.8.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/README.md +67 -0
- package/assets/opencode/agents/aegis.md +211 -0
- package/assets/opencode/plugins/aegis.ts +3 -0
- package/assets/opencode/skills/AgentTrustBoundaries/ContextCrushDefense.md +104 -0
- package/assets/opencode/skills/AgentTrustBoundaries/SKILL.md +31 -0
- package/assets/opencode/skills/AgentTrustBoundaries/TrustBoundaryPatterns.md +114 -0
- package/assets/opencode/skills/AgentTrustBoundaries/Workflows/DefendContextCrush.md +27 -0
- package/assets/opencode/skills/AgentTrustBoundaries/Workflows/HandleUntrustedContent.md +27 -0
- package/assets/opencode/skills/CommandPathSafety/CommandInjectionPatterns.md +95 -0
- package/assets/opencode/skills/CommandPathSafety/PathTraversalAndInstallerSafety.md +106 -0
- package/assets/opencode/skills/CommandPathSafety/SKILL.md +31 -0
- package/assets/opencode/skills/CommandPathSafety/Workflows/EnforcePathBoundaries.md +27 -0
- package/assets/opencode/skills/CommandPathSafety/Workflows/HardenCommandExecution.md +27 -0
- package/assets/opencode/skills/SecretSafeHandling/CloudCredentialPatterns.md +106 -0
- package/assets/opencode/skills/SecretSafeHandling/SKILL.md +31 -0
- package/assets/opencode/skills/SecretSafeHandling/SecretHandlingPlaybook.md +102 -0
- package/assets/opencode/skills/SecretSafeHandling/Workflows/DesignSecretSafeFlow.md +27 -0
- package/assets/opencode/skills/SecretSafeHandling/Workflows/RemoveSecretExposure.md +27 -0
- package/package.json +41 -0
- package/src/__tests__/cli/claude.test.ts +122 -0
- package/src/__tests__/cli/detect.test.ts +91 -0
- package/src/__tests__/cli/install.test.ts +161 -0
- package/src/__tests__/cli/opencode.test.ts +169 -0
- package/src/__tests__/cli/pi.test.ts +113 -0
- package/src/__tests__/cli.test.ts +70 -0
- package/src/__tests__/events/crossProcess.test.ts +82 -0
- package/src/__tests__/events/index.test.ts +32 -0
- package/src/__tests__/extensions.test.ts +81 -0
- package/src/__tests__/migrations/retention.test.ts +118 -0
- package/src/__tests__/queue/index.test.ts +61 -0
- package/src/__tests__/scheduler/index.test.ts +39 -0
- package/src/__tests__/vec/index.test.ts +130 -0
- package/src/__tests__/vec/parity.test.ts +70 -0
- package/src/adapterTypes.ts +23 -0
- package/src/cli/_shared.ts +120 -0
- package/src/cli/bin.ts +97 -0
- package/src/cli/claude.ts +124 -0
- package/src/cli/detect.ts +55 -0
- package/src/cli/hook.ts +25 -0
- package/src/cli/index.ts +22 -0
- package/src/cli/install.ts +185 -0
- package/src/cli/opencode.ts +193 -0
- package/src/cli/pi.ts +74 -0
- package/src/cli/types.ts +78 -0
- package/src/config.ts +163 -0
- package/src/context.ts +172 -0
- package/src/dao/conflicts.ts +26 -0
- package/src/dao/contextItems.ts +70 -0
- package/src/dao/embeddings.ts +78 -0
- package/src/dao/index.ts +9 -0
- package/src/dao/provenanceAudit.ts +108 -0
- package/src/dao/types.ts +142 -0
- package/src/db.ts +780 -0
- package/src/dedup.ts +12 -0
- package/src/embeddings.ts +386 -0
- package/src/events/index.ts +130 -0
- package/src/extensions.ts +140 -0
- package/src/graph.ts +268 -0
- package/src/index.ts +95 -0
- package/src/janitor/archive.ts +66 -0
- package/src/janitor/decay.ts +60 -0
- package/src/janitor/dedup.ts +333 -0
- package/src/janitor/embeddings.ts +209 -0
- package/src/janitor/index.ts +215 -0
- package/src/janitor/promote.ts +188 -0
- package/src/janitor/providers/anthropic.ts +91 -0
- package/src/janitor/providers/cohere.ts +135 -0
- package/src/janitor/providers/gemini.ts +156 -0
- package/src/janitor/providers/ollama.ts +177 -0
- package/src/janitor/providers/openai.ts +121 -0
- package/src/janitor/providers/openrouter.ts +182 -0
- package/src/janitor/providers/types.ts +154 -0
- package/src/janitor/providers/utils.ts +35 -0
- package/src/janitor/supersedes.ts +199 -0
- package/src/lib/honker.ts +54 -0
- package/src/lib/honkerTypes.ts +109 -0
- package/src/lib/jsonlLogger.ts +92 -0
- package/src/lib/writeQueue.ts +28 -0
- package/src/migrations.ts +415 -0
- package/src/paths.ts +22 -0
- package/src/proposals.ts +120 -0
- package/src/providers/disabled.ts +19 -0
- package/src/providers/embeddingProvider.ts +49 -0
- package/src/providers/gemini.ts +37 -0
- package/src/providers/index.ts +2 -0
- package/src/providers/ollama.ts +43 -0
- package/src/providers/openai.ts +35 -0
- package/src/queue/index.ts +53 -0
- package/src/queue/worker.ts +77 -0
- package/src/recall/categorise.ts +139 -0
- package/src/recall/explainer.ts +76 -0
- package/src/scheduler/index.ts +97 -0
- package/src/schema.sql +191 -0
- package/src/secretsScrubber.ts +105 -0
- package/src/shared-db.ts +158 -0
- package/src/vec/index.ts +161 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dao/conflicts.ts — DAO for querying superseded-memory conflicts.
|
|
3
|
+
*/
|
|
4
|
+
import type { Database } from "bun:sqlite";
|
|
5
|
+
import type { ConflictRow } from "./types.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Return memories superseded within the last 7 days for a given project.
|
|
9
|
+
* Used by SessionStart to surface recent conflicts in the session header.
|
|
10
|
+
*/
|
|
11
|
+
export function getRecentConflicts(
|
|
12
|
+
db: Database,
|
|
13
|
+
project: string,
|
|
14
|
+
limit: number,
|
|
15
|
+
): ConflictRow[] {
|
|
16
|
+
return db.query<ConflictRow, [string, string, number]>(
|
|
17
|
+
`SELECT m1.id as olderId, m1.content as olderContent,
|
|
18
|
+
m2.id as newerId, m2.content as newerContent
|
|
19
|
+
FROM memories m1
|
|
20
|
+
JOIN memories m2 ON m1.superseded_by = m2.id
|
|
21
|
+
WHERE (m1.project_scope = ? OR (m1.project_scope IS NULL AND ? IS NULL))
|
|
22
|
+
AND m1.superseded_at > datetime('now', '-7 days')
|
|
23
|
+
ORDER BY m1.superseded_at DESC
|
|
24
|
+
LIMIT ?`
|
|
25
|
+
).all(project, project, limit);
|
|
26
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dao/contextItems.ts — DAO for context_items table.
|
|
3
|
+
* Hooks use these functions instead of raw SQL.
|
|
4
|
+
*/
|
|
5
|
+
import { getDb } from "../shared-db.js";
|
|
6
|
+
import { writeQueue } from "../lib/writeQueue.js";
|
|
7
|
+
import type { ContextItemRow, ContextItemType } from "./types.js";
|
|
8
|
+
|
|
9
|
+
export function listByProject(project: string, type?: ContextItemType): ContextItemRow[] {
|
|
10
|
+
const db = getDb();
|
|
11
|
+
if (type) {
|
|
12
|
+
return db.query<ContextItemRow, [string, string]>(
|
|
13
|
+
`SELECT id, project_name, type, content, session_id, permanent, memory_id, status, created_at
|
|
14
|
+
FROM context_items WHERE project_name=? AND type=? AND status='active' ORDER BY created_at ASC`
|
|
15
|
+
).all(project, type);
|
|
16
|
+
}
|
|
17
|
+
return db.query<ContextItemRow, [string]>(
|
|
18
|
+
`SELECT id, project_name, type, content, session_id, permanent, memory_id, status, created_at
|
|
19
|
+
FROM context_items WHERE project_name=? AND status='active' ORDER BY type, created_at ASC`
|
|
20
|
+
).all(project);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function upsertGoal(project: string, content: string): void {
|
|
24
|
+
writeQueue.enqueue(() => {
|
|
25
|
+
const db = getDb();
|
|
26
|
+
db.transaction(() => {
|
|
27
|
+
db.run(`DELETE FROM context_items WHERE project_name=? AND type='goal'`, [project]);
|
|
28
|
+
db.run(
|
|
29
|
+
`INSERT INTO context_items (project_name, type, content, permanent) VALUES (?, 'goal', ?, 0)`,
|
|
30
|
+
[project, content]
|
|
31
|
+
);
|
|
32
|
+
})();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function appendProgress(project: string, content: string, sessionId?: string): void {
|
|
37
|
+
writeQueue.enqueue(() => {
|
|
38
|
+
const db = getDb();
|
|
39
|
+
// Trim to 20 most recent progress entries
|
|
40
|
+
const existing = db.query<{ id: number }, [string]>(
|
|
41
|
+
`SELECT id FROM context_items WHERE project_name=? AND type='progress' ORDER BY created_at DESC`
|
|
42
|
+
).all(project);
|
|
43
|
+
if (existing.length >= 20) {
|
|
44
|
+
const toDelete = existing.slice(19).map(r => r.id);
|
|
45
|
+
const placeholders = toDelete.map(() => "?").join(",");
|
|
46
|
+
db.run(`DELETE FROM context_items WHERE id IN (${placeholders})`, toDelete);
|
|
47
|
+
}
|
|
48
|
+
db.run(
|
|
49
|
+
`INSERT INTO context_items (project_name, type, content, session_id, permanent) VALUES (?, 'progress', ?, ?, 0)`,
|
|
50
|
+
[project, content, sessionId ?? null]
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function insertPermanent(project: string, type: ContextItemType, content: string): void {
|
|
56
|
+
writeQueue.enqueue(() => {
|
|
57
|
+
getDb().run(
|
|
58
|
+
`INSERT INTO context_items (project_name, type, content, permanent) VALUES (?, ?, ?, 1)`,
|
|
59
|
+
[project, type, content]
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function addDecision(project: string, content: string): void {
|
|
65
|
+
insertPermanent(project, "decision", content);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function addGotcha(project: string, content: string): void {
|
|
69
|
+
insertPermanent(project, "gotcha", content);
|
|
70
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dao/embeddings.ts — DAO for the memory_embeddings side table.
|
|
3
|
+
* All reads are synchronous; writes are serialised through writeQueue.
|
|
4
|
+
*/
|
|
5
|
+
import type { Database } from "bun:sqlite";
|
|
6
|
+
import { writeQueue } from "../lib/writeQueue.js";
|
|
7
|
+
import { getCapabilities } from "../extensions.js";
|
|
8
|
+
import { ensureVecTable, upsertVec, deleteVec } from "../vec/index.js";
|
|
9
|
+
|
|
10
|
+
interface EmbeddingRow {
|
|
11
|
+
memory_id: number;
|
|
12
|
+
embedding: Buffer;
|
|
13
|
+
model: string;
|
|
14
|
+
dim: number;
|
|
15
|
+
created_at: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Return the stored embedding blob for a memory, or null if none exists. */
|
|
19
|
+
export function getEmbedding(db: Database, memoryId: number): Buffer | null {
|
|
20
|
+
const row = db.query<{ embedding: Buffer }, [number]>(
|
|
21
|
+
`SELECT embedding FROM memory_embeddings WHERE memory_id=?`
|
|
22
|
+
).get(memoryId);
|
|
23
|
+
return row?.embedding ?? null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Upsert an embedding for a memory. Serialised through the write queue. */
|
|
27
|
+
export function setEmbedding(
|
|
28
|
+
db: Database,
|
|
29
|
+
memoryId: number,
|
|
30
|
+
blob: Buffer,
|
|
31
|
+
model: string,
|
|
32
|
+
dim: number,
|
|
33
|
+
): Promise<void> {
|
|
34
|
+
return writeQueue.enqueue(() => {
|
|
35
|
+
db.run(
|
|
36
|
+
`INSERT INTO memory_embeddings (memory_id, embedding, model, dim, created_at)
|
|
37
|
+
VALUES (?, ?, ?, ?, datetime('now'))
|
|
38
|
+
ON CONFLICT(memory_id) DO UPDATE SET
|
|
39
|
+
embedding=excluded.embedding,
|
|
40
|
+
model=excluded.model,
|
|
41
|
+
dim=excluded.dim,
|
|
42
|
+
created_at=excluded.created_at`,
|
|
43
|
+
[memoryId, blob, model, dim],
|
|
44
|
+
);
|
|
45
|
+
// Dual-write to the vec0 ANN index when available. The index table is
|
|
46
|
+
// dimension-fixed; a blob whose dim differs from the active index no-ops
|
|
47
|
+
// gracefully (a provider/model switch is reconciled via rebuildVecIndex).
|
|
48
|
+
if (getCapabilities().vec) {
|
|
49
|
+
ensureVecTable(db, dim);
|
|
50
|
+
upsertVec(db, memoryId, blob);
|
|
51
|
+
}
|
|
52
|
+
}, db);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Remove the embedding for a memory. Serialised through the write queue. */
|
|
56
|
+
export function deleteEmbedding(db: Database, memoryId: number): Promise<void> {
|
|
57
|
+
return writeQueue.enqueue(() => {
|
|
58
|
+
db.run(`DELETE FROM memory_embeddings WHERE memory_id=?`, [memoryId]);
|
|
59
|
+
if (getCapabilities().vec) deleteVec(db, memoryId);
|
|
60
|
+
}, db);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Return memory IDs that have no entry in memory_embeddings.
|
|
65
|
+
* Used by the janitor backfill job and SessionStart hint.
|
|
66
|
+
*/
|
|
67
|
+
export function listMemoryIdsMissingEmbedding(db: Database, limit = 100): number[] {
|
|
68
|
+
const rows = db.query<{ id: number }, [number]>(
|
|
69
|
+
`SELECT m.id FROM memories m
|
|
70
|
+
LEFT JOIN memory_embeddings e ON e.memory_id = m.id
|
|
71
|
+
WHERE m.status = 'active' AND e.memory_id IS NULL
|
|
72
|
+
ORDER BY m.importance DESC, m.created_at DESC
|
|
73
|
+
LIMIT ?`
|
|
74
|
+
).all(limit);
|
|
75
|
+
return rows.map(r => r.id);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type { EmbeddingRow };
|
package/src/dao/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dao/index.ts — Single import surface for the DAO layer.
|
|
3
|
+
* Hooks and MCP tools import from here, never from db.ts directly for context_items.
|
|
4
|
+
* Memories are still accessed via src/db.ts (learn, recall, relate, forget).
|
|
5
|
+
*/
|
|
6
|
+
export * from "./types.js";
|
|
7
|
+
export * from "./contextItems.js";
|
|
8
|
+
export * from "./provenanceAudit.js";
|
|
9
|
+
export * from "./embeddings.js";
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dao/provenanceAudit.ts — DAO for memory_provenance and memory_audit tables.
|
|
3
|
+
* All writes to memories go through here for uniform audit coverage.
|
|
4
|
+
*
|
|
5
|
+
* Note: memory_audit.memory_id is intentionally NOT a FK — audit rows survive
|
|
6
|
+
* memory deletion. Do not add a FK constraint.
|
|
7
|
+
*/
|
|
8
|
+
import type { Database } from "bun:sqlite";
|
|
9
|
+
import type {
|
|
10
|
+
ProvenanceRow, ProvenanceInput,
|
|
11
|
+
AuditRow, AuditInput,
|
|
12
|
+
MemorySnapshot,
|
|
13
|
+
} from "./types.js";
|
|
14
|
+
|
|
15
|
+
/** Capture a slim memory snapshot (no embedding blob) for audit before/after JSON. */
|
|
16
|
+
export function snapshotMemory(db: Database, memoryId: number): MemorySnapshot | null {
|
|
17
|
+
return db.query<MemorySnapshot, [number]>(
|
|
18
|
+
`SELECT id, content, category, importance, confidence, source, project_scope, dedup_key,
|
|
19
|
+
created_at, last_confirmed_at, last_used_at, confirm_count, status,
|
|
20
|
+
first_recalled_at, last_recalled_at, recall_count, superseded_by, superseded_at,
|
|
21
|
+
workspace_id, agent_id, created_by
|
|
22
|
+
FROM memories WHERE id=?`
|
|
23
|
+
).get(memoryId) ?? null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Insert a provenance row. Returns the new row id. */
|
|
27
|
+
export function insertProvenance(db: Database, input: ProvenanceInput): number {
|
|
28
|
+
const result = db.run(
|
|
29
|
+
`INSERT INTO memory_provenance (memory_id, source_type, source_ref, actor, metadata)
|
|
30
|
+
VALUES (?, ?, ?, ?, ?)`,
|
|
31
|
+
[input.memory_id, input.source_type, input.source_ref ?? null, input.actor ?? null, input.metadata ?? null]
|
|
32
|
+
);
|
|
33
|
+
return Number(result.lastInsertRowid);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Insert an audit row. Returns the new row id. */
|
|
37
|
+
export function insertAudit(db: Database, input: AuditInput): number {
|
|
38
|
+
const result = db.run(
|
|
39
|
+
`INSERT INTO memory_audit (memory_id, op, actor, session_id, before_json, after_json)
|
|
40
|
+
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
41
|
+
[
|
|
42
|
+
input.memory_id,
|
|
43
|
+
input.op,
|
|
44
|
+
input.actor,
|
|
45
|
+
input.session_id ?? null,
|
|
46
|
+
input.before_json ?? null,
|
|
47
|
+
input.after_json ?? null,
|
|
48
|
+
]
|
|
49
|
+
);
|
|
50
|
+
return Number(result.lastInsertRowid);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** List all provenance rows for a memory, newest first. */
|
|
54
|
+
export function listProvenance(db: Database, memoryId: number): ProvenanceRow[] {
|
|
55
|
+
return db.query<ProvenanceRow, [number]>(
|
|
56
|
+
`SELECT id, memory_id, source_type, source_ref, actor, created_at, metadata
|
|
57
|
+
FROM memory_provenance WHERE memory_id=? ORDER BY created_at DESC, id DESC`
|
|
58
|
+
).all(memoryId);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface QueryAuditOpts {
|
|
62
|
+
memoryId?: number;
|
|
63
|
+
op?: string;
|
|
64
|
+
sessionId?: string;
|
|
65
|
+
since?: string;
|
|
66
|
+
limit?: number;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Query audit rows with optional filters. Results are ordered newest first. */
|
|
70
|
+
export function queryAudit(db: Database, opts: QueryAuditOpts = {}): AuditRow[] {
|
|
71
|
+
const conditions: string[] = [];
|
|
72
|
+
const params: (number | string)[] = [];
|
|
73
|
+
|
|
74
|
+
if (opts.memoryId !== undefined) { conditions.push("memory_id=?"); params.push(opts.memoryId); }
|
|
75
|
+
if (opts.op) { conditions.push("op=?"); params.push(opts.op); }
|
|
76
|
+
if (opts.sessionId) { conditions.push("session_id=?"); params.push(opts.sessionId); }
|
|
77
|
+
if (opts.since) { conditions.push("created_at>=?");params.push(opts.since); }
|
|
78
|
+
|
|
79
|
+
const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
80
|
+
const limit = opts.limit ?? 50;
|
|
81
|
+
|
|
82
|
+
params.push(limit);
|
|
83
|
+
return db.query<AuditRow, typeof params>(
|
|
84
|
+
`SELECT id, memory_id, op, actor, session_id, before_json, after_json, created_at
|
|
85
|
+
FROM memory_audit ${where} ORDER BY created_at DESC LIMIT ?`
|
|
86
|
+
).all(...params);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Batch fetch provenance rows for multiple memory IDs — one query instead of N.
|
|
91
|
+
* Returns a Map keyed by memory_id; use to avoid N+1 in recall({ includeProvenance: true }).
|
|
92
|
+
*/
|
|
93
|
+
export function listProvenanceBatch(db: Database, memoryIds: number[]): Map<number, ProvenanceRow[]> {
|
|
94
|
+
if (memoryIds.length === 0) return new Map();
|
|
95
|
+
const placeholders = memoryIds.map(() => "?").join(",");
|
|
96
|
+
const rows = db.query<ProvenanceRow, number[]>(
|
|
97
|
+
`SELECT id, memory_id, source_type, source_ref, actor, created_at, metadata
|
|
98
|
+
FROM memory_provenance WHERE memory_id IN (${placeholders})
|
|
99
|
+
ORDER BY memory_id, created_at DESC, id DESC`
|
|
100
|
+
).all(...memoryIds);
|
|
101
|
+
const map = new Map<number, ProvenanceRow[]>();
|
|
102
|
+
for (const row of rows) {
|
|
103
|
+
const arr = map.get(row.memory_id) ?? [];
|
|
104
|
+
arr.push(row);
|
|
105
|
+
map.set(row.memory_id, arr);
|
|
106
|
+
}
|
|
107
|
+
return map;
|
|
108
|
+
}
|
package/src/dao/types.ts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dao/types.ts — Shared row types for the DAO layer.
|
|
3
|
+
* MemorySlim omits the embedding blob — use this for all recall paths.
|
|
4
|
+
* MemoryFull includes embedding — only for embeddings.ts internals.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export type MemoryCategory = "preference" | "architecture" | "gotcha" | "pattern" | "workflow" | "constraint";
|
|
8
|
+
export type RelationshipType = "supports" | "contradicts" | "refines" | "depends_on" | "related_to" | "supersedes";
|
|
9
|
+
export type MemoryStatus = "active" | "pending" | "deprecated" | "superseded";
|
|
10
|
+
export type ContextItemType = "goal" | "decision" | "progress" | "gotcha";
|
|
11
|
+
export type ContextItemStatus = "active" | "pending_promotion" | "promoted";
|
|
12
|
+
|
|
13
|
+
/** Slim memory row — no embedding blob. Used by recall(), getContextMerge(), and all MCP responses. */
|
|
14
|
+
export interface MemorySlim {
|
|
15
|
+
id: number;
|
|
16
|
+
content: string;
|
|
17
|
+
title?: string | null;
|
|
18
|
+
category: MemoryCategory;
|
|
19
|
+
importance: number;
|
|
20
|
+
confidence: number;
|
|
21
|
+
source: string | null;
|
|
22
|
+
project_scope: string | null;
|
|
23
|
+
dedup_key: string | null;
|
|
24
|
+
created_at: string;
|
|
25
|
+
last_confirmed_at: string;
|
|
26
|
+
last_used_at: string;
|
|
27
|
+
confirm_count: number;
|
|
28
|
+
status: MemoryStatus;
|
|
29
|
+
first_recalled_at?: string | null;
|
|
30
|
+
last_recalled_at?: string | null;
|
|
31
|
+
recall_count?: number;
|
|
32
|
+
superseded_by?: number | null;
|
|
33
|
+
superseded_at?: string | null;
|
|
34
|
+
workspace_id?: string | null;
|
|
35
|
+
agent_id?: string | null;
|
|
36
|
+
created_by?: string | null;
|
|
37
|
+
hidden?: number;
|
|
38
|
+
color?: string | null;
|
|
39
|
+
icon?: string | null;
|
|
40
|
+
user_note?: string | null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Full memory row — includes embedding blob. Internal use only (embeddings.ts). */
|
|
44
|
+
export interface MemoryFull extends MemorySlim {
|
|
45
|
+
embedding: Buffer | null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface ContextItemRow {
|
|
49
|
+
id: number;
|
|
50
|
+
project_name: string;
|
|
51
|
+
type: ContextItemType;
|
|
52
|
+
content: string;
|
|
53
|
+
title?: string | null;
|
|
54
|
+
session_id: string | null;
|
|
55
|
+
permanent: number;
|
|
56
|
+
memory_id: number | null;
|
|
57
|
+
status: ContextItemStatus;
|
|
58
|
+
created_at: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface MemoryRelationRow {
|
|
62
|
+
id: number;
|
|
63
|
+
source_memory_id: number;
|
|
64
|
+
target_memory_id: number;
|
|
65
|
+
relationship_type: RelationshipType;
|
|
66
|
+
note?: string | null;
|
|
67
|
+
weight?: number;
|
|
68
|
+
created_at: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface MemoryLayoutRow {
|
|
72
|
+
memory_id: number;
|
|
73
|
+
view: string;
|
|
74
|
+
x: number;
|
|
75
|
+
y: number;
|
|
76
|
+
pinned: number;
|
|
77
|
+
updated_at: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// --- Phase 2: Provenance + Audit ---
|
|
81
|
+
|
|
82
|
+
export type ProvenanceSourceType =
|
|
83
|
+
| "learn" | "git-backfill" | "evaluate-session" | "import-bundle"
|
|
84
|
+
| "user-promotion" | "janitor-rollup" | "legacy";
|
|
85
|
+
|
|
86
|
+
export type AuditOp =
|
|
87
|
+
| "insert" | "update" | "forget" | "deprecate" | "supersede" | "redact" | "restore" | "archive";
|
|
88
|
+
|
|
89
|
+
export interface ProvenanceRow {
|
|
90
|
+
id: number;
|
|
91
|
+
memory_id: number;
|
|
92
|
+
source_type: ProvenanceSourceType;
|
|
93
|
+
source_ref: string | null;
|
|
94
|
+
actor: string | null;
|
|
95
|
+
created_at: string;
|
|
96
|
+
metadata: string | null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface ProvenanceInput {
|
|
100
|
+
memory_id: number;
|
|
101
|
+
source_type: ProvenanceSourceType;
|
|
102
|
+
source_ref?: string | null;
|
|
103
|
+
actor?: string | null;
|
|
104
|
+
metadata?: string | null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface AuditRow {
|
|
108
|
+
id: number;
|
|
109
|
+
memory_id: number;
|
|
110
|
+
op: AuditOp;
|
|
111
|
+
actor: string;
|
|
112
|
+
session_id: string | null;
|
|
113
|
+
before_json: string | null;
|
|
114
|
+
after_json: string | null;
|
|
115
|
+
created_at: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface AuditInput {
|
|
119
|
+
memory_id: number;
|
|
120
|
+
op: AuditOp;
|
|
121
|
+
actor: string;
|
|
122
|
+
session_id?: string | null;
|
|
123
|
+
before_json?: string | null;
|
|
124
|
+
after_json?: string | null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* JSON-safe memory snapshot — excludes embedding blob. Used for audit before/after captures.
|
|
129
|
+
* Same shape as MemorySlim but with category/status widened to string (SQLite returns raw strings).
|
|
130
|
+
*/
|
|
131
|
+
export type MemorySnapshot = Omit<MemorySlim, "category" | "status"> & {
|
|
132
|
+
category: string;
|
|
133
|
+
status: string;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/** A superseded-memory conflict row returned by getRecentConflicts(). */
|
|
137
|
+
export interface ConflictRow {
|
|
138
|
+
olderId: number;
|
|
139
|
+
olderContent: string;
|
|
140
|
+
newerId: number;
|
|
141
|
+
newerContent: string;
|
|
142
|
+
}
|