spiracha 2.1.0 → 2.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 (125) hide show
  1. package/AGENTS.md +27 -12
  2. package/README.md +37 -19
  3. package/apps/ui/AGENTS.md +18 -10
  4. package/apps/ui/README.md +17 -10
  5. package/apps/ui/src/components/analytics-breakdowns.tsx +106 -0
  6. package/apps/ui/src/components/antigravity-conversations-table.tsx +1 -0
  7. package/apps/ui/src/components/app-shell.tsx +45 -3
  8. package/apps/ui/src/components/data-table.tsx +17 -1
  9. package/apps/ui/src/components/delete-confirm-dialog.tsx +4 -3
  10. package/apps/ui/src/components/export-dialog.tsx +77 -62
  11. package/apps/ui/src/components/projects-table.tsx +4 -1
  12. package/apps/ui/src/components/route-error-panel.tsx +13 -0
  13. package/apps/ui/src/components/thread-goals-panel.tsx +50 -0
  14. package/apps/ui/src/components/thread-tools-panel.tsx +142 -0
  15. package/apps/ui/src/components/threads-table.tsx +4 -1
  16. package/apps/ui/src/lib/antigravity-server.ts +70 -17
  17. package/apps/ui/src/lib/antigravity-transcript-events.ts +46 -70
  18. package/apps/ui/src/lib/claude-code-server.ts +14 -4
  19. package/apps/ui/src/lib/codex-queries.ts +3 -3
  20. package/apps/ui/src/lib/codex-server.ts +3 -3
  21. package/apps/ui/src/lib/cursor-server.ts +41 -69
  22. package/apps/ui/src/lib/cursor-transcript-events.ts +11 -86
  23. package/apps/ui/src/lib/delete-batch.ts +52 -0
  24. package/apps/ui/src/lib/error-presentation.ts +43 -0
  25. package/apps/ui/src/lib/export-mutation.ts +20 -0
  26. package/apps/ui/src/lib/export-options.ts +15 -0
  27. package/apps/ui/src/lib/grok-server.ts +2 -3
  28. package/apps/ui/src/lib/kiro-server.ts +14 -2
  29. package/apps/ui/src/lib/mutation-error.ts +15 -0
  30. package/apps/ui/src/lib/opencode-server.ts +13 -2
  31. package/apps/ui/src/lib/path-utils.ts +1 -1
  32. package/apps/ui/src/lib/qoder-queries.ts +15 -0
  33. package/apps/ui/src/lib/qoder-transcript-events.ts +1 -1
  34. package/apps/ui/src/lib/route-state-reset.tsx +10 -0
  35. package/apps/ui/src/lib/settings-server.ts +33 -0
  36. package/apps/ui/src/lib/settings-store.tsx +82 -38
  37. package/apps/ui/src/lib/settings.ts +65 -0
  38. package/apps/ui/src/lib/source-session-export-server.ts +1 -1
  39. package/apps/ui/src/lib/thread-metadata.ts +22 -0
  40. package/apps/ui/src/lib/thread-transcript-stats.ts +10 -1
  41. package/apps/ui/src/lib/workspace-delete-navigation.ts +8 -0
  42. package/apps/ui/src/routeTree.gen.ts +282 -282
  43. package/apps/ui/src/routes/__root.tsx +12 -15
  44. package/apps/ui/src/routes/analytics.tsx +10 -61
  45. package/apps/ui/src/routes/antigravity-conversations.$conversationId.tsx +73 -19
  46. package/apps/ui/src/routes/antigravity.$workspaceKey.tsx +42 -60
  47. package/apps/ui/src/routes/antigravity.index.tsx +2 -2
  48. package/apps/ui/src/routes/claude-code-sessions.$sessionId.tsx +25 -11
  49. package/apps/ui/src/routes/claude-code.$workspaceKey.tsx +27 -32
  50. package/apps/ui/src/routes/claude-code.index.tsx +2 -2
  51. package/apps/ui/src/routes/codex.$project.tsx +33 -31
  52. package/apps/ui/src/routes/codex.index.tsx +5 -10
  53. package/apps/ui/src/routes/cursor-threads.$composerId.tsx +29 -16
  54. package/apps/ui/src/routes/cursor.$workspaceKey.tsx +33 -27
  55. package/apps/ui/src/routes/cursor.index.tsx +5 -2
  56. package/apps/ui/src/routes/grok-sessions.$sessionId.tsx +25 -12
  57. package/apps/ui/src/routes/grok.$workspaceKey.tsx +20 -26
  58. package/apps/ui/src/routes/grok.index.tsx +2 -2
  59. package/apps/ui/src/routes/index.tsx +2 -18
  60. package/apps/ui/src/routes/kiro-sessions.$sessionId.tsx +25 -12
  61. package/apps/ui/src/routes/kiro.$workspaceKey.tsx +27 -32
  62. package/apps/ui/src/routes/kiro.index.tsx +2 -2
  63. package/apps/ui/src/routes/opencode-sessions.$sessionId.tsx +29 -36
  64. package/apps/ui/src/routes/opencode.$workspaceKey.tsx +45 -61
  65. package/apps/ui/src/routes/opencode.index.tsx +8 -17
  66. package/apps/ui/src/routes/qoder-sessions.$sessionId.tsx +12 -11
  67. package/apps/ui/src/routes/qoder.$workspaceKey.tsx +19 -25
  68. package/apps/ui/src/routes/qoder.index.tsx +2 -2
  69. package/apps/ui/src/routes/threads.$threadId.tsx +87 -56
  70. package/apps/ui/vite.config.ts +22 -12
  71. package/bin/spiracha.ts +28 -1
  72. package/package.json +26 -17
  73. package/src/client.ts +61 -16
  74. package/src/lib/antigravity-db.ts +236 -82
  75. package/src/lib/antigravity-keychain.ts +7 -8
  76. package/src/lib/antigravity-transcript-phase.ts +47 -0
  77. package/src/lib/claude-code-db.ts +45 -19
  78. package/src/lib/codex-analytics.ts +32 -5
  79. package/src/lib/codex-browser-db.ts +540 -137
  80. package/src/lib/codex-browser-export.ts +2 -7
  81. package/src/lib/codex-browser-types.ts +21 -1
  82. package/src/lib/codex-thread-cache.ts +88 -33
  83. package/src/lib/codex-thread-parser.ts +78 -35
  84. package/src/lib/codex-thread-recovery.ts +38 -11
  85. package/src/lib/codex-transcript-renderer.ts +49 -61
  86. package/src/lib/concurrency.ts +15 -3
  87. package/src/lib/conversation-api.ts +34 -31
  88. package/src/lib/conversation-data/adapter-helpers.ts +25 -3
  89. package/src/lib/conversation-data/antigravity-adapter.ts +54 -29
  90. package/src/lib/conversation-data/claude-code-adapter.ts +32 -6
  91. package/src/lib/conversation-data/codex-adapter.ts +91 -80
  92. package/src/lib/conversation-data/cursor-adapter.ts +48 -34
  93. package/src/lib/conversation-data/grok-adapter.ts +19 -6
  94. package/src/lib/conversation-data/index.ts +29 -10
  95. package/src/lib/conversation-data/kiro-adapter.ts +18 -5
  96. package/src/lib/conversation-data/message-selector.ts +2 -5
  97. package/src/lib/conversation-data/opencode-adapter.ts +43 -15
  98. package/src/lib/conversation-data/path-match.ts +1 -13
  99. package/src/lib/conversation-data/qoder-adapter.ts +23 -18
  100. package/src/lib/conversation-zip-export.ts +20 -2
  101. package/src/lib/cursor-db.ts +34 -23
  102. package/src/lib/cursor-id.ts +17 -0
  103. package/src/lib/cursor-recovery.ts +146 -35
  104. package/src/lib/cursor-transcript-phase.ts +40 -0
  105. package/src/lib/cursor-transcript.ts +21 -5
  106. package/src/lib/grok-db.ts +76 -34
  107. package/src/lib/grok-transcript-phase.ts +11 -2
  108. package/src/lib/grok-transcript.ts +15 -2
  109. package/src/lib/kiro-db.ts +161 -68
  110. package/src/lib/kiro-transcript.ts +0 -4
  111. package/src/lib/opencode-db.ts +4 -8
  112. package/src/lib/opencode-think-tags.ts +17 -3
  113. package/src/lib/portable-path.ts +9 -0
  114. package/src/lib/qoder-acp-client.ts +11 -2
  115. package/src/lib/qoder-db.ts +51 -17
  116. package/src/lib/qoder-transcript-phase.ts +64 -0
  117. package/src/lib/qoder-transcript.ts +30 -2
  118. package/src/lib/shared.ts +51 -15
  119. package/src/lib/sqlite-error.ts +31 -5
  120. package/src/lib/transcript-load-limiter.ts +8 -3
  121. package/src/lib/ui-cache.ts +152 -17
  122. package/src/lib/ui-export-archive.ts +14 -55
  123. package/src/lib/ui-export-files.ts +75 -15
  124. package/src/lib/ui-export-zip.ts +40 -0
  125. package/apps/ui/package.json +0 -65
