spiracha 2.0.0 → 2.1.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 (104) hide show
  1. package/README.md +6 -1
  2. package/apps/ui/README.md +20 -2
  3. package/apps/ui/package.json +2 -2
  4. package/apps/ui/src/components/antigravity-conversations-table.tsx +50 -11
  5. package/apps/ui/src/components/antigravity-workspaces-table.tsx +1 -1
  6. package/apps/ui/src/components/app-shell.tsx +1 -0
  7. package/apps/ui/src/components/breadcrumbs.tsx +21 -3
  8. package/apps/ui/src/components/claude-code-sessions-table.tsx +42 -6
  9. package/apps/ui/src/components/claude-code-workspaces-table.tsx +3 -1
  10. package/apps/ui/src/components/cursor-threads-table.tsx +10 -47
  11. package/apps/ui/src/components/data-table.tsx +7 -5
  12. package/apps/ui/src/components/export-dialog.tsx +2 -12
  13. package/apps/ui/src/components/grok-sessions-table.tsx +146 -0
  14. package/apps/ui/src/components/grok-workspaces-table.tsx +53 -0
  15. package/apps/ui/src/components/kiro-sessions-table.tsx +40 -4
  16. package/apps/ui/src/components/opencode-sessions-table.tsx +40 -4
  17. package/apps/ui/src/components/page-header.tsx +15 -9
  18. package/apps/ui/src/components/qoder-sessions-table.tsx +23 -2
  19. package/apps/ui/src/components/qoder-workspaces-table.tsx +5 -1
  20. package/apps/ui/src/components/selection-actions-toolbar.tsx +80 -0
  21. package/apps/ui/src/components/threads-table.tsx +9 -46
  22. package/apps/ui/src/components/transcript-view.tsx +148 -52
  23. package/apps/ui/src/components/ui/select.tsx +1 -1
  24. package/apps/ui/src/lib/antigravity-conversation-state.ts +17 -4
  25. package/apps/ui/src/lib/antigravity-server.ts +152 -7
  26. package/apps/ui/src/lib/antigravity-transcript-events.ts +11 -3
  27. package/apps/ui/src/lib/claude-code-queries.ts +8 -0
  28. package/apps/ui/src/lib/claude-code-server.ts +175 -7
  29. package/apps/ui/src/lib/claude-code-transcript-events.ts +8 -1
  30. package/apps/ui/src/lib/codex-queries.ts +19 -3
  31. package/apps/ui/src/lib/codex-server.ts +135 -53
  32. package/apps/ui/src/lib/cursor-server.ts +48 -5
  33. package/apps/ui/src/lib/formatters.ts +3 -5
  34. package/apps/ui/src/lib/grok-queries.ts +22 -0
  35. package/apps/ui/src/lib/grok-server.ts +169 -0
  36. package/apps/ui/src/lib/grok-transcript-events.ts +149 -0
  37. package/apps/ui/src/lib/kiro-server.ts +85 -7
  38. package/apps/ui/src/lib/opencode-server.ts +85 -7
  39. package/apps/ui/src/lib/qoder-server.ts +67 -11
  40. package/apps/ui/src/lib/route-search.ts +114 -0
  41. package/apps/ui/src/lib/source-session-export-server.ts +86 -3
  42. package/apps/ui/src/lib/thread-transcript-load.ts +15 -0
  43. package/apps/ui/src/lib/workspace-delete-navigation.ts +12 -0
  44. package/apps/ui/src/routeTree.gen.ts +107 -0
  45. package/apps/ui/src/routes/antigravity-conversations.$conversationId.tsx +76 -10
  46. package/apps/ui/src/routes/antigravity.$workspaceKey.tsx +269 -31
  47. package/apps/ui/src/routes/api.v1.conversations.$source.$id.ts +4 -0
  48. package/apps/ui/src/routes/api.v1.conversations.delete.ts +12 -0
  49. package/apps/ui/src/routes/api.v1.conversations.export.ts +12 -0
  50. package/apps/ui/src/routes/claude-code-sessions.$sessionId.tsx +143 -17
  51. package/apps/ui/src/routes/claude-code.$workspaceKey.tsx +165 -26
  52. package/apps/ui/src/routes/cursor-threads.$composerId.tsx +2 -2
  53. package/apps/ui/src/routes/cursor.$workspaceKey.tsx +11 -1
  54. package/apps/ui/src/routes/grok-sessions.$sessionId.tsx +388 -0
  55. package/apps/ui/src/routes/grok.$workspaceKey.tsx +301 -0
  56. package/apps/ui/src/routes/grok.index.tsx +48 -0
  57. package/apps/ui/src/routes/kiro-sessions.$sessionId.tsx +66 -15
  58. package/apps/ui/src/routes/kiro.$workspaceKey.tsx +199 -32
  59. package/apps/ui/src/routes/opencode-sessions.$sessionId.tsx +105 -19
  60. package/apps/ui/src/routes/opencode.$workspaceKey.tsx +236 -44
  61. package/apps/ui/src/routes/opencode.index.tsx +16 -3
  62. package/apps/ui/src/routes/qoder-sessions.$sessionId.tsx +7 -4
  63. package/apps/ui/src/routes/qoder.$workspaceKey.tsx +75 -28
  64. package/apps/ui/src/routes/threads.$threadId.tsx +548 -64
  65. package/package.json +19 -18
  66. package/src/client.ts +134 -1
  67. package/src/lib/antigravity-db.ts +208 -32
  68. package/src/lib/antigravity-exporter-types.ts +3 -0
  69. package/src/lib/antigravity-projects.ts +201 -0
  70. package/src/lib/claude-code-db.ts +498 -32
  71. package/src/lib/claude-code-exporter-types.ts +5 -0
  72. package/src/lib/claude-code-transcript-phase.ts +60 -1
  73. package/src/lib/claude-code-transcript.ts +8 -5
  74. package/src/lib/codex-browser-export.ts +23 -27
  75. package/src/lib/codex-thread-cache.ts +41 -13
  76. package/src/lib/codex-thread-parser.ts +86 -35
  77. package/src/lib/codex-transcript-filter.ts +31 -0
  78. package/src/lib/codex-transcript-renderer.ts +39 -19
  79. package/src/lib/concurrency.ts +41 -0
  80. package/src/lib/conversation-api.ts +399 -19
  81. package/src/lib/conversation-data/antigravity-adapter.ts +21 -2
  82. package/src/lib/conversation-data/claude-code-adapter.ts +37 -6
  83. package/src/lib/conversation-data/codex-adapter.ts +28 -4
  84. package/src/lib/conversation-data/cursor-adapter.ts +35 -1
  85. package/src/lib/conversation-data/grok-adapter.ts +210 -0
  86. package/src/lib/conversation-data/index.ts +76 -1
  87. package/src/lib/conversation-data/kiro-adapter.ts +41 -7
  88. package/src/lib/conversation-data/opencode-adapter.ts +24 -2
  89. package/src/lib/conversation-data/qoder-adapter.ts +44 -19
  90. package/src/lib/conversation-data/types.ts +43 -0
  91. package/src/lib/conversation-zip-export.ts +57 -0
  92. package/src/lib/cursor-db.ts +34 -5
  93. package/src/lib/grok-db.ts +1026 -0
  94. package/src/lib/grok-exporter-types.ts +110 -0
  95. package/src/lib/grok-transcript-phase.ts +52 -0
  96. package/src/lib/grok-transcript.ts +154 -0
  97. package/src/lib/kiro-db.ts +52 -1
  98. package/src/lib/model-label.ts +11 -3
  99. package/src/lib/opencode-db.ts +598 -55
  100. package/src/lib/opencode-transcript.ts +8 -5
  101. package/src/lib/shared.ts +12 -0
  102. package/src/lib/transcript-load-limiter.ts +82 -0
  103. package/src/lib/ui-cache.ts +43 -17
  104. package/src/lib/ui-export-archive.ts +60 -0
