gnosys 5.5.0 → 5.7.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 +44 -0
- package/dist/cli.js +959 -438
- package/dist/cli.js.map +1 -1
- package/dist/lib/audit.d.ts +13 -0
- package/dist/lib/audit.d.ts.map +1 -1
- package/dist/lib/audit.js +42 -0
- package/dist/lib/audit.js.map +1 -1
- package/dist/lib/chat/choose.d.ts +75 -0
- package/dist/lib/chat/choose.d.ts.map +1 -0
- package/dist/lib/chat/choose.js +146 -0
- package/dist/lib/chat/choose.js.map +1 -0
- package/dist/lib/chat/commands.d.ts +96 -0
- package/dist/lib/chat/commands.d.ts.map +1 -0
- package/dist/lib/chat/commands.js +367 -0
- package/dist/lib/chat/commands.js.map +1 -0
- package/dist/lib/chat/focus.d.ts +70 -0
- package/dist/lib/chat/focus.d.ts.map +1 -0
- package/dist/lib/chat/focus.js +120 -0
- package/dist/lib/chat/focus.js.map +1 -0
- package/dist/lib/chat/index.d.ts +32 -0
- package/dist/lib/chat/index.d.ts.map +1 -0
- package/dist/lib/chat/index.js +151 -0
- package/dist/lib/chat/index.js.map +1 -0
- package/dist/lib/chat/intent.d.ts +100 -0
- package/dist/lib/chat/intent.d.ts.map +1 -0
- package/dist/lib/chat/intent.js +192 -0
- package/dist/lib/chat/intent.js.map +1 -0
- package/dist/lib/chat/llmTurn.d.ts +55 -0
- package/dist/lib/chat/llmTurn.d.ts.map +1 -0
- package/dist/lib/chat/llmTurn.js +103 -0
- package/dist/lib/chat/llmTurn.js.map +1 -0
- package/dist/lib/chat/recall.d.ts +58 -0
- package/dist/lib/chat/recall.d.ts.map +1 -0
- package/dist/lib/chat/recall.js +109 -0
- package/dist/lib/chat/recall.js.map +1 -0
- package/dist/lib/chat/render.d.ts +30 -0
- package/dist/lib/chat/render.d.ts.map +1 -0
- package/dist/lib/chat/render.js +755 -0
- package/dist/lib/chat/render.js.map +1 -0
- package/dist/lib/chat/session.d.ts +121 -0
- package/dist/lib/chat/session.d.ts.map +1 -0
- package/dist/lib/chat/session.js +148 -0
- package/dist/lib/chat/session.js.map +1 -0
- package/dist/lib/chat/toolFence.d.ts +54 -0
- package/dist/lib/chat/toolFence.d.ts.map +1 -0
- package/dist/lib/chat/toolFence.js +90 -0
- package/dist/lib/chat/toolFence.js.map +1 -0
- package/dist/lib/chat/tools.d.ts +48 -0
- package/dist/lib/chat/tools.d.ts.map +1 -0
- package/dist/lib/chat/tools.js +338 -0
- package/dist/lib/chat/tools.js.map +1 -0
- package/dist/lib/chat/types.d.ts +42 -0
- package/dist/lib/chat/types.d.ts.map +1 -0
- package/dist/lib/chat/types.js +6 -0
- package/dist/lib/chat/types.js.map +1 -0
- package/dist/lib/chat/write.d.ts +66 -0
- package/dist/lib/chat/write.d.ts.map +1 -0
- package/dist/lib/chat/write.js +203 -0
- package/dist/lib/chat/write.js.map +1 -0
- package/dist/lib/db.d.ts +41 -1
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +136 -28
- package/dist/lib/db.js.map +1 -1
- package/dist/lib/exportProject.d.ts +51 -0
- package/dist/lib/exportProject.d.ts.map +1 -0
- package/dist/lib/exportProject.js +72 -0
- package/dist/lib/exportProject.js.map +1 -0
- package/dist/lib/importProject.d.ts +35 -0
- package/dist/lib/importProject.d.ts.map +1 -0
- package/dist/lib/importProject.js +135 -0
- package/dist/lib/importProject.js.map +1 -0
- package/dist/lib/remote.d.ts +23 -0
- package/dist/lib/remote.d.ts.map +1 -1
- package/dist/lib/remote.js +88 -0
- package/dist/lib/remote.js.map +1 -1
- package/dist/lib/remoteWizard.d.ts.map +1 -1
- package/dist/lib/remoteWizard.js +13 -17
- package/dist/lib/remoteWizard.js.map +1 -1
- package/dist/lib/setup/sections/ides.d.ts +20 -0
- package/dist/lib/setup/sections/ides.d.ts.map +1 -0
- package/dist/lib/setup/sections/ides.js +124 -0
- package/dist/lib/setup/sections/ides.js.map +1 -0
- package/dist/lib/setup/sections/preferences.d.ts +30 -0
- package/dist/lib/setup/sections/preferences.d.ts.map +1 -0
- package/dist/lib/setup/sections/preferences.js +128 -0
- package/dist/lib/setup/sections/preferences.js.map +1 -0
- package/dist/lib/setup/sections/routing.d.ts +21 -0
- package/dist/lib/setup/sections/routing.d.ts.map +1 -0
- package/dist/lib/setup/sections/routing.js +160 -0
- package/dist/lib/setup/sections/routing.js.map +1 -0
- package/dist/lib/setup/summary.d.ts +42 -0
- package/dist/lib/setup/summary.d.ts.map +1 -0
- package/dist/lib/setup/summary.js +206 -0
- package/dist/lib/setup/summary.js.map +1 -0
- package/dist/lib/timeline.d.ts +7 -0
- package/dist/lib/timeline.d.ts.map +1 -1
- package/dist/lib/timeline.js +19 -5
- package/dist/lib/timeline.js.map +1 -1
- package/package.json +7 -1
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat-side memory writing — promote chat content to gnosys memories.
|
|
3
|
+
*
|
|
4
|
+
* Handles three triggers:
|
|
5
|
+
* /remember <text> explicit user-marked insight
|
|
6
|
+
* /save-turn distill the last user+assistant exchange
|
|
7
|
+
* /attach <file> ingest a file via the multimodal pipeline
|
|
8
|
+
*
|
|
9
|
+
* All promoted memories carry session provenance:
|
|
10
|
+
* tags.session: [<sessionId>]
|
|
11
|
+
* tags.from-chat: ["true"]
|
|
12
|
+
* tags.source: ["remember" | "save-turn" | "auto" | "attach"]
|
|
13
|
+
*/
|
|
14
|
+
import { getLLMProvider } from "../llm.js";
|
|
15
|
+
/** Build the structuring prompt for save-turn / auto-promote (LLM-assisted). */
|
|
16
|
+
function buildStructurePrompt(content, source) {
|
|
17
|
+
return `You are extracting one memory from chat content. Output STRICT JSON only — no markdown fences, no commentary.
|
|
18
|
+
|
|
19
|
+
Schema:
|
|
20
|
+
{
|
|
21
|
+
"title": "<5–10 word title>",
|
|
22
|
+
"category": "decisions | architecture | concepts | requirements | landscape | open-questions | roadmap",
|
|
23
|
+
"tags": ["<3–6 lowercase domain words>"],
|
|
24
|
+
"relevance": "<space-separated keyword cloud for discovery>"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Source: ${source}
|
|
28
|
+
Content:
|
|
29
|
+
${content}
|
|
30
|
+
|
|
31
|
+
Output the JSON object only.`;
|
|
32
|
+
}
|
|
33
|
+
const VALID_CATEGORIES = new Set([
|
|
34
|
+
"decisions",
|
|
35
|
+
"architecture",
|
|
36
|
+
"concepts",
|
|
37
|
+
"requirements",
|
|
38
|
+
"landscape",
|
|
39
|
+
"open-questions",
|
|
40
|
+
"roadmap",
|
|
41
|
+
]);
|
|
42
|
+
const FALLBACK_CATEGORY = {
|
|
43
|
+
remember: "concepts",
|
|
44
|
+
"save-turn": "concepts",
|
|
45
|
+
auto: "decisions",
|
|
46
|
+
attach: "concepts",
|
|
47
|
+
};
|
|
48
|
+
/** Heuristic fallback when LLM isn't available. Uses the first line as the title. */
|
|
49
|
+
function deriveFieldsFallback(content, source) {
|
|
50
|
+
const firstLine = content.split(/\n/, 1)[0].trim();
|
|
51
|
+
const title = firstLine.length > 60 ? firstLine.slice(0, 57) + "..." : firstLine || "Memory";
|
|
52
|
+
return {
|
|
53
|
+
title,
|
|
54
|
+
category: FALLBACK_CATEGORY[source],
|
|
55
|
+
tags: [],
|
|
56
|
+
relevance: content.split(/\s+/).slice(0, 20).join(" "),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async function deriveFieldsViaLLM(config, content, source) {
|
|
60
|
+
try {
|
|
61
|
+
const provider = getLLMProvider(config, "structuring");
|
|
62
|
+
const raw = await provider.generate(buildStructurePrompt(content, source), { maxTokens: 400 });
|
|
63
|
+
// Tolerate the model returning ```json ... ``` despite our instructions
|
|
64
|
+
const trimmed = raw.replace(/^```(?:json)?\s*|\s*```$/g, "").trim();
|
|
65
|
+
const parsed = JSON.parse(trimmed);
|
|
66
|
+
if (!parsed.title || !parsed.category)
|
|
67
|
+
return null;
|
|
68
|
+
return {
|
|
69
|
+
title: parsed.title,
|
|
70
|
+
category: VALID_CATEGORIES.has(parsed.category) ? parsed.category : FALLBACK_CATEGORY[source],
|
|
71
|
+
tags: Array.isArray(parsed.tags) ? parsed.tags.map(String) : [],
|
|
72
|
+
relevance: typeof parsed.relevance === "string" ? parsed.relevance : "",
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Write a chat-sourced memory to the central DB. Returns the assigned ID.
|
|
81
|
+
*
|
|
82
|
+
* Uses LLM structuring when config is provided and the structuring provider
|
|
83
|
+
* is reachable; falls back to a heuristic title + category otherwise.
|
|
84
|
+
*/
|
|
85
|
+
export async function promoteToMemory(db, opts) {
|
|
86
|
+
// Try LLM first; fall back if unavailable or on error
|
|
87
|
+
let fields = null;
|
|
88
|
+
if (opts.config) {
|
|
89
|
+
fields = await deriveFieldsViaLLM(opts.config, opts.content, opts.source);
|
|
90
|
+
}
|
|
91
|
+
if (!fields) {
|
|
92
|
+
fields = deriveFieldsFallback(opts.content, opts.source);
|
|
93
|
+
}
|
|
94
|
+
// Caller-provided overrides win
|
|
95
|
+
if (opts.title)
|
|
96
|
+
fields.title = opts.title;
|
|
97
|
+
if (opts.category && VALID_CATEGORIES.has(opts.category))
|
|
98
|
+
fields.category = opts.category;
|
|
99
|
+
// Provenance tags injected on top of any LLM-suggested ones
|
|
100
|
+
const allTags = [
|
|
101
|
+
...fields.tags,
|
|
102
|
+
`session:${opts.sessionId}`,
|
|
103
|
+
`from-chat:true`,
|
|
104
|
+
`source:${opts.source}`,
|
|
105
|
+
];
|
|
106
|
+
const id = db.getNextId(fields.category, opts.projectId ?? undefined);
|
|
107
|
+
const now = new Date().toISOString();
|
|
108
|
+
const today = now.split("T")[0];
|
|
109
|
+
const memory = {
|
|
110
|
+
id,
|
|
111
|
+
title: fields.title,
|
|
112
|
+
category: fields.category,
|
|
113
|
+
content: `# ${fields.title}\n\n${opts.content}`,
|
|
114
|
+
summary: null,
|
|
115
|
+
tags: JSON.stringify(allTags),
|
|
116
|
+
relevance: fields.relevance,
|
|
117
|
+
author: opts.source === "auto" ? "ai" : "human+ai",
|
|
118
|
+
authority: "declared",
|
|
119
|
+
confidence: 0.85,
|
|
120
|
+
reinforcement_count: 0,
|
|
121
|
+
content_hash: fnv1a(opts.content),
|
|
122
|
+
status: "active",
|
|
123
|
+
tier: "active",
|
|
124
|
+
supersedes: null,
|
|
125
|
+
superseded_by: null,
|
|
126
|
+
last_reinforced: null,
|
|
127
|
+
created: today,
|
|
128
|
+
modified: today,
|
|
129
|
+
source_path: null,
|
|
130
|
+
project_id: opts.projectId,
|
|
131
|
+
scope: opts.projectId ? "project" : "user",
|
|
132
|
+
};
|
|
133
|
+
db.insertMemory(memory);
|
|
134
|
+
db.logAudit({
|
|
135
|
+
timestamp: now,
|
|
136
|
+
operation: "write",
|
|
137
|
+
memory_id: id,
|
|
138
|
+
details: JSON.stringify({ source: `chat:${opts.source}`, sessionId: opts.sessionId }),
|
|
139
|
+
duration_ms: null,
|
|
140
|
+
trace_id: null,
|
|
141
|
+
});
|
|
142
|
+
return { id, title: fields.title, category: fields.category };
|
|
143
|
+
}
|
|
144
|
+
/** Build the content for /save-turn from the most recent user+assistant exchange. */
|
|
145
|
+
export function lastExchange(buffer) {
|
|
146
|
+
// Walk from the end to find the last assistant turn, then the user turn before it
|
|
147
|
+
let assistantIdx = -1;
|
|
148
|
+
for (let i = buffer.length - 1; i >= 0; i--) {
|
|
149
|
+
if (buffer[i].role === "assistant") {
|
|
150
|
+
assistantIdx = i;
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (assistantIdx < 1)
|
|
155
|
+
return null;
|
|
156
|
+
let userIdx = -1;
|
|
157
|
+
for (let i = assistantIdx - 1; i >= 0; i--) {
|
|
158
|
+
if (buffer[i].role === "user") {
|
|
159
|
+
userIdx = i;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (userIdx < 0)
|
|
164
|
+
return null;
|
|
165
|
+
return {
|
|
166
|
+
user: buffer[userIdx].text,
|
|
167
|
+
assistant: buffer[assistantIdx].text,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/** Format a save-turn pair as a markdown exchange suitable for memory content. */
|
|
171
|
+
export function formatExchange(pair) {
|
|
172
|
+
return `**Question / context:**\n${pair.user}\n\n**Answer / decision:**\n${pair.assistant}`;
|
|
173
|
+
}
|
|
174
|
+
// ─── Auto-promote heuristic ──────────────────────────────────────────────
|
|
175
|
+
const AUTO_PROMOTE_PATTERNS = [
|
|
176
|
+
{ pattern: /\b(we (decided|agreed|chose) to|let's (go with|commit to|use))\b/i, source: "auto", reason: "decision-language" },
|
|
177
|
+
{ pattern: /\b(I learned|the answer is|turns out|it works because)\b/i, source: "auto", reason: "insight-language" },
|
|
178
|
+
{ pattern: /\b(let's note|note that|let's remember|don't forget)\b/i, source: "auto", reason: "note-request" },
|
|
179
|
+
];
|
|
180
|
+
/**
|
|
181
|
+
* Scan a user turn for "looks like a decision/insight worth saving" patterns.
|
|
182
|
+
* Returns a hint that the TUI can surface as an inline confirm prompt.
|
|
183
|
+
* Returns null when nothing matches.
|
|
184
|
+
*/
|
|
185
|
+
export function detectAutoPromote(userText) {
|
|
186
|
+
for (const { pattern, reason } of AUTO_PROMOTE_PATTERNS) {
|
|
187
|
+
const m = userText.match(pattern);
|
|
188
|
+
if (m) {
|
|
189
|
+
return { reason, match: m[0] };
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
// ─── helpers ─────────────────────────────────────────────────────────────
|
|
195
|
+
function fnv1a(text) {
|
|
196
|
+
let hash = 0x811c9dc5;
|
|
197
|
+
for (let i = 0; i < text.length; i++) {
|
|
198
|
+
hash ^= text.charCodeAt(i);
|
|
199
|
+
hash = Math.imul(hash, 0x01000193);
|
|
200
|
+
}
|
|
201
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/lib/chat/write.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/db.d.ts
CHANGED
|
@@ -145,6 +145,23 @@ export declare class GnosysDB {
|
|
|
145
145
|
* file handles after a WAL checkpoint or remount.
|
|
146
146
|
*/
|
|
147
147
|
reopen(): void;
|
|
148
|
+
/**
|
|
149
|
+
* Execute a DB operation with automatic recovery from stale-handle errors.
|
|
150
|
+
*
|
|
151
|
+
* SQLITE_CORRUPT ("database disk image is malformed") can happen when a
|
|
152
|
+
* long-lived handle (e.g. an MCP server process) sees stale pages after
|
|
153
|
+
* concurrent writes from another process (`gnosys setup`, sync layer, etc.)
|
|
154
|
+
* truncated the WAL or rolled the schema. The DB file itself is fine —
|
|
155
|
+
* just our cached page view is out of date.
|
|
156
|
+
*
|
|
157
|
+
* Strategy: catch the error, close + reopen the handle, retry once. If it
|
|
158
|
+
* still fails after reopen, rethrow — that's a real corruption case.
|
|
159
|
+
*
|
|
160
|
+
* Used internally by write methods that the MCP server calls long-term.
|
|
161
|
+
* Read methods are also wrapped because reads against stale pages can
|
|
162
|
+
* surface the same error.
|
|
163
|
+
*/
|
|
164
|
+
private withRecovery;
|
|
148
165
|
/**
|
|
149
166
|
* Restore from a backup file. Closes current DB, copies backup over, re-opens.
|
|
150
167
|
*/
|
|
@@ -169,6 +186,8 @@ export declare class GnosysDB {
|
|
|
169
186
|
getAllMemories(): DbMemory[];
|
|
170
187
|
getMemoriesByTier(tier: string): DbMemory[];
|
|
171
188
|
getMemoriesByCategory(category: string): DbMemory[];
|
|
189
|
+
getRelationshipsForMemoryIds(ids: string[]): DbRelationship[];
|
|
190
|
+
getAuditEntriesByProject(projectId: string): DbAuditEntry[];
|
|
172
191
|
updateMemory(id: string, updates: Partial<DbMemory>): void;
|
|
173
192
|
deleteMemory(id: string): void;
|
|
174
193
|
getMemoryCount(): {
|
|
@@ -180,7 +199,7 @@ export declare class GnosysDB {
|
|
|
180
199
|
/**
|
|
181
200
|
* Get active memories scoped to a specific project.
|
|
182
201
|
*/
|
|
183
|
-
getMemoriesByProject(projectId: string): DbMemory[];
|
|
202
|
+
getMemoriesByProject(projectId: string, includeArchived?: boolean): DbMemory[];
|
|
184
203
|
/**
|
|
185
204
|
* Get memories by scope (project, user, global).
|
|
186
205
|
*/
|
|
@@ -232,6 +251,27 @@ export declare class GnosysDB {
|
|
|
232
251
|
getAllSummaries(): DbSummary[];
|
|
233
252
|
logAudit(entry: Omit<DbAuditEntry, "id">): void;
|
|
234
253
|
getAuditLog(memoryId: string, limit?: number): DbAuditEntry[];
|
|
254
|
+
/**
|
|
255
|
+
* Get audit entries newer than a given timestamp. Used by remote sync to
|
|
256
|
+
* push/pull audit_log incrementally. Returns oldest-first so order is
|
|
257
|
+
* preserved across machines.
|
|
258
|
+
*/
|
|
259
|
+
getAuditEntriesAfter(sinceIso: string, limit?: number): DbAuditEntry[];
|
|
260
|
+
/**
|
|
261
|
+
* Get the most recent audit timestamp seen in this DB. Used as a high-water
|
|
262
|
+
* mark for sync: "push entries newer than the most recent timestamp the
|
|
263
|
+
* remote has already seen". Returns null when the table is empty.
|
|
264
|
+
*/
|
|
265
|
+
getLatestAuditTimestamp(): string | null;
|
|
266
|
+
/**
|
|
267
|
+
* Query audit entries with optional filters. Returns newest first.
|
|
268
|
+
* Used by `gnosys audit` and `gnosys doctor` reports.
|
|
269
|
+
*/
|
|
270
|
+
queryAuditLog(opts?: {
|
|
271
|
+
sinceIso?: string;
|
|
272
|
+
operation?: string;
|
|
273
|
+
limit?: number;
|
|
274
|
+
}): DbAuditEntry[];
|
|
235
275
|
updateEmbedding(id: string, embedding: Buffer): void;
|
|
236
276
|
getEmbedding(id: string): Buffer | null;
|
|
237
277
|
getAllEmbeddings(): Array<{
|
package/dist/lib/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/lib/db.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/lib/db.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/db.js
CHANGED
|
@@ -400,6 +400,43 @@ export class GnosysDB {
|
|
|
400
400
|
// reopen failed — leave unavailable; caller surfaces error
|
|
401
401
|
}
|
|
402
402
|
}
|
|
403
|
+
/**
|
|
404
|
+
* Execute a DB operation with automatic recovery from stale-handle errors.
|
|
405
|
+
*
|
|
406
|
+
* SQLITE_CORRUPT ("database disk image is malformed") can happen when a
|
|
407
|
+
* long-lived handle (e.g. an MCP server process) sees stale pages after
|
|
408
|
+
* concurrent writes from another process (`gnosys setup`, sync layer, etc.)
|
|
409
|
+
* truncated the WAL or rolled the schema. The DB file itself is fine —
|
|
410
|
+
* just our cached page view is out of date.
|
|
411
|
+
*
|
|
412
|
+
* Strategy: catch the error, close + reopen the handle, retry once. If it
|
|
413
|
+
* still fails after reopen, rethrow — that's a real corruption case.
|
|
414
|
+
*
|
|
415
|
+
* Used internally by write methods that the MCP server calls long-term.
|
|
416
|
+
* Read methods are also wrapped because reads against stale pages can
|
|
417
|
+
* surface the same error.
|
|
418
|
+
*/
|
|
419
|
+
withRecovery(fn) {
|
|
420
|
+
try {
|
|
421
|
+
return fn();
|
|
422
|
+
}
|
|
423
|
+
catch (err) {
|
|
424
|
+
const errAny = err;
|
|
425
|
+
const isCorrupt = errAny?.code === "SQLITE_CORRUPT" ||
|
|
426
|
+
/database disk image is malformed/i.test(errAny?.message ?? "");
|
|
427
|
+
if (!isCorrupt)
|
|
428
|
+
throw err;
|
|
429
|
+
// One-shot recovery: reopen and retry. If the reopen itself fails or
|
|
430
|
+
// the retry surfaces the same error, that's a real corruption case —
|
|
431
|
+
// surface it loudly.
|
|
432
|
+
this.reopen();
|
|
433
|
+
if (!this.available) {
|
|
434
|
+
throw new Error("Gnosys DB unrecoverable after reopen. The underlying file may be corrupted. " +
|
|
435
|
+
"Run 'gnosys doctor' for diagnostics; restore from a backup if needed.");
|
|
436
|
+
}
|
|
437
|
+
return fn();
|
|
438
|
+
}
|
|
439
|
+
}
|
|
403
440
|
/**
|
|
404
441
|
* Restore from a backup file. Closes current DB, copies backup over, re-opens.
|
|
405
442
|
*/
|
|
@@ -511,25 +548,27 @@ export class GnosysDB {
|
|
|
511
548
|
}
|
|
512
549
|
// ─── Memory CRUD ────────────────────────────────────────────────────
|
|
513
550
|
insertMemory(mem) {
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
551
|
+
return this.withRecovery(() => {
|
|
552
|
+
const stmt = this.db.prepare(`
|
|
553
|
+
INSERT OR REPLACE INTO memories
|
|
554
|
+
(id, title, category, content, summary, tags, relevance, author, authority,
|
|
555
|
+
confidence, reinforcement_count, content_hash, status, tier, supersedes,
|
|
556
|
+
superseded_by, last_reinforced, created, modified, embedding, source_path,
|
|
557
|
+
source_file, source_page, source_timerange,
|
|
558
|
+
project_id, scope)
|
|
559
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
560
|
+
`);
|
|
561
|
+
stmt.run(mem.id, mem.title, mem.category, mem.content, mem.summary || null, mem.tags, mem.relevance, mem.author, mem.authority, mem.confidence, mem.reinforcement_count, mem.content_hash, mem.status, mem.tier, mem.supersedes || null, mem.superseded_by || null, mem.last_reinforced || null, mem.created, mem.modified, mem.embedding || null, mem.source_path || null, mem.source_file || null, mem.source_page || null, mem.source_timerange || null, mem.project_id || null, mem.scope || "project");
|
|
562
|
+
});
|
|
524
563
|
}
|
|
525
564
|
getMemory(id) {
|
|
526
|
-
return this.db.prepare("SELECT * FROM memories WHERE id = ?").get(id) || null;
|
|
565
|
+
return this.withRecovery(() => this.db.prepare("SELECT * FROM memories WHERE id = ?").get(id) || null);
|
|
527
566
|
}
|
|
528
567
|
getActiveMemories() {
|
|
529
|
-
return this.db.prepare("SELECT * FROM memories WHERE tier = 'active' AND status = 'active'").all();
|
|
568
|
+
return this.withRecovery(() => this.db.prepare("SELECT * FROM memories WHERE tier = 'active' AND status = 'active'").all());
|
|
530
569
|
}
|
|
531
570
|
getAllMemories() {
|
|
532
|
-
return this.db.prepare("SELECT * FROM memories").all();
|
|
571
|
+
return this.withRecovery(() => this.db.prepare("SELECT * FROM memories").all());
|
|
533
572
|
}
|
|
534
573
|
getMemoriesByTier(tier) {
|
|
535
574
|
return this.db.prepare("SELECT * FROM memories WHERE tier = ?").all(tier);
|
|
@@ -537,6 +576,19 @@ export class GnosysDB {
|
|
|
537
576
|
getMemoriesByCategory(category) {
|
|
538
577
|
return this.db.prepare("SELECT * FROM memories WHERE category = ? AND tier = 'active'").all(category);
|
|
539
578
|
}
|
|
579
|
+
getRelationshipsForMemoryIds(ids) {
|
|
580
|
+
if (ids.length === 0)
|
|
581
|
+
return [];
|
|
582
|
+
const placeholders = ids.map(() => "?").join(",");
|
|
583
|
+
return this.db
|
|
584
|
+
.prepare(`SELECT * FROM relationships WHERE source_id IN (${placeholders}) OR target_id IN (${placeholders})`)
|
|
585
|
+
.all(...ids, ...ids);
|
|
586
|
+
}
|
|
587
|
+
getAuditEntriesByProject(projectId) {
|
|
588
|
+
return this.db
|
|
589
|
+
.prepare("SELECT * FROM audit_log WHERE memory_id IN (SELECT id FROM memories WHERE project_id = ?) ORDER BY id")
|
|
590
|
+
.all(projectId);
|
|
591
|
+
}
|
|
540
592
|
updateMemory(id, updates) {
|
|
541
593
|
const fields = [];
|
|
542
594
|
const values = [];
|
|
@@ -635,8 +687,11 @@ export class GnosysDB {
|
|
|
635
687
|
/**
|
|
636
688
|
* Get active memories scoped to a specific project.
|
|
637
689
|
*/
|
|
638
|
-
getMemoriesByProject(projectId) {
|
|
639
|
-
|
|
690
|
+
getMemoriesByProject(projectId, includeArchived = false) {
|
|
691
|
+
const sql = includeArchived
|
|
692
|
+
? "SELECT * FROM memories WHERE project_id = ?"
|
|
693
|
+
: "SELECT * FROM memories WHERE project_id = ? AND tier = 'active' AND status = 'active'";
|
|
694
|
+
return this.db.prepare(sql).all(projectId);
|
|
640
695
|
}
|
|
641
696
|
/**
|
|
642
697
|
* Get memories by scope (project, user, global).
|
|
@@ -646,20 +701,22 @@ export class GnosysDB {
|
|
|
646
701
|
}
|
|
647
702
|
// ─── Project Identity (v3.0) ──────────────────────────────────────
|
|
648
703
|
insertProject(project) {
|
|
649
|
-
this.
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
704
|
+
return this.withRecovery(() => {
|
|
705
|
+
this.db.prepare(`
|
|
706
|
+
INSERT OR REPLACE INTO projects
|
|
707
|
+
(id, name, working_directory, user, agent_rules_target, obsidian_vault, created, modified)
|
|
708
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
709
|
+
`).run(project.id, project.name, project.working_directory, project.user, project.agent_rules_target || null, project.obsidian_vault || null, project.created, project.modified);
|
|
710
|
+
});
|
|
654
711
|
}
|
|
655
712
|
getProject(id) {
|
|
656
|
-
return this.db.prepare("SELECT * FROM projects WHERE id = ?").get(id) || null;
|
|
713
|
+
return this.withRecovery(() => this.db.prepare("SELECT * FROM projects WHERE id = ?").get(id) || null);
|
|
657
714
|
}
|
|
658
715
|
getProjectByDirectory(dir) {
|
|
659
|
-
return this.db.prepare("SELECT * FROM projects WHERE working_directory = ?").get(dir) || null;
|
|
716
|
+
return this.withRecovery(() => this.db.prepare("SELECT * FROM projects WHERE working_directory = ?").get(dir) || null);
|
|
660
717
|
}
|
|
661
718
|
getAllProjects() {
|
|
662
|
-
return this.db.prepare("SELECT * FROM projects ORDER BY name").all();
|
|
719
|
+
return this.withRecovery(() => this.db.prepare("SELECT * FROM projects ORDER BY name").all());
|
|
663
720
|
}
|
|
664
721
|
updateProject(id, updates) {
|
|
665
722
|
const fields = [];
|
|
@@ -797,13 +854,64 @@ export class GnosysDB {
|
|
|
797
854
|
}
|
|
798
855
|
// ─── Audit ──────────────────────────────────────────────────────────
|
|
799
856
|
logAudit(entry) {
|
|
800
|
-
this.
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
857
|
+
return this.withRecovery(() => {
|
|
858
|
+
this.db.prepare(`
|
|
859
|
+
INSERT INTO audit_log (timestamp, operation, memory_id, details, duration_ms, trace_id)
|
|
860
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
861
|
+
`).run(entry.timestamp, entry.operation, entry.memory_id, entry.details, entry.duration_ms, entry.trace_id);
|
|
862
|
+
});
|
|
804
863
|
}
|
|
805
864
|
getAuditLog(memoryId, limit = 20) {
|
|
806
|
-
return this.db.prepare("SELECT * FROM audit_log WHERE memory_id = ? ORDER BY timestamp DESC LIMIT ?").all(memoryId, limit);
|
|
865
|
+
return this.withRecovery(() => this.db.prepare("SELECT * FROM audit_log WHERE memory_id = ? ORDER BY timestamp DESC LIMIT ?").all(memoryId, limit));
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Get audit entries newer than a given timestamp. Used by remote sync to
|
|
869
|
+
* push/pull audit_log incrementally. Returns oldest-first so order is
|
|
870
|
+
* preserved across machines.
|
|
871
|
+
*/
|
|
872
|
+
getAuditEntriesAfter(sinceIso, limit) {
|
|
873
|
+
return this.withRecovery(() => {
|
|
874
|
+
const cap = limit ? ` LIMIT ${Math.max(1, Math.floor(limit))}` : "";
|
|
875
|
+
return this.db
|
|
876
|
+
.prepare(`SELECT * FROM audit_log WHERE timestamp > ? ORDER BY timestamp ASC${cap}`)
|
|
877
|
+
.all(sinceIso);
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Get the most recent audit timestamp seen in this DB. Used as a high-water
|
|
882
|
+
* mark for sync: "push entries newer than the most recent timestamp the
|
|
883
|
+
* remote has already seen". Returns null when the table is empty.
|
|
884
|
+
*/
|
|
885
|
+
getLatestAuditTimestamp() {
|
|
886
|
+
return this.withRecovery(() => {
|
|
887
|
+
const row = this.db
|
|
888
|
+
.prepare("SELECT timestamp FROM audit_log ORDER BY timestamp DESC LIMIT 1")
|
|
889
|
+
.get();
|
|
890
|
+
return row?.timestamp ?? null;
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Query audit entries with optional filters. Returns newest first.
|
|
895
|
+
* Used by `gnosys audit` and `gnosys doctor` reports.
|
|
896
|
+
*/
|
|
897
|
+
queryAuditLog(opts = {}) {
|
|
898
|
+
return this.withRecovery(() => {
|
|
899
|
+
const conditions = [];
|
|
900
|
+
const params = [];
|
|
901
|
+
if (opts.sinceIso) {
|
|
902
|
+
conditions.push("timestamp >= ?");
|
|
903
|
+
params.push(opts.sinceIso);
|
|
904
|
+
}
|
|
905
|
+
if (opts.operation) {
|
|
906
|
+
conditions.push("operation = ?");
|
|
907
|
+
params.push(opts.operation);
|
|
908
|
+
}
|
|
909
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
910
|
+
const limit = opts.limit ? ` LIMIT ${Math.max(1, Math.floor(opts.limit))}` : "";
|
|
911
|
+
return this.db
|
|
912
|
+
.prepare(`SELECT * FROM audit_log ${where} ORDER BY timestamp DESC${limit}`)
|
|
913
|
+
.all(...params);
|
|
914
|
+
});
|
|
807
915
|
}
|
|
808
916
|
// ─── Embeddings ─────────────────────────────────────────────────────
|
|
809
917
|
updateEmbedding(id, embedding) {
|