@svenroth-ai/shipwright 0.25.0 → 0.27.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/client/dist/assets/{EmbeddedTerminal-5QvKe3_a.js → EmbeddedTerminal-CqCQUDtp.js} +1 -1
- package/client/dist/assets/{abnfDiagram-VRR7QNED-CXi9HegQ.js → abnfDiagram-VRR7QNED-DX2objTP.js} +1 -1
- package/client/dist/assets/{arc-DLh4GiqR.js → arc-DQmjbsFU.js} +1 -1
- package/client/dist/assets/{architectureDiagram-ZJ3FMSHR-DUypQ8dQ.js → architectureDiagram-ZJ3FMSHR-DAvCsPCW.js} +1 -1
- package/client/dist/assets/{blockDiagram-677ZJIJ3-D2cVMKJG.js → blockDiagram-677ZJIJ3-DC-dlyYI.js} +1 -1
- package/client/dist/assets/{c4Diagram-LMCZKHZV-DtruBGJw.js → c4Diagram-LMCZKHZV-DSlmXfhE.js} +1 -1
- package/client/dist/assets/channel-BfmIcrp7.js +1 -0
- package/client/dist/assets/{chunk-2Q5K7J3B-CAfQkFw2.js → chunk-2Q5K7J3B-C111EHL6.js} +1 -1
- package/client/dist/assets/{chunk-32BRIVSS-CPWXoLnQ.js → chunk-32BRIVSS-DrCYs2XG.js} +1 -1
- package/client/dist/assets/{chunk-5VM5RSS4-xVc3oppQ.js → chunk-5VM5RSS4-DIejoaXS.js} +1 -1
- package/client/dist/assets/{chunk-EX3LRPZG-CUpl6fRR.js → chunk-EX3LRPZG-CGWNeH2g.js} +1 -1
- package/client/dist/assets/{chunk-JWPE2WC7-NejUp56x.js → chunk-JWPE2WC7-CCH0SRFY.js} +1 -1
- package/client/dist/assets/{chunk-MOJQB5TN-C9-2lLg0.js → chunk-MOJQB5TN-B3OpZGRv.js} +1 -1
- package/client/dist/assets/{chunk-RYQCIY6F-BAPtwABy.js → chunk-RYQCIY6F-BKhdp_8v.js} +1 -1
- package/client/dist/assets/{chunk-V7JOEXUC-Dwzihw26.js → chunk-V7JOEXUC-B6Bu8x1y.js} +1 -1
- package/client/dist/assets/{chunk-VR4S4FIN-9-iArFJM.js → chunk-VR4S4FIN-OgFi2_iB.js} +1 -1
- package/client/dist/assets/{chunk-XXDRQBXY-DiWHOrqe.js → chunk-XXDRQBXY-xyjuuhxl.js} +1 -1
- package/client/dist/assets/classDiagram-OUVF2IWQ-HfUQZ6Uc.js +1 -0
- package/client/dist/assets/classDiagram-v2-EOCWNBFH-HfUQZ6Uc.js +1 -0
- package/client/dist/assets/{cose-bilkent-JH36ORCC-Cp04EOcH.js → cose-bilkent-JH36ORCC-BQIH3SCK.js} +1 -1
- package/client/dist/assets/{cynefin-VYW2F7L2-D--GN1v8.js → cynefin-VYW2F7L2-oyLAz8te.js} +1 -1
- package/client/dist/assets/{cynefinDiagram-TSTJHNR4-BGH0o_qp.js → cynefinDiagram-TSTJHNR4-DoLCsH0l.js} +1 -1
- package/client/dist/assets/{dagre-VKFMJZFB-DSKkIKlj.js → dagre-VKFMJZFB-D7djx1_Y.js} +1 -1
- package/client/dist/assets/{diagram-FQU43EPY-Cs_C4lb-.js → diagram-FQU43EPY-DFuYE0Vf.js} +1 -1
- package/client/dist/assets/{diagram-G47NLZAW-oDtAA8O_.js → diagram-G47NLZAW-CffCZVXk.js} +1 -1
- package/client/dist/assets/{diagram-NH7WQ7WH-BiFMjqSH.js → diagram-NH7WQ7WH-BhrHtUlt.js} +1 -1
- package/client/dist/assets/{diagram-OA4YK3LP-Ccs3thCj.js → diagram-OA4YK3LP-CwQPbOn0.js} +1 -1
- package/client/dist/assets/{diagram-WEI45ONY-CdZNqgO3.js → diagram-WEI45ONY-abtYnYqH.js} +1 -1
- package/client/dist/assets/{ebnfDiagram-CCIWWBDH-CapTA0VL.js → ebnfDiagram-CCIWWBDH-DfV7gT4m.js} +1 -1
- package/client/dist/assets/{erDiagram-Q63AITRT-BcRNEP8s.js → erDiagram-Q63AITRT-vtbCprgH.js} +1 -1
- package/client/dist/assets/{flowDiagram-23GEKE2U-CJ_zF7e_.js → flowDiagram-23GEKE2U-CVCgcyDF.js} +1 -1
- package/client/dist/assets/{ganttDiagram-NO4QXBWP-CnJdcg9A.js → ganttDiagram-NO4QXBWP-BclyOgMb.js} +1 -1
- package/client/dist/assets/{gitGraphDiagram-IHSO6WYX-YTUQ_ELk.js → gitGraphDiagram-IHSO6WYX-BXT4rIKj.js} +1 -1
- package/client/dist/assets/index-CKU9dY18.css +1 -0
- package/client/dist/assets/index-DOMl6atu.js +847 -0
- package/client/dist/assets/{infoDiagram-FWYZ7A6U-CLOP_ZWD.js → infoDiagram-FWYZ7A6U-Dr4mN24J.js} +1 -1
- package/client/dist/assets/{ishikawaDiagram-FXEZZL3T-aFTIzr7o.js → ishikawaDiagram-FXEZZL3T-BBUFWq5C.js} +1 -1
- package/client/dist/assets/{journeyDiagram-5HDEW3XC-CbPJB4xd.js → journeyDiagram-5HDEW3XC-CmclipcQ.js} +1 -1
- package/client/dist/assets/{kanban-definition-HUTT4EX6-BoyhytIS.js → kanban-definition-HUTT4EX6-eIzUeZ03.js} +1 -1
- package/client/dist/assets/{linear-1VXA-uBg.js → linear-DGiT7uKK.js} +1 -1
- package/client/dist/assets/{mermaid.core-D_lO2yK9.js → mermaid.core-BcLNGbxW.js} +4 -4
- package/client/dist/assets/{mindmap-definition-LN4V7U3C-iFK7LXMx.js → mindmap-definition-LN4V7U3C-C4ANnNiP.js} +1 -1
- package/client/dist/assets/{pegDiagram-2B236MQR-DNmcmfA-.js → pegDiagram-2B236MQR-DnMeh3Yh.js} +1 -1
- package/client/dist/assets/{pieDiagram-ENE6RG2P-ekx83O5b.js → pieDiagram-ENE6RG2P-CKV_rkhF.js} +1 -1
- package/client/dist/assets/{quadrantDiagram-ABIIQ3AL-DayyD1l8.js → quadrantDiagram-ABIIQ3AL-BuUsGwHh.js} +1 -1
- package/client/dist/assets/{railroadDiagram-RFXS5EU6-Bdgz7S6G.js → railroadDiagram-RFXS5EU6-BwwdKnFL.js} +1 -1
- package/client/dist/assets/{requirementDiagram-TGXJPOKE-szP3Muld.js → requirementDiagram-TGXJPOKE-CpQZouJV.js} +1 -1
- package/client/dist/assets/{sankeyDiagram-HTMAVEWB-Ct3rzgUj.js → sankeyDiagram-HTMAVEWB-4fnDUNVa.js} +1 -1
- package/client/dist/assets/{sequenceDiagram-DBY2YBRQ-_69EfmOU.js → sequenceDiagram-DBY2YBRQ-BOcaWlM0.js} +1 -1
- package/client/dist/assets/{sizeCapture-X5ZJPWSS-BSOU06J2.js → sizeCapture-X5ZJPWSS-_pv-9R0c.js} +1 -1
- package/client/dist/assets/{stateDiagram-2N3HPSRC-HmOmFwQm.js → stateDiagram-2N3HPSRC-CFwCOonY.js} +1 -1
- package/client/dist/assets/stateDiagram-v2-6OUMAXLB-srkiu3Ib.js +1 -0
- package/client/dist/assets/{swimlanes-5IMT3BWC-CVg_4oT7.js → swimlanes-5IMT3BWC-DFa2tzxu.js} +2 -2
- package/client/dist/assets/swimlanesDiagram-G3AALYLV-Dq-0K9Zm.js +8 -0
- package/client/dist/assets/{timeline-definition-FHXFAJF6-CBBaDKXm.js → timeline-definition-FHXFAJF6-rhGYElgn.js} +1 -1
- package/client/dist/assets/{vennDiagram-L72KCM5P-CBXiWPMc.js → vennDiagram-L72KCM5P-BoGjRxyA.js} +1 -1
- package/client/dist/assets/{wardleyDiagram-EHGQE667-uhBCZoW0.js → wardleyDiagram-EHGQE667-D-IGv5bH.js} +1 -1
- package/client/dist/assets/{xychartDiagram-FW5EYKEG-xxE_wY5O.js → xychartDiagram-FW5EYKEG-D9PFTCfm.js} +1 -1
- package/client/dist/index.html +27 -27
- package/lib/claude-cli.mjs +173 -173
- package/lib/preflight.mjs +252 -252
- package/lib/probe-path.mjs +84 -84
- package/lib/probes.mjs +10 -4
- package/lib/server.mjs +506 -369
- package/lib/util.mjs +157 -157
- package/lib/win32-spawn.mjs +253 -253
- package/package.json +68 -68
- package/scripts/deploy-procs.mjs +208 -208
- package/scripts/deploy-swap.mjs +276 -276
- package/scripts/kill-targets.js +140 -140
- package/scripts/repair-claude-json.mjs +295 -295
- package/server/dist/config/default-actions.json +90 -90
- package/server/dist/core/mission-context/association.d.ts +46 -0
- package/server/dist/core/mission-context/association.d.ts.map +1 -1
- package/server/dist/core/mission-context/association.js +69 -0
- package/server/dist/core/mission-context/association.js.map +1 -1
- package/server/dist/core/mission-context/resolver-iterate.d.ts +6 -0
- package/server/dist/core/mission-context/resolver-iterate.d.ts.map +1 -0
- package/server/dist/core/mission-context/resolver-iterate.js +202 -0
- package/server/dist/core/mission-context/resolver-iterate.js.map +1 -0
- package/server/dist/core/mission-context/resolver-parts.d.ts +20 -0
- package/server/dist/core/mission-context/resolver-parts.d.ts.map +1 -1
- package/server/dist/core/mission-context/resolver-parts.js +92 -0
- package/server/dist/core/mission-context/resolver-parts.js.map +1 -1
- package/server/dist/core/mission-context/resolver.d.ts +1 -1
- package/server/dist/core/mission-context/resolver.d.ts.map +1 -1
- package/server/dist/core/mission-context/resolver.js +17 -199
- package/server/dist/core/mission-context/resolver.js.map +1 -1
- package/server/dist/core/mission-context/run-id-recovery.d.ts +21 -5
- package/server/dist/core/mission-context/run-id-recovery.d.ts.map +1 -1
- package/server/dist/core/mission-context/run-id-recovery.js +32 -5
- package/server/dist/core/mission-context/run-id-recovery.js.map +1 -1
- package/server/dist/core/mission-context/scenario.d.ts +18 -11
- package/server/dist/core/mission-context/scenario.d.ts.map +1 -1
- package/server/dist/core/mission-context/scenario.js +40 -3
- package/server/dist/core/mission-context/scenario.js.map +1 -1
- package/server/dist/core/path-guard.d.ts +1 -1
- package/server/dist/core/path-guard.d.ts.map +1 -1
- package/server/dist/core/path-guard.js +9 -2
- package/server/dist/core/path-guard.js.map +1 -1
- package/server/dist/core/sdk-sessions-merge.d.ts +19 -0
- package/server/dist/core/sdk-sessions-merge.d.ts.map +1 -1
- package/server/dist/core/sdk-sessions-merge.js +19 -5
- package/server/dist/core/sdk-sessions-merge.js.map +1 -1
- package/server/dist/core/sdk-sessions-refresh.d.ts +50 -0
- package/server/dist/core/sdk-sessions-refresh.d.ts.map +1 -0
- package/server/dist/core/sdk-sessions-refresh.js +69 -0
- package/server/dist/core/sdk-sessions-refresh.js.map +1 -0
- package/server/dist/core/sdk-sessions-store.d.ts +2 -0
- package/server/dist/core/sdk-sessions-store.d.ts.map +1 -1
- package/server/dist/core/sdk-sessions-store.js +7 -9
- package/server/dist/core/sdk-sessions-store.js.map +1 -1
- package/server/dist/core/shipslog-docs-reader.d.ts +4 -0
- package/server/dist/core/shipslog-docs-reader.d.ts.map +1 -0
- package/server/dist/core/shipslog-docs-reader.js +181 -0
- package/server/dist/core/shipslog-docs-reader.js.map +1 -0
- package/server/dist/core/shipslog-docs-types.d.ts +15 -0
- package/server/dist/core/shipslog-docs-types.d.ts.map +1 -0
- package/server/dist/core/shipslog-docs-types.js +14 -0
- package/server/dist/core/shipslog-docs-types.js.map +1 -0
- package/server/dist/core/shipwright-plugin-version-reader.d.ts +15 -0
- package/server/dist/core/shipwright-plugin-version-reader.d.ts.map +1 -0
- package/server/dist/core/shipwright-plugin-version-reader.js +49 -0
- package/server/dist/core/shipwright-plugin-version-reader.js.map +1 -0
- package/server/dist/external/design-review/serve.js +27 -27
- package/server/dist/external/inbox/_derive.d.ts +2 -25
- package/server/dist/external/inbox/_derive.d.ts.map +1 -1
- package/server/dist/external/inbox/_derive.js.map +1 -1
- package/server/dist/external/inbox/_lead.d.ts +23 -0
- package/server/dist/external/inbox/_lead.d.ts.map +1 -0
- package/server/dist/external/inbox/_lead.js +83 -0
- package/server/dist/external/inbox/_lead.js.map +1 -0
- package/server/dist/external/inbox/_types.d.ts +32 -0
- package/server/dist/external/inbox/_types.d.ts.map +1 -0
- package/server/dist/external/inbox/_types.js +10 -0
- package/server/dist/external/inbox/_types.js.map +1 -0
- package/server/dist/external/inbox/routes.d.ts.map +1 -1
- package/server/dist/external/inbox/routes.js +29 -1
- package/server/dist/external/inbox/routes.js.map +1 -1
- package/server/dist/external/launch/claim-holder-gate.d.ts +42 -0
- package/server/dist/external/launch/claim-holder-gate.d.ts.map +1 -0
- package/server/dist/external/launch/claim-holder-gate.js +87 -0
- package/server/dist/external/launch/claim-holder-gate.js.map +1 -0
- package/server/dist/external/launch/routes.d.ts.map +1 -1
- package/server/dist/external/launch/routes.js +23 -19
- package/server/dist/external/launch/routes.js.map +1 -1
- package/server/dist/external/mission-context/association-write.d.ts +22 -0
- package/server/dist/external/mission-context/association-write.d.ts.map +1 -0
- package/server/dist/external/mission-context/association-write.js +90 -0
- package/server/dist/external/mission-context/association-write.js.map +1 -0
- package/server/dist/external/mission-context/routes.d.ts.map +1 -1
- package/server/dist/external/mission-context/routes.js +18 -31
- package/server/dist/external/mission-context/routes.js.map +1 -1
- package/server/dist/external/org/lead-question-threads.d.ts +46 -0
- package/server/dist/external/org/lead-question-threads.d.ts.map +1 -0
- package/server/dist/external/org/lead-question-threads.js +132 -0
- package/server/dist/external/org/lead-question-threads.js.map +1 -0
- package/server/dist/external/org/mount.d.ts +3 -0
- package/server/dist/external/org/mount.d.ts.map +1 -1
- package/server/dist/external/org/mount.js +2 -1
- package/server/dist/external/org/mount.js.map +1 -1
- package/server/dist/external/org/usage.d.ts.map +1 -1
- package/server/dist/external/org/usage.js +20 -2
- package/server/dist/external/org/usage.js.map +1 -1
- package/server/dist/external/routes.d.ts.map +1 -1
- package/server/dist/external/routes.js +10 -13
- package/server/dist/external/routes.js.map +1 -1
- package/server/dist/external/shipslog-docs/routes.d.ts +10 -0
- package/server/dist/external/shipslog-docs/routes.d.ts.map +1 -0
- package/server/dist/external/shipslog-docs/routes.js +41 -0
- package/server/dist/external/shipslog-docs/routes.js.map +1 -0
- package/server/dist/routes/diagnostics.d.ts +12 -0
- package/server/dist/routes/diagnostics.d.ts.map +1 -1
- package/server/dist/routes/diagnostics.js +4 -1
- package/server/dist/routes/diagnostics.js.map +1 -1
- package/server/dist/routes/org-threads-composite.d.ts +24 -0
- package/server/dist/routes/org-threads-composite.d.ts.map +1 -0
- package/server/dist/routes/org-threads-composite.js +51 -0
- package/server/dist/routes/org-threads-composite.js.map +1 -0
- package/server/dist/routes/org.d.ts +5 -0
- package/server/dist/routes/org.d.ts.map +1 -1
- package/server/dist/routes/org.js +13 -0
- package/server/dist/routes/org.js.map +1 -1
- package/server/dist/terminal/pty-manager.d.ts +23 -1
- package/server/dist/terminal/pty-manager.d.ts.map +1 -1
- package/server/dist/terminal/pty-manager.js +22 -3
- package/server/dist/terminal/pty-manager.js.map +1 -1
- package/server/dist/terminal/pty-write-chunker.d.ts +109 -0
- package/server/dist/terminal/pty-write-chunker.d.ts.map +1 -0
- package/server/dist/terminal/pty-write-chunker.js +234 -0
- package/server/dist/terminal/pty-write-chunker.js.map +1 -0
- package/server/dist/types/org.d.ts +19 -0
- package/server/dist/types/org.d.ts.map +1 -1
- package/server/package.json +1 -1
- package/server/profiles/PROFILE_SCHEMA_VERSION +1 -1
- package/server/profiles/README.md +27 -27
- package/server/profiles/python-plugin-monorepo.json +35 -35
- package/server/profiles/supabase-nextjs.json +253 -253
- package/server/profiles/vite-hono.json +92 -92
- package/client/dist/assets/channel-C_k-9jsa.js +0 -1
- package/client/dist/assets/classDiagram-OUVF2IWQ-CsEPq9Ac.js +0 -1
- package/client/dist/assets/classDiagram-v2-EOCWNBFH-CsEPq9Ac.js +0 -1
- package/client/dist/assets/index-6nZ1bt0a.css +0 -1
- package/client/dist/assets/index-irQhGNpn.js +0 -828
- package/client/dist/assets/stateDiagram-v2-6OUMAXLB-BW8H33dv.js +0 -1
- package/client/dist/assets/swimlanesDiagram-G3AALYLV-BaRlxcPD.js +0 -8
package/lib/util.mjs
CHANGED
|
@@ -1,157 +1,157 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* util.mjs — pure, dependency-free helpers shared across the bootstrapper.
|
|
3
|
-
*
|
|
4
|
-
* Everything here is side-effect free and unit-testable in isolation: SemVer
|
|
5
|
-
* parsing/compare (attach-vs-swap + stale-copy decisions ride on it), platform
|
|
6
|
-
* detection, and the actionable install hints a missing prerequisite must
|
|
7
|
-
* print. No `claude`, no network, no filesystem — those live in the sibling
|
|
8
|
-
* modules behind injected seams.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/** @param {string} v @returns {[number, number, number] | null} */
|
|
12
|
-
export function parseSemver(v) {
|
|
13
|
-
if (typeof v !== "string") return null;
|
|
14
|
-
const m = /^\s*v?(\d+)\.(\d+)\.(\d+)/.exec(v.trim());
|
|
15
|
-
if (!m) return null;
|
|
16
|
-
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Compare two SemVer-shaped strings by MAJOR.MINOR.PATCH.
|
|
21
|
-
* Returns -1 (a<b), 0 (equal or either unparseable), 1 (a>b). Pre-release
|
|
22
|
-
* tails are ignored — this is the comparator for "is tool X new enough"
|
|
23
|
-
* (Node/Python floors), where only the numeric triple can matter.
|
|
24
|
-
*
|
|
25
|
-
* The attach-vs-swap decision needs the OPPOSITE — it must distinguish two
|
|
26
|
-
* `@next` builds that share a triple (`0.24.7-next.0` vs `0.24.7-next.1`) —
|
|
27
|
-
* so it uses `compareSemverFull` instead.
|
|
28
|
-
* @param {string} a @param {string} b @returns {-1 | 0 | 1}
|
|
29
|
-
*/
|
|
30
|
-
export function compareSemver(a, b) {
|
|
31
|
-
const pa = parseSemver(a);
|
|
32
|
-
const pb = parseSemver(b);
|
|
33
|
-
if (!pa || !pb) return 0;
|
|
34
|
-
for (let i = 0; i < 3; i++) {
|
|
35
|
-
if (pa[i] < pb[i]) return -1;
|
|
36
|
-
if (pa[i] > pb[i]) return 1;
|
|
37
|
-
}
|
|
38
|
-
return 0;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Extract the SemVer pre-release identifiers (the dot-separated tail after the
|
|
43
|
-
* first `-`, before any `+build` metadata), or `null` when there is none.
|
|
44
|
-
* `0.24.7-next.1` -> ["next", "1"]; `0.24.7` -> null; junk after the triple
|
|
45
|
-
* without a `-` (e.g. `2.1.132 (Claude Code)`) -> null.
|
|
46
|
-
* @param {string} v @returns {string[] | null}
|
|
47
|
-
*/
|
|
48
|
-
export function parsePrerelease(v) {
|
|
49
|
-
if (typeof v !== "string") return null;
|
|
50
|
-
const m = /^\s*v?\d+\.\d+\.\d+-([0-9A-Za-z.-]+)/.exec(v.trim());
|
|
51
|
-
if (!m) return null;
|
|
52
|
-
return m[1].split(".");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Compare two pre-release identifier lists per SemVer §11.4: a version WITHOUT
|
|
57
|
-
* a pre-release outranks one WITH; numeric identifiers rank below alphanumeric
|
|
58
|
-
* ones; a longer list outranks its own prefix. Both `null` (no pre-release) → 0.
|
|
59
|
-
* @param {string[] | null} a @param {string[] | null} b @returns {-1 | 0 | 1}
|
|
60
|
-
*/
|
|
61
|
-
function comparePrereleaseIds(a, b) {
|
|
62
|
-
// A version WITHOUT a pre-release outranks one WITH (1.0.0 > 1.0.0-next).
|
|
63
|
-
if (a === null && b === null) return 0;
|
|
64
|
-
if (a === null) return 1;
|
|
65
|
-
if (b === null) return -1;
|
|
66
|
-
const len = Math.min(a.length, b.length);
|
|
67
|
-
for (let i = 0; i < len; i++) {
|
|
68
|
-
const ai = a[i];
|
|
69
|
-
const bi = b[i];
|
|
70
|
-
const an = /^\d+$/.test(ai);
|
|
71
|
-
const bn = /^\d+$/.test(bi);
|
|
72
|
-
if (an && bn) {
|
|
73
|
-
const d = Number(ai) - Number(bi);
|
|
74
|
-
if (d !== 0) return d < 0 ? -1 : 1;
|
|
75
|
-
} else if (an !== bn) {
|
|
76
|
-
// Numeric identifiers always have lower precedence than alphanumeric.
|
|
77
|
-
return an ? -1 : 1;
|
|
78
|
-
} else if (ai !== bi) {
|
|
79
|
-
return ai < bi ? -1 : 1;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
if (a.length === b.length) return 0;
|
|
83
|
-
return a.length < b.length ? -1 : 1;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Compare two SemVer-shaped strings by triple AND pre-release tail. Returns
|
|
88
|
-
* -1 / 0 / 1, or 0 when either triple is unparseable (never a false swap
|
|
89
|
-
* trigger). This is the attach-vs-swap comparator: successive `@next` test
|
|
90
|
-
* builds share a MAJOR.MINOR.PATCH and differ ONLY in `-next.N`, so a
|
|
91
|
-
* triple-only compare would report them equal and ATTACH to the stale server
|
|
92
|
-
* instead of swapping in the freshly published build.
|
|
93
|
-
* @param {string} a @param {string} b @returns {-1 | 0 | 1}
|
|
94
|
-
*/
|
|
95
|
-
export function compareSemverFull(a, b) {
|
|
96
|
-
const triple = compareSemver(a, b);
|
|
97
|
-
if (triple !== 0) return triple;
|
|
98
|
-
// Triples equal (or a side unparseable → compareSemver already returned 0
|
|
99
|
-
// and we must not manufacture a difference from the tails). Only when BOTH
|
|
100
|
-
// triples parsed does the pre-release tail decide.
|
|
101
|
-
if (!parseSemver(a) || !parseSemver(b)) return 0;
|
|
102
|
-
return comparePrereleaseIds(parsePrerelease(a), parsePrerelease(b));
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/** @param {NodeJS.Platform} [platform] */
|
|
106
|
-
export function isWindows(platform = process.platform) {
|
|
107
|
-
return platform === "win32";
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Platform-correct, copy-pasteable install command for a missing prerequisite.
|
|
112
|
-
* A missing tool must never be a vague "install it" — the user gets the exact
|
|
113
|
-
* line for THEIR OS. Mirrors the pointers `scripts/verify-setup.sh` prints.
|
|
114
|
-
* @param {"uv"|"python"|"node"|"git"|"claude"} tool
|
|
115
|
-
* @param {NodeJS.Platform} [platform]
|
|
116
|
-
* @returns {string}
|
|
117
|
-
*/
|
|
118
|
-
export function installHint(tool, platform = process.platform) {
|
|
119
|
-
const win = isWindows(platform);
|
|
120
|
-
switch (tool) {
|
|
121
|
-
case "uv":
|
|
122
|
-
return win
|
|
123
|
-
? 'powershell -c "irm https://astral.sh/uv/install.ps1 | iex"'
|
|
124
|
-
: "curl -LsSf https://astral.sh/uv/install.sh | sh";
|
|
125
|
-
case "python":
|
|
126
|
-
// Coupled to uv: the whole stack runs via `uv run`, which resolves a
|
|
127
|
-
// uv-MANAGED Python — a system python3 is neither required nor sufficient.
|
|
128
|
-
// Lead with the uv path; the OS package manager / python.org is the fallback.
|
|
129
|
-
return win
|
|
130
|
-
? "install Python 3.11+ via uv (`uv python install 3.11`) — or from https://www.python.org/downloads/ (NOT the Microsoft Store stub)"
|
|
131
|
-
: "install Python 3.11+ via uv (`uv python install 3.11`) — or your package manager (e.g. `brew install python@3.11`)";
|
|
132
|
-
case "node":
|
|
133
|
-
return "install Node.js >= 20.12.0 from https://nodejs.org/";
|
|
134
|
-
case "git":
|
|
135
|
-
return win
|
|
136
|
-
? "install Git from https://git-scm.com/download/win"
|
|
137
|
-
: "install git (e.g. `brew install git` / `apt install git`)";
|
|
138
|
-
case "claude":
|
|
139
|
-
return win
|
|
140
|
-
? 'powershell -c "irm https://claude.ai/install.ps1 | iex"'
|
|
141
|
-
: "curl -fsSL https://claude.ai/install.sh | bash";
|
|
142
|
-
default:
|
|
143
|
-
return "";
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/** Minimum Node the packaged server needs (mirrors server/package.json engines). */
|
|
148
|
-
export const MIN_NODE = "20.12.0";
|
|
149
|
-
|
|
150
|
-
/** ASCII status glyphs — no emoji, PowerShell-5.1-safe, honest verdict blocks. */
|
|
151
|
-
export const MARK = Object.freeze({
|
|
152
|
-
pass: "[OK]",
|
|
153
|
-
fail: "[!!]",
|
|
154
|
-
warn: "[??]",
|
|
155
|
-
skip: "[--]",
|
|
156
|
-
info: "[..]",
|
|
157
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* util.mjs — pure, dependency-free helpers shared across the bootstrapper.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is side-effect free and unit-testable in isolation: SemVer
|
|
5
|
+
* parsing/compare (attach-vs-swap + stale-copy decisions ride on it), platform
|
|
6
|
+
* detection, and the actionable install hints a missing prerequisite must
|
|
7
|
+
* print. No `claude`, no network, no filesystem — those live in the sibling
|
|
8
|
+
* modules behind injected seams.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** @param {string} v @returns {[number, number, number] | null} */
|
|
12
|
+
export function parseSemver(v) {
|
|
13
|
+
if (typeof v !== "string") return null;
|
|
14
|
+
const m = /^\s*v?(\d+)\.(\d+)\.(\d+)/.exec(v.trim());
|
|
15
|
+
if (!m) return null;
|
|
16
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Compare two SemVer-shaped strings by MAJOR.MINOR.PATCH.
|
|
21
|
+
* Returns -1 (a<b), 0 (equal or either unparseable), 1 (a>b). Pre-release
|
|
22
|
+
* tails are ignored — this is the comparator for "is tool X new enough"
|
|
23
|
+
* (Node/Python floors), where only the numeric triple can matter.
|
|
24
|
+
*
|
|
25
|
+
* The attach-vs-swap decision needs the OPPOSITE — it must distinguish two
|
|
26
|
+
* `@next` builds that share a triple (`0.24.7-next.0` vs `0.24.7-next.1`) —
|
|
27
|
+
* so it uses `compareSemverFull` instead.
|
|
28
|
+
* @param {string} a @param {string} b @returns {-1 | 0 | 1}
|
|
29
|
+
*/
|
|
30
|
+
export function compareSemver(a, b) {
|
|
31
|
+
const pa = parseSemver(a);
|
|
32
|
+
const pb = parseSemver(b);
|
|
33
|
+
if (!pa || !pb) return 0;
|
|
34
|
+
for (let i = 0; i < 3; i++) {
|
|
35
|
+
if (pa[i] < pb[i]) return -1;
|
|
36
|
+
if (pa[i] > pb[i]) return 1;
|
|
37
|
+
}
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Extract the SemVer pre-release identifiers (the dot-separated tail after the
|
|
43
|
+
* first `-`, before any `+build` metadata), or `null` when there is none.
|
|
44
|
+
* `0.24.7-next.1` -> ["next", "1"]; `0.24.7` -> null; junk after the triple
|
|
45
|
+
* without a `-` (e.g. `2.1.132 (Claude Code)`) -> null.
|
|
46
|
+
* @param {string} v @returns {string[] | null}
|
|
47
|
+
*/
|
|
48
|
+
export function parsePrerelease(v) {
|
|
49
|
+
if (typeof v !== "string") return null;
|
|
50
|
+
const m = /^\s*v?\d+\.\d+\.\d+-([0-9A-Za-z.-]+)/.exec(v.trim());
|
|
51
|
+
if (!m) return null;
|
|
52
|
+
return m[1].split(".");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Compare two pre-release identifier lists per SemVer §11.4: a version WITHOUT
|
|
57
|
+
* a pre-release outranks one WITH; numeric identifiers rank below alphanumeric
|
|
58
|
+
* ones; a longer list outranks its own prefix. Both `null` (no pre-release) → 0.
|
|
59
|
+
* @param {string[] | null} a @param {string[] | null} b @returns {-1 | 0 | 1}
|
|
60
|
+
*/
|
|
61
|
+
function comparePrereleaseIds(a, b) {
|
|
62
|
+
// A version WITHOUT a pre-release outranks one WITH (1.0.0 > 1.0.0-next).
|
|
63
|
+
if (a === null && b === null) return 0;
|
|
64
|
+
if (a === null) return 1;
|
|
65
|
+
if (b === null) return -1;
|
|
66
|
+
const len = Math.min(a.length, b.length);
|
|
67
|
+
for (let i = 0; i < len; i++) {
|
|
68
|
+
const ai = a[i];
|
|
69
|
+
const bi = b[i];
|
|
70
|
+
const an = /^\d+$/.test(ai);
|
|
71
|
+
const bn = /^\d+$/.test(bi);
|
|
72
|
+
if (an && bn) {
|
|
73
|
+
const d = Number(ai) - Number(bi);
|
|
74
|
+
if (d !== 0) return d < 0 ? -1 : 1;
|
|
75
|
+
} else if (an !== bn) {
|
|
76
|
+
// Numeric identifiers always have lower precedence than alphanumeric.
|
|
77
|
+
return an ? -1 : 1;
|
|
78
|
+
} else if (ai !== bi) {
|
|
79
|
+
return ai < bi ? -1 : 1;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (a.length === b.length) return 0;
|
|
83
|
+
return a.length < b.length ? -1 : 1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Compare two SemVer-shaped strings by triple AND pre-release tail. Returns
|
|
88
|
+
* -1 / 0 / 1, or 0 when either triple is unparseable (never a false swap
|
|
89
|
+
* trigger). This is the attach-vs-swap comparator: successive `@next` test
|
|
90
|
+
* builds share a MAJOR.MINOR.PATCH and differ ONLY in `-next.N`, so a
|
|
91
|
+
* triple-only compare would report them equal and ATTACH to the stale server
|
|
92
|
+
* instead of swapping in the freshly published build.
|
|
93
|
+
* @param {string} a @param {string} b @returns {-1 | 0 | 1}
|
|
94
|
+
*/
|
|
95
|
+
export function compareSemverFull(a, b) {
|
|
96
|
+
const triple = compareSemver(a, b);
|
|
97
|
+
if (triple !== 0) return triple;
|
|
98
|
+
// Triples equal (or a side unparseable → compareSemver already returned 0
|
|
99
|
+
// and we must not manufacture a difference from the tails). Only when BOTH
|
|
100
|
+
// triples parsed does the pre-release tail decide.
|
|
101
|
+
if (!parseSemver(a) || !parseSemver(b)) return 0;
|
|
102
|
+
return comparePrereleaseIds(parsePrerelease(a), parsePrerelease(b));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** @param {NodeJS.Platform} [platform] */
|
|
106
|
+
export function isWindows(platform = process.platform) {
|
|
107
|
+
return platform === "win32";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Platform-correct, copy-pasteable install command for a missing prerequisite.
|
|
112
|
+
* A missing tool must never be a vague "install it" — the user gets the exact
|
|
113
|
+
* line for THEIR OS. Mirrors the pointers `scripts/verify-setup.sh` prints.
|
|
114
|
+
* @param {"uv"|"python"|"node"|"git"|"claude"} tool
|
|
115
|
+
* @param {NodeJS.Platform} [platform]
|
|
116
|
+
* @returns {string}
|
|
117
|
+
*/
|
|
118
|
+
export function installHint(tool, platform = process.platform) {
|
|
119
|
+
const win = isWindows(platform);
|
|
120
|
+
switch (tool) {
|
|
121
|
+
case "uv":
|
|
122
|
+
return win
|
|
123
|
+
? 'powershell -c "irm https://astral.sh/uv/install.ps1 | iex"'
|
|
124
|
+
: "curl -LsSf https://astral.sh/uv/install.sh | sh";
|
|
125
|
+
case "python":
|
|
126
|
+
// Coupled to uv: the whole stack runs via `uv run`, which resolves a
|
|
127
|
+
// uv-MANAGED Python — a system python3 is neither required nor sufficient.
|
|
128
|
+
// Lead with the uv path; the OS package manager / python.org is the fallback.
|
|
129
|
+
return win
|
|
130
|
+
? "install Python 3.11+ via uv (`uv python install 3.11`) — or from https://www.python.org/downloads/ (NOT the Microsoft Store stub)"
|
|
131
|
+
: "install Python 3.11+ via uv (`uv python install 3.11`) — or your package manager (e.g. `brew install python@3.11`)";
|
|
132
|
+
case "node":
|
|
133
|
+
return "install Node.js >= 20.12.0 from https://nodejs.org/";
|
|
134
|
+
case "git":
|
|
135
|
+
return win
|
|
136
|
+
? "install Git from https://git-scm.com/download/win"
|
|
137
|
+
: "install git (e.g. `brew install git` / `apt install git`)";
|
|
138
|
+
case "claude":
|
|
139
|
+
return win
|
|
140
|
+
? 'powershell -c "irm https://claude.ai/install.ps1 | iex"'
|
|
141
|
+
: "curl -fsSL https://claude.ai/install.sh | bash";
|
|
142
|
+
default:
|
|
143
|
+
return "";
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Minimum Node the packaged server needs (mirrors server/package.json engines). */
|
|
148
|
+
export const MIN_NODE = "20.12.0";
|
|
149
|
+
|
|
150
|
+
/** ASCII status glyphs — no emoji, PowerShell-5.1-safe, honest verdict blocks. */
|
|
151
|
+
export const MARK = Object.freeze({
|
|
152
|
+
pass: "[OK]",
|
|
153
|
+
fail: "[!!]",
|
|
154
|
+
warn: "[??]",
|
|
155
|
+
skip: "[--]",
|
|
156
|
+
info: "[..]",
|
|
157
|
+
});
|