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.
- package/README.md +225 -0
- package/dist/cli/commands/export.d.ts +9 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +126 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/list.d.ts +9 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +77 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/search.d.ts +9 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +47 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/commands/show.d.ts +9 -0
- package/dist/cli/commands/show.d.ts.map +1 -0
- package/dist/cli/commands/show.js +51 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/formatters/index.d.ts +6 -0
- package/dist/cli/formatters/index.d.ts.map +1 -0
- package/dist/cli/formatters/index.js +6 -0
- package/dist/cli/formatters/index.js.map +1 -0
- package/dist/cli/formatters/json.d.ts +28 -0
- package/dist/cli/formatters/json.d.ts.map +1 -0
- package/dist/cli/formatters/json.js +98 -0
- package/dist/cli/formatters/json.js.map +1 -0
- package/dist/cli/formatters/table.d.ts +45 -0
- package/dist/cli/formatters/table.d.ts.map +1 -0
- package/dist/cli/formatters/table.js +439 -0
- package/dist/cli/formatters/table.js.map +1 -0
- package/dist/cli/index.d.ts +6 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +51 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +8 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/parser.d.ts +38 -0
- package/dist/core/parser.d.ts.map +1 -0
- package/dist/core/parser.js +324 -0
- package/dist/core/parser.js.map +1 -0
- package/dist/core/storage.d.ts +45 -0
- package/dist/core/storage.d.ts.map +1 -0
- package/dist/core/storage.js +869 -0
- package/dist/core/storage.js.map +1 -0
- package/dist/core/types.d.ts +113 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +6 -0
- package/dist/core/types.js.map +1 -0
- package/dist/lib/errors.d.ts +56 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +90 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/platform.d.ts +25 -0
- package/dist/lib/platform.d.ts.map +1 -0
- package/dist/lib/platform.js +66 -0
- package/dist/lib/platform.js.map +1 -0
- 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":"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"}
|
|
@@ -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"}
|