specrails-desktop 2.32.0 → 2.34.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 (228) hide show
  1. package/client/dist/assets/{ActivityFeedPage-DvnFkjVG.js → ActivityFeedPage-DIDxNsDj.js} +1 -1
  2. package/client/dist/assets/{AgentBrowserCapture-CBjcliD7.js → AgentBrowserCapture-7pJ2G5VY.js} +1 -1
  3. package/client/dist/assets/AgentModeAnalyticsPane-BSSyTnTM.js +2 -0
  4. package/client/dist/assets/{AgentModeCodePane-CokuFVdV.js → AgentModeCodePane-DzW6gvDw.js} +2 -2
  5. package/client/dist/assets/{AgentModeJobsPane-rf_DlWNo.js → AgentModeJobsPane-9wJff15f.js} +1 -1
  6. package/client/dist/assets/AgentsPage-CIA67psb.js +87 -0
  7. package/client/dist/assets/AnalyticsPage-C0LwYELz.js +1 -0
  8. package/client/dist/assets/CodePage-RtKvHmAO.js +2 -0
  9. package/client/dist/assets/{DesktopAnalyticsPage-gBRVqiw6.js → DesktopAnalyticsPage-BU8Y_Ts1.js} +1 -1
  10. package/client/dist/assets/{DocsDialog-BzO5dg2B.js → DocsDialog-DIpoaGlQ.js} +1 -1
  11. package/client/dist/assets/{DocsPage-Db_uxr1j.js → DocsPage-ME47KZpK.js} +1 -1
  12. package/client/dist/assets/InteractiveJobComposer-BGjIe9R6.js +19 -0
  13. package/client/dist/assets/{JobDetailModal-DPHh2WOS.js → JobDetailModal-1UZkqH4I.js} +1 -1
  14. package/client/dist/assets/JobDetailPage-CN65sAf1.js +1 -0
  15. package/client/dist/assets/JobsPage-f-4dqys7.js +1 -0
  16. package/client/dist/assets/LoopBuilderPage-WeiofeL6.js +7 -0
  17. package/client/dist/assets/LoopPreviewModal-DDTnTyH0.js +1 -0
  18. package/client/dist/assets/LoopsPage-BVNchIex.js +1 -0
  19. package/client/dist/assets/MinimizedChatsContext-CHsu3NCX.js +1 -0
  20. package/client/dist/assets/PluginsPage-CdFzGEfQ.js +2 -0
  21. package/client/dist/assets/ProjectSettingsDialog-BkCXBQWk.js +1 -0
  22. package/client/dist/assets/TemplatePreviewModal-RDi0khFG.js +1 -0
  23. package/client/dist/assets/TicketDetailModal-MhJzrqbi.js +14 -0
  24. package/client/dist/assets/{Trans-B2i5HVcM.js → Trans-CTqw6rr9.js} +1 -1
  25. package/client/dist/assets/{addspec-DhmnXER8.js → addspec-A1lDQa4M.js} +1 -1
  26. package/client/dist/assets/{addspec-BRlk8jON.js → addspec-BHZd0N5F.js} +1 -1
  27. package/client/dist/assets/{addspec-CHW9xf_X.js → addspec-BPpZ_olp.js} +1 -1
  28. package/client/dist/assets/{addspec-Di41DpYV.js → addspec-B_TPJt-R.js} +1 -1
  29. package/client/dist/assets/{addspec-4WmLJmBG.js → addspec-CLYLvaVP.js} +1 -1
  30. package/client/dist/assets/{addspec-C7XRejU4.js → addspec-CQBjzt24.js} +1 -1
  31. package/client/dist/assets/{addspec-x3mizDxc.js → addspec-D2YIQ0GU.js} +1 -1
  32. package/client/dist/assets/{addspec-DTmRrWrF.js → addspec-iFdQ6D99.js} +1 -1
  33. package/client/dist/assets/agent-Bd-q3Wqp.js +1 -0
  34. package/client/dist/assets/agent-BlvdW4Hv.js +1 -0
  35. package/client/dist/assets/agent-C-KQhxeM.js +1 -0
  36. package/client/dist/assets/agent-Ca15w5eu.js +1 -0
  37. package/client/dist/assets/agent-D6fKaoMd.js +1 -0
  38. package/client/dist/assets/agent-HFMYMTbB.js +1 -0
  39. package/client/dist/assets/agent-QIEbkBjg.js +1 -0
  40. package/client/dist/assets/agent-mTCsAbCl.js +1 -0
  41. package/client/dist/assets/agentstudio-BNUth0uj.js +1 -0
  42. package/client/dist/assets/agentstudio-BNdB5hkr.js +1 -0
  43. package/client/dist/assets/agentstudio-C7-bt8FO.js +1 -0
  44. package/client/dist/assets/agentstudio-C8uNchpV.js +1 -0
  45. package/client/dist/assets/agentstudio-CKabyMlg.js +1 -0
  46. package/client/dist/assets/agentstudio-CN2pokQu.js +1 -0
  47. package/client/dist/assets/agentstudio-DR7doNBV.js +1 -0
  48. package/client/dist/assets/agentstudio-y2dVDXeM.js +1 -0
  49. package/client/dist/assets/{analytics-C9RaQcE3.js → analytics-47pYygtV.js} +1 -1
  50. package/client/dist/assets/{analytics-B8Qtptbl.js → analytics-B0vt1g5U.js} +1 -1
  51. package/client/dist/assets/analytics-BMzCvrCU.js +1 -0
  52. package/client/dist/assets/{analytics-BPptRY4f.js → analytics-BlFN3Zwx.js} +1 -1
  53. package/client/dist/assets/{analytics-BxDGOIwf.js → analytics-CZYzL-nR.js} +1 -1
  54. package/client/dist/assets/{analytics-D_OZdQ9O.js → analytics-DAsb9MJ8.js} +1 -1
  55. package/client/dist/assets/{analytics-CJIwqrEl.js → analytics-FXQlQ2Yt.js} +1 -1
  56. package/client/dist/assets/{analytics-We6lUMI8.js → analytics-RnFCNkah.js} +1 -1
  57. package/client/dist/assets/{builder-CWYPw7Cw.js → builder-0IWtosUm.js} +1 -1
  58. package/client/dist/assets/{builder-CX1437hF.js → builder-Bf2N6XWn.js} +1 -1
  59. package/client/dist/assets/{builder-BiUG9Z5K.js → builder-BnqaaBkT.js} +1 -1
  60. package/client/dist/assets/{builder-CGRz_-zP.js → builder-BxxfGgAO.js} +1 -1
  61. package/client/dist/assets/{builder-DwDexYRE.js → builder-C5IIgWsq.js} +1 -1
  62. package/client/dist/assets/builder-CHuahItu.js +1 -0
  63. package/client/dist/assets/{builder-Cowk9jtL.js → builder-CjWosXL_.js} +1 -1
  64. package/client/dist/assets/{builder-3bygQtZi.js → builder-CpCIOoKj.js} +1 -1
  65. package/client/dist/assets/dashboard-BHRqsGCV.js +1 -0
  66. package/client/dist/assets/dashboard-Bfr90vOl.js +1 -0
  67. package/client/dist/assets/dashboard-CTsM8x3m.js +1 -0
  68. package/client/dist/assets/dashboard-CqC6wX0h.js +1 -0
  69. package/client/dist/assets/dashboard-CuZtAszc.js +1 -0
  70. package/client/dist/assets/dashboard-DAcqIc-n.js +1 -0
  71. package/client/dist/assets/dashboard-DekiV-86.js +1 -0
  72. package/client/dist/assets/dashboard-DoDczc5S.js +1 -0
  73. package/client/dist/assets/{dist-js-CkTZKBF9.js → dist-js-BmsFWRly.js} +1 -1
  74. package/client/dist/assets/{dist-js-ClShHcGa.js → dist-js-J5W_N5ng.js} +1 -1
  75. package/client/dist/assets/{formatDistanceToNow-BjGwPf6I.js → formatDistanceToNow-BOuXgebD.js} +1 -1
  76. package/client/dist/assets/{getTimezoneOffsetInMilliseconds-CSCbUI4W.js → getTimezoneOffsetInMilliseconds-EjGOpn4b.js} +1 -1
  77. package/client/dist/assets/{i18n-Ch-Db_x2.js → i18n-nJQvD5zJ.js} +2 -2
  78. package/client/dist/assets/index-C_sdsSZt.js +63 -0
  79. package/client/dist/assets/index-DCN5QbDm.css +2 -0
  80. package/client/dist/assets/{jira-BySfUuQZ.js → jira-BNZu8f9O.js} +1 -1
  81. package/client/dist/assets/{jira-gAvOyije.js → jira-BOoaUXbb.js} +1 -1
  82. package/client/dist/assets/{jira-pRaL7JQo.js → jira-BYVN4L2u.js} +1 -1
  83. package/client/dist/assets/jira-CKJg3HZd.js +1 -0
  84. package/client/dist/assets/{jira-Byw2C0F8.js → jira-DDDsZ4ub.js} +1 -1
  85. package/client/dist/assets/{jira-D38Gj7AT.js → jira-DXwYjVE4.js} +1 -1
  86. package/client/dist/assets/{jira-D11gPhxz.js → jira-Dn6U2nRW.js} +1 -1
  87. package/client/dist/assets/{jira-api-BgFIr8eD.js → jira-api-Bhixwn-d.js} +1 -1
  88. package/client/dist/assets/{jira-CNeYi06w.js → jira-j7hVolR5.js} +1 -1
  89. package/client/dist/assets/nav-ApJVg3xu.js +1 -0
  90. package/client/dist/assets/nav-BKNky1Bg.js +1 -0
  91. package/client/dist/assets/nav-C6vWWKYx.js +1 -0
  92. package/client/dist/assets/nav-CXJ6Aw89.js +1 -0
  93. package/client/dist/assets/nav-CsmFBIDf.js +1 -0
  94. package/client/dist/assets/nav-DjkmQJjd.js +1 -0
  95. package/client/dist/assets/nav-iwjCg5FR.js +1 -0
  96. package/client/dist/assets/nav-pYuXq7sf.js +1 -0
  97. package/client/dist/assets/{provider-capabilities-BvoExILy.js → provider-capabilities-Doej9lfa.js} +1 -1
  98. package/client/dist/assets/setup-3jWaoVUO.js +1 -0
  99. package/client/dist/assets/setup-BjgRneb2.js +1 -0
  100. package/client/dist/assets/setup-BzFIjv-f.js +1 -0
  101. package/client/dist/assets/setup-C4VfQsxE.js +1 -0
  102. package/client/dist/assets/setup-DfUkpDbN.js +1 -0
  103. package/client/dist/assets/setup-ECe90Pmu.js +1 -0
  104. package/client/dist/assets/setup-dlqC4Jmm.js +1 -0
  105. package/client/dist/assets/setup-jwfLMiM2.js +1 -0
  106. package/client/dist/assets/{spending-Dq43JYmD.js → spending-BpYPsevQ.js} +1 -1
  107. package/client/dist/assets/tickets-B4rjuSYi.js +1 -0
  108. package/client/dist/assets/tickets-Bc71ce1C.js +1 -0
  109. package/client/dist/assets/tickets-CLg7VTJ8.js +1 -0
  110. package/client/dist/assets/tickets-CP9U1GJt.js +1 -0
  111. package/client/dist/assets/tickets-CZNBiHbq.js +1 -0
  112. package/client/dist/assets/tickets-DlX2mEkD.js +1 -0
  113. package/client/dist/assets/tickets-W6pBmbrX.js +1 -0
  114. package/client/dist/assets/tickets-_yKvCt4Y.js +1 -0
  115. package/client/dist/assets/{useBrowserCaptureSession-TTO8vHtd.js → useBrowserCaptureSession-BBXBN0Na.js} +1 -1
  116. package/client/dist/assets/useDesktop-B6Du2N83.js +1 -0
  117. package/client/dist/assets/{useSharedWebSocket-DaPh7QBL.js → useSharedWebSocket-DK96ctb7.js} +1 -1
  118. package/client/dist/index.html +24 -24
  119. package/docs/guide/de/getting-started/3-adding-your-first-project.md +13 -32
  120. package/docs/guide/de/integrations/1-ai-providers.md +27 -16
  121. package/docs/guide/en/getting-started/3-adding-your-first-project.md +8 -27
  122. package/docs/guide/en/integrations/1-ai-providers.md +21 -18
  123. package/docs/guide/es/getting-started/3-adding-your-first-project.md +12 -31
  124. package/docs/guide/es/integrations/1-ai-providers.md +24 -16
  125. package/docs/guide/fr/getting-started/3-adding-your-first-project.md +15 -34
  126. package/docs/guide/fr/integrations/1-ai-providers.md +25 -16
  127. package/docs/guide/it/getting-started/3-adding-your-first-project.md +16 -35
  128. package/docs/guide/it/integrations/1-ai-providers.md +25 -16
  129. package/docs/guide/ja/getting-started/3-adding-your-first-project.md +16 -35
  130. package/docs/guide/ja/integrations/1-ai-providers.md +7 -12
  131. package/docs/guide/pt/getting-started/3-adding-your-first-project.md +15 -34
  132. package/docs/guide/pt/integrations/1-ai-providers.md +24 -16
  133. package/docs/guide/zh/getting-started/3-adding-your-first-project.md +18 -37
  134. package/docs/guide/zh/integrations/1-ai-providers.md +7 -12
  135. package/docs/internals/project-builder.md +11 -6
  136. package/package.json +1 -1
  137. package/server/dist/ai-invocations.js +35 -0
  138. package/server/dist/blueprint-commit.js +1 -1
  139. package/server/dist/desktop-db.js +22 -1
  140. package/server/dist/desktop-router.js +132 -43
  141. package/server/dist/framework-reseed.js +144 -0
  142. package/server/dist/index.js +41 -2
  143. package/server/dist/jira/jira-sync-manager.js +49 -2
  144. package/server/dist/jira-router.js +21 -0
  145. package/server/dist/job-phase-breakdown.js +132 -0
  146. package/server/dist/legacy-migration.js +395 -0
  147. package/server/dist/loop-executors.js +5 -1
  148. package/server/dist/offline-assemble.js +32 -4
  149. package/server/dist/pr-body.js +13 -0
  150. package/server/dist/project-router-jobs.js +16 -0
  151. package/server/dist/project-router-spending.js +11 -1
  152. package/server/dist/provider-detection.js +222 -0
  153. package/server/dist/provider-selection.js +71 -19
  154. package/server/dist/queue-manager.js +4 -0
  155. package/server/dist/rail-pr-decision.js +10 -0
  156. package/server/dist/rails-router.js +11 -0
  157. package/server/dist/rails-store.js +5 -1
  158. package/server/dist/repo-map.js +293 -0
  159. package/server/dist/setup-manager.js +57 -0
  160. package/server/dist/spending.js +45 -0
  161. package/client/dist/assets/AgentsPage-B648IzGI.js +0 -87
  162. package/client/dist/assets/AnalyticsPage-0rBoULPX.js +0 -1
  163. package/client/dist/assets/CodePage-ju302Vl7.js +0 -2
  164. package/client/dist/assets/InteractiveJobComposer-_jmsE_Az.js +0 -19
  165. package/client/dist/assets/JobDetailPage-7nwHyHGV.js +0 -1
  166. package/client/dist/assets/JobsPage-C_6YrcmE.js +0 -1
  167. package/client/dist/assets/LoopBuilderPage-DJ1UPDwL.js +0 -7
  168. package/client/dist/assets/LoopPreviewModal-12cUnljK.js +0 -1
  169. package/client/dist/assets/LoopsPage-CHYK0Xjr.js +0 -1
  170. package/client/dist/assets/MinimizedChatsContext-Gt6KQySM.js +0 -1
  171. package/client/dist/assets/PluginsPage-E59oQmwc.js +0 -2
  172. package/client/dist/assets/ProjectSettingsDialog-DQTLQ7ie.js +0 -1
  173. package/client/dist/assets/TemplatePreviewModal-nXUcDgfk.js +0 -1
  174. package/client/dist/assets/TicketDetailModal-C-tHW-2s.js +0 -14
  175. package/client/dist/assets/agent-BKsuIgIT.js +0 -1
  176. package/client/dist/assets/agent-Bs9NilfI.js +0 -1
  177. package/client/dist/assets/agent-C23h684q.js +0 -1
  178. package/client/dist/assets/agent-CqEjy3Z2.js +0 -1
  179. package/client/dist/assets/agent-D5DZTks1.js +0 -1
  180. package/client/dist/assets/agent-DE8hUYPl.js +0 -1
  181. package/client/dist/assets/agent-DsTuJGSc.js +0 -1
  182. package/client/dist/assets/agent-DwZM05-x.js +0 -1
  183. package/client/dist/assets/agentstudio-8TQqBenW.js +0 -1
  184. package/client/dist/assets/agentstudio-B8Z_mmEX.js +0 -1
  185. package/client/dist/assets/agentstudio-BZR9YmLs.js +0 -1
  186. package/client/dist/assets/agentstudio-Bge9pAWb.js +0 -1
  187. package/client/dist/assets/agentstudio-Bz169Vzt.js +0 -1
  188. package/client/dist/assets/agentstudio-D6L2jpNi.js +0 -1
  189. package/client/dist/assets/agentstudio-K2-Z7CL0.js +0 -1
  190. package/client/dist/assets/agentstudio-Zmgzthv8.js +0 -1
  191. package/client/dist/assets/analytics-BHqUazhP.js +0 -1
  192. package/client/dist/assets/builder-skfnZ1uC.js +0 -1
  193. package/client/dist/assets/dashboard-BVq6kRJe.js +0 -1
  194. package/client/dist/assets/dashboard-BaKPPmLH.js +0 -1
  195. package/client/dist/assets/dashboard-Bm8e4zYG.js +0 -1
  196. package/client/dist/assets/dashboard-Bt6IesnM.js +0 -1
  197. package/client/dist/assets/dashboard-C_NQZle_.js +0 -1
  198. package/client/dist/assets/dashboard-CyZKoGoI.js +0 -1
  199. package/client/dist/assets/dashboard-HIUdUBQ0.js +0 -1
  200. package/client/dist/assets/dashboard-pm4Mr229.js +0 -1
  201. package/client/dist/assets/index-Bz0TeGRs.css +0 -2
  202. package/client/dist/assets/index-kCUcnT8G.js +0 -77
  203. package/client/dist/assets/jira-CmKWERE0.js +0 -1
  204. package/client/dist/assets/nav-BHDiSIVu.js +0 -1
  205. package/client/dist/assets/nav-CMiYAq4i.js +0 -1
  206. package/client/dist/assets/nav-CqS7NrDW.js +0 -1
  207. package/client/dist/assets/nav-D-0M7xfv.js +0 -1
  208. package/client/dist/assets/nav-D65O6u9I.js +0 -1
  209. package/client/dist/assets/nav-D_LKYvBr.js +0 -1
  210. package/client/dist/assets/nav-FDTJmU79.js +0 -1
  211. package/client/dist/assets/nav-VaB-C4k5.js +0 -1
  212. package/client/dist/assets/setup-BBiHEO7h.js +0 -1
  213. package/client/dist/assets/setup-BlTWhNIQ.js +0 -1
  214. package/client/dist/assets/setup-Bp2L_oiP.js +0 -1
  215. package/client/dist/assets/setup-CInYXp1-.js +0 -1
  216. package/client/dist/assets/setup-CYH3bP6K.js +0 -1
  217. package/client/dist/assets/setup-DwcQ921P.js +0 -1
  218. package/client/dist/assets/setup-PBLjuDSs.js +0 -1
  219. package/client/dist/assets/setup-bx6FtoBp.js +0 -1
  220. package/client/dist/assets/tickets-BL9r1G0e.js +0 -1
  221. package/client/dist/assets/tickets-B_NyHJ8f.js +0 -1
  222. package/client/dist/assets/tickets-BarF1wuG.js +0 -1
  223. package/client/dist/assets/tickets-CclVhpQA.js +0 -1
  224. package/client/dist/assets/tickets-CqqOHbli.js +0 -1
  225. package/client/dist/assets/tickets-DCkFSiqt.js +0 -1
  226. package/client/dist/assets/tickets-Djn3ccfT.js +0 -1
  227. package/client/dist/assets/tickets-MiHBPsy_.js +0 -1
  228. package/client/dist/assets/useDesktop-DUvS4fuP.js +0 -1
