export.js
1 import * as fs from 'node:fs'; 2 import { cli, Strategy } from '@jackwener/opencli/registry'; 3 function makeExportCommand(site, readSelector) { 4 return cli({ 5 site, 6 name: 'export', 7 description: `Export the current ${site} conversation to a Markdown file`, 8 domain: 'localhost', 9 strategy: Strategy.UI, 10 browser: true, 11 args: [ 12 { name: 'output', required: false, help: `Output file (default: /tmp/${site}-export.md)` }, 13 ], 14 columns: ['Status', 'File', 'Messages'], 15 func: async (page, kwargs) => { 16 const outputPath = kwargs.output || `/tmp/${site}-export.md`; 17 const md = await page.evaluate(` 18 (function() { 19 const selectors = ${JSON.stringify(readSelector)}.split(','); 20 let messages = []; 21 22 for (const sel of selectors) { 23 const nodes = document.querySelectorAll(sel.trim()); 24 if (nodes.length > 0) { 25 messages = Array.from(nodes).map(n => n.innerText || n.textContent); 26 break; 27 } 28 } 29 30 if (messages.length === 0) { 31 const main = document.querySelector('main, [role="main"], .messages-list, [role="log"]'); 32 if (main) messages = [main.innerText || main.textContent]; 33 } 34 35 if (messages.length === 0) messages = [document.body.innerText]; 36 37 return messages.map((m, i) => '## Message ' + (i + 1) + '\\n\\n' + m.trim()).join('\\n\\n---\\n\\n'); 38 })() 39 `); 40 fs.writeFileSync(outputPath, `# ${site} Conversation Export\\n\\n` + md); 41 return [ 42 { 43 Status: 'Success', 44 File: outputPath, 45 Messages: md.split('## Message').length - 1, 46 }, 47 ]; 48 }, 49 }); 50 } 51 export const cursorExport = makeExportCommand('cursor', '[data-message-role]');