specrails-desktop 2.0.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.
- package/.claude/commands/specrails/batch-implement.md +287 -0
- package/.claude/commands/specrails/compat-check.md +271 -0
- package/.claude/commands/specrails/doctor.md +62 -0
- package/.claude/commands/specrails/enrich.md +1635 -0
- package/.claude/commands/specrails/explore-spec.md +173 -0
- package/.claude/commands/specrails/health-check.md +527 -0
- package/.claude/commands/specrails/implement.md +1457 -0
- package/.claude/commands/specrails/memory-inspect.md +259 -0
- package/.claude/commands/specrails/opsx-diff.md +419 -0
- package/.claude/commands/specrails/propose-spec.md +102 -0
- package/.claude/commands/specrails/reconfig.md +89 -0
- package/.claude/commands/specrails/refactor-recommender.md +212 -0
- package/.claude/commands/specrails/retry.md +363 -0
- package/.claude/commands/specrails/telemetry.md +552 -0
- package/.claude/commands/specrails/why.md +96 -0
- package/LICENSE +21 -0
- package/README.md +290 -0
- package/cli/dist/specrails-desktop.js +1098 -0
- package/client/dist/assets/ActivityFeedPage-Gy4x8dBt.js +1 -0
- package/client/dist/assets/AgentsPage-CPgu--Fb.js +86 -0
- package/client/dist/assets/AnalyticsPage-B5sJEee2.js +1 -0
- package/client/dist/assets/BarChart-7IMQ8HY1.js +33 -0
- package/client/dist/assets/CodePage-CBdFvbwe.js +2 -0
- package/client/dist/assets/DesktopAnalyticsPage-w0rdTq4w.js +1 -0
- package/client/dist/assets/DocsDialog-BZUYM7wm.js +11 -0
- package/client/dist/assets/DocsPage-9QglWl46.js +11 -0
- package/client/dist/assets/ExportDropdown-BLZFXtNi.js +1 -0
- package/client/dist/assets/IntegrationsPage-BxBE4y99.js +3 -0
- package/client/dist/assets/JobDetailPage-DydWx_5S.js +16 -0
- package/client/dist/assets/JobsPage-20ibw0IO.js +1 -0
- package/client/dist/assets/abap-Bw6f2wDG.js +1 -0
- package/client/dist/assets/activity-BEIp_Y1A.js +1 -0
- package/client/dist/assets/activity-BdrPln96.js +1 -0
- package/client/dist/assets/activity-CpkRS8Sx.js +1 -0
- package/client/dist/assets/activity-DKCpESPt.js +1 -0
- package/client/dist/assets/activity-DOUVEjJi.js +1 -0
- package/client/dist/assets/activity-DRwkql_y.js +1 -0
- package/client/dist/assets/activity-DcDQ7tjw.js +1 -0
- package/client/dist/assets/activity-Dv6H7wEr.js +1 -0
- package/client/dist/assets/addon-image-3WCl5Vhd.js +1 -0
- package/client/dist/assets/addon-ligatures-C5OdliKs.js +2 -0
- package/client/dist/assets/addon-webgl-BbX6pSjl.js +44 -0
- package/client/dist/assets/addspec-B5yl4Loj.js +1 -0
- package/client/dist/assets/addspec-BEeF5-zc.js +1 -0
- package/client/dist/assets/addspec-D33ocMxf.js +1 -0
- package/client/dist/assets/addspec-DFswZ0jK.js +1 -0
- package/client/dist/assets/addspec-DRE-jZv7.js +1 -0
- package/client/dist/assets/addspec-DVZ15Jp8.js +1 -0
- package/client/dist/assets/addspec-Fkv91Opc.js +1 -0
- package/client/dist/assets/addspec-GWm4ffKl.js +1 -0
- package/client/dist/assets/agents-1nCDWRmP.js +1 -0
- package/client/dist/assets/agents-Bm9rPqnt.js +1 -0
- package/client/dist/assets/agents-CMxtJMLD.js +1 -0
- package/client/dist/assets/agents-DK-Dlc0i.js +1 -0
- package/client/dist/assets/agents-Q6Ldfpxx.js +1 -0
- package/client/dist/assets/agents-TeOSy-ax.js +1 -0
- package/client/dist/assets/agents-iTqjRajS.js +1 -0
- package/client/dist/assets/agents-s87sMGzL.js +1 -0
- package/client/dist/assets/agentstudio-B6Wb59E7.js +1 -0
- package/client/dist/assets/agentstudio-BADhZ41e.js +1 -0
- package/client/dist/assets/agentstudio-BSnWLR63.js +1 -0
- package/client/dist/assets/agentstudio-BdidyBzZ.js +1 -0
- package/client/dist/assets/agentstudio-CxlUllqI.js +1 -0
- package/client/dist/assets/agentstudio-D3I62TLJ.js +1 -0
- package/client/dist/assets/agentstudio-DuH9TogZ.js +1 -0
- package/client/dist/assets/agentstudio-Kw88_dUF.js +1 -0
- package/client/dist/assets/aiedit-BWxHGsYA.js +1 -0
- package/client/dist/assets/aiedit-D2ji6Qy0.js +1 -0
- package/client/dist/assets/aiedit-DAhZTvtk.js +1 -0
- package/client/dist/assets/aiedit-DJMny-D5.js +1 -0
- package/client/dist/assets/aiedit-DOcxERkU.js +1 -0
- package/client/dist/assets/aiedit-DvrcbwGv.js +1 -0
- package/client/dist/assets/aiedit-TTwzL1TS.js +1 -0
- package/client/dist/assets/aiedit-WBSjT_C1.js +1 -0
- package/client/dist/assets/analytics-BIdr0YfL.js +1 -0
- package/client/dist/assets/analytics-C6EzgtdE.js +1 -0
- package/client/dist/assets/analytics-C9Zc-rkM.js +1 -0
- package/client/dist/assets/analytics-CVx3YOc0.js +1 -0
- package/client/dist/assets/analytics-CYj0tfj7.js +1 -0
- package/client/dist/assets/analytics-CnY4kNG3.js +1 -0
- package/client/dist/assets/analytics-CrPCZRJ-.js +1 -0
- package/client/dist/assets/analytics-DMCto-TF.js +1 -0
- package/client/dist/assets/apex-Cw8_REBo.js +1 -0
- package/client/dist/assets/atom-one-dark-B-oHczHB.css +1 -0
- package/client/dist/assets/attachments-BIsSSnHJ.js +1 -0
- package/client/dist/assets/attachments-BW4L3l2L.js +1 -0
- package/client/dist/assets/attachments-Bcf6BG6V.js +1 -0
- package/client/dist/assets/attachments-Bke8sCU4.js +1 -0
- package/client/dist/assets/attachments-COcrGRFz.js +1 -0
- package/client/dist/assets/attachments-DYHGA2Dj.js +1 -0
- package/client/dist/assets/attachments-Dd92KpUH.js +1 -0
- package/client/dist/assets/attachments-DzdU6DV6.js +1 -0
- package/client/dist/assets/azcli-Cz6HAoOw.js +1 -0
- package/client/dist/assets/bat-CcJ-xyqL.js +1 -0
- package/client/dist/assets/bicep-z1WDCKYz.js +2 -0
- package/client/dist/assets/browser-5ErDlJoR.js +1 -0
- package/client/dist/assets/browser-Bc-YdlVg.js +1 -0
- package/client/dist/assets/browser-BlYF4OOq.js +1 -0
- package/client/dist/assets/browser-CT-ReZGt.js +1 -0
- package/client/dist/assets/browser-DGITz3fC.js +1 -0
- package/client/dist/assets/browser-JsAIGCEW.js +1 -0
- package/client/dist/assets/browser-M5-rbPlw.js +1 -0
- package/client/dist/assets/browser-Qya9cARy.js +1 -0
- package/client/dist/assets/cameligo-BRewOpfa.js +1 -0
- package/client/dist/assets/chat-BEGuC03z.js +1 -0
- package/client/dist/assets/chat-BEW60P_u.js +1 -0
- package/client/dist/assets/chat-BQNMD0PL.js +1 -0
- package/client/dist/assets/chat-BsbNGPW9.js +1 -0
- package/client/dist/assets/chat-CboQguCi.js +1 -0
- package/client/dist/assets/chat-DRCa9pOt.js +1 -0
- package/client/dist/assets/chat-DwUm6W9z.js +1 -0
- package/client/dist/assets/chat-yoXwguQu.js +1 -0
- package/client/dist/assets/chunk-CilyBKbf.js +1 -0
- package/client/dist/assets/clojure-DBjRWN6g.js +1 -0
- package/client/dist/assets/clsx-DnqN-uhr.js +1 -0
- package/client/dist/assets/code-AL1rVIMb.js +1 -0
- package/client/dist/assets/code-C0BKpkht.js +1 -0
- package/client/dist/assets/code-C0FTS3ew.js +1 -0
- package/client/dist/assets/code-CPcHxzxw.js +1 -0
- package/client/dist/assets/code-D3ryDniw.js +1 -0
- package/client/dist/assets/code-D3zVVQTj.js +1 -0
- package/client/dist/assets/code-PCmfS3dn.js +1 -0
- package/client/dist/assets/code-exI0G5Wd.js +1 -0
- package/client/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
- package/client/dist/assets/coffee-Cfk_XHGR.js +1 -0
- package/client/dist/assets/commands-B772IyDa.js +1 -0
- package/client/dist/assets/commands-BDDp6xFG.js +1 -0
- package/client/dist/assets/commands-CJxCry-o.js +1 -0
- package/client/dist/assets/commands-CfgY-_of.js +1 -0
- package/client/dist/assets/commands-DLrvnPNg.js +1 -0
- package/client/dist/assets/commands-IXMOKBYt.js +1 -0
- package/client/dist/assets/commands-UD1NzmwX.js +1 -0
- package/client/dist/assets/commands-sqrqsxyE.js +1 -0
- package/client/dist/assets/common-DCr6VzJ7.js +1 -0
- package/client/dist/assets/common-Dard9UNH.js +1 -0
- package/client/dist/assets/common-DeDELLZJ.js +1 -0
- package/client/dist/assets/common-DltqHaAe.js +1 -0
- package/client/dist/assets/common-Dmm1GhdD.js +1 -0
- package/client/dist/assets/common-DnjcgkPH.js +1 -0
- package/client/dist/assets/common-GbpxfPG8.js +1 -0
- package/client/dist/assets/common-wA36jmj1.js +1 -0
- package/client/dist/assets/cpp-BVob6BaP.js +1 -0
- package/client/dist/assets/csharp-C4fbRuOu.js +1 -0
- package/client/dist/assets/csp-DthFP_vT.js +1 -0
- package/client/dist/assets/css-CGMH0hcW.js +3 -0
- package/client/dist/assets/css.worker-Wv5dxAWO.js +89 -0
- package/client/dist/assets/cssMode-Cc6ozl-J.js +1 -0
- package/client/dist/assets/cypher-Pnf68BRV.js +1 -0
- package/client/dist/assets/dart-PMMOtxZX.js +1 -0
- package/client/dist/assets/dashboard-B4ixDVk8.js +1 -0
- package/client/dist/assets/dashboard-BZBADHSj.js +1 -0
- package/client/dist/assets/dashboard-C1MfeUHs.js +1 -0
- package/client/dist/assets/dashboard-C7SK6xu5.js +1 -0
- package/client/dist/assets/dashboard-CB6Le1yN.js +1 -0
- package/client/dist/assets/dashboard-CoTpMOBM.js +1 -0
- package/client/dist/assets/dashboard-Duo4DDCW.js +1 -0
- package/client/dist/assets/dashboard-I19DXBxw.js +1 -0
- package/client/dist/assets/dist-js-BY-Fv_fg.js +1 -0
- package/client/dist/assets/dist-js-Bakc4uxT.js +1 -0
- package/client/dist/assets/dockerfile-di1nsJCc.js +1 -0
- package/client/dist/assets/ecl-D_WVcB5M.js +1 -0
- package/client/dist/assets/editor-Br_kD0ds.css +1 -0
- package/client/dist/assets/editor.api2-XLGzZfbc.js +872 -0
- package/client/dist/assets/editor.main-CfXxHimg.js +6 -0
- package/client/dist/assets/editor.worker-Bd9IXS8d.js +26 -0
- package/client/dist/assets/elixir-OAdJEMOn.js +1 -0
- package/client/dist/assets/explore-4mFpnrKU.js +1 -0
- package/client/dist/assets/explore-A8Ltoblq.js +1 -0
- package/client/dist/assets/explore-B9A3iN2W.js +1 -0
- package/client/dist/assets/explore-BV5Xxlsn.js +1 -0
- package/client/dist/assets/explore-BrBJvfjP.js +1 -0
- package/client/dist/assets/explore-C3FSE42C.js +1 -0
- package/client/dist/assets/explore-D2EFgt8J.js +1 -0
- package/client/dist/assets/explore-hFc3HFcp.js +1 -0
- package/client/dist/assets/flow9-D3QEZjgn.js +1 -0
- package/client/dist/assets/format-command-CwGuwzGA.js +1 -0
- package/client/dist/assets/freemarker2-DP7J1gG3.js +3 -0
- package/client/dist/assets/fsharp-BF0k_8N8.js +1 -0
- package/client/dist/assets/go-BAQO5Jsz.js +1 -0
- package/client/dist/assets/graphql-hdFVFkiV.js +1 -0
- package/client/dist/assets/handlebars-BjRlucw6.js +1 -0
- package/client/dist/assets/hcl-DWnl1o-X.js +1 -0
- package/client/dist/assets/html-OumBQJ-U.js +1 -0
- package/client/dist/assets/html.worker-CQP8QQsS.js +502 -0
- package/client/dist/assets/htmlMode-CStc3zXM.js +1 -0
- package/client/dist/assets/index-CimDRRi7.css +2 -0
- package/client/dist/assets/index-XGZaKl_u.js +142 -0
- package/client/dist/assets/ini-CB-6OVu3.js +1 -0
- package/client/dist/assets/integrations-C3p12Ms6.js +1 -0
- package/client/dist/assets/integrations-Cr6hH7XR.js +1 -0
- package/client/dist/assets/integrations-Cublz3m6.js +1 -0
- package/client/dist/assets/integrations-D28q1kF6.js +1 -0
- package/client/dist/assets/integrations-DRdbki5W.js +1 -0
- package/client/dist/assets/integrations-DaC4SzzL.js +1 -0
- package/client/dist/assets/integrations-DmQYCUvN.js +1 -0
- package/client/dist/assets/integrations-HIlUxXVs.js +1 -0
- package/client/dist/assets/java-d1CmfiHX.js +1 -0
- package/client/dist/assets/javascript-CMk--e7g.js +1 -0
- package/client/dist/assets/jobs-BE1siB0M.js +1 -0
- package/client/dist/assets/jobs-BHcQ_Faf.js +1 -0
- package/client/dist/assets/jobs-CFfc2dNX.js +1 -0
- package/client/dist/assets/jobs-CSi5n8X_.js +1 -0
- package/client/dist/assets/jobs-Dc3X86PY.js +1 -0
- package/client/dist/assets/jobs-De5tASex.js +1 -0
- package/client/dist/assets/jobs-DsoXEdo7.js +1 -0
- package/client/dist/assets/jobs-Wl-ApPMb.js +1 -0
- package/client/dist/assets/json.worker-DzV-CpCQ.js +58 -0
- package/client/dist/assets/jsonMode-C2h3ZcjZ.js +7 -0
- package/client/dist/assets/julia-Bgv08lKa.js +1 -0
- package/client/dist/assets/kotlin-u98kaVTf.js +1 -0
- package/client/dist/assets/less-CjYwpgg5.js +2 -0
- package/client/dist/assets/lexon-YTjaAFBB.js +1 -0
- package/client/dist/assets/lib-CPxTMOAq.js +7 -0
- package/client/dist/assets/liquid-mI3KJrBE.js +1 -0
- package/client/dist/assets/lspLanguageFeatures-DU09ggWi.js +4 -0
- package/client/dist/assets/lua-BzmkWv27.js +1 -0
- package/client/dist/assets/m3-CFwk9fw0.js +1 -0
- package/client/dist/assets/markdown-CR5iMpSZ.js +1 -0
- package/client/dist/assets/mdx-C41VDTR_.js +1 -0
- package/client/dist/assets/mips-CcEalc17.js +1 -0
- package/client/dist/assets/monaco.contribution-CPObAXMC.js +2 -0
- package/client/dist/assets/msdax-BQbkawnr.js +1 -0
- package/client/dist/assets/mysql-GTlaaW_P.js +1 -0
- package/client/dist/assets/nav-0fwkrgHt.js +1 -0
- package/client/dist/assets/nav-BEL3MTwK.js +1 -0
- package/client/dist/assets/nav-B_G-TJDW.js +1 -0
- package/client/dist/assets/nav-C2YXcbZS.js +1 -0
- package/client/dist/assets/nav-ClzOE4mA.js +1 -0
- package/client/dist/assets/nav-CtYwmMgu.js +1 -0
- package/client/dist/assets/nav-D2bOGSEg.js +1 -0
- package/client/dist/assets/nav-iH1V5j6o.js +1 -0
- package/client/dist/assets/objective-c-Byu1T5if.js +1 -0
- package/client/dist/assets/pascal-BrfzBfRm.js +1 -0
- package/client/dist/assets/pascaligo-BXXKFUeo.js +1 -0
- package/client/dist/assets/perl-B3OikKq-.js +1 -0
- package/client/dist/assets/pgsql-CTsa0Acc.js +1 -0
- package/client/dist/assets/php-DiQh3FUW.js +1 -0
- package/client/dist/assets/pla-92uH8Fzm.js +1 -0
- package/client/dist/assets/postiats-BbeWkKUr.js +1 -0
- package/client/dist/assets/powerquery-DgDMzpsm.js +1 -0
- package/client/dist/assets/powershell-BfdUUzaG.js +1 -0
- package/client/dist/assets/preload-helper-DSXbuxSR.js +1 -0
- package/client/dist/assets/protobuf-BojW2ftW.js +2 -0
- package/client/dist/assets/pug-BxqTg3IU.js +1 -0
- package/client/dist/assets/python-Y27rKQtk.js +1 -0
- package/client/dist/assets/qsharp-BX_A-MW9.js +1 -0
- package/client/dist/assets/r-D9BMnxvJ.js +1 -0
- package/client/dist/assets/razor-Cd5-q9Bp.js +1 -0
- package/client/dist/assets/redis-5cJqEQJJ.js +1 -0
- package/client/dist/assets/redshift-d8BBqiwb.js +1 -0
- package/client/dist/assets/restructuredtext-C8a6yIcZ.js +1 -0
- package/client/dist/assets/ruby-egeh-6KX.js +1 -0
- package/client/dist/assets/rust-a3r9IInB.js +1 -0
- package/client/dist/assets/sb-y8iRIDei.js +1 -0
- package/client/dist/assets/scala-BPDK2AmK.js +1 -0
- package/client/dist/assets/scheme-BIWUEoOs.js +1 -0
- package/client/dist/assets/scss-CA-PSzwg.js +3 -0
- package/client/dist/assets/settings-55oDcbSh.js +1 -0
- package/client/dist/assets/settings-Bd4Tq1RB.js +1 -0
- package/client/dist/assets/settings-CCSM-Fhn.js +1 -0
- package/client/dist/assets/settings-D3e_bDoW.js +1 -0
- package/client/dist/assets/settings-DKbTkbn7.js +1 -0
- package/client/dist/assets/settings-Dxpo6_w7.js +1 -0
- package/client/dist/assets/settings-bt84e3Aa.js +1 -0
- package/client/dist/assets/settings-nu68QukM.js +1 -0
- package/client/dist/assets/setup-BMqwfbW9.js +1 -0
- package/client/dist/assets/setup-Bb5LcG28.js +1 -0
- package/client/dist/assets/setup-BeEx2_da.js +1 -0
- package/client/dist/assets/setup-CCCrB53Q.js +1 -0
- package/client/dist/assets/setup-CJA0ATmd.js +1 -0
- package/client/dist/assets/setup-CeiDbZcb.js +1 -0
- package/client/dist/assets/setup-Cus7TApA.js +1 -0
- package/client/dist/assets/setup-D9qOs2Xo.js +1 -0
- package/client/dist/assets/shell--LiT1Bja.js +1 -0
- package/client/dist/assets/solidity-DdqZccZg.js +1 -0
- package/client/dist/assets/sophia-S6-YxNG_.js +1 -0
- package/client/dist/assets/sparql-BSf5kMp2.js +1 -0
- package/client/dist/assets/specs-BFfu3u-a.js +1 -0
- package/client/dist/assets/specs-B__C8-8a.js +1 -0
- package/client/dist/assets/specs-CZ1PsXsC.js +1 -0
- package/client/dist/assets/specs-D2FzlLn9.js +1 -0
- package/client/dist/assets/specs-DaUTrNF9.js +1 -0
- package/client/dist/assets/specs-Dyc5hYeE.js +1 -0
- package/client/dist/assets/specs-cKEh2LXt.js +1 -0
- package/client/dist/assets/specs-k0PyLDVt.js +1 -0
- package/client/dist/assets/sql-D7KgjR8G.js +1 -0
- package/client/dist/assets/st-BnoDa-Ml.js +1 -0
- package/client/dist/assets/swift-DEUHTkUX.js +1 -0
- package/client/dist/assets/systemverilog-Tqb_KPnW.js +1 -0
- package/client/dist/assets/tcl-BmBFS2qq.js +1 -0
- package/client/dist/assets/terminal-80yDMgMF.js +1 -0
- package/client/dist/assets/terminal-Bje4ziIa.js +1 -0
- package/client/dist/assets/terminal-C2WYcFHF.js +1 -0
- package/client/dist/assets/terminal-CSONJOex.js +1 -0
- package/client/dist/assets/terminal-DEqzGtcr.js +1 -0
- package/client/dist/assets/terminal-DeWzh6ys.js +1 -0
- package/client/dist/assets/terminal-YOlsJCQj.js +1 -0
- package/client/dist/assets/terminal-lkZYR4wJ.js +1 -0
- package/client/dist/assets/tickets-CB7N30gm.js +1 -0
- package/client/dist/assets/tickets-CF2PYelu.js +1 -0
- package/client/dist/assets/tickets-DNOANUXr.js +1 -0
- package/client/dist/assets/tickets-DU1aqsbr.js +1 -0
- package/client/dist/assets/tickets-DYvafSaY.js +1 -0
- package/client/dist/assets/tickets-DlpC_iTg.js +1 -0
- package/client/dist/assets/tickets-DucYgtdl.js +1 -0
- package/client/dist/assets/tickets-clefmXLv.js +1 -0
- package/client/dist/assets/ts.worker-METxwbDZ.js +67719 -0
- package/client/dist/assets/tsMode-B0y_xEci.js +11 -0
- package/client/dist/assets/twig-BQV8igWC.js +1 -0
- package/client/dist/assets/typescript-BzK0OgwW.js +1 -0
- package/client/dist/assets/typespec-DlFroUGY.js +1 -0
- package/client/dist/assets/useProjectCache-DSaiGFjV.js +1 -0
- package/client/dist/assets/vb-BlrJpIMX.js +1 -0
- package/client/dist/assets/wgsl-BWgIc6FZ.js +298 -0
- package/client/dist/assets/workers-rt--R2Qy.js +1 -0
- package/client/dist/assets/xml-eX9QXAmI.js +1 -0
- package/client/dist/assets/yaml-fcsNkpOt.js +1 -0
- package/client/dist/index.html +246 -0
- package/docs/README.md +54 -0
- package/docs/cli.md +198 -0
- package/docs/codex.md +210 -0
- package/docs/creating-specs.md +197 -0
- package/docs/customizing.md +197 -0
- package/docs/getting-started.md +140 -0
- package/docs/internals/README.md +25 -0
- package/docs/internals/adding-a-provider.md +238 -0
- package/docs/internals/api-reference.md +634 -0
- package/docs/internals/architecture.md +332 -0
- package/docs/internals/configuration.md +172 -0
- package/docs/internals/openspec-workflow.md +282 -0
- package/docs/internals/operations-runbook.md +198 -0
- package/docs/internals/profiles.md +152 -0
- package/docs/platforms/macos.md +130 -0
- package/docs/platforms/windows.md +81 -0
- package/docs/running-pipelines.md +240 -0
- package/docs/terminal.md +138 -0
- package/docs/tracking-cost.md +155 -0
- package/package.json +82 -0
- package/server/dist/agent-generator.js +232 -0
- package/server/dist/agent-refine-db.js +124 -0
- package/server/dist/agent-refine-manager.js +526 -0
- package/server/dist/ai-invocations.js +111 -0
- package/server/dist/attachment-manager.js +299 -0
- package/server/dist/auth.js +207 -0
- package/server/dist/binary-probe.js +35 -0
- package/server/dist/browser-capture-manager.js +576 -0
- package/server/dist/browser-capture-types.js +28 -0
- package/server/dist/browser-network.js +149 -0
- package/server/dist/browser-playwright.js +888 -0
- package/server/dist/build-dirs.js +44 -0
- package/server/dist/changes-reader.js +120 -0
- package/server/dist/chat-manager.js +1060 -0
- package/server/dist/chromium-resolver.js +311 -0
- package/server/dist/code-explorer-router.js +788 -0
- package/server/dist/codex-otel-bridge.js +235 -0
- package/server/dist/command-resolver.js +102 -0
- package/server/dist/config.js +306 -0
- package/server/dist/context-budget.js +113 -0
- package/server/dist/context-scope.js +279 -0
- package/server/dist/contract-refine-runner.js +521 -0
- package/server/dist/core-compat.js +207 -0
- package/server/dist/core-package.js +14 -0
- package/server/dist/db.js +1034 -0
- package/server/dist/desktop-analytics.js +156 -0
- package/server/dist/desktop-db.js +456 -0
- package/server/dist/desktop-router.js +735 -0
- package/server/dist/docs-router.js +207 -0
- package/server/dist/explore-contract-refine.js +421 -0
- package/server/dist/explore-cwd-manager.js +242 -0
- package/server/dist/explore-draft-title.js +47 -0
- package/server/dist/explore-smash.js +450 -0
- package/server/dist/feature-flags.js +17 -0
- package/server/dist/file-provenance.js +382 -0
- package/server/dist/file-summary-generator.js +221 -0
- package/server/dist/file-summary-manager.js +689 -0
- package/server/dist/hooks.js +102 -0
- package/server/dist/ids.js +7 -0
- package/server/dist/index.js +586 -0
- package/server/dist/metrics.js +136 -0
- package/server/dist/mobile/index.js +16 -0
- package/server/dist/mobile/mobile-admin-router.js +84 -0
- package/server/dist/mobile/mobile-auth.js +67 -0
- package/server/dist/mobile/mobile-devices.js +80 -0
- package/server/dist/mobile/mobile-event-bus.js +39 -0
- package/server/dist/mobile/mobile-gateway.js +285 -0
- package/server/dist/mobile/mobile-mdns.js +81 -0
- package/server/dist/mobile/mobile-pairing.js +179 -0
- package/server/dist/mobile/mobile-redact.js +53 -0
- package/server/dist/mobile/mobile-router.js +411 -0
- package/server/dist/mobile/mobile-tls.js +86 -0
- package/server/dist/mobile/mobile-types.js +9 -0
- package/server/dist/mobile/mobile-ws.js +275 -0
- package/server/dist/path-resolver.js +298 -0
- package/server/dist/plugin-manager.js +617 -0
- package/server/dist/plugins/claude-approval.js +179 -0
- package/server/dist/plugins/claude-md-mutation.js +146 -0
- package/server/dist/plugins/codex-mcp.js +108 -0
- package/server/dist/plugins/contributors.js +72 -0
- package/server/dist/plugins/drift.js +58 -0
- package/server/dist/plugins/index.js +14 -0
- package/server/dist/plugins/json-mutation.js +120 -0
- package/server/dist/plugins/manager.js +32 -0
- package/server/dist/plugins/ownership.js +86 -0
- package/server/dist/plugins/paths.js +37 -0
- package/server/dist/plugins/prereq-installer.js +104 -0
- package/server/dist/plugins/rail-integration.js +79 -0
- package/server/dist/plugins/serena/index.js +13 -0
- package/server/dist/plugins/serena/install.js +91 -0
- package/server/dist/plugins/serena/instructions-content.js +21 -0
- package/server/dist/plugins/serena/manifest.js +111 -0
- package/server/dist/plugins/serena/verify.js +78 -0
- package/server/dist/plugins-router.js +215 -0
- package/server/dist/pricing.js +89 -0
- package/server/dist/profile-manager.js +310 -0
- package/server/dist/profiles-router.js +759 -0
- package/server/dist/project-registry.js +443 -0
- package/server/dist/project-router.js +4016 -0
- package/server/dist/proposal-manager.js +291 -0
- package/server/dist/provider-selection.js +69 -0
- package/server/dist/providers/claude-adapter.js +281 -0
- package/server/dist/providers/codex-adapter.js +264 -0
- package/server/dist/providers/index.js +23 -0
- package/server/dist/providers/registry.js +37 -0
- package/server/dist/providers/types.js +22 -0
- package/server/dist/queue-manager.js +1511 -0
- package/server/dist/rails-router.js +362 -0
- package/server/dist/rails-store.js +116 -0
- package/server/dist/result-event.js +106 -0
- package/server/dist/schemas/profile.v1.json +151 -0
- package/server/dist/setup-manager.js +1165 -0
- package/server/dist/setup-prerequisites.js +372 -0
- package/server/dist/smash-runner.js +663 -0
- package/server/dist/spec-draft-parser.js +133 -0
- package/server/dist/spec-launcher-manager.js +174 -0
- package/server/dist/spec-models.js +32 -0
- package/server/dist/specrails-tech-client.js +82 -0
- package/server/dist/spending.js +448 -0
- package/server/dist/telemetry-compactor.js +180 -0
- package/server/dist/telemetry-export.js +317 -0
- package/server/dist/telemetry-receiver.js +224 -0
- package/server/dist/terminal-manager.js +633 -0
- package/server/dist/terminal-marks-store.js +117 -0
- package/server/dist/terminal-osc-parser.js +159 -0
- package/server/dist/terminal-settings.js +282 -0
- package/server/dist/terminal-shell-integration.js +196 -0
- package/server/dist/ticket-broadcast.js +47 -0
- package/server/dist/ticket-store.js +397 -0
- package/server/dist/ticket-watcher.js +117 -0
- package/server/dist/types.js +10 -0
- package/server/dist/user-mcp-config.js +117 -0
- package/server/dist/util/cli-prompt.js +181 -0
- package/server/dist/util/secure-fs.js +50 -0
- package/server/dist/util/win-spawn.js +43 -0
- package/server/dist/webhook-manager.js +89 -0
- package/server/dist/ws-routing.js +47 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MIN_VERSIONS = void 0;
|
|
7
|
+
exports.parseSemver = parseSemver;
|
|
8
|
+
exports.compareVersions = compareVersions;
|
|
9
|
+
exports.getSetupPrerequisitesStatus = getSetupPrerequisitesStatus;
|
|
10
|
+
exports.__resetSetupPrerequisitesCacheForTest = __resetSetupPrerequisitesCacheForTest;
|
|
11
|
+
exports.formatMissingSetupPrerequisites = formatMissingSetupPrerequisites;
|
|
12
|
+
const child_process_1 = require("child_process");
|
|
13
|
+
const fs_1 = __importDefault(require("fs"));
|
|
14
|
+
const path_1 = __importDefault(require("path"));
|
|
15
|
+
const providers_1 = require("./providers");
|
|
16
|
+
const WHICH_CMD = process.platform === 'win32' ? 'where' : 'which';
|
|
17
|
+
exports.MIN_VERSIONS = {
|
|
18
|
+
node: '18.0.0',
|
|
19
|
+
npm: '9.0.0',
|
|
20
|
+
git: '2.20.0',
|
|
21
|
+
uv: '0.1.0',
|
|
22
|
+
};
|
|
23
|
+
function locateCommand(command) {
|
|
24
|
+
const result = (0, child_process_1.spawnSync)(WHICH_CMD, [command], {
|
|
25
|
+
env: process.env,
|
|
26
|
+
shell: process.platform === 'win32',
|
|
27
|
+
encoding: 'utf-8',
|
|
28
|
+
});
|
|
29
|
+
if (result.error || (result.status ?? 1) !== 0)
|
|
30
|
+
return { found: false };
|
|
31
|
+
const resolvedPath = `${result.stdout ?? ''}`.trim().split(/\r?\n/)[0]?.trim() || undefined;
|
|
32
|
+
return { found: true, resolvedPath };
|
|
33
|
+
}
|
|
34
|
+
function probeVersion(command, resolvedPath) {
|
|
35
|
+
// IMPORTANT: prefer the absolute path returned by `which`. When the server is
|
|
36
|
+
// bundled with `pkg`, calling spawn with the bare command name `'node'` is
|
|
37
|
+
// intercepted by pkg's child_process patch and redirected to `process.execPath`
|
|
38
|
+
// (the server binary itself) — the child then crashes with
|
|
39
|
+
// `Cannot find module '/--version'` from pkg/prelude/bootstrap.js. Passing
|
|
40
|
+
// an absolute path bypasses this interception.
|
|
41
|
+
const target = resolvedPath || command;
|
|
42
|
+
// On Windows we must use `shell: true` to execute `.cmd` shims (npm, npx) — Node
|
|
43
|
+
// refuses to spawn them directly since CVE-2024-27980. But cmd.exe splits the
|
|
44
|
+
// command line on whitespace, so an absolute path like
|
|
45
|
+
// `C:\Program Files\Git\cmd\git.exe` becomes `C:\Program` + arg `Files\Git\...`.
|
|
46
|
+
// Wrap the target in double quotes when it contains a space.
|
|
47
|
+
const isWin = process.platform === 'win32';
|
|
48
|
+
const quotedTarget = isWin && /\s/.test(target) ? `"${target}"` : target;
|
|
49
|
+
const result = (0, child_process_1.spawnSync)(quotedTarget, ['--version'], {
|
|
50
|
+
env: process.env,
|
|
51
|
+
shell: isWin,
|
|
52
|
+
encoding: 'utf-8',
|
|
53
|
+
timeout: 5_000,
|
|
54
|
+
});
|
|
55
|
+
if (result.error) {
|
|
56
|
+
const err = result.error;
|
|
57
|
+
return { executed: false, error: `${err.code ?? 'ERR'}: ${err.message}` };
|
|
58
|
+
}
|
|
59
|
+
if ((result.status ?? 1) !== 0) {
|
|
60
|
+
const stderr = `${result.stderr ?? ''}`.trim().slice(0, 400);
|
|
61
|
+
const signal = result.signal ? ` signal=${result.signal}` : '';
|
|
62
|
+
return { executed: false, error: `exit=${result.status ?? '?'}${signal}${stderr ? ` stderr=${stderr}` : ''}` };
|
|
63
|
+
}
|
|
64
|
+
const output = `${result.stdout ?? result.stderr ?? ''}`.trim();
|
|
65
|
+
const version = output.split(/\r?\n/)[0]?.trim() || undefined;
|
|
66
|
+
return { executed: true, version };
|
|
67
|
+
}
|
|
68
|
+
/** Extracts the first `major.minor.patch` triple from a version string.
|
|
69
|
+
* Tolerates prefixes like `v`, `git version `, `node `. */
|
|
70
|
+
function parseSemver(raw) {
|
|
71
|
+
if (!raw)
|
|
72
|
+
return null;
|
|
73
|
+
const match = raw.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
74
|
+
if (!match)
|
|
75
|
+
return null;
|
|
76
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
77
|
+
}
|
|
78
|
+
function compareVersions(a, b) {
|
|
79
|
+
const pa = parseSemver(a);
|
|
80
|
+
const pb = parseSemver(b);
|
|
81
|
+
if (!pa || !pb)
|
|
82
|
+
return 0;
|
|
83
|
+
for (let i = 0; i < 3; i++) {
|
|
84
|
+
if (pa[i] !== pb[i])
|
|
85
|
+
return pa[i] - pb[i];
|
|
86
|
+
}
|
|
87
|
+
return 0;
|
|
88
|
+
}
|
|
89
|
+
function meetsMinimumVersion(version, minVersion) {
|
|
90
|
+
if (!minVersion)
|
|
91
|
+
return true;
|
|
92
|
+
if (!version)
|
|
93
|
+
return false;
|
|
94
|
+
return compareVersions(version, minVersion) >= 0;
|
|
95
|
+
}
|
|
96
|
+
function brokenSymlinkHint(label, command, resolvedPath) {
|
|
97
|
+
const where = resolvedPath ? ` at ${resolvedPath}` : '';
|
|
98
|
+
return `${label} found${where} but failed to execute — possibly a broken symlink or a stale install. Reinstall ${command} or remove the stale link${resolvedPath ? ` at ${resolvedPath}` : ''}.`;
|
|
99
|
+
}
|
|
100
|
+
const BUNDLED_TOOL_KEYS = new Set(['node', 'npm', 'npx', 'git']);
|
|
101
|
+
function isBundledTool(key) {
|
|
102
|
+
return BUNDLED_TOOL_KEYS.has(key);
|
|
103
|
+
}
|
|
104
|
+
/** Candidate absolute paths for a bundled tool, in priority order. Windows git
|
|
105
|
+
* ships the real binary at git/cmd/git.exe with a redirector at git/bin/git.exe
|
|
106
|
+
* — we accept either so a layout shift in the PortableGit extractor degrades to
|
|
107
|
+
* a working alternate rather than a false "corrupted-bundle". */
|
|
108
|
+
function getBundledToolCandidates(runtimesBase, tool) {
|
|
109
|
+
if (process.platform === 'win32') {
|
|
110
|
+
const map = {
|
|
111
|
+
node: [path_1.default.join(runtimesBase, 'node', 'node.exe')],
|
|
112
|
+
npm: [path_1.default.join(runtimesBase, 'node', 'npm.cmd')],
|
|
113
|
+
npx: [path_1.default.join(runtimesBase, 'node', 'npx.cmd')],
|
|
114
|
+
git: [path_1.default.join(runtimesBase, 'git', 'cmd', 'git.exe'), path_1.default.join(runtimesBase, 'git', 'bin', 'git.exe')],
|
|
115
|
+
};
|
|
116
|
+
return map[tool];
|
|
117
|
+
}
|
|
118
|
+
const map = {
|
|
119
|
+
node: [path_1.default.join(runtimesBase, 'node', 'bin', 'node')],
|
|
120
|
+
npm: [path_1.default.join(runtimesBase, 'node', 'bin', 'npm')],
|
|
121
|
+
npx: [path_1.default.join(runtimesBase, 'node', 'bin', 'npx')],
|
|
122
|
+
git: [path_1.default.join(runtimesBase, 'git', 'bin', 'git')],
|
|
123
|
+
};
|
|
124
|
+
return map[tool];
|
|
125
|
+
}
|
|
126
|
+
function fileExists(p) {
|
|
127
|
+
try {
|
|
128
|
+
return fs_1.default.existsSync(p);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Short-lived memo: probing involves up to ~12 synchronous spawnSync calls that
|
|
135
|
+
// block the single Express event loop. The endpoint only fires from low-freq
|
|
136
|
+
// setup flows, so a 30s TTL eliminates repeated probe storms (cold-cache
|
|
137
|
+
// client, window-focus rechecks) without masking real PATH changes.
|
|
138
|
+
let _statusCache = null;
|
|
139
|
+
const STATUS_CACHE_TTL_MS = 30_000;
|
|
140
|
+
function getSetupPrerequisitesStatus(options = {}) {
|
|
141
|
+
const key = options.includeUv ? 'uv' : 'base';
|
|
142
|
+
const now = Date.now();
|
|
143
|
+
if (_statusCache && _statusCache.key === key && now - _statusCache.at < STATUS_CACHE_TTL_MS) {
|
|
144
|
+
return _statusCache.value;
|
|
145
|
+
}
|
|
146
|
+
const value = computeSetupPrerequisitesStatus(options);
|
|
147
|
+
_statusCache = { key, at: now, value };
|
|
148
|
+
return value;
|
|
149
|
+
}
|
|
150
|
+
/** Test-only: clear the short-lived prerequisites memo so each test re-probes. */
|
|
151
|
+
function __resetSetupPrerequisitesCacheForTest() {
|
|
152
|
+
_statusCache = null;
|
|
153
|
+
}
|
|
154
|
+
function computeSetupPrerequisitesStatus(options = {}) {
|
|
155
|
+
const isDesktop = process.env.SPECRAILS_IS_DESKTOP === '1';
|
|
156
|
+
const runtimesBase = process.env.SPECRAILS_BUNDLED_RUNTIMES_PATH ?? '';
|
|
157
|
+
const platform = process.platform === 'darwin'
|
|
158
|
+
? 'darwin'
|
|
159
|
+
: process.platform === 'win32'
|
|
160
|
+
? 'win32'
|
|
161
|
+
: 'linux';
|
|
162
|
+
const definitions = [
|
|
163
|
+
{
|
|
164
|
+
key: 'node',
|
|
165
|
+
kind: 'tool',
|
|
166
|
+
label: 'Node.js',
|
|
167
|
+
command: 'node',
|
|
168
|
+
required: true,
|
|
169
|
+
minVersion: exports.MIN_VERSIONS.node,
|
|
170
|
+
installUrl: 'https://nodejs.org/en/download',
|
|
171
|
+
installHint: process.platform === 'win32'
|
|
172
|
+
? 'Install Node.js LTS, then restart Specrails so Windows refreshes PATH.'
|
|
173
|
+
: 'Install Node.js LTS, then restart Specrails so PATH is refreshed.',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
key: 'npm',
|
|
177
|
+
kind: 'tool',
|
|
178
|
+
label: 'npm',
|
|
179
|
+
command: 'npm',
|
|
180
|
+
required: true,
|
|
181
|
+
minVersion: exports.MIN_VERSIONS.npm,
|
|
182
|
+
installUrl: 'https://nodejs.org/en/download',
|
|
183
|
+
installHint: 'npm ships with Node.js LTS.',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
key: 'npx',
|
|
187
|
+
kind: 'tool',
|
|
188
|
+
label: 'npx',
|
|
189
|
+
command: 'npx',
|
|
190
|
+
required: true,
|
|
191
|
+
installUrl: 'https://nodejs.org/en/download',
|
|
192
|
+
installHint: 'npx ships with npm and is required to run specrails-core.',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
key: 'git',
|
|
196
|
+
kind: 'tool',
|
|
197
|
+
label: 'Git',
|
|
198
|
+
command: 'git',
|
|
199
|
+
required: true,
|
|
200
|
+
minVersion: exports.MIN_VERSIONS.git,
|
|
201
|
+
installUrl: process.platform === 'win32'
|
|
202
|
+
? 'https://git-scm.com/download/win'
|
|
203
|
+
: 'https://git-scm.com/downloads',
|
|
204
|
+
installHint: process.platform === 'win32'
|
|
205
|
+
? 'Install Git for Windows and enable the option that adds Git to PATH, then restart Specrails.'
|
|
206
|
+
: 'Install Git and restart Specrails if PATH changed.',
|
|
207
|
+
},
|
|
208
|
+
];
|
|
209
|
+
// Provider CLIs (one entry per registered adapter). Individually `required:
|
|
210
|
+
// false` — the "at least one provider" rule is enforced at the bottom of
|
|
211
|
+
// this function, not via `required`.
|
|
212
|
+
for (const adapter of (0, providers_1.listAdapters)()) {
|
|
213
|
+
definitions.push({
|
|
214
|
+
key: adapter.id,
|
|
215
|
+
kind: 'provider',
|
|
216
|
+
label: adapter.displayName,
|
|
217
|
+
command: adapter.binary,
|
|
218
|
+
required: false,
|
|
219
|
+
minVersion: adapter.minCliVersion ?? undefined,
|
|
220
|
+
installUrl: providerInstallUrl(adapter.id),
|
|
221
|
+
installHint: providerInstallHint(adapter.id, process.platform),
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
if (options.includeUv) {
|
|
225
|
+
definitions.push({
|
|
226
|
+
key: 'uv',
|
|
227
|
+
kind: 'tool',
|
|
228
|
+
label: 'uv',
|
|
229
|
+
command: 'uv',
|
|
230
|
+
required: false,
|
|
231
|
+
minVersion: exports.MIN_VERSIONS.uv,
|
|
232
|
+
installUrl: 'https://docs.astral.sh/uv/getting-started/installation/',
|
|
233
|
+
installHint: process.platform === 'win32'
|
|
234
|
+
? 'Install uv via winget (`winget install astral-sh.uv`) or PowerShell installer, then restart Specrails.'
|
|
235
|
+
: process.platform === 'darwin'
|
|
236
|
+
? 'Install uv via Homebrew (`brew install uv`) or the curl installer, then restart Specrails.'
|
|
237
|
+
: 'Install uv via the curl installer (`curl -LsSf https://astral.sh/uv/install.sh | sh`), then restart Specrails.',
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
const prerequisites = definitions.map((definition) => {
|
|
241
|
+
// Desktop mode: probe bundled absolute paths for node/npm/npx/git.
|
|
242
|
+
// Provider CLIs (claude, codex) are always probed via system PATH regardless of mode.
|
|
243
|
+
if (isDesktop && definition.kind === 'tool' && isBundledTool(definition.key)) {
|
|
244
|
+
const candidates = getBundledToolCandidates(runtimesBase, definition.key);
|
|
245
|
+
const bundledPath = candidates.find(fileExists);
|
|
246
|
+
// Only treat as bundled when the binary FILE actually exists. A missing
|
|
247
|
+
// file means this build never shipped runtimes for this platform/arch
|
|
248
|
+
// (e.g. a runtimes-less Windows ARM64 build, or a partial CI extraction)
|
|
249
|
+
// — fall through to the system probe so a system-installed tool still
|
|
250
|
+
// satisfies the requirement, instead of dead-ending Add Project with a
|
|
251
|
+
// futile "reinstall the app" message. 'corrupted-bundle' is reserved for
|
|
252
|
+
// the case where the file EXISTS but fails its --version probe.
|
|
253
|
+
if (bundledPath) {
|
|
254
|
+
const probe = probeVersion(definition.key, bundledPath);
|
|
255
|
+
if (!probe.executed) {
|
|
256
|
+
return {
|
|
257
|
+
...definition,
|
|
258
|
+
installed: true,
|
|
259
|
+
executable: false,
|
|
260
|
+
bundled: true,
|
|
261
|
+
error: 'corrupted-bundle',
|
|
262
|
+
resolvedPath: bundledPath,
|
|
263
|
+
executionError: probe.error,
|
|
264
|
+
meetsMinimum: false,
|
|
265
|
+
installHint: 'Bundle corrupted — reinstall the Specrails app.',
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
...definition,
|
|
270
|
+
installed: true,
|
|
271
|
+
executable: true,
|
|
272
|
+
bundled: true,
|
|
273
|
+
version: probe.version,
|
|
274
|
+
resolvedPath: bundledPath,
|
|
275
|
+
meetsMinimum: meetsMinimumVersion(probe.version, definition.minVersion),
|
|
276
|
+
installHint: '',
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
// bundledPath not found → fall through to the system probe below.
|
|
280
|
+
}
|
|
281
|
+
// Non-desktop (or provider CLI in any mode, or desktop with bundle absent): system probe.
|
|
282
|
+
const lookup = locateCommand(definition.command);
|
|
283
|
+
const installed = lookup.found;
|
|
284
|
+
let executable = false;
|
|
285
|
+
let version;
|
|
286
|
+
let executionError;
|
|
287
|
+
if (installed) {
|
|
288
|
+
const probe = probeVersion(definition.command, lookup.resolvedPath);
|
|
289
|
+
executable = probe.executed;
|
|
290
|
+
version = probe.version;
|
|
291
|
+
executionError = probe.error;
|
|
292
|
+
}
|
|
293
|
+
const meetsMinimum = installed && executable && meetsMinimumVersion(version, definition.minVersion);
|
|
294
|
+
const installHint = installed && !executable
|
|
295
|
+
? brokenSymlinkHint(definition.label, definition.command, lookup.resolvedPath)
|
|
296
|
+
: definition.installHint;
|
|
297
|
+
return {
|
|
298
|
+
...definition,
|
|
299
|
+
installed,
|
|
300
|
+
executable,
|
|
301
|
+
version,
|
|
302
|
+
resolvedPath: lookup.resolvedPath,
|
|
303
|
+
executionError,
|
|
304
|
+
meetsMinimum,
|
|
305
|
+
installHint,
|
|
306
|
+
};
|
|
307
|
+
});
|
|
308
|
+
// A required tool counts as missing if not installed, not executable, or below its minimum version.
|
|
309
|
+
const missingRequired = prerequisites.filter((item) => item.required && (!item.installed || !item.executable || !item.meetsMinimum));
|
|
310
|
+
// At-least-one provider rule: if no provider entry is usable, surface a
|
|
311
|
+
// synthetic "missing required" entry so the UI blocks Add Project.
|
|
312
|
+
const providers = prerequisites.filter((p) => p.kind === 'provider');
|
|
313
|
+
const anyProviderUsable = providers.some((p) => p.installed && p.executable && p.meetsMinimum);
|
|
314
|
+
if (providers.length > 0 && !anyProviderUsable) {
|
|
315
|
+
// Mark all provider rows as missingRequired so PrerequisitesPanel renders
|
|
316
|
+
// them visibly. They keep `required: false` so the type still matches the
|
|
317
|
+
// tool semantics; the panel inspects `kind === 'provider'` for grouping.
|
|
318
|
+
for (const p of providers)
|
|
319
|
+
missingRequired.push(p);
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
ok: missingRequired.length === 0,
|
|
323
|
+
platform,
|
|
324
|
+
prerequisites,
|
|
325
|
+
missingRequired,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
// ─── Provider install hints ────────────────────────────────────────────────
|
|
329
|
+
function providerInstallUrl(id) {
|
|
330
|
+
switch (id) {
|
|
331
|
+
case 'claude':
|
|
332
|
+
return 'https://claude.com/download';
|
|
333
|
+
case 'codex':
|
|
334
|
+
return 'https://developers.openai.com/codex';
|
|
335
|
+
default:
|
|
336
|
+
return 'https://github.com';
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function providerInstallHint(id, platform) {
|
|
340
|
+
switch (id) {
|
|
341
|
+
case 'claude':
|
|
342
|
+
return 'Install Claude Code from https://claude.com/download, run `claude login`, then restart Specrails.';
|
|
343
|
+
case 'codex':
|
|
344
|
+
return platform === 'darwin'
|
|
345
|
+
? 'Install Codex CLI via `brew install codex` (or follow https://developers.openai.com/codex), authenticate with `codex login`, then restart Specrails.'
|
|
346
|
+
: platform === 'win32'
|
|
347
|
+
? 'Install Codex CLI from https://developers.openai.com/codex, authenticate with `codex login`, then restart Specrails.'
|
|
348
|
+
: 'Install Codex CLI from https://developers.openai.com/codex (or `pipx install codex-cli`), authenticate with `codex login`, then restart Specrails.';
|
|
349
|
+
default:
|
|
350
|
+
return `Install the ${id} CLI and restart Specrails.`;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function formatMissingSetupPrerequisites(status = getSetupPrerequisitesStatus()) {
|
|
354
|
+
if (status.ok)
|
|
355
|
+
return null;
|
|
356
|
+
return [
|
|
357
|
+
'SpecRails setup needs a few developer tools before it can install this project.',
|
|
358
|
+
'',
|
|
359
|
+
...status.missingRequired.map((item) => {
|
|
360
|
+
if (!item.installed) {
|
|
361
|
+
return `- ${item.label} (${item.command}) is not on PATH. ${item.installHint}`;
|
|
362
|
+
}
|
|
363
|
+
if (!item.executable) {
|
|
364
|
+
return `- ${item.installHint}`;
|
|
365
|
+
}
|
|
366
|
+
// installed and executable but below minimum version
|
|
367
|
+
return `- ${item.label} ${item.version ?? '?'} found, but version ${item.minVersion}+ is required. ${item.installHint}`;
|
|
368
|
+
}),
|
|
369
|
+
'',
|
|
370
|
+
'Install the missing tools, restart Specrails, then retry setup.',
|
|
371
|
+
].join('\n');
|
|
372
|
+
}
|