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,140 @@
|
|
|
1
|
+
# Getting started
|
|
2
|
+
|
|
3
|
+
This guide walks you from "I just heard about specrails-desktop" to "I just shipped my first AI-driven change" in about ten minutes. No prior knowledge of specrails-core required — the app installs it for you.
|
|
4
|
+
|
|
5
|
+
## What you'll need
|
|
6
|
+
|
|
7
|
+
- **An AI CLI signed in** — either [Claude Code](https://claude.com/claude-code) (via Claude subscription login or an `ANTHROPIC_API_KEY`) or the Codex CLI. You can use one or both — see [Codex](codex.md).
|
|
8
|
+
- A project you want to work on (any Git repository works)
|
|
9
|
+
|
|
10
|
+
If you install with **npm** (Option 2 below) you'll also need **Node.js 20+** and **`git`** on your PATH. The **desktop app** bundles its own Node and Git runtimes, so you don't need those installed separately.
|
|
11
|
+
|
|
12
|
+
That's it. specrails-desktop will install specrails-core in your project on first run if it isn't there yet.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
Two options:
|
|
17
|
+
|
|
18
|
+
### Option 1 — Desktop app (recommended)
|
|
19
|
+
|
|
20
|
+
Download a signed build for your OS from `https://specrails.dev/downloads/specrails-desktop/latest/`:
|
|
21
|
+
|
|
22
|
+
- **macOS** — `specrails-desktop-<version>-aarch64.dmg` (Apple Silicon, notarised)
|
|
23
|
+
- **Windows** — `specrails-desktop-<version>-x64-setup.exe` (NSIS) or `.msi`
|
|
24
|
+
|
|
25
|
+
Open the installer, drag to Applications (macOS) or click through the wizard (Windows). The app bundles the server, so you don't need a separate process. macOS handles all the Homebrew/Volta/nvm PATH gymnastics for you — see [platforms/macos.md](platforms/macos.md) if anything looks off.
|
|
26
|
+
|
|
27
|
+
> First Windows launch shows a SmartScreen warning until the installer is code-signed. Click **More info → Run anyway**. Details and hash-verification steps in [platforms/windows.md](platforms/windows.md).
|
|
28
|
+
|
|
29
|
+
### Option 2 — npm
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g specrails-desktop
|
|
33
|
+
specrails-desktop start
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
By default the app binds to `http://127.0.0.1:4200`. Open it in your browser.
|
|
37
|
+
|
|
38
|
+
## Add a project
|
|
39
|
+
|
|
40
|
+
There are two ways. Pick whichever feels natural.
|
|
41
|
+
|
|
42
|
+
**From the dashboard:**
|
|
43
|
+
|
|
44
|
+
1. Click **+** in the left sidebar.
|
|
45
|
+
2. Enter the absolute path to your project (e.g. `/Users/you/repos/my-app`).
|
|
46
|
+
3. Pick your **AI providers**. Check **Claude**, **Codex**, or both — when you select both, the first one becomes the project default. The provider set is fixed once the project is created.
|
|
47
|
+
4. The prerequisites panel verifies `node`, `npm`, `npx`, `git`. If anything's missing, the panel surfaces OS-aware install commands you can copy.
|
|
48
|
+
5. Click **Add**.
|
|
49
|
+
|
|
50
|
+
**From the CLI:**
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
specrails-desktop add /path/to/your/project
|
|
54
|
+
specrails-desktop list # verify
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### If the project doesn't have specrails-core yet
|
|
58
|
+
|
|
59
|
+
The setup wizard runs automatically. Three steps:
|
|
60
|
+
|
|
61
|
+
1. **Configure** — choose which agents to install (the baseline trio `sr-architect`, `sr-developer`, `sr-reviewer` is always selected; optional agents like Test Writer or Security Reviewer are opt-in). Pick a model preset (Balanced / Budget / Max) and optionally override the model per agent.
|
|
62
|
+
2. **Install** — the app runs the installer (`npx specrails-core@latest init --yes --from-config <config>`) non-interactively and streams the output live.
|
|
63
|
+
3. **Done** — a summary tells you how many agents and commands landed. Click **Continue to project**.
|
|
64
|
+
|
|
65
|
+
That's the whole onboarding. No tier picker, no second wizard. You can manage agents and their per-agent models later from the **Agents** page (Profiles tab).
|
|
66
|
+
|
|
67
|
+
## Your first spec
|
|
68
|
+
|
|
69
|
+
A "spec" is a description of work you want done. specrails-desktop gives you two ways to author them.
|
|
70
|
+
|
|
71
|
+
### Quick mode — one-shot generation
|
|
72
|
+
|
|
73
|
+
When you already know what you want:
|
|
74
|
+
|
|
75
|
+
1. On the Dashboard, click **+ Add Spec → Quick**.
|
|
76
|
+
2. Type a one-line title (e.g. *"Add a webhook retry with exponential backoff"*).
|
|
77
|
+
3. (Optional) toggle **Enrich with Contract Layer** to get a structured block of names, data shapes, invariants, and a file touch list appended to the description.
|
|
78
|
+
4. Hit Enter.
|
|
79
|
+
|
|
80
|
+
Your AI CLI generates the full spec in one turn. A small toast at the bottom right shows the project, the spec title, and live elapsed time ("Generating… 0:12") — it turns into a success or failure toast (with a **View** action) when generation finishes.
|
|
81
|
+
|
|
82
|
+
### Explore mode — converse with the AI
|
|
83
|
+
|
|
84
|
+
When the spec needs shaping:
|
|
85
|
+
|
|
86
|
+
1. Click **+ Add Spec → Explore**.
|
|
87
|
+
2. (Optional) pick a context preset from the slider — `Minimal` (just your message) up to `Desktop` (the full codebase + Contract Layer enrichment + project and user-approved MCPs).
|
|
88
|
+
3. Type a starting message. The AI responds with a live draft below.
|
|
89
|
+
4. Iterate. Each turn updates the draft.
|
|
90
|
+
5. Click **Save as Draft** to come back later, or **Create Spec** when the draft looks right.
|
|
91
|
+
|
|
92
|
+
The committed spec lands on your board with status `todo`.
|
|
93
|
+
|
|
94
|
+
## Run your first pipeline
|
|
95
|
+
|
|
96
|
+
The right pane of the Dashboard is your **Rails** — execution lanes:
|
|
97
|
+
|
|
98
|
+
1. Drag a spec card from the left pane onto a Rail.
|
|
99
|
+
2. (Optional) pick an **agent profile** from the rail header. This picker only appears once the project has profiles (create them on the **Agents** page); otherwise the rail runs in legacy mode (single orchestrator, no per-agent overrides).
|
|
100
|
+
3. Press **▶ Play** on the rail.
|
|
101
|
+
|
|
102
|
+
The rail flips to running. The Jobs page (right sidebar) streams the AI's output live. When the slash command defines them, you'll see the pipeline phases progress: Architect → Developer → Reviewer → Ship.
|
|
103
|
+
|
|
104
|
+
Token usage, duration, and cost are tracked per turn and surface in:
|
|
105
|
+
|
|
106
|
+
- **Jobs page** — each job has a status panel with live counters and a `JobTicketHeader` chip for every ticket the job touched (click to open).
|
|
107
|
+
- **Analytics page** — burn rate, top tickets, daily timeline (see [Tracking cost](tracking-cost.md)).
|
|
108
|
+
- **The spec's detail modal** — a one-line spending summary linking back to Analytics filtered by that ticket.
|
|
109
|
+
|
|
110
|
+
## What's next?
|
|
111
|
+
|
|
112
|
+
- **[Creating specs](creating-specs.md)** — drafts, SMASH (decompose epics), Continue Editing (refine specs in place), Compare (side-by-side review).
|
|
113
|
+
- **[Running pipelines](running-pipelines.md)** — agent profiles, plugins (Serena), telemetry export.
|
|
114
|
+
- **[Tracking cost](tracking-cost.md)** — analytics deep dive and CSV exports.
|
|
115
|
+
- **[Codex](codex.md)** — using the Codex CLI as a provider, alongside or instead of Claude.
|
|
116
|
+
- **[Terminal panel](terminal.md)** — the built-in per-project terminal (toggle with `Cmd/Ctrl+J`).
|
|
117
|
+
- **[Customising the app](customizing.md)** — themes, terminal settings, kill switches.
|
|
118
|
+
- **[CLI reference](cli.md)** — drive specrails-desktop from the terminal.
|
|
119
|
+
|
|
120
|
+
## Troubleshooting
|
|
121
|
+
|
|
122
|
+
**"Port 4200 already in use" on start**
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
specrails-desktop stop # stops the running server cleanly
|
|
126
|
+
# or kill the process holding the port
|
|
127
|
+
lsof -i :4200 # macOS / Linux
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**The `claude` command isn't found inside the app**
|
|
131
|
+
|
|
132
|
+
On macOS, this usually means the app was launched from Finder/Dock and didn't pick up Homebrew/Volta paths. The app fixes this at startup automatically, but if it still fails, see [platforms/macos.md](platforms/macos.md).
|
|
133
|
+
|
|
134
|
+
**The setup wizard fails on `npx specrails-core@latest init`**
|
|
135
|
+
|
|
136
|
+
Most likely Node is missing from the shell environment that launched the app, or your AI CLI isn't authenticated (sign in to the `claude` CLI or set `ANTHROPIC_API_KEY`; for Codex, sign in to the `codex` CLI). Click **Copy diagnostics** in the install-instructions modal — that prints the resolved PATH, where the app found each tool, and login-shell status. Paste it into a bug report if you can't figure it out.
|
|
137
|
+
|
|
138
|
+
**More**
|
|
139
|
+
|
|
140
|
+
Operational issues (port conflicts, stale PID files, database corruption) are covered in the [Operations runbook](internals/operations-runbook.md).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Internals
|
|
2
|
+
|
|
3
|
+
These docs are primarily for contributors and people building on the app's API. They mostly describe how the app works under the hood — though a couple (like the profiles quick start) double as practical how-tos.
|
|
4
|
+
|
|
5
|
+
If you're a user looking for **how do I do X?** docs, head back to the [user guides](../README.md).
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
| Doc | What it covers |
|
|
10
|
+
|-----|----------------|
|
|
11
|
+
| [architecture.md](architecture.md) | Server modules, client layout, WebSocket protocol, process spawning, security model |
|
|
12
|
+
| [api-reference.md](api-reference.md) | REST endpoint catalogue under `/api/*` and `/api/projects/:projectId/*` |
|
|
13
|
+
| [configuration.md](configuration.md) | Settings, env vars, kill switches, advanced flags |
|
|
14
|
+
| [operations-runbook.md](operations-runbook.md) | Start/stop, port conflicts, recovery procedures, backups |
|
|
15
|
+
| [openspec-workflow.md](openspec-workflow.md) | `opsx:*` change lifecycle — used by the app itself for structured change management |
|
|
16
|
+
| [adding-a-provider.md](adding-a-provider.md) | How to add a new AI CLI: one adapter file plus one entry in the registry |
|
|
17
|
+
| [profiles.md](profiles.md) | Agent profiles quick start: open the Agents section, pick a profile per rail at launch, author custom agents in Agent Studio. For the true file-format and snapshotting internals, read `server/profile-manager.ts` and the profile-manager section of `CLAUDE.md` |
|
|
18
|
+
|
|
19
|
+
**See also:** [`../codex.md`](../codex.md) for the multi-provider model (Claude Code + Codex CLI as first-class engines).
|
|
20
|
+
|
|
21
|
+
## Contributing
|
|
22
|
+
|
|
23
|
+
For coding conventions, file naming, the coverage policy, and how WebSocket handlers are expected to be wired, see [`CLAUDE.md`](../../CLAUDE.md) at the repo root. That file is the authoritative source for project-wide rules.
|
|
24
|
+
|
|
25
|
+
When adding a feature, follow the OpenSpec workflow: `/opsx:new → /opsx:ff → /opsx:apply → /opsx:verify → /opsx:archive`. The `/opsx:*` invocations resolve to command files under `.claude/commands/opsx/*.md` (the related skills under `.claude/skills/` are named `openspec-*`).
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Adding a new AI provider to Specrails
|
|
2
|
+
|
|
3
|
+
The app is provider-agnostic by design. Every manager that spawns an AI
|
|
4
|
+
CLI consumes a `ProviderAdapter` rather than branching on a hardcoded
|
|
5
|
+
`if (provider === 'claude')`. Adding a new provider is mostly one adapter
|
|
6
|
+
file plus one entry in the registry — but the codebase still carries a
|
|
7
|
+
handful of `'claude' | 'codex'` type unions and two hardcoded provider
|
|
8
|
+
lists that you must widen by hand today. Those are tracked in the
|
|
9
|
+
**Type-union widening** and **Manual wiring still required** sections
|
|
10
|
+
below.
|
|
11
|
+
|
|
12
|
+
If you find yourself wanting to write `if (this._provider === 'X')` in
|
|
13
|
+
a manager, **the design has drifted** — find the capability you're
|
|
14
|
+
gating on, add a flag to `ProviderCapabilities`, and branch on the
|
|
15
|
+
flag instead.
|
|
16
|
+
|
|
17
|
+
## The recipe
|
|
18
|
+
|
|
19
|
+
### 1. Implement the adapter
|
|
20
|
+
|
|
21
|
+
Create `server/providers/<id>-adapter.ts` exporting a `const` of type
|
|
22
|
+
`ProviderAdapter`:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import type { ProviderAdapter, SpawnAction, SpawnOptions, AdapterEvent, NormalisedResult, DetectionResult } from './types'
|
|
26
|
+
|
|
27
|
+
const MODELS = [
|
|
28
|
+
{ value: 'flagship', label: 'Provider X Flagship', default: true as const },
|
|
29
|
+
{ value: 'fast', label: 'Provider X Fast' },
|
|
30
|
+
] as const
|
|
31
|
+
|
|
32
|
+
export const exampleAdapter: ProviderAdapter = {
|
|
33
|
+
id: 'example',
|
|
34
|
+
displayName: 'Example CLI',
|
|
35
|
+
binary: 'example',
|
|
36
|
+
minCliVersion: '1.0.0',
|
|
37
|
+
projectDirName: '.example',
|
|
38
|
+
instructionsFilename: 'EXAMPLE.md',
|
|
39
|
+
mcpRegistration: 'cli-add', // or 'project-json'
|
|
40
|
+
capabilities: {
|
|
41
|
+
nativeResume: true,
|
|
42
|
+
nativeStreamJson: true,
|
|
43
|
+
nativeCostUsd: false, // if false, add the provider:model entries to server/pricing.ts
|
|
44
|
+
nativeOtelEnv: false, // if false, the app will synthesise OTEL via the bridge
|
|
45
|
+
profileEnvSupport: true,
|
|
46
|
+
systemPromptArg: false,
|
|
47
|
+
},
|
|
48
|
+
modelCatalog: () => MODELS,
|
|
49
|
+
defaultModel: () => 'flagship',
|
|
50
|
+
buildArgs: (action: SpawnAction, opts: SpawnOptions): string[] => { /* per-action argv */ },
|
|
51
|
+
parseStreamLine: (line: string): AdapterEvent | null => { /* line → canonical event */ },
|
|
52
|
+
extractResult: (events): NormalisedResult => { /* events → tokens/cost/session */ },
|
|
53
|
+
baselineAgents: () => ['sr-architect', 'sr-developer', 'sr-reviewer'],
|
|
54
|
+
detectInstalled: async (): Promise<DetectionResult> => { /* `which` + `--version` */ },
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The `ProviderAdapter` interface is documented in
|
|
59
|
+
`server/providers/types.ts`. Read the existing
|
|
60
|
+
`server/providers/{claude,codex}-adapter.ts` for the patterns —
|
|
61
|
+
`SpawnAction` shapes per provider, `text-delta` event normalisation
|
|
62
|
+
across native JSONL formats, etc. Note the shipped baseline is the
|
|
63
|
+
three-agent trio `['sr-architect', 'sr-developer', 'sr-reviewer']`;
|
|
64
|
+
`ProfileManager` validation requires exactly your `baselineAgents()` to
|
|
65
|
+
be present in every profile chain, so don't add agents your scaffold
|
|
66
|
+
won't actually create.
|
|
67
|
+
|
|
68
|
+
`parseStreamLine` returns `null` for empty input lines **and** for lines
|
|
69
|
+
that fail `JSON.parse` (see `server/providers/codex-adapter.ts`); unknown
|
|
70
|
+
JSON event types resolve to `{ kind: 'other' }`. Write your tests
|
|
71
|
+
accordingly — don't assume null-only-on-empty.
|
|
72
|
+
|
|
73
|
+
### 2. Register it
|
|
74
|
+
|
|
75
|
+
Append the import to `server/providers/index.ts`:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { register } from './registry'
|
|
79
|
+
import { claudeAdapter } from './claude-adapter'
|
|
80
|
+
import { codexAdapter } from './codex-adapter'
|
|
81
|
+
import { exampleAdapter } from './example-adapter' // ← add this
|
|
82
|
+
|
|
83
|
+
register(claudeAdapter)
|
|
84
|
+
register(codexAdapter)
|
|
85
|
+
register(exampleAdapter) // ← and this
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Truly automatic** (these walk the registry, so they pick up the new
|
|
89
|
+
provider with zero edits):
|
|
90
|
+
|
|
91
|
+
- `getAdapter` / `listAdapters` / `hasAdapter` (`server/providers/registry.ts`).
|
|
92
|
+
- `detectAvailableCLIs` (`server/core-compat.ts`).
|
|
93
|
+
- `POST /api/projects` provider validation (`server/desktop-router.ts`,
|
|
94
|
+
via `hasAdapter` / `listAdapters`).
|
|
95
|
+
- `setup-prerequisites` provider rows (`server/setup-prerequisites.ts`,
|
|
96
|
+
iterates `listAdapters()`).
|
|
97
|
+
- Analytics `byProvider` (`server/spending.ts`) and the
|
|
98
|
+
`ProviderBreakdownCard` (`client/src/components/analytics/ProviderBreakdownCard.tsx`).
|
|
99
|
+
|
|
100
|
+
**Manual wiring still required** (these hardcode `claude` / `codex`
|
|
101
|
+
today and will NOT surface a 4th provider until edited):
|
|
102
|
+
|
|
103
|
+
- `GET /api/available-providers` (`server/desktop-router.ts`) returns a
|
|
104
|
+
literal `{ claude, codex }` shape — add your key.
|
|
105
|
+
- `AddProjectDialog` (`client/src/components/AddProjectDialog.tsx`)
|
|
106
|
+
hardcodes `PROVIDER_ORDER = ['claude', 'codex']` and reads
|
|
107
|
+
`data.claude` / `data.codex` explicitly. Without editing it the
|
|
108
|
+
provider won't appear in the Add Project UI.
|
|
109
|
+
- `providerInstallUrl` / `providerInstallHint`
|
|
110
|
+
(`server/setup-prerequisites.ts`) have generic `default:` fallbacks so
|
|
111
|
+
nothing crashes, but a good install hint needs a `case` for your id.
|
|
112
|
+
|
|
113
|
+
### Type-union widening
|
|
114
|
+
|
|
115
|
+
A 4th provider is a **compile-time blocker** until you widen the
|
|
116
|
+
`'claude' | 'codex'` unions still scattered across the server. The build
|
|
117
|
+
fails until they're widened (or migrated to a shared `ProviderId`):
|
|
118
|
+
|
|
119
|
+
- `CliProvider` (`server/desktop-db.ts`) — the canonical project-row provider type.
|
|
120
|
+
- `SpecProvider` (`server/spec-models.ts`).
|
|
121
|
+
- The inline `'claude' | 'codex'` unions in `server/queue-manager.ts`
|
|
122
|
+
(`EnqueueOptions.provider`, `_jobProviderSelection`),
|
|
123
|
+
`server/chat-manager.ts`, `server/agent-refine-manager.ts`, and
|
|
124
|
+
`server/project-registry.ts`.
|
|
125
|
+
|
|
126
|
+
Expect to widen roughly eight unions. The long-term goal is to delete
|
|
127
|
+
them in favour of a single `ProviderId` derived from the registry — if
|
|
128
|
+
you add a new hardcoded site instead of widening the existing ones, file
|
|
129
|
+
an OpenSpec change first (see the closing section).
|
|
130
|
+
|
|
131
|
+
### 3. (If `nativeCostUsd === false`) add pricing entries
|
|
132
|
+
|
|
133
|
+
For providers that don't report `total_cost_usd` in their terminal
|
|
134
|
+
event, append the rate card to `server/pricing.ts`:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
'example:flagship': { inputPer1M: 5.00, outputPer1M: 15.00, cacheReadPer1M: 0.50, lastReviewedAt: '2026-05-18' },
|
|
138
|
+
'example:fast': { inputPer1M: 0.50, outputPer1M: 1.50, cacheReadPer1M: 0.05, lastReviewedAt: '2026-05-18' },
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The `finaliseInvocationResult` flow in `server/result-event.ts` falls
|
|
142
|
+
back to this table automatically and returns an `estimated` flag that
|
|
143
|
+
`recordInvocation` (`server/ai-invocations.ts`) persists as
|
|
144
|
+
`total_cost_usd_estimated = 1` on the `ai_invocations` row, which in
|
|
145
|
+
turn lights up the `~` tilde + Hero footnote on the AnalyticsPage.
|
|
146
|
+
|
|
147
|
+
### 4. (If `nativeOtelEnv === false`) confirm the OTEL bridge works
|
|
148
|
+
|
|
149
|
+
The synthetic OTEL bridge at `server/codex-otel-bridge.ts` is
|
|
150
|
+
provider-neutral despite its name — it consumes the canonical
|
|
151
|
+
`AdapterEvent` stream. As long as your adapter's `parseStreamLine`
|
|
152
|
+
emits `text-delta`, `tool-use`, `session-started`, and `result` events,
|
|
153
|
+
the bridge will synthesise traces / metrics / logs for free. The
|
|
154
|
+
exported factory is still named `createCodexOtelBridge`; if that bugs
|
|
155
|
+
you, renaming it to `createSyntheticOtelBridge` (and updating callers)
|
|
156
|
+
is safe — same logic.
|
|
157
|
+
|
|
158
|
+
### 5. (If `mcpRegistration === 'cli-add'`) wire the plugin install path
|
|
159
|
+
|
|
160
|
+
The codex MCP integration lives at `server/plugins/codex-mcp.ts`.
|
|
161
|
+
Mirror that file for a new `<provider>-mcp.ts` if your provider has a
|
|
162
|
+
similar `<binary> mcp add/remove/list` subcommand. Then update
|
|
163
|
+
`server/plugins/serena/install.ts`, which routes to the CLI-add helper
|
|
164
|
+
whenever `getAdapter(providerId).mcpRegistration === 'cli-add'`. The
|
|
165
|
+
app-level `PluginManager` already threads `providerId` through every
|
|
166
|
+
relevant method.
|
|
167
|
+
|
|
168
|
+
For `mcpRegistration === 'project-json'` providers, the existing
|
|
169
|
+
`.mcp.json` surgical-merge path applies — nothing to add.
|
|
170
|
+
|
|
171
|
+
## Known gotchas
|
|
172
|
+
|
|
173
|
+
- **Legacy result path.** `normaliseResultEvent(event, provider)`
|
|
174
|
+
(`server/result-event.ts`) is still live for any callsite not yet
|
|
175
|
+
migrated to `finaliseInvocationResult`. It only special-cases
|
|
176
|
+
`provider === 'claude'`; everything else falls into the non-claude
|
|
177
|
+
(codex-shaped) branch. A 4th provider hitting that path would be
|
|
178
|
+
silently parsed as codex — migrate the callsite or extend the branch.
|
|
179
|
+
- **Rail slash-command translation is provider-specific.** In
|
|
180
|
+
`server/queue-manager.ts` the rail prompt builder rewrites
|
|
181
|
+
`/specrails:<name>` → `$<name>` for codex (so codex picks up the
|
|
182
|
+
matching `.codex/skills/<name>/SKILL.md`), while claude passes the
|
|
183
|
+
command verbatim. A new adapter falls through to the claude branch
|
|
184
|
+
(verbatim). If your CLI needs a different invocation syntax, add a
|
|
185
|
+
branch keyed on a capability, not on the provider id.
|
|
186
|
+
|
|
187
|
+
## Drop a fixture set
|
|
188
|
+
|
|
189
|
+
Add a JSONL capture of a real `<binary> exec --json` (or whatever your
|
|
190
|
+
CLI's JSONL flag is) under
|
|
191
|
+
`server/providers/__fixtures__/<id>/<minCliVersion>/`. The adapter's
|
|
192
|
+
test suite consumes these so future CLI-version bumps surface schema
|
|
193
|
+
drift loudly instead of silently.
|
|
194
|
+
|
|
195
|
+
## Write the tests
|
|
196
|
+
|
|
197
|
+
Mirror the test layout under `server/providers/<id>-adapter.test.ts`.
|
|
198
|
+
Required coverage:
|
|
199
|
+
|
|
200
|
+
- Identity: id / binary / projectDirName / instructionsFilename /
|
|
201
|
+
mcpRegistration / capability flags / model catalog.
|
|
202
|
+
- `buildArgs` for every `SpawnAction` the manager flow uses (today:
|
|
203
|
+
`chat-turn`, `chat-resume`, `rail-job`, `spec-gen`, `agent-refine`,
|
|
204
|
+
`setup-enrich`, `setup-enrich-resume`, `auto-title`).
|
|
205
|
+
- `parseStreamLine` per event type, including an "unknown type maps
|
|
206
|
+
to kind: 'other'" defensive test and a "returns null on empty input
|
|
207
|
+
and on unparseable JSON" test.
|
|
208
|
+
- `extractResult` from a fixture-derived event sequence.
|
|
209
|
+
- `detectInstalled` happy / missing / non-zero-exit paths.
|
|
210
|
+
|
|
211
|
+
## Verify
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
npm run typecheck
|
|
215
|
+
npx vitest run server/providers server/pricing server/result-event server/plugin-manager
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
`npm run typecheck` runs `tsc --noEmit` for both the server and the
|
|
219
|
+
client — important here, because the type-union widening above touches
|
|
220
|
+
types both halves import, and a missed union surfaces only on the side
|
|
221
|
+
you didn't check.
|
|
222
|
+
|
|
223
|
+
Then a manual smoke test: register a project via the UI with the new
|
|
224
|
+
provider, run a chat turn, run a rail, confirm tokens + cost land on
|
|
225
|
+
the AnalyticsPage.
|
|
226
|
+
|
|
227
|
+
## Don't break the principle
|
|
228
|
+
|
|
229
|
+
The drift inventory above — the two hardcoded provider lists, the ~8
|
|
230
|
+
`'claude' | 'codex'` unions, the legacy `normaliseResultEvent` branch,
|
|
231
|
+
and the provider-specific rail rewrite — is the current debt. The
|
|
232
|
+
long-term goal is to delete every one of those sites in favour of a
|
|
233
|
+
registry-derived `ProviderId` so that adding a fifth provider really is
|
|
234
|
+
just the adapter file plus the registry entry. If you find a NEW
|
|
235
|
+
hardcoded `if (provider === 'X')` site that this guide doesn't list,
|
|
236
|
+
**the architecture has drifted further** — file an OpenSpec change at
|
|
237
|
+
`openspec/changes/<your-change-name>/` and capture the drift before
|
|
238
|
+
papering over it with another manager-level branch.
|