fivocell 8.12.8 → 8.12.9

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.
@@ -0,0 +1,335 @@
1
+ "use strict";
2
+ /**
3
+ * Claude Code Session Adapter
4
+ *
5
+ * Reads Claude Code session files and history,
6
+ * extracts decisions, tool calls, file changes, and preferences.
7
+ * Converts them to Cell's structured format for the import orchestrator.
8
+ *
9
+ * Session path: ~/.claude/projects/<project>/sessions/<uuid>.jsonl
10
+ * History path: ~/.claude/history.jsonl
11
+ * Format reference: https://code.claude.com/docs/en/claude-directory
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.parseHistoryJsonl = parseHistoryJsonl;
48
+ exports.discoverClaudeSessions = discoverClaudeSessions;
49
+ exports.parseAllClaudeSessions = parseAllClaudeSessions;
50
+ exports.isClaudeInstalled = isClaudeInstalled;
51
+ const fs = __importStar(require("fs"));
52
+ const path = __importStar(require("path"));
53
+ const os = __importStar(require("os"));
54
+ // ─── Path helpers ─────────────────────────────────────────────────────────
55
+ function getClaudeDir() {
56
+ if (process.env.CLAUDE_CONFIG_DIR)
57
+ return process.env.CLAUDE_CONFIG_DIR;
58
+ return path.join(os.homedir(), '.claude');
59
+ }
60
+ function getProjectsDir() {
61
+ return path.join(getClaudeDir(), 'projects');
62
+ }
63
+ function getHistoryPath() {
64
+ return path.join(getClaudeDir(), 'history.jsonl');
65
+ }
66
+ function urlDecodeProjectName(encoded) {
67
+ try {
68
+ return decodeURIComponent(encoded);
69
+ }
70
+ catch {
71
+ // Fallback: remove leading dash and replace dashes with path separators
72
+ return encoded.replace(/^-/, '').replace(/-/g, path.sep);
73
+ }
74
+ }
75
+ // ─── JSONL parser ─────────────────────────────────────────────────────────
76
+ function parseJsonl(filePath) {
77
+ if (!fs.existsSync(filePath))
78
+ return [];
79
+ const content = fs.readFileSync(filePath, 'utf-8');
80
+ const lines = content.split('\n').filter(l => l.trim());
81
+ const results = [];
82
+ for (const line of lines) {
83
+ try {
84
+ results.push(JSON.parse(line));
85
+ }
86
+ catch {
87
+ // skip malformed lines
88
+ }
89
+ }
90
+ return results;
91
+ }
92
+ // ─── Decision detection heuristics ───────────────────────────────────────
93
+ const DECISION_PATTERNS = [
94
+ /\blet's\s+use\b/i,
95
+ /\bswitch\s+to\b/i,
96
+ /\b(don't|do not|never|always)\s+\w+/i,
97
+ /\bgoing\s+with\b/i,
98
+ /\bdecided\s+to\b/i,
99
+ /\bopted\s+for\b/i,
100
+ /\bchose\b/i,
101
+ /\bbetter\s+to\b/i,
102
+ /\brecommend\b/i,
103
+ /\bwe\s+should\b/i,
104
+ /\bprefer\b/i,
105
+ /\buse\s+this\s+instead\b/i,
106
+ /\bmigrate\s+to\b/i,
107
+ /\breplace\s+with\b/i,
108
+ /\bupgrade\s+to\b/i,
109
+ ];
110
+ function detectDecisions(text, sessionId, timestamp) {
111
+ const decisions = [];
112
+ const lines = text.split('\n');
113
+ for (const line of lines) {
114
+ for (const pattern of DECISION_PATTERNS) {
115
+ if (pattern.test(line)) {
116
+ decisions.push({
117
+ text: line.trim().substring(0, 200),
118
+ sessionId,
119
+ timestamp,
120
+ confidence: 'medium',
121
+ });
122
+ break;
123
+ }
124
+ }
125
+ }
126
+ return decisions;
127
+ }
128
+ // ─── Tool identification ─────────────────────────────────────────────────
129
+ const FILE_TOOL_NAMES = new Set(['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash']);
130
+ const WRITE_TOOL_NAMES = new Set(['Write', 'Edit']);
131
+ // ─── Parse a single session file ─────────────────────────────────────────
132
+ function parseSessionFile(filePath, projectEncoded, projectName) {
133
+ const records = parseJsonl(filePath);
134
+ if (records.length === 0)
135
+ return null;
136
+ const sessionId = path.basename(filePath, '.jsonl');
137
+ let model = 'unknown';
138
+ let startTime = '';
139
+ let endTime = '';
140
+ let cwd = '';
141
+ let totalInputTokens = 0;
142
+ let totalOutputTokens = 0;
143
+ const decisions = [];
144
+ const fileChanges = [];
145
+ const toolUses = [];
146
+ const userPrompts = [];
147
+ for (const record of records) {
148
+ if (!startTime || record.timestamp < startTime)
149
+ startTime = record.timestamp;
150
+ if (record.timestamp > endTime)
151
+ endTime = record.timestamp;
152
+ if (record.cwd)
153
+ cwd = record.cwd;
154
+ if (record.type === 'user') {
155
+ const content = record.message?.content;
156
+ if (typeof content === 'string') {
157
+ userPrompts.push(content.substring(0, 500));
158
+ }
159
+ }
160
+ if (record.type === 'assistant' && record.message) {
161
+ if (record.message.model)
162
+ model = record.message.model;
163
+ if (record.message.usage) {
164
+ totalInputTokens += record.message.usage.input_tokens || 0;
165
+ totalOutputTokens += record.message.usage.output_tokens || 0;
166
+ }
167
+ const contentBlocks = record.message.content;
168
+ if (Array.isArray(contentBlocks)) {
169
+ for (const block of contentBlocks) {
170
+ if (block.type === 'text' && block.text) {
171
+ // Extract decisions from text responses
172
+ const textDecisions = detectDecisions(block.text, sessionId, record.timestamp);
173
+ decisions.push(...textDecisions);
174
+ }
175
+ if (block.type === 'tool_use' && block.name) {
176
+ toolUses.push({
177
+ toolName: block.name,
178
+ input: block.input || {},
179
+ sessionId,
180
+ timestamp: record.timestamp,
181
+ isError: false,
182
+ });
183
+ if (FILE_TOOL_NAMES.has(block.name)) {
184
+ const filePath2 = block.input?.file_path
185
+ || block.input?.pattern
186
+ || '';
187
+ if (filePath2) {
188
+ fileChanges.push({
189
+ filePath: filePath2,
190
+ action: WRITE_TOOL_NAMES.has(block.name) ? 'edit' : 'read',
191
+ sessionId,
192
+ timestamp: record.timestamp,
193
+ });
194
+ }
195
+ }
196
+ }
197
+ }
198
+ }
199
+ }
200
+ if (record.type === 'tool_result') {
201
+ // Find the last tool use for this session (reverse iteration)
202
+ let lastToolUse;
203
+ for (let i = toolUses.length - 1; i >= 0; i--) {
204
+ if (toolUses[i].sessionId === sessionId) {
205
+ lastToolUse = toolUses[i];
206
+ break;
207
+ }
208
+ }
209
+ if (lastToolUse) {
210
+ lastToolUse.isError = record.toolUseResult?.is_error || false;
211
+ }
212
+ }
213
+ }
214
+ return {
215
+ sessionId,
216
+ projectName,
217
+ model,
218
+ messageCount: records.length,
219
+ startTime,
220
+ endTime: endTime || startTime,
221
+ totalInputTokens,
222
+ totalOutputTokens,
223
+ decisions,
224
+ fileChanges,
225
+ toolUses,
226
+ userPrompts,
227
+ cwd,
228
+ };
229
+ }
230
+ function parseHistoryJsonl() {
231
+ const entries = parseJsonl(getHistoryPath());
232
+ const projects = new Set();
233
+ let earliest = '';
234
+ let latest = '';
235
+ for (const entry of entries) {
236
+ if (entry.projectPath)
237
+ projects.add(entry.projectPath);
238
+ if (!earliest || entry.timestamp < earliest)
239
+ earliest = entry.timestamp;
240
+ if (entry.timestamp > latest)
241
+ latest = entry.timestamp;
242
+ }
243
+ return {
244
+ entries,
245
+ summary: {
246
+ totalPrompts: entries.length,
247
+ uniqueProjects: [...projects],
248
+ earliestTimestamp: earliest,
249
+ latestTimestamp: latest,
250
+ },
251
+ };
252
+ }
253
+ function discoverClaudeSessions() {
254
+ const projectsDir = getProjectsDir();
255
+ if (!fs.existsSync(projectsDir)) {
256
+ return { projectDirs: [], sessionFiles: [], totalSessions: 0, projects: [] };
257
+ }
258
+ const projectDirs = [];
259
+ const sessionFiles = [];
260
+ const projects = [];
261
+ try {
262
+ const entries = fs.readdirSync(projectsDir, { withFileTypes: true });
263
+ for (const entry of entries) {
264
+ if (!entry.isDirectory())
265
+ continue;
266
+ const projectDir = path.join(projectsDir, entry.name);
267
+ const sessionsDir = path.join(projectDir, 'sessions');
268
+ if (fs.existsSync(sessionsDir)) {
269
+ projectDirs.push(projectDir);
270
+ projects.push(urlDecodeProjectName(entry.name));
271
+ const sessionEntries = fs.readdirSync(sessionsDir);
272
+ for (const se of sessionEntries) {
273
+ if (se.endsWith('.jsonl')) {
274
+ sessionFiles.push(path.join(sessionsDir, se));
275
+ }
276
+ }
277
+ }
278
+ }
279
+ }
280
+ catch {
281
+ // Permission or read error — skip
282
+ }
283
+ return {
284
+ projectDirs,
285
+ sessionFiles,
286
+ totalSessions: sessionFiles.length,
287
+ projects,
288
+ };
289
+ }
290
+ function parseAllClaudeSessions() {
291
+ const discovery = discoverClaudeSessions();
292
+ const sessions = [];
293
+ let totalDecisions = 0;
294
+ let totalFileChanges = 0;
295
+ let totalToolUses = 0;
296
+ // Map encoded dir names to readable project names
297
+ for (const projectDir of discovery.projectDirs) {
298
+ const encodedName = path.basename(projectDir);
299
+ const projectName = urlDecodeProjectName(encodedName);
300
+ const sessionsDir = path.join(projectDir, 'sessions');
301
+ try {
302
+ const files = fs.readdirSync(sessionsDir);
303
+ for (const file of files) {
304
+ if (!file.endsWith('.jsonl'))
305
+ continue;
306
+ const session = parseSessionFile(path.join(sessionsDir, file), encodedName, projectName);
307
+ if (session) {
308
+ sessions.push(session);
309
+ totalDecisions += session.decisions.length;
310
+ totalFileChanges += session.fileChanges.length;
311
+ totalToolUses += session.toolUses.length;
312
+ }
313
+ }
314
+ }
315
+ catch {
316
+ // Skip unreadable directories
317
+ }
318
+ }
319
+ // Parse history
320
+ const { entries, summary } = parseHistoryJsonl();
321
+ return {
322
+ sessions,
323
+ historyEntries: entries,
324
+ historySummary: summary,
325
+ totalDecisions,
326
+ totalFileChanges,
327
+ totalToolUses,
328
+ };
329
+ }
330
+ // ─── Check if Claude Code is installed ───────────────────────────────────
331
+ function isClaudeInstalled() {
332
+ const claudeDir = getClaudeDir();
333
+ return fs.existsSync(claudeDir) && fs.existsSync(path.join(claudeDir, 'projects'));
334
+ }
335
+ //# sourceMappingURL=claude-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-adapter.js","sourceRoot":"","sources":["../../../../../src/walls/07-runtime/import/adapters/claude-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Cell Import Orchestrator
3
+ *
4
+ * Takes structured data from tool adapters (e.g. Claude adapter),
5
+ * converts it to Cell's internal format, and feeds it into the
6
+ * existing memory system: session-memory, memory-event-store,
7
+ * and context-ranker.
8
+ *
9
+ * Principle: Importer = adapter + converter, NOT a new AI.
10
+ * Existing engines (ranker, vibe, decisions) do the heavy lifting.
11
+ */
12
+ export interface ImportSource {
13
+ name: string;
14
+ detected: boolean;
15
+ sessionCount: number;
16
+ decisionCount: number;
17
+ fileChangeCount: number;
18
+ }
19
+ export interface ImportResult {
20
+ success: boolean;
21
+ sources: ImportSource[];
22
+ totalSessionsImported: number;
23
+ totalDecisionsExtracted: number;
24
+ totalFileChangesTracked: number;
25
+ totalMemoryEvents: number;
26
+ errors: string[];
27
+ dryRun: boolean;
28
+ }
29
+ export interface ImportOptions {
30
+ dryRun?: boolean;
31
+ source?: string;
32
+ }
33
+ export declare function detectSources(): ImportSource[];
34
+ export declare function runImport(options?: ImportOptions): Promise<ImportResult>;
35
+ export declare function saveImportTimestamp(): void;
36
+ export declare function getLastImportTimestamp(): string | null;
37
+ //# sourceMappingURL=import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../../../src/walls/07-runtime/import/import.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAcH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,uBAAuB,EAAE,MAAM,CAAC;IAChC,uBAAuB,EAAE,MAAM,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgID,wBAAgB,aAAa,IAAI,YAAY,EAAE,CAyB9C;AAID,wBAAsB,SAAS,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CA2ElF;AAID,wBAAgB,mBAAmB,IAAI,IAAI,CAU1C;AAED,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,IAAI,CAStD"}
@@ -0,0 +1,283 @@
1
+ "use strict";
2
+ /**
3
+ * Cell Import Orchestrator
4
+ *
5
+ * Takes structured data from tool adapters (e.g. Claude adapter),
6
+ * converts it to Cell's internal format, and feeds it into the
7
+ * existing memory system: session-memory, memory-event-store,
8
+ * and context-ranker.
9
+ *
10
+ * Principle: Importer = adapter + converter, NOT a new AI.
11
+ * Existing engines (ranker, vibe, decisions) do the heavy lifting.
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.detectSources = detectSources;
48
+ exports.runImport = runImport;
49
+ exports.saveImportTimestamp = saveImportTimestamp;
50
+ exports.getLastImportTimestamp = getLastImportTimestamp;
51
+ const fs = __importStar(require("fs"));
52
+ const path = __importStar(require("path"));
53
+ const os = __importStar(require("os"));
54
+ const database_1 = require("../../06-memory/database/database");
55
+ const claude_adapter_1 = require("./adapters/claude-adapter");
56
+ // ─── Feed session into Cell memory ───────────────────────────────────────
57
+ function importClaudeSession(session, projectCwd) {
58
+ const db = (0, database_1.getDb)();
59
+ const projectName = projectCwd
60
+ ? path.basename(projectCwd)
61
+ : session.projectName || 'imported';
62
+ let memoryEvents = 0;
63
+ let decisions = 0;
64
+ // 1. Record each decision as a memory event
65
+ for (const dec of session.decisions) {
66
+ try {
67
+ const { recordMemoryEvent } = require('../../06-memory/stores/memory-event-store');
68
+ recordMemoryEvent({
69
+ project: projectName,
70
+ type: 'decision',
71
+ topic: 'imported',
72
+ summary: `[import:claude] ${dec.text.substring(0, 200)}`,
73
+ importance: dec.confidence === 'high' ? 8 : dec.confidence === 'medium' ? 6 : 4,
74
+ details: { source: 'claude', sessionId: session.sessionId, timestamp: dec.timestamp },
75
+ tags: ['import', 'claude', 'decision'],
76
+ });
77
+ memoryEvents++;
78
+ decisions++;
79
+ }
80
+ catch { }
81
+ }
82
+ // 2. Record tool usage patterns as memory events
83
+ const toolCounts = new Map();
84
+ for (const tu of session.toolUses) {
85
+ toolCounts.set(tu.toolName, (toolCounts.get(tu.toolName) || 0) + 1);
86
+ }
87
+ for (const [toolName, count] of toolCounts) {
88
+ try {
89
+ const { recordMemoryEvent } = require('../../06-memory/stores/memory-event-store');
90
+ recordMemoryEvent({
91
+ project: projectName,
92
+ type: 'pattern',
93
+ topic: 'tool_usage',
94
+ summary: `[import:claude] Tool "${toolName}" used ${count}x across ${session.sessionId.substring(0, 8)}…`,
95
+ importance: 5,
96
+ details: { source: 'claude', sessionId: session.sessionId, toolName, count },
97
+ tags: ['import', 'claude', 'tool_usage'],
98
+ });
99
+ memoryEvents++;
100
+ }
101
+ catch { }
102
+ }
103
+ // 3. Record file changes
104
+ const changedFiles = new Map();
105
+ for (const fc of session.fileChanges) {
106
+ changedFiles.set(fc.filePath, (changedFiles.get(fc.filePath) || 0) + 1);
107
+ }
108
+ for (const [filePath2, count] of changedFiles) {
109
+ try {
110
+ const { recordMemoryEvent } = require('../../06-memory/stores/memory-event-store');
111
+ recordMemoryEvent({
112
+ project: projectName,
113
+ type: 'file_event',
114
+ topic: 'imported',
115
+ summary: `[import:claude] File "${filePath2}" touched ${count}x`,
116
+ importance: 3,
117
+ details: { source: 'claude', sessionId: session.sessionId, filePath: filePath2, count },
118
+ tags: ['import', 'claude', 'file_event'],
119
+ });
120
+ memoryEvents++;
121
+ }
122
+ catch { }
123
+ }
124
+ // 4. Record session summary in the sessions table for context continuity
125
+ try {
126
+ const existing = db.prepare('SELECT id FROM sessions WHERE tool_name = ? AND context_snapshot = ? AND project = ?').get('claude', session.sessionId, projectName);
127
+ if (!existing) {
128
+ db.prepare(`
129
+ INSERT INTO sessions (tool_name, project, start_time, end_time, files_touched, key_decisions, context_snapshot)
130
+ VALUES (?, ?, ?, ?, ?, ?, ?)
131
+ `).run('claude', projectName, session.startTime, session.endTime, JSON.stringify(session.fileChanges.map(fc => fc.filePath)), JSON.stringify(session.decisions.map(d => d.text)), `Imported Claude session ${session.sessionId.substring(0, 8)}… (${session.messageCount} messages, model: ${session.model})`);
132
+ // Record as memory event too
133
+ try {
134
+ const { recordMemoryEvent } = require('../../06-memory/stores/memory-event-store');
135
+ recordMemoryEvent({
136
+ project: projectName,
137
+ type: 'session',
138
+ topic: 'imported',
139
+ summary: `[import:claude] Session ${session.sessionId.substring(0, 8)}… (${session.messageCount} msgs, ${session.totalInputTokens + session.totalOutputTokens} tokens)`,
140
+ importance: 5,
141
+ details: {
142
+ source: 'claude',
143
+ sessionId: session.sessionId,
144
+ model: session.model,
145
+ messageCount: session.messageCount,
146
+ inputTokens: session.totalInputTokens,
147
+ outputTokens: session.totalOutputTokens,
148
+ toolUses: session.toolUses.length,
149
+ decisions: session.decisions.length,
150
+ fileChanges: session.fileChanges.length,
151
+ },
152
+ tags: ['import', 'claude', 'session'],
153
+ });
154
+ memoryEvents++;
155
+ }
156
+ catch { }
157
+ }
158
+ }
159
+ catch { }
160
+ return { memoryEvents, decisions };
161
+ }
162
+ // ─── Detect all importable sources ───────────────────────────────────────
163
+ function detectSources() {
164
+ const sources = [];
165
+ // Claude Code
166
+ const claudeInstalled = (0, claude_adapter_1.isClaudeInstalled)();
167
+ let claudeSessions = 0;
168
+ if (claudeInstalled) {
169
+ try {
170
+ const { discoverClaudeSessions } = require('./adapters/claude-adapter');
171
+ const discovery = discoverClaudeSessions();
172
+ claudeSessions = discovery.totalSessions;
173
+ }
174
+ catch { }
175
+ }
176
+ sources.push({
177
+ name: 'claude',
178
+ detected: claudeInstalled,
179
+ sessionCount: claudeSessions,
180
+ decisionCount: 0,
181
+ fileChangeCount: 0,
182
+ });
183
+ // Future: add more sources here (cursor, codex, windsurf, gemini)
184
+ // sources.push({ name: 'cursor', detected: false, sessionCount: 0, ... });
185
+ return sources;
186
+ }
187
+ // ─── Run import ──────────────────────────────────────────────────────────
188
+ async function runImport(options = {}) {
189
+ const errors = [];
190
+ let totalSessionsImported = 0;
191
+ let totalDecisionsExtracted = 0;
192
+ let totalFileChangesTracked = 0;
193
+ let totalMemoryEvents = 0;
194
+ const sources = [];
195
+ const cwd = process.cwd();
196
+ // ─── Claude import ─────────────────────────────────────────────────
197
+ if (!options.source || options.source === 'claude') {
198
+ if ((0, claude_adapter_1.isClaudeInstalled)()) {
199
+ try {
200
+ const parsed = (0, claude_adapter_1.parseAllClaudeSessions)();
201
+ if (options.dryRun) {
202
+ sources.push({
203
+ name: 'claude',
204
+ detected: true,
205
+ sessionCount: parsed.sessions.length,
206
+ decisionCount: parsed.totalDecisions,
207
+ fileChangeCount: parsed.totalFileChanges,
208
+ });
209
+ }
210
+ else {
211
+ let sessionImported = 0;
212
+ let decisionsExtracted = 0;
213
+ let fileChangesTracked = 0;
214
+ let memoryEvents = 0;
215
+ for (const session of parsed.sessions) {
216
+ try {
217
+ const result = importClaudeSession(session, cwd);
218
+ sessionImported++;
219
+ decisionsExtracted += result.decisions;
220
+ memoryEvents += result.memoryEvents;
221
+ fileChangesTracked += session.fileChanges.length;
222
+ }
223
+ catch (e) {
224
+ errors.push(`claude: session ${session.sessionId}: ${String(e)}`);
225
+ }
226
+ }
227
+ sources.push({
228
+ name: 'claude',
229
+ detected: true,
230
+ sessionCount: sessionImported,
231
+ decisionCount: decisionsExtracted,
232
+ fileChangeCount: fileChangesTracked,
233
+ });
234
+ totalSessionsImported += sessionImported;
235
+ totalDecisionsExtracted += decisionsExtracted;
236
+ totalFileChangesTracked += fileChangesTracked;
237
+ totalMemoryEvents += memoryEvents;
238
+ }
239
+ }
240
+ catch (e) {
241
+ errors.push(`claude: import failed: ${String(e)}`);
242
+ sources.push({ name: 'claude', detected: true, sessionCount: 0, decisionCount: 0, fileChangeCount: 0 });
243
+ }
244
+ }
245
+ else {
246
+ sources.push({ name: 'claude', detected: false, sessionCount: 0, decisionCount: 0, fileChangeCount: 0 });
247
+ }
248
+ }
249
+ // ─── Future: add more source imports here ──────────────────────────
250
+ return {
251
+ success: errors.length === 0,
252
+ sources,
253
+ totalSessionsImported,
254
+ totalDecisionsExtracted,
255
+ totalFileChangesTracked,
256
+ totalMemoryEvents,
257
+ errors,
258
+ dryRun: !!options.dryRun,
259
+ };
260
+ }
261
+ // ─── Sync timestamp tracking ─────────────────────────────────────────────
262
+ function saveImportTimestamp() {
263
+ try {
264
+ const dir = path.join(os.homedir(), '.fivo', 'cell', 'personal');
265
+ if (!fs.existsSync(dir))
266
+ fs.mkdirSync(dir, { recursive: true });
267
+ fs.writeFileSync(path.join(dir, 'import-timestamp.json'), JSON.stringify({ lastImportAt: new Date().toISOString() }, null, 2), 'utf-8');
268
+ }
269
+ catch { }
270
+ }
271
+ function getLastImportTimestamp() {
272
+ try {
273
+ const filePath = path.join(os.homedir(), '.fivo', 'cell', 'personal', 'import-timestamp.json');
274
+ if (!fs.existsSync(filePath))
275
+ return null;
276
+ const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
277
+ return data.lastImportAt || null;
278
+ }
279
+ catch {
280
+ return null;
281
+ }
282
+ }
283
+ //# sourceMappingURL=import.js.map