nlm-memory 0.4.2 → 0.5.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/dist/cli/nlm.js +221 -32
- package/dist/cli/nlm.js.map +1 -1
- package/dist/core/adapters/cursor.d.ts +45 -0
- package/dist/core/adapters/cursor.js +397 -0
- package/dist/core/adapters/cursor.js.map +1 -0
- package/dist/core/adapters/from-source.js +10 -0
- package/dist/core/adapters/from-source.js.map +1 -1
- package/dist/core/adapters/windsurf.d.ts +44 -0
- package/dist/core/adapters/windsurf.js +299 -0
- package/dist/core/adapters/windsurf.js.map +1 -0
- package/dist/core/hook/claude-settings.d.ts +12 -5
- package/dist/core/hook/claude-settings.js +21 -6
- package/dist/core/hook/claude-settings.js.map +1 -1
- package/dist/core/sources/source-registry.d.ts +1 -1
- package/dist/core/sources/source-registry.js +18 -0
- package/dist/core/sources/source-registry.js.map +1 -1
- package/dist/core/storage/sqlite-session-store.d.ts +2 -0
- package/dist/core/storage/sqlite-session-store.js +38 -2
- package/dist/core/storage/sqlite-session-store.js.map +1 -1
- package/dist/hook/hook-auth.d.ts +13 -0
- package/dist/hook/hook-auth.js +19 -0
- package/dist/hook/hook-auth.js.map +1 -0
- package/dist/hook/prompt-recall-hook.js +7 -1
- package/dist/hook/prompt-recall-hook.js.map +1 -1
- package/dist/hook/session-start-hook.js +4 -1
- package/dist/hook/session-start-hook.js.map +1 -1
- package/dist/hook/stop-hook.js +4 -1
- package/dist/hook/stop-hook.js.map +1 -1
- package/dist/http/app.d.ts +2 -0
- package/dist/http/app.js +74 -0
- package/dist/http/app.js.map +1 -1
- package/dist/install/claude-code.js +1 -1
- package/dist/install/claude-code.js.map +1 -1
- package/dist/install/cursor.d.ts +25 -0
- package/dist/install/cursor.js +43 -0
- package/dist/install/cursor.js.map +1 -0
- package/dist/install/nlm-dir-perms.d.ts +19 -0
- package/dist/install/nlm-dir-perms.js +43 -0
- package/dist/install/nlm-dir-perms.js.map +1 -0
- package/dist/install/ollama.d.ts +18 -1
- package/dist/install/ollama.js +62 -7
- package/dist/install/ollama.js.map +1 -1
- package/dist/install/setup.d.ts +4 -0
- package/dist/install/setup.js +141 -18
- package/dist/install/setup.js.map +1 -1
- package/dist/install/windsurf.d.ts +25 -0
- package/dist/install/windsurf.js +43 -0
- package/dist/install/windsurf.js.map +1 -0
- package/dist/shared/types.d.ts +4 -0
- package/dist/ui/assets/{index-BA6IpU8g.css → index-C8cpwbYJ.css} +1 -1
- package/dist/ui/assets/index-CB50QnL-.js +69 -0
- package/dist/ui/index.html +2 -2
- package/logs/CHANGELOG/CHANGELOG-2026.md +186 -0
- package/logs/CHANGELOG/CHANGELOG.md +107 -235
- package/migrations/014_sources_cursor.sql +30 -0
- package/migrations/015_sources_windsurf.sql +30 -0
- package/package.json +1 -1
- package/plugin/scripts/prompt-recall-hook.mjs +55 -4
- package/plugin/scripts/stop-hook.mjs +57 -6
- package/src/cli/nlm.ts +224 -31
- package/src/core/adapters/cursor.ts +486 -0
- package/src/core/adapters/from-source.ts +10 -0
- package/src/core/adapters/windsurf.ts +386 -0
- package/src/core/hook/claude-settings.ts +30 -9
- package/src/core/sources/source-registry.ts +19 -1
- package/src/core/storage/sqlite-session-store.ts +46 -1
- package/src/hook/hook-auth.ts +18 -0
- package/src/hook/prompt-recall-hook.ts +7 -1
- package/src/hook/session-start-hook.ts +4 -1
- package/src/hook/stop-hook.ts +4 -1
- package/src/http/app.ts +78 -0
- package/src/install/claude-code.ts +1 -1
- package/src/install/cursor.ts +68 -0
- package/src/install/nlm-dir-perms.ts +55 -0
- package/src/install/ollama.ts +80 -7
- package/src/install/setup.ts +138 -17
- package/src/install/windsurf.ts +68 -0
- package/src/shared/types.ts +4 -0
- package/src/ui/components/SessionDrawer.tsx +97 -34
- package/src/ui/pages/River.tsx +90 -44
- package/src/ui/pages/Search.tsx +357 -64
- package/src/ui/pages/Thread.tsx +267 -56
- package/src/ui/styles.css +129 -5
- package/tests/integration/getbyids-sqlite.test.ts +40 -0
- package/tests/integration/hook-claude-settings.test.ts +14 -1
- package/tests/integration/mcp.test.ts +12 -0
- package/tests/integration/source-registry.test.ts +5 -3
- package/tests/unit/core/adapters/cursor.test.ts +485 -0
- package/tests/unit/core/adapters/windsurf.test.ts +416 -0
- package/dist/ui/assets/index-B_qIVV0k.js +0 -69
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WindsurfAdapter — reads Windsurf (Codeium Cascade) sessions.
|
|
3
|
+
*
|
|
4
|
+
* ## Storage locations (macOS; Linux uses ~/.config/)
|
|
5
|
+
*
|
|
6
|
+
* Workspace DBs ~/Library/Application Support/Windsurf/User/workspaceStorage/<hash>/state.vscdb
|
|
7
|
+
* Table: ItemTable
|
|
8
|
+
* Key: workbench.panel.aichat.view.aichat.chatdata — chat tabs
|
|
9
|
+
* Bubble role: type 'user' → user, type 'ai' → assistant
|
|
10
|
+
*
|
|
11
|
+
* Global DB ~/Library/Application Support/Windsurf/User/globalStorage/state.vscdb
|
|
12
|
+
* Table: cursorDiskKV (if present) — composerData:*, agentData:*, flowData:*
|
|
13
|
+
* Table: ItemTable (fallback) — keys matching %agent%, %flow%, %cascade%
|
|
14
|
+
* Conversation format: type 1/2 (user/assistant) or role: user/assistant
|
|
15
|
+
*
|
|
16
|
+
* ## Session ID prefixes
|
|
17
|
+
*
|
|
18
|
+
* ws_ — workspace chat tab (ItemTable chatdata)
|
|
19
|
+
* wsg_ — global DB agent/flow session (cursorDiskKV or ItemTable)
|
|
20
|
+
*
|
|
21
|
+
* ## pathOrUrl in source registry
|
|
22
|
+
* Path to the Windsurf User directory. The adapter discovers:
|
|
23
|
+
* <userDir>/workspaceStorage/<hash>/state.vscdb (workspace)
|
|
24
|
+
* <userDir>/globalStorage/state.vscdb (global)
|
|
25
|
+
*
|
|
26
|
+
* Env override: NLM_WINDSURF_USER_DIR
|
|
27
|
+
*/
|
|
28
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
29
|
+
import { homedir } from "node:os";
|
|
30
|
+
import { join } from "node:path";
|
|
31
|
+
import Database from "better-sqlite3";
|
|
32
|
+
import { durationMinutes, normalizeTimestamp, safeSessionId } from "./common.js";
|
|
33
|
+
const CHAT_KEY = "workbench.panel.aichat.view.aichat.chatdata";
|
|
34
|
+
// ── Path helpers ──────────────────────────────────────────────────────────────
|
|
35
|
+
export function defaultUserDir() {
|
|
36
|
+
if (process.env["NLM_WINDSURF_USER_DIR"])
|
|
37
|
+
return process.env["NLM_WINDSURF_USER_DIR"];
|
|
38
|
+
const home = homedir();
|
|
39
|
+
if (process.platform === "darwin") {
|
|
40
|
+
return join(home, "Library/Application Support/Windsurf/User");
|
|
41
|
+
}
|
|
42
|
+
return join(home, ".config/Windsurf/User");
|
|
43
|
+
}
|
|
44
|
+
function workspaceStorageDir(userDir) {
|
|
45
|
+
return join(userDir, "workspaceStorage");
|
|
46
|
+
}
|
|
47
|
+
function globalDbPath(userDir) {
|
|
48
|
+
return join(userDir, "globalStorage", "state.vscdb");
|
|
49
|
+
}
|
|
50
|
+
function listWorkspaceDbs(userDir) {
|
|
51
|
+
const wsDir = workspaceStorageDir(userDir);
|
|
52
|
+
if (!existsSync(wsDir))
|
|
53
|
+
return [];
|
|
54
|
+
try {
|
|
55
|
+
return readdirSync(wsDir, { withFileTypes: true })
|
|
56
|
+
.filter((e) => e.isDirectory())
|
|
57
|
+
.map((e) => join(wsDir, e.name, "state.vscdb"))
|
|
58
|
+
.filter((p) => existsSync(p));
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// ── Turn extraction ───────────────────────────────────────────────────────────
|
|
65
|
+
function extractChatTurns(bubbles) {
|
|
66
|
+
const turns = [];
|
|
67
|
+
for (const b of bubbles) {
|
|
68
|
+
const text = (b.rawText ?? b.text ?? "").trim();
|
|
69
|
+
if (!text)
|
|
70
|
+
continue;
|
|
71
|
+
turns.push({ role: b.type === "user" ? "user" : "assistant", text });
|
|
72
|
+
}
|
|
73
|
+
return turns;
|
|
74
|
+
}
|
|
75
|
+
function extractAgentTurns(bubbles) {
|
|
76
|
+
const turns = [];
|
|
77
|
+
for (const b of bubbles) {
|
|
78
|
+
const text = (b.text ?? "").trim();
|
|
79
|
+
if (!text)
|
|
80
|
+
continue;
|
|
81
|
+
// Accept numeric type (1/2) or string role
|
|
82
|
+
const isUser = b.type === 1 || b.role === "user";
|
|
83
|
+
const isAssistant = b.type === 2 || b.role === "assistant";
|
|
84
|
+
if (!isUser && !isAssistant)
|
|
85
|
+
continue;
|
|
86
|
+
turns.push({ role: isUser ? "user" : "assistant", text });
|
|
87
|
+
}
|
|
88
|
+
return turns;
|
|
89
|
+
}
|
|
90
|
+
function provisionalLabel(turns) {
|
|
91
|
+
for (const t of turns) {
|
|
92
|
+
if (t.role !== "user")
|
|
93
|
+
continue;
|
|
94
|
+
const first = t.text.split("\n", 1)[0]?.trim();
|
|
95
|
+
if (first)
|
|
96
|
+
return first.slice(0, 80);
|
|
97
|
+
}
|
|
98
|
+
return "Untitled session";
|
|
99
|
+
}
|
|
100
|
+
function buildChunk(id, runtimeSessionId, sourcePath, turns, startedAt, endedAt, label) {
|
|
101
|
+
const text = turns.map((t) => `${t.role}: ${t.text}`).join("\n\n");
|
|
102
|
+
return {
|
|
103
|
+
id,
|
|
104
|
+
runtime: "windsurf/1.0",
|
|
105
|
+
runtimeSessionId,
|
|
106
|
+
sourcePath,
|
|
107
|
+
startedAt,
|
|
108
|
+
endedAt,
|
|
109
|
+
durationMin: durationMinutes(startedAt, endedAt),
|
|
110
|
+
turnCount: turns.length,
|
|
111
|
+
byteRange: [0, Buffer.byteLength(text, "utf8")],
|
|
112
|
+
projectDir: "",
|
|
113
|
+
gitBranch: "",
|
|
114
|
+
text,
|
|
115
|
+
label,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// ── Workspace chat helpers ────────────────────────────────────────────────────
|
|
119
|
+
function parseTabsFromDb(dbPath) {
|
|
120
|
+
let db;
|
|
121
|
+
try {
|
|
122
|
+
db = new Database(dbPath, { readonly: true });
|
|
123
|
+
const row = db
|
|
124
|
+
.prepare(`SELECT key, value FROM ItemTable WHERE key = ?`)
|
|
125
|
+
.get(CHAT_KEY);
|
|
126
|
+
if (!row?.value)
|
|
127
|
+
return [];
|
|
128
|
+
const data = JSON.parse(row.value);
|
|
129
|
+
return Array.isArray(data.tabs) ? data.tabs : [];
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
db?.close();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function parseGlobalSessions(globalPath) {
|
|
139
|
+
if (!existsSync(globalPath))
|
|
140
|
+
return [];
|
|
141
|
+
let db;
|
|
142
|
+
const results = [];
|
|
143
|
+
try {
|
|
144
|
+
db = new Database(globalPath, { readonly: true });
|
|
145
|
+
const tables = db
|
|
146
|
+
.prepare(`SELECT name FROM sqlite_master WHERE type='table'`)
|
|
147
|
+
.all()
|
|
148
|
+
.map((r) => r.name);
|
|
149
|
+
if (tables.includes("cursorDiskKV")) {
|
|
150
|
+
const rows = db
|
|
151
|
+
.prepare(`SELECT key, value FROM cursorDiskKV
|
|
152
|
+
WHERE key LIKE 'composerData:%' OR key LIKE 'agentData:%' OR key LIKE 'flowData:%'
|
|
153
|
+
ORDER BY rowid ASC`)
|
|
154
|
+
.all();
|
|
155
|
+
for (const row of rows) {
|
|
156
|
+
if (!row.value)
|
|
157
|
+
continue;
|
|
158
|
+
try {
|
|
159
|
+
const meta = JSON.parse(row.value);
|
|
160
|
+
const rawId = meta.composerId ?? row.key.split(":").slice(1).join(":");
|
|
161
|
+
if (rawId)
|
|
162
|
+
results.push({ id: rawId, meta, dbPath: globalPath });
|
|
163
|
+
}
|
|
164
|
+
catch { /* skip */ }
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else if (tables.includes("ItemTable")) {
|
|
168
|
+
// Fallback: probe for agent/flow/cascade keys
|
|
169
|
+
const rows = db
|
|
170
|
+
.prepare(`SELECT key, value FROM ItemTable
|
|
171
|
+
WHERE key LIKE '%agent%' OR key LIKE '%flow%' OR key LIKE '%cascade%'`)
|
|
172
|
+
.all();
|
|
173
|
+
for (const row of rows) {
|
|
174
|
+
if (!row.value)
|
|
175
|
+
continue;
|
|
176
|
+
try {
|
|
177
|
+
const data = JSON.parse(row.value);
|
|
178
|
+
if (typeof data !== "object" || !data)
|
|
179
|
+
continue;
|
|
180
|
+
// Accept any object with a conversation array
|
|
181
|
+
const conv = data.conversation;
|
|
182
|
+
if (!Array.isArray(conv) || conv.length === 0)
|
|
183
|
+
continue;
|
|
184
|
+
const id = data.composerId ?? row.key;
|
|
185
|
+
results.push({ id, meta: data, dbPath: globalPath });
|
|
186
|
+
}
|
|
187
|
+
catch { /* skip */ }
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch { /* inaccessible */ }
|
|
192
|
+
finally {
|
|
193
|
+
db?.close();
|
|
194
|
+
}
|
|
195
|
+
return results;
|
|
196
|
+
}
|
|
197
|
+
// ── Adapter ───────────────────────────────────────────────────────────────────
|
|
198
|
+
export class WindsurfAdapter {
|
|
199
|
+
name = "windsurf";
|
|
200
|
+
runtimeVersion = "windsurf/1.0";
|
|
201
|
+
transcriptKind = "windsurf-sqlite";
|
|
202
|
+
userDir;
|
|
203
|
+
constructor(opts = {}) {
|
|
204
|
+
this.userDir = opts.userDir ?? defaultUserDir();
|
|
205
|
+
}
|
|
206
|
+
detect() {
|
|
207
|
+
if (existsSync(this.userDir)) {
|
|
208
|
+
return { adapterName: this.name, enabled: true, path: this.userDir, hint: null };
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
adapterName: this.name,
|
|
212
|
+
enabled: false,
|
|
213
|
+
path: null,
|
|
214
|
+
hint: "Windsurf User directory not found — install Windsurf or set NLM_WINDSURF_USER_DIR.",
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
async discover(options) {
|
|
218
|
+
const seen = new Set();
|
|
219
|
+
const ids = [];
|
|
220
|
+
const add = (id) => { if (!seen.has(id)) {
|
|
221
|
+
seen.add(id);
|
|
222
|
+
ids.push(id);
|
|
223
|
+
} };
|
|
224
|
+
const cutoff = options?.since?.getTime();
|
|
225
|
+
// ── Workspace chat tabs ───────────────────────────────────────────────
|
|
226
|
+
for (const dbPath of listWorkspaceDbs(this.userDir)) {
|
|
227
|
+
for (const tab of parseTabsFromDb(dbPath)) {
|
|
228
|
+
if (!tab.tabId)
|
|
229
|
+
continue;
|
|
230
|
+
if (!(tab.bubbles && tab.bubbles.length > 0))
|
|
231
|
+
continue;
|
|
232
|
+
if (cutoff !== undefined) {
|
|
233
|
+
const ts = tab.lastSendTime;
|
|
234
|
+
// Only skip when we have a real non-zero timestamp older than the cutoff.
|
|
235
|
+
// Missing (undefined) or zero timestamps are treated as "unknown age" — include.
|
|
236
|
+
if (ts !== undefined && ts > 0 && ts < cutoff)
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
add(`ws_${tab.tabId}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// ── Global agent/flow sessions ────────────────────────────────────────
|
|
243
|
+
for (const gs of parseGlobalSessions(globalDbPath(this.userDir))) {
|
|
244
|
+
if (cutoff !== undefined) {
|
|
245
|
+
const ts = gs.meta.lastUpdatedAt ?? gs.meta.createdAt;
|
|
246
|
+
if (ts !== undefined && ts !== null) {
|
|
247
|
+
const normalized = normalizeTimestamp(ts);
|
|
248
|
+
if (normalized && Date.parse(normalized) < cutoff)
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
add(`wsg_${gs.id}`);
|
|
253
|
+
}
|
|
254
|
+
return ids;
|
|
255
|
+
}
|
|
256
|
+
async parseSession(id) {
|
|
257
|
+
if (id.startsWith("wsg_")) {
|
|
258
|
+
return this._parseGlobalSession(id.slice("wsg_".length));
|
|
259
|
+
}
|
|
260
|
+
// ws_ prefix or legacy plain tabId
|
|
261
|
+
const tabId = id.startsWith("ws_") ? id.slice("ws_".length) : id;
|
|
262
|
+
return this._parseWorkspaceChatTab(tabId);
|
|
263
|
+
}
|
|
264
|
+
_parseWorkspaceChatTab(tabId) {
|
|
265
|
+
for (const dbPath of listWorkspaceDbs(this.userDir)) {
|
|
266
|
+
const tabs = parseTabsFromDb(dbPath);
|
|
267
|
+
const tab = tabs.find((t) => t.tabId === tabId);
|
|
268
|
+
if (!tab)
|
|
269
|
+
continue;
|
|
270
|
+
const turns = extractChatTurns(tab.bubbles ?? []);
|
|
271
|
+
if (turns.length === 0)
|
|
272
|
+
return null;
|
|
273
|
+
const endedAtMs = tab.lastSendTime ?? 0;
|
|
274
|
+
const endedAt = endedAtMs > 0 ? new Date(endedAtMs).toISOString() : "";
|
|
275
|
+
const label = tab.chatTitle?.trim()
|
|
276
|
+
? tab.chatTitle.trim().slice(0, 80)
|
|
277
|
+
: provisionalLabel(turns);
|
|
278
|
+
return buildChunk(safeSessionId("ws", tabId), tabId, `${dbPath}::${tabId}`, turns, endedAt, endedAt, label);
|
|
279
|
+
}
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
_parseGlobalSession(rawId) {
|
|
283
|
+
for (const gs of parseGlobalSessions(globalDbPath(this.userDir))) {
|
|
284
|
+
if (gs.id !== rawId)
|
|
285
|
+
continue;
|
|
286
|
+
const turns = extractAgentTurns(gs.meta.conversation ?? []);
|
|
287
|
+
if (turns.length === 0)
|
|
288
|
+
return null;
|
|
289
|
+
const startedAt = normalizeTimestamp(gs.meta.createdAt ?? gs.meta.lastUpdatedAt ?? "");
|
|
290
|
+
const endedAt = normalizeTimestamp(gs.meta.lastUpdatedAt ?? gs.meta.createdAt ?? "");
|
|
291
|
+
const label = gs.meta.name?.trim()
|
|
292
|
+
? gs.meta.name.trim().slice(0, 80)
|
|
293
|
+
: provisionalLabel(turns);
|
|
294
|
+
return buildChunk(safeSessionId("wsg", rawId), rawId, `${gs.dbPath}::${rawId}`, turns, startedAt, endedAt, label);
|
|
295
|
+
}
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=windsurf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windsurf.js","sourceRoot":"","sources":["../../../src/core/adapters/windsurf.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,17 +12,24 @@
|
|
|
12
12
|
* and node receives the wrong argv — silent hook bricking.
|
|
13
13
|
*/
|
|
14
14
|
export declare function shellQuote(arg: string): string;
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Double-quote a cmd.exe argument. Embedded double quotes are doubled per
|
|
17
|
+
* cmd.exe parsing rules. Used for hook commands on Windows where Claude
|
|
18
|
+
* Code dispatches via cmd.exe /c rather than sh -c.
|
|
19
|
+
*/
|
|
20
|
+
export declare function cmdQuote(arg: string): string;
|
|
21
|
+
export declare function buildHookCommand(execPath: string, hookJs: string, mode: "shadow" | "live", targetPlatform?: NodeJS.Platform): string;
|
|
16
22
|
export interface SmokeTestResult {
|
|
17
23
|
readonly ok: boolean;
|
|
18
24
|
readonly reason?: string;
|
|
19
25
|
readonly stderr?: string;
|
|
20
26
|
}
|
|
21
27
|
/**
|
|
22
|
-
* Invoke the wired command exactly the way Claude Code does (sh -c
|
|
23
|
-
* JSON on stdin
|
|
24
|
-
* class of failures where settings.json
|
|
25
|
-
* at startup (path tokenization, missing
|
|
28
|
+
* Invoke the wired command exactly the way Claude Code does (sh -c on
|
|
29
|
+
* POSIX, cmd.exe /c on Windows) with JSON on stdin and confirm the hook
|
|
30
|
+
* log gained an entry. Catches the class of failures where settings.json
|
|
31
|
+
* looks valid but the hook fails at startup (path tokenization, missing
|
|
32
|
+
* modules, missing shell, etc.).
|
|
26
33
|
*/
|
|
27
34
|
export declare function smokeTestHookCommand(command: string, hookLogPath: string, timeoutMs?: number): SmokeTestResult;
|
|
28
35
|
export type ClaudeHookEvent = "UserPromptSubmit" | "SessionStart" | "SessionEnd" | "Stop" | "PreCompact" | "SubagentStart" | "PostToolUse" | "PreToolUse";
|
|
@@ -28,18 +28,33 @@ const HOOK_SCRIPT_MARKERS = [
|
|
|
28
28
|
export function shellQuote(arg) {
|
|
29
29
|
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
30
30
|
}
|
|
31
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Double-quote a cmd.exe argument. Embedded double quotes are doubled per
|
|
33
|
+
* cmd.exe parsing rules. Used for hook commands on Windows where Claude
|
|
34
|
+
* Code dispatches via cmd.exe /c rather than sh -c.
|
|
35
|
+
*/
|
|
36
|
+
export function cmdQuote(arg) {
|
|
37
|
+
return `"${arg.replace(/"/g, '""')}"`;
|
|
38
|
+
}
|
|
39
|
+
export function buildHookCommand(execPath, hookJs, mode, targetPlatform = process.platform) {
|
|
40
|
+
if (targetPlatform === "win32") {
|
|
41
|
+
// cmd.exe: `set VAR=val && "exec" "script"`. The set is scoped to the
|
|
42
|
+
// cmd /c invocation so the env var is visible to the chained child.
|
|
43
|
+
return `set NLM_HOOK_MODE=${mode} && ${cmdQuote(execPath)} ${cmdQuote(hookJs)}`;
|
|
44
|
+
}
|
|
32
45
|
return `NLM_HOOK_MODE=${mode} ${shellQuote(execPath)} ${shellQuote(hookJs)}`;
|
|
33
46
|
}
|
|
34
47
|
/**
|
|
35
|
-
* Invoke the wired command exactly the way Claude Code does (sh -c
|
|
36
|
-
* JSON on stdin
|
|
37
|
-
* class of failures where settings.json
|
|
38
|
-
* at startup (path tokenization, missing
|
|
48
|
+
* Invoke the wired command exactly the way Claude Code does (sh -c on
|
|
49
|
+
* POSIX, cmd.exe /c on Windows) with JSON on stdin and confirm the hook
|
|
50
|
+
* log gained an entry. Catches the class of failures where settings.json
|
|
51
|
+
* looks valid but the hook fails at startup (path tokenization, missing
|
|
52
|
+
* modules, missing shell, etc.).
|
|
39
53
|
*/
|
|
40
54
|
export function smokeTestHookCommand(command, hookLogPath, timeoutMs = 5000) {
|
|
41
55
|
const sizeBefore = existsSync(hookLogPath) ? statSync(hookLogPath).size : 0;
|
|
42
|
-
const
|
|
56
|
+
const isWin = process.platform === "win32";
|
|
57
|
+
const result = spawnSync(isWin ? "cmd.exe" : "sh", [isWin ? "/c" : "-c", command], {
|
|
43
58
|
input: JSON.stringify({ prompt: "smoke test", session_id: "install-smoke" }),
|
|
44
59
|
timeout: timeoutMs,
|
|
45
60
|
encoding: "utf8",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-settings.js","sourceRoot":"","sources":["../../../src/core/hook/claude-settings.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,qEAAqE;AACrE,uEAAuE;AACvE,gCAAgC;AAChC,MAAM,mBAAmB,GAAG;IAC1B,uBAAuB;IACvB,qBAAqB;IACrB,cAAc;IACd,uBAAuB;IACvB,qBAAqB;IACrB,wBAAwB;CAChB,CAAC;AAEX;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,QAAgB,EAChB,MAAc,EACd,IAAuB;
|
|
1
|
+
{"version":3,"file":"claude-settings.js","sourceRoot":"","sources":["../../../src/core/hook/claude-settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* See docs/plans/desktop-product.md (Phase 0).
|
|
14
14
|
*/
|
|
15
15
|
import type Database from "better-sqlite3";
|
|
16
|
-
export type SourceKind = "claude-code" | "hermes" | "hermes-agent" | "aider" | "opencode" | "pi" | "jsonl-generic" | "webhook";
|
|
16
|
+
export type SourceKind = "claude-code" | "hermes" | "hermes-agent" | "aider" | "cursor" | "windsurf" | "opencode" | "pi" | "jsonl-generic" | "webhook";
|
|
17
17
|
export interface SourceRow {
|
|
18
18
|
readonly id: number;
|
|
19
19
|
readonly kind: SourceKind;
|
|
@@ -17,8 +17,10 @@ import { existsSync } from "node:fs";
|
|
|
17
17
|
import { homedir } from "node:os";
|
|
18
18
|
import { join } from "node:path";
|
|
19
19
|
import { defaultHistoryFile as defaultAiderHistoryFile } from "../adapters/aider.js";
|
|
20
|
+
import { defaultDbPath as defaultCursorDbPath } from "../adapters/cursor.js";
|
|
20
21
|
import { defaultDbPath as defaultHermesAgentDbPath } from "../adapters/hermes-agent.js";
|
|
21
22
|
import { defaultDbPath as defaultOpenCodeDbPath } from "../adapters/opencode.js";
|
|
23
|
+
import { defaultUserDir as defaultWindsurfUserDir } from "../adapters/windsurf.js";
|
|
22
24
|
function rowFromDb(r, revealedToken = null) {
|
|
23
25
|
let parsed = {};
|
|
24
26
|
try {
|
|
@@ -157,6 +159,8 @@ export class SourceRegistry {
|
|
|
157
159
|
const openCodeDbPath = defaultOpenCodeDbPath();
|
|
158
160
|
const hermesAgentDbPath = defaultHermesAgentDbPath();
|
|
159
161
|
const aiderHistoryFile = defaultAiderHistoryFile();
|
|
162
|
+
const cursorDbPath = defaultCursorDbPath();
|
|
163
|
+
const windsurfUserDir = defaultWindsurfUserDir();
|
|
160
164
|
const presets = [
|
|
161
165
|
{
|
|
162
166
|
kind: "claude-code",
|
|
@@ -186,6 +190,20 @@ export class SourceRegistry {
|
|
|
186
190
|
runtimeLabel: "aider/1.0",
|
|
187
191
|
enabled: existsSync(aiderHistoryFile),
|
|
188
192
|
},
|
|
193
|
+
{
|
|
194
|
+
kind: "cursor",
|
|
195
|
+
name: "Cursor",
|
|
196
|
+
pathOrUrl: cursorDbPath,
|
|
197
|
+
runtimeLabel: "cursor/1.0",
|
|
198
|
+
enabled: existsSync(cursorDbPath),
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
kind: "windsurf",
|
|
202
|
+
name: "Windsurf",
|
|
203
|
+
pathOrUrl: windsurfUserDir,
|
|
204
|
+
runtimeLabel: "windsurf/1.0",
|
|
205
|
+
enabled: existsSync(windsurfUserDir),
|
|
206
|
+
},
|
|
189
207
|
{
|
|
190
208
|
kind: "opencode",
|
|
191
209
|
name: "OpenCode",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-registry.js","sourceRoot":"","sources":["../../../src/core/sources/source-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,kBAAkB,IAAI,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,aAAa,IAAI,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACxF,OAAO,EAAE,aAAa,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"source-registry.js","sourceRoot":"","sources":["../../../src/core/sources/source-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -144,9 +144,11 @@ export declare class SqliteSessionStore implements SessionStore {
|
|
|
144
144
|
keywordSearch(query: string, limit: number): Promise<ReadonlyArray<KeywordNeighbor>>;
|
|
145
145
|
updateStatus(sessionId: string, status: SessionStatus): Promise<void>;
|
|
146
146
|
insertSessionForTest(session: Session): void;
|
|
147
|
+
insertEdgeForTest(fromSession: string, toSession: string, kind?: "supersedes" | "continues"): void;
|
|
147
148
|
insertEmbeddingForTest(sessionId: string, vector: Float32Array): void;
|
|
148
149
|
insertChunkEmbeddingForTest(sessionId: string, chunkIdx: number, vector: Float32Array): void;
|
|
149
150
|
private loadEntities;
|
|
151
|
+
private loadSessionEdges;
|
|
150
152
|
private loadMarkers;
|
|
151
153
|
private rowToSession;
|
|
152
154
|
}
|
|
@@ -347,8 +347,9 @@ export class SqliteSessionStore {
|
|
|
347
347
|
return null;
|
|
348
348
|
const entities = this.loadEntities([sessionId]);
|
|
349
349
|
const markers = this.loadMarkers([sessionId]);
|
|
350
|
+
const edges = this.loadSessionEdges([sessionId]);
|
|
350
351
|
const overlay = loadActionOverlay(this.db);
|
|
351
|
-
return this.rowToSession(row, entities, markers, overlay);
|
|
352
|
+
return this.rowToSession(row, entities, markers, overlay, edges);
|
|
352
353
|
}
|
|
353
354
|
/**
|
|
354
355
|
* Batched session fetch for the recall path. Deliberately omits the
|
|
@@ -481,6 +482,11 @@ export class SqliteSessionStore {
|
|
|
481
482
|
session.decisions.forEach((d, i) => markerStmt.run(session.id, "decision", d, i));
|
|
482
483
|
session.open.forEach((q, i) => markerStmt.run(session.id, "open", q, i));
|
|
483
484
|
}
|
|
485
|
+
insertEdgeForTest(fromSession, toSession, kind = "supersedes") {
|
|
486
|
+
this.db
|
|
487
|
+
.prepare("INSERT OR IGNORE INTO session_edges (from_session, to_session, kind) VALUES (?, ?, ?)")
|
|
488
|
+
.run(fromSession, toSession, kind);
|
|
489
|
+
}
|
|
484
490
|
insertEmbeddingForTest(sessionId, vector) {
|
|
485
491
|
this.insertChunkEmbeddingForTest(sessionId, 0, vector);
|
|
486
492
|
}
|
|
@@ -510,6 +516,32 @@ export class SqliteSessionStore {
|
|
|
510
516
|
}
|
|
511
517
|
return out;
|
|
512
518
|
}
|
|
519
|
+
loadSessionEdges(ids) {
|
|
520
|
+
if (ids.length === 0)
|
|
521
|
+
return new Map();
|
|
522
|
+
const placeholders = ids.map(() => "?").join(",");
|
|
523
|
+
const rows = this.db
|
|
524
|
+
.prepare(`
|
|
525
|
+
SELECT from_session, to_session
|
|
526
|
+
FROM session_edges
|
|
527
|
+
WHERE kind = 'supersedes'
|
|
528
|
+
AND (from_session IN (${placeholders}) OR to_session IN (${placeholders}))
|
|
529
|
+
`)
|
|
530
|
+
.all(...ids, ...ids);
|
|
531
|
+
const out = new Map();
|
|
532
|
+
for (const id of ids) {
|
|
533
|
+
out.set(id, { supersededBy: null, supersedes: [] });
|
|
534
|
+
}
|
|
535
|
+
for (const r of rows) {
|
|
536
|
+
const fromEntry = out.get(r.from_session);
|
|
537
|
+
if (fromEntry)
|
|
538
|
+
fromEntry.supersedes.push(r.to_session);
|
|
539
|
+
const toEntry = out.get(r.to_session);
|
|
540
|
+
if (toEntry)
|
|
541
|
+
toEntry.supersededBy = r.from_session;
|
|
542
|
+
}
|
|
543
|
+
return out;
|
|
544
|
+
}
|
|
513
545
|
loadMarkers(ids) {
|
|
514
546
|
if (ids.length === 0)
|
|
515
547
|
return new Map();
|
|
@@ -536,7 +568,7 @@ export class SqliteSessionStore {
|
|
|
536
568
|
}
|
|
537
569
|
return out;
|
|
538
570
|
}
|
|
539
|
-
rowToSession(row, entitiesById, markersById, overlay) {
|
|
571
|
+
rowToSession(row, entitiesById, markersById, overlay, edgesById) {
|
|
540
572
|
const m = markersById.get(row.id);
|
|
541
573
|
const rawDecisions = m?.decisions ?? [];
|
|
542
574
|
const rawOpen = m?.open ?? [];
|
|
@@ -553,6 +585,7 @@ export class SqliteSessionStore {
|
|
|
553
585
|
}
|
|
554
586
|
activeOpen.push(text);
|
|
555
587
|
}
|
|
588
|
+
const edges = edgesById?.get(row.id);
|
|
556
589
|
return {
|
|
557
590
|
id: row.id,
|
|
558
591
|
runtime: row.runtime,
|
|
@@ -569,6 +602,9 @@ export class SqliteSessionStore {
|
|
|
569
602
|
entities: entitiesById.get(row.id) ?? [],
|
|
570
603
|
decisions: [...rawDecisions, ...promotedDecisions],
|
|
571
604
|
open: activeOpen,
|
|
605
|
+
...(edges !== undefined
|
|
606
|
+
? { supersededBy: edges.supersededBy, supersedes: edges.supersedes }
|
|
607
|
+
: {}),
|
|
572
608
|
};
|
|
573
609
|
}
|
|
574
610
|
}
|