@@ -0,0 +1 @@
1
+ var e={title:`Añadir proyecto`,description:`Registra un directorio de proyecto para gestionarlo desde Specrails.`,noProviderDetected:`No se ha detectado ningún CLI de IA. Instala primero Claude Code, Codex CLI, Gemini CLI o Kimi Code.`,pathLabel:`Ruta del proyecto`,pathPlaceholder:`/Users/yo/mi-proyecto`,pathHint:`Ruta absoluta a la raíz del proyecto`,browseForFolder:`Buscar carpeta`,selectProjectFolder:`Seleccionar carpeta del proyecto`,nameLabel:`Nombre para mostrar`,optional:`(opcional)`,namePlaceholder:`Mi proyecto`,nameHint:`Por defecto, el nombre del directorio`,adding:`Añadiendo...`,submit:`Añadir proyecto`,toolsRequired_one:`Se necesita {{tools}} para añadir un proyecto`,toolsRequired_other:`Se necesitan {{tools}} para añadir un proyecto`,errors:{pathRequired:`La ruta del proyecto es obligatoria`,addFailed:`No se pudo añadir el proyecto`},toasts:{registered:`Proyecto "{{name}}" registrado`},chooser:{description:`Trae un repositorio existente o construye un proyecto nuevo desde una idea.`,existingTitle:`Proyecto existente`,existingDescription:`Registra un repositorio que ya existe en disco.`,newTitle:`Proyecto nuevo`,newDescription:`Describe una idea y recibe un repo inicializado con un backlog del Hito 1.`}},t={corruptedBundle:`bundle dañado — reinstala la app`,notInstalled:`no instalado`,failedToExecute:`encontrado pero no se pudo ejecutar`,failedToExecuteAt:`encontrado en {{path}} pero no se pudo ejecutar`,failedToExecuteWithError:`encontrado pero no se pudo ejecutar ({{error}})`,failedToExecuteAtWithError:`encontrado en {{path}} pero no se pudo ejecutar ({{error}})`,needsMinimum:`{{version}} encontrada — se necesita {{minVersion}}+`,unknownVersion:`desconocida`,installedLabel:`instalado`,verifyError:`No se pudieron verificar las herramientas de desarrollo en local — la instalación lo validará.`,allDetected:`Todas las herramientas necesarias detectadas`,bundleCorruptedTitle:`Bundle de la app dañado`,toolsRequired_one:`{{count}} herramienta de desarrollo necesaria`,toolsRequired_other:`{{count}} herramientas de desarrollo necesarias`,reinstallHint:`Reinstala la app Specrails para restaurar las herramientas incluidas.`,installMissingHint:`Instala las herramientas que faltan para continuar.`,moreInfo:`Más información`,bundledBadge:`incluida`,optional:`opcional`,ghNoAuth:"Sin sesión — ejecuta `gh auth login`"},n={title:`Instalar herramientas de desarrollo`,description:`SpecRails necesita Node.js, npm, npx y Git en el PATH. Elige el snippet de tu SO, ejecútalo y pulsa "Ya lo he instalado, volver a comprobar".`,darwin:{intro:`Homebrew te da ambas herramientas en una línea. Si no tienes brew, usa las descargas oficiales.`,installNodeGit:`Instalar Node.js y Git con Homebrew`},win32:{intro:`Winget viene incluido en Windows 11 y en las versiones recientes de Windows 10. Abre PowerShell o Terminal y ejecuta:`,installNode:`Instalar Node.js LTS`,installGit:`Instalar Git`,note:`Tras la instalación, reinicia Specrails para que Windows actualice el PATH.`},linux:{intro:`Usa el gestor de paquetes de tu distro:`,debian:`Debian / Ubuntu`,fedora:`Fedora / RHEL`},links:{nodeOfficial:`Node.js (oficial)`,gitOfficial:`Git (oficial)`,gitWindows:`Git para Windows (oficial)`},showOtherPlatforms:`Mostrar otras plataformas`,hideOtherPlatforms:`Ocultar otras plataformas`,recheck:`Ya lo he instalado, volver a comprobar`,diagnostics:{copy:`Copiar diagnóstico`,copied:`Diagnóstico copiado`,failed:`Error al copiar`},corrupted:{title:`Bundle de la app dañado`,description:`No se pudieron verificar una o más herramientas incluidas (Node.js, Git).`,body:`Esta herramienta viene incluida con la app Specrails y no puede instalarse por separado. Si ves este mensaje, el bundle de la app puede estar dañado. Reinstala Specrails.`}},r={title:`Bienvenido a <spec>spec</spec><rails>rails</rails>`,description:`Specrails gestiona varios proyectos desde una única interfaz. Añade tu primer proyecto para empezar.`,addFirstProject:`Añade tu primer proyecto`,jiraHint:`Conecta cada proyecto a su propio tablero de Jira — las specs se sincronizan en ambos sentidos.`,mcpHint:`Conecta herramientas de IA externas a Specrails mediante un servidor MCP local seguro — actívalo en Ajustes.`,agentChatHint:`Opera Specrails conversando — un agente integrado gestiona specs, rails y analíticas por ti a través del MCP local. Ábrelo desde la burbuja o con ⌘⇧A.`},i=JSON.parse(`{"productTour":"Tour del producto","stepCount":"Paso {{current}} de {{total}}","goToStep":"Ir al paso {{step}}: {{label}}","stepLabel":"Paso {{step}}","dontShowAgain":"No volver a mostrar","skipTour":"Saltar el tour","getStarted":"Empezar","flow":{"addSpec":"Añade una spec","dropInRail":"Suéltala en un rail","hitPlay":"Dale a Play","ship":"Ship","architect":"Arquitecto","developer":"Desarrollador","reviewer":"Revisor"},"language":{"nav":"Idioma","title":"Elige tu idioma","subtitle":"Specrails habla tu idioma","intro":"Selecciona el idioma en el que quieres la interfaz. Se aplica al instante — este tour incluido.","note":"Puedes cambiarlo cuando quieras en Ajustes → Idioma."},"theme":{"nav":"Tema","title":"Elige tu estilo","subtitle":"Temas integrados, aplicados al instante","intro":"Decide qué aspecto tendrá Specrails — el tema se aplica en cuanto haces clic.","note":"Puedes cambiarlo cuando quieras en Ajustes → Apariencia."},"welcome":{"nav":"Bienvenida","title":"Bienvenido a Specrails","subtitle":"Tu centro de mando local para publicar software con agentes de IA","intro":"Specrails convierte una idea en código publicado — y te permite <b>ver, dirigir y confiar en</b> cada paso. Redacta una spec hablando con una IA, suéltala en un rail de ejecución y dale a Play. El pipeline se encarga de la arquitectura, la implementación, la revisión y la pull request, retransmitiendo su trabajo en directo en todo momento.","coreLoopLabel":"El bucle principal","flowCaption":"Cada spec pasa automáticamente por <b>Arquitecto → Desarrollador → Revisor → Ship</b>.","localNote":"<b>100 % local · un solo usuario · sin cuentas.</b> Todo se ejecuta en tu máquina. Tu código nunca sale del portátil a menos que <i>tú</i> lances un agente sobre él.","tourNote":"Este tour rápido repasa todo lo que puede hacer la aplicación — alrededor de un minuto."},"authorSpecs":{"nav":"Crea specs","title":"Convierte ideas en specs","subtitle":"Seis formas de capturar exactamente lo que quieres construir","intro":"Una <b>spec</b> es una descripción del trabajo que quieres que se haga. Redáctala como mejor encaje en cada momento — desde una línea rápida hasta una conversación completa con la IA.","exploreLabel":"Explore — conversa","exploreBody":"Describe lo que quieres en un chat; un borrador en vivo se reconstruye en cada turno. Un slider de presets ajusta cuánto contexto del proyecto ve la IA — desde solo tu mensaje hasta el codebase completo más tus servidores MCP.","quickLabel":"Quick — de una sola vez","quickBody":"¿Ya sabes lo que quieres? Genera una spec completa en un solo turno. Opcionalmente, enriquécela con una Contract Layer: nombres exactos, formas de datos, invariantes y una lista de archivos a tocar para que los agentes no reinventen nada.","websiteLabel":"Desde una web","websiteBody":"Abre un navegador embebido. Selecciona un elemento al pasar el ratón o arrastra un rectángulo, y la captura, el DOM y el CSS aplicado se convierten en adjuntos. La versión de escritorio incluye su propio Chromium, así que funciona sin conexión.","smashLabel":"SMASH para una épica grande","smashBody":"Divide una spec grande en una familia de sub-specs más pequeñas con un clic — cada hija lleva un breve resumen en su tarjeta.","draftsLabel":"Borradores y seguir editando","draftsBody":"Aparca una exploración en curso como ticket en borrador y retómala más tarde; reabre cualquier spec en Explore para seguir refinándola.","compareLabel":"Compara lado a lado","compareBody":"Arrastra una spec al borde de la pantalla y se desliza un selector con tus otras specs — revisa dos a la vez, al estilo tablet."},"rails":{"nav":"Ejecuta en rails","title":"Ejecuta el pipeline sobre rails","subtitle":"Organiza las specs en carriles y lanza los agentes","intro":"El lado derecho del Dashboard son tus <b>Rails</b> — carriles de ejecución. Arrastra una tarjeta de spec a un rail y pulsa <play>▶ Play</play> para lanzar un job de implementación.","jobLabel":"Qué ejecuta cada job","flowCaption":"Cada fase retransmite sus logs en directo mientras trabaja.","modeLabel":"Elige un Loop para ejecutar","modeBody":"Cada rail ejecuta un <b>Loop</b>. Elige uno de serie — <b>Implement</b> (el pipeline estructurado completo), <b>Batch</b> (varias specs a la vez) o <b>Freestyle</b> (un proveedor compatible trabaja de forma autónoma, sin pipeline fijo) — o uno que hayas creado tú.","profilesLabel":"Perfiles de agentes","profilesBody":"Un catálogo declarativo por proyecto que decide qué agentes se ejecutan y qué modelo usa cada uno — se elige por rail y se congela por job para que el trabajo concurrente quede aislado.","jobDetailLabel":"Detalle del job en directo","jobDetailBody":"Cada job muestra una cabecera con la identidad del ticket, un contador de duración en directo y los turnos y tokens acumulados, con el coste definitivo resuelto al terminar.","isolationLabel":"Muchos proyectos, aislados","isolationBody":"Cada proyecto tiene su propia base de datos y su propia cola de jobs. Ejecuta proyectos distintos a la vez y cambia entre ellos desde la barra lateral izquierda — tu posición se recuerda por proyecto.","loopsLabel":"Crea tus propios loops","loopsBody":"<b>Loops</b> es un editor visual: encadena pasos de IA, comandos de shell y un <b>Loop Decider</b> que se repite hasta cumplir un objetivo — p. ej. verificar → corregir → verificar hasta que todo esté en verde. Publica un loop y elígelo en cualquier rail."},"agent":{"nav":"Chat con el agente","title":"Opera la app conversando","subtitle":"Un copiloto que maneja Specrails por ti","intro":"El <b>chat con el agente</b> integrado te permite manejar Specrails preguntando — crea specs, lanza rails, consulta analíticas — en lugar de ir haciendo clic. Funciona a través de las propias herramientas <b>MCP</b> de Specrails y, como todo es en vivo, ves cómo cambia el tablero mientras trabaja.","openLabel":"Siempre a un clic","openBody":"Ábrelo desde la burbuja flotante de abajo, o pulsa ⌘⇧A (Ctrl+Shift+A) desde cualquier sitio. El panel se mueve, se redimensiona, se maximiza y recuerda dónde lo dejaste.","operateLabel":"Maneja toda la app","operateBody":"Elige un proyecto (o Inicio para todo) y un proveedor, y simplemente pide: “lanza los tres tickets de mayor prioridad”, “¿cuánto he gastado esta semana?”.","levelsLabel":"Tú llevas las riendas","levelsBody":"Un nivel en vivo — <b>Observa → Edita → Opera → Autónomo</b>, que se alterna con Shift+Tab — decide hasta dónde puede llegar. Nunca actúa por encima del nivel que fijes.","watchLabel":"Míralo suceder","watchBody":"El panel no es modal, así que los rails y las specs aparecen en el dashboard en tiempo real mientras el agente trabaja. Un chip de estado muestra qué está haciendo ahora mismo.","mcpLabel":"Funciona sobre el MCP local","mcpBody":"El agente maneja la app a través del servidor MCP integrado de Specrails. Si está apagado, el panel ofrece activarlo con un clic — no se instala nada."},"providers":{"nav":"Tu agente","title":"Trae tu propio agente","subtitle":"Claude Code, Codex, Gemini y Kimi como motores de primera clase","intro":"La app trata <b>Claude Code</b>, <b>Codex CLI</b>, <b>Gemini CLI</b> y <b>Kimi Code</b> como motores intercambiables tras un mismo contrato. Un proyecto puede instalar uno o varios — la elección se hace al instalar.","table":{"capability":"Capacidad","streamingResume":"Streaming y reanudación de sesión","native":"Nativo","costReporting":"Informe de costes","providerBilled":"Facturado por el proveedor","estimated":"Estimado (~)","unavailable":"No disponible","telemetry":"Telemetría (OTEL)","synthesized":"Sintetizada","agentProfiles":"Perfiles de agentes"},"calloutLabel":"Cuando hay varios instalados","calloutBody":"Elige el motor <b>por spec, por rail o por lanzamiento de terminal</b>. La aplicación recuerda tu última elección por proyecto. Los costes estimados se marcan con <mono>~</mono>; Kimi no informa de tokens ni coste."},"cost":{"nav":"Controla el coste","title":"Controla cada céntimo","subtitle":"Cada invocación facturable, registrada y visualizada","intro":"Cada invocación de IA — en rails, Quick, Explore, ediciones con IA, SMASH y resúmenes de archivos — registra su ciclo de vida y proveedor. El uso y el coste quedan no disponibles cuando el proveedor, como Kimi, no los informa.","analyticsLabel":"Página de analítica","analyticsBody":"Un hero de burn-rate, línea temporal diaria, top de tickets, desglose por modelo y un scatter de coste frente a turnos. Filtra por periodo (7d / 30d / 90d / Todo) y por superficie.","perTicketLabel":"Gasto por ticket","perTicketBody":"El detalle de cada spec muestra cuánto costó y cuántos turnos llevó, con enlace directo a la analítica filtrada por ese ticket.","honestLabel":"Números honestos","honestBody":"El coste de Claude es el facturado por el proveedor; Codex y Gemini pueden estimarse y se marcan con <mono>~</mono>. Kimi no informa de tokens ni coste USD nativo, así que esos campos aparecen como no disponibles, no como cero.","budgetsLabel":"Presupuestos y alertas","budgetsBody":"Define un presupuesto diario y una alerta de coste por job; la aplicación pausa la cola automáticamente cuando cruzas la línea. Exporta lo que quieras a CSV o JSON."},"workspace":{"nav":"Espacio de trabajo","title":"Hazlo tu espacio de trabajo","subtitle":"Todo lo que necesitas sin salir de la ventana","terminalLabel":"Panel de terminal","terminalBody":"Un terminal real al estilo VS Code en la parte inferior (<mod>{{mod}}</mod> <j>J</j>) — renderizado WebGL, búsqueda, imágenes inline, arrastrar y soltar rutas e integración con el shell. Hasta 10 sesiones por proyecto.","codeLabel":"Explorador de código","codeBody":"Un árbol de archivos de solo lectura y un visor Monaco con resúmenes de IA en lenguaje llano y chips de procedencia «tocado por IA», para que cualquiera pueda seguir qué cambió y por qué.","integrationsLabel":"Integraciones","integrationsBody":"Un marketplace por proyecto de integraciones MCP — la navegación semántica de código de Serena viene incluida. Las instalaciones son aditivas: añadir una nunca altera otra.","themesLabel":"Temas","themesBody":"Seis temas integrados — specrails (por defecto), dracula, aurora-light, obsidian-dark, code-rain y galaxy — aplicados antes de que la UI pinte, así no hay parpadeo. Cámbialos en Ajustes → Apariencia.","chatsLabel":"Chats minimizables","chatsBody":"Aparca una sesión de Explore o AI Edit en un chip del dock y retómala más tarde — nunca se pierde entre recargas o cambios de proyecto.","desktopLabel":"Escritorio o navegador","desktopBody":"Ejecuta Specrails en tu navegador o descarga la app de escritorio firmada (macOS y Windows), que incluye su propio servidor y runtimes."},"companion":{"nav":"Compañera móvil","title":"Llévate Specrails contigo","subtitle":"Specrails Companion — tus pipelines, en tu teléfono","intro":"<b>Specrails Companion</b> es una app web en specrails.dev/companion-app — ábrela en tu teléfono (o añádela a tu pantalla de inicio) para navegar por el tablero de specs, lanzar y detener rails, seguir los logs de los jobs en directo y echar un vistazo a la analítica. Sin instalación, sin tienda de apps.","localLabel":"100 % local, como todo lo demás","localBody":"Tu teléfono se conecta directamente a este ordenador — peer-to-peer y cifrado (WebRTC). Sin servidores intermedios en la nube, sin cuentas, y tu código nunca sale de tus dispositivos.","downloadLabel":"Ábrela en tu teléfono","downloadHint":"Escanea el código con la cámara de tu teléfono o abre specrails.dev/companion-app en su navegador.","open":"Abrir Specrails Companion","pairLabel":"Emparejar lleva diez segundos","pairBody":"En tu teléfono abre specrails.dev/companion-app y luego, aquí, ve a Ajustes → Compañera móvil → Emparejar compañera web y sigue los pasos en pantalla."},"moveFast":{"nav":"Ve rápido","title":"Muévete a la velocidad del pensamiento","subtitle":"Teclado primero, en todas partes","paletteLabel":"Paleta de comandos","paletteShortcut":"<f>Pulsa</f> <mod>{{mod}}</mod> <m>+</m> <k>K</k> <m>en cualquier parte</m>","paletteBody":"Cambia de proyecto, ejecuta comandos de spec, salta a cualquier página y encuentra jobs recientes — todo con búsqueda difusa.","terminalLabel":"Panel de terminal","terminalBody":"Alterna con <mod>{{mod}}</mod> <j>J</j>.","shortcutsLabel":"Todos los atajos","shortcutsBody":"Pulsa <q>?</q> para ver la chuleta completa.","chatLabel":"Barra lateral de chat","chatBody":"Alterna la barra lateral derecha con <mod>{{mod}}</mod> <bkey>B</bkey>.","projectsLabel":"Barra lateral de proyectos","projectsBody":"Alterna la barra lateral Arc izquierda con <alt>{{alt}}</alt> <mod>{{mod}}</mod> <bkey>B</bkey>.","outro":"<b>Fin del tour.</b> Añade un proyecto desde la barra lateral izquierda y publica tu primera spec. Puedes reabrir este recorrido cuando quieras desde Ajustes."},"jira":{"label":"Integración con Jira","body":"Respalda cualquier proyecto con un <b>tablero de Jira</b> — cada spec es un issue de Jira, sincronizado en ambos sentidos: el estado sigue al rail y se publica un comentario al terminar un job. Configúralo por proyecto al añadirlo, o cuando quieras en Ajustes."}}`),a={addProject:e,prerequisites:t,instructions:n,welcome:r,onboarding:i};export{e as addProject,a as default,n as instructions,i as onboarding,t as prerequisites,r as welcome};
@@ -0,0 +1 @@
1
+ var e={title:`Ajouter un projet`,description:`Enregistrez un répertoire de projet pour le gérer depuis Specrails.`,noProviderDetected:`Aucune CLI d'IA détectée. Installez d'abord Claude Code, Codex CLI, Gemini CLI ou Kimi Code.`,pathLabel:`Chemin du projet`,pathPlaceholder:`/Users/moi/mon-projet`,pathHint:`Chemin absolu vers la racine du projet`,browseForFolder:`Parcourir les dossiers`,selectProjectFolder:`Sélectionner le dossier du projet`,nameLabel:`Nom d'affichage`,optional:`(facultatif)`,namePlaceholder:`Mon projet`,nameHint:`Par défaut, le nom du répertoire`,adding:`Ajout...`,submit:`Ajouter le projet`,toolsRequired_one:`{{tools}} est requis pour ajouter un projet`,toolsRequired_other:`{{tools}} sont requis pour ajouter un projet`,errors:{pathRequired:`Le chemin du projet est requis`,addFailed:`Échec de l'ajout du projet`},toasts:{registered:`Projet « {{name}} » enregistré`},chooser:{description:`Apportez un dépôt existant, ou construisez un tout nouveau projet à partir d'une idée.`,existingTitle:`Projet existant`,existingDescription:`Enregistrez un dépôt qui existe déjà sur le disque.`,newTitle:`Nouveau projet`,newDescription:`Décrivez une idée et obtenez un dépôt initialisé avec un backlog du Jalon 1.`}},t={corruptedBundle:`bundle corrompu — réinstallez l'application`,notInstalled:`non installé`,failedToExecute:`trouvé mais impossible à exécuter`,failedToExecuteAt:`trouvé à {{path}} mais impossible à exécuter`,failedToExecuteWithError:`trouvé mais impossible à exécuter ({{error}})`,failedToExecuteAtWithError:`trouvé à {{path}} mais impossible à exécuter ({{error}})`,needsMinimum:`{{version}} trouvé — nécessite {{minVersion}}+`,unknownVersion:`inconnue`,installedLabel:`installé`,verifyError:`Impossible de vérifier les outils de développement en local — l'installation s'en chargera.`,allDetected:`Tous les outils requis sont détectés`,bundleCorruptedTitle:`Bundle de l'application corrompu`,toolsRequired_one:`{{count}} outil de développement requis`,toolsRequired_other:`{{count}} outils de développement requis`,reinstallHint:`Réinstallez l'application Specrails pour restaurer les outils embarqués.`,installMissingHint:`Installez les outils manquants pour continuer.`,moreInfo:`Plus d'infos`,bundledBadge:`embarqué`,optional:`optionnel`,ghNoAuth:"Non connecté — exécutez `gh auth login`"},n={title:`Installer les outils de développement`,description:`SpecRails a besoin de Node.js, npm, npx et Git sur le PATH. Choisissez le snippet pour votre OS, exécutez-le, puis cliquez sur « Je l'ai installé, revérifier ».`,darwin:{intro:`Homebrew installe les deux outils en une seule ligne. Si vous n'avez pas brew, utilisez les téléchargements officiels.`,installNodeGit:`Installer Node.js et Git via Homebrew`},win32:{intro:`Winget est fourni avec Windows 11 et les versions récentes de Windows 10. Ouvrez PowerShell ou le Terminal et exécutez :`,installNode:`Installer Node.js LTS`,installGit:`Installer Git`,note:`Après l'installation, redémarrez Specrails pour que Windows actualise le PATH.`},linux:{intro:`Utilisez le gestionnaire de paquets de votre distribution :`,debian:`Debian / Ubuntu`,fedora:`Fedora / RHEL`},links:{nodeOfficial:`Node.js (officiel)`,gitOfficial:`Git (officiel)`,gitWindows:`Git pour Windows (officiel)`},showOtherPlatforms:`Afficher les autres plateformes`,hideOtherPlatforms:`Masquer les autres plateformes`,recheck:`Je l'ai installé, revérifier`,diagnostics:{copy:`Copier les diagnostics`,copied:`Diagnostics copiés`,failed:`Échec de la copie`},corrupted:{title:`Bundle de l'application corrompu`,description:`Un ou plusieurs outils embarqués (Node.js, Git) n'ont pas pu être vérifiés.`,body:`Cet outil est embarqué avec l'application Specrails et ne peut pas être installé séparément. Si vous voyez ce message, le bundle de l'application est peut-être corrompu. Veuillez réinstaller Specrails.`}},r={title:`Bienvenue dans <spec>spec</spec><rails>rails</rails>`,description:`Specrails gère plusieurs projets depuis une seule interface. Ajoutez votre premier projet pour commencer.`,addFirstProject:`Ajouter votre premier projet`,jiraHint:`Connectez chaque projet à son propre tableau Jira — les specs restent synchronisées dans les deux sens.`,mcpHint:`Connectez des outils d'IA externes à Specrails via un serveur MCP local sécurisé — activez-le dans les Paramètres.`,agentChatHint:`Pilotez Specrails en discutant — un agent intégré gère les specs, les rails et les analyses pour vous via le MCP local. Ouvrez-le depuis la bulle ou avec ⌘⇧A.`},i=JSON.parse(`{"productTour":"Visite guidée","stepCount":"Étape {{current}} sur {{total}}","goToStep":"Aller à l'étape {{step}} : {{label}}","stepLabel":"Étape {{step}}","dontShowAgain":"Ne plus afficher","skipTour":"Passer la visite","getStarted":"Commencer","flow":{"addSpec":"Ajouter une spec","dropInRail":"Déposer dans un rail","hitPlay":"Appuyer sur Play","ship":"Livrer","architect":"Architecte","developer":"Développeur","reviewer":"Relecteur"},"language":{"nav":"Langue","title":"Choisissez votre langue","subtitle":"Specrails parle votre langue","intro":"Choisissez la langue de l'interface. Elle s'applique instantanément — cette visite comprise.","note":"Vous pouvez en changer à tout moment dans Paramètres → Langue."},"theme":{"nav":"Thème","title":"Trouvez votre style","subtitle":"Des thèmes intégrés, appliqués instantanément","intro":"Choisissez l'apparence de Specrails — le thème s'applique dès que vous cliquez.","note":"Vous pouvez en changer à tout moment dans Paramètres → Apparence."},"welcome":{"nav":"Bienvenue","title":"Bienvenue dans Specrails","subtitle":"Votre cockpit local pour livrer du logiciel avec des agents IA","intro":"Specrails transforme une idée en code livré — et vous laisse <b>voir, piloter et vérifier</b> chaque étape. Rédigez une spec en discutant avec une IA, déposez-la sur un rail d'exécution et appuyez sur Play. Le pipeline gère l'architecture, l'implémentation, la revue et la pull request, en streamant son travail en direct du début à la fin.","coreLoopLabel":"La boucle de base","flowCaption":"Chaque spec passe automatiquement par <b>Architecte → Développeur → Relecteur → Livraison</b>.","localNote":"<b>100 % local · mono-utilisateur · sans compte.</b> Tout s'exécute sur votre machine. Votre code ne quitte jamais le laptop, sauf si <i>vous</i> lancez un agent dessus.","tourNote":"Cette visite rapide passe en revue tout ce que l'application sait faire — environ une minute."},"authorSpecs":{"nav":"Rédiger des specs","title":"Transformez vos idées en specs","subtitle":"Six façons de capturer exactement ce que vous voulez construire","intro":"Une <b>spec</b> est une description du travail à réaliser. Rédigez-la comme le moment s'y prête — de la simple phrase à la conversation complète avec l'IA.","exploreLabel":"Explore — conversez","exploreBody":"Décrivez ce que vous voulez dans un chat ; un brouillon vivant se reconstruit à chaque tour. Un curseur de presets règle la quantité de contexte projet que voit l'IA — de votre message seul jusqu'au codebase complet plus vos serveurs MCP.","quickLabel":"Quick — en un coup","quickBody":"Vous savez déjà ce que vous voulez ? Générez une spec complète en un seul tour. Enrichissez-la éventuellement d'un Contract Layer : noms exacts, formes de données, invariants et liste des fichiers touchés, pour que les agents ne réinventent rien.","websiteLabel":"Depuis un site web","websiteBody":"Ouvre un navigateur embarqué. Survolez un élément pour le sélectionner ou tracez un rectangle : la capture d'écran, le DOM et le CSS appliqué deviennent des pièces jointes. La version desktop embarque son propre Chromium, donc ça fonctionne hors ligne.","smashLabel":"SMASH pour les grosses epics","smashBody":"Éclatez une grande spec en une famille de sous-specs plus petites en un clic — chaque enfant porte un court résumé sur sa carte.","draftsLabel":"Brouillons & reprise d'édition","draftsBody":"Mettez une exploration en cours de côté comme ticket brouillon et reprenez-la plus tard ; rouvrez n'importe quelle spec dans Explore pour continuer à l'affiner.","compareLabel":"Comparer côte à côte","compareBody":"Glissez une spec vers le bord de l'écran et un sélecteur de vos autres specs apparaît — passez-en deux en revue ensemble, façon tablette."},"rails":{"nav":"Exécuter sur des rails","title":"Lancez le pipeline sur des rails","subtitle":"Organisez les specs en couloirs, puis lancez les agents","intro":"La partie droite du Dashboard, ce sont vos <b>Rails</b> — des couloirs d'exécution. Glissez une carte de spec sur un rail et appuyez sur <play>▶ Play</play> pour lancer un job d'implémentation.","jobLabel":"Ce que chaque job exécute","flowCaption":"Chaque phase streame ses logs en direct pendant qu'elle travaille.","modeLabel":"Choisissez un Loop à exécuter","modeBody":"Chaque rail exécute un <b>Loop</b>. Choisissez-en un intégré — <b>Implement</b> (le pipeline structuré complet), <b>Batch</b> (plusieurs specs à la fois) ou <b>Freestyle</b> (un fournisseur compatible travaille en autonomie, sans pipeline figé) — ou un que vous avez créé vous-même.","profilesLabel":"Profils d'agents","profilesBody":"Un catalogue déclaratif par projet qui décide quels agents s'exécutent et quel modèle chacun utilise — choisi par rail et snapshotté par job pour que les travaux concurrents restent isolés.","jobDetailLabel":"Détail de job en direct","jobDetailBody":"Chaque job affiche un en-tête d'identité de ticket, un chrono de durée en direct et des compteurs de tours/tokens, avec le coût définitif résolu à la fin.","isolationLabel":"Plusieurs projets, isolés","isolationBody":"Chaque projet a sa propre base de données et sa propre file de jobs. Exécutez plusieurs projets en même temps et passez de l'un à l'autre depuis la barre latérale gauche — votre position est mémorisée par projet.","loopsLabel":"Créez vos propres loops","loopsBody":"<b>Loops</b> est un éditeur visuel : enchaînez des étapes IA, des commandes shell et un <b>Loop Decider</b> qui répète jusqu'à ce qu'un objectif soit atteint — p. ex. vérifier → corriger → vérifier jusqu'à ce que tout soit au vert. Publiez un loop et choisissez-le sur n'importe quel rail."},"agent":{"nav":"Chat de l'agent","title":"Pilotez l'app en discutant","subtitle":"Un copilote qui pilote Specrails pour vous","intro":"Le <b>chat de l'agent</b> intégré vous permet de piloter Specrails en demandant — créer des specs, lancer des rails, consulter les analyses — au lieu de cliquer partout. Il fonctionne via les propres outils <b>MCP</b> de Specrails et, comme tout est en direct, vous voyez le tableau changer pendant qu'il travaille.","openLabel":"Toujours à portée de clic","openBody":"Ouvrez-le depuis la bulle flottante en bas, ou appuyez sur ⌘⇧A (Ctrl+Shift+A) depuis n'importe où. Le panneau se déplace, se redimensionne, s'agrandit et se souvient de l'endroit où vous l'avez laissé.","operateLabel":"Pilote toute l'app","operateBody":"Choisissez un projet (ou Accueil pour tout) et un fournisseur, puis demandez simplement : “lance les trois tickets les plus prioritaires”, “combien ai-je dépensé cette semaine ?”.","levelsLabel":"C'est vous qui tenez la laisse","levelsBody":"Un niveau en direct — <b>Observer → Modifier → Opérer → Autonome</b>, que l'on fait défiler avec Shift+Tab — décide jusqu'où il peut aller. Il n'agit jamais au-dessus du niveau que vous définissez.","watchLabel":"Regardez-le faire","watchBody":"Le panneau n'est pas modal : les rails et les specs apparaissent sur le tableau de bord en temps réel pendant que l'agent travaille. Une pastille d'état indique ce qu'il fait en ce moment.","mcpLabel":"Fonctionne sur le MCP local","mcpBody":"L'agent pilote l'app via le serveur MCP intégré de Specrails. S'il est désactivé, le panneau propose de l'activer en un clic — rien n'est installé."},"providers":{"nav":"Votre agent","title":"Apportez votre propre agent","subtitle":"Claude Code, Codex, Gemini et Kimi comme moteurs de premier ordre","intro":"L'app traite <b>Claude Code</b>, <b>Codex CLI</b>, <b>Gemini CLI</b> et <b>Kimi Code</b> comme des moteurs interchangeables derrière un même contrat. Un projet peut en installer un ou plusieurs — le choix se fait à l'installation.","table":{"capability":"Capacité","streamingResume":"Streaming & reprise de session","native":"Natif","costReporting":"Suivi des coûts","providerBilled":"Facturé par le fournisseur","estimated":"Estimé (~)","unavailable":"Indisponible","telemetry":"Télémétrie (OTEL)","synthesized":"Synthétisée","agentProfiles":"Profils d'agents"},"calloutLabel":"Quand plusieurs sont installés","calloutBody":"Choisissez le moteur <b>par spec, par rail ou par lancement de terminal</b>. Les coûts estimés sont marqués d'un <mono>~</mono> ; Kimi ne fournit ni tokens ni coût."},"cost":{"nav":"Suivre les coûts","title":"Suivez chaque centime","subtitle":"Chaque invocation facturable, enregistrée et visualisée","intro":"Chaque invocation d'IA enregistre son cycle de vie et son fournisseur. L'usage et le coût restent indisponibles lorsqu'un fournisseur, tel que Kimi, ne les fournit pas.","analyticsLabel":"Page Analytics","analyticsBody":"Un hero de burn-rate, une timeline quotidienne, le top des tickets, la répartition par modèle et un nuage coût vs tours. Filtrez par période (7 j / 30 j / 90 j / Tout) et par surface.","perTicketLabel":"Dépenses par ticket","perTicketBody":"Le détail de chaque spec montre ce qu'elle a coûté et combien de tours il a fallu, avec un lien direct vers Analytics filtré sur ce ticket.","honestLabel":"Des chiffres honnêtes","honestBody":"Le coût Claude est fourni par le fournisseur ; Codex et Gemini peuvent être estimés et marqués d'un <mono>~</mono>. Pour Kimi, les tokens et le coût USD sont indisponibles, pas nuls.","budgetsLabel":"Budgets & alertes","budgetsBody":"Définissez un budget quotidien et une alerte de coût par job ; l'application met automatiquement la file en pause quand vous franchissez la limite. Exportez tout en CSV ou JSON."},"workspace":{"nav":"Espace de travail","title":"Faites-en votre espace de travail","subtitle":"Tout ce qu'il vous faut sans quitter la fenêtre","terminalLabel":"Panneau de terminal","terminalBody":"Un vrai terminal façon VS Code en bas (<mod>{{mod}}</mod> <j>J</j>) — rendu WebGL, recherche, images inline, glisser-déposer de chemins et intégration shell. Jusqu'à 10 sessions par projet.","codeLabel":"Explorateur de code","codeBody":"Une arborescence de fichiers en lecture seule et un viewer Monaco avec des résumés IA en langage clair et des puces de provenance « touché par l'IA », pour que chacun puisse suivre ce qui a changé et pourquoi.","integrationsLabel":"Intégrations","integrationsBody":"Une marketplace d'intégrations MCP par projet — la navigation sémantique de code Serena est incluse. Les installations sont additives : en ajouter une ne perturbe jamais les autres.","themesLabel":"Thèmes","themesBody":"Six thèmes intégrés — specrails (par défaut), dracula, aurora-light, obsidian-dark, code-rain et galaxy — appliqués avant le rendu de l'UI, donc sans flash. Changez-les dans Paramètres → Apparence.","chatsLabel":"Chats minimisables","chatsBody":"Rangez une session Explore ou Édition IA dans une puce du dock et reprenez-la plus tard — jamais perdue, même après un rechargement ou un changement de projet.","desktopLabel":"Desktop ou navigateur","desktopBody":"Lancez Specrails dans votre navigateur, ou prenez l'application desktop signée (macOS & Windows) qui embarque son propre serveur et ses runtimes."},"companion":{"nav":"Compagnon mobile","title":"Emportez Specrails avec vous","subtitle":"Specrails Companion — vos pipelines, dans votre poche","intro":"<b>Specrails Companion</b> est une application web disponible sur specrails.dev/companion-app — ouvrez-la sur votre téléphone (ou ajoutez-la à votre écran d'accueil) pour parcourir le tableau des specs, lancer et arrêter des rails, suivre les logs des jobs en direct et jeter un œil aux analytics. Aucune installation, aucun app store.","localLabel":"100 % local, comme tout le reste","localBody":"Votre téléphone se connecte directement à cet ordinateur — en pair-à-pair et chiffré (WebRTC). Pas de relais cloud, pas de compte, et votre code ne quitte jamais vos appareils.","downloadLabel":"Ouvrez-la sur votre téléphone","downloadHint":"Scannez le code avec l'appareil photo de votre téléphone, ou ouvrez specrails.dev/companion-app dans son navigateur.","open":"Ouvrir Specrails Companion","pairLabel":"L'appairage prend dix secondes","pairBody":"Sur votre téléphone, ouvrez specrails.dev/companion-app, puis ici allez dans Paramètres → Compagnon mobile → Appairer le compagnon web et suivez les étapes à l'écran."},"moveFast":{"nav":"Aller vite","title":"Avancez à la vitesse de la pensée","subtitle":"Le clavier d'abord, partout","paletteLabel":"Palette de commandes","paletteShortcut":"<f>Appuyez sur</f> <mod>{{mod}}</mod> <m>+</m> <k>K</k> <m>n'importe où</m>","paletteBody":"Changez de projet, lancez des commandes de spec, sautez vers n'importe quelle page et retrouvez les jobs récents — le tout en recherche floue.","terminalLabel":"Panneau de terminal","terminalBody":"Basculez avec <mod>{{mod}}</mod> <j>J</j>.","shortcutsLabel":"Tous les raccourcis","shortcutsBody":"Appuyez sur <q>?</q> pour voir l'antisèche complète.","chatLabel":"Barre latérale de chat","chatBody":"Basculez la barre latérale droite avec <mod>{{mod}}</mod> <bkey>B</bkey>.","projectsLabel":"Barre latérale des projets","projectsBody":"Basculez la barre latérale Arc de gauche avec <alt>{{alt}}</alt> <mod>{{mod}}</mod> <bkey>B</bkey>.","outro":"<b>La visite est terminée.</b> Ajoutez un projet depuis la barre latérale gauche et livrez votre première spec. Vous pouvez rouvrir cette visite à tout moment depuis les Paramètres."},"jira":{"label":"Intégration Jira","body":"Adossez n'importe quel projet à un <b>tableau Jira</b> — chaque spec devient un ticket Jira, synchronisé dans les deux sens : le statut suit le rail et un commentaire est publié à la fin d'un job. Configurez-le par projet lors de l'ajout, ou à tout moment dans les Paramètres."}}`),a={addProject:e,prerequisites:t,instructions:n,welcome:r,onboarding:i};export{e as addProject,a as default,n as instructions,i as onboarding,t as prerequisites,r as welcome};
@@ -0,0 +1 @@
1
+ var e={title:`プロジェクトを追加`,description:`プロジェクトディレクトリを登録して Specrails から管理します。`,noProviderDetected:`AI CLI が見つかりません。まず Claude Code、Codex CLI、Gemini CLI、Kimi Code のいずれかをインストールしてください。`,pathLabel:`プロジェクトパス`,pathPlaceholder:`/Users/me/my-project`,pathHint:`プロジェクトルートへの絶対パス`,browseForFolder:`フォルダを参照`,selectProjectFolder:`プロジェクトフォルダを選択`,nameLabel:`表示名`,optional:`(任意)`,namePlaceholder:`マイプロジェクト`,nameHint:`デフォルトはディレクトリ名`,adding:`追加中…`,submit:`プロジェクトを追加`,toolsRequired_one:`プロジェクトの追加には {{tools}} が必要です`,toolsRequired_other:`プロジェクトの追加には {{tools}} が必要です`,errors:{pathRequired:`プロジェクトパスは必須です`,addFailed:`プロジェクトの追加に失敗しました`},toasts:{registered:`プロジェクト「{{name}}」を登録しました`},chooser:{description:`既存のリポジトリを取り込むか、アイデアから新しいプロジェクトを作りましょう。`,existingTitle:`既存プロジェクト`,existingDescription:`ディスク上に既にあるリポジトリを登録します。`,newTitle:`新規プロジェクト`,newDescription:`アイデアを伝えると、マイルストーン1のバックログ付きでリポジトリが用意されます。`}},t={corruptedBundle:`バンドル破損 — アプリを再インストールしてください`,notInstalled:`未インストール`,failedToExecute:`見つかりましたが実行できませんでした`,failedToExecuteAt:`{{path}} に見つかりましたが実行できませんでした`,failedToExecuteWithError:`見つかりましたが実行できませんでした({{error}})`,failedToExecuteAtWithError:`{{path}} に見つかりましたが実行できませんでした({{error}})`,needsMinimum:`{{version}} が見つかりました — {{minVersion}} 以上が必要です`,unknownVersion:`不明`,installedLabel:`インストール済み`,verifyError:`開発者ツールをローカルで検証できませんでした — インストール時に検証されます。`,allDetected:`必要なツールはすべて検出されました`,bundleCorruptedTitle:`アプリバンドルが破損しています`,toolsRequired_one:`{{count}} 個の開発者ツールが必要です`,toolsRequired_other:`{{count}} 個の開発者ツールが必要です`,reinstallHint:`Specrails アプリを再インストールしてバンドルツールを復元してください。`,installMissingHint:`続行するには不足しているツールをインストールしてください。`,moreInfo:`詳細`,bundledBadge:`バンドル`,optional:`任意`,ghNoAuth:"未ログイン — `gh auth login` を実行してください"},n={title:`開発者ツールをインストール`,description:`SpecRails には PATH 上の Node.js、npm、npx、Git が必要です。お使いの OS のスニペットを選んで実行し、「インストールしました。再チェック」をクリックしてください。`,darwin:{intro:`Homebrew なら1行で両方のツールをインストールできます。brew がない場合は公式ダウンロードを利用してください。`,installNodeGit:`Homebrew で Node.js と Git をインストール`},win32:{intro:`Winget は Windows 11 および最近の Windows 10 に同梱されています。PowerShell またはターミナルを開いて実行してください:`,installNode:`Node.js LTS をインストール`,installGit:`Git をインストール`,note:`インストール後、Windows が PATH を更新するように Specrails を再起動してください。`},linux:{intro:`ディストリビューションのパッケージマネージャーを使用してください:`,debian:`Debian / Ubuntu`,fedora:`Fedora / RHEL`},links:{nodeOfficial:`Node.js(公式)`,gitOfficial:`Git(公式)`,gitWindows:`Git for Windows(公式)`},showOtherPlatforms:`他のプラットフォームを表示`,hideOtherPlatforms:`他のプラットフォームを非表示`,recheck:`インストールしました。再チェック`,diagnostics:{copy:`診断情報をコピー`,copied:`診断情報をコピーしました`,failed:`コピーに失敗しました`},corrupted:{title:`アプリバンドルが破損しています`,description:`バンドルされたツール(Node.js、Git)の一部を検証できませんでした。`,body:`このツールは Specrails アプリにバンドルされており、個別にインストールできません。このメッセージが表示される場合、アプリバンドルが破損している可能性があります。Specrails を再インストールしてください。`}},r={title:`<spec>spec</spec><rails>rails</rails> へようこそ`,description:`Specrails は複数のプロジェクトを単一のインターフェースで管理します。最初のプロジェクトを追加して始めましょう。`,addFirstProject:`最初のプロジェクトを追加`,jiraHint:`各プロジェクトを専用の Jira ボードに接続 — スペックは双方向で同期され続けます。`,mcpHint:`安全なローカル MCP サーバーを通じて外部 AI ツールを Specrails に接続 — 設定で有効にできます。`,agentChatHint:`チャットで Specrails を操作 — 内蔵エージェントがローカル MCP を通じて specs・rails・分析をあなたの代わりに処理します。バブルから、または ⌘⇧A で開けます。`},i=JSON.parse(`{"productTour":"プロダクトツアー","stepCount":"ステップ {{current}} / {{total}}","goToStep":"ステップ {{step}} へ移動: {{label}}","stepLabel":"ステップ {{step}}","dontShowAgain":"今後表示しない","skipTour":"ツアーをスキップ","getStarted":"始める","flow":{"addSpec":"スペックを追加","dropInRail":"レールにドロップ","hitPlay":"再生を押す","ship":"Ship","architect":"アーキテクト","developer":"デベロッパー","reviewer":"レビュアー"},"language":{"nav":"言語","title":"言語を選ぶ","subtitle":"Specrailsはあなたの言語に対応","intro":"インターフェースで使いたい言語を選んでください。即座に適用されます — このツアーも含めて。","note":"設定 → 言語でいつでも変更できます。"},"theme":{"nav":"テーマ","title":"好みの見た目を選ぶ","subtitle":"内蔵テーマを即座に適用","intro":"Specrailsの見た目を選びましょう — テーマはクリックした瞬間に適用されます。","note":"設定 → 外観でいつでも変更できます。"},"welcome":{"nav":"ようこそ","title":"Specrails へようこそ","subtitle":"AI エージェントでソフトウェアを出荷するためのローカルコックピット","intro":"Specrails はアイデアを出荷済みのコードに変えます — そのすべてのステップを<b>見て、操り、信頼</b>できます。AI と対話してスペックを下書きし、実行レールにドロップして再生を押すだけ。パイプラインがアーキテクチャ、実装、レビュー、プルリクエストまで処理し、その作業をライブでストリーミングします。","coreLoopLabel":"コアループ","flowCaption":"各スペックは <b>アーキテクト → デベロッパー → レビュアー → Ship</b> を自動で流れます。","localNote":"<b>100% ローカル · シングルユーザー · アカウント不要。</b>すべてあなたのマシン上で動作します。<i>あなた</i>がエージェントを起動しない限り、コードがラップトップの外に出ることはありません。","tourNote":"このクイックツアーではアプリの全機能を紹介します — 所要時間は約1分です。"},"authorSpecs":{"nav":"スペック作成","title":"アイデアをスペックに変える","subtitle":"作りたいものを正確に捉える6つの方法","intro":"<b>スペック</b>とは、実行してほしい作業の記述です。短い一文から AI との本格的な対話まで、その時々に合った方法で作成できます。","exploreLabel":"Explore — 対話する","exploreBody":"作りたいものをチャットで説明すると、ライブドラフトがターンごとに再構築されます。プリセットスライダーで AI に見せるプロジェクトコンテキストの量を調整できます — メッセージのみから、コードベース全体 + MCP サーバーまで。","quickLabel":"Quick — 一発生成","quickBody":"作りたいものが明確なら、1ターンで完全なスペックを生成できます。オプションで Contract Layer によるエンリッチも可能: 正確な名前、データ形状、不変条件、変更ファイルリストにより、エージェントが車輪の再発明をしません。","websiteLabel":"ウェブサイトから","websiteBody":"埋め込みブラウザが開きます。要素をホバー選択するか矩形をドラッグすると、スクリーンショット、DOM、適用された CSS が添付ファイルになります。デスクトップ版は独自の Chromium を同梱しているのでオフラインでも動作します。","smashLabel":"大きなエピックを SMASH","smashBody":"大きなスペックをワンクリックで小さなサブスペック群に分解します — 各子スペックのカードには短い要約が付きます。","draftsLabel":"下書きと編集の再開","draftsBody":"進行中の探索を下書きチケットとして保存し、後で再開できます。どのスペックも Explore で開き直して改良を続けられます。","compareLabel":"並べて比較","compareBody":"スペックを画面の端にドラッグすると、他のスペックのピッカーがスライドインします — タブレット風に2つを並べてレビューできます。"},"rails":{"nav":"レールで実行","title":"パイプラインをレールで実行","subtitle":"スペックをレーンに整理してエージェントを起動","intro":"ダッシュボードの右側が<b>レール</b> — 実行レーンです。スペックカードをレールにドラッグして <play>▶ 再生</play> を押すと、実装ジョブが起動します。","jobLabel":"各ジョブの実行内容","flowCaption":"各フェーズは作業中のログをライブでストリーミングします。","modeLabel":"実行する Loop を選択","modeBody":"各 rail は <b>Loop</b> を実行します。組み込みの Loop を選ぶ — <b>Implement</b>、<b>Batch</b>、または対応プロバイダーが自律的に動く <b>Freestyle</b> — か、自分で作った Loop を選びます。","profilesLabel":"エージェントプロファイル","profilesBody":"どのエージェントを実行し、それぞれどのモデルを使うかを決めるプロジェクトごとの宣言的カタログ — レールごとに選択され、ジョブごとにスナップショットされるため並行作業が分離されます。","jobDetailLabel":"ライブジョブ詳細","jobDetailBody":"各ジョブにはチケット識別ヘッダー、ライブの経過時間ティッカー、進行中のターン/トークン数が表示され、確定コストは終了時に解決されます。","isolationLabel":"複数プロジェクト、完全分離","isolationBody":"各プロジェクトは独自のデータベースとジョブキューを持ちます。複数のプロジェクトを同時に実行し、左サイドバーから切り替えられます — 位置はプロジェクトごとに記憶されます。","loopsLabel":"独自の loop を作る","loopsBody":"<b>Loops</b> はビジュアルビルダーです。AI ステップ、シェルコマンド、そして目標を達成するまで繰り返す <b>Loop Decider</b> を連結できます — 例えば、すべてグリーンになるまで 検証 → 修正 → 検証 を繰り返す。loop を公開すれば、どの rail でも選択できます。"},"agent":{"nav":"エージェントチャット","title":"チャットでアプリを操作","subtitle":"Specrails をあなたの代わりに動かすコパイロット","intro":"内蔵の <b>エージェントチャット</b> を使えば、あちこちクリックする代わりに、頼むだけで Specrails を操作できます — spec の作成、rail の起動、分析の確認まで。Specrails 独自の <b>MCP</b> ツールを介して動作し、すべてがライブなので、動作中にボードが変化する様子を見られます。","openLabel":"いつでもワンクリック","openBody":"下部のフローティングバブルから、またはどこからでも ⌘⇧A(Ctrl+Shift+A)で開けます。パネルは移動・リサイズ・最大化でき、前回の位置を記憶します。","operateLabel":"アプリ全体を動かす","operateBody":"プロジェクト(またはすべてを見るにはホーム)とプロバイダーを選び、あとは頼むだけ:“優先度の高い上位 3 件のチケットを起動して”、“今週いくら使った?”。","levelsLabel":"手綱はあなたが握る","levelsBody":"ライブのレベル — <b>観察 → 編集 → 操作 → 自律</b>、Shift+Tab で切り替え — が、どこまで進めるかを決めます。設定したレベルを超えて動くことは決してありません。","watchLabel":"その様子を見守る","watchBody":"パネルは非モーダルなので、エージェントの作業中も rails や specs がリアルタイムでダッシュボードに表示されます。ステータスチップが今何をしているかを示します。","mcpLabel":"ローカル MCP 上で動作","mcpBody":"エージェントは組み込みの Specrails MCP サーバーを通じてアプリを動かします。オフの場合、パネルがワンクリックで有効化を提案します — 何もインストールされません。"},"providers":{"nav":"あなたのエージェント","title":"自分のエージェントを持ち込む","subtitle":"Claude Code・Codex・Gemini・Kimi を第一級エンジンとして","intro":"アプリは <b>Claude Code</b>・<b>Codex CLI</b>・<b>Gemini CLI</b>・<b>Kimi Code</b> を同一契約の下で交換可能なエンジンとして扱います。プロジェクトには 1 つ以上をインストールできます。","table":{"capability":"機能","streamingResume":"ストリーミングとセッション再開","native":"ネイティブ","costReporting":"コストレポート","providerBilled":"プロバイダー請求額","estimated":"推定(~)","unavailable":"利用不可","telemetry":"テレメトリ(OTEL)","synthesized":"合成","agentProfiles":"エージェントプロファイル"},"calloutLabel":"複数インストールされている場合","calloutBody":"<b>スペックごと、レールごと、ターミナル起動ごと</b>にエンジンを選べます。推定コストには <mono>~</mono> が付きます。Kimi はトークンやコストを報告しません。"},"cost":{"nav":"コスト追跡","title":"1セント単位で追跡","subtitle":"課金対象のすべての呼び出しを記録・可視化","intro":"すべての AI 呼び出しでライフサイクルとプロバイダーを記録します。Kimi のように使用量やコストを報告しない場合、それらは利用不可のままです。","analyticsLabel":"分析ページ","analyticsBody":"バーンレートのヒーロー表示、日次タイムライン、トップチケット、モデル別内訳、コスト対ターン数の散布図。期間(7日 / 30日 / 90日 / 全期間)とサーフェスでフィルタできます。","perTicketLabel":"チケット別の支出","perTicketBody":"各スペックの詳細にはコストと所要ターン数が表示され、そのチケットでフィルタした分析ページへディープリンクします。","honestLabel":"正直な数字","honestBody":"Claude のコストはプロバイダー報告値、Codex と Gemini は推定の場合 <mono>~</mono> が付きます。Kimi のトークンと USD コストは 0 ではなく利用不可です。","budgetsLabel":"予算とアラート","budgetsBody":"日次予算とジョブ単位のコストアラートを設定でき、上限を超えるとアプリが自動でキューを一時停止します。すべて CSV または JSON にエクスポートできます。"},"workspace":{"nav":"ワークスペース","title":"あなたのワークスペースに","subtitle":"ウィンドウを離れずに必要なすべてを","terminalLabel":"ターミナルパネル","terminalBody":"画面下部の本格的な VS Code スタイルのターミナル(<mod>{{mod}}</mod> <j>J</j>)— WebGL レンダリング、検索、インライン画像、パスのドラッグ&ドロップ、シェル統合。プロジェクトごとに最大10セッション。","codeLabel":"コードエクスプローラー","codeBody":"読み取り専用のファイルツリーと Monaco ビューアに、平易な AI 要約と「AI が変更」の来歴チップが付き、誰でも何がなぜ変わったかを追えます。","integrationsLabel":"インテグレーション","integrationsBody":"プロジェクトごとの MCP インテグレーションのマーケットプレイス — Serena のセマンティックコードナビゲーションを同梱。インストールは加算式で、追加しても他に影響しません。","themesLabel":"テーマ","themesBody":"6つの組み込みテーマ — specrails(デフォルト)、dracula、aurora-light、obsidian-dark、code-rain、galaxy — を UI の描画前に適用するため、フラッシュがありません。設定 → 外観で変更できます。","chatsLabel":"最小化できるチャット","chatsBody":"Explore や AI 編集のセッションをドックのチップに格納して後で再開 — リフレッシュやプロジェクト切り替えで失われることはありません。","desktopLabel":"デスクトップまたはブラウザ","desktopBody":"ブラウザで Specrails を実行するか、サーバーとランタイムを同梱した署名済みデスクトップアプリ(macOS と Windows)を入手できます。"},"companion":{"nav":"モバイルコンパニオン","title":"Specrails を持ち歩く","subtitle":"Specrails Companion — あなたのパイプラインを、スマートフォンで","intro":"<b>Specrails Companion</b> は specrails.dev/companion-app で使える Web アプリです — スマートフォンで開く(またはホーム画面に追加する)だけで、スペックボードの閲覧、レールの起動と停止、ジョブログのライブ追跡、分析のチェックができます。インストール不要、アプリストアも不要。","localLabel":"ほかのすべてと同じく 100% ローカル","localBody":"スマートフォンはこのコンピュータに直接接続します — ピアツーピアで暗号化(WebRTC)。クラウド中継なし、アカウント不要、コードがあなたのデバイスの外に出ることはありません。","downloadLabel":"スマートフォンで開く","downloadHint":"スマートフォンのカメラでコードをスキャンするか、ブラウザで specrails.dev/companion-app を開いてください。","open":"Specrails Companion を開く","pairLabel":"ペアリングは10秒で完了","pairBody":"スマートフォンで specrails.dev/companion-app を開き、こちらで 設定 → モバイルコンパニオン → Web コンパニオンをペアリング と進んで、画面の手順に従ってください。"},"moveFast":{"nav":"高速操作","title":"思考のスピードで動く","subtitle":"どこでもキーボードファースト","paletteLabel":"コマンドパレット","paletteShortcut":"<f>どこでも</f> <mod>{{mod}}</mod> <m>+</m> <k>K</k> <m>を押す</m>","paletteBody":"プロジェクトの切り替え、スペックコマンドの実行、任意のページへのジャンプ、最近のジョブの検索 — すべてあいまい検索で。","terminalLabel":"ターミナルパネル","terminalBody":"<mod>{{mod}}</mod> <j>J</j> で切り替え。","shortcutsLabel":"全ショートカット","shortcutsBody":"<q>?</q> を押すと完全なチートシートが表示されます。","chatLabel":"チャットサイドバー","chatBody":"<mod>{{mod}}</mod> <bkey>B</bkey> で右サイドバーを切り替え。","projectsLabel":"プロジェクトサイドバー","projectsBody":"<alt>{{alt}}</alt> <mod>{{mod}}</mod> <bkey>B</bkey> で左の Arc サイドバーを切り替え。","outro":"<b>ツアーは以上です。</b>左サイドバーからプロジェクトを追加して、最初のスペックを出荷しましょう。このウォークスルーは設定からいつでも再表示できます。"},"jira":{"label":"Jira 連携","body":"任意のプロジェクトを <b>Jira ボード</b> で裏付けます — 各スペックは Jira の課題になり、双方向で同期されます。ステータスは rail に追従し、job 完了時にコメントが投稿されます。追加時にプロジェクトごとに設定するか、いつでも設定から構成できます。"}}`),a={addProject:e,prerequisites:t,instructions:n,welcome:r,onboarding:i};export{e as addProject,a as default,n as instructions,i as onboarding,t as prerequisites,r as welcome};
@@ -1 +1 @@
1
- import{o as e}from"./i18n-Ch-Db_x2.js";var t={job:`analytics:surfaces.job`,"quick-spec":`analytics:surfaces.quickSpec`,"explore-spec":`analytics:surfaces.exploreSpec`,"ai-edit":`analytics:surfaces.aiEdit`,smash:`analytics:surfaces.smash`,"file-summary":`analytics:surfaces.fileSummary`,loop:`analytics:surfaces.loop`,"chat-sidebar":`analytics:surfaces.chatSidebar`,"spec-launcher":`analytics:surfaces.specLauncher`,proposal:`analytics:surfaces.proposal`,"agent-studio":`analytics:surfaces.agentStudio`,setup:`analytics:surfaces.setup`},n={bg:`bg-muted/40`,text:`text-muted-foreground`,ring:`ring-border/40`,dot:`bg-muted-foreground`},r={job:{bg:`bg-accent-info/15`,text:`text-accent-info`,ring:`ring-accent-info/40`,dot:`bg-accent-info`},"quick-spec":{bg:`bg-accent-secondary/15`,text:`text-accent-secondary`,ring:`ring-accent-secondary/40`,dot:`bg-accent-secondary`},"explore-spec":{bg:`bg-accent-highlight/15`,text:`text-accent-highlight`,ring:`ring-accent-highlight/40`,dot:`bg-accent-highlight`},"ai-edit":{bg:`bg-accent-success/15`,text:`text-accent-success`,ring:`ring-accent-success/40`,dot:`bg-accent-success`},smash:{bg:`bg-accent-highlight/15`,text:`text-accent-highlight`,ring:`ring-accent-highlight/40`,dot:`bg-accent-highlight`},"file-summary":{bg:`bg-accent-warning/15`,text:`text-accent-warning`,ring:`ring-accent-warning/40`,dot:`bg-accent-warning`},loop:{bg:`bg-accent-primary/15`,text:`text-accent-primary`,ring:`ring-accent-primary/40`,dot:`bg-accent-primary`},"chat-sidebar":{bg:`bg-accent-info/15`,text:`text-accent-info`,ring:`ring-accent-info/40`,dot:`bg-accent-info`},"spec-launcher":{bg:`bg-accent-secondary/15`,text:`text-accent-secondary`,ring:`ring-accent-secondary/40`,dot:`bg-accent-secondary`},proposal:{bg:`bg-accent-highlight/15`,text:`text-accent-highlight`,ring:`ring-accent-highlight/40`,dot:`bg-accent-highlight`},"agent-studio":{bg:`bg-accent-success/15`,text:`text-accent-success`,ring:`ring-accent-success/40`,dot:`bg-accent-success`},setup:{bg:`bg-accent-primary/15`,text:`text-accent-primary`,ring:`ring-accent-primary/40`,dot:`bg-accent-primary`}};function i(e,t){return new Proxy(e,{get(e,n,r){return typeof n==`string`&&!(n in e)?t(n):Reflect.get(e,n,r)}})}var a=i(Object.defineProperties({},Object.fromEntries(Object.keys(t).map(n=>[n,{get:()=>e.t(t[n]),enumerable:!0}]))),e=>e),o=i(r,()=>n);export{a as n,o as t};
1
+ import{o as e}from"./i18n-nJQvD5zJ.js";var t={job:`analytics:surfaces.job`,"quick-spec":`analytics:surfaces.quickSpec`,"explore-spec":`analytics:surfaces.exploreSpec`,"ai-edit":`analytics:surfaces.aiEdit`,smash:`analytics:surfaces.smash`,"file-summary":`analytics:surfaces.fileSummary`,loop:`analytics:surfaces.loop`,"chat-sidebar":`analytics:surfaces.chatSidebar`,"spec-launcher":`analytics:surfaces.specLauncher`,proposal:`analytics:surfaces.proposal`,"agent-studio":`analytics:surfaces.agentStudio`,setup:`analytics:surfaces.setup`},n={bg:`bg-muted/40`,text:`text-muted-foreground`,ring:`ring-border/40`,dot:`bg-muted-foreground`},r={job:{bg:`bg-accent-info/15`,text:`text-accent-info`,ring:`ring-accent-info/40`,dot:`bg-accent-info`},"quick-spec":{bg:`bg-accent-secondary/15`,text:`text-accent-secondary`,ring:`ring-accent-secondary/40`,dot:`bg-accent-secondary`},"explore-spec":{bg:`bg-accent-highlight/15`,text:`text-accent-highlight`,ring:`ring-accent-highlight/40`,dot:`bg-accent-highlight`},"ai-edit":{bg:`bg-accent-success/15`,text:`text-accent-success`,ring:`ring-accent-success/40`,dot:`bg-accent-success`},smash:{bg:`bg-accent-highlight/15`,text:`text-accent-highlight`,ring:`ring-accent-highlight/40`,dot:`bg-accent-highlight`},"file-summary":{bg:`bg-accent-warning/15`,text:`text-accent-warning`,ring:`ring-accent-warning/40`,dot:`bg-accent-warning`},loop:{bg:`bg-accent-primary/15`,text:`text-accent-primary`,ring:`ring-accent-primary/40`,dot:`bg-accent-primary`},"chat-sidebar":{bg:`bg-accent-info/15`,text:`text-accent-info`,ring:`ring-accent-info/40`,dot:`bg-accent-info`},"spec-launcher":{bg:`bg-accent-secondary/15`,text:`text-accent-secondary`,ring:`ring-accent-secondary/40`,dot:`bg-accent-secondary`},proposal:{bg:`bg-accent-highlight/15`,text:`text-accent-highlight`,ring:`ring-accent-highlight/40`,dot:`bg-accent-highlight`},"agent-studio":{bg:`bg-accent-success/15`,text:`text-accent-success`,ring:`ring-accent-success/40`,dot:`bg-accent-success`},setup:{bg:`bg-accent-primary/15`,text:`text-accent-primary`,ring:`ring-accent-primary/40`,dot:`bg-accent-primary`}};function i(e,t){return new Proxy(e,{get(e,n,r){return typeof n==`string`&&!(n in e)?t(n):Reflect.get(e,n,r)}})}var a=i(Object.defineProperties({},Object.fromEntries(Object.keys(t).map(n=>[n,{get:()=>e.t(t[n]),enumerable:!0}]))),e=>e),o=i(r,()=>n);export{a as n,o as t};
@@ -0,0 +1 @@
1
+ var e={critical:`Kritisch`,high:`Hoch`,medium:`Mittel`,low:`Niedrig`},t={todo:`To-do`,inProgress:`In Arbeit`,done:`Fertig`,cancelled:`Abgebrochen`,draft:`Entwurf`,onReview:`In Prüfung`},n={manual:`Manuell erstellt`,productBacklog:`Aus dem Product-Backlog`,proposeSpec:`Aus einem Spec-Vorschlag`,getBacklogSpecs:`Aus Backlog-Specs`,freePrompt:`Aus Raw-Prompt`},r={title:`Titel`,description:`Beschreibung`,status:`Status`,priority:`Priorität`,labels:`Labels`,markdownPlaceholder:`Markdown-Beschreibung…`,supportsMarkdown:`Unterstützt Markdown`},i={createdAgo:`Erstellt {{time}}`,updatedAgo:`Aktualisiert {{time}}`},a=`Unbenannt`,o={title:`Ticket löschen`,body:`Möchtest du <strong>#{{id}} {{title}}</strong> wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden.`},s={toast:{updated:`Ticket aktualisiert`,updateFailed:`Ticket konnte nicht aktualisiert werden`,deleteFailed:`Ticket konnte nicht gelöscht werden`},compare:`Vergleichen`,compareTooltip:`Mit einer anderen Spec vergleichen`,doneEditing:`Bearbeitung abschließen`,addDescription:`Beschreibung hinzufügen…`,prerequisites:`Voraussetzungen`,addLabel:`Label hinzufügen`,addLabelPlaceholder:`Label hinzufügen…`,effort:`Aufwand`,assignee:`Zugewiesen an`,continueEditing:`Weiter bearbeiten`,ticketFallbackLabel:`Ticket #{{id}}`},c={title:`Contract Layer`,populated:`{{n}}/5 befüllt`},l={moveToRail:`Auf Rail verschieben`,removeFromRail:`Von Rail entfernen`,currentlyOn:`Aktuell auf {{rail}}`,popoverTitle:`Auf Rail verschieben`,noRails:`Keine Rails verfügbar.`},u={ariaLabel:`Ticket-Aktionen`,deleteTicket:`Ticket löschen`,changeStatus:`Status ändern`,statusOptions:`Statusoptionen`,setPriority:`Priorität festlegen`,priorityOptions:`Prioritätsoptionen`},d={list:`Listenansicht`,grid:`Rasteransicht (Kanban)`,postit:`Post-it-Ansicht`},f={title:`Ticket erstellen`,titlePlaceholder:`Ticket-Titel…`,labelsPlaceholder:`Tippen, um Labels hinzuzufügen…`,create:`Erstellen`,creating:`Wird erstellt…`,toast:{created:`Ticket erstellt`,createFailed:`Ticket konnte nicht erstellt werden`}},p={title:`Vergleichen mit…`,count:`({{n}} Specs)`,searchPlaceholder:`Specs durchsuchen…`,noMatches:`Keine passenden Specs`,empty:`Keine anderen Specs zum Vergleichen`},m={ariaLabel:`Ticket-Ausgaben in Analytics anzeigen`,turns_one:`{{count}} Turn`,turns_other:`{{count}} Turns`,active:`{{duration}} aktiv`,breakdownItem:`{{n}} {{label}}`,estimatedTooltip:`Geschätzt aus der lokalen Preistabelle — dieser Anbieter meldet die Kosten nicht nativ.`,costUnavailableTooltip:`Keiner der Aufrufe dieses Tickets hat Kostentelemetrie bereitgestellt.`,costPartiallyUnavailableTooltip:`Nur bekannte Kosten-Zwischensumme; einige Aufrufe haben keine Kostentelemetrie bereitgestellt.`,turnsUnavailableTooltip:`Die Turn-Telemetrie ist für dieses Ticket nicht verfügbar.`,turnsPartiallyUnavailableTooltip:`Nur bekannte Turn-Zwischensumme; einige Aufrufe haben keine Turn-Telemetrie bereitgestellt.`},h={newTicket:`Neues Ticket: {{title}}`,newTicketsAdded_one:`{{count}} neues Ticket aus der Produkt-Discovery hinzugefügt`,newTicketsAdded_other:`{{count}} neue Tickets aus der Produkt-Discovery hinzugefügt`},g={priority:e,ticketStatus:t,source:n,fields:r,meta:i,untitled:a,deleteDialog:o,detailModal:s,contractLayer:c,rail:l,contextMenu:u,viewMode:d,createModal:f,comparePicker:p,spendingLine:m,toasts:h};export{p as comparePicker,u as contextMenu,c as contractLayer,f as createModal,g as default,o as deleteDialog,s as detailModal,r as fields,i as meta,e as priority,l as rail,n as source,m as spendingLine,t as ticketStatus,h as toasts,a as untitled,d as viewMode};
@@ -0,0 +1 @@
1
+ var e={critical:`Critica`,high:`Alta`,medium:`Media`,low:`Bassa`},t={todo:`Da fare`,inProgress:`In corso`,done:`Completato`,cancelled:`Annullato`,draft:`Bozza`,onReview:`In revisione`},n={manual:`Creato manualmente`,productBacklog:`Dal product backlog`,proposeSpec:`Da proposta di spec`,getBacklogSpecs:`Dalle spec del backlog`,freePrompt:`Da prompt Raw`},r={title:`Titolo`,description:`Descrizione`,status:`Stato`,priority:`Priorità`,labels:`Etichette`,markdownPlaceholder:`Descrizione in Markdown...`,supportsMarkdown:`Supporta Markdown`},i={createdAgo:`Creato {{time}}`,updatedAgo:`Aggiornato {{time}}`},a=`Senza titolo`,o={title:`Elimina ticket`,body:`Vuoi davvero eliminare <strong>#{{id}} {{title}}</strong>? Questa azione è irreversibile.`},s={toast:{updated:`Ticket aggiornato`,updateFailed:`Impossibile aggiornare il ticket`,deleteFailed:`Impossibile eliminare il ticket`},compare:`Confronta`,compareTooltip:`Confronta con un'altra spec`,doneEditing:`Fine modifica`,addDescription:`Aggiungi una descrizione...`,prerequisites:`Prerequisiti`,addLabel:`Aggiungi etichetta`,addLabelPlaceholder:`Aggiungi etichetta...`,effort:`Effort`,assignee:`Assegnatario`,continueEditing:`Continua a modificare`,ticketFallbackLabel:`Ticket #{{id}}`},c={title:`Contract Layer`,populated:`{{n}}/5 compilate`},l={moveToRail:`Sposta su un rail`,removeFromRail:`Rimuovi dal rail`,currentlyOn:`Attualmente su {{rail}}`,popoverTitle:`Sposta su un rail`,noRails:`Nessun rail disponibile.`},u={ariaLabel:`Azioni ticket`,deleteTicket:`Elimina ticket`,changeStatus:`Cambia stato`,statusOptions:`Opzioni di stato`,setPriority:`Imposta priorità`,priorityOptions:`Opzioni di priorità`},d={list:`Vista elenco`,grid:`Vista griglia (Kanban)`,postit:`Vista post-it`},f={title:`Crea ticket`,titlePlaceholder:`Titolo del ticket...`,labelsPlaceholder:`Digita per aggiungere etichette...`,create:`Crea`,creating:`Creazione...`,toast:{created:`Ticket creato`,createFailed:`Impossibile creare il ticket`}},p={title:`Confronta con…`,count:`({{n}} spec)`,searchPlaceholder:`Cerca tra le spec…`,noMatches:`Nessuna spec corrispondente`,empty:`Nessun'altra spec da confrontare`},m={ariaLabel:`Vedi la spesa del ticket in Analytics`,turns_one:`{{count}} turno`,turns_other:`{{count}} turni`,active:`{{duration}} di attività`,breakdownItem:`{{n}} {{label}}`,estimatedTooltip:`Stimato dalla tabella prezzi locale — questo provider non riporta il costo in modo nativo.`,costUnavailableTooltip:`Nessuna invocazione di questo ticket ha esposto telemetria dei costi.`,costPartiallyUnavailableTooltip:`Solo subtotale dei costi noti; alcune invocazioni non hanno esposto il costo.`,turnsUnavailableTooltip:`La telemetria dei turn non è disponibile per questo ticket.`,turnsPartiallyUnavailableTooltip:`Solo subtotale dei turn noti; alcune invocazioni non hanno esposto la telemetria dei turn.`},h={newTicket:`Nuovo ticket: {{title}}`,newTicketsAdded_one:`{{count}} nuovo ticket aggiunto dalla product discovery`,newTicketsAdded_other:`{{count}} nuovi ticket aggiunti dalla product discovery`},g={priority:e,ticketStatus:t,source:n,fields:r,meta:i,untitled:a,deleteDialog:o,detailModal:s,contractLayer:c,rail:l,contextMenu:u,viewMode:d,createModal:f,comparePicker:p,spendingLine:m,toasts:h};export{p as comparePicker,u as contextMenu,c as contractLayer,f as createModal,g as default,o as deleteDialog,s as detailModal,r as fields,i as meta,e as priority,l as rail,n as source,m as spendingLine,t as ticketStatus,h as toasts,a as untitled,d as viewMode};
@@ -0,0 +1 @@
1
+ var e={critical:`Critique`,high:`Haute`,medium:`Moyenne`,low:`Basse`},t={todo:`À faire`,inProgress:`En cours`,done:`Terminé`,cancelled:`Annulé`,draft:`Brouillon`,onReview:`En revue`},n={manual:`Créé manuellement`,productBacklog:`Depuis le product backlog`,proposeSpec:`Depuis une proposition de spec`,getBacklogSpecs:`Depuis les specs du backlog`,freePrompt:`Depuis un prompt Raw`},r={title:`Titre`,description:`Description`,status:`Statut`,priority:`Priorité`,labels:`Labels`,markdownPlaceholder:`Description en Markdown…`,supportsMarkdown:`Markdown pris en charge`},i={createdAgo:`Créé {{time}}`,updatedAgo:`Mis à jour {{time}}`},a=`Sans titre`,o={title:`Supprimer le ticket`,body:`Voulez-vous vraiment supprimer <strong>#{{id}} {{title}}</strong> ? Cette action est irréversible.`},s={toast:{updated:`Ticket mis à jour`,updateFailed:`Échec de la mise à jour du ticket`,deleteFailed:`Échec de la suppression du ticket`},compare:`Comparer`,compareTooltip:`Comparer avec une autre spec`,doneEditing:`Terminer l'édition`,addDescription:`Ajouter une description…`,prerequisites:`Prérequis`,addLabel:`Ajouter un label`,addLabelPlaceholder:`Ajouter un label…`,effort:`Effort`,assignee:`Assigné à`,continueEditing:`Continuer l'édition`,ticketFallbackLabel:`Ticket #{{id}}`},c={title:`Contract Layer`,populated:`{{n}}/5 renseignés`},l={moveToRail:`Déplacer vers un rail`,removeFromRail:`Retirer du rail`,currentlyOn:`Actuellement sur {{rail}}`,popoverTitle:`Déplacer vers un rail`,noRails:`Aucun rail disponible.`},u={ariaLabel:`Actions du ticket`,deleteTicket:`Supprimer le ticket`,changeStatus:`Changer le statut`,statusOptions:`Options de statut`,setPriority:`Définir la priorité`,priorityOptions:`Options de priorité`},d={list:`Vue liste`,grid:`Vue grille (Kanban)`,postit:`Vue post-it`},f={title:`Créer un ticket`,titlePlaceholder:`Titre du ticket…`,labelsPlaceholder:`Saisissez pour ajouter des labels…`,create:`Créer`,creating:`Création…`,toast:{created:`Ticket créé`,createFailed:`Échec de la création du ticket`}},p={title:`Comparer avec…`,count:`({{n}} specs)`,searchPlaceholder:`Rechercher des specs…`,noMatches:`Aucune spec correspondante`,empty:`Aucune autre spec à comparer`},m={ariaLabel:`Voir les dépenses du ticket dans Analytics`,turns_one:`{{count}} tour`,turns_other:`{{count}} tours`,active:`{{duration}} actif`,breakdownItem:`{{n}} {{label}}`,estimatedTooltip:`Estimé à partir de la table de tarifs locale — ce fournisseur ne signale pas le coût de manière native.`,costUnavailableTooltip:`Aucune invocation de ce ticket n'a exposé de télémétrie de coût.`,costPartiallyUnavailableTooltip:`Sous-total des coûts connus uniquement ; certaines invocations n'ont pas exposé leur coût.`,turnsUnavailableTooltip:`La télémétrie des tours est indisponible pour ce ticket.`,turnsPartiallyUnavailableTooltip:`Sous-total des tours connus uniquement ; certaines invocations n'ont pas exposé leur télémétrie des tours.`},h={newTicket:`Nouveau ticket : {{title}}`,newTicketsAdded_one:`{{count}} nouveau ticket ajouté depuis la product discovery`,newTicketsAdded_other:`{{count}} nouveaux tickets ajoutés depuis la product discovery`},g={priority:e,ticketStatus:t,source:n,fields:r,meta:i,untitled:a,deleteDialog:o,detailModal:s,contractLayer:c,rail:l,contextMenu:u,viewMode:d,createModal:f,comparePicker:p,spendingLine:m,toasts:h};export{p as comparePicker,u as contextMenu,c as contractLayer,f as createModal,g as default,o as deleteDialog,s as detailModal,r as fields,i as meta,e as priority,l as rail,n as source,m as spendingLine,t as ticketStatus,h as toasts,a as untitled,d as viewMode};
@@ -0,0 +1 @@
1
+ var e={critical:`Crítica`,high:`Alta`,medium:`Media`,low:`Baja`},t={todo:`Por hacer`,inProgress:`En curso`,done:`Hecho`,cancelled:`Cancelado`,draft:`Borrador`,onReview:`En revisión`},n={manual:`Creado manualmente`,productBacklog:`Desde el product backlog`,proposeSpec:`Desde una propuesta de spec`,getBacklogSpecs:`Desde specs del backlog`,freePrompt:`Desde un prompt Raw`},r={title:`Título`,description:`Descripción`,status:`Estado`,priority:`Prioridad`,labels:`Etiquetas`,markdownPlaceholder:`Descripción en Markdown...`,supportsMarkdown:`Admite Markdown`},i={createdAgo:`Creado {{time}}`,updatedAgo:`Actualizado {{time}}`},a=`Sin título`,o={title:`Eliminar ticket`,body:`¿Seguro que quieres eliminar <strong>#{{id}} {{title}}</strong>? Esta acción no se puede deshacer.`},s={toast:{updated:`Ticket actualizado`,updateFailed:`No se pudo actualizar el ticket`,deleteFailed:`No se pudo eliminar el ticket`},compare:`Comparar`,compareTooltip:`Comparar con otra spec`,doneEditing:`Terminar edición`,addDescription:`Añadir una descripción...`,prerequisites:`Requisitos previos`,addLabel:`Añadir etiqueta`,addLabelPlaceholder:`Añadir etiqueta...`,effort:`Esfuerzo`,assignee:`Asignado a`,continueEditing:`Seguir editando`,ticketFallbackLabel:`Ticket #{{id}}`},c={title:`Contract Layer`,populated:`{{n}}/5 con contenido`},l={moveToRail:`Mover a un rail`,removeFromRail:`Quitar del rail`,currentlyOn:`Actualmente en {{rail}}`,popoverTitle:`Mover a un rail`,noRails:`No hay rails disponibles.`},u={ariaLabel:`Acciones del ticket`,deleteTicket:`Eliminar ticket`,changeStatus:`Cambiar estado`,statusOptions:`Opciones de estado`,setPriority:`Establecer prioridad`,priorityOptions:`Opciones de prioridad`},d={list:`Vista de lista`,grid:`Vista de cuadrícula (Kanban)`,postit:`Vista post-it`},f={title:`Crear ticket`,titlePlaceholder:`Título del ticket...`,labelsPlaceholder:`Escribe para añadir etiquetas...`,create:`Crear`,creating:`Creando...`,toast:{created:`Ticket creado`,createFailed:`No se pudo crear el ticket`}},p={title:`Comparar con…`,count:`({{n}} specs)`,searchPlaceholder:`Buscar specs…`,noMatches:`Ninguna spec coincide`,empty:`No hay otras specs para comparar`},m={ariaLabel:`Ver el gasto del ticket en Analíticas`,turns_one:`{{count}} turno`,turns_other:`{{count}} turnos`,active:`{{duration}} activo`,breakdownItem:`{{n}} {{label}}`,estimatedTooltip:`Estimado a partir de la tabla de precios local — este proveedor no informa el coste de forma nativa.`,costUnavailableTooltip:`Ninguna invocación de este ticket expuso telemetría de coste.`,costPartiallyUnavailableTooltip:`Solo subtotal de coste conocido; algunas invocaciones no expusieron telemetría.`,turnsUnavailableTooltip:`La telemetría de turnos no está disponible para este ticket.`,turnsPartiallyUnavailableTooltip:`Solo subtotal de turnos conocido; algunas invocaciones no expusieron telemetría.`},h={newTicket:`Nuevo ticket: {{title}}`,newTicketsAdded_one:`{{count}} ticket nuevo añadido desde product discovery`,newTicketsAdded_other:`{{count}} tickets nuevos añadidos desde product discovery`},g={priority:e,ticketStatus:t,source:n,fields:r,meta:i,untitled:a,deleteDialog:o,detailModal:s,contractLayer:c,rail:l,contextMenu:u,viewMode:d,createModal:f,comparePicker:p,spendingLine:m,toasts:h};export{p as comparePicker,u as contextMenu,c as contractLayer,f as createModal,g as default,o as deleteDialog,s as detailModal,r as fields,i as meta,e as priority,l as rail,n as source,m as spendingLine,t as ticketStatus,h as toasts,a as untitled,d as viewMode};
@@ -0,0 +1 @@
1
+ var e={critical:`Crítica`,high:`Alta`,medium:`Média`,low:`Baixa`},t={todo:`Por fazer`,inProgress:`Em curso`,done:`Concluído`,cancelled:`Cancelado`,draft:`Rascunho`,onReview:`Em revisão`},n={manual:`Criado manualmente`,productBacklog:`Do product backlog`,proposeSpec:`De proposta de spec`,getBacklogSpecs:`De specs do backlog`,freePrompt:`De prompt Raw`},r={title:`Título`,description:`Descrição`,status:`Estado`,priority:`Prioridade`,labels:`Etiquetas`,markdownPlaceholder:`Descrição em Markdown...`,supportsMarkdown:`Suporta Markdown`},i={createdAgo:`Criado {{time}}`,updatedAgo:`Atualizado {{time}}`},a=`Sem título`,o={title:`Eliminar ticket`,body:`Tem a certeza de que quer eliminar <strong>#{{id}} {{title}}</strong>? Esta ação não pode ser anulada.`},s={toast:{updated:`Ticket atualizado`,updateFailed:`Falha ao atualizar o ticket`,deleteFailed:`Falha ao eliminar o ticket`},compare:`Comparar`,compareTooltip:`Comparar com outra spec`,doneEditing:`Terminar edição`,addDescription:`Adicionar uma descrição...`,prerequisites:`Pré-requisitos`,addLabel:`Adicionar etiqueta`,addLabelPlaceholder:`Adicionar etiqueta...`,effort:`Esforço`,assignee:`Responsável`,continueEditing:`Continuar a editar`,ticketFallbackLabel:`Ticket #{{id}}`},c={title:`Contract Layer`,populated:`{{n}}/5 preenchidas`},l={moveToRail:`Mover para um rail`,removeFromRail:`Remover do rail`,currentlyOn:`Atualmente em {{rail}}`,popoverTitle:`Mover para um rail`,noRails:`Nenhum rail disponível.`},u={ariaLabel:`Ações do ticket`,deleteTicket:`Eliminar ticket`,changeStatus:`Alterar estado`,statusOptions:`Opções de estado`,setPriority:`Definir prioridade`,priorityOptions:`Opções de prioridade`},d={list:`Vista de lista`,grid:`Vista de grelha (Kanban)`,postit:`Vista de post-its`},f={title:`Criar ticket`,titlePlaceholder:`Título do ticket...`,labelsPlaceholder:`Escreva para adicionar etiquetas...`,create:`Criar`,creating:`A criar...`,toast:{created:`Ticket criado`,createFailed:`Falha ao criar o ticket`}},p={title:`Comparar com…`,count:`({{n}} specs)`,searchPlaceholder:`Pesquisar specs…`,noMatches:`Nenhuma spec corresponde`,empty:`Não há outras specs para comparar`},m={ariaLabel:`Ver os gastos do ticket em Analytics`,turns_one:`{{count}} turno`,turns_other:`{{count}} turnos`,active:`{{duration}} ativo`,breakdownItem:`{{n}} {{label}}`,estimatedTooltip:`Estimado a partir da tabela de preços local — este provedor não informa o custo nativamente.`,costUnavailableTooltip:`Nenhuma invocação deste ticket forneceu telemetria de custo.`,costPartiallyUnavailableTooltip:`Apenas o subtotal conhecido de custo; algumas invocações não forneceram telemetria de custo.`,turnsUnavailableTooltip:`A telemetria de turnos está indisponível para este ticket.`,turnsPartiallyUnavailableTooltip:`Apenas o subtotal conhecido de turnos; algumas invocações não forneceram telemetria de turnos.`},h={newTicket:`Novo ticket: {{title}}`,newTicketsAdded_one:`{{count}} novo ticket adicionado a partir da descoberta de produto`,newTicketsAdded_other:`{{count}} novos tickets adicionados a partir da descoberta de produto`},g={priority:e,ticketStatus:t,source:n,fields:r,meta:i,untitled:a,deleteDialog:o,detailModal:s,contractLayer:c,rail:l,contextMenu:u,viewMode:d,createModal:f,comparePicker:p,spendingLine:m,toasts:h};export{p as comparePicker,u as contextMenu,c as contractLayer,f as createModal,g as default,o as deleteDialog,s as detailModal,r as fields,i as meta,e as priority,l as rail,n as source,m as spendingLine,t as ticketStatus,h as toasts,a as untitled,d as viewMode};
@@ -0,0 +1 @@
1
+ var e={critical:`紧急`,high:`高`,medium:`中`,low:`低`},t={todo:`待办`,inProgress:`进行中`,done:`完成`,cancelled:`已取消`,draft:`草稿`,onReview:`审核中`},n={manual:`手动创建`,productBacklog:`来自产品 backlog`,proposeSpec:`来自 spec 提案`,getBacklogSpecs:`来自 backlog spec`,freePrompt:`来自 Raw prompt`},r={title:`标题`,description:`描述`,status:`状态`,priority:`优先级`,labels:`标签`,markdownPlaceholder:`Markdown 描述…`,supportsMarkdown:`支持 Markdown`},i={createdAgo:`创建于 {{time}}`,updatedAgo:`更新于 {{time}}`},a=`未命名`,o={title:`删除工单`,body:`确定要删除 <strong>#{{id}} {{title}}</strong> 吗?此操作无法撤销。`},s={toast:{updated:`工单已更新`,updateFailed:`更新工单失败`,deleteFailed:`删除工单失败`},compare:`对比`,compareTooltip:`与另一个 spec 对比`,doneEditing:`完成编辑`,addDescription:`添加描述…`,prerequisites:`前置条件`,addLabel:`添加标签`,addLabelPlaceholder:`添加标签…`,effort:`工作量`,assignee:`负责人`,continueEditing:`继续编辑`,ticketFallbackLabel:`工单 #{{id}}`},c={title:`Contract Layer`,populated:`已填充 {{n}}/5`},l={moveToRail:`放入 Rail`,removeFromRail:`从 Rail 移除`,currentlyOn:`当前位于 {{rail}}`,popoverTitle:`放入 rail`,noRails:`没有可用的 rail。`},u={ariaLabel:`工单操作`,deleteTicket:`删除工单`,changeStatus:`更改状态`,statusOptions:`状态选项`,setPriority:`设置优先级`,priorityOptions:`优先级选项`},d={list:`列表视图`,grid:`网格视图(看板)`,postit:`便签视图`},f={title:`创建工单`,titlePlaceholder:`工单标题…`,labelsPlaceholder:`输入以添加标签…`,create:`创建`,creating:`正在创建…`,toast:{created:`工单已创建`,createFailed:`创建工单失败`}},p={title:`选择对比对象…`,count:`({{n}} 个 spec)`,searchPlaceholder:`搜索 spec…`,noMatches:`没有匹配的 spec`,empty:`没有其他可对比的 spec`},m={ariaLabel:`在分析页查看此工单的支出`,turns_one:`{{count}} 轮`,turns_other:`{{count}} 轮`,active:`活跃 {{duration}}`,breakdownItem:`{{n}} {{label}}`,estimatedTooltip:`根据本地价格表估算 — 此提供商不原生报告成本。`,costUnavailableTooltip:`此工单的所有调用均未提供成本遥测数据。`,costPartiallyUnavailableTooltip:`仅显示已知成本小计;部分调用未提供成本遥测数据。`,turnsUnavailableTooltip:`此工单的轮次遥测数据不可用。`,turnsPartiallyUnavailableTooltip:`仅显示已知轮次小计;部分调用未提供轮次遥测数据。`},h={newTicket:`新工单:{{title}}`,newTicketsAdded_one:`已从产品发现新增 {{count}} 个工单`,newTicketsAdded_other:`已从产品发现新增 {{count}} 个工单`},g={priority:e,ticketStatus:t,source:n,fields:r,meta:i,untitled:a,deleteDialog:o,detailModal:s,contractLayer:c,rail:l,contextMenu:u,viewMode:d,createModal:f,comparePicker:p,spendingLine:m,toasts:h};export{p as comparePicker,u as contextMenu,c as contractLayer,f as createModal,g as default,o as deleteDialog,s as detailModal,r as fields,i as meta,e as priority,l as rail,n as source,m as spendingLine,t as ticketStatus,h as toasts,a as untitled,d as viewMode};
@@ -0,0 +1 @@
1
+ import{r as e}from"./rolldown-runtime-CNC7AqOf.js";var t=e({comparePicker:()=>h,contextMenu:()=>f,contractLayer:()=>u,createModal:()=>m,default:()=>v,deleteDialog:()=>c,detailModal:()=>l,fields:()=>a,meta:()=>o,priority:()=>n,rail:()=>d,source:()=>i,spendingLine:()=>g,ticketStatus:()=>r,toasts:()=>_,untitled:()=>s,viewMode:()=>p}),n={critical:`Critical`,high:`High`,medium:`Medium`,low:`Low`},r={todo:`Todo`,inProgress:`In Progress`,done:`Done`,cancelled:`Cancelled`,draft:`Draft`,onReview:`On review`},i={manual:`Created manually`,productBacklog:`From product backlog`,proposeSpec:`From spec proposal`,getBacklogSpecs:`From backlog specs`,freePrompt:`From Raw prompt`},a={title:`Title`,description:`Description`,status:`Status`,priority:`Priority`,labels:`Labels`,markdownPlaceholder:`Markdown description...`,supportsMarkdown:`Supports markdown`},o={createdAgo:`Created {{time}}`,updatedAgo:`Updated {{time}}`},s=`Untitled`,c={title:`Delete ticket`,body:`Are you sure you want to delete <strong>#{{id}} {{title}}</strong>? This action cannot be undone.`},l={toast:{updated:`Ticket updated`,updateFailed:`Failed to update ticket`,deleteFailed:`Failed to delete ticket`},compare:`Compare`,compareTooltip:`Compare with another spec`,doneEditing:`Done editing`,addDescription:`Add a description...`,prerequisites:`Prerequisites`,addLabel:`Add label`,addLabelPlaceholder:`Add label...`,effort:`Effort`,assignee:`Assignee`,continueEditing:`Continue Editing`,ticketFallbackLabel:`Ticket #{{id}}`},u={title:`Contract Layer`,populated:`{{n}}/5 populated`},d={moveToRail:`Move to Rail`,removeFromRail:`Remove from Rail`,currentlyOn:`Currently on {{rail}}`,popoverTitle:`Move to rail`,noRails:`No rails available.`},f={ariaLabel:`Ticket actions`,deleteTicket:`Delete ticket`,changeStatus:`Change status`,statusOptions:`Status options`,setPriority:`Set priority`,priorityOptions:`Priority options`},p={list:`List view`,grid:`Grid view (Kanban)`,postit:`Post-it view`},m={title:`Create Ticket`,titlePlaceholder:`Ticket title...`,labelsPlaceholder:`Type to add labels...`,create:`Create`,creating:`Creating...`,toast:{created:`Ticket created`,createFailed:`Failed to create ticket`}},h={title:`Compare with…`,count:`({{n}} specs)`,searchPlaceholder:`Search specs…`,noMatches:`No matching specs`,empty:`No other specs to compare`},g={ariaLabel:`View ticket spending in Analytics`,turns_one:`{{count}} turn`,turns_other:`{{count}} turns`,active:`{{duration}} active`,breakdownItem:`{{n}} {{label}}`,estimatedTooltip:`Estimated from the local pricing table — this provider does not report cost natively.`,costUnavailableTooltip:`None of this ticket's invocations exposed cost telemetry.`,costPartiallyUnavailableTooltip:`Known cost subtotal only; some invocations did not expose cost telemetry.`,turnsUnavailableTooltip:`Turn telemetry is unavailable for this ticket.`,turnsPartiallyUnavailableTooltip:`Known turn subtotal only; some invocations did not expose turn telemetry.`},_={newTicket:`New ticket: {{title}}`,newTicketsAdded_one:`{{count}} new ticket added from product discovery`,newTicketsAdded_other:`{{count}} new tickets added from product discovery`},v={priority:n,ticketStatus:r,source:i,fields:a,meta:o,untitled:s,deleteDialog:c,detailModal:l,contractLayer:u,rail:d,contextMenu:f,viewMode:p,createModal:m,comparePicker:h,spendingLine:g,toasts:_};export{t};
@@ -0,0 +1 @@
1
+ var e={critical:`クリティカル`,high:`高`,medium:`中`,low:`低`},t={todo:`Todo`,inProgress:`進行中`,done:`完了`,cancelled:`キャンセル`,draft:`下書き`,onReview:`レビュー中`},n={manual:`手動で作成`,productBacklog:`プロダクトバックログから`,proposeSpec:`スペック提案から`,getBacklogSpecs:`バックログスペックから`,freePrompt:`Raw プロンプトから`},r={title:`タイトル`,description:`説明`,status:`ステータス`,priority:`優先度`,labels:`ラベル`,markdownPlaceholder:`Markdown で説明...`,supportsMarkdown:`Markdown 対応`},i={createdAgo:`{{time}}に作成`,updatedAgo:`{{time}}に更新`},a=`無題`,o={title:`チケットを削除`,body:`<strong>#{{id}} {{title}}</strong> を削除してもよろしいですか?この操作は元に戻せません。`},s={toast:{updated:`チケットを更新しました`,updateFailed:`チケットの更新に失敗しました`,deleteFailed:`チケットの削除に失敗しました`},compare:`比較`,compareTooltip:`別のスペックと比較`,doneEditing:`編集を終了`,addDescription:`説明を追加...`,prerequisites:`前提条件`,addLabel:`ラベルを追加`,addLabelPlaceholder:`ラベルを追加...`,effort:`工数`,assignee:`担当者`,continueEditing:`編集を続ける`,ticketFallbackLabel:`チケット #{{id}}`},c={title:`Contract Layer`,populated:`{{n}}/5 件入力済み`},l={moveToRail:`レールに移動`,removeFromRail:`レールから削除`,currentlyOn:`現在 {{rail}} 上にあります`,popoverTitle:`レールに移動`,noRails:`利用可能なレールがありません。`},u={ariaLabel:`チケット操作`,deleteTicket:`チケットを削除`,changeStatus:`ステータスを変更`,statusOptions:`ステータスオプション`,setPriority:`優先度を設定`,priorityOptions:`優先度オプション`},d={list:`リスト表示`,grid:`グリッド表示(カンバン)`,postit:`付箋表示`},f={title:`チケットを作成`,titlePlaceholder:`チケットのタイトル...`,labelsPlaceholder:`入力してラベルを追加...`,create:`作成`,creating:`作成中...`,toast:{created:`チケットを作成しました`,createFailed:`チケットの作成に失敗しました`}},p={title:`比較対象を選択…`,count:`(スペック {{n}} 件)`,searchPlaceholder:`スペックを検索…`,noMatches:`一致するスペックはありません`,empty:`比較できる他のスペックはありません`},m={ariaLabel:`アナリティクスでチケットの支出を表示`,turns_one:`{{count}} ターン`,turns_other:`{{count}} ターン`,active:`アクティブ {{duration}}`,breakdownItem:`{{n}} {{label}}`,estimatedTooltip:`ローカルの料金表からの推定値 — このプロバイダーはコストをネイティブに報告しません。`,costUnavailableTooltip:`このチケットの呼び出しではコストのテレメトリが提供されませんでした。`,costPartiallyUnavailableTooltip:`既知のコスト小計のみです。一部の呼び出しではコストのテレメトリが提供されませんでした。`,turnsUnavailableTooltip:`このチケットではターンのテレメトリを利用できません。`,turnsPartiallyUnavailableTooltip:`既知のターン小計のみです。一部の呼び出しではターンのテレメトリが提供されませんでした。`},h={newTicket:`新しいチケット: {{title}}`,newTicketsAdded_one:`プロダクトディスカバリーから {{count}} 件の新しいチケットを追加しました`,newTicketsAdded_other:`プロダクトディスカバリーから {{count}} 件の新しいチケットを追加しました`},g={priority:e,ticketStatus:t,source:n,fields:r,meta:i,untitled:a,deleteDialog:o,detailModal:s,contractLayer:c,rail:l,contextMenu:u,viewMode:d,createModal:f,comparePicker:p,spendingLine:m,toasts:h};export{p as comparePicker,u as contextMenu,c as contractLayer,f as createModal,g as default,o as deleteDialog,s as detailModal,r as fields,i as meta,e as priority,l as rail,n as source,m as spendingLine,t as ticketStatus,h as toasts,a as untitled,d as viewMode};
@@ -1 +1 @@
1
- import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{n as t}from"./jsx-runtime-zu2_FqZY.js";import{o as n}from"./i18n-Ch-Db_x2.js";import{t as r}from"./createLucideIcon-Bjbbp_KS.js";import{a as i,n as a}from"./auth-D_5bQv5W.js";import{t as o}from"./api-B2M7CtDw.js";var s=r(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]),c=r(`globe`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20`,key:`13o1zl`}],[`path`,{d:`M2 12h20`,key:`9i4pu4`}]]),l=r(`rotate-cw`,[[`path`,{d:`M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8`,key:`1p45f6`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}]]),u=e(t(),1);function d(){return typeof window<`u`&&`__TAURI_INTERNALS__`in window||typeof window<`u`&&window.location.protocol!==`http:`&&window.location.protocol!==`https:`?`ws://localhost:4200`:`${window.location.protocol===`https:`?`wss:`:`ws:`}//${window.location.host}`}var f=d();function p(){let e={BASE_URL:`/`,DEV:!1,MODE:`production`,PROD:!0,SSR:!1}.VITE_FEATURE_BROWSER_CAPTURE;return typeof e!=`string`||e!==`false`}var m={desktop:{width:1280,height:800},tablet:{width:768,height:1024},mobile:{width:375,height:667}},h=class extends Error{},g=class extends Error{};function _(e){if(!e)throw Error(`A project owner is required for browser sessions`);return`${i}/api/projects/${encodeURIComponent(e)}`}async function v(e,t){let n=await fetch(`${_(e)}/browser/sessions`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({initialUrl:t})});if(n.status===409)throw new h(`Too many open browser sessions`);if(n.status===502)throw new g(`The browser failed to launch`);if(!n.ok)throw Error(`Failed to open browser (${n.status})`);return(await n.json()).session}async function y(e,t,n,r){let i=await fetch(`${_(e)}/browser/sessions/${t}/navigate`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:n,url:r})});if(!i.ok)throw Error(`Navigation failed (${i.status})`);return await i.json()}async function b(e,t,n,r,i){let a=await fetch(`${_(e)}/browser/sessions/${t}/capture`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({rect:n,pendingSpecId:r,captureNetwork:i?.captureNetwork??!0})});if(!a.ok)throw Error(await x(a));return await a.json()}async function x(e){let t=await e.json().then(e=>e.error).catch(()=>void 0);return t?`Capture failed (${e.status}): ${t}`:`Capture failed (${e.status})`}async function S(e,t,n,r,i,a=m){let o=await fetch(`${_(e)}/browser/sessions/${t}/capture-breakpoints`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({rect:n,anchorPoint:r,pendingSpecId:i,breakpoints:a})});if(!o.ok)throw Error(await x(o));return await o.json()}async function C(e,t,n){let r=new FormData;r.append(`file`,t,n);let i=await fetch(`${o()}/tickets/${e}/attachments`,{method:`POST`,body:r});if(!i.ok)throw Error(`Upload failed (${i.status})`);return(await i.json()).attachment}async function w(e,t,n,r){let i=await fetch(`${_(e)}/browser/sessions/${t}/clipboard`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:n,text:r})});if(!i.ok)throw Error(`Clipboard failed (${i.status})`);return await i.json()}async function T(e,t,n,r){let i=await fetch(`${_(e)}/browser/sessions/${t}/element`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({selector:n,direction:r})});if(!i.ok)throw Error(`Element navigate failed (${i.status})`);return(await i.json()).probe}async function E(e,t,n){try{await fetch(`${_(e)}/browser/sessions/${t}/popup-view`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({target:n})})}catch{}}function D(e){if(!e||e===`about:blank`)return`…`;try{return new URL(e).hostname||`…`}catch{return`…`}}async function O(e,t){try{await fetch(`${_(e)}/browser/sessions/${t}`,{method:`DELETE`})}catch{}}function k(e,t){return`${f||(typeof window<`u`?`${window.location.protocol===`https:`?`wss:`:`ws:`}//${window.location.host}`:`ws://localhost:4200`)}/ws/browser/${e}?projectId=${encodeURIComponent(t)}`}function A(e,t){let n=k(e,t),r=a(),i=r?new WebSocket(n,[`specrails-desktop`,r]):new WebSocket(n);return i.binaryType=`arraybuffer`,i}function j(e,t=e=>requestAnimationFrame(e),n=e=>cancelAnimationFrame(e)){let r=null,i=null,a=null,o=!1,s=()=>{a!=null&&(n(a),a=null);let t=r,o=i;r=null,i=null,t&&(!o||t.x!==o.x||t.y!==o.y)&&e({type:`mouse`,action:`move`,x:t.x,y:t.y}),o&&e({type:`wheel`,x:o.x,y:o.y,deltaX:o.deltaX,deltaY:o.deltaY})},c=()=>{a==null&&!o&&(a=t(()=>{a=null,s()}))};return{move(e,t){o||(r={x:e,y:t},c())},wheel(e,t,n,r){o||(i?(i.x=e,i.y=t,i.deltaX+=n,i.deltaY+=r):i={x:e,y:t,deltaX:n,deltaY:r},c())},flush(){o||s()},dispose(){o||(o=!0,a!=null&&(n(a),a=null),r=null,i=null)}}}function M(e,t,n){let r=t.width>0?(e.x-t.left)/t.width:0,i=t.height>0?(e.y-t.top)/t.height:0,a=Math.min(Math.max(r,0),1)*n.width,o=Math.min(Math.max(i,0),1)*n.height;return{x:Math.round(a),y:Math.round(o)}}function N(e,t,n){let r=n.width>0?t.width/n.width:0,i=n.height>0?t.height/n.height:0;return{left:t.left+e.x*r,top:t.top+e.y*i,width:e.width*r,height:e.height*i}}function P(e,t){return{x:Math.min(e.x,t.x),y:Math.min(e.y,t.y),width:Math.abs(e.x-t.x),height:Math.abs(e.y-t.y)}}function F(e,t=8){return e.width>=t&&e.height>=t}function I(e,t){let n=Math.max(1,t.width),r=Math.max(1,t.height),i=Math.max(0,Math.min(e.x,n-1)),a=Math.max(0,Math.min(e.y,r-1)),o=Math.min(n,Math.max(i+1,e.x+e.width)),s=Math.min(r,Math.max(a+1,e.y+e.height));return{x:Math.round(i),y:Math.round(a),width:Math.round(o-i),height:Math.round(s-a)}}function L(e){return{nodeCount:e.nodes.length,htmlBytes:e.html.length,truncated:e.htmlTruncated,networkCount:e.networkRequests?.length??0}}function R(e){let t=e.schedule??(e=>requestAnimationFrame(e)),n=e.cancel??(e=>cancelAnimationFrame(e)),r=e.now??(()=>typeof performance<`u`?performance.now():Date.now()),i=e.release??(()=>{}),a={received:0,decoded:0,drawn:0,droppedStale:0,droppedUndrawn:0,decodeMsTotal:0,drawMsTotal:0},o=!1,s=!1,c=null,l=null,u=null,d=()=>{u=null;let t=l;if(l=null,t==null||o){t!=null&&f(t);return}let n=r();try{e.draw(t),a.drawn++,a.drawMsTotal+=r()-n}catch{}finally{f(t)}},f=e=>{try{i(e)}catch{}},p=()=>{u==null&&!o&&(u=t(d))},m=t=>{s=!0;let n=r();e.decode(t).then(e=>{if(o){f(e);return}a.decoded++,a.decodeMsTotal+=r()-n,l!=null&&(a.droppedUndrawn++,f(l)),l=e,p(),h()},()=>{h()})},h=()=>{if(o){s=!1;return}let e=c;c=null,e==null?s=!1:m(e)};return{push(e){if(!o){if(a.received++,s){c!=null&&a.droppedStale++,c=e;return}m(e)}},stats(){return{...a}},dispose(){if(!o){if(o=!0,c=null,u!=null){try{n(u)}catch{}u=null}l!=null&&(f(l),l=null)}}}}var z=`specrails-desktop:browser-capture-debug`;function B(){try{return typeof localStorage<`u`&&localStorage.getItem(z)===`1`}catch{return!1}}function V(e,t,n){let r=Math.max(1,n),i=t.decoded-e.decoded,a=t.drawn-e.drawn,o=e=>Math.round(e*10)/10;return{fpsReceived:o((t.received-e.received)*1e3/r),fpsDrawn:o(a*1e3/r),droppedStale:t.droppedStale-e.droppedStale,droppedUndrawn:t.droppedUndrawn-e.droppedUndrawn,avgDecodeMs:i>0?o((t.decodeMsTotal-e.decodeMsTotal)/i):0,avgDrawMs:a>0?o((t.drawMsTotal-e.drawMsTotal)/a):0}}function H(e,t=e=>console.table([e]),n=2e3,r=()=>Date.now()){let i=e(),a=r(),o=setInterval(()=>{let n=e(),o=r();t(V(i,n,o-a)),i=n,a=o},n);return()=>clearInterval(o)}function U(e){let{projectId:t,open:r,initialUrl:i}=e,a=(0,u.useRef)(null),o=(0,u.useRef)(null),s=(0,u.useRef)(null),c=(0,u.useRef)(0),l=(0,u.useRef)(new Map),d=(0,u.useCallback)(()=>{if(c.current!==0||l.current.size===0)return;let e=[...l.current.values()];l.current.clear();for(let t of e)O(t.projectId,t.sessionId)},[]),[f,p]=(0,u.useState)({status:`connecting`,errorMsg:null,url:null,title:null,viewport:{width:1280,height:800},hoverRect:null,hoverSelector:null,hoverPath:null,popup:null});(0,u.useEffect)(()=>{if(!r||!t)return;let e=!1,u=null;p(e=>({...e,status:`connecting`,errorMsg:null,popup:null}));let d=R({decode:e=>createImageBitmap(new Blob([e],{type:`image/jpeg`})),draw:e=>{let t=a.current;t&&(t.width!==e.width&&(t.width=e.width),t.height!==e.height&&(t.height=e.height),t.getContext(`2d`)?.drawImage(e,0,0))},release:e=>e.close()}),f=B()?H(()=>d.stats()):null;return(async()=>{try{let r=await v(t,i);if(e){O(t,r.id);return}u=r.id,s.current={id:r.id,projectId:t},p(e=>({...e,url:r.url,title:r.title,viewport:{width:r.viewportWidth,height:r.viewportHeight}}));let a=A(r.id,t);o.current=a,a.onmessage=e=>{if(typeof e.data==`string`){try{let t=JSON.parse(e.data);if(t.type===`ready`)p(e=>({...e,status:`ready`,url:t.url??e.url,title:t.title??e.title,viewport:t.viewport??e.viewport}));else if(t.type===`nav`)p(e=>({...e,url:t.url??e.url,title:t.title??e.title}));else if(t.type===`hover`)p(e=>({...e,hoverRect:t.rect??null,hoverSelector:t.selector??null,hoverPath:t.path??null}));else if(t.type===`popup`){let e=typeof t.count==`number`?t.count:0;p(n=>({...n,popup:e>0?{count:e,active:t.active===!0,url:t.url??null}:null}))}}catch{}return}d.push(e.data)},a.onopen=()=>{e||p(e=>({...e,status:`ready`}))},a.onerror=()=>{e||p(e=>({...e,status:`error`,errorMsg:n.t(`browser:session.connectionError`)}))},a.onclose=()=>{e||p(e=>e.status===`ready`?{...e,status:`error`,errorMsg:n.t(`browser:session.lostConnection`)}:e)}}catch(t){if(e)return;let r=t instanceof h?n.t(`browser:session.tooManySessions`):t instanceof g?n.t(`browser:session.launchFailed`):n.t(`browser:session.openFailed`);p(e=>({...e,status:`error`,errorMsg:r}))}})(),()=>{e=!0,f?.(),d.dispose();let n=o.current;if(n){n.onmessage=null,n.onopen=null,n.onerror=null,n.onclose=null;try{n.close()}catch{}}o.current=null;let r=u;r&&s.current?.id===r&&s.current.projectId===t&&(s.current=null),r&&(c.current>0?l.current.set(`${t}\0${r}`,{sessionId:r,projectId:t}):O(t,r))}},[r,t,i,d]);let m=(0,u.useCallback)(e=>{let t=o.current;if(t&&t.readyState===WebSocket.OPEN)try{t.send(JSON.stringify({type:`input`,event:e}))}catch{}},[]),_=(0,u.useCallback)(async(e,t)=>{let n=s.current;if(n)try{let r=await y(n.projectId,n.id,e,t);if(s.current?.id!==n.id||s.current.projectId!==n.projectId)return;p(e=>({...e,url:r.url,title:r.title}))}catch{}},[]),x=(0,u.useCallback)(async(e,t,n)=>{let r=s.current;if(!r)throw Error(`No active browser session`);c.current+=1;try{return await b(r.projectId,r.id,e,t,n)}finally{c.current=Math.max(0,c.current-1),d()}},[d]),C=(0,u.useCallback)(async(e,t,n,r)=>{let i=s.current;if(!i)throw Error(`No active browser session`);c.current+=1;try{return await S(i.projectId,i.id,e,t,n,r)}finally{c.current=Math.max(0,c.current-1),d()}},[d]),D=(0,u.useCallback)(async(e,t)=>{let n=s.current;return n?w(n.projectId,n.id,e,t):{text:``}},[]),k=(0,u.useCallback)((e,t)=>{let n=Math.max(1,Math.round(e)),r=Math.max(1,Math.round(t));p(e=>({...e,viewport:{width:n,height:r}})),m({type:`resize`,width:n,height:r})},[m]),j=(0,u.useCallback)(e=>{let t=o.current;if(t&&t.readyState===WebSocket.OPEN)try{t.send(JSON.stringify({type:`probe`,x:e.x,y:e.y}))}catch{}},[]),M=(0,u.useCallback)(()=>{p(e=>e.hoverRect||e.hoverPath?{...e,hoverRect:null,hoverSelector:null,hoverPath:null}:e)},[]),N=(0,u.useCallback)(async(e,t)=>{let n=s.current;return n?T(n.projectId,n.id,e,t):null},[]),P=(0,u.useCallback)(e=>{let t=s.current;t&&(p(t=>t.popup?{...t,popup:{...t.popup,active:e===`popup`}}:t),E(t.projectId,t.id,e))},[]);return{...f,canvasRef:a,forwardInput:m,navigate:_,capture:x,captureBreakpoints:C,clipboard:D,navigateElement:N,setViewport:k,probe:j,clearHover:M,setPopupView:P}}export{L as a,M as c,P as d,C as f,s as g,c as h,j as i,N as l,l as m,m as n,p as o,f as p,I as r,F as s,U as t,D as u};
1
+ import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{n as t}from"./jsx-runtime-zu2_FqZY.js";import{o as n}from"./i18n-nJQvD5zJ.js";import{t as r}from"./createLucideIcon-Bjbbp_KS.js";import{a as i,n as a}from"./auth-D_5bQv5W.js";import{t as o}from"./api-B2M7CtDw.js";var s=r(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]),c=r(`globe`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20`,key:`13o1zl`}],[`path`,{d:`M2 12h20`,key:`9i4pu4`}]]),l=r(`rotate-cw`,[[`path`,{d:`M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8`,key:`1p45f6`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}]]),u=e(t(),1);function d(){return typeof window<`u`&&`__TAURI_INTERNALS__`in window||typeof window<`u`&&window.location.protocol!==`http:`&&window.location.protocol!==`https:`?`ws://localhost:4200`:`${window.location.protocol===`https:`?`wss:`:`ws:`}//${window.location.host}`}var f=d();function p(){let e={BASE_URL:`/`,DEV:!1,MODE:`production`,PROD:!0,SSR:!1}.VITE_FEATURE_BROWSER_CAPTURE;return typeof e!=`string`||e!==`false`}var m={desktop:{width:1280,height:800},tablet:{width:768,height:1024},mobile:{width:375,height:667}},h=class extends Error{},g=class extends Error{};function _(e){if(!e)throw Error(`A project owner is required for browser sessions`);return`${i}/api/projects/${encodeURIComponent(e)}`}async function v(e,t){let n=await fetch(`${_(e)}/browser/sessions`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({initialUrl:t})});if(n.status===409)throw new h(`Too many open browser sessions`);if(n.status===502)throw new g(`The browser failed to launch`);if(!n.ok)throw Error(`Failed to open browser (${n.status})`);return(await n.json()).session}async function y(e,t,n,r){let i=await fetch(`${_(e)}/browser/sessions/${t}/navigate`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:n,url:r})});if(!i.ok)throw Error(`Navigation failed (${i.status})`);return await i.json()}async function b(e,t,n,r,i){let a=await fetch(`${_(e)}/browser/sessions/${t}/capture`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({rect:n,pendingSpecId:r,captureNetwork:i?.captureNetwork??!0})});if(!a.ok)throw Error(await x(a));return await a.json()}async function x(e){let t=await e.json().then(e=>e.error).catch(()=>void 0);return t?`Capture failed (${e.status}): ${t}`:`Capture failed (${e.status})`}async function S(e,t,n,r,i,a=m){let o=await fetch(`${_(e)}/browser/sessions/${t}/capture-breakpoints`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({rect:n,anchorPoint:r,pendingSpecId:i,breakpoints:a})});if(!o.ok)throw Error(await x(o));return await o.json()}async function C(e,t,n){let r=new FormData;r.append(`file`,t,n);let i=await fetch(`${o()}/tickets/${e}/attachments`,{method:`POST`,body:r});if(!i.ok)throw Error(`Upload failed (${i.status})`);return(await i.json()).attachment}async function w(e,t,n,r){let i=await fetch(`${_(e)}/browser/sessions/${t}/clipboard`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:n,text:r})});if(!i.ok)throw Error(`Clipboard failed (${i.status})`);return await i.json()}async function T(e,t,n,r){let i=await fetch(`${_(e)}/browser/sessions/${t}/element`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({selector:n,direction:r})});if(!i.ok)throw Error(`Element navigate failed (${i.status})`);return(await i.json()).probe}async function E(e,t,n){try{await fetch(`${_(e)}/browser/sessions/${t}/popup-view`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({target:n})})}catch{}}function D(e){if(!e||e===`about:blank`)return`…`;try{return new URL(e).hostname||`…`}catch{return`…`}}async function O(e,t){try{await fetch(`${_(e)}/browser/sessions/${t}`,{method:`DELETE`})}catch{}}function k(e,t){return`${f||(typeof window<`u`?`${window.location.protocol===`https:`?`wss:`:`ws:`}//${window.location.host}`:`ws://localhost:4200`)}/ws/browser/${e}?projectId=${encodeURIComponent(t)}`}function A(e,t){let n=k(e,t),r=a(),i=r?new WebSocket(n,[`specrails-desktop`,r]):new WebSocket(n);return i.binaryType=`arraybuffer`,i}function j(e,t=e=>requestAnimationFrame(e),n=e=>cancelAnimationFrame(e)){let r=null,i=null,a=null,o=!1,s=()=>{a!=null&&(n(a),a=null);let t=r,o=i;r=null,i=null,t&&(!o||t.x!==o.x||t.y!==o.y)&&e({type:`mouse`,action:`move`,x:t.x,y:t.y}),o&&e({type:`wheel`,x:o.x,y:o.y,deltaX:o.deltaX,deltaY:o.deltaY})},c=()=>{a==null&&!o&&(a=t(()=>{a=null,s()}))};return{move(e,t){o||(r={x:e,y:t},c())},wheel(e,t,n,r){o||(i?(i.x=e,i.y=t,i.deltaX+=n,i.deltaY+=r):i={x:e,y:t,deltaX:n,deltaY:r},c())},flush(){o||s()},dispose(){o||(o=!0,a!=null&&(n(a),a=null),r=null,i=null)}}}function M(e,t,n){let r=t.width>0?(e.x-t.left)/t.width:0,i=t.height>0?(e.y-t.top)/t.height:0,a=Math.min(Math.max(r,0),1)*n.width,o=Math.min(Math.max(i,0),1)*n.height;return{x:Math.round(a),y:Math.round(o)}}function N(e,t,n){let r=n.width>0?t.width/n.width:0,i=n.height>0?t.height/n.height:0;return{left:t.left+e.x*r,top:t.top+e.y*i,width:e.width*r,height:e.height*i}}function P(e,t){return{x:Math.min(e.x,t.x),y:Math.min(e.y,t.y),width:Math.abs(e.x-t.x),height:Math.abs(e.y-t.y)}}function F(e,t=8){return e.width>=t&&e.height>=t}function I(e,t){let n=Math.max(1,t.width),r=Math.max(1,t.height),i=Math.max(0,Math.min(e.x,n-1)),a=Math.max(0,Math.min(e.y,r-1)),o=Math.min(n,Math.max(i+1,e.x+e.width)),s=Math.min(r,Math.max(a+1,e.y+e.height));return{x:Math.round(i),y:Math.round(a),width:Math.round(o-i),height:Math.round(s-a)}}function L(e){return{nodeCount:e.nodes.length,htmlBytes:e.html.length,truncated:e.htmlTruncated,networkCount:e.networkRequests?.length??0}}function R(e){let t=e.schedule??(e=>requestAnimationFrame(e)),n=e.cancel??(e=>cancelAnimationFrame(e)),r=e.now??(()=>typeof performance<`u`?performance.now():Date.now()),i=e.release??(()=>{}),a={received:0,decoded:0,drawn:0,droppedStale:0,droppedUndrawn:0,decodeMsTotal:0,drawMsTotal:0},o=!1,s=!1,c=null,l=null,u=null,d=()=>{u=null;let t=l;if(l=null,t==null||o){t!=null&&f(t);return}let n=r();try{e.draw(t),a.drawn++,a.drawMsTotal+=r()-n}catch{}finally{f(t)}},f=e=>{try{i(e)}catch{}},p=()=>{u==null&&!o&&(u=t(d))},m=t=>{s=!0;let n=r();e.decode(t).then(e=>{if(o){f(e);return}a.decoded++,a.decodeMsTotal+=r()-n,l!=null&&(a.droppedUndrawn++,f(l)),l=e,p(),h()},()=>{h()})},h=()=>{if(o){s=!1;return}let e=c;c=null,e==null?s=!1:m(e)};return{push(e){if(!o){if(a.received++,s){c!=null&&a.droppedStale++,c=e;return}m(e)}},stats(){return{...a}},dispose(){if(!o){if(o=!0,c=null,u!=null){try{n(u)}catch{}u=null}l!=null&&(f(l),l=null)}}}}var z=`specrails-desktop:browser-capture-debug`;function B(){try{return typeof localStorage<`u`&&localStorage.getItem(z)===`1`}catch{return!1}}function V(e,t,n){let r=Math.max(1,n),i=t.decoded-e.decoded,a=t.drawn-e.drawn,o=e=>Math.round(e*10)/10;return{fpsReceived:o((t.received-e.received)*1e3/r),fpsDrawn:o(a*1e3/r),droppedStale:t.droppedStale-e.droppedStale,droppedUndrawn:t.droppedUndrawn-e.droppedUndrawn,avgDecodeMs:i>0?o((t.decodeMsTotal-e.decodeMsTotal)/i):0,avgDrawMs:a>0?o((t.drawMsTotal-e.drawMsTotal)/a):0}}function H(e,t=e=>console.table([e]),n=2e3,r=()=>Date.now()){let i=e(),a=r(),o=setInterval(()=>{let n=e(),o=r();t(V(i,n,o-a)),i=n,a=o},n);return()=>clearInterval(o)}function U(e){let{projectId:t,open:r,initialUrl:i}=e,a=(0,u.useRef)(null),o=(0,u.useRef)(null),s=(0,u.useRef)(null),c=(0,u.useRef)(0),l=(0,u.useRef)(new Map),d=(0,u.useCallback)(()=>{if(c.current!==0||l.current.size===0)return;let e=[...l.current.values()];l.current.clear();for(let t of e)O(t.projectId,t.sessionId)},[]),[f,p]=(0,u.useState)({status:`connecting`,errorMsg:null,url:null,title:null,viewport:{width:1280,height:800},hoverRect:null,hoverSelector:null,hoverPath:null,popup:null});(0,u.useEffect)(()=>{if(!r||!t)return;let e=!1,u=null;p(e=>({...e,status:`connecting`,errorMsg:null,popup:null}));let d=R({decode:e=>createImageBitmap(new Blob([e],{type:`image/jpeg`})),draw:e=>{let t=a.current;t&&(t.width!==e.width&&(t.width=e.width),t.height!==e.height&&(t.height=e.height),t.getContext(`2d`)?.drawImage(e,0,0))},release:e=>e.close()}),f=B()?H(()=>d.stats()):null;return(async()=>{try{let r=await v(t,i);if(e){O(t,r.id);return}u=r.id,s.current={id:r.id,projectId:t},p(e=>({...e,url:r.url,title:r.title,viewport:{width:r.viewportWidth,height:r.viewportHeight}}));let a=A(r.id,t);o.current=a,a.onmessage=e=>{if(typeof e.data==`string`){try{let t=JSON.parse(e.data);if(t.type===`ready`)p(e=>({...e,status:`ready`,url:t.url??e.url,title:t.title??e.title,viewport:t.viewport??e.viewport}));else if(t.type===`nav`)p(e=>({...e,url:t.url??e.url,title:t.title??e.title}));else if(t.type===`hover`)p(e=>({...e,hoverRect:t.rect??null,hoverSelector:t.selector??null,hoverPath:t.path??null}));else if(t.type===`popup`){let e=typeof t.count==`number`?t.count:0;p(n=>({...n,popup:e>0?{count:e,active:t.active===!0,url:t.url??null}:null}))}}catch{}return}d.push(e.data)},a.onopen=()=>{e||p(e=>({...e,status:`ready`}))},a.onerror=()=>{e||p(e=>({...e,status:`error`,errorMsg:n.t(`browser:session.connectionError`)}))},a.onclose=()=>{e||p(e=>e.status===`ready`?{...e,status:`error`,errorMsg:n.t(`browser:session.lostConnection`)}:e)}}catch(t){if(e)return;let r=t instanceof h?n.t(`browser:session.tooManySessions`):t instanceof g?n.t(`browser:session.launchFailed`):n.t(`browser:session.openFailed`);p(e=>({...e,status:`error`,errorMsg:r}))}})(),()=>{e=!0,f?.(),d.dispose();let n=o.current;if(n){n.onmessage=null,n.onopen=null,n.onerror=null,n.onclose=null;try{n.close()}catch{}}o.current=null;let r=u;r&&s.current?.id===r&&s.current.projectId===t&&(s.current=null),r&&(c.current>0?l.current.set(`${t}\0${r}`,{sessionId:r,projectId:t}):O(t,r))}},[r,t,i,d]);let m=(0,u.useCallback)(e=>{let t=o.current;if(t&&t.readyState===WebSocket.OPEN)try{t.send(JSON.stringify({type:`input`,event:e}))}catch{}},[]),_=(0,u.useCallback)(async(e,t)=>{let n=s.current;if(n)try{let r=await y(n.projectId,n.id,e,t);if(s.current?.id!==n.id||s.current.projectId!==n.projectId)return;p(e=>({...e,url:r.url,title:r.title}))}catch{}},[]),x=(0,u.useCallback)(async(e,t,n)=>{let r=s.current;if(!r)throw Error(`No active browser session`);c.current+=1;try{return await b(r.projectId,r.id,e,t,n)}finally{c.current=Math.max(0,c.current-1),d()}},[d]),C=(0,u.useCallback)(async(e,t,n,r)=>{let i=s.current;if(!i)throw Error(`No active browser session`);c.current+=1;try{return await S(i.projectId,i.id,e,t,n,r)}finally{c.current=Math.max(0,c.current-1),d()}},[d]),D=(0,u.useCallback)(async(e,t)=>{let n=s.current;return n?w(n.projectId,n.id,e,t):{text:``}},[]),k=(0,u.useCallback)((e,t)=>{let n=Math.max(1,Math.round(e)),r=Math.max(1,Math.round(t));p(e=>({...e,viewport:{width:n,height:r}})),m({type:`resize`,width:n,height:r})},[m]),j=(0,u.useCallback)(e=>{let t=o.current;if(t&&t.readyState===WebSocket.OPEN)try{t.send(JSON.stringify({type:`probe`,x:e.x,y:e.y}))}catch{}},[]),M=(0,u.useCallback)(()=>{p(e=>e.hoverRect||e.hoverPath?{...e,hoverRect:null,hoverSelector:null,hoverPath:null}:e)},[]),N=(0,u.useCallback)(async(e,t)=>{let n=s.current;return n?T(n.projectId,n.id,e,t):null},[]),P=(0,u.useCallback)(e=>{let t=s.current;t&&(p(t=>t.popup?{...t,popup:{...t.popup,active:e===`popup`}}:t),E(t.projectId,t.id,e))},[]);return{...f,canvasRef:a,forwardInput:m,navigate:_,capture:x,captureBreakpoints:C,clipboard:D,navigateElement:N,setViewport:k,probe:j,clearHover:M,setPopupView:P}}export{L as a,M as c,P as d,C as f,s as g,c as h,j as i,N as l,l as m,m as n,p as o,f as p,I as r,F as s,U as t,D as u};
@@ -0,0 +1 @@
1
+ import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{n as t,t as n}from"./jsx-runtime-zu2_FqZY.js";import{o as r}from"./i18n-nJQvD5zJ.js";import{n as i}from"./dist-bVqfYmby.js";import{a}from"./auth-D_5bQv5W.js";import{r as o}from"./useSharedWebSocket-DK96ctb7.js";import{n as s}from"./api-B2M7CtDw.js";var c=e(t(),1),l=new Map;function u(e,t){return`${e}:${t}`}function d(e){return(e instanceof Error?e.message:e==null?``:String(e)).trim()||`Request failed`}function f(e){if(!e)return;let t=`${e}:`;for(let e of l.keys())e.startsWith(t)&&l.delete(e)}function p({namespace:e,projectId:t,initialValue:n,fetcher:r,pollInterval:i=0}){let a=t?u(t,e):null,[o,s]=(0,c.useState)(()=>a&&l.has(a)?l.get(a):n),[f,p]=(0,c.useState)(()=>!a||!l.has(a)),[m,h]=(0,c.useState)(f),[g,_]=(0,c.useState)(null),v=(0,c.useRef)(r);v.current=r;let y=(0,c.useRef)(n);y.current=n;let b=(0,c.useRef)(a);b.current=a;let x=(0,c.useRef)(0),S=(0,c.useRef)(null),C=(0,c.useCallback)(async(e,t,n)=>{let r=++x.current;S.current?.abort();let i=new AbortController;S.current=i,n&&b.current===e&&(h(!0),_(null));try{let n=await v.current({projectId:t,signal:i.signal});if(i.signal.aborted||r!==x.current)return;l.set(e,n),b.current===e&&(s(n),_(null))}catch(t){if(i.signal.aborted||r!==x.current)return;b.current===e&&_(d(t))}finally{r===x.current&&(S.current===i&&(S.current=null),b.current===e&&(h(!1),p(!1)))}},[]);return(0,c.useEffect)(()=>{if(x.current+=1,S.current?.abort(),S.current=null,_(null),!a||!t){s(y.current),p(!0),h(!1);return}let e=l.has(a);e?(s(l.get(a)),p(!1),h(!1)):(s(y.current),p(!0),h(!0)),C(a,t,!e);let n;return i>0&&(n=setInterval(()=>{C(a,t,!1)},i)),()=>{x.current+=1,S.current?.abort(),S.current=null,n&&clearInterval(n)}},[a,t,i,C]),{data:o,isLoading:m,isFirstLoad:f,error:g,refresh:(0,c.useCallback)(async()=>{!a||!t||await C(a,t,!0)},[a,t,C])}}var m=n();function h(e){return e.providers&&e.providers.length>0?e.providers:[e.provider]}var g=(0,c.createContext)(null),_=`specrails-desktop:activeProjectId`;function v(e){try{e?localStorage.setItem(_,e):localStorage.removeItem(_)}catch{}}function y(){try{return localStorage.getItem(_)}catch{return null}}function b({children:e}){let[t,n]=(0,c.useState)([]),[l,u]=(0,c.useState)(null),[d,p]=(0,c.useState)(!0),[h,_]=(0,c.useState)(!1),b=(0,c.useRef)(null),x=(0,c.useRef)(new Set),S=(0,c.useCallback)(e=>{v(e),s(e),u(t=>(t!==null&&t!==e&&(b.current&&clearTimeout(b.current),_(!0),b.current=setTimeout(()=>_(!1),400)),e))},[]),{registerHandler:C,unregisterHandler:w}=o();(0,c.useEffect)(()=>{async function e(){try{let e=await fetch(`${a}/api/projects`);if(!e.ok)return;let t=await e.json();n(t.projects)}catch{}finally{p(!1)}}e()},[]);let T=(0,c.useCallback)(e=>{let t=e;if(typeof t.type==`string`){if(t.type===`desktop.projects`){if(!Array.isArray(t.projects))return;let e=t.projects;n(e),u(t=>{let n;if(t&&e.find(e=>e.id===t))n=t;else{let t=y();n=t&&e.find(e=>e.id===t)?t:e.length>0?e[0].id:null}return v(n),s(n),n}),p(!1)}else if(t.type===`desktop.project_added`){let e=t.project;n(t=>t.find(t=>t.id===e.id)?t:[...t,e]),x.current.has(e.id)?x.current.delete(e.id):(i.success(r.t(`nav:projects.added`,{name:e.name})),S(e.id))}else if(t.type===`providers.detected_changed`)fetch(`${a}/api/projects`).then(e=>e.ok?e.json():null).then(e=>{e&&Array.isArray(e.projects)&&n(e.projects)}).catch(()=>{});else if(t.type===`desktop.project_removed`){let e=t.projectId;i.success(r.t(`nav:projects.removed`)),f(e),n(t=>t.filter(t=>t.id!==e)),u(t=>t===e?(v(null),s(null),null):t)}}},[]);(0,c.useLayoutEffect)(()=>(C(`desktop`,T),()=>w(`desktop`)),[T,C,w]);let E=(0,c.useRef)(0);(0,c.useEffect)(()=>{let e=()=>{let e=Date.now();e-E.current<6e4||(E.current=e,fetch(`${a}/api/providers/detected?refresh=1`).catch(()=>{}))};return window.addEventListener(`focus`,e),()=>window.removeEventListener(`focus`,e)},[]);let D=(0,c.useCallback)(async(e,t,r)=>{try{let i={path:e};r&&r.length>0&&(i.providers=r),t&&(i.name=t);let a=await fetch(`/api/projects`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(i)});if(!a.ok){let e=await a.json();throw Error(e.error??`HTTP ${a.status}`)}let o=await a.json();return x.current.add(o.project.id),n(e=>e.find(e=>e.id===o.project.id)?e:[...e,o.project]),S(o.project.id),o}catch(e){throw console.error(`[useDesktop] addProject error:`,e),e}},[S]),O=(0,c.useCallback)(async e=>{try{let t=await fetch(`${a}/api/projects/${e}`,{method:`DELETE`});if(!t.ok){let e=await t.json();throw Error(e.error??`HTTP ${t.status}`)}f(e),n(t=>t.filter(t=>t.id!==e)),u(t=>t===e?(v(null),s(null),null):t)}catch(e){throw console.error(`[useDesktop] removeProject error:`,e),e}},[]),k=(0,c.useMemo)(()=>({projects:t,activeProjectId:l,setActiveProjectId:S,addProject:D,removeProject:O,isLoading:d,isSwitchingProject:h}),[t,l,S,D,O,d,h]);return(0,m.jsx)(g.Provider,{value:k,children:e})}var x={projects:[],activeProjectId:null,setActiveProjectId:()=>{},addProject:async()=>null,removeProject:async()=>{},isLoading:!1,isSwitchingProject:!1};function S(){return(0,c.useContext)(g)??x}export{p as i,h as n,S as r,b as t};
@@ -1 +1 @@
1
- import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{n as t,t as n}from"./jsx-runtime-zu2_FqZY.js";import{n as r}from"./auth-D_5bQv5W.js";var i=e(t(),1),a=n(),o=[1e3,2e3,4e3,8e3,16e3],s=(0,i.createContext)(null);function c({url:e,children:t}){let[n,c]=(0,i.useState)(`connecting`),l=(0,i.useRef)(new Map),u=(0,i.useRef)(null),d=(0,i.useRef)(0),f=(0,i.useRef)(null);(0,i.useEffect)(()=>{let t=!1;function n(){if(t)return;let i=r(),a=i?new WebSocket(e,[`specrails-desktop`,i]):new WebSocket(e);u.current=a,c(`connecting`),a.onopen=()=>{if(t){a.close();return}d.current=0,c(`connected`)},a.onmessage=e=>{if(t)return;let n;try{n=JSON.parse(e.data)}catch{return}for(let e of l.current.values())try{e(n)}catch(e){console.error(`[useSharedWebSocket] handler threw while processing message`,e)}},a.onclose=()=>{if(t)return;u.current=null;let e=d.current;if(e>=o.length){c(`connecting`),f.current=setTimeout(n,3e4);return}c(`connecting`);let r=o[e];d.current+=1,f.current=setTimeout(n,r)}}return n(),()=>{t=!0,f.current&&clearTimeout(f.current);let e=u.current;if(e)if(e.onmessage=null,e.onclose=null,e.onerror=null,e.readyState===WebSocket.CONNECTING)e.onopen=()=>{try{e.close()}catch{}};else{e.onopen=null;try{e.close()}catch{}}}},[e]);let p=(0,i.useCallback)((e,t)=>{l.current.set(e,t)},[]),m=(0,i.useCallback)(e=>{l.current.delete(e)},[]),h=(0,i.useMemo)(()=>({registerHandler:p,unregisterHandler:m,connectionStatus:n}),[p,m,n]);return(0,a.jsx)(s.Provider,{value:h,children:t})}function l(){let e=(0,i.useContext)(s);if(!e)throw Error(`useSharedWebSocket must be used within SharedWebSocketProvider`);return e}export{l as n,c as t};
1
+ import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{n as t,t as n}from"./jsx-runtime-zu2_FqZY.js";import{n as r}from"./auth-D_5bQv5W.js";var i=e(t(),1),a=n(),o=[1e3,2e3,4e3,8e3,16e3],s=(0,i.createContext)(null);function c({url:e,children:t}){let[n,c]=(0,i.useState)(`connecting`),l=(0,i.useRef)(new Map),u=(0,i.useRef)(null),d=(0,i.useRef)(0),f=(0,i.useRef)(null);(0,i.useEffect)(()=>{let t=!1;function n(){if(t)return;let i=r(),a=i?new WebSocket(e,[`specrails-desktop`,i]):new WebSocket(e);u.current=a,c(`connecting`),a.onopen=()=>{if(t){a.close();return}d.current=0,c(`connected`)},a.onmessage=e=>{if(t)return;let n;try{n=JSON.parse(e.data)}catch{return}for(let e of l.current.values())try{e(n)}catch(e){console.error(`[useSharedWebSocket] handler threw while processing message`,e)}},a.onclose=()=>{if(t)return;u.current=null;let e=d.current;if(e>=o.length){c(`connecting`),f.current=setTimeout(n,3e4);return}c(`connecting`);let r=o[e];d.current+=1,f.current=setTimeout(n,r)}}return n(),()=>{t=!0,f.current&&clearTimeout(f.current);let e=u.current;if(e)if(e.onmessage=null,e.onclose=null,e.onerror=null,e.readyState===WebSocket.CONNECTING)e.onopen=()=>{try{e.close()}catch{}};else{e.onopen=null;try{e.close()}catch{}}}},[e]);let p=(0,i.useCallback)((e,t)=>{l.current.set(e,t)},[]),m=(0,i.useCallback)(e=>{l.current.delete(e)},[]),h=(0,i.useMemo)(()=>({registerHandler:p,unregisterHandler:m,connectionStatus:n}),[p,m,n]);return(0,a.jsx)(s.Provider,{value:h,children:t})}function l(){let e=(0,i.useContext)(s);if(!e)throw Error(`useSharedWebSocket must be used within SharedWebSocketProvider`);return e}export{c as n,l as r,s as t};
@@ -204,7 +204,7 @@
204
204
  .specrails-splash__mark .pill { opacity: 1; }
