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,311 @@
|
|
|
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.discoverChromiumExecutable = discoverChromiumExecutable;
|
|
7
|
+
exports.resolveBundledChromiumPath = resolveBundledChromiumPath;
|
|
8
|
+
exports.resolveBundledChromiumExecutable = resolveBundledChromiumExecutable;
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const os_1 = __importDefault(require("os"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const child_process_1 = require("child_process");
|
|
13
|
+
const stream_1 = require("stream");
|
|
14
|
+
const promises_1 = require("stream/promises");
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the Chromium executable the browser-capture feature should launch.
|
|
17
|
+
*
|
|
18
|
+
* In desktop mode (`SPECRAILS_IS_DESKTOP=1`) we ship Chromium INSIDE the app, but
|
|
19
|
+
* NOT as an unpacked directory: Tauri's resource bundler dereferences symlinks when
|
|
20
|
+
* it copies `bundle.resources` into the .app (tauri-apps/tauri#13219), which mangles
|
|
21
|
+
* Chromium's versioned `*.framework` (the `Versions/Current` + top-level symlinks
|
|
22
|
+
* become flat duplicate copies) and invalidates its code signature — macOS
|
|
23
|
+
* notarization then rejects the app ("The signature of the binary is invalid").
|
|
24
|
+
*
|
|
25
|
+
* So we ship Chromium as a single OPAQUE, OBFUSCATED blob
|
|
26
|
+
* (`<runtimes>/chromium/chromium.pak`):
|
|
27
|
+
* - It is an XOR-transformed `chromium.tar.gz`. The notarization service recursively
|
|
28
|
+
* unpacks archives it recognises (.zip → .tar.gz → .tar → …) and validates every
|
|
29
|
+
* Mach-O inside; Chromium's ~50 nested binaries are only ad-hoc ("linker") signed
|
|
30
|
+
* by Google, so a plain archive fails notarization. XOR-ing breaks the gzip/tar
|
|
31
|
+
* magic, so the notary cannot identify the file as a container and treats it as
|
|
32
|
+
* opaque data — nothing inside is inspected, and the app notarizes with NO
|
|
33
|
+
* Developer-ID signing of Chromium. (Obfuscation, not security: the key is public.)
|
|
34
|
+
* - Tauri also copies it as one regular file — nothing to dereference.
|
|
35
|
+
* - At first use we reverse the XOR and extract it to a writable cache
|
|
36
|
+
* (`~/.specrails/runtimes/chromium`), restoring the framework symlinks intact. The
|
|
37
|
+
* extracted Chromium keeps Google's ad-hoc signature, which is sufficient to execute
|
|
38
|
+
* on Apple Silicon, and — being self-extracted rather than downloaded — carries no
|
|
39
|
+
* `com.apple.quarantine` xattr, so Gatekeeper does not block it.
|
|
40
|
+
*
|
|
41
|
+
* A plain `chromium.tar.gz`/`chromium.tar` is also accepted (e.g. unobfuscated local
|
|
42
|
+
* builds). When no archive is present (dev, a runtimes-less build, a partial
|
|
43
|
+
* extraction) we fall back to discovering an UNPACKED `<runtimes>/chromium` tree, and
|
|
44
|
+
* finally to `null` so Playwright uses its own managed browser — never dead-ending.
|
|
45
|
+
*
|
|
46
|
+
* We DISCOVER rather than hard-code the executable path because Playwright's layout
|
|
47
|
+
* changes across versions (`chrome-mac/Chromium.app` → `chrome-mac-arm64/Google Chrome
|
|
48
|
+
* for Testing.app`, `chrome-win/chrome.exe`, `chrome-linux/chrome`).
|
|
49
|
+
*/
|
|
50
|
+
const MAX_DEPTH = 6;
|
|
51
|
+
function isFile(p) {
|
|
52
|
+
try {
|
|
53
|
+
return fs_1.default.statSync(p).isFile();
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Depth-bounded search for the first file whose basename satisfies `match`. */
|
|
60
|
+
function findFirstFile(root, match, depth = 0) {
|
|
61
|
+
if (depth > MAX_DEPTH)
|
|
62
|
+
return null;
|
|
63
|
+
let entries;
|
|
64
|
+
try {
|
|
65
|
+
entries = fs_1.default.readdirSync(root, { withFileTypes: true });
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
// Files first (cheap), then recurse into dirs.
|
|
71
|
+
for (const e of entries) {
|
|
72
|
+
if (e.isFile() && match(e.name))
|
|
73
|
+
return path_1.default.join(root, e.name);
|
|
74
|
+
}
|
|
75
|
+
for (const e of entries) {
|
|
76
|
+
if (e.isDirectory()) {
|
|
77
|
+
const hit = findFirstFile(path_1.default.join(root, e.name), match, depth + 1);
|
|
78
|
+
if (hit)
|
|
79
|
+
return hit;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
/** On macOS: locate the main executable inside the first `*.app` under `root`. */
|
|
85
|
+
function findMacAppExecutable(root, depth = 0) {
|
|
86
|
+
if (depth > MAX_DEPTH)
|
|
87
|
+
return null;
|
|
88
|
+
let entries;
|
|
89
|
+
try {
|
|
90
|
+
entries = fs_1.default.readdirSync(root, { withFileTypes: true });
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
for (const e of entries) {
|
|
96
|
+
if (e.isDirectory() && e.name.endsWith('.app')) {
|
|
97
|
+
const macosDir = path_1.default.join(root, e.name, 'Contents', 'MacOS');
|
|
98
|
+
// The main binary is conventionally named like the app (sans ".app");
|
|
99
|
+
// fall back to the first regular file in MacOS/.
|
|
100
|
+
const preferred = path_1.default.join(macosDir, e.name.slice(0, -'.app'.length));
|
|
101
|
+
if (isFile(preferred))
|
|
102
|
+
return preferred;
|
|
103
|
+
try {
|
|
104
|
+
for (const inner of fs_1.default.readdirSync(macosDir, { withFileTypes: true })) {
|
|
105
|
+
if (inner.isFile())
|
|
106
|
+
return path_1.default.join(macosDir, inner.name);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch { /* keep searching */ }
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
for (const e of entries) {
|
|
113
|
+
if (e.isDirectory() && !e.name.endsWith('.app')) {
|
|
114
|
+
const hit = findMacAppExecutable(path_1.default.join(root, e.name), depth + 1);
|
|
115
|
+
if (hit)
|
|
116
|
+
return hit;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
/** Find the bundled Chromium executable under `<chromiumRoot>`, or null. */
|
|
122
|
+
function discoverChromiumExecutable(chromiumRoot) {
|
|
123
|
+
if (!fs_1.default.existsSync(chromiumRoot))
|
|
124
|
+
return null;
|
|
125
|
+
if (process.platform === 'win32') {
|
|
126
|
+
return findFirstFile(chromiumRoot, (n) => n === 'chrome.exe' || n === 'chromium.exe');
|
|
127
|
+
}
|
|
128
|
+
if (process.platform === 'darwin') {
|
|
129
|
+
return (findMacAppExecutable(chromiumRoot) ??
|
|
130
|
+
findFirstFile(chromiumRoot, (n) => n === 'Chromium' || n === 'chromium' || n === 'chrome'));
|
|
131
|
+
}
|
|
132
|
+
// linux
|
|
133
|
+
return findFirstFile(chromiumRoot, (n) => n === 'chrome' || n === 'chromium' || n === 'chrome-wrapper');
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Returns the absolute path to an UNPACKED bundled Chromium binary, or `null`.
|
|
137
|
+
*
|
|
138
|
+
* This is the synchronous, no-extraction path: it only inspects a chromium tree that
|
|
139
|
+
* already exists on disk under `<runtimes>/chromium`. Prefer the async
|
|
140
|
+
* `resolveBundledChromiumExecutable()` for the launch path — it additionally extracts
|
|
141
|
+
* the shipped `chromium.tar.gz` archive. Kept for the unpacked fallback (local builds)
|
|
142
|
+
* and never throws.
|
|
143
|
+
*/
|
|
144
|
+
function resolveBundledChromiumPath() {
|
|
145
|
+
if (process.env.SPECRAILS_IS_DESKTOP !== '1')
|
|
146
|
+
return null;
|
|
147
|
+
const runtimesPath = process.env.SPECRAILS_BUNDLED_RUNTIMES_PATH;
|
|
148
|
+
if (!runtimesPath)
|
|
149
|
+
return null;
|
|
150
|
+
try {
|
|
151
|
+
return discoverChromiumExecutable(path_1.default.join(runtimesPath, 'chromium'));
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Candidate archive names under `<runtimes>/chromium`, in preference order. */
|
|
158
|
+
const ARCHIVE_NAMES = ['chromium.pak', 'chromium.tar.gz', 'chromium.tar'];
|
|
159
|
+
// XOR key for the obfuscated `chromium.pak` blob. Keep byte-identical to KEY in
|
|
160
|
+
// scripts/obfuscate-chromium.mjs — the round-trip is covered by a unit test.
|
|
161
|
+
// (Safe to have changed at the rebrand: the .pak and this binary always ship
|
|
162
|
+
// together in the same bundle, and the extraction cache re-extracts on a new
|
|
163
|
+
// archive via the `.source` marker.)
|
|
164
|
+
const OBFUSCATION_KEY = Buffer.from('specrails-desktop-chromium-pack-v1', 'utf8');
|
|
165
|
+
/** Streaming XOR transform (symmetric: packs and unpacks). */
|
|
166
|
+
function xorStream() {
|
|
167
|
+
let offset = 0;
|
|
168
|
+
return new stream_1.Transform({
|
|
169
|
+
transform(chunk, _enc, cb) {
|
|
170
|
+
const out = Buffer.allocUnsafe(chunk.length);
|
|
171
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
172
|
+
out[i] = chunk[i] ^ OBFUSCATION_KEY[(offset + i) % OBFUSCATION_KEY.length];
|
|
173
|
+
}
|
|
174
|
+
offset += chunk.length;
|
|
175
|
+
cb(null, out);
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
/** De-obfuscate a `.pak` blob into a real `.tar.gz` at `outPath`. */
|
|
180
|
+
async function deobfuscate(pakPath, outPath) {
|
|
181
|
+
await (0, promises_1.pipeline)(fs_1.default.createReadStream(pakPath), xorStream(), fs_1.default.createWriteStream(outPath));
|
|
182
|
+
}
|
|
183
|
+
/** Writable extraction destination (overridable for tests via env). */
|
|
184
|
+
function chromiumCacheDir() {
|
|
185
|
+
return (process.env.SPECRAILS_CHROMIUM_CACHE_DIR ||
|
|
186
|
+
path_1.default.join(os_1.default.homedir(), '.specrails', 'runtimes', 'chromium'));
|
|
187
|
+
}
|
|
188
|
+
/** Identity string for an archive (size:mtime) used to skip re-extraction. */
|
|
189
|
+
function archiveIdentity(archivePath) {
|
|
190
|
+
const st = fs_1.default.statSync(archivePath);
|
|
191
|
+
return `${st.size}:${Math.round(st.mtimeMs)}`;
|
|
192
|
+
}
|
|
193
|
+
/** Resolve the platform `tar` binary. macOS/Linux ship `/usr/bin/tar`; Windows 10+ ships `tar` (bsdtar) on PATH. */
|
|
194
|
+
function tarBinary() {
|
|
195
|
+
if (process.platform !== 'win32' && isFile('/usr/bin/tar'))
|
|
196
|
+
return '/usr/bin/tar';
|
|
197
|
+
return 'tar';
|
|
198
|
+
}
|
|
199
|
+
/** Extract `archivePath` into `destDir` using the system tar (auto-detects gzip). */
|
|
200
|
+
function runTarExtract(archivePath, destDir) {
|
|
201
|
+
return new Promise((resolve, reject) => {
|
|
202
|
+
const child = (0, child_process_1.spawn)(tarBinary(), ['-xf', archivePath, '-C', destDir], { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
203
|
+
let stderr = '';
|
|
204
|
+
child.stderr?.on('data', (d) => { stderr += d.toString(); });
|
|
205
|
+
child.on('error', reject);
|
|
206
|
+
child.on('close', (code) => {
|
|
207
|
+
if (code === 0)
|
|
208
|
+
resolve();
|
|
209
|
+
else
|
|
210
|
+
reject(new Error(`tar exited ${code}: ${stderr.trim().slice(0, 500)}`));
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
// In-process single-slot cache so concurrent / StrictMode double-invokes share one
|
|
215
|
+
// extraction instead of racing. Keyed by archive identity; invalidated if it changes.
|
|
216
|
+
let _extractInflight = null;
|
|
217
|
+
/** First archive that exists under `<runtimes>/chromium`, or null. */
|
|
218
|
+
function findBundledArchive(runtimesPath) {
|
|
219
|
+
for (const name of ARCHIVE_NAMES) {
|
|
220
|
+
const p = path_1.default.join(runtimesPath, 'chromium', name);
|
|
221
|
+
if (isFile(p))
|
|
222
|
+
return p;
|
|
223
|
+
}
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
async function extractAndDiscover(archivePath, identity) {
|
|
227
|
+
const destRoot = chromiumCacheDir();
|
|
228
|
+
const marker = path_1.default.join(destRoot, '.source');
|
|
229
|
+
// Fast path: already extracted from this exact archive.
|
|
230
|
+
try {
|
|
231
|
+
if (fs_1.default.readFileSync(marker, 'utf8') === identity) {
|
|
232
|
+
const exe = discoverChromiumExecutable(destRoot);
|
|
233
|
+
if (exe)
|
|
234
|
+
return exe;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch { /* not yet extracted / stale → fall through */ }
|
|
238
|
+
// Extract to a temp sibling, then atomically swap in.
|
|
239
|
+
const tmpDir = `${destRoot}.tmp-${process.pid}`;
|
|
240
|
+
fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
241
|
+
fs_1.default.mkdirSync(tmpDir, { recursive: true });
|
|
242
|
+
// An obfuscated `.pak` is XOR-decoded to a real `.tar.gz` first; plain archives
|
|
243
|
+
// are fed straight to tar.
|
|
244
|
+
const isPak = archivePath.endsWith('.pak');
|
|
245
|
+
const decodedTar = isPak ? `${tmpDir}.tar.gz` : null;
|
|
246
|
+
try {
|
|
247
|
+
let tarSource = archivePath;
|
|
248
|
+
if (decodedTar) {
|
|
249
|
+
await deobfuscate(archivePath, decodedTar);
|
|
250
|
+
tarSource = decodedTar;
|
|
251
|
+
}
|
|
252
|
+
await runTarExtract(tarSource, tmpDir);
|
|
253
|
+
const exeInTmp = discoverChromiumExecutable(tmpDir);
|
|
254
|
+
if (!exeInTmp)
|
|
255
|
+
throw new Error('no chromium executable found after extraction');
|
|
256
|
+
try {
|
|
257
|
+
fs_1.default.chmodSync(exeInTmp, 0o755);
|
|
258
|
+
}
|
|
259
|
+
catch { /* perms best-effort */ }
|
|
260
|
+
fs_1.default.rmSync(destRoot, { recursive: true, force: true });
|
|
261
|
+
fs_1.default.mkdirSync(path_1.default.dirname(destRoot), { recursive: true });
|
|
262
|
+
fs_1.default.renameSync(tmpDir, destRoot);
|
|
263
|
+
fs_1.default.writeFileSync(marker, identity);
|
|
264
|
+
return discoverChromiumExecutable(destRoot);
|
|
265
|
+
}
|
|
266
|
+
finally {
|
|
267
|
+
fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
268
|
+
if (decodedTar)
|
|
269
|
+
fs_1.default.rmSync(decodedTar, { force: true });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Resolve the bundled Chromium executable for the launch path, extracting the
|
|
274
|
+
* shipped archive on first use. Returns `null` (never throws) when not in desktop
|
|
275
|
+
* mode, when no bundle is present, or when extraction fails — so Playwright falls
|
|
276
|
+
* back to its managed browser rather than dead-ending.
|
|
277
|
+
*/
|
|
278
|
+
async function resolveBundledChromiumExecutable() {
|
|
279
|
+
if (process.env.SPECRAILS_IS_DESKTOP !== '1')
|
|
280
|
+
return null;
|
|
281
|
+
const runtimesPath = process.env.SPECRAILS_BUNDLED_RUNTIMES_PATH;
|
|
282
|
+
if (!runtimesPath)
|
|
283
|
+
return null;
|
|
284
|
+
let archivePath = null;
|
|
285
|
+
try {
|
|
286
|
+
archivePath = findBundledArchive(runtimesPath);
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
archivePath = null;
|
|
290
|
+
}
|
|
291
|
+
// No archive shipped → fall back to an unpacked tree (local/dev builds).
|
|
292
|
+
if (!archivePath)
|
|
293
|
+
return resolveBundledChromiumPath();
|
|
294
|
+
let identity;
|
|
295
|
+
try {
|
|
296
|
+
identity = archiveIdentity(archivePath);
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
return resolveBundledChromiumPath();
|
|
300
|
+
}
|
|
301
|
+
if (_extractInflight && _extractInflight.identity === identity) {
|
|
302
|
+
return _extractInflight.promise;
|
|
303
|
+
}
|
|
304
|
+
const promise = extractAndDiscover(archivePath, identity).catch((err) => {
|
|
305
|
+
console.error('[chromium-resolver] extraction failed:', err instanceof Error ? err.message : err);
|
|
306
|
+
_extractInflight = null; // allow a later retry
|
|
307
|
+
return resolveBundledChromiumPath();
|
|
308
|
+
});
|
|
309
|
+
_extractInflight = { identity, promise };
|
|
310
|
+
return promise;
|
|
311
|
+
}
|