cursor-history 0.5.1

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.
Files changed (58) hide show
  1. package/README.md +225 -0
  2. package/dist/cli/commands/export.d.ts +9 -0
  3. package/dist/cli/commands/export.d.ts.map +1 -0
  4. package/dist/cli/commands/export.js +126 -0
  5. package/dist/cli/commands/export.js.map +1 -0
  6. package/dist/cli/commands/list.d.ts +9 -0
  7. package/dist/cli/commands/list.d.ts.map +1 -0
  8. package/dist/cli/commands/list.js +77 -0
  9. package/dist/cli/commands/list.js.map +1 -0
  10. package/dist/cli/commands/search.d.ts +9 -0
  11. package/dist/cli/commands/search.d.ts.map +1 -0
  12. package/dist/cli/commands/search.js +47 -0
  13. package/dist/cli/commands/search.js.map +1 -0
  14. package/dist/cli/commands/show.d.ts +9 -0
  15. package/dist/cli/commands/show.d.ts.map +1 -0
  16. package/dist/cli/commands/show.js +51 -0
  17. package/dist/cli/commands/show.js.map +1 -0
  18. package/dist/cli/formatters/index.d.ts +6 -0
  19. package/dist/cli/formatters/index.d.ts.map +1 -0
  20. package/dist/cli/formatters/index.js +6 -0
  21. package/dist/cli/formatters/index.js.map +1 -0
  22. package/dist/cli/formatters/json.d.ts +28 -0
  23. package/dist/cli/formatters/json.d.ts.map +1 -0
  24. package/dist/cli/formatters/json.js +98 -0
  25. package/dist/cli/formatters/json.js.map +1 -0
  26. package/dist/cli/formatters/table.d.ts +45 -0
  27. package/dist/cli/formatters/table.d.ts.map +1 -0
  28. package/dist/cli/formatters/table.js +439 -0
  29. package/dist/cli/formatters/table.js.map +1 -0
  30. package/dist/cli/index.d.ts +6 -0
  31. package/dist/cli/index.d.ts.map +1 -0
  32. package/dist/cli/index.js +51 -0
  33. package/dist/cli/index.js.map +1 -0
  34. package/dist/core/index.d.ts +7 -0
  35. package/dist/core/index.d.ts.map +1 -0
  36. package/dist/core/index.js +8 -0
  37. package/dist/core/index.js.map +1 -0
  38. package/dist/core/parser.d.ts +38 -0
  39. package/dist/core/parser.d.ts.map +1 -0
  40. package/dist/core/parser.js +324 -0
  41. package/dist/core/parser.js.map +1 -0
  42. package/dist/core/storage.d.ts +45 -0
  43. package/dist/core/storage.d.ts.map +1 -0
  44. package/dist/core/storage.js +869 -0
  45. package/dist/core/storage.js.map +1 -0
  46. package/dist/core/types.d.ts +113 -0
  47. package/dist/core/types.d.ts.map +1 -0
  48. package/dist/core/types.js +6 -0
  49. package/dist/core/types.js.map +1 -0
  50. package/dist/lib/errors.d.ts +56 -0
  51. package/dist/lib/errors.d.ts.map +1 -0
  52. package/dist/lib/errors.js +90 -0
  53. package/dist/lib/errors.js.map +1 -0
  54. package/dist/lib/platform.d.ts +25 -0
  55. package/dist/lib/platform.d.ts.map +1 -0
  56. package/dist/lib/platform.js +66 -0
  57. package/dist/lib/platform.js.map +1 -0
  58. package/package.json +64 -0
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point for cursor-history
4
+ */
5
+ import { Command } from 'commander';
6
+ import { readFileSync } from 'node:fs';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { dirname, join } from 'node:path';
9
+ import { handleError, ExitCode } from '../lib/errors.js';
10
+ // Read version from package.json
11
+ const __dirname = dirname(fileURLToPath(import.meta.url));
12
+ const packageJson = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf-8'));
13
+ // Create main program
14
+ const program = new Command();
15
+ program
16
+ .name('cursor-history')
17
+ .description('View and search Cursor IDE chat history')
18
+ .version(packageJson.version, '-v, --version', 'Show version number')
19
+ .option('--json', 'Output in JSON format')
20
+ .option('--data-path <path>', 'Custom Cursor data directory')
21
+ .option('-w, --workspace <path>', 'Filter by workspace path');
22
+ // Lazy-load commands to avoid circular dependencies
23
+ async function loadCommands() {
24
+ const { registerListCommand } = await import('./commands/list.js');
25
+ const { registerShowCommand } = await import('./commands/show.js');
26
+ const { registerSearchCommand } = await import('./commands/search.js');
27
+ const { registerExportCommand } = await import('./commands/export.js');
28
+ registerListCommand(program);
29
+ registerShowCommand(program);
30
+ registerSearchCommand(program);
31
+ registerExportCommand(program);
32
+ }
33
+ // Main execution
34
+ async function main() {
35
+ try {
36
+ await loadCommands();
37
+ // If no arguments, show help
38
+ if (process.argv.length === 2) {
39
+ program.help();
40
+ }
41
+ await program.parseAsync(process.argv);
42
+ }
43
+ catch (error) {
44
+ handleError(error);
45
+ }
46
+ }
47
+ main().catch((error) => {
48
+ console.error('Unexpected error:', error);
49
+ process.exit(ExitCode.GENERAL_ERROR);
50
+ });
51
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEzD,iCAAiC;AACjC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAE1F,CAAC;AAEF,sBAAsB;AACtB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,gBAAgB,CAAC;KACtB,WAAW,CAAC,yCAAyC,CAAC;KACtD,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,qBAAqB,CAAC;KACpE,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;KACzC,MAAM,CAAC,oBAAoB,EAAE,8BAA8B,CAAC;KAC5D,MAAM,CAAC,wBAAwB,EAAE,0BAA0B,CAAC,CAAC;AAEhE,oDAAoD;AACpD,KAAK,UAAU,YAAY;IACzB,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACnE,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACnE,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACvE,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAEvE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,iBAAiB;AACjB,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,YAAY,EAAE,CAAC;QAErB,6BAA6B;QAC7B,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,CAAC;QAED,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,WAAW,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Public API for Cursor Chat History
3
+ */
4
+ export type { Platform, MessageRole, CursorDataStore, Workspace, ChatSession, ChatSessionSummary, Message, CodeBlock, SearchResult, SearchSnippet, ListOptions, SearchOptions, ExportOptions, } from './types.js';
5
+ export { findWorkspaces, listWorkspaces, listSessions, getSession, searchSessions, openDatabase, readWorkspaceJson, } from './storage.js';
6
+ export { parseChatData, extractCodeBlocks, extractPreview, getSearchSnippets, exportToMarkdown, exportToJson, } from './parser.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EACV,QAAQ,EACR,WAAW,EACX,eAAe,EACf,SAAS,EACT,WAAW,EACX,kBAAkB,EAClB,OAAO,EACP,SAAS,EACT,YAAY,EACZ,aAAa,EACb,WAAW,EACX,aAAa,EACb,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,cAAc,EACd,cAAc,EACd,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EACZ,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,GACb,MAAM,aAAa,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Public API for Cursor Chat History
3
+ */
4
+ // Storage operations
5
+ export { findWorkspaces, listWorkspaces, listSessions, getSession, searchSessions, openDatabase, readWorkspaceJson, } from './storage.js';
6
+ // Parsing utilities
7
+ export { parseChatData, extractCodeBlocks, extractPreview, getSearchSnippets, exportToMarkdown, exportToJson, } from './parser.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmBH,qBAAqB;AACrB,OAAO,EACL,cAAc,EACd,cAAc,EACd,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EACZ,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAEtB,oBAAoB;AACpB,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,GACb,MAAM,aAAa,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Chat data parsing and content extraction
3
+ */
4
+ import type { ChatSession, Message, CodeBlock, SearchSnippet } from './types.js';
5
+ /**
6
+ * Combined data from multiple keys
7
+ */
8
+ export interface CursorChatBundle {
9
+ composerData?: string;
10
+ prompts?: string;
11
+ generations?: string;
12
+ }
13
+ /**
14
+ * Parse chat data JSON string into ChatSession array
15
+ * Handles both legacy and new Cursor formats
16
+ */
17
+ export declare function parseChatData(jsonString: string, bundle?: CursorChatBundle): ChatSession[];
18
+ /**
19
+ * Extract code blocks from message content
20
+ */
21
+ export declare function extractCodeBlocks(content: string): CodeBlock[];
22
+ /**
23
+ * Extract preview text from messages (first user message, ~100 chars)
24
+ */
25
+ export declare function extractPreview(messages: Message[]): string;
26
+ /**
27
+ * Search messages for query and return snippets with context
28
+ */
29
+ export declare function getSearchSnippets(messages: Message[], query: string, contextChars?: number): SearchSnippet[];
30
+ /**
31
+ * Export a chat session to Markdown format
32
+ */
33
+ export declare function exportToMarkdown(session: ChatSession, workspacePath?: string): string;
34
+ /**
35
+ * Export a chat session to JSON format
36
+ */
37
+ export declare function exportToJson(session: ChatSession, workspacePath?: string): string;
38
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/core/parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAe,MAAM,YAAY,CAAC;AA0D9F;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,WAAW,EAAE,CA2B1F;AAwLD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,CAsB9D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAiB1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,MAAM,EACb,YAAY,GAAE,MAAW,GACxB,aAAa,EAAE,CAoDjB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAyBrF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAiBjF"}
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Chat data parsing and content extraction
3
+ */
4
+ /**
5
+ * Parse chat data JSON string into ChatSession array
6
+ * Handles both legacy and new Cursor formats
7
+ */
8
+ export function parseChatData(jsonString, bundle) {
9
+ let data;
10
+ try {
11
+ data = JSON.parse(jsonString);
12
+ }
13
+ catch {
14
+ return [];
15
+ }
16
+ // Check if this is the new composer format
17
+ if ('allComposers' in data && data.allComposers) {
18
+ return parseComposerFormat(data, bundle);
19
+ }
20
+ // Legacy format
21
+ const rawData = data;
22
+ const rawSessions = rawData.chatSessions ?? rawData.tabs ?? [];
23
+ const sessions = [];
24
+ for (const raw of rawSessions) {
25
+ const session = parseSession(raw);
26
+ if (session && session.messages.length > 0) {
27
+ sessions.push(session);
28
+ }
29
+ }
30
+ return sessions;
31
+ }
32
+ /**
33
+ * Parse new composer format into ChatSession array
34
+ */
35
+ function parseComposerFormat(data, bundle) {
36
+ const sessions = [];
37
+ const composers = data.allComposers ?? [];
38
+ // Parse generations if available (prompts lack timestamps so we skip them)
39
+ let generations = [];
40
+ if (bundle?.generations) {
41
+ try {
42
+ generations = JSON.parse(bundle.generations);
43
+ }
44
+ catch {
45
+ // Ignore parse errors
46
+ }
47
+ }
48
+ // Sort generations by timestamp for pairing
49
+ const sortedGenerations = [...generations].sort((a, b) => (a.unixMs ?? 0) - (b.unixMs ?? 0));
50
+ for (const composer of composers) {
51
+ if (!composer.composerId)
52
+ continue;
53
+ const createdAt = composer.createdAt ? new Date(composer.createdAt) : new Date();
54
+ const lastUpdatedAt = composer.lastUpdatedAt
55
+ ? new Date(composer.lastUpdatedAt)
56
+ : createdAt;
57
+ // Try to find messages that fall within this session's time range
58
+ const sessionMessages = [];
59
+ // For now, we'll create placeholder sessions with metadata
60
+ // The actual messages are in a flat list and hard to associate
61
+ // We'll include the name as preview if available
62
+ if (composer.name) {
63
+ sessionMessages.push({
64
+ id: null,
65
+ role: 'user',
66
+ content: composer.name,
67
+ timestamp: createdAt,
68
+ codeBlocks: [],
69
+ });
70
+ }
71
+ // Find generations that might belong to this session (by time proximity)
72
+ const sessionStart = composer.createdAt ?? 0;
73
+ const sessionEnd = composer.lastUpdatedAt ?? Date.now();
74
+ for (const gen of sortedGenerations) {
75
+ if (gen.unixMs && gen.unixMs >= sessionStart && gen.unixMs <= sessionEnd + 60000) {
76
+ if (gen.textDescription) {
77
+ sessionMessages.push({
78
+ id: gen.generationUUID ?? null,
79
+ role: 'user', // textDescription is actually the prompt
80
+ content: gen.textDescription,
81
+ timestamp: new Date(gen.unixMs),
82
+ codeBlocks: extractCodeBlocks(gen.textDescription),
83
+ });
84
+ }
85
+ }
86
+ }
87
+ sessions.push({
88
+ id: composer.composerId,
89
+ index: 0,
90
+ title: composer.name ?? null,
91
+ createdAt,
92
+ lastUpdatedAt,
93
+ messageCount: sessionMessages.length || 1,
94
+ messages: sessionMessages.length > 0 ? sessionMessages : [{
95
+ id: null,
96
+ role: 'user',
97
+ content: composer.name ?? '(Empty session)',
98
+ timestamp: createdAt,
99
+ codeBlocks: [],
100
+ }],
101
+ workspaceId: '',
102
+ });
103
+ }
104
+ return sessions;
105
+ }
106
+ /**
107
+ * Parse a single raw session into ChatSession
108
+ */
109
+ function parseSession(raw) {
110
+ if (!raw.id) {
111
+ return null;
112
+ }
113
+ const rawMessages = raw.messages ?? raw.bubbles ?? [];
114
+ const messages = rawMessages.map(parseMessage).filter((m) => m !== null);
115
+ if (messages.length === 0) {
116
+ return null;
117
+ }
118
+ // Derive timestamps
119
+ const createdAt = raw.createdAt
120
+ ? new Date(raw.createdAt)
121
+ : (messages[0]?.timestamp ?? new Date());
122
+ const lastUpdatedAt = raw.lastUpdatedAt
123
+ ? new Date(raw.lastUpdatedAt)
124
+ : raw.lastSendTime
125
+ ? new Date(raw.lastSendTime)
126
+ : (messages[messages.length - 1]?.timestamp ?? createdAt);
127
+ // Derive title from first user message if not set
128
+ const title = raw.title ?? deriveTitle(messages);
129
+ return {
130
+ id: raw.id,
131
+ index: 0, // Assigned later during listing
132
+ title,
133
+ createdAt,
134
+ lastUpdatedAt,
135
+ messageCount: messages.length,
136
+ messages,
137
+ workspaceId: '', // Assigned by caller
138
+ };
139
+ }
140
+ /**
141
+ * Parse a single raw message into Message
142
+ */
143
+ function parseMessage(raw) {
144
+ const content = raw.content ?? raw.text ?? '';
145
+ if (!content && !raw.role && !raw.type) {
146
+ return null;
147
+ }
148
+ // Normalize role
149
+ const rawRole = raw.role ?? raw.type ?? 'user';
150
+ const role = normalizeRole(rawRole);
151
+ // Parse timestamp
152
+ const timestamp = raw.timestamp
153
+ ? new Date(raw.timestamp)
154
+ : raw.createdAt
155
+ ? new Date(raw.createdAt)
156
+ : new Date();
157
+ return {
158
+ id: raw.id ?? null,
159
+ role,
160
+ content,
161
+ timestamp,
162
+ codeBlocks: extractCodeBlocks(content),
163
+ };
164
+ }
165
+ /**
166
+ * Normalize role string to MessageRole type
167
+ */
168
+ function normalizeRole(role) {
169
+ const lower = role.toLowerCase();
170
+ if (lower === 'assistant' || lower === 'ai' || lower === 'bot' || lower === 'system') {
171
+ return 'assistant';
172
+ }
173
+ return 'user';
174
+ }
175
+ /**
176
+ * Derive title from first user message
177
+ */
178
+ function deriveTitle(messages) {
179
+ const firstUserMessage = messages.find((m) => m.role === 'user');
180
+ if (!firstUserMessage) {
181
+ return null;
182
+ }
183
+ // Take first line, truncate to 50 chars
184
+ const firstLine = firstUserMessage.content.split('\n')[0] ?? '';
185
+ if (firstLine.length <= 50) {
186
+ return firstLine || null;
187
+ }
188
+ return firstLine.slice(0, 47) + '...';
189
+ }
190
+ /**
191
+ * Extract code blocks from message content
192
+ */
193
+ export function extractCodeBlocks(content) {
194
+ const blocks = [];
195
+ // Match fenced code blocks: ```language\ncode\n```
196
+ const regex = /^```(\w*)\n([\s\S]*?)^```/gm;
197
+ let match;
198
+ while ((match = regex.exec(content)) !== null) {
199
+ const language = match[1] || null;
200
+ const code = match[2] ?? '';
201
+ // Calculate start line
202
+ const beforeMatch = content.slice(0, match.index);
203
+ const startLine = beforeMatch.split('\n').length - 1;
204
+ blocks.push({
205
+ language,
206
+ content: code.trimEnd(),
207
+ startLine,
208
+ });
209
+ }
210
+ return blocks;
211
+ }
212
+ /**
213
+ * Extract preview text from messages (first user message, ~100 chars)
214
+ */
215
+ export function extractPreview(messages) {
216
+ const firstUserMessage = messages.find((m) => m.role === 'user');
217
+ if (!firstUserMessage) {
218
+ return '';
219
+ }
220
+ // Remove code blocks for cleaner preview
221
+ const cleanContent = firstUserMessage.content
222
+ .replace(/```[\s\S]*?```/g, '[code]')
223
+ .replace(/\n+/g, ' ')
224
+ .trim();
225
+ if (cleanContent.length <= 100) {
226
+ return cleanContent;
227
+ }
228
+ return cleanContent.slice(0, 97) + '...';
229
+ }
230
+ /**
231
+ * Search messages for query and return snippets with context
232
+ */
233
+ export function getSearchSnippets(messages, query, contextChars = 50) {
234
+ const snippets = [];
235
+ const lowerQuery = query.toLowerCase();
236
+ for (const message of messages) {
237
+ const lowerContent = message.content.toLowerCase();
238
+ const positions = [];
239
+ // Find all match positions
240
+ let searchStart = 0;
241
+ while (true) {
242
+ const pos = lowerContent.indexOf(lowerQuery, searchStart);
243
+ if (pos === -1)
244
+ break;
245
+ positions.push([pos, pos + query.length]);
246
+ searchStart = pos + 1;
247
+ }
248
+ if (positions.length === 0) {
249
+ continue;
250
+ }
251
+ // Extract snippet with context around first match
252
+ const firstMatch = positions[0];
253
+ const snippetStart = Math.max(0, firstMatch[0] - contextChars);
254
+ const snippetEnd = Math.min(message.content.length, firstMatch[1] + contextChars);
255
+ let text = message.content.slice(snippetStart, snippetEnd);
256
+ // Add ellipsis if truncated
257
+ if (snippetStart > 0) {
258
+ text = '...' + text;
259
+ }
260
+ if (snippetEnd < message.content.length) {
261
+ text = text + '...';
262
+ }
263
+ // Adjust positions for the snippet offset
264
+ const adjustedPositions = positions
265
+ .filter(([start, end]) => start >= snippetStart && end <= snippetEnd)
266
+ .map(([start, end]) => [
267
+ start - snippetStart + (snippetStart > 0 ? 3 : 0),
268
+ end - snippetStart + (snippetStart > 0 ? 3 : 0),
269
+ ]);
270
+ snippets.push({
271
+ messageRole: message.role,
272
+ text,
273
+ matchPositions: adjustedPositions,
274
+ });
275
+ }
276
+ return snippets;
277
+ }
278
+ /**
279
+ * Export a chat session to Markdown format
280
+ */
281
+ export function exportToMarkdown(session, workspacePath) {
282
+ const lines = [];
283
+ // Header
284
+ lines.push(`# ${session.title ?? 'Untitled Chat'}`);
285
+ lines.push('');
286
+ lines.push(`**Date**: ${session.createdAt.toISOString().split('T')[0]}`);
287
+ if (workspacePath) {
288
+ lines.push(`**Workspace**: ${workspacePath}`);
289
+ }
290
+ lines.push(`**Messages**: ${session.messageCount}`);
291
+ lines.push('');
292
+ lines.push('---');
293
+ lines.push('');
294
+ // Messages
295
+ for (const message of session.messages) {
296
+ const roleLabel = message.role === 'user' ? '**User**' : '**Assistant**';
297
+ lines.push(`### ${roleLabel}`);
298
+ lines.push('');
299
+ lines.push(message.content);
300
+ lines.push('');
301
+ }
302
+ return lines.join('\n');
303
+ }
304
+ /**
305
+ * Export a chat session to JSON format
306
+ */
307
+ export function exportToJson(session, workspacePath) {
308
+ const exportData = {
309
+ id: session.id,
310
+ title: session.title,
311
+ createdAt: session.createdAt.toISOString(),
312
+ lastUpdatedAt: session.lastUpdatedAt.toISOString(),
313
+ messageCount: session.messageCount,
314
+ workspacePath: workspacePath ?? null,
315
+ messages: session.messages.map((m) => ({
316
+ role: m.role,
317
+ content: m.content,
318
+ timestamp: m.timestamp.toISOString(),
319
+ codeBlocks: m.codeBlocks,
320
+ })),
321
+ };
322
+ return JSON.stringify(exportData, null, 2);
323
+ }
324
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/core/parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqEH;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,UAAkB,EAAE,MAAyB;IACzE,IAAI,IAAgC,CAAC;IAErC,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAA+B,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,2CAA2C;IAC3C,IAAI,cAAc,IAAI,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QAChD,OAAO,mBAAmB,CAAC,IAAoB,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC;IAED,gBAAgB;IAChB,MAAM,OAAO,GAAG,IAAmB,CAAC;IACpC,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;IAC/D,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,IAAkB,EAAE,MAAyB;IACxE,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC;IAE1C,2EAA2E;IAC3E,IAAI,WAAW,GAAsB,EAAE,CAAC;IAExC,IAAI,MAAM,EAAE,WAAW,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAsB,CAAC;QACpE,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;IACH,CAAC;IAED,4CAA4C;IAC5C,MAAM,iBAAiB,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;IAE7F,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC,QAAQ,CAAC,UAAU;YAAE,SAAS;QAEnC,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QACjF,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa;YAC1C,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;YAClC,CAAC,CAAC,SAAS,CAAC;QAEd,kEAAkE;QAClE,MAAM,eAAe,GAAc,EAAE,CAAC;QAEtC,2DAA2D;QAC3D,+DAA+D;QAC/D,iDAAiD;QACjD,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAClB,eAAe,CAAC,IAAI,CAAC;gBACnB,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,QAAQ,CAAC,IAAI;gBACtB,SAAS,EAAE,SAAS;gBACpB,UAAU,EAAE,EAAE;aACf,CAAC,CAAC;QACL,CAAC;QAED,yEAAyE;QACzE,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,IAAI,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QAExD,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;YACpC,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,YAAY,IAAI,GAAG,CAAC,MAAM,IAAI,UAAU,GAAG,KAAK,EAAE,CAAC;gBACjF,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;oBACxB,eAAe,CAAC,IAAI,CAAC;wBACnB,EAAE,EAAE,GAAG,CAAC,cAAc,IAAI,IAAI;wBAC9B,IAAI,EAAE,MAAM,EAAE,yCAAyC;wBACvD,OAAO,EAAE,GAAG,CAAC,eAAe;wBAC5B,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;wBAC/B,UAAU,EAAE,iBAAiB,CAAC,GAAG,CAAC,eAAe,CAAC;qBACnD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC;YACZ,EAAE,EAAE,QAAQ,CAAC,UAAU;YACvB,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,QAAQ,CAAC,IAAI,IAAI,IAAI;YAC5B,SAAS;YACT,aAAa;YACb,YAAY,EAAE,eAAe,CAAC,MAAM,IAAI,CAAC;YACzC,QAAQ,EAAE,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;oBACxD,EAAE,EAAE,IAAI;oBACR,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,QAAQ,CAAC,IAAI,IAAI,iBAAiB;oBAC3C,SAAS,EAAE,SAAS;oBACpB,UAAU,EAAE,EAAE;iBACf,CAAC;YACF,WAAW,EAAE,EAAE;SAChB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,GAAmB;IACvC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;IACtD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAgB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IAEvF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oBAAoB;IACpB,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS;QAC7B,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;QACzB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;IAE3C,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa;QACrC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC;QAC7B,CAAC,CAAC,GAAG,CAAC,YAAY;YAChB,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;YAC5B,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,SAAS,IAAI,SAAS,CAAC,CAAC;IAE9D,kDAAkD;IAClD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC;IAEjD,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,KAAK,EAAE,CAAC,EAAE,gCAAgC;QAC1C,KAAK;QACL,SAAS;QACT,aAAa;QACb,YAAY,EAAE,QAAQ,CAAC,MAAM;QAC7B,QAAQ;QACR,WAAW,EAAE,EAAE,EAAE,qBAAqB;KACvC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,GAAe;IACnC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iBAAiB;IACjB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC;IAC/C,MAAM,IAAI,GAAgB,aAAa,CAAC,OAAO,CAAC,CAAC;IAEjD,kBAAkB;IAClB,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS;QAC7B,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;QACzB,CAAC,CAAC,GAAG,CAAC,SAAS;YACb,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;YACzB,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;IAEjB,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE,IAAI,IAAI;QAClB,IAAI;QACJ,OAAO;QACP,SAAS;QACT,UAAU,EAAE,iBAAiB,CAAC,OAAO,CAAC;KACvC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrF,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,QAAmB;IACtC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACjE,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,wCAAwC;IACxC,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAChE,IAAI,SAAS,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC3B,OAAO,SAAS,IAAI,IAAI,CAAC;IAC3B,CAAC;IACD,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,mDAAmD;IACnD,MAAM,KAAK,GAAG,6BAA6B,CAAC;IAE5C,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAE5B,uBAAuB;QACvB,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QAErD,MAAM,CAAC,IAAI,CAAC;YACV,QAAQ;YACR,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;YACvB,SAAS;SACV,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAmB;IAChD,MAAM,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACjE,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,yCAAyC;IACzC,MAAM,YAAY,GAAG,gBAAgB,CAAC,OAAO;SAC1C,OAAO,CAAC,iBAAiB,EAAE,QAAQ,CAAC;SACpC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;IAEV,IAAI,YAAY,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;QAC/B,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAmB,EACnB,KAAa,EACb,eAAuB,EAAE;IAEzB,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAEvC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACnD,MAAM,SAAS,GAAuB,EAAE,CAAC;QAEzC,2BAA2B;QAC3B,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;YAC1D,IAAI,GAAG,KAAK,CAAC,CAAC;gBAAE,MAAM;YACtB,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;YAC1C,WAAW,GAAG,GAAG,GAAG,CAAC,CAAC;QACxB,CAAC;QAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,SAAS;QACX,CAAC;QAED,kDAAkD;QAClD,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;QACjC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC;QAElF,IAAI,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAE3D,4BAA4B;QAC5B,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YACrB,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC;QACtB,CAAC;QACD,IAAI,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACxC,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC;QACtB,CAAC;QAED,0CAA0C;QAC1C,MAAM,iBAAiB,GAAuB,SAAS;aACpD,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,YAAY,IAAI,GAAG,IAAI,UAAU,CAAC;aACpE,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;YACrB,KAAK,GAAG,YAAY,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,GAAG,GAAG,YAAY,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAChD,CAAC,CAAC;QAEL,QAAQ,CAAC,IAAI,CAAC;YACZ,WAAW,EAAE,OAAO,CAAC,IAAI;YACzB,IAAI;YACJ,cAAc,EAAE,iBAAiB;SAClC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAoB,EAAE,aAAsB;IAC3E,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,SAAS;IACT,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC,CAAC;IACpD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACzE,IAAI,aAAa,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,kBAAkB,aAAa,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,iBAAiB,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACpD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,WAAW;IACX,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,KAAK,CAAC,IAAI,CAAC,OAAO,SAAS,EAAE,CAAC,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAoB,EAAE,aAAsB;IACvE,MAAM,UAAU,GAAG;QACjB,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE;QAC1C,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC,WAAW,EAAE;QAClD,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,aAAa,EAAE,aAAa,IAAI,IAAI;QACpC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE;YACpC,UAAU,EAAE,CAAC,CAAC,UAAU;SACzB,CAAC,CAAC;KACJ,CAAC;IAEF,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Storage discovery and database access for Cursor chat history
3
+ */
4
+ import Database from 'better-sqlite3';
5
+ import type { Workspace, ChatSession, ChatSessionSummary, ListOptions, SearchOptions, SearchResult } from './types.js';
6
+ /**
7
+ * Open a SQLite database file
8
+ */
9
+ export declare function openDatabase(dbPath: string): Database.Database;
10
+ /**
11
+ * Read workspace.json to get the original workspace path
12
+ */
13
+ export declare function readWorkspaceJson(workspaceDir: string): string | null;
14
+ /**
15
+ * Find all workspaces with chat history
16
+ */
17
+ export declare function findWorkspaces(customDataPath?: string): Workspace[];
18
+ /**
19
+ * List chat sessions with optional filtering
20
+ * Uses workspace storage for listing (has correct paths and complete list)
21
+ */
22
+ export declare function listSessions(options: ListOptions, customDataPath?: string): ChatSessionSummary[];
23
+ /**
24
+ * List all workspaces with chat history
25
+ */
26
+ export declare function listWorkspaces(customDataPath?: string): Workspace[];
27
+ /**
28
+ * Get a specific session by index
29
+ * Tries global storage first for complete AI responses, falls back to workspace storage
30
+ */
31
+ export declare function getSession(index: number, customDataPath?: string): ChatSession | null;
32
+ /**
33
+ * Search across all chat sessions
34
+ */
35
+ export declare function searchSessions(query: string, options: SearchOptions, customDataPath?: string): SearchResult[];
36
+ /**
37
+ * List sessions from global Cursor storage (cursorDiskKV table)
38
+ * This is where Cursor stores full conversation data including AI responses
39
+ */
40
+ export declare function listGlobalSessions(): ChatSessionSummary[];
41
+ /**
42
+ * Get a session from global storage by index
43
+ */
44
+ export declare function getGlobalSession(index: number): ChatSession | null;
45
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/core/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,YAAY,EACb,MAAM,YAAY,CAAC;AAmCpB;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAE9D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBrE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,CAoDnE;AA0DD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAsDhG;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,CAUnE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAwGrF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,EACtB,cAAc,CAAC,EAAE,MAAM,GACtB,YAAY,EAAE,CAqChB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,kBAAkB,EAAE,CAiGzD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAyDlE"}