205
205
  }
206
206
  </style>
207
- <script type="module" crossorigin src="/assets/index-kCUcnT8G.js"></script>
207
+ <script type="module" crossorigin src="/assets/index-C_sdsSZt.js"></script>
208
208
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-CNC7AqOf.js">
209
209
  <link rel="modulepreload" crossorigin href="/assets/jsx-runtime-zu2_FqZY.js">
210
210
  <link rel="modulepreload" crossorigin href="/assets/react-dom-DiWzBDP9.js">
@@ -212,45 +212,45 @@
212
212
  <link rel="modulepreload" crossorigin href="/assets/chunk-KS7C4IRE-Cx5sqopX.js">
213
213
  <link rel="modulepreload" crossorigin href="/assets/createLucideIcon-Bjbbp_KS.js">
214
214
  <link rel="modulepreload" crossorigin href="/assets/activity-DiyjsgQV.js">
215
- <link rel="modulepreload" crossorigin href="/assets/addspec-x3mizDxc.js">
216
- <link rel="modulepreload" crossorigin href="/assets/agent-Bs9NilfI.js">
215
+ <link rel="modulepreload" crossorigin href="/assets/addspec-D2YIQ0GU.js">
216
+ <link rel="modulepreload" crossorigin href="/assets/agent-mTCsAbCl.js">
217
217
  <link rel="modulepreload" crossorigin href="/assets/agents-ms7TwG16.js">
