spiracha 1.3.2 → 1.4.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 (160) hide show
  1. package/AGENTS.md +7 -1
  2. package/README.md +6 -0
  3. package/apps/ui/AGENTS.md +8 -0
  4. package/apps/ui/README.md +10 -3
  5. package/apps/ui/dist/client/assets/analytics-DK2jdvmI.js +1 -0
  6. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-DmD0sN8X.js +7 -0
  7. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-KAcXtNxI.js +1 -0
  8. package/apps/ui/dist/client/assets/antigravity-keychain-panel-BRHVjFAM.js +1 -0
  9. package/apps/ui/dist/client/assets/antigravity._workspaceKey-ByitGWki.js +1 -0
  10. package/apps/ui/dist/client/assets/antigravity._workspaceKey-CGV7amas.js +1 -0
  11. package/apps/ui/dist/client/assets/antigravity.index-DEEkjlZa.js +1 -0
  12. package/apps/ui/dist/client/assets/antigravity.index-DgW25FEV.js +1 -0
  13. package/apps/ui/dist/client/assets/badge-DfWvPfKF.js +1 -0
  14. package/apps/ui/dist/client/assets/checkbox-CdHitXWQ.js +1 -0
  15. package/apps/ui/dist/client/assets/createServerFn-CgRRVpBH.js +3 -0
  16. package/apps/ui/dist/client/assets/cursor-threads._composerId-CmBFclK8.js +1 -0
  17. package/apps/ui/dist/client/assets/cursor-threads._composerId-Ti2gTm63.js +1 -0
  18. package/apps/ui/dist/client/assets/cursor._workspaceKey-CaAZjGmm.js +1 -0
  19. package/apps/ui/dist/client/assets/cursor._workspaceKey-DzD_c6j9.js +1 -0
  20. package/apps/ui/dist/client/assets/cursor.index-CrnMwDCi.js +1 -0
  21. package/apps/ui/dist/client/assets/cursor.index-PkCFVcl4.js +2 -0
  22. package/apps/ui/dist/client/assets/{data-table-Cj-v-uyB.js → data-table-Br78_dk3.js} +2 -2
  23. package/apps/ui/dist/client/assets/delete-confirm-dialog-BHRmyLHr.js +11 -0
  24. package/apps/ui/dist/client/assets/dist-B9pyYCVU.js +1 -0
  25. package/apps/ui/dist/client/assets/dist-BhZOxAPP.js +1 -0
  26. package/apps/ui/dist/client/assets/dist-DvMS2965.js +1 -0
  27. package/apps/ui/dist/client/assets/download-Bf0QJKD3.js +1 -0
  28. package/apps/ui/dist/client/assets/dropdown-menu-Dy5cLzTy.js +1 -0
  29. package/apps/ui/dist/client/assets/es2015-BkCWttyM.js +41 -0
  30. package/apps/ui/dist/client/assets/export-dialog-C86SYHJn.js +1 -0
  31. package/apps/ui/dist/client/assets/formatters-BM9kB7ed.js +1 -0
  32. package/apps/ui/dist/client/assets/index-CPvAP-jk.js +149 -0
  33. package/apps/ui/dist/client/assets/jsx-runtime-DGeXAQPT.js +1 -0
  34. package/apps/ui/dist/client/assets/metric-card-Dplm0ZiM.js +1 -0
  35. package/apps/ui/dist/client/assets/page-header-Cwa3p6Tl.js +1 -0
  36. package/apps/ui/dist/client/assets/projects._project-Ckf6muWZ.js +1 -0
  37. package/apps/ui/dist/client/assets/projects._project-DSDwH4NF.js +1 -0
  38. package/apps/ui/dist/client/assets/projects.index-DEfhWqa8.js +1 -0
  39. package/apps/ui/dist/client/assets/projects.index-V5ibNZII.js +3 -0
  40. package/apps/ui/dist/client/assets/react-dom-DL96Jor4.js +1 -0
  41. package/apps/ui/dist/client/assets/refresh-ccw-BgKjOiA6.js +1 -0
  42. package/apps/ui/dist/client/assets/reload-error-panel-AHqu0akK.js +1 -0
  43. package/apps/ui/dist/client/assets/routes-Df2tgpyd.js +1 -0
  44. package/apps/ui/dist/client/assets/scroll-text-fM0sMOB3.js +1 -0
  45. package/apps/ui/dist/client/assets/select-Bf2GwfPR.js +1 -0
  46. package/apps/ui/dist/client/assets/settings-5VQIzME0.js +1 -0
  47. package/apps/ui/dist/client/assets/sqlite-error-B6uZjUe8.js +1 -0
  48. package/apps/ui/dist/client/assets/styles-BhRkXgwB.css +1 -0
  49. package/apps/ui/dist/client/assets/tabs-OO4VU5KR.js +7 -0
  50. package/apps/ui/dist/client/assets/text-filter-DVAZySUS.js +2 -0
  51. package/apps/ui/dist/client/assets/threads._threadId-BB9tTsV4.js +1 -0
  52. package/apps/ui/dist/client/assets/threads._threadId-BgDhFj2I.js +1 -0
  53. package/apps/ui/dist/client/assets/useMutation-CC_B7uy5.js +1 -0
  54. package/apps/ui/dist/client/assets/useQuery-C5By6WKU.js +1 -0
  55. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CRW2kqj0.js +232 -0
  56. package/apps/ui/dist/server/assets/analytics-CYP_LT5Y.js +16 -0
  57. package/apps/ui/dist/server/assets/{analytics-CBNOYZwJ.js → analytics-CtpOMVMO.js} +13 -6
  58. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-BtexWY-K.js +613 -0
  59. package/apps/ui/dist/server/assets/{antigravity-conversations._conversationId-BIdYNy68.js → antigravity-conversations._conversationId-zMrR6v6R.js} +2 -2
  60. package/apps/ui/dist/server/assets/{antigravity-db-D9gW1D8G.js → antigravity-db-Bh8_U9uw.js} +11 -7
  61. package/apps/ui/dist/server/assets/{antigravity-keychain-panel-DcLyBBwd.js → antigravity-keychain-panel-CC7FLmAK.js} +1 -1
  62. package/apps/ui/dist/server/assets/{antigravity-queries-CgQhlQ7J.js → antigravity-queries-CGrJO9Vr.js} +6 -6
  63. package/apps/ui/dist/server/assets/{antigravity-server-DFUx4Khk.js → antigravity-server-CHRjVFqN.js} +11 -11
  64. package/apps/ui/dist/server/assets/{antigravity._workspaceKey-DnSlSC-C.js → antigravity._workspaceKey-B0QeYUOh.js} +2 -2
  65. package/apps/ui/dist/server/assets/{antigravity._workspaceKey-D42ixtzp.js → antigravity._workspaceKey-C3kP-qyN.js} +5 -5
  66. package/apps/ui/dist/server/assets/{antigravity.index-DZVT-cac.js → antigravity.index-CPCYkqCi.js} +2 -2
  67. package/apps/ui/dist/server/assets/{codex-queries-eOJGfHQj.js → codex-queries-CtgeZ7VL.js} +16 -14
  68. package/apps/ui/dist/server/assets/{codex-server-nrETIF--.js → codex-server-CNXSJuc2.js} +105 -120
  69. package/apps/ui/dist/server/assets/concurrency-VXtYvlGh.js +18 -0
  70. package/apps/ui/dist/server/assets/{createServerRpc-BtXIw2iP.js → createServerRpc-CF_DEwnm.js} +1 -1
  71. package/apps/ui/dist/server/assets/{createSsrRpc-COf5Zuye.js → createSsrRpc-C754NPki.js} +1 -1
  72. package/apps/ui/dist/server/assets/{cursor-db-B7agkAvM.js → cursor-db-cYZEU3WQ.js} +194 -7
  73. package/apps/ui/dist/server/assets/{cursor-queries-BMhuJeUO.js → cursor-queries-NCIM0Nat.js} +13 -11
  74. package/apps/ui/dist/server/assets/{cursor-recovery-9bJLs7vG.js → cursor-recovery-nq-kR62j.js} +1 -1
  75. package/apps/ui/dist/server/assets/{cursor-server-BgylIFgn.js → cursor-server-C3q7hrp-.js} +70 -41
  76. package/apps/ui/dist/server/assets/{cursor-threads._composerId-DXffY_CK.js → cursor-threads._composerId-BPJFWfJj.js} +2 -2
  77. package/apps/ui/dist/server/assets/cursor-threads._composerId-BkMMTQ3v.js +582 -0
  78. package/apps/ui/dist/server/assets/{cursor._workspaceKey-BP2J1x_x.js → cursor._workspaceKey-C5PdTaKB.js} +2 -2
  79. package/apps/ui/dist/server/assets/{cursor._workspaceKey-BQd0e-Pd.js → cursor._workspaceKey-Ckj7apKI.js} +11 -9
  80. package/apps/ui/dist/server/assets/{cursor.index-CQVxtCm8.js → cursor.index-DkWT-mxw.js} +2 -2
  81. package/apps/ui/dist/server/assets/{delete-confirm-dialog-PCD7S0_M.js → delete-confirm-dialog-BcBNCxWB.js} +5 -1
  82. package/apps/ui/dist/server/assets/empty-plugin-adapters-B3lHh1La.js +5 -0
  83. package/apps/ui/dist/server/assets/{export-dialog-DaPlOGFT.js → export-dialog-BItjWgkZ.js} +53 -11
  84. package/apps/ui/dist/server/assets/{projects._project-DUN3iWfg.js → projects._project-Bpbc3C-L.js} +5 -3
  85. package/apps/ui/dist/server/assets/{projects._project-Dim9Y0kD.js → projects._project-CvZho6EQ.js} +42 -12
  86. package/apps/ui/dist/server/assets/{projects.index-DjSQK5dm.js → projects.index-BkLiF2FF.js} +21 -7
  87. package/apps/ui/dist/server/assets/projects.index-DesYXwfi.js +14 -0
  88. package/apps/ui/dist/server/assets/route-search-ts4W9MJ9.js +38 -0
  89. package/apps/ui/dist/server/assets/{router-DrDgc-LD.js → router-6m-ihwqA.js} +78 -62
  90. package/apps/ui/dist/server/assets/{routes-B-GlEe2C.js → routes-Bsact1uB.js} +2 -2
  91. package/apps/ui/dist/server/assets/{routes-CNHAUMwo.js → routes-BzkJgq4W.js} +2 -2
  92. package/apps/ui/dist/server/assets/start-CI_0bSiY.js +4 -0
  93. package/apps/ui/dist/server/assets/tabs-CGA13IZM.js +502 -0
  94. package/apps/ui/dist/server/assets/{threads._threadId-CJzm4KrZ.js → threads._threadId-Bs0yuqO9.js} +2 -2
  95. package/apps/ui/dist/server/assets/threads._threadId-D2GYkVn6.js +639 -0
  96. package/apps/ui/dist/server/assets/ui-export-files-BHLX9bhN.js +83 -0
  97. package/apps/ui/dist/server/server.js +340 -218
  98. package/package.json +9 -9
  99. package/src/lib/antigravity-db.ts +20 -13
  100. package/src/lib/codex-analytics.ts +118 -18
  101. package/src/lib/codex-browser-db.ts +1 -25
  102. package/src/lib/codex-browser-export.ts +9 -69
  103. package/src/lib/cursor-db.ts +318 -7
  104. package/src/lib/cursor-exporter.ts +2 -2
  105. package/src/lib/ui-cache.ts +14 -1
  106. package/src/spiracha.ts +20 -1
  107. package/apps/ui/dist/client/assets/analytics-B_hYz65v.js +0 -1
  108. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-qiyygB7e.js +0 -1
  109. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-z1SQC2Kg.js +0 -1
  110. package/apps/ui/dist/client/assets/antigravity-keychain-panel-dYuRWtCf.js +0 -1
  111. package/apps/ui/dist/client/assets/antigravity._workspaceKey-CliqUr7o.js +0 -1
  112. package/apps/ui/dist/client/assets/antigravity._workspaceKey-CnoBzyX6.js +0 -1
  113. package/apps/ui/dist/client/assets/antigravity.index-CakfZz_E.js +0 -1
  114. package/apps/ui/dist/client/assets/antigravity.index-DY7M1KhG.js +0 -1
  115. package/apps/ui/dist/client/assets/badge-aHE9ETVe.js +0 -1
  116. package/apps/ui/dist/client/assets/checkbox-DN3XnJaA.js +0 -1
  117. package/apps/ui/dist/client/assets/cursor-threads._composerId-BMQyx8qG.js +0 -1
  118. package/apps/ui/dist/client/assets/cursor-threads._composerId-BTlaA-tV.js +0 -1
  119. package/apps/ui/dist/client/assets/cursor._workspaceKey-CrgrfevV.js +0 -1
  120. package/apps/ui/dist/client/assets/cursor._workspaceKey-bYS2syGL.js +0 -1
  121. package/apps/ui/dist/client/assets/cursor.index-CTqZMPYU.js +0 -1
  122. package/apps/ui/dist/client/assets/cursor.index-Clsz4E_e.js +0 -2
  123. package/apps/ui/dist/client/assets/delete-confirm-dialog-DTpzBiNK.js +0 -11
  124. package/apps/ui/dist/client/assets/dist-BNAn99Pu.js +0 -1
  125. package/apps/ui/dist/client/assets/download-P3Rp23Ad.js +0 -1
  126. package/apps/ui/dist/client/assets/dropdown-menu-3qB5j9nt.js +0 -1
  127. package/apps/ui/dist/client/assets/es2015-Dwm_turD.js +0 -41
  128. package/apps/ui/dist/client/assets/export-dialog-CazdrASq.js +0 -1
  129. package/apps/ui/dist/client/assets/formatters-BdnWuM1z.js +0 -1
  130. package/apps/ui/dist/client/assets/index-BVFnfS78.js +0 -22
  131. package/apps/ui/dist/client/assets/json-panel-DLkS30sQ.js +0 -1
  132. package/apps/ui/dist/client/assets/metadata-section-jnIkB7dB.js +0 -1
  133. package/apps/ui/dist/client/assets/metric-card-CBZuWLzQ.js +0 -1
  134. package/apps/ui/dist/client/assets/page-header-CnD21cPn.js +0 -1
  135. package/apps/ui/dist/client/assets/projects._project-BLszwvYL.js +0 -1
  136. package/apps/ui/dist/client/assets/projects._project-DvLxYbvk.js +0 -1
  137. package/apps/ui/dist/client/assets/projects.index-COn8woBR.js +0 -1
  138. package/apps/ui/dist/client/assets/projects.index-DYs98skV.js +0 -3
  139. package/apps/ui/dist/client/assets/refresh-ccw-BDrYXjtD.js +0 -1
  140. package/apps/ui/dist/client/assets/reload-error-panel-DLAg0AW2.js +0 -1
  141. package/apps/ui/dist/client/assets/routes-BtF5-coe.js +0 -1
  142. package/apps/ui/dist/client/assets/scroll-text-CqaFm9by.js +0 -1
  143. package/apps/ui/dist/client/assets/select-DbnpwqL6.js +0 -1
  144. package/apps/ui/dist/client/assets/settings-CGX3VleN.js +0 -1
  145. package/apps/ui/dist/client/assets/styles-Ch0r3kMZ.css +0 -1
  146. package/apps/ui/dist/client/assets/text-document-panel-DPleOmmq.js +0 -1
  147. package/apps/ui/dist/client/assets/text-filter-7M6wRo-t.js +0 -2
  148. package/apps/ui/dist/client/assets/threads._threadId-D5w76IB-.js +0 -7
  149. package/apps/ui/dist/client/assets/threads._threadId-Dx85sI9P.js +0 -1
  150. package/apps/ui/dist/client/assets/useMutation-MZ3Hr9h9.js +0 -1
  151. package/apps/ui/dist/client/assets/useQuery-Cb4V0AT0.js +0 -1
  152. package/apps/ui/dist/server/assets/__23tanstack-start-plugin-adapters-BzCA6dXo.js +0 -5
  153. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CBbkUXw6.js +0 -227
  154. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-B9Rm4EXh.js +0 -212
  155. package/apps/ui/dist/server/assets/cursor-threads._composerId-BsxFKzoJ.js +0 -218
  156. package/apps/ui/dist/server/assets/json-panel-RYsxWFae.js +0 -16
  157. package/apps/ui/dist/server/assets/metadata-section-D6Lbc7D6.js +0 -54
  158. package/apps/ui/dist/server/assets/start-HeKLHD9b.js +0 -4
  159. package/apps/ui/dist/server/assets/text-document-panel-D8JbQWAn.js +0 -23
  160. package/apps/ui/dist/server/assets/threads._threadId-DODTYddm.js +0 -1052
