spiracha 1.2.0 → 1.3.2
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/AGENTS.md +50 -12
- package/README.md +117 -64
- package/apps/ui/AGENTS.md +16 -8
- package/apps/ui/README.md +28 -12
- package/apps/ui/dist/client/assets/{analytics-Cv0JMDN2.js → analytics-B_hYz65v.js} +1 -1
- package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-qiyygB7e.js +1 -0
- package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-z1SQC2Kg.js +1 -0
- package/apps/ui/dist/client/assets/antigravity-keychain-panel-dYuRWtCf.js +1 -0
- package/apps/ui/dist/client/assets/antigravity._workspaceKey-CliqUr7o.js +1 -0
- package/apps/ui/dist/client/assets/antigravity._workspaceKey-CnoBzyX6.js +1 -0
- package/apps/ui/dist/client/assets/antigravity.index-CakfZz_E.js +1 -0
- package/apps/ui/dist/client/assets/antigravity.index-DY7M1KhG.js +1 -0
- package/apps/ui/dist/client/assets/badge-aHE9ETVe.js +1 -0
- package/apps/ui/dist/client/assets/checkbox-DN3XnJaA.js +1 -0
- package/apps/ui/dist/client/assets/cursor-threads._composerId-BMQyx8qG.js +1 -0
- package/apps/ui/dist/client/assets/cursor-threads._composerId-BTlaA-tV.js +1 -0
- package/apps/ui/dist/client/assets/cursor._workspaceKey-CrgrfevV.js +1 -0
- package/apps/ui/dist/client/assets/cursor._workspaceKey-bYS2syGL.js +1 -0
- package/apps/ui/dist/client/assets/cursor.index-CTqZMPYU.js +1 -0
- package/apps/ui/dist/client/assets/cursor.index-Clsz4E_e.js +2 -0
- package/apps/ui/dist/client/assets/{data-table-Bgnh7phF.js → data-table-Cj-v-uyB.js} +2 -2
- package/apps/ui/dist/client/assets/delete-confirm-dialog-DTpzBiNK.js +11 -0
- package/apps/ui/dist/client/assets/dist-BNAn99Pu.js +1 -0
- package/apps/ui/dist/client/assets/download-P3Rp23Ad.js +1 -0
- package/apps/ui/dist/client/assets/dropdown-menu-3qB5j9nt.js +1 -0
- package/apps/ui/dist/client/assets/es2015-Dwm_turD.js +41 -0
- package/apps/ui/dist/client/assets/export-dialog-CazdrASq.js +1 -0
- package/apps/ui/dist/client/assets/formatters-BdnWuM1z.js +1 -0
- package/apps/ui/dist/client/assets/index-BVFnfS78.js +22 -0
- package/apps/ui/dist/client/assets/json-panel-DLkS30sQ.js +1 -0
- package/apps/ui/dist/client/assets/metadata-section-jnIkB7dB.js +1 -0
- package/apps/ui/dist/client/assets/{metric-card-BJX5rkHK.js → metric-card-CBZuWLzQ.js} +1 -1
- package/apps/ui/dist/client/assets/page-header-CnD21cPn.js +1 -0
- package/apps/ui/dist/client/assets/projects._project-BLszwvYL.js +1 -0
- package/apps/ui/dist/client/assets/projects._project-DvLxYbvk.js +1 -0
- package/apps/ui/dist/client/assets/projects.index-COn8woBR.js +1 -0
- package/apps/ui/dist/client/assets/projects.index-DYs98skV.js +3 -0
- package/apps/ui/dist/client/assets/refresh-ccw-BDrYXjtD.js +1 -0
- package/apps/ui/dist/client/assets/reload-error-panel-DLAg0AW2.js +1 -0
- package/apps/ui/dist/client/assets/routes-BtF5-coe.js +1 -0
- package/apps/ui/dist/client/assets/scroll-text-CqaFm9by.js +1 -0
- package/apps/ui/dist/client/assets/select-DbnpwqL6.js +1 -0
- package/apps/ui/dist/client/assets/settings-CGX3VleN.js +1 -0
- package/apps/ui/dist/client/assets/styles-Ch0r3kMZ.css +1 -0
- package/apps/ui/dist/client/assets/text-document-panel-DPleOmmq.js +1 -0
- package/apps/ui/dist/client/assets/text-filter-7M6wRo-t.js +2 -0
- package/apps/ui/dist/client/assets/threads._threadId-D5w76IB-.js +7 -0
- package/apps/ui/dist/client/assets/{threads._threadId-CUiCZSwo.js → threads._threadId-Dx85sI9P.js} +1 -1
- package/apps/ui/dist/client/assets/useMutation-MZ3Hr9h9.js +1 -0
- package/apps/ui/dist/client/assets/useQuery-Cb4V0AT0.js +1 -0
- package/apps/ui/dist/client/icon.svg +28 -0
- package/apps/ui/dist/client/manifest.json +6 -16
- package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CBbkUXw6.js +227 -0
- package/apps/ui/dist/server/assets/{analytics-2QpLKjlG.js → analytics-CBNOYZwJ.js} +2 -2
- package/apps/ui/dist/server/assets/antigravity-conversation-state-HgzS302O.js +16 -0
- package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-B9Rm4EXh.js +212 -0
- package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-BIdYNy68.js +20 -0
- package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-D426O-64.js +11 -0
- package/apps/ui/dist/server/assets/antigravity-db-D9gW1D8G.js +576 -0
- package/apps/ui/dist/server/assets/antigravity-keychain-DOiuHDwK.js +126 -0
- package/apps/ui/dist/server/assets/antigravity-keychain-panel-DcLyBBwd.js +55 -0
- package/apps/ui/dist/server/assets/antigravity-queries-CgQhlQ7J.js +37 -0
- package/apps/ui/dist/server/assets/antigravity-server-DFUx4Khk.js +114 -0
- package/apps/ui/dist/server/assets/antigravity._workspaceKey-3m_MzNFA.js +11 -0
- package/apps/ui/dist/server/assets/antigravity._workspaceKey-D42ixtzp.js +210 -0
- package/apps/ui/dist/server/assets/antigravity._workspaceKey-DnSlSC-C.js +28 -0
- package/apps/ui/dist/server/assets/antigravity.index-DZVT-cac.js +104 -0
- package/apps/ui/dist/server/assets/antigravity.index-DudTB3Tq.js +11 -0
- package/apps/ui/dist/server/assets/badge-EvdhKK_Z.js +26 -0
- package/apps/ui/dist/server/assets/{codex-queries-BH4Cb0v3.js → codex-queries-eOJGfHQj.js} +4 -16
- package/apps/ui/dist/server/assets/{codex-server-DqzruLmg.js → codex-server-nrETIF--.js} +149 -140
- package/apps/ui/dist/server/assets/createServerRpc-BtXIw2iP.js +12 -0
- package/apps/ui/dist/server/assets/createSsrRpc-COf5Zuye.js +16 -0
- package/apps/ui/dist/server/assets/cursor-db-B7agkAvM.js +643 -0
- package/apps/ui/dist/server/assets/cursor-exporter-types-CI3goo-c.js +34 -0
- package/apps/ui/dist/server/assets/cursor-queries-BMhuJeUO.js +65 -0
- package/apps/ui/dist/server/assets/cursor-recovery-9bJLs7vG.js +361 -0
- package/apps/ui/dist/server/assets/cursor-server-BgylIFgn.js +184 -0
- package/apps/ui/dist/server/assets/cursor-threads._composerId-BB0Y_Mao.js +11 -0
- package/apps/ui/dist/server/assets/cursor-threads._composerId-BsxFKzoJ.js +218 -0
- package/apps/ui/dist/server/assets/cursor-threads._composerId-DXffY_CK.js +18 -0
- package/apps/ui/dist/server/assets/cursor-transcript-2iL3KFSK.js +125 -0
- package/apps/ui/dist/server/assets/cursor._workspaceKey-BP2J1x_x.js +28 -0
- package/apps/ui/dist/server/assets/cursor._workspaceKey-BQd0e-Pd.js +399 -0
- package/apps/ui/dist/server/assets/cursor._workspaceKey-nmg3YIOQ.js +11 -0
- package/apps/ui/dist/server/assets/cursor.index-CQVxtCm8.js +189 -0
- package/apps/ui/dist/server/assets/cursor.index-CcsX7DG0.js +11 -0
- package/apps/ui/dist/server/assets/{delete-confirm-dialog-CWqcTXTF.js → delete-confirm-dialog-PCD7S0_M.js} +5 -4
- package/apps/ui/dist/server/assets/download-DMmiy1xf.js +92 -0
- package/apps/ui/dist/server/assets/{input-B4tEzctc.js → dropdown-menu-Dy_9t6TN.js} +1 -11
- package/apps/ui/dist/server/assets/{download-Drctxary.js → export-dialog-DaPlOGFT.js} +1 -92
- package/apps/ui/dist/server/assets/json-panel-RYsxWFae.js +16 -0
- package/apps/ui/dist/server/assets/{loading-panel-DbLdvjtR.js → loading-panel-BGFnWseS.js} +1 -1
- package/apps/ui/dist/server/assets/metadata-section-D6Lbc7D6.js +54 -0
- package/apps/ui/dist/server/assets/page-header-VNSaM3xd.js +29 -0
- package/apps/ui/dist/server/assets/projects._project-Bshqk7JA.js +12 -0
- package/apps/ui/dist/server/assets/{projects._project-gT01HBqH.js → projects._project-DUN3iWfg.js} +4 -4
- package/apps/ui/dist/server/assets/{projects._project-DreIU5b0.js → projects._project-Dim9Y0kD.js} +54 -26
- package/apps/ui/dist/server/assets/projects.index-BLXOx5eL.js +12 -0
- package/apps/ui/dist/server/assets/{projects.index-BYmgSGAj.js → projects.index-DjSQK5dm.js} +23 -27
- package/apps/ui/dist/server/assets/{projects.index-CaplpeMy.js → reload-error-panel-BJMxY3U1.js} +5 -6
- package/apps/ui/dist/server/assets/{router-Qj5Kn7bl.js → router-DrDgc-LD.js} +131 -44
- package/apps/ui/dist/server/assets/{routes-_LbCIjtJ.js → routes-B-GlEe2C.js} +54 -39
- package/apps/ui/dist/server/assets/{routes-BtcXuK0x.js → routes-CNHAUMwo.js} +2 -2
- package/apps/ui/dist/server/assets/{settings-MvWDgc1u.js → settings-OayxIYQQ.js} +1 -1
- package/apps/ui/dist/server/assets/shared-CPRNYIql.js +134 -0
- package/apps/ui/dist/server/assets/text-document-panel-D8JbQWAn.js +23 -0
- package/apps/ui/dist/server/assets/text-filter-CGKxMCKt.js +36 -0
- package/apps/ui/dist/server/assets/{threads._threadId-DcbAJkwf.js → threads._threadId-CJzm4KrZ.js} +3 -3
- package/apps/ui/dist/server/assets/{threads._threadId-D5m6ypGw.js → threads._threadId-DODTYddm.js} +69 -76
- package/apps/ui/dist/server/server.js +77 -13
- package/package.json +21 -11
- package/src/export-cursor.ts +244 -0
- package/src/lib/antigravity-db.ts +936 -0
- package/src/lib/antigravity-exporter-types.ts +70 -0
- package/src/lib/antigravity-keychain.ts +203 -0
- package/src/lib/codex-browser-db.ts +7 -1
- package/src/lib/codex-browser-types.ts +22 -1
- package/src/lib/codex-thread-recovery.ts +202 -0
- package/src/lib/cursor-db.ts +1096 -0
- package/src/lib/cursor-exporter-types.ts +190 -0
- package/src/lib/cursor-exporter.ts +266 -0
- package/src/lib/cursor-recovery.ts +543 -0
- package/src/lib/cursor-transcript.ts +183 -0
- package/src/spiracha.ts +16 -3
- package/src/ui-cli.ts +2 -2
- package/apps/ui/dist/client/assets/checkbox-DjHij7DJ.js +0 -1
- package/apps/ui/dist/client/assets/delete-confirm-dialog-CIZy_LXD.js +0 -11
- package/apps/ui/dist/client/assets/download-DQtfva4z.js +0 -1
- package/apps/ui/dist/client/assets/es2015-DsDKdYCE.js +0 -41
- package/apps/ui/dist/client/assets/formatters-CWFrMKSn.js +0 -1
- package/apps/ui/dist/client/assets/index-C_-e0lDI.js +0 -22
- package/apps/ui/dist/client/assets/input-BbgApiqZ.js +0 -1
- package/apps/ui/dist/client/assets/page-header-ODLuGLAB.js +0 -1
- package/apps/ui/dist/client/assets/projects._project-C2Pys_bB.js +0 -1
- package/apps/ui/dist/client/assets/projects._project-CHvAKvlu.js +0 -1
- package/apps/ui/dist/client/assets/projects.index-BmwtS1x-.js +0 -1
- package/apps/ui/dist/client/assets/projects.index-CuLw73mt.js +0 -1
- package/apps/ui/dist/client/assets/routes-CfnaTOlj.js +0 -1
- package/apps/ui/dist/client/assets/select-B1kH_5lx.js +0 -1
- package/apps/ui/dist/client/assets/settings-mYTB3sso.js +0 -1
- package/apps/ui/dist/client/assets/styles-CMrP9Jb4.css +0 -1
- package/apps/ui/dist/client/assets/threads._threadId-C_47okme.js +0 -7
- package/apps/ui/dist/client/favicon.ico +0 -0
- package/apps/ui/dist/client/logo192.png +0 -0
- package/apps/ui/dist/client/logo512.png +0 -0
- package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-kj_QB_26.js +0 -99
- package/apps/ui/dist/server/assets/page-header-CxdZM86z.js +0 -25
- package/apps/ui/dist/server/assets/projects._project-CLSohrBp.js +0 -26
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { stdin as input, stdout as output } from 'node:process';
|
|
4
|
+
import { createInterface } from 'node:readline/promises';
|
|
5
|
+
import { findCursorWorkspaceGroups, listCursorThreadsForGroup, listCursorWorkspaceGroups } from './lib/cursor-db';
|
|
6
|
+
import { getCursorHelpText, parseCursorCliArgs, runCursorExport } from './lib/cursor-exporter';
|
|
7
|
+
import { type CursorThreadSummary, type CursorWorkspaceGroup, resolveCursorUserDir } from './lib/cursor-exporter-types';
|
|
8
|
+
import { isCursorRunning, pruneCursorThreads, recoverCursorWorkspaceGroup } from './lib/cursor-recovery';
|
|
9
|
+
import { CliUsageError } from './lib/shared';
|
|
10
|
+
|
|
11
|
+
type CursorSubcommand = 'list' | 'export' | 'recover' | 'prune';
|
|
12
|
+
|
|
13
|
+
const PRUNE_CONFIRM_PHRASE = 'delete permanently';
|
|
14
|
+
|
|
15
|
+
const resolveSubcommand = (argv: string[]): { subcommand: CursorSubcommand; rest: string[] } => {
|
|
16
|
+
const [first, ...rest] = argv;
|
|
17
|
+
if (first === 'list' || first === 'export' || first === 'recover' || first === 'prune') {
|
|
18
|
+
return { rest, subcommand: first };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Default to export so `spiracha cursor <workspace>` behaves like the other exporters.
|
|
22
|
+
return { rest: argv, subcommand: 'export' };
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const promptLine = async (question: string): Promise<string> => {
|
|
26
|
+
const rl = createInterface({ input, output });
|
|
27
|
+
try {
|
|
28
|
+
return (await rl.question(question)).trim();
|
|
29
|
+
} finally {
|
|
30
|
+
rl.close();
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const ensureCursorClosed = async (): Promise<void> => {
|
|
35
|
+
if (await isCursorRunning()) {
|
|
36
|
+
throw new Error('Cursor is still running. Quit Cursor completely, then run again with --apply.');
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const runCursorList = async (argv: string[]): Promise<void> => {
|
|
41
|
+
const query = argv.find((arg) => !arg.startsWith('-')) ?? null;
|
|
42
|
+
const groups = await listCursorWorkspaceGroups();
|
|
43
|
+
const filtered = query ? findCursorWorkspaceGroups(groups, query) : groups;
|
|
44
|
+
|
|
45
|
+
if (filtered.length === 0) {
|
|
46
|
+
console.log('No Cursor workspaces found.');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
console.log(`Found ${filtered.length} Cursor workspace(s):\n`);
|
|
51
|
+
for (const group of filtered) {
|
|
52
|
+
const recover = group.needsRecovery ? ' [needs recovery]' : '';
|
|
53
|
+
console.log(`${group.label}${recover}`);
|
|
54
|
+
console.log(` key: ${group.key}`);
|
|
55
|
+
console.log(` threads: ~${group.threadCount} buckets: ${group.buckets.length}`);
|
|
56
|
+
}
|
|
57
|
+
console.log('\nExport with: spiracha cursor export --workspace <name> --tools --commentary');
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const runCursorExportCommand = async (argv: string[]): Promise<void> => {
|
|
61
|
+
const options = parseCursorCliArgs(argv);
|
|
62
|
+
const result = await runCursorExport(options);
|
|
63
|
+
|
|
64
|
+
if (result.exportedCount === 0) {
|
|
65
|
+
console.log('No threads were exported.');
|
|
66
|
+
} else {
|
|
67
|
+
console.log(`Exported ${result.exportedCount} thread(s) to ${result.outputDir}`);
|
|
68
|
+
for (const file of result.files) {
|
|
69
|
+
console.log(` ${file.composerId} -> ${file.outputPath}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (result.missingThreadIds.length > 0) {
|
|
74
|
+
console.log(`Skipped ${result.missingThreadIds.length} thread(s) with no exportable content.`);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const resolveSingleGroupOrThrow = (groups: CursorWorkspaceGroup[], query: string): CursorWorkspaceGroup => {
|
|
79
|
+
const matched = findCursorWorkspaceGroups(groups, query);
|
|
80
|
+
if (matched.length === 0) {
|
|
81
|
+
throw new Error(`No Cursor workspace matched query: ${query}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (matched.length > 1) {
|
|
85
|
+
const keys = matched.map((group) => ` - ${group.key}`).join('\n');
|
|
86
|
+
throw new Error(`Query "${query}" matched multiple workspaces. Refine it:\n${keys}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return matched[0]!;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const runCursorRecover = async (argv: string[]): Promise<void> => {
|
|
93
|
+
const apply = argv.includes('--apply');
|
|
94
|
+
const query = argv.find((arg) => !arg.startsWith('-'));
|
|
95
|
+
if (!query) {
|
|
96
|
+
throw new CliUsageError('recover requires a workspace name or path.');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (apply) {
|
|
100
|
+
await ensureCursorClosed();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const group = resolveSingleGroupOrThrow(await listCursorWorkspaceGroups(), query);
|
|
104
|
+
const result = await recoverCursorWorkspaceGroup(group, apply);
|
|
105
|
+
|
|
106
|
+
console.log(`[${group.label}] merges ${result.mergedThreadCount} thread(s) into bucket ${result.activeBucketId}`);
|
|
107
|
+
for (const thread of result.threads) {
|
|
108
|
+
console.log(` - ${thread.name} [${thread.composerId.slice(0, 8)}] bubbles=${thread.bubbleCount}`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!apply) {
|
|
112
|
+
console.log('\nDry run only. Re-run with --apply after quitting Cursor.');
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
console.log(
|
|
117
|
+
`\nRecovery complete: relinked ${result.relinkedHeaderCount}, added ${result.addedHeaderCount} header(s).`,
|
|
118
|
+
);
|
|
119
|
+
console.log('Reopen the project in Cursor and check Chat History.');
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const selectPruneThreads = async (argv: string[]): Promise<CursorThreadSummary[]> => {
|
|
123
|
+
const threadIds = collectFlagValues(argv, ['--thread', '-t']);
|
|
124
|
+
const query = collectFlagValues(argv, ['--workspace', '-w'])[0] ?? argv.find((arg) => !arg.startsWith('-'));
|
|
125
|
+
const groups = await listCursorWorkspaceGroups();
|
|
126
|
+
|
|
127
|
+
if (threadIds.length > 0) {
|
|
128
|
+
const all = (await Promise.all(groups.map((group) => listCursorThreadsForGroup(group)))).flat();
|
|
129
|
+
return all.filter(
|
|
130
|
+
(thread) =>
|
|
131
|
+
threadIds.includes(thread.composerId) || threadIds.some((id) => thread.composerId.startsWith(id)),
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (!query) {
|
|
136
|
+
throw new CliUsageError('prune requires a --workspace or one or more --thread ids.');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const group = resolveSingleGroupOrThrow(groups, query);
|
|
140
|
+
return listCursorThreadsForGroup(group);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const collectFlagValues = (argv: string[], flags: string[]): string[] => {
|
|
144
|
+
const values: string[] = [];
|
|
145
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
146
|
+
if (flags.includes(argv[index] as string)) {
|
|
147
|
+
const value = argv[index + 1];
|
|
148
|
+
if (value && !value.startsWith('-')) {
|
|
149
|
+
values.push(value);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return values;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const runCursorPrune = async (argv: string[]): Promise<void> => {
|
|
158
|
+
const apply = argv.includes('--apply');
|
|
159
|
+
const threads = await selectPruneThreads(argv);
|
|
160
|
+
|
|
161
|
+
if (threads.length === 0) {
|
|
162
|
+
console.log('No matching threads to prune.');
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
console.log(`Prune target: ${threads.length} thread(s)`);
|
|
167
|
+
for (const thread of threads) {
|
|
168
|
+
console.log(` - ${thread.name} [${thread.composerId.slice(0, 8)}] bubbles=${thread.bubbleCount}`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (!apply) {
|
|
172
|
+
const preview = await pruneCursorThreads(threads, false);
|
|
173
|
+
console.log(`\nDry run: would delete ${preview.bubblesDeleted} bubble(s) across ${threads.length} thread(s).`);
|
|
174
|
+
console.log('Re-run with --apply after quitting Cursor.');
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
await ensureCursorClosed();
|
|
179
|
+
console.log(`\nThis permanently deletes ${threads.length} thread(s) and their on-disk transcripts.`);
|
|
180
|
+
const typed = await promptLine(`Type "${PRUNE_CONFIRM_PHRASE}" to confirm: `);
|
|
181
|
+
if (typed !== PRUNE_CONFIRM_PHRASE) {
|
|
182
|
+
console.log('Confirmation failed. Nothing was deleted.');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const result = await pruneCursorThreads(threads, true);
|
|
187
|
+
console.log(
|
|
188
|
+
`Deleted ${result.bubblesDeleted} bubble(s), ${result.headersRemoved} header(s), ` +
|
|
189
|
+
`${result.transcriptDirsRemoved} transcript dir(s) across ${result.composerIds.length} thread(s).`,
|
|
190
|
+
);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export const runExportCursorCli = async (argv = process.argv.slice(2)): Promise<void> => {
|
|
194
|
+
if (argv.includes('--help') || argv.includes('-h') || argv.length === 0) {
|
|
195
|
+
console.log(getCursorHelpText());
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const { subcommand, rest } = resolveSubcommand(argv);
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
await dispatchCursorSubcommand(subcommand, rest);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
if (error instanceof CliUsageError) {
|
|
205
|
+
console.error(error.message);
|
|
206
|
+
console.error('');
|
|
207
|
+
console.error(getCursorHelpText());
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (error instanceof Error) {
|
|
212
|
+
console.error(error.message);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
throw error;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const dispatchCursorSubcommand = async (subcommand: CursorSubcommand, rest: string[]): Promise<void> => {
|
|
221
|
+
if (subcommand === 'list') {
|
|
222
|
+
await runCursorList(rest);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (subcommand === 'recover') {
|
|
227
|
+
await runCursorRecover(rest);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (subcommand === 'prune') {
|
|
232
|
+
await runCursorPrune(rest);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
await runCursorExportCommand(rest);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// Surfaces the resolved Cursor data dir for diagnostics in error messages.
|
|
240
|
+
export const getResolvedCursorUserDir = (): string => resolveCursorUserDir();
|
|
241
|
+
|
|
242
|
+
if (import.meta.main) {
|
|
243
|
+
await runExportCursorCli();
|
|
244
|
+
}
|