218
- <link rel="modulepreload" crossorigin href="/assets/agentstudio-Bz169Vzt.js">
218
+ <link rel="modulepreload" crossorigin href="/assets/agentstudio-CN2pokQu.js">
219
219
  <link rel="modulepreload" crossorigin href="/assets/aiedit-iIjz2_Qk.js">
220
- <link rel="modulepreload" crossorigin href="/assets/analytics-BHqUazhP.js">
220
+ <link rel="modulepreload" crossorigin href="/assets/analytics-BMzCvrCU.js">
221
221
  <link rel="modulepreload" crossorigin href="/assets/attachments-B53PG733.js">
222
222
  <link rel="modulepreload" crossorigin href="/assets/browser-CXUcnTMI.js">
223
- <link rel="modulepreload" crossorigin href="/assets/builder-skfnZ1uC.js">
223
+ <link rel="modulepreload" crossorigin href="/assets/builder-CHuahItu.js">
224
224
  <link rel="modulepreload" crossorigin href="/assets/chat-BGD7MXAy.js">
225
225
  <link rel="modulepreload" crossorigin href="/assets/code-CHPkOkDS.js">
226
226
  <link rel="modulepreload" crossorigin href="/assets/commands-DyUZQ1FI.js">
227
227
  <link rel="modulepreload" crossorigin href="/assets/common-DHsv9N5d.js">