@@ -2,7 +2,7 @@ import { t as cn } from "./utils-C_uf36nf.js";
2
2
  import { t as Button } from "./button-CmTDnzOn.js";
3
3
  import { t as Checkbox$1 } from "./checkbox-C0hovF41.js";
4
4
  import { a as SelectValue, i as SelectTrigger, n as SelectContent, r as SelectItem, t as Select$1 } from "./select-GW76p-ld.js";
5
- import { useState } from "react";
5
+ import { useEffect, useId, useState } from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  import { XIcon } from "lucide-react";
8
8
  import { Dialog } from "radix-ui";
@@ -81,11 +81,23 @@ function DialogDescription({ className, ...props }) {
81
81
  }
82
82
  //#endregion
83
83
  //#region src/components/export-dialog.tsx
84
- function ExportDialog({ open, pending = false, title = "Export thread", onExport, onOpenChange }) {
84
+ function ExportDialog({ errorMessage = null, forceZipArchive = false, open, pending = false, title = "Export thread", onExport, onOpenChange }) {
85
85
  const [outputFormat, setOutputFormat] = useState("md");
86
86
  const [includeMetadata, setIncludeMetadata] = useState(true);
87
87
  const [includeCommentary, setIncludeCommentary] = useState(false);
88
88
  const [includeTools, setIncludeTools] = useState(true);
89
+ const [zipArchive, setZipArchive] = useState(false);
90
+ const effectiveZipArchive = forceZipArchive || zipArchive;
91
+ const zipDescriptionId = useId();
92
+ useEffect(() => {
93
+ if (!open) {
94
+ setOutputFormat("md");
95
+ setIncludeMetadata(true);
96
+ setIncludeCommentary(false);
97
+ setIncludeTools(true);
98
+ setZipArchive(false);
99
+ }
100
+ }, [open]);
89
101
  return /* @__PURE__ */ jsx(Dialog$1, {
90
102
  open,
91
103
  onOpenChange,
@@ -110,15 +122,20 @@ function ExportDialog({ open, pending = false, title = "Export thread", onExport
110
122
  onValueChange: (value) => setOutputFormat(value),
111
123
  children: [/* @__PURE__ */ jsx(SelectTrigger, {
112
124
  id: "output-format",
113
- className: "border-[var(--border)] bg-[var(--panel-secondary)]",
125
+ className: "border-[var(--border)] bg-[var(--panel-secondary)] text-[var(--foreground)]",
114
126
  children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Choose a format" })
115
- }), /* @__PURE__ */ jsxs(SelectContent, { children: [/* @__PURE__ */ jsx(SelectItem, {
116
- value: "md",
117
- children: "Markdown (.md)"
118
- }), /* @__PURE__ */ jsx(SelectItem, {
119
- value: "txt",
120
- children: "Plain text (.txt)"
121
- })] })]
127
+ }), /* @__PURE__ */ jsxs(SelectContent, {
128
+ className: "border-[var(--border)] bg-[var(--panel)] text-[var(--foreground)] shadow-[var(--panel-shadow)]",
129
+ children: [/* @__PURE__ */ jsx(SelectItem, {
130
+ className: "focus:bg-[var(--panel-secondary)] focus:text-[var(--foreground)] data-[highlighted]:bg-[var(--panel-secondary)] data-[highlighted]:text-[var(--foreground)]",
131
+ value: "md",
132
+ children: "Markdown (.md)"
133
+ }), /* @__PURE__ */ jsx(SelectItem, {
134
+ className: "focus:bg-[var(--panel-secondary)] focus:text-[var(--foreground)] data-[highlighted]:bg-[var(--panel-secondary)] data-[highlighted]:text-[var(--foreground)]",
135
+ value: "txt",
136
+ children: "Plain text (.txt)"
137
+ })]
138
+ })]
122
139
  })]
