mnueron 0.3.0 → 0.4.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 +123 -1
- package/dashboard/index.html +38 -0
- package/dist/cli.js +1187 -1
- package/dist/cli.js.map +1 -1
- package/dist/dashboard/server.js +95 -0
- package/dist/dashboard/server.js.map +1 -1
- package/dist/detectors/claude_desktop.js +79 -22
- package/dist/detectors/claude_desktop.js.map +1 -1
- package/dist/import/claude_cowork.js +359 -0
- package/dist/import/claude_cowork.js.map +1 -0
- package/dist/import/claude_desktop.js +196 -0
- package/dist/import/claude_desktop.js.map +1 -0
- package/dist/store/consolidator.js +168 -0
- package/dist/store/consolidator.js.map +1 -0
- package/dist/store/entity-extractor.js +283 -0
- package/dist/store/entity-extractor.js.map +1 -0
- package/dist/store/entity-resolver.js +378 -0
- package/dist/store/entity-resolver.js.map +1 -0
- package/dist/store/local.js +522 -14
- package/dist/store/local.js.map +1 -1
- package/dist/store/procedural.js +328 -0
- package/dist/store/procedural.js.map +1 -0
- package/dist/store/relation-extractor.js +292 -0
- package/dist/store/relation-extractor.js.map +1 -0
- package/dist/store/remote.js +182 -20
- package/dist/store/remote.js.map +1 -1
- package/dist/tools.js +84 -0
- package/dist/tools.js.map +1 -1
- package/dist/watch/cowork.js +137 -0
- package/dist/watch/cowork.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v0.2.6 — Claude Cowork local import.
|
|
3
|
+
*
|
|
4
|
+
* Cowork ("local agent mode") is the desktop variant of Claude that the
|
|
5
|
+
* non-developer "Cowork" mode runs on. Under the hood it's the Claude Code
|
|
6
|
+
* runtime, which writes one JSONL transcript per session into a folder
|
|
7
|
+
* whose name encodes the session's cwd.
|
|
8
|
+
*
|
|
9
|
+
* On disk these transcripts live under one of several roots depending on
|
|
10
|
+
* how the Claude desktop app was installed and the OS:
|
|
11
|
+
*
|
|
12
|
+
* - ~/.claude/projects/<encoded-cwd>/<sessionUuid>.jsonl
|
|
13
|
+
* (regular Claude Code or non-Store Claude Desktop installs)
|
|
14
|
+
*
|
|
15
|
+
* - %LOCALAPPDATA%\Packages\Claude_<sfx>\LocalCache\Roaming\Claude\
|
|
16
|
+
* local-agent-mode-sessions\**\.claude\projects\
|
|
17
|
+
* <encoded-cwd>\<sessionUuid>.jsonl
|
|
18
|
+
* OR more directly
|
|
19
|
+
* %LOCALAPPDATA%\Packages\Claude_<sfx>\LocalCache\Roaming\Claude\
|
|
20
|
+
* local-agent-mode-sessions\**\<sessionUuid>.jsonl
|
|
21
|
+
* (Microsoft Store install — Store sandboxes %APPDATA% writes into
|
|
22
|
+
* the package folder)
|
|
23
|
+
*
|
|
24
|
+
* To stay robust to wherever Cowork actually writes, we recursively walk
|
|
25
|
+
* a list of candidate roots looking for *.jsonl files. Each file is then
|
|
26
|
+
* sniffed: it counts as a Cowork transcript when the cwd recorded in the
|
|
27
|
+
* file contains `local-agent-mode-sessions`.
|
|
28
|
+
*
|
|
29
|
+
* Each session becomes ONE memory containing the flattened transcript.
|
|
30
|
+
* The mnueron chunker (LocalProvider.save/bulkSave) automatically splits
|
|
31
|
+
* long transcripts per-turn for granular recall.
|
|
32
|
+
*
|
|
33
|
+
* Triggered from the CLI: `mnueron import --claude-cowork`
|
|
34
|
+
*/
|
|
35
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
36
|
+
import { homedir, platform } from 'node:os';
|
|
37
|
+
import { join } from 'node:path';
|
|
38
|
+
const MAX_TRANSCRIPT_CHARS = 10_000_000; // chunker splits per-turn; cap just prevents runaway
|
|
39
|
+
const MAX_WALK_DEPTH = 10; // safety cap on recursion
|
|
40
|
+
const COWORK_MARKER = 'local-agent-mode-sessions';
|
|
41
|
+
/**
|
|
42
|
+
* Roots to walk on this platform.
|
|
43
|
+
*
|
|
44
|
+
* Order matters only for the `projectsDir` "primary" hint. We still walk
|
|
45
|
+
* every existing root and merge the sessions found.
|
|
46
|
+
*/
|
|
47
|
+
function candidateRoots() {
|
|
48
|
+
const home = homedir();
|
|
49
|
+
const roots = [];
|
|
50
|
+
// Universal: ~/.claude/projects/
|
|
51
|
+
roots.push(join(home, '.claude', 'projects'));
|
|
52
|
+
switch (platform()) {
|
|
53
|
+
case 'win32': {
|
|
54
|
+
const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
|
|
55
|
+
const localApp = process.env.LOCALAPPDATA ?? join(home, 'AppData', 'Local');
|
|
56
|
+
// Non-Store install location for the cowork agent root.
|
|
57
|
+
roots.push(join(appdata, 'Claude', 'local-agent-mode-sessions'));
|
|
58
|
+
roots.push(join(appdata, 'AnthropicClaude', 'local-agent-mode-sessions'));
|
|
59
|
+
// Microsoft Store sandboxed location. The package suffix isn't stable,
|
|
60
|
+
// so we glob the Packages directory for any Claude*\LocalCache\Roaming
|
|
61
|
+
// \Claude\local-agent-mode-sessions folder.
|
|
62
|
+
const packagesDir = join(localApp, 'Packages');
|
|
63
|
+
if (existsSync(packagesDir)) {
|
|
64
|
+
try {
|
|
65
|
+
for (const name of readdirSync(packagesDir)) {
|
|
66
|
+
if (!name.toLowerCase().startsWith('claude') &&
|
|
67
|
+
!name.toLowerCase().startsWith('anthropic')) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
roots.push(join(packagesDir, name, 'LocalCache', 'Roaming', 'Claude', 'local-agent-mode-sessions'));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
/* ignore unreadable Packages dir */
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case 'darwin':
|
|
80
|
+
// ~/Library/Application Support/Claude/local-agent-mode-sessions/
|
|
81
|
+
roots.push(join(home, 'Library', 'Application Support', 'Claude', 'local-agent-mode-sessions'), join(home, 'Library', 'Application Support', 'AnthropicClaude', 'local-agent-mode-sessions'));
|
|
82
|
+
break;
|
|
83
|
+
case 'linux':
|
|
84
|
+
roots.push(join(home, '.config', 'Claude', 'local-agent-mode-sessions'), join(home, '.config', 'AnthropicClaude', 'local-agent-mode-sessions'));
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
return roots;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Locate every Cowork session transcript reachable from this machine.
|
|
91
|
+
* Read-only — does not import anything.
|
|
92
|
+
*/
|
|
93
|
+
export function probeClaudeCowork() {
|
|
94
|
+
const attempted = candidateRoots();
|
|
95
|
+
const scanned = [];
|
|
96
|
+
const sessions = [];
|
|
97
|
+
for (const root of attempted) {
|
|
98
|
+
if (!existsSync(root))
|
|
99
|
+
continue;
|
|
100
|
+
scanned.push(root);
|
|
101
|
+
walkForJsonl(root, 0, (filePath) => {
|
|
102
|
+
try {
|
|
103
|
+
const fileStat = statSync(filePath);
|
|
104
|
+
if (!fileStat.isFile() || fileStat.size < 50)
|
|
105
|
+
return;
|
|
106
|
+
const info = quickScan(filePath);
|
|
107
|
+
// Only keep files that look like cowork transcripts (cwd marker).
|
|
108
|
+
if (info.messageCount === 0)
|
|
109
|
+
return;
|
|
110
|
+
if (!info.cwd.includes(COWORK_MARKER))
|
|
111
|
+
return;
|
|
112
|
+
const base = filePath.split(/[\\/]/).pop() ?? '';
|
|
113
|
+
sessions.push({
|
|
114
|
+
sessionId: base.replace(/\.jsonl$/, ''),
|
|
115
|
+
filePath,
|
|
116
|
+
cwd: info.cwd,
|
|
117
|
+
title: info.title,
|
|
118
|
+
messageCount: info.messageCount,
|
|
119
|
+
mtimeMs: fileStat.mtimeMs,
|
|
120
|
+
sizeBytes: fileStat.size,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
/* unreadable — skip */
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
// Dedup by sessionId — the same transcript can show up under multiple roots
|
|
129
|
+
// (e.g., a symlinked or sandboxed copy).
|
|
130
|
+
const dedup = new Map();
|
|
131
|
+
for (const s of sessions) {
|
|
132
|
+
const prev = dedup.get(s.sessionId);
|
|
133
|
+
if (!prev || s.mtimeMs > prev.mtimeMs)
|
|
134
|
+
dedup.set(s.sessionId, s);
|
|
135
|
+
}
|
|
136
|
+
const final = [...dedup.values()].sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
137
|
+
const out = {
|
|
138
|
+
found: final.length > 0,
|
|
139
|
+
projectsDir: scanned[0] ?? null,
|
|
140
|
+
scannedRoots: scanned,
|
|
141
|
+
pathsAttempted: attempted,
|
|
142
|
+
sessions: final,
|
|
143
|
+
hints: [],
|
|
144
|
+
};
|
|
145
|
+
if (final.length > 0) {
|
|
146
|
+
out.hints.push(`Found ${final.length} Cowork session(s) across ${scanned.length} root(s).`);
|
|
147
|
+
}
|
|
148
|
+
else if (scanned.length === 0) {
|
|
149
|
+
out.hints.push('None of the candidate Cowork roots existed on this machine.', 'On Windows the Microsoft Store install lives under', '%LOCALAPPDATA%\\Packages\\Claude_<sfx>\\LocalCache\\Roaming\\Claude\\local-agent-mode-sessions\\.', 'If you have a non-default install location, point us at it:', ' mnueron import --claude-cowork --dir <path>');
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
out.hints.push(`Walked ${scanned.length} root(s) but found no Cowork session transcripts.`, 'A .jsonl file qualifies as Cowork when the cwd it records contains', `"${COWORK_MARKER}". Run a Cowork chat once and re-try.`);
|
|
153
|
+
}
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Recursively walk `dir` up to MAX_WALK_DEPTH levels and call `onFile` for
|
|
158
|
+
* each `.jsonl` we find. Doesn't follow symlinks, swallows perm errors.
|
|
159
|
+
*/
|
|
160
|
+
function walkForJsonl(dir, depth, onFile) {
|
|
161
|
+
if (depth > MAX_WALK_DEPTH)
|
|
162
|
+
return;
|
|
163
|
+
let entries;
|
|
164
|
+
try {
|
|
165
|
+
entries = readdirSync(dir);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
for (const name of entries) {
|
|
171
|
+
const p = join(dir, name);
|
|
172
|
+
let st;
|
|
173
|
+
try {
|
|
174
|
+
st = statSync(p);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (st.isDirectory()) {
|
|
180
|
+
walkForJsonl(p, depth + 1, onFile);
|
|
181
|
+
}
|
|
182
|
+
else if (st.isFile() && name.endsWith('.jsonl')) {
|
|
183
|
+
onFile(p);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Pass over a transcript counting human-readable turns and grabbing the
|
|
189
|
+
* latest ai-title + cwd. Skips internal-state records.
|
|
190
|
+
*/
|
|
191
|
+
function quickScan(filePath) {
|
|
192
|
+
const raw = readFileSync(filePath, 'utf8');
|
|
193
|
+
let title;
|
|
194
|
+
let cwd = '';
|
|
195
|
+
let messageCount = 0;
|
|
196
|
+
for (const line of raw.split('\n')) {
|
|
197
|
+
if (!line.trim())
|
|
198
|
+
continue;
|
|
199
|
+
let obj;
|
|
200
|
+
try {
|
|
201
|
+
obj = JSON.parse(line);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (obj.type === 'user' || obj.type === 'assistant') {
|
|
207
|
+
messageCount++;
|
|
208
|
+
if (!cwd && typeof obj.cwd === 'string')
|
|
209
|
+
cwd = obj.cwd;
|
|
210
|
+
}
|
|
211
|
+
else if (obj.type === 'ai-title' && typeof obj.aiTitle === 'string') {
|
|
212
|
+
title = obj.aiTitle;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return { title, cwd, messageCount };
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Convert one Cowork transcript file into a SaveMemoryInput. Returns an
|
|
219
|
+
* empty array if there are no human-readable turns.
|
|
220
|
+
*/
|
|
221
|
+
export function importFromCoworkSession(filePath, namespace, sessionMeta) {
|
|
222
|
+
const raw = readFileSync(filePath, 'utf8');
|
|
223
|
+
const turns = [];
|
|
224
|
+
for (const line of raw.split('\n')) {
|
|
225
|
+
if (!line.trim())
|
|
226
|
+
continue;
|
|
227
|
+
let obj;
|
|
228
|
+
try {
|
|
229
|
+
obj = JSON.parse(line);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (obj.type === 'user') {
|
|
235
|
+
const text = extractUserText(obj.message);
|
|
236
|
+
if (text)
|
|
237
|
+
turns.push({ role: 'user', text, ts: obj.timestamp });
|
|
238
|
+
}
|
|
239
|
+
else if (obj.type === 'assistant') {
|
|
240
|
+
const text = extractAssistantText(obj.message);
|
|
241
|
+
if (text)
|
|
242
|
+
turns.push({ role: 'assistant', text, ts: obj.timestamp });
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (turns.length === 0)
|
|
246
|
+
return [];
|
|
247
|
+
const parts = [];
|
|
248
|
+
const titleLine = sessionMeta.title
|
|
249
|
+
? `# ${sessionMeta.title}`
|
|
250
|
+
: `# Cowork session ${sessionMeta.sessionId}`;
|
|
251
|
+
parts.push(titleLine);
|
|
252
|
+
if (turns[0]?.ts)
|
|
253
|
+
parts.push(`(${turns[0].ts})`);
|
|
254
|
+
parts.push('');
|
|
255
|
+
for (const t of turns) {
|
|
256
|
+
parts.push(`**${t.role === 'assistant' ? 'Claude' : 'User'}:** ${t.text}`);
|
|
257
|
+
parts.push('');
|
|
258
|
+
}
|
|
259
|
+
let content = parts.join('\n').trim();
|
|
260
|
+
if (content.length > MAX_TRANSCRIPT_CHARS) {
|
|
261
|
+
content = content.slice(0, MAX_TRANSCRIPT_CHARS) +
|
|
262
|
+
`\n\n[truncated — original ${content.length} chars]`;
|
|
263
|
+
}
|
|
264
|
+
return [{
|
|
265
|
+
content,
|
|
266
|
+
namespace,
|
|
267
|
+
source: 'claude-cowork',
|
|
268
|
+
source_ref: `cowork:${sessionMeta.sessionId}`,
|
|
269
|
+
tags: ['imported', 'claude-cowork'],
|
|
270
|
+
metadata: {
|
|
271
|
+
title: sessionMeta.title ?? null,
|
|
272
|
+
session_id: sessionMeta.sessionId,
|
|
273
|
+
cwd: sessionMeta.cwd,
|
|
274
|
+
message_count: turns.length,
|
|
275
|
+
first_timestamp: turns[0]?.ts ?? null,
|
|
276
|
+
last_timestamp: turns[turns.length - 1]?.ts ?? null,
|
|
277
|
+
},
|
|
278
|
+
}];
|
|
279
|
+
}
|
|
280
|
+
function extractUserText(message) {
|
|
281
|
+
if (!message)
|
|
282
|
+
return '';
|
|
283
|
+
if (typeof message.content === 'string')
|
|
284
|
+
return message.content.trim();
|
|
285
|
+
if (Array.isArray(message.content)) {
|
|
286
|
+
return message.content
|
|
287
|
+
.filter((b) => b?.type === 'text' && typeof b.text === 'string')
|
|
288
|
+
.map((b) => b.text)
|
|
289
|
+
.join('\n')
|
|
290
|
+
.trim();
|
|
291
|
+
}
|
|
292
|
+
return '';
|
|
293
|
+
}
|
|
294
|
+
function extractAssistantText(message) {
|
|
295
|
+
if (!message || !Array.isArray(message.content))
|
|
296
|
+
return '';
|
|
297
|
+
// Skip thinking blocks (internal reasoning) and tool_use blocks (mostly noise
|
|
298
|
+
// in memory). Keep only `text` blocks — these are what the human actually saw.
|
|
299
|
+
return message.content
|
|
300
|
+
.filter((b) => b?.type === 'text' && typeof b.text === 'string')
|
|
301
|
+
.map((b) => b.text)
|
|
302
|
+
.join('\n')
|
|
303
|
+
.trim();
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Probe + import every Cowork session into mnueron. Idempotent via
|
|
307
|
+
* `source_ref` dedup — re-running just re-upserts.
|
|
308
|
+
*/
|
|
309
|
+
export async function autoImport(provider, namespace, opts = {}) {
|
|
310
|
+
const probe = probeClaudeCowork();
|
|
311
|
+
if (!probe.found || probe.sessions.length === 0) {
|
|
312
|
+
throw new Error('No Cowork sessions found. ' +
|
|
313
|
+
'Run Cowork at least once first, then try again.');
|
|
314
|
+
}
|
|
315
|
+
const sessions = opts.limit && opts.limit > 0
|
|
316
|
+
? probe.sessions.slice(0, opts.limit)
|
|
317
|
+
: probe.sessions;
|
|
318
|
+
let parsed = 0;
|
|
319
|
+
let empty = 0;
|
|
320
|
+
let errors = 0;
|
|
321
|
+
let saved = 0;
|
|
322
|
+
const items = [];
|
|
323
|
+
for (const s of sessions) {
|
|
324
|
+
try {
|
|
325
|
+
const sessionItems = importFromCoworkSession(s.filePath, namespace, {
|
|
326
|
+
sessionId: s.sessionId,
|
|
327
|
+
title: s.title,
|
|
328
|
+
cwd: s.cwd,
|
|
329
|
+
});
|
|
330
|
+
if (sessionItems.length === 0) {
|
|
331
|
+
empty++;
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
items.push(...sessionItems);
|
|
335
|
+
parsed++;
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
errors++;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (!opts.dryRun && items.length > 0) {
|
|
342
|
+
const result = await provider.bulkSave(items);
|
|
343
|
+
saved = result.saved;
|
|
344
|
+
errors += result.errors;
|
|
345
|
+
}
|
|
346
|
+
return {
|
|
347
|
+
totalSessions: probe.sessions.length,
|
|
348
|
+
parsed,
|
|
349
|
+
empty,
|
|
350
|
+
saved,
|
|
351
|
+
errors,
|
|
352
|
+
sessions: sessions.map((s) => ({
|
|
353
|
+
sessionId: s.sessionId,
|
|
354
|
+
title: s.title,
|
|
355
|
+
messageCount: s.messageCount,
|
|
356
|
+
})),
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=claude_cowork.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude_cowork.js","sourceRoot":"","sources":["../../src/import/claude_cowork.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v0.2.5 — Claude Desktop local import.
|
|
3
|
+
*
|
|
4
|
+
* Claude Desktop is an Electron app. Its on-disk format is undocumented
|
|
5
|
+
* and has changed across versions (Local Storage / IndexedDB / SQLite
|
|
6
|
+
* variants depending on Electron + Anthropic's app shape). Cracking the
|
|
7
|
+
* live cache is fragile.
|
|
8
|
+
*
|
|
9
|
+
* Stable path that works on every version: Claude's built-in
|
|
10
|
+
* Settings → Privacy → Export data feature outputs a JSON file with all
|
|
11
|
+
* conversations. This module:
|
|
12
|
+
*
|
|
13
|
+
* 1. PROBE mode: locate the Claude Desktop folder and list what's
|
|
14
|
+
* there. Useful for the user to discover where their data lives
|
|
15
|
+
* and for us to add format-specific parsers as we see real data.
|
|
16
|
+
*
|
|
17
|
+
* 2. IMPORT mode: ingest a JSON export file (the one from
|
|
18
|
+
* Settings → Privacy → Export). Same `importClaudeExport()` path
|
|
19
|
+
* as the regular CLI's `mnueron import --claude`.
|
|
20
|
+
*
|
|
21
|
+
* 3. AUTO mode: try to find a recently-downloaded Claude export under
|
|
22
|
+
* ~/Downloads, ~/Desktop, or the Claude config folder itself. If
|
|
23
|
+
* one is found, import it. Otherwise, fall through to PROBE and
|
|
24
|
+
* print instructions for getting one.
|
|
25
|
+
*
|
|
26
|
+
* Why not crack the cache: Electron's leveldb data is unstable across
|
|
27
|
+
* minor versions, varies by platform, and Anthropic changes shape
|
|
28
|
+
* without notice. The JSON export is a documented API surface and
|
|
29
|
+
* survives version bumps.
|
|
30
|
+
*/
|
|
31
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
32
|
+
import { homedir, platform } from 'node:os';
|
|
33
|
+
import { join } from 'node:path';
|
|
34
|
+
import { importClaudeExport } from './claude.js';
|
|
35
|
+
/**
|
|
36
|
+
* Walk all the standard Claude Desktop folder locations and return what's
|
|
37
|
+
* there + heuristic hints. Doesn't read or modify anything — read-only
|
|
38
|
+
* inspection.
|
|
39
|
+
*/
|
|
40
|
+
export function probeClaudeDesktop() {
|
|
41
|
+
const attempted = standardPaths();
|
|
42
|
+
const found = attempted.find((p) => existsSync(p)) ?? null;
|
|
43
|
+
const out = {
|
|
44
|
+
found: !!found,
|
|
45
|
+
path: found,
|
|
46
|
+
pathsAttempted: attempted,
|
|
47
|
+
contents: [],
|
|
48
|
+
hints: [],
|
|
49
|
+
exportCandidates: [],
|
|
50
|
+
};
|
|
51
|
+
if (!found) {
|
|
52
|
+
out.hints.push('Claude Desktop folder not found at any standard location.', 'Install Claude Desktop from https://claude.ai/download first.', 'If you have it installed under a non-default path, point us at it:', ' mnueron import --claude-desktop --dir <path>');
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
// Top-level listing
|
|
56
|
+
for (const name of readdirSync(found)) {
|
|
57
|
+
try {
|
|
58
|
+
const p = join(found, name);
|
|
59
|
+
const stat = statSync(p);
|
|
60
|
+
out.contents.push({
|
|
61
|
+
name,
|
|
62
|
+
type: stat.isDirectory() ? 'dir' : 'file',
|
|
63
|
+
size: stat.isFile() ? stat.size : undefined,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
/* permission denied or symlink loop — skip */
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Heuristic hints based on what's there
|
|
71
|
+
const has = (n) => out.contents.some((c) => c.name === n);
|
|
72
|
+
if (has('Local Storage'))
|
|
73
|
+
out.hints.push('• Local Storage/ — Electron localStorage (leveldb)');
|
|
74
|
+
if (has('IndexedDB'))
|
|
75
|
+
out.hints.push('• IndexedDB/ — conversations likely stored here in newer builds');
|
|
76
|
+
if (has('Preferences'))
|
|
77
|
+
out.hints.push('• Preferences — app config JSON (settings only, no chats)');
|
|
78
|
+
if (has('Session Storage'))
|
|
79
|
+
out.hints.push('• Session Storage/ — short-lived per-session data');
|
|
80
|
+
if (has('Cache') || has('Code Cache')) {
|
|
81
|
+
out.hints.push('• Cache/ Code Cache/ — HTTP + V8 caches (skip; no chat data)');
|
|
82
|
+
}
|
|
83
|
+
// Probe for an export JSON file in the Claude folder itself
|
|
84
|
+
out.exportCandidates.push(...findExportCandidates(found));
|
|
85
|
+
// Also check Downloads + Desktop, since that's where the export
|
|
86
|
+
// dialog usually drops the file.
|
|
87
|
+
const home = homedir();
|
|
88
|
+
for (const folder of [join(home, 'Downloads'), join(home, 'Desktop')]) {
|
|
89
|
+
if (existsSync(folder)) {
|
|
90
|
+
out.exportCandidates.push(...findExportCandidates(folder));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (out.exportCandidates.length > 0) {
|
|
94
|
+
out.hints.push(`Found ${out.exportCandidates.length} candidate export file(s) — see exportCandidates below.`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
out.hints.push('No Claude export JSON found yet. To create one:', ' 1. Open Claude Desktop', ' 2. Settings → Privacy → Export data', ' 3. Save the resulting JSON to your Downloads folder', ' 4. Re-run: mnueron import --claude-desktop');
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Heuristic: a Claude export file is a `.json` that contains either
|
|
103
|
+
* `"chat_messages"` or `"conversations"` near the top + was modified in
|
|
104
|
+
* the last 90 days. We don't fully parse here — just enough to flag.
|
|
105
|
+
*/
|
|
106
|
+
function findExportCandidates(dir) {
|
|
107
|
+
const hits = [];
|
|
108
|
+
try {
|
|
109
|
+
const ninetyDaysAgo = Date.now() - 90 * 24 * 3600 * 1000;
|
|
110
|
+
for (const name of readdirSync(dir)) {
|
|
111
|
+
if (!name.toLowerCase().endsWith('.json'))
|
|
112
|
+
continue;
|
|
113
|
+
const p = join(dir, name);
|
|
114
|
+
try {
|
|
115
|
+
const stat = statSync(p);
|
|
116
|
+
if (!stat.isFile() || stat.size < 200 || stat.mtimeMs < ninetyDaysAgo)
|
|
117
|
+
continue;
|
|
118
|
+
// Sniff: read the first 8 KB and look for tell-tale keys. Avoids
|
|
119
|
+
// parsing massive files just to reject them.
|
|
120
|
+
const fd = readFileSync(p, { encoding: 'utf8', flag: 'r' }).slice(0, 8192);
|
|
121
|
+
if (fd.includes('"chat_messages"') ||
|
|
122
|
+
fd.includes('"conversations"') ||
|
|
123
|
+
(fd.includes('"sender"') && fd.includes('"human"'))) {
|
|
124
|
+
hits.push(p);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch { /* unreadable — skip */ }
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch { /* dir not readable */ }
|
|
131
|
+
return hits;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Import a Claude Desktop export JSON file. Delegates to the existing
|
|
135
|
+
* importClaudeExport() — same format as `mnueron import --claude` for
|
|
136
|
+
* web exports.
|
|
137
|
+
*/
|
|
138
|
+
export async function importFromExportFile(filePath, namespace) {
|
|
139
|
+
if (!existsSync(filePath)) {
|
|
140
|
+
throw new Error(`export file not found: ${filePath}`);
|
|
141
|
+
}
|
|
142
|
+
return importClaudeExport(filePath, namespace);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Auto-find a recent export JSON and import it. Returns the import
|
|
146
|
+
* result + the resolved path. If nothing's found, throws so the caller
|
|
147
|
+
* can fall back to probe + manual guidance.
|
|
148
|
+
*/
|
|
149
|
+
export async function autoImport(provider, namespace) {
|
|
150
|
+
const probe = probeClaudeDesktop();
|
|
151
|
+
if (probe.exportCandidates.length === 0) {
|
|
152
|
+
throw new Error('No Claude Desktop export JSON found. ' +
|
|
153
|
+
'Open Claude Desktop → Settings → Privacy → Export data, ' +
|
|
154
|
+
'save the JSON, then re-run this command.');
|
|
155
|
+
}
|
|
156
|
+
// Pick the newest by mtime
|
|
157
|
+
const newest = probe.exportCandidates
|
|
158
|
+
.map((p) => ({ p, m: statSync(p).mtimeMs }))
|
|
159
|
+
.sort((a, b) => b.m - a.m)[0].p;
|
|
160
|
+
const items = await importFromExportFile(newest, namespace);
|
|
161
|
+
const result = await provider.bulkSave(items);
|
|
162
|
+
return { path: newest, ...result };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Default-location paths for Claude Desktop's user data folder per OS.
|
|
166
|
+
* The first one that exists wins. If your install is non-standard,
|
|
167
|
+
* pass `--dir <path>` to the CLI subcommand.
|
|
168
|
+
*/
|
|
169
|
+
function standardPaths() {
|
|
170
|
+
const home = homedir();
|
|
171
|
+
switch (platform()) {
|
|
172
|
+
case 'darwin':
|
|
173
|
+
return [
|
|
174
|
+
join(home, 'Library', 'Application Support', 'Claude'),
|
|
175
|
+
join(home, 'Library', 'Application Support', 'AnthropicClaude'),
|
|
176
|
+
];
|
|
177
|
+
case 'win32': {
|
|
178
|
+
const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
|
|
179
|
+
const localApp = process.env.LOCALAPPDATA ?? join(home, 'AppData', 'Local');
|
|
180
|
+
return [
|
|
181
|
+
join(appdata, 'Claude'),
|
|
182
|
+
join(appdata, 'AnthropicClaude'),
|
|
183
|
+
join(localApp, 'Claude'),
|
|
184
|
+
join(localApp, 'AnthropicClaude'),
|
|
185
|
+
];
|
|
186
|
+
}
|
|
187
|
+
case 'linux':
|
|
188
|
+
return [
|
|
189
|
+
join(home, '.config', 'Claude'),
|
|
190
|
+
join(home, '.config', 'AnthropicClaude'),
|
|
191
|
+
];
|
|
192
|
+
default:
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=claude_desktop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude_desktop.js","sourceRoot":"","sources":["../../src/import/claude_desktop.ts"],"names":[],"mappings":"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"}
|