228
- <link rel="modulepreload" crossorigin href="/assets/dashboard-C_NQZle_.js">
228
+ <link rel="modulepreload" crossorigin href="/assets/dashboard-CTsM8x3m.js">
229
229
  <link rel="modulepreload" crossorigin href="/assets/explore-DgBACn39.js">
230
230
  <link rel="modulepreload" crossorigin href="/assets/integrations-mB-7zoyT.js">
231
- <link rel="modulepreload" crossorigin href="/assets/jira-CmKWERE0.js">
231
+ <link rel="modulepreload" crossorigin href="/assets/jira-CKJg3HZd.js">
232
232
  <link rel="modulepreload" crossorigin href="/assets/jobs-B_TeSQxb.js">
233
233
  <link rel="modulepreload" crossorigin href="/assets/loops-CnxqL8IL.js">
234
234
  <link rel="modulepreload" crossorigin href="/assets/mcp-uDkXYu4L.js">
235
- <link rel="modulepreload" crossorigin href="/assets/nav-VaB-C4k5.js">
235
+ <link rel="modulepreload" crossorigin href="/assets/nav-DjkmQJjd.js">
236
236
  <link rel="modulepreload" crossorigin href="/assets/settings-CuVwOpe0.js">
237
- <link rel="modulepreload" crossorigin href="/assets/setup-DwcQ921P.js">
237
+ <link rel="modulepreload" crossorigin href="/assets/setup-3jWaoVUO.js">
238
238
  <link rel="modulepreload" crossorigin href="/assets/specs-DII0C8gw.js">