123
140
  }),
124
141
  /* @__PURE__ */ jsxs("div", {
@@ -171,9 +188,33 @@ function ExportDialog({ open, pending = false, title = "Export thread", onExport
171
188
  children: "Includes tool-call summaries and tool-output summaries in the export."
172
189
  })]
173
190
  })]
191
+ }),
192
+ /* @__PURE__ */ jsxs("div", {
193
+ className: "flex items-center gap-3 rounded-2xl border border-[var(--border)] bg-[var(--panel-secondary)] p-3",
194
+ children: [/* @__PURE__ */ jsx(Checkbox$1, {
195
+ "aria-label": "Zip archive",
196
+ "aria-describedby": zipDescriptionId,
197
+ checked: effectiveZipArchive,
198
+ disabled: forceZipArchive,
199
+ onCheckedChange: (checked) => setZipArchive(checked === true)
200
+ }), /* @__PURE__ */ jsxs("span", {
201
+ className: "space-y-1",
202
+ children: [/* @__PURE__ */ jsx("span", {
203
+ className: "block font-medium text-sm",
204
+ children: "Zip archive"
205
+ }), /* @__PURE__ */ jsx("span", {
206
+ className: "block text-[var(--muted-foreground)] text-sm",
207
+ id: zipDescriptionId,
208
+ children: forceZipArchive ? "Required when exporting multiple threads." : "Downloads the exported transcript inside a .zip archive."
209
+ })]
210
+ })]
174
211
  })
175
212
  ]
176
213
  }),
214
+ errorMessage ? /* @__PURE__ */ jsx("p", {
215
+ className: "text-[var(--destructive)] text-sm",
216
+ children: errorMessage
217
+ }) : null,
177
218
  /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(Button, {
178
219
  className: "rounded-full",
179
220
  variant: "outline",
@@ -186,7 +227,8 @@ function ExportDialog({ open, pending = false, title = "Export thread", onExport
186
227
  includeCommentary,
187
228
  includeMetadata,
188
229
  includeTools,
189
- outputFormat
230
+ outputFormat,
231
+ zipArchive: effectiveZipArchive
190
232
  }),
191
233
  children: pending ? "Exporting..." : "Download export"
192
234
  })] })
@@ -1,10 +1,11 @@
1
- import { r as projectThreadsQueryOptions } from "./codex-queries-eOJGfHQj.js";
1
+ import { r as projectThreadsQueryOptions } from "./codex-queries-CtgeZ7VL.js";
2
+ import { i as parseTextQuerySearch } from "./route-search-ts4W9MJ9.js";
2
3
  import { t as LoadingPanel } from "./loading-panel-BGFnWseS.js";
3
4
  import { createFileRoute, lazyRouteComponent } from "@tanstack/react-router";