@@ -0,0 +1,65 @@
1
+ import { DEFAULT_EXPORT_DIALOG_OPTIONS, type ExportDialogOptions } from '#/lib/export-options';
2
+
3
+ export type Settings = {
4
+ convertToProjectRoot: boolean;
5
+ exportDefaults: ExportDialogOptions;
6
+ redactUsername: boolean;
7
+ };
8
+
9
+ export const SETTINGS_COOKIE_NAME = 'spiracha-settings';
10
+
11
+ export const DEFAULT_SETTINGS: Settings = {
12
+ convertToProjectRoot: false,
13
+ exportDefaults: DEFAULT_EXPORT_DIALOG_OPTIONS,
14
+ redactUsername: false,
15
+ };
16
+
17
+ const asRecord = (value: unknown): Record<string, unknown> | null =>
18
+ value !== null && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : null;
19
+
20
+ const booleanOrDefault = (value: unknown, fallback: boolean) => (typeof value === 'boolean' ? value : fallback);
21
+
22
+ const parseExportDefaults = (value: unknown): ExportDialogOptions => {
23
+ const record = asRecord(value);
24
+ if (!record) {
25
+ return DEFAULT_EXPORT_DIALOG_OPTIONS;
26
+ }
27
+
28
+ return {
29
+ includeCommentary: booleanOrDefault(record.includeCommentary, DEFAULT_EXPORT_DIALOG_OPTIONS.includeCommentary),
30
+ includeMetadata: booleanOrDefault(record.includeMetadata, DEFAULT_EXPORT_DIALOG_OPTIONS.includeMetadata),
31
+ includeTools: booleanOrDefault(record.includeTools, DEFAULT_EXPORT_DIALOG_OPTIONS.includeTools),
32
+ outputFormat:
33
+ record.outputFormat === 'txt' || record.outputFormat === 'md'
34
+ ? record.outputFormat
35
+ : DEFAULT_EXPORT_DIALOG_OPTIONS.outputFormat,
36
+ zipArchive: booleanOrDefault(record.zipArchive, DEFAULT_EXPORT_DIALOG_OPTIONS.zipArchive),
37
+ };
38
+ };
39
+
40
+ export const normalizeSettings = (value: unknown): Settings => {
41
+ const record = asRecord(value);
42
+ if (!record) {
43
+ return DEFAULT_SETTINGS;
44
+ }
45
+
46
+ return {
47
+ convertToProjectRoot: booleanOrDefault(record.convertToProjectRoot, DEFAULT_SETTINGS.convertToProjectRoot),
48
+ exportDefaults: parseExportDefaults(record.exportDefaults),
49
+ redactUsername: booleanOrDefault(record.redactUsername, DEFAULT_SETTINGS.redactUsername),
50
+ };
51
+ };
52
+
53
+ export const parseSerializedSettings = (serialized: string | null | undefined): Settings => {
54
+ if (!serialized) {
55
+ return DEFAULT_SETTINGS;
56
+ }
57
+
58
+ try {
59
+ return normalizeSettings(JSON.parse(decodeURIComponent(serialized)));
60
+ } catch {
61
+ return DEFAULT_SETTINGS;
62
+ }
63
+ };
64
+
65
+ export const serializeSettings = (settings: Settings) => JSON.stringify(settings);
@@ -8,9 +8,9 @@ import {
8
8
  getExportMimeType,
9
9
  resolveUniqueExportFileBaseName,
10
10
  sanitizeExportFileName,
11
- zipExportDirectory,
12
11
  } from '@spiracha/lib/ui-export-archive';