239
239
  <link rel="modulepreload" crossorigin href="/assets/terminal-BFRZnMPP.js">
240
- <link rel="modulepreload" crossorigin href="/assets/tickets-CqqOHbli.js">
241
- <link rel="modulepreload" crossorigin href="/assets/i18n-Ch-Db_x2.js">
242
- <link rel="modulepreload" crossorigin href="/assets/Trans-B2i5HVcM.js">
240
+ <link rel="modulepreload" crossorigin href="/assets/tickets-W6pBmbrX.js">
241
+ <link rel="modulepreload" crossorigin href="/assets/i18n-nJQvD5zJ.js">
242
+ <link rel="modulepreload" crossorigin href="/assets/Trans-CTqw6rr9.js">
243
243
  <link rel="modulepreload" crossorigin href="/assets/dist-bVqfYmby.js">
244
244
  <link rel="modulepreload" crossorigin href="/assets/arrow-left-CpIR4j7G.js">
245
245
  <link rel="modulepreload" crossorigin href="/assets/auth-D_5bQv5W.js">
246
246
  <link rel="modulepreload" crossorigin href="/assets/api-B2M7CtDw.js">
247
- <link rel="modulepreload" crossorigin href="/assets/useBrowserCaptureSession-TTO8vHtd.js">
247
+ <link rel="modulepreload" crossorigin href="/assets/useBrowserCaptureSession-BBXBN0Na.js">
248
248
  <link rel="modulepreload" crossorigin href="/assets/arrow-up-right-9DoMn7fD.js">