4
5
  import { jsx } from "react/jsx-runtime";
5
6
  //#region src/routes/projects.$project.tsx
6
7
  var $$splitErrorComponentImporter = () => import("./projects._project-Bshqk7JA.js");
7
- var $$splitComponentImporter = () => import("./projects._project-Dim9Y0kD.js");
8
+ var $$splitComponentImporter = () => import("./projects._project-CvZho6EQ.js");
8
9
  var Route = createFileRoute("/projects/$project")({
9
10
  component: lazyRouteComponent($$splitComponentImporter, "component"),
10
11
  errorComponent: lazyRouteComponent($$splitErrorComponentImporter, "errorComponent"),
@@ -12,7 +13,8 @@ var Route = createFileRoute("/projects/$project")({
12
13
  pendingComponent: () => /* @__PURE__ */ jsx(LoadingPanel, {
13
14
  description: "Loading project threads and transcript summaries. Large projects can take a moment.",
14
15
  title: "Loading project"
15
- })
16
+ }),
17
+ validateSearch: parseTextQuerySearch
16
18
  });
17
19
  //#endregion
18
20
  export { Route as t };
@@ -1,17 +1,18 @@
1
1
  import { t as Button } from "./button-CmTDnzOn.js";
2
2
  import { n as useSettings } from "./settings-store-DpEJEQ7M.js";
3
- import { c as deleteThreadFn, d as exportThreadsFn, f as recoverProjectThreadsFn, l as deleteThreadsFn, r as projectThreadsQueryOptions, u as exportThreadFn } from "./codex-queries-eOJGfHQj.js";
4
- import { t as Route } from "./projects._project-DUN3iWfg.js";
3
+ import { c as deleteThreadFn, d as exportThreadsFn, f as recoverProjectThreadsFn, l as deleteThreadsFn, r as projectThreadsQueryOptions, u as exportThreadFn } from "./codex-queries-CtgeZ7VL.js";
4
+ import { o as withTextQuerySearch } from "./route-search-ts4W9MJ9.js";
5
+ import { t as Route } from "./projects._project-Bpbc3C-L.js";
5
6
  import { t as DataTable } from "./data-table-Cdct823O.js";
6
7
  import { t as PageHeader } from "./page-header-VNSaM3xd.js";
7
8
  import { n as formatBytes, o as formatNumber, r as formatDateTime, s as formatTokens } from "./formatters-FJaGZgJk.js";
8
9
  import { n as downloadUrlFile, t as downloadTextFile } from "./download-DMmiy1xf.js";
9
10
  import { i as DropdownMenuTrigger, n as DropdownMenuContent, r as DropdownMenuItem, t as DropdownMenu } from "./dropdown-menu-Dy_9t6TN.js";
10
11
  import { n as ListSearchInput, t as matchesTextQuery } from "./text-filter-CGKxMCKt.js";
11
- import { t as DeleteConfirmDialog } from "./delete-confirm-dialog-PCD7S0_M.js";
12
- import { t as ExportDialog } from "./export-dialog-DaPlOGFT.js";
13
- import { useDeferredValue, useMemo, useState } from "react";
14
- import { Link } from "@tanstack/react-router";
12
+ import { t as DeleteConfirmDialog } from "./delete-confirm-dialog-BcBNCxWB.js";
13
+ import { t as ExportDialog } from "./export-dialog-BItjWgkZ.js";
14
+ import { startTransition, useDeferredValue, useMemo, useState } from "react";
15
+ import { Link, useNavigate } from "@tanstack/react-router";
15
16
  import { jsx, jsxs } from "react/jsx-runtime";
16
17
  import { useMutation, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
17
18
  import { Download, MoreHorizontal, RefreshCcw, Trash2, X } from "lucide-react";
@@ -186,12 +187,30 @@ function ThreadsTable({ threads, onDeleteThread, onDeleteThreads, onExportThread
186
187
  }
187
188
  //#endregion
188
189
  //#region src/routes/projects.$project.tsx?tsr-split=component
190
+ var shouldForceZipArchive = (pendingExport) => {
191
+ return Boolean(pendingExport && pendingExport.threadIds.length > 1);
192
+ };
193
+ var getDeleteConfirmLabel = (pendingDelete, isPending) => {
194
+ if (isPending) return "Deleting...";
195
+ if (pendingDelete && pendingDelete.threads.length > 1) return "Delete threads";
196
+ return "Delete thread";
197
+ };
198
+ var getDeleteDescription = (pendingDelete) => {
199
+ if (!pendingDelete) return "";
200
+ if (pendingDelete.threads.length === 1) return `Delete the thread "${pendingDelete.threads[0].thread.title}" from the Codex database. Leave Session files unchecked if you only want to remove the current DB row.`;
201
+ return `Delete ${pendingDelete.threads.length} selected threads from the Codex database. Enable Delete Session files if you also want to remove their rollout JSONL files.`;
202
+ };
203
+ var getDeleteTitle = (pendingDelete) => {
204
+ if (pendingDelete && pendingDelete.threads.length > 1) return `Delete ${pendingDelete.threads.length} Codex threads?`;
205
+ return "Delete Codex thread?";
206
+ };
189
207
  function ProjectDetailPage() {
208
+ const navigate = useNavigate({ from: Route.fullPath });
190
209
  const params = Route.useParams();
191
210
  const queryClient = useQueryClient();
192
211
  const threads = useSuspenseQuery(projectThreadsQueryOptions(params.project)).data;
193
212
  const { settings } = useSettings();
194
- const [searchInput, setSearchInput] = useState("");
213
+ const searchInput = Route.useSearch().q ?? "";
195
214
  const [pendingDelete, setPendingDelete] = useState(null);
196
215
  const [pendingExport, setPendingExport] = useState(null);
197
216
  const deferredSearch = useDeferredValue(searchInput.trim().toLowerCase());
@@ -231,7 +250,8 @@ function ProjectDetailPage() {
231
250
  outputFormat: options.outputFormat,
232
251
  project: params.project,
233
252
  selectedThreadCount: pendingExport.threadIds.length,
234
- selectedThreadIds: pendingExport.threadIds
253
+ selectedThreadIds: pendingExport.threadIds,
254
+ zipArchive: options.zipArchive
235
255
  });
236
256
  const download = pendingExport.threadIds.length === 1 ? await exportThreadFn({ data: {
237
257
  ...options,
@@ -276,6 +296,15 @@ function ProjectDetailPage() {
276
296
  ]);
277
297
  });
278
298
  const visibleThreadsById = useMemo(() => new Map(visibleThreads.map((thread) => [thread.thread.id, thread])), [visibleThreads]);
299
+ const updateSearchInput = (value) => {
300
+ startTransition(() => {
301
+ navigate({
302
+ params: true,
303
+ replace: true,
304
+ search: (previous) => withTextQuerySearch(previous, value)
305
+ });
306
+ });
307
+ };
279
308
  const lookupSelectedThreads = (threadIds) => {
280
309
  return threadIds.map((threadId) => visibleThreadsById.get(threadId) ?? null).filter((thread) => thread !== null);
281
310
  };
@@ -295,7 +324,7 @@ function ProjectDetailPage() {
295
324
  }), /* @__PURE__ */ jsx(ListSearchInput, {
296
325
  placeholder: "Search thread title, preview, or model",
297
326
  value: searchInput,
298
- onValueChange: setSearchInput
327
+ onValueChange: updateSearchInput
299
328
  })]
300
329
  }),
301
330
  eyebrow: "Codex project",
@@ -332,12 +361,12 @@ function ProjectDetailPage() {
332
361
  }
333
362
  }),