@@ -16,6 +16,7 @@ import { Route as IndexRouteImport } from './routes/index'
16
16
  import { Route as QoderIndexRouteImport } from './routes/qoder.index'
17
17
  import { Route as OpencodeIndexRouteImport } from './routes/opencode.index'
18
18
  import { Route as KiroIndexRouteImport } from './routes/kiro.index'
19
+ import { Route as GrokIndexRouteImport } from './routes/grok.index'
19
20
  import { Route as CursorIndexRouteImport } from './routes/cursor.index'
20
21
  import { Route as CodexIndexRouteImport } from './routes/codex.index'
21
22
  import { Route as ClaudeCodeIndexRouteImport } from './routes/claude-code.index'
@@ -27,6 +28,8 @@ import { Route as OpencodeWorkspaceKeyRouteImport } from './routes/opencode.$wor
27
28
  import { Route as OpencodeSessionsSessionIdRouteImport } from './routes/opencode-sessions.$sessionId'
28
29
  import { Route as KiroWorkspaceKeyRouteImport } from './routes/kiro.$workspaceKey'
29
30
  import { Route as KiroSessionsSessionIdRouteImport } from './routes/kiro-sessions.$sessionId'
31
+ import { Route as GrokWorkspaceKeyRouteImport } from './routes/grok.$workspaceKey'
32
+ import { Route as GrokSessionsSessionIdRouteImport } from './routes/grok-sessions.$sessionId'
30
33
  import { Route as CursorWorkspaceKeyRouteImport } from './routes/cursor.$workspaceKey'
31
34
  import { Route as CursorThreadsComposerIdRouteImport } from './routes/cursor-threads.$composerId'
32
35
  import { Route as CodexProjectRouteImport } from './routes/codex.$project'
@@ -38,6 +41,8 @@ import { Route as ApiV1SourcesRouteImport } from './routes/api.v1.sources'
38
41
  import { Route as ApiV1ResolveRouteImport } from './routes/api.v1.resolve'
39
42
  import { Route as ApiV1ConversationsRouteImport } from './routes/api.v1.conversations'