249
249
  <link rel="modulepreload" crossorigin href="/assets/sparkles-DrY8hb0X.js">
250
250
  <link rel="modulepreload" crossorigin href="/assets/x-CBMI9ejn.js">
251
- <link rel="modulepreload" crossorigin href="/assets/useSharedWebSocket-DaPh7QBL.js">
252
- <link rel="modulepreload" crossorigin href="/assets/useDesktop-DUvS4fuP.js">
253
- <link rel="modulepreload" crossorigin href="/assets/MinimizedChatsContext-Gt6KQySM.js">
251
+ <link rel="modulepreload" crossorigin href="/assets/useSharedWebSocket-DK96ctb7.js">
252
+ <link rel="modulepreload" crossorigin href="/assets/useDesktop-B6Du2N83.js">
253
+ <link rel="modulepreload" crossorigin href="/assets/MinimizedChatsContext-CHsu3NCX.js">
254
254
  <link rel="modulepreload" crossorigin href="/assets/external-link-BcU5EWZp.js">
255
255
  <link rel="modulepreload" crossorigin href="/assets/chevron-right-CViMxucY.js">
256
256
  <link rel="modulepreload" crossorigin href="/assets/circle-x-CMYsN4ZH.js">
@@ -271,14 +271,14 @@
271
271
  <link rel="modulepreload" crossorigin href="/assets/utils-BC4DHlz2.js">
