spiracha 1.1.1 → 1.2.0

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 (51) hide show
  1. package/AGENTS.md +13 -7
  2. package/README.md +6 -2
  3. package/apps/ui/AGENTS.md +2 -0
  4. package/apps/ui/README.md +3 -1
  5. package/apps/ui/dist/client/assets/{analytics-CqWZmyV6.js → analytics-Cv0JMDN2.js} +1 -1
  6. package/apps/ui/dist/client/assets/{checkbox-DXM4lkJq.js → checkbox-DjHij7DJ.js} +1 -1
  7. package/apps/ui/dist/client/assets/{data-table-DnPYMPCD.js → data-table-Bgnh7phF.js} +1 -1
  8. package/apps/ui/dist/client/assets/{delete-confirm-dialog-CcZaRX33.js → delete-confirm-dialog-CIZy_LXD.js} +1 -1
  9. package/apps/ui/dist/client/assets/download-DQtfva4z.js +1 -0
  10. package/apps/ui/dist/client/assets/{es2015-Bm0kEzx2.js → es2015-DsDKdYCE.js} +1 -1
  11. package/apps/ui/dist/client/assets/{formatters-C12LmYaa.js → formatters-CWFrMKSn.js} +1 -1
  12. package/apps/ui/dist/client/assets/{index-DdJ7ahIt.js → index-C_-e0lDI.js} +2 -2
  13. package/apps/ui/dist/client/assets/{input-CEsI7EpI.js → input-BbgApiqZ.js} +1 -1
  14. package/apps/ui/dist/client/assets/{metric-card-9jwBF7rG.js → metric-card-BJX5rkHK.js} +1 -1
  15. package/apps/ui/dist/client/assets/{page-header-Dr_h1CVv.js → page-header-ODLuGLAB.js} +1 -1
  16. package/apps/ui/dist/client/assets/{projects._project-uyNGnpjH.js → projects._project-C2Pys_bB.js} +1 -1
  17. package/apps/ui/dist/client/assets/{projects._project-zoM8d2nH.js → projects._project-CHvAKvlu.js} +1 -1
  18. package/apps/ui/dist/client/assets/{projects.index-D1CWVN-O.js → projects.index-BmwtS1x-.js} +1 -1
  19. package/apps/ui/dist/client/assets/{projects.index-DukMuny6.js → projects.index-CuLw73mt.js} +1 -1
  20. package/apps/ui/dist/client/assets/{routes-Gr2Wwh83.js → routes-CfnaTOlj.js} +1 -1
  21. package/apps/ui/dist/client/assets/{select-CFim44gT.js → select-B1kH_5lx.js} +1 -1
  22. package/apps/ui/dist/client/assets/{settings-DqhyDxo2.js → settings-mYTB3sso.js} +1 -1
  23. package/apps/ui/dist/client/assets/{threads._threadId-DT75NiBa.js → threads._threadId-CUiCZSwo.js} +1 -1
  24. package/apps/ui/dist/client/assets/{threads._threadId-Df5VXIuZ.js → threads._threadId-C_47okme.js} +1 -1
  25. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-kj_QB_26.js +99 -0
  26. package/apps/ui/dist/server/assets/{analytics-BMxW_bZL.js → analytics-2QpLKjlG.js} +1 -1
  27. package/apps/ui/dist/server/assets/{codex-queries-CAF6HYiG.js → codex-queries-BH4Cb0v3.js} +2 -2
  28. package/apps/ui/dist/server/assets/{codex-server-BFZq2Y2O.js → codex-server-DqzruLmg.js} +35 -87
  29. package/apps/ui/dist/server/assets/{download-C5rkk_Bo.js → download-Drctxary.js} +7 -7
  30. package/apps/ui/dist/server/assets/{projects._project-CcJLp_A8.js → projects._project-DreIU5b0.js} +3 -3
  31. package/apps/ui/dist/server/assets/{projects._project-CJ7l0ynC.js → projects._project-gT01HBqH.js} +2 -2
  32. package/apps/ui/dist/server/assets/{projects.index-srtogpuF.js → projects.index-BYmgSGAj.js} +1 -1
  33. package/apps/ui/dist/server/assets/{router-C_w-haH6.js → router-Qj5Kn7bl.js} +6 -6
  34. package/apps/ui/dist/server/assets/{routes-BhbxvJE7.js → routes-BtcXuK0x.js} +2 -2
  35. package/apps/ui/dist/server/assets/{routes-CPe-ppmC.js → routes-_LbCIjtJ.js} +2 -2
  36. package/apps/ui/dist/server/assets/{threads._threadId-euyNckhj.js → threads._threadId-D5m6ypGw.js} +3 -3
  37. package/apps/ui/dist/server/assets/{threads._threadId-Ba7vv6-K.js → threads._threadId-DcbAJkwf.js} +2 -2
  38. package/apps/ui/dist/server/server.js +19 -36
  39. package/bin/codex-chats-claude.js +5 -0
  40. package/bin/codex-chats.js +5 -0
  41. package/bin/spiracha.js +5 -0
  42. package/package.json +9 -6
  43. package/src/lib/codex-browser-export.ts +28 -3
  44. package/src/lib/codex-exporter-cli.ts +9 -9
  45. package/src/lib/codex-exporter-transcript.ts +16 -190
  46. package/src/lib/codex-exporter-types.ts +1 -1
  47. package/src/lib/codex-exporter.ts +0 -1
  48. package/src/lib/interactive-cli.ts +2 -2
  49. package/src/mcp-server.ts +2 -2
  50. package/apps/ui/dist/client/assets/download-DOwxk-cG.js +0 -1
  51. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-C0V305Nt.js +0 -99