40
43
  import { Route as ApiV1ConversationQueryRouteImport } from './routes/api.v1.conversation-query'
44
+ import { Route as ApiV1ConversationsExportRouteImport } from './routes/api.v1.conversations.export'
45
+ import { Route as ApiV1ConversationsDeleteRouteImport } from './routes/api.v1.conversations.delete'
41
46
  import { Route as ApiV1ConversationsSourceIdRouteImport } from './routes/api.v1.conversations.$source.$id'
42
47
  import { Route as ApiV1ConversationsSourceIdExportRouteImport } from './routes/api.v1.conversations.$source.$id.export'
43
48
 
@@ -76,6 +81,11 @@ const KiroIndexRoute = KiroIndexRouteImport.update({
76
81
  path: '/kiro/',
77
82
  getParentRoute: () => rootRouteImport,
78
83
  } as any)
84
+ const GrokIndexRoute = GrokIndexRouteImport.update({
85
+ id: '/grok/',
86
+ path: '/grok/',
87
+ getParentRoute: () => rootRouteImport,
88
+ } as any)
79
89
  const CursorIndexRoute = CursorIndexRouteImport.update({
80
90
  id: '/cursor/',
81
91
  path: '/cursor/',
@@ -132,6 +142,16 @@ const KiroSessionsSessionIdRoute = KiroSessionsSessionIdRouteImport.update({
132
142
  path: '/kiro-sessions/$sessionId',
133
143
  getParentRoute: () => rootRouteImport,
134
144
  } as any)
145
+ const GrokWorkspaceKeyRoute = GrokWorkspaceKeyRouteImport.update({
146
+ id: '/grok/$workspaceKey',
147
+ path: '/grok/$workspaceKey',
148
+ getParentRoute: () => rootRouteImport,
149
+ } as any)
150
+ const GrokSessionsSessionIdRoute = GrokSessionsSessionIdRouteImport.update({
151
+ id: '/grok-sessions/$sessionId',
152
+ path: '/grok-sessions/$sessionId',
153
+ getParentRoute: () => rootRouteImport,
154
+ } as any)
135
155
  const CursorWorkspaceKeyRoute = CursorWorkspaceKeyRouteImport.update({
136
156
  id: '/cursor/$workspaceKey',
137
157
  path: '/cursor/$workspaceKey',
@@ -189,6 +209,18 @@ const ApiV1ConversationQueryRoute = ApiV1ConversationQueryRouteImport.update({
189
209
  path: '/api/v1/conversation-query',
190
210
  getParentRoute: () => rootRouteImport,
191
211
  } as any)
212
+ const ApiV1ConversationsExportRoute =
213
+ ApiV1ConversationsExportRouteImport.update({
214
+ id: '/export',
215
+ path: '/export',
216
+ getParentRoute: () => ApiV1ConversationsRoute,
217
+ } as any)
218
+ const ApiV1ConversationsDeleteRoute =
219
+ ApiV1ConversationsDeleteRouteImport.update({
220
+ id: '/delete',
221
+ path: '/delete',
222
+ getParentRoute: () => ApiV1ConversationsRoute,
223
+ } as any)
192
224
  const ApiV1ConversationsSourceIdRoute =
193
225
  ApiV1ConversationsSourceIdRouteImport.update({
194
226
  id: '/$source/$id',
@@ -214,6 +246,8 @@ export interface FileRoutesByFullPath {
214
246
  '/codex/$project': typeof CodexProjectRoute
215
247
  '/cursor-threads/$composerId': typeof CursorThreadsComposerIdRoute
216
248
  '/cursor/$workspaceKey': typeof CursorWorkspaceKeyRoute
249
+ '/grok-sessions/$sessionId': typeof GrokSessionsSessionIdRoute
250
+ '/grok/$workspaceKey': typeof GrokWorkspaceKeyRoute
217
251
  '/kiro-sessions/$sessionId': typeof KiroSessionsSessionIdRoute
218
252
  '/kiro/$workspaceKey': typeof KiroWorkspaceKeyRoute
219
253
  '/opencode-sessions/$sessionId': typeof OpencodeSessionsSessionIdRoute
@@ -225,6 +259,7 @@ export interface FileRoutesByFullPath {
225
259
  '/claude-code/': typeof ClaudeCodeIndexRoute
226
260
  '/codex/': typeof CodexIndexRoute
227
261
  '/cursor/': typeof CursorIndexRoute
262
+ '/grok/': typeof GrokIndexRoute
228
263
  '/kiro/': typeof KiroIndexRoute
229
264
  '/opencode/': typeof OpencodeIndexRoute
230
265
  '/qoder/': typeof QoderIndexRoute
@@ -232,6 +267,8 @@ export interface FileRoutesByFullPath {
232
267
  '/api/v1/conversations': typeof ApiV1ConversationsRouteWithChildren
233
268
  '/api/v1/resolve': typeof ApiV1ResolveRoute
234
269
  '/api/v1/sources': typeof ApiV1SourcesRoute
270
+ '/api/v1/conversations/delete': typeof ApiV1ConversationsDeleteRoute
271
+ '/api/v1/conversations/export': typeof ApiV1ConversationsExportRoute
235
272
  '/api/v1/conversations/$source/$id': typeof ApiV1ConversationsSourceIdRouteWithChildren
236
273
  '/api/v1/conversations/$source/$id/export': typeof ApiV1ConversationsSourceIdExportRoute
237
274
  }
@@ -247,6 +284,8 @@ export interface FileRoutesByTo {
247
284
  '/codex/$project': typeof CodexProjectRoute
248
285
  '/cursor-threads/$composerId': typeof CursorThreadsComposerIdRoute
249
286
  '/cursor/$workspaceKey': typeof CursorWorkspaceKeyRoute
287
+ '/grok-sessions/$sessionId': typeof GrokSessionsSessionIdRoute
288
+ '/grok/$workspaceKey': typeof GrokWorkspaceKeyRoute
250
289
  '/kiro-sessions/$sessionId': typeof KiroSessionsSessionIdRoute
251
290
  '/kiro/$workspaceKey': typeof KiroWorkspaceKeyRoute
252
291
  '/opencode-sessions/$sessionId': typeof OpencodeSessionsSessionIdRoute
@@ -258,6 +297,7 @@ export interface FileRoutesByTo {
258
297
  '/claude-code': typeof ClaudeCodeIndexRoute
259
298
  '/codex': typeof CodexIndexRoute
260
299
  '/cursor': typeof CursorIndexRoute
300
+ '/grok': typeof GrokIndexRoute
261
301
  '/kiro': typeof KiroIndexRoute
262
302
  '/opencode': typeof OpencodeIndexRoute
263
303
  '/qoder': typeof QoderIndexRoute
@@ -265,6 +305,8 @@ export interface FileRoutesByTo {
265
305
  '/api/v1/conversations': typeof ApiV1ConversationsRouteWithChildren
266
306
  '/api/v1/resolve': typeof ApiV1ResolveRoute
267
307
  '/api/v1/sources': typeof ApiV1SourcesRoute
308
+ '/api/v1/conversations/delete': typeof ApiV1ConversationsDeleteRoute
309
+ '/api/v1/conversations/export': typeof ApiV1ConversationsExportRoute
268
310
  '/api/v1/conversations/$source/$id': typeof ApiV1ConversationsSourceIdRouteWithChildren
269
311
  '/api/v1/conversations/$source/$id/export': typeof ApiV1ConversationsSourceIdExportRoute
270
312
  }
@@ -281,6 +323,8 @@ export interface FileRoutesById {
281
323
  '/codex/$project': typeof CodexProjectRoute
282
324
  '/cursor-threads/$composerId': typeof CursorThreadsComposerIdRoute
283
325
  '/cursor/$workspaceKey': typeof CursorWorkspaceKeyRoute
326
+ '/grok-sessions/$sessionId': typeof GrokSessionsSessionIdRoute
327
+ '/grok/$workspaceKey': typeof GrokWorkspaceKeyRoute
284
328
  '/kiro-sessions/$sessionId': typeof KiroSessionsSessionIdRoute
285
329
  '/kiro/$workspaceKey': typeof KiroWorkspaceKeyRoute
286
330
  '/opencode-sessions/$sessionId': typeof OpencodeSessionsSessionIdRoute
@@ -292,6 +336,7 @@ export interface FileRoutesById {
292
336
  '/claude-code/': typeof ClaudeCodeIndexRoute
293
337
  '/codex/': typeof CodexIndexRoute
294
338
  '/cursor/': typeof CursorIndexRoute
339
+ '/grok/': typeof GrokIndexRoute
295
340
  '/kiro/': typeof KiroIndexRoute
296
341
  '/opencode/': typeof OpencodeIndexRoute
297
342
  '/qoder/': typeof QoderIndexRoute
@@ -299,6 +344,8 @@ export interface FileRoutesById {
299
344
  '/api/v1/conversations': typeof ApiV1ConversationsRouteWithChildren
300
345
  '/api/v1/resolve': typeof ApiV1ResolveRoute
301
346
  '/api/v1/sources': typeof ApiV1SourcesRoute
347
+ '/api/v1/conversations/delete': typeof ApiV1ConversationsDeleteRoute
348
+ '/api/v1/conversations/export': typeof ApiV1ConversationsExportRoute
302
349
  '/api/v1/conversations/$source/$id': typeof ApiV1ConversationsSourceIdRouteWithChildren
303
350
  '/api/v1/conversations/$source/$id/export': typeof ApiV1ConversationsSourceIdExportRoute
304
351
  }
@@ -316,6 +363,8 @@ export interface FileRouteTypes {
316
363
  | '/codex/$project'
317
364
  | '/cursor-threads/$composerId'
318
365
  | '/cursor/$workspaceKey'
366
+ | '/grok-sessions/$sessionId'
367
+ | '/grok/$workspaceKey'
319
368
  | '/kiro-sessions/$sessionId'
320
369
  | '/kiro/$workspaceKey'
321
370
  | '/opencode-sessions/$sessionId'
@@ -327,6 +376,7 @@ export interface FileRouteTypes {
327
376
  | '/claude-code/'
328
377
  | '/codex/'
329
378
  | '/cursor/'
379
+ | '/grok/'
330
380
  | '/kiro/'
331
381
  | '/opencode/'
332
382
  | '/qoder/'
@@ -334,6 +384,8 @@ export interface FileRouteTypes {
334
384
  | '/api/v1/conversations'
335
385
  | '/api/v1/resolve'
336
386
  | '/api/v1/sources'
387
+ | '/api/v1/conversations/delete'
388
+ | '/api/v1/conversations/export'
337
389
  | '/api/v1/conversations/$source/$id'
338
390
  | '/api/v1/conversations/$source/$id/export'
339
391
  fileRoutesByTo: FileRoutesByTo
@@ -349,6 +401,8 @@ export interface FileRouteTypes {
349
401
  | '/codex/$project'
350
402
  | '/cursor-threads/$composerId'
351
403
  | '/cursor/$workspaceKey'
404
+ | '/grok-sessions/$sessionId'
405
+ | '/grok/$workspaceKey'
352
406
  | '/kiro-sessions/$sessionId'
353
407
  | '/kiro/$workspaceKey'
354
408
  | '/opencode-sessions/$sessionId'
@@ -360,6 +414,7 @@ export interface FileRouteTypes {
360
414
  | '/claude-code'
361
415
  | '/codex'
362
416
  | '/cursor'
417
+ | '/grok'
363
418
  | '/kiro'
364
419
  | '/opencode'
365
420
  | '/qoder'
@@ -367,6 +422,8 @@ export interface FileRouteTypes {
367
422
  | '/api/v1/conversations'
368
423
  | '/api/v1/resolve'
369
424
  | '/api/v1/sources'
425
+ | '/api/v1/conversations/delete'
426
+ | '/api/v1/conversations/export'
370
427
  | '/api/v1/conversations/$source/$id'
371
428
  | '/api/v1/conversations/$source/$id/export'
372
429
  id:
@@ -382,6 +439,8 @@ export interface FileRouteTypes {
382
439
  | '/codex/$project'
383
440
  | '/cursor-threads/$composerId'
384
441
  | '/cursor/$workspaceKey'
442
+ | '/grok-sessions/$sessionId'
443
+ | '/grok/$workspaceKey'
385
444
  | '/kiro-sessions/$sessionId'
386
445
  | '/kiro/$workspaceKey'
387
446
  | '/opencode-sessions/$sessionId'
@@ -393,6 +452,7 @@ export interface FileRouteTypes {
393
452
  | '/claude-code/'
394
453
  | '/codex/'
395
454
  | '/cursor/'
455
+ | '/grok/'
396
456
  | '/kiro/'
397
457
  | '/opencode/'
398
458
  | '/qoder/'
@@ -400,6 +460,8 @@ export interface FileRouteTypes {
400
460
  | '/api/v1/conversations'
401
461
  | '/api/v1/resolve'
402
462
  | '/api/v1/sources'
463
+ | '/api/v1/conversations/delete'
464
+ | '/api/v1/conversations/export'
403
465
  | '/api/v1/conversations/$source/$id'
404
466
  | '/api/v1/conversations/$source/$id/export'
405
467
  fileRoutesById: FileRoutesById
@@ -416,6 +478,8 @@ export interface RootRouteChildren {
416
478
  CodexProjectRoute: typeof CodexProjectRoute
417
479
  CursorThreadsComposerIdRoute: typeof CursorThreadsComposerIdRoute
418
480
  CursorWorkspaceKeyRoute: typeof CursorWorkspaceKeyRoute
481
+ GrokSessionsSessionIdRoute: typeof GrokSessionsSessionIdRoute
482
+ GrokWorkspaceKeyRoute: typeof GrokWorkspaceKeyRoute
419
483
  KiroSessionsSessionIdRoute: typeof KiroSessionsSessionIdRoute
420
484
  KiroWorkspaceKeyRoute: typeof KiroWorkspaceKeyRoute
421
485
  OpencodeSessionsSessionIdRoute: typeof OpencodeSessionsSessionIdRoute
@@ -427,6 +491,7 @@ export interface RootRouteChildren {
427
491
  ClaudeCodeIndexRoute: typeof ClaudeCodeIndexRoute
428
492
  CodexIndexRoute: typeof CodexIndexRoute
429
493
  CursorIndexRoute: typeof CursorIndexRoute
494
+ GrokIndexRoute: typeof GrokIndexRoute
430
495
  KiroIndexRoute: typeof KiroIndexRoute
431
496
  OpencodeIndexRoute: typeof OpencodeIndexRoute
432
497
  QoderIndexRoute: typeof QoderIndexRoute
@@ -487,6 +552,13 @@ declare module '@tanstack/react-router' {
487
552
  preLoaderRoute: typeof KiroIndexRouteImport
488
553
  parentRoute: typeof rootRouteImport
489
554
  }
555
+ '/grok/': {
556
+ id: '/grok/'
557
+ path: '/grok'
558
+ fullPath: '/grok/'
559
+ preLoaderRoute: typeof GrokIndexRouteImport
560
+ parentRoute: typeof rootRouteImport
561
+ }
490
562
  '/cursor/': {
491
563
  id: '/cursor/'
492
564
  path: '/cursor'
@@ -564,6 +636,20 @@ declare module '@tanstack/react-router' {
564
636
  preLoaderRoute: typeof KiroSessionsSessionIdRouteImport
565
637
  parentRoute: typeof rootRouteImport
566
638
  }
639
+ '/grok/$workspaceKey': {
640
+ id: '/grok/$workspaceKey'
641
+ path: '/grok/$workspaceKey'
642
+ fullPath: '/grok/$workspaceKey'
643
+ preLoaderRoute: typeof GrokWorkspaceKeyRouteImport
644
+ parentRoute: typeof rootRouteImport
645
+ }
646
+ '/grok-sessions/$sessionId': {
647
+ id: '/grok-sessions/$sessionId'
648
+ path: '/grok-sessions/$sessionId'
649
+ fullPath: '/grok-sessions/$sessionId'
650
+ preLoaderRoute: typeof GrokSessionsSessionIdRouteImport
651
+ parentRoute: typeof rootRouteImport
652
+ }
567
653
  '/cursor/$workspaceKey': {
568
654
  id: '/cursor/$workspaceKey'
569
655
  path: '/cursor/$workspaceKey'
@@ -641,6 +727,20 @@ declare module '@tanstack/react-router' {
641
727
  preLoaderRoute: typeof ApiV1ConversationQueryRouteImport
642
728
  parentRoute: typeof rootRouteImport
643
729
  }
730
+ '/api/v1/conversations/export': {
731
+ id: '/api/v1/conversations/export'
732
+ path: '/export'
733
+ fullPath: '/api/v1/conversations/export'
734
+ preLoaderRoute: typeof ApiV1ConversationsExportRouteImport
735
+ parentRoute: typeof ApiV1ConversationsRoute
736
+ }
737
+ '/api/v1/conversations/delete': {
738
+ id: '/api/v1/conversations/delete'
739
+ path: '/delete'
740
+ fullPath: '/api/v1/conversations/delete'
741
+ preLoaderRoute: typeof ApiV1ConversationsDeleteRouteImport
742
+ parentRoute: typeof ApiV1ConversationsRoute
743
+ }
644
744
  '/api/v1/conversations/$source/$id': {
645
745
  id: '/api/v1/conversations/$source/$id'
646
746
  path: '/$source/$id'
@@ -674,10 +774,14 @@ const ApiV1ConversationsSourceIdRouteWithChildren =
674
774
  )
675
775
 
676
776
  interface ApiV1ConversationsRouteChildren {
777
+ ApiV1ConversationsDeleteRoute: typeof ApiV1ConversationsDeleteRoute
778
+ ApiV1ConversationsExportRoute: typeof ApiV1ConversationsExportRoute
677
779
  ApiV1ConversationsSourceIdRoute: typeof ApiV1ConversationsSourceIdRouteWithChildren
678
780
  }
679
781
 
680
782
  const ApiV1ConversationsRouteChildren: ApiV1ConversationsRouteChildren = {
783
+ ApiV1ConversationsDeleteRoute: ApiV1ConversationsDeleteRoute,
784
+ ApiV1ConversationsExportRoute: ApiV1ConversationsExportRoute,
681
785
  ApiV1ConversationsSourceIdRoute: ApiV1ConversationsSourceIdRouteWithChildren,
682
786
  }
683
787
 
@@ -697,6 +801,8 @@ const rootRouteChildren: RootRouteChildren = {
697
801
  CodexProjectRoute: CodexProjectRoute,
698
802
  CursorThreadsComposerIdRoute: CursorThreadsComposerIdRoute,
699
803
  CursorWorkspaceKeyRoute: CursorWorkspaceKeyRoute,
804
+ GrokSessionsSessionIdRoute: GrokSessionsSessionIdRoute,
805
+ GrokWorkspaceKeyRoute: GrokWorkspaceKeyRoute,
700
806
  KiroSessionsSessionIdRoute: KiroSessionsSessionIdRoute,
701
807
  KiroWorkspaceKeyRoute: KiroWorkspaceKeyRoute,
702
808
  OpencodeSessionsSessionIdRoute: OpencodeSessionsSessionIdRoute,
@@ -708,6 +814,7 @@ const rootRouteChildren: RootRouteChildren = {
708
814
  ClaudeCodeIndexRoute: ClaudeCodeIndexRoute,
709
815
  CodexIndexRoute: CodexIndexRoute,
710
816
  CursorIndexRoute: CursorIndexRoute,
817
+ GrokIndexRoute: GrokIndexRoute,
711
818
  KiroIndexRoute: KiroIndexRoute,
712
819
  OpencodeIndexRoute: OpencodeIndexRoute,
713
820
  QoderIndexRoute: QoderIndexRoute,
@@ -1,9 +1,10 @@
1
- import { useMutation, useSuspenseQuery } from '@tanstack/react-query';
2
- import { createFileRoute, Link } from '@tanstack/react-router';
3
- import { Download, ScrollText } from 'lucide-react';
1
+ import { useMutation, useQueryClient, useSuspenseQuery } from '@tanstack/react-query';
2
+ import { createFileRoute, Link, useNavigate } from '@tanstack/react-router';
3
+ import { Download, ScrollText, Trash2 } from 'lucide-react';
4
4
  import { useMemo, useState } from 'react';
5
5
  import { AntigravityKeychainPanel } from '#/components/antigravity-keychain-panel';
6
6
  import { Breadcrumbs } from '#/components/breadcrumbs';
7
+ import { DeleteConfirmDialog } from '#/components/delete-confirm-dialog';
7
8
  import { JsonPanel } from '#/components/json-panel';
8
9
  import { LoadingPanel } from '#/components/loading-panel';
9
10
  import { MetadataSection } from '#/components/metadata-section';
@@ -11,7 +12,7 @@ import { MetricCard } from '#/components/metric-card';
11
12
  import { PageHeader } from '#/components/page-header';
12
13
  import { ReloadErrorPanel } from '#/components/reload-error-panel';
13
14
  import { TextDocumentPanel } from '#/components/text-document-panel';
14
- import { TranscriptView } from '#/components/transcript-view';
15
+ import { DEFAULT_SHOW_USER_MESSAGES, TranscriptView } from '#/components/transcript-view';
15
16
  import { Button } from '#/components/ui/button';
16
17
  import { Checkbox } from '#/components/ui/checkbox';
17
18
  import { Tabs, TabsContent, TabsList, TabsTrigger } from '#/components/ui/tabs';
@@ -21,6 +22,7 @@ import {
21
22
  antigravityDecryptionQueryOptions,
22
23
  } from '#/lib/antigravity-queries';
23
24
  import {
25
+ deleteAntigravityConversationFn,
24
26
  exportAntigravityArtifactsFn,
25
27
  exportAntigravityConversationFn,
26
28
  type getAntigravityConversationDetailFn,
@@ -56,10 +58,10 @@ const buildConversationMetadata = (detail: AntigravityConversationDetail) => {
56
58
  value: (
57
59
  <Link
58
60
  className="text-[var(--accent)]"
59
- params={{ workspaceKey: detail.conversation.workspaceKey }}
61
+ params={{ workspaceKey: detail.conversationGroup.key }}
60
62
  to="/antigravity/$workspaceKey"
61
63
  >
62
- {detail.conversation.workspaceLabel}
64
+ {detail.conversationGroup.label}
63
65
  </Link>
64
66
  ),
65
67
  },
@@ -106,6 +108,14 @@ const buildTranscriptStatsItems = (
106
108
  ];
107
109
  };
108
110
 
111
+ const getConversationSizeLabel = (detail: AntigravityConversationDetail): string => {
112
+ if (detail.conversation.totalBytes > 0) {
113
+ return formatBytes(detail.conversation.totalBytes);
114
+ }
115
+
116
+ return detail.conversation.summaryPath ? 'Summary' : formatBytes(detail.conversation.totalBytes);
117
+ };
118
+
109
119
  export const Route = createFileRoute('/antigravity-conversations/$conversationId')({
110
120
  component: AntigravityConversationDetailPage,
111
121
  errorComponent: AntigravityConversationDetailErrorComponent,
@@ -133,6 +143,7 @@ function AntigravityConversationHeaderActions({
133
143
  exportArtifactsPending,
134
144
  exportConversationPending,
135
145
  showConversationExport,
146
+ onDeleteConversation,
136
147
  onExportArtifacts,
137
148
  onExportConversation,
138
149
  }: {
@@ -141,6 +152,7 @@ function AntigravityConversationHeaderActions({
141
152
  exportArtifactsPending: boolean;
142
153
  exportConversationPending: boolean;
143
154
  showConversationExport: boolean;
155
+ onDeleteConversation: () => void;
144
156
  onExportArtifacts: () => void;
145
157
  onExportConversation: () => void;
146
158
  }) {
@@ -170,6 +182,15 @@ function AntigravityConversationHeaderActions({
170
182
  Export artifacts
171
183
  </Button>
172
184
  ) : null}
185
+ <Button
186
+ className="rounded-full border-[var(--destructive)]/20 text-[var(--destructive)]"
187
+ type="button"
188
+ variant="outline"
189
+ onClick={onDeleteConversation}
190
+ >
191
+ <Trash2 className="mr-2 size-4" />
192
+ Delete
193
+ </Button>
173
194
  </div>
174
195
  );
175
196
  }
@@ -281,13 +302,16 @@ function AntigravityRawPanels({
281
302
  }
282
303
 
283
304
  function AntigravityConversationDetailPage() {
305
+ const navigate = useNavigate();
306
+ const queryClient = useQueryClient();
284
307
  const decryptionState = useSuspenseQuery(antigravityDecryptionQueryOptions()).data;
285
308
  const detail = useSuspenseQuery(antigravityConversationDetailQueryOptions(Route.useParams().conversationId)).data;
309
+ const [deleteOpen, setDeleteOpen] = useState(false);
286
310
  const [showToolCalls, setShowToolCalls] = useState(false);
287
311
  const [showCommentary, setShowCommentary] = useState(false);
288
312
  const [showExtraEvents, setShowExtraEvents] = useState(false);
289
313
  const [showRawJson, setShowRawJson] = useState(false);
290
- const [showUserMessages, setShowUserMessages] = useState(true);
314
+ const [showUserMessages, setShowUserMessages] = useState(DEFAULT_SHOW_USER_MESSAGES);
291
315
  const transcriptEvents = useMemo(
292
316
  () => antigravityMarkdownToThreadEvents(detail.conversationMarkdown),
293
317
  [detail.conversationMarkdown],
@@ -315,6 +339,26 @@ function AntigravityConversationDetailPage() {
315
339
  },
316
340
  });
317
341
 
342
+ const deleteConversationMutation = useMutation({
343
+ mutationFn: () =>
344
+ deleteAntigravityConversationFn({ data: { conversationId: detail.conversation.conversationId } }),
345
+ onSuccess: async () => {
346
+ await Promise.all([
347
+ queryClient.invalidateQueries({ queryKey: ['antigravity-workspaces'] }),
348
+ queryClient.invalidateQueries({
349
+ queryKey: ['antigravity-conversations', detail.conversationGroup.key],
350
+ }),
351
+ queryClient.invalidateQueries({
352
+ queryKey: ['antigravity-conversation', detail.conversation.conversationId],
353
+ }),
354
+ ]);
355
+ navigate({
356
+ params: { workspaceKey: detail.conversationGroup.key },
357
+ to: '/antigravity/$workspaceKey',
358
+ });
359
+ },
360
+ });
361
+
318
362
  return (
319
363
  <div className="space-y-6">
320
364
  <PageHeader
@@ -325,6 +369,7 @@ function AntigravityConversationDetailPage() {
325
369
  exportArtifactsPending={exportArtifactsMutation.isPending}
326
370
  exportConversationPending={exportConversationMutation.isPending}
327
371
  showConversationExport={showConversationExport}
372
+ onDeleteConversation={() => setDeleteOpen(true)}
328
373
  onExportArtifacts={() => exportArtifactsMutation.mutate()}
329
374
  onExportConversation={() => exportConversationMutation.mutate()}
330
375
  />
@@ -334,8 +379,8 @@ function AntigravityConversationDetailPage() {
334
379
  items={[
335
380
  { label: 'Antigravity', to: '/antigravity' },
336
381
  {
337
- label: detail.conversation.workspaceLabel,
338
- params: { workspaceKey: detail.conversation.workspaceKey },
382
+ label: detail.conversationGroup.label,
383
+ params: { workspaceKey: detail.conversationGroup.key },
339
384
  to: '/antigravity/$workspaceKey',
340
385
  },
341
386
  { label: detail.conversation.title },
@@ -352,7 +397,7 @@ function AntigravityConversationDetailPage() {
352
397
  <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
353
398
  <MetricCard label="Transcript entries" value={formatNumber(detail.conversation.transcriptEntryCount)} />
354
399
  <MetricCard label="Artifacts" value={formatNumber(detail.conversation.artifactCount)} />
355
- <MetricCard label="Size" value={formatBytes(detail.conversation.conversationBytes)} />
400
+ <MetricCard label="Size" value={getConversationSizeLabel(detail)} />
356
401
  <MetricCard
357
402
  helper={detail.conversation.transcriptSource ?? 'summary'}
358
403
  label="Indexed items"
@@ -433,6 +478,27 @@ function AntigravityConversationDetailPage() {
433
478
  : 'Artifact export failed'}
434
479
  </p>
435
480
  ) : null}
481
+
482
+ <DeleteConfirmDialog
483
+ confirmLabel={deleteConversationMutation.isPending ? 'Deleting...' : 'Delete conversation'}
484
+ description="Permanently delete this Antigravity conversation from disk. This removes its summary entry, conversation file, transcript logs, and generated artifacts."
485
+ errorMessage={
486
+ deleteConversationMutation.isError
487
+ ? deleteConversationMutation.error instanceof Error
488
+ ? deleteConversationMutation.error.message
489
+ : 'Conversation delete failed'
490
+ : null
491
+ }
492
+ open={deleteOpen}
493
+ title="Delete this Antigravity conversation?"
494
+ onConfirm={() => deleteConversationMutation.mutate()}
495
+ onOpenChange={(open) => {
496
+ setDeleteOpen(open);
497
+ if (!open) {
498
+ deleteConversationMutation.reset();
499
+ }
500
+ }}
501
+ />
436
502
  </div>
437
503
  );
438
504
  }