13
12
  import { buildUiExportDownloadUrl, ensureUiExportDir } from '@spiracha/lib/ui-export-files';
13
+ import { zipExportDirectory } from '@spiracha/lib/ui-export-zip';
14
14
 
15
15
  type ExportFormat = 'md' | 'txt';
16
16
 
@@ -0,0 +1,22 @@
1
+ const humanizePolicy = (value: string) => value.replaceAll(/[-_]+/gu, ' ');
2
+
3
+ export const formatSandboxPolicy = (serializedPolicy: string) => {
4
+ const trimmed = serializedPolicy.trim();
5
+ if (!trimmed) {
6
+ return 'n/a';
7
+ }
8
+
9
+ try {
10
+ const parsed = JSON.parse(trimmed) as unknown;
11
+ if (typeof parsed === 'string') {
12
+ return humanizePolicy(parsed);
13
+ }
14
+ if (parsed && typeof parsed === 'object' && 'type' in parsed && typeof parsed.type === 'string') {
15
+ return humanizePolicy(parsed.type);
16
+ }
17
+ } catch {
18
+ return humanizePolicy(trimmed);
19
+ }
20
+
21
+ return humanizePolicy(trimmed);
22
+ };
@@ -1,6 +1,15 @@
1
1
  import type { ThreadEvent, ThreadTranscriptStats } from '@spiracha/lib/codex-browser-types';