@@ -40,16 +40,16 @@ export const convertSessionFile = async (target: ExportTarget, options: CodexCli
40
40
  return null;
41
41
  }
42
42
 
43
- if (options.optimized) {
44
- return transcriptState.sections.join('\n\n').trimEnd() + '\n';
45
- }
46
-
47
43
  const title = getTitle(target, transcriptState.sessionMeta);
48
- const metadata = buildMetadataEntries(target, transcriptState.sessionMeta, options);
49
44
  const parts = [
50
45
  renderDocumentTitle(title, options.outputFormat),
51
46
  '',
52
- renderMetadataBlock(metadata, options.outputFormat),
47
+ options.includeMetadata
48
+ ? renderMetadataBlock(
49
+ buildMetadataEntries(target, transcriptState.sessionMeta, options),
50
+ options.outputFormat,
51
+ )
52
+ : '',
53
53
  ...transcriptState.sections,
54
54
  ].filter(Boolean);
55
55
  return parts.join('\n').trimEnd() + '\n';
@@ -69,7 +69,6 @@ export const writeSessionFileExport = async (
69
69
  assistantModel: target.thread?.model ?? null,
70
70
  sections: [],
71
71
  sessionMeta: {},
72
- startedTranscript: false,
73
72
  };
74
73
  let wroteSection = false;
75
74
 
@@ -82,7 +81,7 @@ export const writeSessionFileExport = async (
82
81
  continue;
83
82
  }
84
83
 
85
- transcriptStream.write(transform(wroteSection ? `${getSectionSeparator(options)}${block}` : block));
84
+ transcriptStream.write(transform(wroteSection ? `${getSectionSeparator()}${block}` : block));
86
85
  wroteSection = true;
87
86
  }
88
87
  await finalizeExportWriteStream(transcriptStream);
@@ -124,7 +123,6 @@ type CodexTranscriptState = {
124
123
  assistantModel: string | null;
125
124
  sessionMeta: SessionMeta;
126
125
  sections: string[];
127
- startedTranscript: boolean;
128
126
  };
129
127
 