334
363
  /* @__PURE__ */ jsx(DeleteConfirmDialog, {
335
- confirmLabel: deleteThreadMutation.isPending ? "Deleting..." : pendingDelete && pendingDelete.threads.length > 1 ? "Delete threads" : "Delete thread",
364
+ confirmLabel: getDeleteConfirmLabel(pendingDelete, deleteThreadMutation.isPending),
336
365
  defaultDeleteSessionFiles: true,
337
- description: pendingDelete ? pendingDelete.threads.length === 1 ? `Delete the thread "${pendingDelete.threads[0].thread.title}" from the Codex database. Leave Session files unchecked if you only want to remove the current DB row.` : `Delete ${pendingDelete.threads.length} selected threads from the Codex database. Enable Delete Session files if you also want to remove their rollout JSONL files.` : "",
366
+ description: getDeleteDescription(pendingDelete),
338
367
  open: pendingDelete !== null,
339
368
  showDeleteSessionFilesOption: true,
340
- title: pendingDelete && pendingDelete.threads.length > 1 ? `Delete ${pendingDelete.threads.length} Codex threads?` : "Delete Codex thread?",
369
+ title: getDeleteTitle(pendingDelete),
341
370
  onConfirm: ({ deleteSessionFiles }) => {
342
371
  if (!pendingDelete) return;
343
372
  deleteThreadMutation.mutate({
@@ -350,6 +379,7 @@ function ProjectDetailPage() {
350
379
  }
351
380
  }),
352
381
  /* @__PURE__ */ jsx(ExportDialog, {
382
+ forceZipArchive: shouldForceZipArchive(pendingExport),
353
383
  open: pendingExport !== null,
354
384
  pending: exportThreadMutation.isPending,
355
385
  title: pendingExport ? `Export ${pendingExport.threadLabel}` : "Export thread",
@@ -1,13 +1,15 @@
1
1
  import { t as Button } from "./button-CmTDnzOn.js";
2
- import { i as projectsQueryOptions, s as deleteProjectFn } from "./codex-queries-eOJGfHQj.js";
2
+ import { i as projectsQueryOptions, s as deleteProjectFn } from "./codex-queries-CtgeZ7VL.js";
3
+ import { o as withTextQuerySearch } from "./route-search-ts4W9MJ9.js";
4
+ import { t as Route } from "./projects.index-DesYXwfi.js";
3
5
  import { t as DataTable } from "./data-table-Cdct823O.js";
4
6
  import { t as PageHeader } from "./page-header-VNSaM3xd.js";
5
7
  import { i as formatList, o as formatNumber, r as formatDateTime, s as formatTokens } from "./formatters-FJaGZgJk.js";
6
8
  import { i as DropdownMenuTrigger, n as DropdownMenuContent, r as DropdownMenuItem, t as DropdownMenu } from "./dropdown-menu-Dy_9t6TN.js";
7
9
  import { n as ListSearchInput, t as matchesTextQuery } from "./text-filter-CGKxMCKt.js";
8
- import { t as DeleteConfirmDialog } from "./delete-confirm-dialog-PCD7S0_M.js";
9
- import { useDeferredValue, useState } from "react";
10
- import { Link } from "@tanstack/react-router";
10
+ import { t as DeleteConfirmDialog } from "./delete-confirm-dialog-BcBNCxWB.js";
11
+ import { startTransition, useDeferredValue, useState } from "react";
12
+ import { Link, useNavigate } from "@tanstack/react-router";
11
13
  import { jsx, jsxs } from "react/jsx-runtime";
12
14
  import { useMutation, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
13
15
  import { MoreHorizontal, Trash2 } from "lucide-react";
@@ -98,15 +100,20 @@ function ProjectsTable({ projects, onDeleteProject }) {
98
100
  return /* @__PURE__ */ jsx(DataTable, {
99
101
  columns: columns(onDeleteProject),
100
102
  data: projects,
101
- emptyMessage: "No projects match the current search."
103
+ emptyMessage: "No projects match the current search.",
104
+ initialSorting: [{
105
+ desc: true,
106
+ id: "lastUpdatedAtMs"
107
+ }]
102
108
  });
103
109
  }
104
110
  //#endregion
105
111
  //#region src/routes/projects.index.tsx?tsr-split=component
106
112
  function ProjectsPage() {
113
+ const navigate = useNavigate({ from: Route.fullPath });
107
114
  const queryClient = useQueryClient();
108
115
  const projects = useSuspenseQuery(projectsQueryOptions()).data;
109
- const [searchInput, setSearchInput] = useState("");
116
+ const searchInput = Route.useSearch().q ?? "";
110
117
  const [pendingDelete, setPendingDelete] = useState(null);
111
118
  const deferredSearch = useDeferredValue(searchInput.trim().toLowerCase());
112
119
  const deleteProjectMutation = useMutation({
@@ -134,7 +141,14 @@ function ProjectsPage() {
134
141
  actions: /* @__PURE__ */ jsx(ListSearchInput, {
135
142
  placeholder: "Search project name, cwd, or model",
136
143
  value: searchInput,
137
- onValueChange: setSearchInput
144
+ onValueChange: (value) => {
145
+ startTransition(() => {
146
+ navigate({
147
+ replace: true,
148
+ search: (previous) => withTextQuerySearch(previous, value)
149
+ });
150
+ });
151
+ }
138
152
  }),
139
153
  eyebrow: "Inventory",
140
154
  subtitle: "Derived projects are grouped from the final basename of each thread cwd, matching the existing CLI behavior.",
@@ -0,0 +1,14 @@
1
+ import { i as projectsQueryOptions } from "./codex-queries-CtgeZ7VL.js";
2
+ import { i as parseTextQuerySearch } from "./route-search-ts4W9MJ9.js";
3
+ import { createFileRoute, lazyRouteComponent } from "@tanstack/react-router";
4
+ //#region src/routes/projects.index.tsx
5
+ var $$splitErrorComponentImporter = () => import("./projects.index-BLXOx5eL.js");
6
+ var $$splitComponentImporter = () => import("./projects.index-BkLiF2FF.js");
7
+ var Route = createFileRoute("/projects/")({
8
+ component: lazyRouteComponent($$splitComponentImporter, "component"),
9
+ errorComponent: lazyRouteComponent($$splitErrorComponentImporter, "errorComponent"),
10
+ loader: ({ context }) => context.queryClient.ensureQueryData(projectsQueryOptions()),
11
+ validateSearch: parseTextQuerySearch
12
+ });
13
+ //#endregion
14
+ export { Route as t };
@@ -0,0 +1,38 @@
1
+ //#region src/lib/route-search.ts
2
+ var asNonBlankString = (value) => {
3
+ if (typeof value !== "string") return;
4
+ const trimmed = value.trim();
5
+ return trimmed.length > 0 ? trimmed : void 0;
6
+ };
7
+ var parseTextQuerySearch = (search) => {
8
+ const q = asNonBlankString(search.q);
9
+ return q ? { q } : {};
10
+ };
11
+ var parseAnalyticsSearch = (search) => {
12
+ const project = asNonBlankString(search.project);
13
+ return project ? { project } : {};
14
+ };
15
+ var withTextQuerySearch = (current, query) => {
16
+ const next = { ...current };
17
+ const q = asNonBlankString(query);
18
+ if (q) next.q = q;
19
+ else delete next.q;
20
+ return next;
21
+ };
22
+ var withAnalyticsProjectSearch = (current, project) => {
23
+ const next = { ...current };
24
+ const trimmedProject = asNonBlankString(project);
25
+ if (trimmedProject) next.project = trimmedProject;
26
+ else delete next.project;
27
+ return next;
28
+ };
29
+ var ALL_PROJECTS_SELECT_VALUE = "__all__";
30
+ var PROJECT_SELECT_PREFIX = "project:";
31
+ var encodeAnalyticsProjectSelectValue = (project) => {
32
+ return project ? `${PROJECT_SELECT_PREFIX}${project}` : ALL_PROJECTS_SELECT_VALUE;
33
+ };
34
+ var decodeAnalyticsProjectSelectValue = (value) => {
35
+ return value === ALL_PROJECTS_SELECT_VALUE || !value.startsWith(PROJECT_SELECT_PREFIX) ? null : value.slice(8);
36
+ };
37
+ //#endregion
38
+ export { withAnalyticsProjectSearch as a, parseTextQuerySearch as i, encodeAnalyticsProjectSelectValue as n, withTextQuerySearch as o, parseAnalyticsSearch as r, decodeAnalyticsProjectSelectValue as t };
@@ -1,16 +1,17 @@
1
1
  import { t as cn } from "./utils-C_uf36nf.js";
2
2
  import { t as Button } from "./button-CmTDnzOn.js";
3
3
  import { t as SettingsProvider } from "./settings-store-DpEJEQ7M.js";
4
- import { i as projectsQueryOptions, t as analyticsQueryOptions } from "./codex-queries-eOJGfHQj.js";
5
- import { t as Route$7 } from "./routes-CNHAUMwo.js";
6
- import { r as cursorWorkspacesQueryOptions } from "./cursor-queries-BMhuJeUO.js";
7
- import { i as antigravityWorkspacesQueryOptions } from "./antigravity-queries-CgQhlQ7J.js";
8
- import { t as Route$8 } from "./threads._threadId-CJzm4KrZ.js";
9
- import { t as Route$9 } from "./projects._project-DUN3iWfg.js";
10
- import { t as Route$10 } from "./cursor._workspaceKey-BP2J1x_x.js";
11
- import { t as Route$11 } from "./cursor-threads._composerId-DXffY_CK.js";
12
- import { t as Route$12 } from "./antigravity._workspaceKey-DnSlSC-C.js";
13
- import { t as Route$13 } from "./antigravity-conversations._conversationId-BIdYNy68.js";
4
+ import { t as Route$5 } from "./analytics-CYP_LT5Y.js";
5
+ import { t as Route$6 } from "./routes-BzkJgq4W.js";
6
+ import { t as Route$7 } from "./projects.index-DesYXwfi.js";
7
+ import { r as cursorWorkspacesQueryOptions } from "./cursor-queries-NCIM0Nat.js";
8
+ import { i as antigravityWorkspacesQueryOptions } from "./antigravity-queries-CGrJO9Vr.js";
9
+ import { t as Route$8 } from "./threads._threadId-Bs0yuqO9.js";
10
+ import { t as Route$9 } from "./projects._project-Bpbc3C-L.js";
11
+ import { t as Route$10 } from "./cursor._workspaceKey-C5PdTaKB.js";
12
+ import { t as Route$11 } from "./cursor-threads._composerId-BPJFWfJj.js";
13
+ import { t as Route$12 } from "./antigravity._workspaceKey-B0QeYUOh.js";
14
+ import { t as Route$13 } from "./antigravity-conversations._conversationId-zMrR6v6R.js";
14
15
  import { useEffect, useState } from "react";
15
16
  import { HeadContent, Link, Outlet, Scripts, createFileRoute, createRootRouteWithContext, createRouter, lazyRouteComponent, notFound, redirect, useRouterState } from "@tanstack/react-router";
16
17
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -23,6 +24,19 @@ function getContext() {
23
24
  return { queryClient: new QueryClient() };
24
25
  }
25
26
  //#endregion
27
+ //#region ../../package.json?raw
28
+ var package_default = "{\n \"author\": {\n \"name\": \"Ragaeeb Haq\",\n \"url\": \"https://github.com/ragaeeb\"\n },\n \"bin\": {\n \"codex-chats\": \"./bin/codex-chats.js\",\n \"codex-chats-claude\": \"./bin/codex-chats-claude.js\",\n \"spiracha\": \"./bin/spiracha.js\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/ragaeeb/spiracha/issues\"\n },\n \"dependencies\": {\n \"@inquirer/prompts\": \"^8.5.2\",\n \"@modelcontextprotocol/sdk\": \"^1.29.0\",\n \"@tanstack/react-query\": \"5.101.0\",\n \"@tanstack/react-router\": \"1.170.15\",\n \"@tanstack/react-router-ssr-query\": \"1.167.1\",\n \"@tanstack/react-table\": \"8.21.3\",\n \"@tanstack/react-virtual\": \"3.14.2\",\n \"class-variance-authority\": \"0.7.1\",\n \"clsx\": \"2.1.1\",\n \"iconv-lite\": \"^0.7.2\",\n \"lucide-react\": \"1.17.0\",\n \"radix-ui\": \"1.5.0\",\n \"react\": \"19.2.7\",\n \"react-dom\": \"19.2.7\",\n \"tailwind-merge\": \"3.6.0\",\n \"zod\": \"4.4.3\"\n },\n \"description\": \"Export local Codex, Claude Code, and Cursor transcripts, and browse Codex, Cursor, and Antigravity history through a local UI.\",\n \"devDependencies\": {\n \"@types/bun\": \"^1.3.14\",\n \"@types/node\": \"^25.9.2\",\n \"typescript\": \"^6.0.3\"\n },\n \"engines\": {\n \"bun\": \">=1.3.14\"\n },\n \"files\": [\n \"bin/codex-chats.js\",\n \"bin/codex-chats-claude.js\",\n \"bin/spiracha.js\",\n \"src/export-chats.ts\",\n \"src/export-claude.ts\",\n \"src/export-cursor.ts\",\n \"src/mcp-server.ts\",\n \"src/spiracha.ts\",\n \"src/ui-cli.ts\",\n \"src/lib/antigravity-db.ts\",\n \"src/lib/antigravity-exporter-types.ts\",\n \"src/lib/antigravity-keychain.ts\",\n \"src/lib/claude-exporter.ts\",\n \"src/lib/cursor-db.ts\",\n \"src/lib/cursor-exporter.ts\",\n \"src/lib/cursor-exporter-types.ts\",\n \"src/lib/cursor-recovery.ts\",\n \"src/lib/cursor-transcript.ts\",\n \"src/lib/codex-exporter-cli.ts\",\n \"src/lib/codex-exporter-db.ts\",\n \"src/lib/codex-exporter-transcript.ts\",\n \"src/lib/codex-exporter-types.ts\",\n \"src/lib/codex-exporter.ts\",\n \"src/lib/codex-browser-db.ts\",\n \"src/lib/codex-browser-export.ts\",\n \"src/lib/codex-browser-types.ts\",\n \"src/lib/codex-thread-recovery.ts\",\n \"src/lib/codex-thread-cache.ts\",\n \"src/lib/codex-thread-parser.ts\",\n \"src/lib/codex-analytics.ts\",\n \"src/lib/path-transforms.ts\",\n \"src/lib/sqlite-error.ts\",\n \"src/lib/sqlite-retry.ts\",\n \"src/lib/ui-export-files.ts\",\n \"src/lib/ui-cache.ts\",\n \"src/lib/interactive-cli.ts\",\n \"src/lib/model-label.ts\",\n \"src/lib/native-open.ts\",\n \"src/lib/shared.ts\",\n \"apps/ui/dist/client/assets/**/*\",\n \"apps/ui/dist/client/icon.svg\",\n \"apps/ui/dist/client/manifest.json\",\n \"apps/ui/dist/client/robots.txt\",\n \"apps/ui/dist/server/**/*\",\n \"README.md\",\n \"AGENTS.md\"\n ],\n \"homepage\": \"https://github.com/ragaeeb/spiracha\",\n \"keywords\": [\n \"codex\",\n \"claude\",\n \"cursor\",\n \"antigravity\",\n \"transcripts\",\n \"export\",\n \"markdown\",\n \"bun\"\n ],\n \"license\": \"MIT\",\n \"name\": \"spiracha\",\n \"packageManager\": \"bun@1.3.14\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/ragaeeb/spiracha.git\"\n },\n \"scripts\": {\n \"build\": \"bun run typecheck && bun run --cwd apps/ui build\",\n \"coverage\": \"bun run coverage:root && bun run coverage:ui\",\n \"coverage:root\": \"bun test --coverage --coverage-reporter=lcov --coverage-dir coverage && bun run ./src/coverage-check.ts root\",\n \"coverage:ui\": \"bun run --cwd apps/ui coverage && bun run ./src/coverage-check.ts ui\",\n \"export:claude\": \"bun run ./src/export-claude.ts\",\n \"format\": \"biome check . --write && biome lint . --write\",\n \"lint\": \"biome check .\",\n \"mcp\": \"bun run ./src/mcp-server.ts\",\n \"smoke:package-ui\": \"bun run ./src/package-ui-smoke.ts\",\n \"start\": \"bun run ./src/export-chats.ts\",\n \"typecheck\": \"bun run typecheck:root && bun run typecheck:ui\",\n \"typecheck:root\": \"bunx tsc --noEmit\",\n \"typecheck:ui\": \"bun run --cwd apps/ui typecheck\",\n \"ui:dev\": \"bun run --cwd apps/ui dev\",\n \"ui:preview\": \"bun run --cwd apps/ui preview\"\n },\n \"type\": \"module\",\n \"version\": \"1.4.0\",\n \"workspaces\": [\n \"apps/*\"\n ]\n}\n";
29
+ //#endregion
30
+ //#region src/lib/package-metadata.ts
31
+ var parsePackageMetadata = () => {
32
+ const packageJson = JSON.parse(package_default);
33
+ return {
34
+ homepage: typeof packageJson.homepage === "string" ? packageJson.homepage : "",
35
+ version: typeof packageJson.version === "string" ? packageJson.version : "0.0.0"
36
+ };
37
+ };
38
+ var packageMetadata = parsePackageMetadata();
39
+ //#endregion
26
40
  //#region src/components/theme-toggle.tsx
27
41
  var getPreferredTheme = () => {
28
42
  if (typeof window === "undefined") return "light";
@@ -96,6 +110,13 @@ var navItems = [
96
110
  var isNavItemActive = (pathname, item) => {
97
111
  return (item.activePrefixes ?? [item.to]).some((prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`));
98
112
  };
113
+ var GitHubIcon = ({ className }) => /* @__PURE__ */ jsx("svg", {
114
+ "aria-hidden": "true",
115
+ className,
116
+ fill: "currentColor",
117
+ viewBox: "0 0 24 24",
118
+ children: /* @__PURE__ */ jsx("path", { d: "M12 2C6.48 2 2 6.59 2 12.25c0 4.53 2.87 8.36 6.84 9.72.5.09.68-.22.68-.49v-1.9c-2.78.62-3.37-1.22-3.37-1.22-.45-1.18-1.11-1.49-1.11-1.49-.91-.64.07-.63.07-.63 1 .07 1.53 1.06 1.53 1.06.9 1.56 2.35 1.11 2.92.85.09-.67.35-1.11.63-1.37-2.22-.26-4.56-1.14-4.56-5.06 0-1.12.39-2.03 1.03-2.75-.1-.26-.45-1.3.1-2.71 0 0 .84-.28 2.75 1.05A9.35 9.35 0 0 1 12 6.98c.85 0 1.7.12 2.5.35 1.9-1.33 2.74-1.05 2.74-1.05.55 1.41.2 2.45.1 2.71.64.72 1.03 1.63 1.03 2.75 0 3.93-2.34 4.79-4.57 5.05.36.32.68.95.68 1.91v2.78c0 .27.18.59.69.49A10.22 10.22 0 0 0 22 12.25C22 6.59 17.52 2 12 2Z" })
119
+ });
99
120
  function AppShell({ children }) {
100
121
  const pathname = useRouterState({ select: (state) => state.location.pathname });
101
122
  return /* @__PURE__ */ jsx("div", {
@@ -108,13 +129,26 @@ function AppShell({ children }) {
108
129
  className: "flex items-start justify-between gap-4 lg:flex-col lg:items-stretch",
109
130
  children: [/* @__PURE__ */ jsxs("div", {
110
131
  className: "space-y-1.5",
111
- children: [/* @__PURE__ */ jsx("p", {
132
+ children: [/* @__PURE__ */ jsxs("p", {
112
133
  className: "font-semibold text-[10px] text-[var(--muted-foreground)] uppercase tracking-[0.18em]",
113
- children: "Spiracha"
114
- }), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("h1", {
115
- className: "font-['IBM_Plex_Sans'] font-semibold text-lg tracking-[-0.02em]",
116
- children: "Spiracha Console"
117
- }) })]
134
+ children: ["Spiracha ", /* @__PURE__ */ jsxs("span", {
135
+ className: "tracking-normal",
136
+ children: ["v", packageMetadata.version]
137
+ })]
138
+ }), /* @__PURE__ */ jsxs("div", {
139
+ className: "space-y-1",
140
+ children: [/* @__PURE__ */ jsx("h1", {
141
+ className: "font-['IBM_Plex_Sans'] font-semibold text-lg tracking-[-0.02em]",
142
+ children: "Spiracha Console"
143
+ }), packageMetadata.homepage ? /* @__PURE__ */ jsx("a", {
144
+ "aria-label": "Open Spiracha GitHub repository",
145
+ className: "inline-flex size-7 items-center justify-center rounded-md text-[var(--muted-foreground)] transition-colors hover:bg-[var(--panel-secondary)] hover:text-[var(--foreground)]",
146
+ href: packageMetadata.homepage,
147
+ rel: "noreferrer",
148
+ target: "_blank",
149
+ children: /* @__PURE__ */ jsx(GitHubIcon, { className: "size-4" })
150
+ }) : null]
151
+ })]
118
152
  }), /* @__PURE__ */ jsx(ThemeToggle, {})]
119
153
  }), /* @__PURE__ */ jsx("nav", {
120
154
  className: "mt-5 grid gap-1",
@@ -146,7 +180,7 @@ function TooltipProvider({ delayDuration = 0, ...props }) {
146
180
  }
147
181
  //#endregion
148
182
  //#region src/styles.css?url
149
- var styles_default = "/assets/styles-Ch0r3kMZ.css";
183
+ var styles_default = "/assets/styles-BhRkXgwB.css";
150
184
  //#endregion
151
185
  //#region src/routes/__root.tsx
152
186
  var themeInitScript = `
@@ -191,7 +225,7 @@ function RootErrorComponent({ error }) {
191
225
  })
192
226
  });
193
227
  }
194
- var Route$6 = createRootRouteWithContext()({
228
+ var Route$4 = createRootRouteWithContext()({
195
229
  component: RootComponent,
196
230
  errorComponent: RootErrorComponent,
197
231
  head: () => ({
@@ -236,25 +270,16 @@ function RootDocument({ children }) {
236
270
  }
237
271
  //#endregion
238
272
  //#region src/routes/settings.tsx
239
- var $$splitComponentImporter$5 = () => import("./settings-OayxIYQQ.js");
240
- var Route$5 = createFileRoute("/settings")({ component: lazyRouteComponent($$splitComponentImporter$5, "component") });
241
- //#endregion
242
- //#region src/routes/analytics.tsx
243
- var $$splitComponentImporter$4 = () => import("./analytics-CBNOYZwJ.js");
244
- var Route$4 = createFileRoute("/analytics")({
245
- component: lazyRouteComponent($$splitComponentImporter$4, "component"),
246
- loader: ({ context }) => {
247
- return Promise.all([context.queryClient.ensureQueryData(projectsQueryOptions()), context.queryClient.ensureQueryData(analyticsQueryOptions(null))]);
248
- }
249
- });
273
+ var $$splitComponentImporter$3 = () => import("./settings-OayxIYQQ.js");
274
+ var Route$3 = createFileRoute("/settings")({ component: lazyRouteComponent($$splitComponentImporter$3, "component") });
250
275
  //#endregion
251
276
  //#region src/lib/thread-id.ts
252
277
  var THREAD_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;
253
278
  var isCodexThreadId = (value) => THREAD_ID_PATTERN.test(value);
254
279
  //#endregion
255
280
  //#region src/routes/$threadId.tsx
256
- var $$splitComponentImporter$3 = () => import("./_threadId-B6SrBR9E.js");
257
- var Route$3 = createFileRoute("/$threadId")({
281
+ var $$splitComponentImporter$2 = () => import("./_threadId-B6SrBR9E.js");
282
+ var Route$2 = createFileRoute("/$threadId")({
258
283
  beforeLoad: ({ params }) => {
259
284
  if (!isCodexThreadId(params.threadId)) throw notFound();
260
285
  throw redirect({
@@ -262,21 +287,12 @@ var Route$3 = createFileRoute("/$threadId")({
262
287
  to: "/threads/$threadId"
263
288
  });
264
289
  },
265
- component: lazyRouteComponent($$splitComponentImporter$3, "component")
266
- });
267
- //#endregion
268
- //#region src/routes/projects.index.tsx
269
- var $$splitErrorComponentImporter$2 = () => import("./projects.index-BLXOx5eL.js");
270
- var $$splitComponentImporter$2 = () => import("./projects.index-DjSQK5dm.js");
271
- var Route$2 = createFileRoute("/projects/")({
272
- component: lazyRouteComponent($$splitComponentImporter$2, "component"),
273
- errorComponent: lazyRouteComponent($$splitErrorComponentImporter$2, "errorComponent"),
274
- loader: ({ context }) => context.queryClient.ensureQueryData(projectsQueryOptions())
290
+ component: lazyRouteComponent($$splitComponentImporter$2, "component")
275
291
  });
276
292
  //#endregion
277
293
  //#region src/routes/cursor.index.tsx
278
294
  var $$splitErrorComponentImporter$1 = () => import("./cursor.index-CcsX7DG0.js");
279
- var $$splitComponentImporter$1 = () => import("./cursor.index-CQVxtCm8.js");
295
+ var $$splitComponentImporter$1 = () => import("./cursor.index-DkWT-mxw.js");
280
296
  var Route$1 = createFileRoute("/cursor/")({
281
297
  component: lazyRouteComponent($$splitComponentImporter$1, "component"),
282
298
  errorComponent: lazyRouteComponent($$splitErrorComponentImporter$1, "errorComponent"),
@@ -285,7 +301,7 @@ var Route$1 = createFileRoute("/cursor/")({
285
301
  //#endregion
286
302
  //#region src/routes/antigravity.index.tsx
287
303
  var $$splitErrorComponentImporter = () => import("./antigravity.index-DudTB3Tq.js");
288
- var $$splitComponentImporter = () => import("./antigravity.index-DZVT-cac.js");
304
+ var $$splitComponentImporter = () => import("./antigravity.index-CPCYkqCi.js");
289
305
  var Route = createFileRoute("/antigravity/")({
290
306
  component: lazyRouteComponent($$splitComponentImporter, "component"),
291
307
  errorComponent: lazyRouteComponent($$splitErrorComponentImporter, "errorComponent"),
@@ -293,65 +309,65 @@ var Route = createFileRoute("/antigravity/")({
293
309
  });
294
310
  //#endregion
295
311
  //#region src/routeTree.gen.ts
296
- var SettingsRoute = Route$5.update({
312
+ var SettingsRoute = Route$3.update({
297
313
  id: "/settings",
298
314
  path: "/settings",
299
- getParentRoute: () => Route$6
315
+ getParentRoute: () => Route$4
300
316
  });
301
- var AnalyticsRoute = Route$4.update({
317
+ var AnalyticsRoute = Route$5.update({
302
318
  id: "/analytics",
303
319
  path: "/analytics",
304
- getParentRoute: () => Route$6
320
+ getParentRoute: () => Route$4
305
321
  });
306
- var ThreadIdRoute = Route$3.update({
322
+ var ThreadIdRoute = Route$2.update({
307
323
  id: "/$threadId",
308
324
  path: "/$threadId",
309
- getParentRoute: () => Route$6
325
+ getParentRoute: () => Route$4
310
326
  });
311
- var IndexRoute = Route$7.update({
327
+ var IndexRoute = Route$6.update({
312
328
  id: "/",
313
329
  path: "/",
314
- getParentRoute: () => Route$6
330
+ getParentRoute: () => Route$4
315
331
  });
316
- var ProjectsIndexRoute = Route$2.update({
332
+ var ProjectsIndexRoute = Route$7.update({
317
333
  id: "/projects/",
318
334
  path: "/projects/",
319
- getParentRoute: () => Route$6
335
+ getParentRoute: () => Route$4
320
336
  });
321
337
  var CursorIndexRoute = Route$1.update({
322
338
  id: "/cursor/",
323
339
  path: "/cursor/",
324
- getParentRoute: () => Route$6
340
+ getParentRoute: () => Route$4
325
341
  });
326
342
  var AntigravityIndexRoute = Route.update({
327
343
  id: "/antigravity/",
328
344
  path: "/antigravity/",
329
- getParentRoute: () => Route$6
345
+ getParentRoute: () => Route$4
330
346
  });
331
347
  var ThreadsThreadIdRoute = Route$8.update({
332
348
  id: "/threads/$threadId",
333
349
  path: "/threads/$threadId",
334
- getParentRoute: () => Route$6
350
+ getParentRoute: () => Route$4
335
351
  });
336
352
  var ProjectsProjectRoute = Route$9.update({
337
353
  id: "/projects/$project",
338
354
  path: "/projects/$project",
339
- getParentRoute: () => Route$6
355
+ getParentRoute: () => Route$4
340
356
  });
341
357
  var CursorWorkspaceKeyRoute = Route$10.update({
342
358
  id: "/cursor/$workspaceKey",
343
359
  path: "/cursor/$workspaceKey",
344
- getParentRoute: () => Route$6
360
+ getParentRoute: () => Route$4
345
361
  });
346
362
  var CursorThreadsComposerIdRoute = Route$11.update({
347
363
  id: "/cursor-threads/$composerId",
348
364
  path: "/cursor-threads/$composerId",
349
- getParentRoute: () => Route$6
365
+ getParentRoute: () => Route$4
350
366
  });
351
367
  var AntigravityWorkspaceKeyRoute = Route$12.update({
352
368
  id: "/antigravity/$workspaceKey",
353
369
  path: "/antigravity/$workspaceKey",
354
- getParentRoute: () => Route$6
370
+ getParentRoute: () => Route$4
355
371
  });
356
372
  var rootRouteChildren = {
357
373
  IndexRoute,
@@ -361,7 +377,7 @@ var rootRouteChildren = {
361
377
  AntigravityConversationsConversationIdRoute: Route$13.update({
362
378
  id: "/antigravity-conversations/$conversationId",
363
379
  path: "/antigravity-conversations/$conversationId",
364
- getParentRoute: () => Route$6
380
+ getParentRoute: () => Route$4
365
381
  }),
366
382
  AntigravityWorkspaceKeyRoute,
367
383
  CursorThreadsComposerIdRoute,
@@ -372,7 +388,7 @@ var rootRouteChildren = {
372
388
  CursorIndexRoute,
373
389
  ProjectsIndexRoute
374
390
  };
375
- var routeTree = Route$6._addFileChildren(rootRouteChildren)._addFileTypes();
391
+ var routeTree = Route$4._addFileChildren(rootRouteChildren)._addFileTypes();
376
392
  //#endregion
377
393
  //#region src/router.tsx
378
394
  function getRouter() {