2
2
 
3
- const EXEC_TOOL_NAMES = new Set(['bash', 'exec', 'execute', 'execute_command', 'run_command', 'shell', 'terminal']);
3
+ const EXEC_TOOL_NAMES = new Set([
4
+ 'bash',
5
+ 'exec',
6
+ 'exec_command',
7
+ 'execute',
8
+ 'execute_command',
9
+ 'run_command',
10
+ 'shell',
11
+ 'terminal',
12
+ ]);
4
13
 
5
14
  const isExecToolName = (name: string | null | undefined): boolean => {
6
15
  return EXEC_TOOL_NAMES.has((name ?? '').trim().toLowerCase());
@@ -10,3 +10,11 @@ export const isWorkspaceEmptiedByDelete = <TItem>(
10
10
  const deletedIdSet = new Set(deletedIds);
11
11
  return items.every((item) => deletedIdSet.has(getItemId(item)));
12
12
  };
13
+
14
+ export const shouldNavigateToSourceIndexAfterDelete = <TWorkspace>(
15
+ workspaces: TWorkspace[],
16
+ deletedWorkspaceKey: string,
17
+ getWorkspaceKey: (workspace: TWorkspace) => string,
18
+ ) => {
19
+ return !workspaces.some((workspace) => getWorkspaceKey(workspace) === deletedWorkspaceKey);
20
+ };