130
128
  const collectCodexTranscript = async (
@@ -136,7 +134,6 @@ const collectCodexTranscript = async (
136
134
  assistantModel,
137
135
  sections: [],
138
136
  sessionMeta: {},
139
- startedTranscript: false,
140
137
  };
141
138
 
142
139
  for await (const parsed of readJsonlObjects(sessionFile)) {
@@ -146,9 +143,7 @@ const collectCodexTranscript = async (
146
143
  return state;
147
144
  };
148
145
 
149
- const getSectionSeparator = (options: CodexCliOptions) => {
150
- return options.optimized ? '\n\n' : '\n';
151
- };
146
+ const getSectionSeparator = () => '\n';
152
147
 
153
148
  const processCodexTranscriptRecord = (
154
149
  parsed: Record<string, JsonValue>,
@@ -181,58 +176,23 @@ const renderCodexTranscriptRecord = (
181
176
  return '';
182
177
  }
183
178
 
184
- return options.optimized
185
- ? renderCompactToolBlock(tool, options.outputFormat)
186
- : renderToolBlock(tool, options.outputFormat);
179
+ return renderToolBlock(tool, options.outputFormat);
187
180
  };
188
181
 
189
182
  const processCodexMessageRecord = (message: MessageRecord, options: CodexCliOptions, state: CodexTranscriptState) => {
190
- if (options.optimized) {
191
- return processOptimizedCodexMessageRecord(message, options, state);
192
- }
193
-
194
183
  return renderMessageBlock(message, options.outputFormat, state.assistantModel, options.includeCommentary);
195
184
  };
196
185
 
197
- const processOptimizedCodexMessageRecord = (
198
- message: MessageRecord,
199
- options: CodexCliOptions,
200
- state: CodexTranscriptState,
201
- ) => {
202
- if (message.role !== 'user' && message.role !== 'assistant') {
203
- return '';
204
- }
205
-
206
- if (message.role === 'assistant' && message.phase === 'commentary' && !options.includeCommentary) {
207
- return '';
208
- }
209
-
210
- const compact = compactMessageText(message, true);
211
- if (!compact) {
212
- return '';
213
- }
214
-
215
- if (!state.startedTranscript) {
216
- if (shouldSkipOptimizedPrelude(message.role, compact)) {
217
- return '';
218
- }
219
- state.startedTranscript = true;
220
- }
221
-
222
- return renderCompactBlock(message, compact, options.outputFormat, state.assistantModel);
223
- };
224
-
225
186
  const buildStreamExportPrefix = (target: ExportTarget, sessionMeta: SessionMeta, options: CodexCliOptions) => {
226
- if (options.optimized) {
187
+ if (!options.includeMetadata) {
227
188
  return '';
228
189
  }
229
190
 
230
191
  const title = getTitle(target, sessionMeta);
231
- const metadata = buildMetadataEntries(target, sessionMeta, options);
232
192
  const parts = [
233
193
  renderDocumentTitle(title, options.outputFormat),
234
194
  '',
235
- renderMetadataBlock(metadata, options.outputFormat),
195
+ renderMetadataBlock(buildMetadataEntries(target, sessionMeta, options), options.outputFormat),
236
196
  ]
237
197
  .filter(Boolean)
238
198
  .join('\n');
@@ -240,13 +200,6 @@ const buildStreamExportPrefix = (target: ExportTarget, sessionMeta: SessionMeta,
240
200
  return `${parts}\n`;
241
201
  };
242
202
 
243
- export const compactMessageText = (message: MessageRecord, optimized: boolean): string => {
244
- const rawText = extractText(message.content);
245
- const cleaned = stripPreviewBlock(rawText);
246
-
247
- return optimized ? optimizePlainText(optimizeRenderedText(cleaned)) : cleaned.trim();
248
- };
249
-
250
203
  export const formatToolOutputSummary = (outputText: string, outputFormat: ExportFormat): string => {
251
204
  if (!outputText) {
252
205
  return '';
@@ -308,27 +261,6 @@ const getTitle = (target: ExportTarget, sessionMeta: SessionMeta): string => {
308
261
  return sessionMeta.id ?? path.basename(target.sessionFile, '.jsonl');
309
262
  };
310
263
 
311
- const shouldSkipOptimizedPrelude = (role: string, text: string): boolean => {
312
- if (role !== 'user') {
313
- return true;
314
- }
315
-
316
- return (
317
- text.startsWith('AGENTS.md instructions for ') ||
318
- text.startsWith('# AGENTS.md instructions for ') ||
319
- text.startsWith('<permissions instructions>') ||
320
- text.startsWith('<environment_context>') ||
321
- text.startsWith('<app-context>') ||
322
- text.startsWith('<collaboration_mode>') ||
323
- text.startsWith('<skills_instructions>') ||
324
- text.startsWith('You are Codex, a coding agent based on GPT-5.') ||
325
- text.startsWith('Read this before making changes.') ||
326
- text.includes('Filesystem sandboxing defines which files can be read or written.') ||
327
- text.includes('approval_policy') ||
328
- text.includes('base_instructions')
329
- );
330
- };
331
-
332
264
  const buildMetadataEntries = (
333
265
  target: ExportTarget,
334
266
  sessionMeta: SessionMeta,
@@ -585,7 +517,7 @@ const renderMessageBlock = (
585
517
  return '';
586
518
  }
587
519
 
588
- const text = cleanExtractedText(extractText(message.content)).trim();
520
+ const text = cleanExtractedText(stripPreviewBlock(extractText(message.content))).trim();
589
521
  if (!text || shouldSkipMessage(message.role, text)) {
590
522
  return '';
591
523
  }
@@ -606,36 +538,6 @@ const renderToolBlock = (tool: ToolRecord, outputFormat: ExportFormat): string =
606
538
  return summary ? renderSection('Tool Output', summary, outputFormat) : '';
607
539
  };
608
540
 
609
- const renderCompactBlock = (
610
- message: MessageRecord,
611
- text: string,
612
- outputFormat: ExportFormat,
613
- assistantModel: string | null,
614
- ): string => {
615
- const prefix = message.role === 'user' ? 'U:' : `${formatModelLabel(message.model ?? assistantModel)}:`;
616
- const lines = text.split('\n');
617
- const [firstLine, ...rest] = lines;
618
-
619
- if (rest.length === 0) {
620
- return `${prefix} ${normalizeCompactLiteral(firstLine, outputFormat)}`;
621
- }
622
-
623
- return [
624
- `${prefix} ${normalizeCompactLiteral(firstLine, outputFormat)}`,
625
- ...rest.map((line) => normalizeCompactLiteral(line, outputFormat)),
626
- ].join('\n');
627
- };
628
-
629
- const renderCompactToolBlock = (tool: ToolRecord, outputFormat: ExportFormat): string => {
630
- if (tool.kind === 'call') {
631
- const details = formatCompactToolCall(tool, outputFormat);
632
- return details ? `T: ${details}` : '';
633
- }
634
-
635
- const summary = formatCompactToolOutput(tool.outputText ?? '');
636
- return summary ? `R: ${summary}` : '';
637
- };
638
-
639
541
  const stripPreviewBlock = (text: string): string => {
640
542
  const parts = text
641
543
  .split(/\n{2,}/)
@@ -662,49 +564,15 @@ const stripPreviewBlock = (text: string): string => {
662
564
  return parts.slice(1).join('\n\n');
663
565
  };
664
566
 
665
- const optimizeRenderedText = (text: string): string => {
666
- return text
667
- .replace(/^\*Phase:\s+`[^`]+`\*\s*\n*/gm, '')
668
- .replace(/^\s*<image\b[^>]*>\s*$/gim, '')
669
- .replace(/^\s*<\/image>\s*$/gim, '')
670
- .replace(/^\s*\[Image attached\]\s*$/gim, '')
671
- .replace(/^#{1,6}\s+/gm, '')
672
- .replace(/^```[^\n]*\n?/gm, '')
673
- .replace(/\n```$/gm, '')
674
- .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
675
- .replace(/^##\s+User\s*$/gm, 'User:')
676
- .replace(/^##\s+Assistant\s*$/gm, 'Assistant:')
677
- .replace(/`([^`]+)`/g, '$1')
678
- .replace(/\*\*([^*]+)\*\*/g, '$1')
679
- .replace(/\*([^*\n]+)\*/g, '$1')
680
- .replace(/\n{3,}/g, '\n\n')
681
- .trim();
682
- };
683
-
684
- const optimizePlainText = (text: string): string => {
685
- const normalized = text
686
- .replace(/\r/g, '')
687
- .replace(/^\s*<image\b[^>]*>\s*$/gim, '')
688
- .replace(/^\s*<\/image>\s*$/gim, '')
689
- .replace(/^\s*\[Image attached\]\s*$/gim, '')
690
- .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
691
- .replace(/`([^`]+)`/g, '$1')
692
- .replace(/\*\*([^*]+)\*\*/g, '$1')
693
- .replace(/\*([^*\n]+)\*/g, '$1');
694
-
695
- return normalized
696
- .split('\n')
697
- .map((line) => line.replace(/[ \t]+$/g, ''))
698
- .join('\n')
699
- .replace(/\n{3,}/g, '\n\n')
700
- .trim();
701
- };
702
-
703
567
  const shouldSkipMessage = (role: string, text: string): boolean => {
704
568
  if (text.startsWith('<environment_context>')) {
705
569
  return true;
706
570
  }
707
571
 
572
+ if (text.startsWith('AGENTS.md instructions for ')) {
573
+ return true;
574
+ }
575
+
708
576
  if (text.startsWith('# AGENTS.md instructions for ')) {
709
577
  return true;
710
578
  }
@@ -725,44 +593,6 @@ const formatToolCallDetails = (tool: ToolRecord, outputFormat: ExportFormat): st
725
593
  return details.cmd ? `Command: ${formatInlineLiteral(details.cmd, outputFormat)}` : '';
726
594
  };
727
595
 
728
- const formatCompactToolCall = (tool: ToolRecord, outputFormat: ExportFormat): string => {
729
- if (tool.name === 'exec_command') {
730
- const details = parseExecCommandArguments(tool.argumentsText);
731
- if (!details.cmd) {
732
- return 'exec_command';
733
- }
734
-
735
- const command = formatInlineLiteral(details.cmd, outputFormat);
736
- return details.workdir ? `exec_command ${command} @ ${details.workdir}` : `exec_command ${command}`;
737
- }
738
-
739
- return tool.callId ? `${tool.name} (${tool.callId})` : tool.name;
740
- };
741
-
742
- const formatCompactToolOutput = (outputText: string): string => {
743
- if (!outputText) {
744
- return '';
745
- }
746
-
747
- const lines = outputText
748
- .split('\n')
749
- .map((line) => line.trim())
750
- .filter(Boolean);
751
-
752
- const exit = lines.find((line) => line.startsWith('Process exited with code '));
753
- const wall = lines.find((line) => line.startsWith('Wall time: '));
754
-
755
- if (exit && wall) {
756
- return `${exit.replace('Process ', '')}; ${wall.toLowerCase()}`;
757
- }
758
-
759
- if (exit) {
760
- return exit.replace('Process ', '');
761
- }
762
-
763
- return '';
764
- };
765
-
766
596
  const extractText = (content: JsonValue): string => {
767
597
  if (typeof content === 'string') {
768
598
  return content;
@@ -802,7 +632,3 @@ const extractContentPart = (value: JsonValue): string => {
802
632
 
803
633
  return text ?? '';
804
634
  };
805
-
806
- const normalizeCompactLiteral = (value: string, outputFormat: ExportFormat): string => {
807
- return outputFormat === 'md' ? value : value.replace(/`([^`]+)`/g, '$1');
808
- };
@@ -9,7 +9,7 @@ export type CodexCliOptions = {
9
9
  cwdFilter: string | null;
10
10
  projectFilter: string | null;
11
11
  threadIds: string[];
12
- optimized: boolean;
12
+ includeMetadata: boolean;
13
13
  includeCommentary: boolean;
14
14
  includeTools: boolean;
15
15
  outputFormat: ExportFormat;
@@ -27,7 +27,6 @@ export {
27
27
  toOutputRelativePath,
28
28
  } from './codex-exporter-db';
29
29
  export {
30
- compactMessageText,
31
30
  convertSessionFile,
32
31
  formatToolOutputSummary,
33
32
  parseExecCommandArguments,
@@ -307,7 +307,7 @@ const promptForCommonCodexOptions = async (
307
307
  target: Pick<CodexCliOptions, 'threadIds' | 'cwdFilter' | 'projectFilter'>,
308
308
  ): Promise<CodexCliOptions> => {
309
309
  const outputFormat = await promptForOutputFormat(rl);
310
- const optimized = await promptYesNo(rl, 'Use optimized output? [y/N]: ', false);
310
+ const includeMetadata = await promptYesNo(rl, 'Include metadata? [Y/n]: ', true);
311
311
  const includeCommentary = await promptYesNo(rl, 'Include commentary messages? [y/N]: ', false);
312
312
  const includeTools = await promptYesNo(rl, 'Include tool logs? [y/N]: ', false);
313
313
  const flat = await promptYesNo(rl, 'Write to a flat output folder? [y/N]: ', false);
@@ -318,9 +318,9 @@ const promptForCommonCodexOptions = async (
318
318
  dbPath,
319
319
  flat,
320
320
  includeCommentary,
321
+ includeMetadata,
321
322
  includeTools,
322
323
  inputDir: DEFAULT_INPUT_DIR,
323
- optimized,
324
324
  outputDir: outputDir ?? resolveInteractiveOutputDir(target.cwdFilter),
325
325
  outputFormat,
326
326
  projectFilter: target.projectFilter,
package/src/mcp-server.ts CHANGED
@@ -24,9 +24,9 @@ const exportCodexChatsInputSchema = {
24
24
  dbPath: z.string().optional().describe('Optional override for the Codex SQLite database'),
25
25
  deeplinks: z.array(z.string()).optional().describe('Optional Codex deeplinks like codex://threads/<thread-id>'),
26
26
  flat: z.boolean().optional().describe('Write output into a single flat folder'),
27
+ includeMetadata: z.boolean().optional().describe('Include the chat metadata section at the top of each export'),
27
28
  includeTools: z.boolean().optional().describe('Include exec_command tool logs'),
28
29
  inputDir: z.string().optional().describe('Optional override for the Codex sessions directory'),
29
- optimized: z.boolean().optional().describe('Suppress metadata and optimize for compact text'),
30
30
  outputDir: z.string().optional().describe('Optional output directory'),
31
31
  outputFormat: z.enum(['md', 'txt']).optional().describe('Output format'),
32
32
  project: z.string().optional().describe('Optional project name matched against path basename'),
@@ -60,9 +60,9 @@ server.registerTool(
60
60
  dbPath: expandHome(args.dbPath ?? DEFAULT_DB_PATH),
61
61
  flat: args.flat ?? false,
62
62
  includeCommentary: true,
63
+ includeMetadata: args.includeMetadata ?? true,
63
64
  includeTools: args.includeTools ?? false,
64
65
  inputDir: expandHome(args.inputDir ?? DEFAULT_INPUT_DIR),
65
- optimized: args.optimized ?? false,
66
66
  outputDir: args.outputDir ? expandHome(args.outputDir) : resolveDefaultOutputDir(cwdFilter),
67
67
  outputFormat: args.outputFormat ?? 'md',
68
68
  projectFilter: args.project ?? null,
@@ -1 +0,0 @@
1
- import{a as e,c as t,d as n,l as r,o as i,s as a,u as o}from"./delete-confirm-dialog-CcZaRX33.js";import{t as s}from"./checkbox-DXM4lkJq.js";import{a as c,i as l,n as u,r as d,t as f}from"./select-CFim44gT.js";import{H as p,W as m,dt as h,g,mt as _,pt as v}from"./index-DdJ7ahIt.js";var y=m(`download`,[[`path`,{d:`M12 15V3`,key:`m9g1x1`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}],[`path`,{d:`m7 10 5 5 5-5`,key:`brsn70`}]]),b=m(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]),x=_(v(),1),S=h();function C({...e}){return(0,S.jsx)(o,{"data-slot":`dialog`,...e})}function w({...e}){return(0,S.jsx)(r,{"data-slot":`dialog-portal`,...e})}function T({className:e,...n}){return(0,S.jsx)(t,{"data-slot":`dialog-overlay`,className:p(`data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=open]:animate-in`,e),...n})}function E({className:t,children:n,showCloseButton:r=!0,...a}){return(0,S.jsxs)(w,{"data-slot":`dialog-portal`,children:[(0,S.jsx)(T,{}),(0,S.jsxs)(i,{"data-slot":`dialog-content`,className:p(`data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg outline-none duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:max-w-lg`,t),...a,children:[n,r&&(0,S.jsxs)(e,{"data-slot":`dialog-close`,className:`absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0`,children:[(0,S.jsx)(b,{}),(0,S.jsx)(`span`,{className:`sr-only`,children:`Close`})]})]})]})}function D({className:e,...t}){return(0,S.jsx)(`div`,{"data-slot":`dialog-header`,className:p(`flex flex-col gap-2 text-center sm:text-left`,e),...t})}function O({className:t,showCloseButton:n=!1,children:r,...i}){return(0,S.jsxs)(`div`,{"data-slot":`dialog-footer`,className:p(`flex flex-col-reverse gap-2 sm:flex-row sm:justify-end`,t),...i,children:[r,n&&(0,S.jsx)(e,{asChild:!0,children:(0,S.jsx)(g,{variant:`outline`,children:`Close`})})]})}function k({className:e,...t}){return(0,S.jsx)(n,{"data-slot":`dialog-title`,className:p(`font-semibold text-lg leading-none`,e),...t})}function A({className:e,...t}){return(0,S.jsx)(a,{"data-slot":`dialog-description`,className:p(`text-muted-foreground text-sm`,e),...t})}function j({open:e,pending:t=!1,title:n=`Export thread`,onExport:r,onOpenChange:i}){let[a,o]=(0,x.useState)(`md`),[p,m]=(0,x.useState)(!1),[h,_]=(0,x.useState)(!1),[v,y]=(0,x.useState)(!0);return(0,S.jsx)(C,{open:e,onOpenChange:i,children:(0,S.jsxs)(E,{className:`border-[var(--border)] bg-[var(--panel)] text-[var(--foreground)]`,children:[(0,S.jsxs)(D,{children:[(0,S.jsx)(k,{children:n}),(0,S.jsx)(A,{className:`text-[var(--muted-foreground)]`,children:`Choose the transcript format and whether the export includes tool calls.`})]}),(0,S.jsxs)(`div`,{className:`space-y-5 py-2`,children:[(0,S.jsxs)(`div`,{className:`space-y-2`,children:[(0,S.jsx)(`label`,{className:`font-medium text-sm`,htmlFor:`output-format`,children:`Output format`}),(0,S.jsxs)(f,{value:a,onValueChange:e=>o(e),children:[(0,S.jsx)(l,{id:`output-format`,className:`border-[var(--border)] bg-[var(--panel-secondary)]`,children:(0,S.jsx)(c,{placeholder:`Choose a format`})}),(0,S.jsxs)(u,{children:[(0,S.jsx)(d,{value:`md`,children:`Markdown (.md)`}),(0,S.jsx)(d,{value:`txt`,children:`Plain text (.txt)`})]})]})]}),(0,S.jsxs)(`div`,{className:`flex items-center gap-3 rounded-2xl border border-[var(--border)] bg-[var(--panel-secondary)] p-3`,children:[(0,S.jsx)(s,{"aria-label":`Optimized transcript`,checked:p,onCheckedChange:e=>m(e===!0)}),(0,S.jsxs)(`span`,{className:`space-y-1`,children:[(0,S.jsx)(`span`,{className:`block font-medium text-sm`,children:`Optimized transcript`}),(0,S.jsx)(`span`,{className:`block text-[var(--muted-foreground)] text-sm`,children:`Removes metadata and condenses the transcript for readability and token efficiency.`})]})]}),(0,S.jsxs)(`div`,{className:`flex items-center gap-3 rounded-2xl border border-[var(--border)] bg-[var(--panel-secondary)] p-3`,children:[(0,S.jsx)(s,{"aria-label":`Include commentary`,checked:h,onCheckedChange:e=>_(e===!0)}),(0,S.jsxs)(`span`,{className:`space-y-1`,children:[(0,S.jsx)(`span`,{className:`block font-medium text-sm`,children:`Include commentary`}),(0,S.jsx)(`span`,{className:`block text-[var(--muted-foreground)] text-sm`,children:`Includes assistant commentary-phase updates in the exported transcript.`})]})]}),(0,S.jsxs)(`div`,{className:`flex items-center gap-3 rounded-2xl border border-[var(--border)] bg-[var(--panel-secondary)] p-3`,children:[(0,S.jsx)(s,{"aria-label":`Include tool calls`,checked:v,onCheckedChange:e=>y(e===!0)}),(0,S.jsxs)(`span`,{className:`space-y-1`,children:[(0,S.jsx)(`span`,{className:`block font-medium text-sm`,children:`Include tool calls`}),(0,S.jsx)(`span`,{className:`block text-[var(--muted-foreground)] text-sm`,children:`Includes tool-call summaries and tool-output summaries in the export.`})]})]})]}),(0,S.jsxs)(O,{children:[(0,S.jsx)(g,{className:`rounded-full`,variant:`outline`,onClick:()=>i(!1),children:`Cancel`}),(0,S.jsx)(g,{className:`rounded-full`,disabled:t,onClick:()=>r({includeCommentary:h,includeTools:v,optimized:p,outputFormat:a}),children:t?`Exporting...`:`Download export`})]})]})})}var M=6,N=250,P=3e4,F=(e,t,n,r)=>{e[t](`[spiracha:download] ${n}`,r)},I=e=>new Promise(t=>{window.setTimeout(t,e)}),L=(e,t,n)=>{let r=e.createElement(`a`);r.href=t,r.download=n,e.body.append(r),r.click(),r.remove()},R=e=>e>=200&&e<400||e===405,z=async(e,t,{fetchImpl:n=fetch,logger:r=console,maxAttempts:i=M,retryDelayMs:a=N,sleep:o=I}={})=>{for(let s=1;s<=i;s+=1){try{let i=await n(e,{cache:`no-store`,method:`HEAD`});if(R(i.status)){F(r,`info`,`url_ready`,{attempt:s,downloadUrl:e,fileName:t,status:i.status});return}F(r,`warn`,`url_not_ready`,{attempt:s,downloadUrl:e,fileName:t,status:i.status})}catch(n){F(r,`warn`,`url_probe_failed`,{attempt:s,downloadUrl:e,error:n instanceof Error?n.message:String(n),fileName:t})}s<i&&await o(a)}throw Error(`Download file was not available after ${i} attempts: ${t}`)},B=async(e,t,{documentRef:n=document,fetchImpl:r=fetch,logger:i=console,maxAttempts:a=M,retryDelayMs:o=N,sleep:s=I}={})=>{F(i,`info`,`start`,{downloadUrl:t,fileName:e}),await z(t,e,{fetchImpl:r,logger:i,maxAttempts:a,retryDelayMs:o,sleep:s}),L(n,t,e),F(i,`info`,`triggered`,{downloadUrl:t,fileName:e})},V=(e,t,n,{createObjectUrl:r=e=>URL.createObjectURL(e),documentRef:i=document,logger:a=console,revokeDelayMs:o=P,revokeObjectUrl:s=e=>URL.revokeObjectURL(e),schedule:c=(e,t)=>{window.setTimeout(e,t)}}={})=>{F(a,`info`,`inline_start`,{fileName:e,mimeType:n,sizeBytes:t.length});let l=r(new Blob([t],{type:n}));L(i,l,e),c(()=>s(l),o),F(a,`info`,`inline_triggered`,{fileName:e,mimeType:n,sizeBytes:t.length})};export{y as a,b as i,B as n,j as r,V as t};
@@ -1,99 +0,0 @@
1
- //#region \0tanstack-start-manifest:v
2
- var tsrStartManifest = () => ({
3
- routes: {
4
- __root__: {
5
- filePath: "/Users/rhaq/workspace/spiracha/apps/ui/src/routes/__root.tsx",
6
- children: [
7
- "/",
8
- "/$threadId",
9
- "/analytics",
10
- "/settings",
11
- "/projects/$project",
12
- "/threads/$threadId",
13
- "/projects/"
14
- ],
15
- preloads: ["/assets/index-DdJ7ahIt.js"]
16
- },
17
- "/": {
18
- filePath: "/Users/rhaq/workspace/spiracha/apps/ui/src/routes/index.tsx",
19
- children: void 0,
20
- preloads: [
21
- "/assets/routes-Gr2Wwh83.js",
22
- "/assets/metric-card-9jwBF7rG.js",
23
- "/assets/page-header-Dr_h1CVv.js",
24
- "/assets/formatters-C12LmYaa.js"
25
- ]
26
- },
27
- "/$threadId": {
28
- filePath: "/Users/rhaq/workspace/spiracha/apps/ui/src/routes/$threadId.tsx",
29
- children: void 0,
30
- preloads: ["/assets/_threadId-CAIeH5mq.js"]
31
- },
32
- "/analytics": {
33
- filePath: "/Users/rhaq/workspace/spiracha/apps/ui/src/routes/analytics.tsx",
34
- children: void 0,
35
- preloads: [
36
- "/assets/analytics-CqWZmyV6.js",
37
- "/assets/data-table-DnPYMPCD.js",
38
- "/assets/metric-card-9jwBF7rG.js",
39
- "/assets/page-header-Dr_h1CVv.js",
40
- "/assets/select-CFim44gT.js",
41
- "/assets/formatters-C12LmYaa.js"
42
- ]
43
- },
44
- "/settings": {
45
- filePath: "/Users/rhaq/workspace/spiracha/apps/ui/src/routes/settings.tsx",
46
- children: void 0,
47
- preloads: [
48
- "/assets/settings-DqhyDxo2.js",
49
- "/assets/page-header-Dr_h1CVv.js",
50
- "/assets/checkbox-DXM4lkJq.js"
51
- ]
52
- },
53
- "/projects/$project": {
54
- filePath: "/Users/rhaq/workspace/spiracha/apps/ui/src/routes/projects.$project.tsx",
55
- children: void 0,
56
- preloads: [
57
- "/assets/projects._project-uyNGnpjH.js",
58
- "/assets/data-table-DnPYMPCD.js",
59
- "/assets/delete-confirm-dialog-CcZaRX33.js",
60
- "/assets/download-DOwxk-cG.js",
61
- "/assets/page-header-Dr_h1CVv.js",
62
- "/assets/input-CEsI7EpI.js",
63
- "/assets/formatters-C12LmYaa.js",
64
- "/assets/projects._project-zoM8d2nH.js"
65
- ]
66
- },
67
- "/threads/$threadId": {
68
- filePath: "/Users/rhaq/workspace/spiracha/apps/ui/src/routes/threads.$threadId.tsx",
69
- children: void 0,
70
- preloads: [
71
- "/assets/threads._threadId-DT75NiBa.js",
72
- "/assets/threads._threadId-Df5VXIuZ.js",
73
- "/assets/delete-confirm-dialog-CcZaRX33.js",
74
- "/assets/download-DOwxk-cG.js",
75
- "/assets/metric-card-9jwBF7rG.js",
76
- "/assets/page-header-Dr_h1CVv.js",
77
- "/assets/checkbox-DXM4lkJq.js",
78
- "/assets/formatters-C12LmYaa.js",
79
- "/assets/es2015-Bm0kEzx2.js"
80
- ]
81
- },
82
- "/projects/": {
83
- filePath: "/Users/rhaq/workspace/spiracha/apps/ui/src/routes/projects.index.tsx",
84
- children: void 0,
85
- preloads: [
86
- "/assets/projects.index-D1CWVN-O.js",
87
- "/assets/data-table-DnPYMPCD.js",
88
- "/assets/delete-confirm-dialog-CcZaRX33.js",
89
- "/assets/page-header-Dr_h1CVv.js",
90
- "/assets/input-CEsI7EpI.js",
91
- "/assets/formatters-C12LmYaa.js",
92
- "/assets/projects.index-DukMuny6.js"
93
- ]
94
- }
95
- },
96
- clientEntry: "/assets/index-DdJ7ahIt.js"
97
- });
98
- //#endregion
99
- export { tsrStartManifest };