272
272
  <link rel="modulepreload" crossorigin href="/assets/button-BUIIBQPT.js">
273
273
  <link rel="modulepreload" crossorigin href="/assets/dialog-CzIekCw0.js">
274
- <link rel="modulepreload" crossorigin href="/assets/jira-api-BgFIr8eD.js">
275
- <link rel="modulepreload" crossorigin href="/assets/provider-capabilities-BvoExILy.js">
274
+ <link rel="modulepreload" crossorigin href="/assets/jira-api-Bhixwn-d.js">
275
+ <link rel="modulepreload" crossorigin href="/assets/provider-capabilities-Doej9lfa.js">
276
276
  <link rel="modulepreload" crossorigin href="/assets/lib-CGdyxIWg.js">
277
- <link rel="modulepreload" crossorigin href="/assets/getTimezoneOffsetInMilliseconds-CSCbUI4W.js">
278
- <link rel="modulepreload" crossorigin href="/assets/formatDistanceToNow-BjGwPf6I.js">
279
- <link rel="modulepreload" crossorigin href="/assets/spending-Dq43JYmD.js">
280
- <link rel="modulepreload" crossorigin href="/assets/TicketDetailModal-C-tHW-2s.js">
281
- <link rel="stylesheet" crossorigin href="/assets/index-Bz0TeGRs.css">
277
+ <link rel="modulepreload" crossorigin href="/assets/getTimezoneOffsetInMilliseconds-EjGOpn4b.js">
278
+ <link rel="modulepreload" crossorigin href="/assets/formatDistanceToNow-BOuXgebD.js">
279
+ <link rel="modulepreload" crossorigin href="/assets/spending-BpYPsevQ.js">
280
+ <link rel="modulepreload" crossorigin href="/assets/TicketDetailModal-MhJzrqbi.js">
281
+ <link rel="stylesheet" crossorigin href="/assets/index-DCN5QbDm.css">
282
282
  </head>
283
283
  <body>
284
284
  <div id="specrails-splash" aria-hidden="false" role="status" aria-label="Loading Specrails">
@@ -4,55 +4,36 @@ Ein Projekt ist einfach ein Ordner auf deinem Computer, der eine Codebasis enth
4
4
 
5
5
  ## Den Dialog „Projekt hinzufügen“ öffnen
6
6
 
7
- Klicke auf dem Willkommensbildschirm auf **Dein erstes Projekt hinzufügen** (oder später auf die Schaltfläche **Projekt hinzufügen** in der linken Seitenleiste). Ein kleiner Dialog erscheint.
7
+ Klicke auf **Füge dein erstes Projekt hinzu** auf dem Willkommensbildschirm (oder später auf den Button **Projekt hinzufügen** in der linken Seitenleiste). Ein kleiner Dialog erscheint.
8
8
 
9
9
  ## Die Details ausfüllen
10
10
 
11
11
  **Projektordner** *(erforderlich)*
12
12
 
13
- Zeige specrails den Ordner, der deinen Code enthält. In der Desktop-App kannst du auf das Ordnersymbol klicken, um ihn visuell auszuwählen, oder den vollständigen Pfad einfügen. Das sollte das Wurzelverzeichnis deines Repositorys sein – der Ordner, der deinen Code und (üblicherweise) ein `.git`-Verzeichnis enthält.
13
+ Zeige specrails den Ordner, der deinen Code enthält. In der Desktop-App kannst du auf das Ordnersymbol klicken, um visuell zu wählen, oder den vollständigen Pfad einfügen. Es sollte die Wurzel deines Repositories sein — der Ordner mit deinem Code und (üblicherweise) einem `.git`-Verzeichnis.
14
14
 
15
15
  **Projektname** *(optional)*
16
16
 
17
- Ein freundliches Label, das in der Seitenleiste angezeigt wird. Lässt du es leer, verwendet specrails den Ordnernamen.
17
+ Eine freundliche Bezeichnung in der Seitenleiste. Lässt du sie leer, verwendet specrails den Ordnernamen.
18
18
 
19
- **Provider**
19
+ > Im Hintergrund läuft eine schnelle Prüfung, ob die erforderlichen Tools vorhanden sind. Fehlt etwas Wesentliches, bleibt der **Hinzufügen**-Button deaktiviert und ein **Mehr Infos**-Link liefert dir die genauen Installationsbefehle.
20
20
 
21
- Wähle, welche KI-Provider dieses Projekt nutzen soll. specrails zeigt dir die, die es auf deinem Rechner gefunden hat:
21
+ Das ist das ganze Formular — klicke auf **Hinzufügen** und fertig.
22
22
 
23
- - 🤖 **Claude**
24
- - ⚡ **Codex**
25
- - ✨ **Gemini**
23
+ ## KI-Provider werden automatisch erkannt
26
24
 
27
- Nicht gefundene Provider sind ausgegraut und als *nicht gefunden* markiert – installiere einen, melde dich an und öffne den Dialog dann erneut. Standardmäßig ist jeder verfügbare Provider vorausgewählt, du kannst die Auswahl aber auf genau den reduzieren, den du möchtest. Wählst du mehr als einen, wird der **erste** zum Standard des Projekts; pro Aufgabe kannst du später trotzdem wählen.
25
+ Du wählst keine Provider mehr aus. Specrails erkennt jedes auf deinem Rechner installierte KI-CLI — **Claude**, **Codex**, **Gemini**, **Kimi** — und jedes Projekt kann sie alle nutzen, immer. Installierst du später einen neuen Provider, erscheint er beim nächsten Fokussieren der App von selbst überall; keine Neueinrichtung, keine Konfiguration pro Projekt. Ist ein Provider installiert, aber nicht angemeldet, zeigt sein Auswahlmenü ein dezentes *Nicht angemeldet*-Badge.
28
26
 
29
- > Im Hintergrund läuft eine schnelle Prüfung, um sicherzustellen, dass die benötigten Tools vorhanden sind. Fehlt etwas Wesentliches, bleibt die **Hinzufügen**-Schaltfläche deaktiviert, und ein **Weitere Informationen**-Link liefert dir die genauen Installationsbefehle.
27
+ ## Die Einrichtung läuft still im Hintergrund
30
28
 
31
- Klicke auf **Hinzufügen**, um fortzufahren.
29
+ Es gibt keinen Einrichtungsassistenten. Sobald du auf **Hinzufügen** klickst, ist das Projekt registriert und erscheint in deiner Seitenleiste — du kannst es sofort öffnen. Im Hintergrund baut specrails den Workspace des Projekts zusammen (wenige Sekunden, vollständig offline): Ein kleiner pulsierender Punkt in der Projektzeile zeigt die Arbeit an und verschwindet, sobald alles bereit ist. Schlägt etwas für einen Provider fehl, funktioniert das Projekt mit den anderen weiter — ein bernsteinfarbener Punkt erscheint, ein Klick darauf versucht es erneut.
32
30
 
33
- ## Setup, das in Sekunden läuft
31
+ ## Was installiert wird — und wo
34
32
 
35
- Ist der Ordner bereits für specrails konfiguriert, bist du fertig – das Projekt erscheint sofort in deiner Seitenleiste.
33
+ Die Einrichtung ist bewusst **nicht-invasiv**: Dein Repository bleibt unberührt. Alle specrails-Artefakte (Agentendefinitionen, Befehle, Profile, lokale Einstellungen) liegen in einem Workspace pro Projekt unter deinem Home-Verzeichnis, verknüpft mit einer einzigen gemeinsamen Framework-Installation, die mit der App ausgeliefert wird. Dein Repo wird nie verändert — und bei einem App-Update erhält jedes Projekt das neue Framework automatisch, auf einmal.
36
34
 
37
- Handelt es sich um ein frisches Projekt, läuft ein kurzer **Einrichtungsassistent**. Er hat drei Schritte:
38
-
39
- 1. **Konfigurieren** – bestätige die Grundlagen für jeden Provider, den du ausgewählt hast.
40
- 2. **Installieren** – specrails richtet das Projekt automatisch ein. Das ist die *schnelle* Installation: einsatzbereite Vorlagen-Agenten, die in Sekunden bereitstehen. Du siehst dabei ein Live-Log.
41
- 3. **Fertig** – eine Zusammenfassung, die bestätigt, dass alles bereit ist.
42
-
43
- Bei einem Projekt mit mehreren Providern läuft die Installation einmal pro Provider, nacheinander, und der Schritt „Fertig“ zeigt für jeden eine eigene Karte.
44
-
45
- ## Was installiert wird
46
-
47
- Das Setup ist bewusst schlank und **nicht-invasiv**. specrails fügt deinem Projekt eine kleine Menge Konfiguration hinzu, damit die Pipeline weiß, wie sie laufen soll:
48
-
49
- - Einen `.specrails/`-Ordner, der die Agent-Profile und lokalen Einstellungen deines Projekts enthält.
50
- - Agent-Definitionen unter `.claude/agents/`, die die Pipeline Architect → Developer → Reviewer → Ship antreiben.
51
-
52
- Mehr nicht – specrails schreibt deinen Quellcode beim Setup nicht um, und diese Dateien lassen sich problemlos committen, wenn du die Konfiguration mit deinem Team teilen möchtest.
53
-
54
- > **Lieber das tiefgehende Setup?** Die App liefert bewusst die schnelle Vorlagen-Installation. Wenn du den KI-angereicherten Ablauf bevorzugst (Codebasis-Analyse und individuelle Agent-Personas), kannst du `npx specrails-core@latest init` aus deinem Projektordner in einem Terminal ausführen.
35
+ > **Lieber die tiefe Einrichtung?** Die App liefert absichtlich die schnelle Template-Installation. Wenn du den KI-angereicherten Ablauf bevorzugst (Codebasis-Analyse und individuelle Agenten-Personas), kannst du `npx specrails-core@latest init` im Projektordner in einem Terminal ausführen.
55
36
 
56
37
  ## Du bist drin
57
38
 
58
- Sobald das Setup abgeschlossen ist, setzt specrails dich direkt ins Dashboard deines Projekts. Zeit für die Tour – siehe [Die Dashboard-Tour](the-dashboard-tour).
39
+ Das Projekt-Dashboard ist verfügbar, sobald du auf **Hinzufügen** klickst. Zeit für die Tour — siehe [Die Dashboard-Tour](the-dashboard-tour).