mnueron 0.2.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 +186 -2
- 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 +666 -17
- 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
|
@@ -1,37 +1,94 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
1
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
2
2
|
import { homedir, platform } from 'node:os';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { JsonMcpDetector } from './json_detector.js';
|
|
5
|
+
/**
|
|
6
|
+
* Where Claude Desktop's `claude_desktop_config.json` lives, by OS.
|
|
7
|
+
*
|
|
8
|
+
* On Windows there are two install shapes to consider:
|
|
9
|
+
*
|
|
10
|
+
* - Traditional (.exe / installer): config at
|
|
11
|
+
* %APPDATA%\Claude\claude_desktop_config.json
|
|
12
|
+
* - Microsoft Store install: every %APPDATA% write the app makes is
|
|
13
|
+
* redirected by the Store to:
|
|
14
|
+
* %LOCALAPPDATA%\Packages\Claude_<sfx>\LocalCache\Roaming\Claude\
|
|
15
|
+
* claude_desktop_config.json
|
|
16
|
+
*
|
|
17
|
+
* The earlier detector only looked at the traditional path, so users with
|
|
18
|
+
* the Microsoft Store install saw "Claude Desktop not detected." We now
|
|
19
|
+
* check both and pick the first one that exists (or whose parent dir does,
|
|
20
|
+
* which catches "installed but never launched after install").
|
|
21
|
+
*/
|
|
5
22
|
export class ClaudeDesktopDetector extends JsonMcpDetector {
|
|
6
23
|
id = 'claude-desktop';
|
|
7
24
|
displayName = 'Claude Desktop';
|
|
8
25
|
configPath() {
|
|
26
|
+
const candidates = this.candidatePaths();
|
|
27
|
+
if (candidates.length === 0)
|
|
28
|
+
return null;
|
|
29
|
+
for (const p of candidates) {
|
|
30
|
+
if (existsSync(p))
|
|
31
|
+
return p;
|
|
32
|
+
const dir = p.replace(/[/\\]claude_desktop_config\.json$/, '');
|
|
33
|
+
if (existsSync(dir))
|
|
34
|
+
return p;
|
|
35
|
+
}
|
|
36
|
+
return candidates[0] ?? null;
|
|
37
|
+
}
|
|
38
|
+
isInstalled() {
|
|
39
|
+
for (const p of this.candidatePaths()) {
|
|
40
|
+
if (existsSync(p))
|
|
41
|
+
return true;
|
|
42
|
+
const dir = p.replace(/[/\\]claude_desktop_config\.json$/, '');
|
|
43
|
+
if (existsSync(dir))
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Every place Claude Desktop's config has been observed to land, ordered
|
|
50
|
+
* by preference. Order matters: configPath() returns the first existing
|
|
51
|
+
* one.
|
|
52
|
+
*/
|
|
53
|
+
candidatePaths() {
|
|
9
54
|
const home = homedir();
|
|
55
|
+
const out = [];
|
|
10
56
|
switch (platform()) {
|
|
11
57
|
case 'darwin':
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
58
|
+
out.push(join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'));
|
|
59
|
+
out.push(join(home, 'Library', 'Application Support', 'AnthropicClaude', 'claude_desktop_config.json'));
|
|
60
|
+
break;
|
|
61
|
+
case 'win32': {
|
|
62
|
+
const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
|
|
63
|
+
const localApp = process.env.LOCALAPPDATA ?? join(home, 'AppData', 'Local');
|
|
64
|
+
out.push(join(appdata, 'Claude', 'claude_desktop_config.json'));
|
|
65
|
+
out.push(join(appdata, 'AnthropicClaude', 'claude_desktop_config.json'));
|
|
66
|
+
// Microsoft Store install — Store redirects %APPDATA% writes into
|
|
67
|
+
// the package's LocalCache\Roaming. Package suffix isn't stable, so
|
|
68
|
+
// we glob Packages\Claude* and Packages\Anthropic*.
|
|
69
|
+
const packagesDir = join(localApp, 'Packages');
|
|
70
|
+
if (existsSync(packagesDir)) {
|
|
71
|
+
try {
|
|
72
|
+
for (const name of readdirSync(packagesDir)) {
|
|
73
|
+
const lower = name.toLowerCase();
|
|
74
|
+
if (!lower.startsWith('claude') && !lower.startsWith('anthropic'))
|
|
75
|
+
continue;
|
|
76
|
+
out.push(join(packagesDir, name, 'LocalCache', 'Roaming', 'Claude', 'claude_desktop_config.json'));
|
|
77
|
+
out.push(join(packagesDir, name, 'LocalCache', 'Roaming', 'AnthropicClaude', 'claude_desktop_config.json'));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* unreadable Packages dir — skip Store paths */
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
15
86
|
case 'linux':
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
87
|
+
out.push(join(home, '.config', 'Claude', 'claude_desktop_config.json'));
|
|
88
|
+
out.push(join(home, '.config', 'AnthropicClaude', 'claude_desktop_config.json'));
|
|
89
|
+
break;
|
|
19
90
|
}
|
|
20
|
-
|
|
21
|
-
isInstalled() {
|
|
22
|
-
// We treat presence of the config dir OR the app itself as "installed."
|
|
23
|
-
// On Windows the app folder is %LOCALAPPDATA%\Programs\Claude. We check
|
|
24
|
-
// for either to avoid false negatives for users who configured but never
|
|
25
|
-
// launched, or who launched but on a system without the typical path.
|
|
26
|
-
const path = this.configPath();
|
|
27
|
-
if (!path)
|
|
28
|
-
return false;
|
|
29
|
-
if (existsSync(path))
|
|
30
|
-
return true;
|
|
31
|
-
// Check the directory's parent — if Claude Desktop has run at least once
|
|
32
|
-
// it creates this folder.
|
|
33
|
-
const dir = path.replace(/[\/\\]claude_desktop_config\.json$/, '');
|
|
34
|
-
return existsSync(dir);
|
|
91
|
+
return out;
|
|
35
92
|
}
|
|
36
93
|
}
|
|
37
94
|
//# sourceMappingURL=claude_desktop.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude_desktop.js","sourceRoot":"","sources":["../../src/detectors/claude_desktop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"claude_desktop.js","sourceRoot":"","sources":["../../src/detectors/claude_desktop.ts"],"names":[],"mappings":"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"}
|
|
@@ -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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"}
|