frizz 0.12.11 → 0.12.13
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/dist/codex-app-server-daemon.js +8 -1
- package/dist/dev-child.js +639 -293
- package/dist/frizz.js +499 -82
- package/package.json +1 -1
- package/runtime/cc-worker/bin/frizz-mcp.mjs +19 -14
- package/runtime/cc-worker/hooks/bash-background.d.mts +1 -1
- package/runtime/cc-worker/hooks/bash-background.mjs +17 -6
- package/runtime/cc-worker/hooks/deny-ask.mjs +5 -4
- package/runtime/cc-worker/hooks/deny-plan.mjs +3 -3
- package/runtime/cc-worker/hooks/session-seed.mjs +1 -1
- package/runtime/cc-worker/skills/gh/SKILL.md +3 -3
- package/web-dist/assets/{TerminalPane-DHvHCziB.js → TerminalPane-Cv0c_SNS.js} +1 -1
- package/web-dist/assets/{abnfDiagram-VRR7QNED-DIzM_IN8.js → abnfDiagram-VRR7QNED-B-wED8ht.js} +1 -1
- package/web-dist/assets/architecture-TIHT7OUA-nsH-QfGr.js +1 -0
- package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-Bm_8vd5v.js → architectureDiagram-ZJ3FMSHR-kHm_O2sR.js} +1 -1
- package/web-dist/assets/{blockDiagram-677ZJIJ3-BXUW_N2o.js → blockDiagram-677ZJIJ3-CdazUaKU.js} +1 -1
- package/web-dist/assets/{c4Diagram-LMCZKHZV-C7rfqxUO.js → c4Diagram-LMCZKHZV-rauLKZbJ.js} +1 -1
- package/web-dist/assets/channel-fvwjeUt3.js +1 -0
- package/web-dist/assets/{chunk-32BRIVSS-DbfUERLa.js → chunk-32BRIVSS-DjOqyEDX.js} +1 -1
- package/web-dist/assets/{chunk-52WLFC77-BT_3wKSP.js → chunk-52WLFC77-f1SThegZ.js} +1 -1
- package/web-dist/assets/{chunk-C7G6YPKG-JqApnOVt.js → chunk-C7G6YPKG-BfQsesjz.js} +1 -1
- package/web-dist/assets/{chunk-EX3LRPZG-Cj6hlA4t.js → chunk-EX3LRPZG-BIzZW7OQ.js} +1 -1
- package/web-dist/assets/{chunk-FWX5IMBZ-BGthhuW_.js → chunk-FWX5IMBZ-CATINZFC.js} +2 -2
- package/web-dist/assets/{chunk-HOUHSVGY-uyLpm_YS.js → chunk-HOUHSVGY-DbMBRCCE.js} +1 -1
- package/web-dist/assets/{chunk-ICXQ74PX-BlwUMZAk.js → chunk-ICXQ74PX-COcoSWx4.js} +1 -1
- package/web-dist/assets/{chunk-MOJQB5TN-MXbNNk-P.js → chunk-MOJQB5TN-CVnI-o_4.js} +1 -1
- package/web-dist/assets/{chunk-OGEWGWER-Da4My1Rf.js → chunk-OGEWGWER-U0vdZqB6.js} +1 -1
- package/web-dist/assets/{chunk-PUDLZKDR-C-PgvO__.js → chunk-PUDLZKDR-Bukb7rem.js} +1 -1
- package/web-dist/assets/{chunk-Q4XR5HBZ-BxZFe7gr.js → chunk-Q4XR5HBZ-Bl019PHd.js} +1 -1
- package/web-dist/assets/{chunk-V7JOEXUC-DgERuXm_.js → chunk-V7JOEXUC-YJR0vzI6.js} +1 -1
- package/web-dist/assets/{chunk-VAUOI2AC-T5OoQE-_.js → chunk-VAUOI2AC-CK6NU9kj.js} +1 -1
- package/web-dist/assets/{chunk-VR4S4FIN--HFvJUG1.js → chunk-VR4S4FIN-B3LBv3C3.js} +1 -1
- package/web-dist/assets/{chunk-WYO6CB5R-DlAvy41i.js → chunk-WYO6CB5R-DjRPyRuS.js} +1 -1
- package/web-dist/assets/{chunk-ZGVPDNZ5-BdDg7X_H.js → chunk-ZGVPDNZ5-BUJCayKP.js} +1 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-BRZQ_xnN.js +1 -0
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-BRZQ_xnN.js +1 -0
- package/web-dist/assets/{cynefin-VYW2F7L2-BhjNO28R.js → cynefin-VYW2F7L2-CE3ce51v.js} +1 -1
- package/web-dist/assets/{cynefinDiagram-TSTJHNR4-B6VA5gCd.js → cynefinDiagram-TSTJHNR4-DSXSPZQV.js} +1 -1
- package/web-dist/assets/{dagre-VKFMJZFB-6MXoEc6K.js → dagre-VKFMJZFB-VwBQdjum.js} +1 -1
- package/web-dist/assets/{diagram-FQU43EPY-D2RSPoK4.js → diagram-FQU43EPY-7Tf5_WDu.js} +1 -1
- package/web-dist/assets/{diagram-G47NLZAW-BOSbtzOf.js → diagram-G47NLZAW-mu4aclWA.js} +1 -1
- package/web-dist/assets/{diagram-NH7WQ7WH-Dt_u21nP.js → diagram-NH7WQ7WH-B3kAVNwv.js} +1 -1
- package/web-dist/assets/{diagram-OA4YK3LP-CjuWW-7r.js → diagram-OA4YK3LP-DAaV-2ou.js} +1 -1
- package/web-dist/assets/{diagram-WEI45ONY-rANIKJ8N.js → diagram-WEI45ONY-DijPfgly.js} +1 -1
- package/web-dist/assets/{ebnfDiagram-CCIWWBDH-Bf3kfaKZ.js → ebnfDiagram-CCIWWBDH-B1o42Wp-.js} +1 -1
- package/web-dist/assets/{erDiagram-Q63AITRT-6vBp0ITn.js → erDiagram-Q63AITRT-Dqej9Wi3.js} +1 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-B8xeGcXU.js +1 -0
- package/web-dist/assets/flowDiagram-23GEKE2U-Cnyfcz6Z.js +1 -0
- package/web-dist/assets/{ganttDiagram-NO4QXBWP-C2qN2PMS.js → ganttDiagram-NO4QXBWP-UoyrLPUT.js} +1 -1
- package/web-dist/assets/{gitGraph-TEB2WS4Q-CRASqc9n.js → gitGraph-TEB2WS4Q-CwjIwQ3T.js} +1 -1
- package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-gsXSPrH2.js → gitGraphDiagram-IHSO6WYX-BxU758_g.js} +1 -1
- package/web-dist/assets/index-CT6k_A5y.css +1 -0
- package/web-dist/assets/index-k8HCkyvh.js +319 -0
- package/web-dist/assets/{info-DKCQHKI2-rDkFlFOd.js → info-DKCQHKI2-CWtSI6aK.js} +1 -1
- package/web-dist/assets/{infoDiagram-FWYZ7A6U-03ql8Tqr.js → infoDiagram-FWYZ7A6U-n5xRfy_d.js} +1 -1
- package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-CfDSAVNp.js → ishikawaDiagram-FXEZZL3T-DU1LTQY-.js} +1 -1
- package/web-dist/assets/{journeyDiagram-5HDEW3XC-RWaA6AvH.js → journeyDiagram-5HDEW3XC-BzZWHoPv.js} +1 -1
- package/web-dist/assets/{kanban-definition-HUTT4EX6-C89qresM.js → kanban-definition-HUTT4EX6-CeneyR7c.js} +1 -1
- package/web-dist/assets/{line-CZtSsvHu.js → line-DTfkLWnw.js} +1 -1
- package/web-dist/assets/{mermaid-parser.core-DKNnvxt0.js → mermaid-parser.core-CHzoJ5LT.js} +3 -3
- package/web-dist/assets/{mermaid.core-DX8cFeBF.js → mermaid.core-Cl84DLN2.js} +3 -3
- package/web-dist/assets/{mindmap-definition-LN4V7U3C-DW8ClyAX.js → mindmap-definition-LN4V7U3C-C39sBNqB.js} +1 -1
- package/web-dist/assets/{packet-7NZHBO7P-CUOv3apI.js → packet-7NZHBO7P-Bj73rlQn.js} +1 -1
- package/web-dist/assets/{pegDiagram-2B236MQR-CFyxKEBL.js → pegDiagram-2B236MQR-BEEM1vSv.js} +1 -1
- package/web-dist/assets/{pie-RZYD4A2V-DyXXRie2.js → pie-RZYD4A2V-CJ-fEfdy.js} +1 -1
- package/web-dist/assets/{pieDiagram-ENE6RG2P-yUw7HA8l.js → pieDiagram-ENE6RG2P-Dcqj3oyh.js} +1 -1
- package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-Mc7aea_i.js → quadrantDiagram-ABIIQ3AL-D5cljQ3D.js} +1 -1
- package/web-dist/assets/{radar-I7S5WNFK-BKj0BsQy.js → radar-I7S5WNFK-G8JqqGPf.js} +1 -1
- package/web-dist/assets/{railroad-3IZDKUUU-DUK_kJIY.js → railroad-3IZDKUUU-CaGNL0iN.js} +1 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-DWZmdy-r.js +1 -0
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-C-XoPuo_.js +1 -0
- package/web-dist/assets/railroad-peg-LSFZ7HO6-BGpxqg46.js +1 -0
- package/web-dist/assets/{railroadDiagram-RFXS5EU6-By0Xgb_U.js → railroadDiagram-RFXS5EU6-BZGZXMY4.js} +1 -1
- package/web-dist/assets/{requirementDiagram-TGXJPOKE-CgTycsRY.js → requirementDiagram-TGXJPOKE-Dj5yn_9e.js} +1 -1
- package/web-dist/assets/{sankeyDiagram-HTMAVEWB-mJ_-Grkn.js → sankeyDiagram-HTMAVEWB-7iJ_NDNf.js} +1 -1
- package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-Dn6YyeNv.js → sequenceDiagram-DBY2YBRQ-Bl54CknA.js} +1 -1
- package/web-dist/assets/{stateDiagram-2N3HPSRC-BBws1E-e.js → stateDiagram-2N3HPSRC-DuvjeNgJ.js} +1 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-BR-vrMgH.js +1 -0
- package/web-dist/assets/{swimlanes-5IMT3BWC-Jab-07o9.js → swimlanes-5IMT3BWC-B7-Jj4Sk.js} +1 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-C1HvMf2k.js +8 -0
- package/web-dist/assets/{timeline-definition-FHXFAJF6-Cq6RznHz.js → timeline-definition-FHXFAJF6-jsey2pEG.js} +1 -1
- package/web-dist/assets/{treeView-QDETBFTQ-KSelJnyL.js → treeView-QDETBFTQ-DhPmOzHr.js} +1 -1
- package/web-dist/assets/{treemap-6X3UGDF4-B-iiUurZ.js → treemap-6X3UGDF4-Dw2IaXqK.js} +1 -1
- package/web-dist/assets/{vennDiagram-L72KCM5P-B8t4NeQy.js → vennDiagram-L72KCM5P-CXKZkBab.js} +1 -1
- package/web-dist/assets/{wardley-OPB4EBWU-CtkAPZLQ.js → wardley-OPB4EBWU-CTCdDwyE.js} +1 -1
- package/web-dist/assets/{wardleyDiagram-EHGQE667-DC-ms_sD.js → wardleyDiagram-EHGQE667-B1w0xIqB.js} +1 -1
- package/web-dist/assets/{xychartDiagram-FW5EYKEG-DW6fcgjF.js → xychartDiagram-FW5EYKEG-gULk-uIl.js} +1 -1
- package/web-dist/index.html +2 -2
- package/web-dist/assets/architecture-TIHT7OUA-DBvKOf0j.js +0 -1
- package/web-dist/assets/channel-CbdXYswc.js +0 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-BVXwECjS.js +0 -1
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-BVXwECjS.js +0 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-STTT-geQ.js +0 -1
- package/web-dist/assets/flowDiagram-23GEKE2U-CC7DF1Fz.js +0 -1
- package/web-dist/assets/index-DimQCLe8.js +0 -319
- package/web-dist/assets/index-XhfdAXcw.css +0 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-BDImJcFw.js +0 -1
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-BR2XIYqq.js +0 -1
- package/web-dist/assets/railroad-peg-LSFZ7HO6-DRCwBbJY.js +0 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-B2jOFVGG.js +0 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-DhYK_6fH.js +0 -8
package/dist/frizz.js
CHANGED
|
@@ -12841,14 +12841,16 @@ var init_src = __esm({
|
|
|
12841
12841
|
"the write-up.",
|
|
12842
12842
|
"",
|
|
12843
12843
|
"**DECIDE RATHER THAN ASK.** Stop only for a decision that is genuinely the human's AND that blocks you",
|
|
12844
|
-
"right now:
|
|
12844
|
+
"right now: register that one with `mcp__frizz__ask`. Every other open choice INSIDE the task \u2014 a name, a",
|
|
12845
12845
|
"default, a reversible design call \u2014 is yours to make: decide it, say in one line which way you went and",
|
|
12846
12846
|
"what would reverse it, and carry on. A choice that would ENLARGE the task is not one of those: an",
|
|
12847
12847
|
"unanswered question is not permission to go build the answer.",
|
|
12848
12848
|
"",
|
|
12849
|
-
"Otherwise,
|
|
12849
|
+
"Otherwise, sign off \u2014 a registration, or a fence at the END of your next message:",
|
|
12850
12850
|
"",
|
|
12851
|
-
"-
|
|
12851
|
+
"- `mcp__frizz__ask` \u2014 you need the human. NOT a fence: the ```question fence is retired, and a fence",
|
|
12852
|
+
" with a question in its body is plain prose. Register it (options with one-line trade-offs, the",
|
|
12853
|
+
" recommended one first), then rest normally \u2014 an open registered question is the sign-off.",
|
|
12852
12854
|
"- `` ```done `` \u2014 genuinely FINISHED. A DISMISSAL: the card is filed away and nobody looks again, so",
|
|
12853
12855
|
" if anything is still owed, it is not done. Body: 1-3 sentences, then bullets, each opening with a",
|
|
12854
12856
|
" **bolded verb phrase**.",
|
|
@@ -19831,7 +19833,7 @@ init_local_origin();
|
|
|
19831
19833
|
import { readFileSync as readFileSync13 } from "node:fs";
|
|
19832
19834
|
import { homedir as homedir11 } from "node:os";
|
|
19833
19835
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19834
|
-
import { join as
|
|
19836
|
+
import { join as join16 } from "node:path";
|
|
19835
19837
|
|
|
19836
19838
|
// src/browser.ts
|
|
19837
19839
|
import { spawn, execFile } from "node:child_process";
|
|
@@ -22489,6 +22491,8 @@ async function readJsonBody(req, limit = 64 * 1024) {
|
|
|
22489
22491
|
var RestartSupervisorProxy = class {
|
|
22490
22492
|
server = null;
|
|
22491
22493
|
restartInFlight = null;
|
|
22494
|
+
/** Which action `restartInFlight` is. An update's prepare phase leaves the child serving; a restart does not. */
|
|
22495
|
+
transition = null;
|
|
22492
22496
|
state = "ready";
|
|
22493
22497
|
message;
|
|
22494
22498
|
options;
|
|
@@ -22615,10 +22619,11 @@ var RestartSupervisorProxy = class {
|
|
|
22615
22619
|
status() {
|
|
22616
22620
|
const delegated = this.options.status?.();
|
|
22617
22621
|
const updateVersion = this.options.updateVersion?.();
|
|
22618
|
-
const
|
|
22622
|
+
const owner = { state: this.state, ...this.message ? { message: this.message } : {} };
|
|
22623
|
+
const reported = this.transition === "update" && delegated ? { ...delegated, ...delegated.state === "ready" ? { preparing: true } : {} } : this.restartInFlight !== null || this.state === "failed" ? owner : delegated ?? owner;
|
|
22619
22624
|
return {
|
|
22620
22625
|
...delegated ?? {},
|
|
22621
|
-
...
|
|
22626
|
+
...reported,
|
|
22622
22627
|
// Never infer this from the generic protocol: legacy/static supervisors can recover a child
|
|
22623
22628
|
// but cannot build and promote the canonical Frizz artifact.
|
|
22624
22629
|
updateRestart: typeof this.options.updateRestart === "function",
|
|
@@ -22634,8 +22639,9 @@ var RestartSupervisorProxy = class {
|
|
|
22634
22639
|
...this.options.dev ? { dev: true } : {}
|
|
22635
22640
|
};
|
|
22636
22641
|
}
|
|
22637
|
-
async runAction(action) {
|
|
22642
|
+
async runAction(action, transition) {
|
|
22638
22643
|
if (this.restartInFlight) return this.restartInFlight;
|
|
22644
|
+
this.transition = transition;
|
|
22639
22645
|
this.state = "restarting";
|
|
22640
22646
|
this.message = void 0;
|
|
22641
22647
|
const work = (async () => {
|
|
@@ -22655,6 +22661,7 @@ var RestartSupervisorProxy = class {
|
|
|
22655
22661
|
}
|
|
22656
22662
|
).finally(() => {
|
|
22657
22663
|
this.restartInFlight = null;
|
|
22664
|
+
this.transition = null;
|
|
22658
22665
|
});
|
|
22659
22666
|
this.restartInFlight = work;
|
|
22660
22667
|
return work;
|
|
@@ -22738,11 +22745,11 @@ var RestartSupervisorProxy = class {
|
|
|
22738
22745
|
return;
|
|
22739
22746
|
}
|
|
22740
22747
|
if (pathname === SUPERVISOR_UPDATE_RESTART_PATH) {
|
|
22741
|
-
void this.runAction(this.options.updateRestart);
|
|
22748
|
+
void this.runAction(this.options.updateRestart, "update");
|
|
22742
22749
|
responseJson(res, 202, { protocol: SUPERVISOR_CONTROL_PROTOCOL, state: "restarting" });
|
|
22743
22750
|
return;
|
|
22744
22751
|
}
|
|
22745
|
-
const result = await this.runAction(this.options.restart);
|
|
22752
|
+
const result = await this.runAction(this.options.restart, "restart");
|
|
22746
22753
|
responseJson(res, result.state === "ready" ? 202 : 503, { protocol: SUPERVISOR_CONTROL_PROTOCOL, ...result });
|
|
22747
22754
|
}
|
|
22748
22755
|
handleLocalImage(req, res) {
|
|
@@ -22975,10 +22982,17 @@ async function signOutSession(port, target2) {
|
|
|
22975
22982
|
|
|
22976
22983
|
// src/pane-host.ts
|
|
22977
22984
|
var CTRL_C = "";
|
|
22985
|
+
function raiseInterrupt() {
|
|
22986
|
+
if (process.listenerCount("SIGINT") > 0) {
|
|
22987
|
+
process.emit("SIGINT", "SIGINT");
|
|
22988
|
+
return;
|
|
22989
|
+
}
|
|
22990
|
+
process.kill(process.pid, "SIGINT");
|
|
22991
|
+
}
|
|
22978
22992
|
function installPaneHost(options2) {
|
|
22979
22993
|
const input = options2.input ?? process.stdin;
|
|
22980
22994
|
const output = options2.output ?? process.stdout;
|
|
22981
|
-
const onInterrupt = options2.onInterrupt ??
|
|
22995
|
+
const onInterrupt = options2.onInterrupt ?? raiseInterrupt;
|
|
22982
22996
|
if (!input.isTTY || !output.isTTY || typeof input.setRawMode !== "function") return null;
|
|
22983
22997
|
let active = null;
|
|
22984
22998
|
let disposed = false;
|
|
@@ -23498,9 +23512,9 @@ function connectRelay(options2) {
|
|
|
23498
23512
|
};
|
|
23499
23513
|
const scheduleRetry = (reason) => {
|
|
23500
23514
|
if (stopped) return;
|
|
23501
|
-
const
|
|
23502
|
-
options2.onStatus?.("retrying", `${reason}; retrying in ${Math.round(
|
|
23503
|
-
retryHandle = setTimer(() => void open(),
|
|
23515
|
+
const delay4 = backoff(attempt++);
|
|
23516
|
+
options2.onStatus?.("retrying", `${reason}; retrying in ${Math.round(delay4 / 1e3)}s`);
|
|
23517
|
+
retryHandle = setTimer(() => void open(), delay4);
|
|
23504
23518
|
};
|
|
23505
23519
|
const open = async () => {
|
|
23506
23520
|
if (stopped) return;
|
|
@@ -24300,7 +24314,7 @@ function formatDuration(ms) {
|
|
|
24300
24314
|
function tildePath(path, home) {
|
|
24301
24315
|
if (!home || !path.startsWith(home)) return path;
|
|
24302
24316
|
const rest = path.slice(home.length);
|
|
24303
|
-
return rest === "" ? "~" : rest
|
|
24317
|
+
return rest === "" ? "~" : /^[\\/]/.test(rest) ? `~${rest}` : path;
|
|
24304
24318
|
}
|
|
24305
24319
|
var Readout = class {
|
|
24306
24320
|
out;
|
|
@@ -24952,6 +24966,54 @@ async function probeFrizz(port, expected2, fetcher = fetch, timeoutMs = HEALTH_P
|
|
|
24952
24966
|
clearTimeout(timeout);
|
|
24953
24967
|
}
|
|
24954
24968
|
}
|
|
24969
|
+
async function readFrizzHealth(port, fetcher = fetch, timeoutMs = HEALTH_PROBE_TIMEOUT_MS) {
|
|
24970
|
+
const controller = new AbortController();
|
|
24971
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
24972
|
+
timeout.unref?.();
|
|
24973
|
+
try {
|
|
24974
|
+
const response = await fetcher(`http://127.0.0.1:${port}${FRIZZ_ROUTE_PREFIX}/health`, { signal: controller.signal });
|
|
24975
|
+
if (!response.ok) return null;
|
|
24976
|
+
const health = await response.json();
|
|
24977
|
+
if (health.ok !== true || typeof health.projectId !== "string" || typeof health.projectDir !== "string" || typeof health.bootId !== "string") return null;
|
|
24978
|
+
return health;
|
|
24979
|
+
} catch {
|
|
24980
|
+
return null;
|
|
24981
|
+
} finally {
|
|
24982
|
+
clearTimeout(timeout);
|
|
24983
|
+
}
|
|
24984
|
+
}
|
|
24985
|
+
async function resolveLaunchControlTarget(options2) {
|
|
24986
|
+
const own = { target: options2.target, stateDir: options2.stateDir, host: true };
|
|
24987
|
+
if (readProjectLaunchOwner(options2.stateDir)) return own;
|
|
24988
|
+
const fetcher = options2.fetcher ?? fetch;
|
|
24989
|
+
const stateDirFor = options2.stateDirFor ?? ((projectId) => projectStateDir(projectId));
|
|
24990
|
+
for (const port of new Set(options2.ports ?? [DEFAULT_PORT, fallbackPort(DEFAULT_PORT)])) {
|
|
24991
|
+
const health = await readFrizzHealth(port, fetcher);
|
|
24992
|
+
if (!health || health.projectId === options2.target.projectId) continue;
|
|
24993
|
+
const stateDir = stateDirFor(health.projectId);
|
|
24994
|
+
if (!readProjectLaunchOwner(stateDir)) continue;
|
|
24995
|
+
return { target: { projectId: health.projectId, projectDir: health.projectDir, stateDir }, stateDir, host: false };
|
|
24996
|
+
}
|
|
24997
|
+
return own;
|
|
24998
|
+
}
|
|
24999
|
+
async function requestFrizzStop(port, expected2, ownerToken, fetcher = fetch) {
|
|
25000
|
+
if (!await probeFrizz(port, expected2, fetcher)) return false;
|
|
25001
|
+
const controller = new AbortController();
|
|
25002
|
+
const timeout = setTimeout(() => controller.abort(), 1e3);
|
|
25003
|
+
timeout.unref?.();
|
|
25004
|
+
try {
|
|
25005
|
+
const response = await fetcher(`http://127.0.0.1:${port}${FRIZZ_ROUTE_PREFIX}/control/stop`, {
|
|
25006
|
+
method: "POST",
|
|
25007
|
+
headers: { "x-frizz-launch-token": ownerToken },
|
|
25008
|
+
signal: controller.signal
|
|
25009
|
+
});
|
|
25010
|
+
return response.status === 202;
|
|
25011
|
+
} catch {
|
|
25012
|
+
return false;
|
|
25013
|
+
} finally {
|
|
25014
|
+
clearTimeout(timeout);
|
|
25015
|
+
}
|
|
25016
|
+
}
|
|
24955
25017
|
function expectedOwnerHealth(target2, owner) {
|
|
24956
25018
|
return {
|
|
24957
25019
|
projectId: target2.projectId,
|
|
@@ -25042,6 +25104,66 @@ async function waitForWorkspace(port, expected2, timeoutMs = LAUNCH_TIMEOUT_MS,
|
|
|
25042
25104
|
await delay2(150);
|
|
25043
25105
|
}
|
|
25044
25106
|
}
|
|
25107
|
+
async function stopProjectLaunch(options2) {
|
|
25108
|
+
const { stateDir, target: target2 } = options2;
|
|
25109
|
+
const adapter = options2.adapter ?? defaultProcessPlatformAdapter;
|
|
25110
|
+
const fetcher = options2.fetcher ?? fetch;
|
|
25111
|
+
const sleep = options2.sleep ?? ((ms) => delay2(ms));
|
|
25112
|
+
const owner = readProjectLaunchOwner(stateDir);
|
|
25113
|
+
if (!owner) return { kind: "not-running" };
|
|
25114
|
+
const status = liveWorkspaceOwner(stateDir, target2, adapter);
|
|
25115
|
+
const controlPort = status?.port ?? (status ? void 0 : await options2.fallbackPort?.());
|
|
25116
|
+
const controlled = controlPort ? await requestFrizzStop(controlPort, expectedOwnerHealth(target2, owner), owner.token, fetcher) : false;
|
|
25117
|
+
if (!controlled && !processGenerationIsStale(owner, adapter)) {
|
|
25118
|
+
throw new Error(
|
|
25119
|
+
"Frizz refused to stop a live owner without authenticated token-bound control; the owner was left untouched"
|
|
25120
|
+
);
|
|
25121
|
+
}
|
|
25122
|
+
const reap = () => {
|
|
25123
|
+
if (!readProjectLaunchOwner(stateDir)) return true;
|
|
25124
|
+
const reaped = tryAcquireProjectLaunchOwner(target2, "launcher", { delegateDrainTimeoutMs: 250, adapter });
|
|
25125
|
+
if (reaped.kind !== "acquired") return false;
|
|
25126
|
+
reaped.lease.release();
|
|
25127
|
+
return true;
|
|
25128
|
+
};
|
|
25129
|
+
const deadline = adapter.now() + (options2.timeoutMs ?? 1e4);
|
|
25130
|
+
while (adapter.now() < deadline) {
|
|
25131
|
+
if (reap()) return { kind: "stopped", stale: !controlled };
|
|
25132
|
+
await sleep(100);
|
|
25133
|
+
}
|
|
25134
|
+
await sleep(100);
|
|
25135
|
+
if (reap()) return { kind: "stopped", stale: !controlled };
|
|
25136
|
+
throw new Error(`supervisor pid ${owner.pid} did not stop within ${Math.round((options2.timeoutMs ?? 1e4) / 1e3)}s`);
|
|
25137
|
+
}
|
|
25138
|
+
async function runningFrizzStatus(options2) {
|
|
25139
|
+
const fetcher = options2.fetcher ?? fetch;
|
|
25140
|
+
const owner = liveWorkspaceOwner(options2.stateDir, options2.target, options2.adapter ?? defaultProcessPlatformAdapter);
|
|
25141
|
+
if (!owner?.port) return null;
|
|
25142
|
+
const expected2 = expectedOwnerHealth(options2.target, readProjectLaunchOwner(options2.stateDir));
|
|
25143
|
+
if (!await probeFrizz(owner.port, expected2, fetcher)) return null;
|
|
25144
|
+
const controller = new AbortController();
|
|
25145
|
+
const timeout = setTimeout(() => controller.abort(), HEALTH_PROBE_TIMEOUT_MS);
|
|
25146
|
+
timeout.unref?.();
|
|
25147
|
+
let control = {};
|
|
25148
|
+
try {
|
|
25149
|
+
const response = await fetcher(`http://127.0.0.1:${owner.port}${FRIZZ_ROUTE_PREFIX}/control/status`, {
|
|
25150
|
+
signal: controller.signal,
|
|
25151
|
+
headers: { origin: `http://127.0.0.1:${owner.port}`, "cache-control": "no-store" }
|
|
25152
|
+
});
|
|
25153
|
+
if (response.ok) {
|
|
25154
|
+
const body = await response.json();
|
|
25155
|
+
control = {
|
|
25156
|
+
...typeof body.version === "string" ? { version: body.version } : {},
|
|
25157
|
+
...typeof body.state === "string" ? { state: body.state } : {},
|
|
25158
|
+
...typeof body.message === "string" ? { message: body.message } : {}
|
|
25159
|
+
};
|
|
25160
|
+
}
|
|
25161
|
+
} catch {
|
|
25162
|
+
} finally {
|
|
25163
|
+
clearTimeout(timeout);
|
|
25164
|
+
}
|
|
25165
|
+
return { port: owner.port, pid: owner.pid, ...control };
|
|
25166
|
+
}
|
|
25045
25167
|
|
|
25046
25168
|
// src/production.ts
|
|
25047
25169
|
init_project_launch();
|
|
@@ -25061,6 +25183,7 @@ var DEV_CRASH_STABLE_MS = 5e3;
|
|
|
25061
25183
|
var DEV_CRASH_RETRY_BASE_MS = 500;
|
|
25062
25184
|
var DEV_CRASH_RETRY_MAX_MS = 1e4;
|
|
25063
25185
|
var CHILD_STOP_TIMEOUT_MS = 15e3;
|
|
25186
|
+
var CHILD_KILL_GRACE_MS = 5e3;
|
|
25064
25187
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".mjs", ".cjs", ".json"]);
|
|
25065
25188
|
var CONFIG_NAMES = /* @__PURE__ */ new Set(["package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml", ".npmrc"]);
|
|
25066
25189
|
var CHILD_RUNTIME_PACKAGES = /* @__PURE__ */ new Set(["server", "shared", "rpc", "claude-agent-sdk-runtime"]);
|
|
@@ -25091,7 +25214,7 @@ function devCrashRetryDelay(attempt) {
|
|
|
25091
25214
|
return Math.min(DEV_CRASH_RETRY_BASE_MS * 2 ** exponent, DEV_CRASH_RETRY_MAX_MS);
|
|
25092
25215
|
}
|
|
25093
25216
|
var SUPERVISOR_ESCALATE_GRACE_MS = 500;
|
|
25094
|
-
var SUPERVISOR_DRAIN_DEADLINE_MS = CHILD_STOP_TIMEOUT_MS + 5e3;
|
|
25217
|
+
var SUPERVISOR_DRAIN_DEADLINE_MS = CHILD_STOP_TIMEOUT_MS + CHILD_KILL_GRACE_MS + 5e3;
|
|
25095
25218
|
function stripPrefix(line) {
|
|
25096
25219
|
return line.startsWith("[frizz] ") ? line.slice("[frizz] ".length) : line;
|
|
25097
25220
|
}
|
|
@@ -25306,6 +25429,13 @@ var Supervisor = class {
|
|
|
25306
25429
|
/** Environment of the generation that actually reached ready, never merely the latest pointer. */
|
|
25307
25430
|
activeChildEnvironment = {};
|
|
25308
25431
|
lastRestartFailure;
|
|
25432
|
+
/**
|
|
25433
|
+
* True from the moment an update starts draining the old child until that update has settled.
|
|
25434
|
+
* Before it — the prepare phase — the old child is untouched and serving, and the status delegate
|
|
25435
|
+
* says so; during it the child bookkeeping reads as "failed" (no child, no boot), which is not
|
|
25436
|
+
* what a poll during those seconds should learn.
|
|
25437
|
+
*/
|
|
25438
|
+
handoffDraining = false;
|
|
25309
25439
|
constructor(opts) {
|
|
25310
25440
|
const launchOwner = verifyProjectLaunchDelegate(opts.launchTarget, opts.launchOwnerToken);
|
|
25311
25441
|
const callerGeneration = currentProcessGeneration();
|
|
@@ -25324,7 +25454,7 @@ var Supervisor = class {
|
|
|
25324
25454
|
this.childLaunchProvider = opts.childLaunchProvider;
|
|
25325
25455
|
this.childArgs = opts.childArgs ?? [];
|
|
25326
25456
|
this.watchSubscribe = opts.watchSubscribe ?? ((root, callback, options2) => watcher.subscribe(root, callback, options2));
|
|
25327
|
-
this.reexec = opts.reexec ?? (typeof process.execve === "function" ? (request) => process.execve(request.executable, request.argv, request.env) : void 0);
|
|
25457
|
+
this.reexec = opts.reexec ?? (process.platform !== "win32" && typeof process.execve === "function" ? (request) => process.execve(request.executable, request.argv, request.env) : void 0);
|
|
25328
25458
|
if (opts.stateDir && resolve5(opts.stateDir) !== opts.launchTarget.stateDir) {
|
|
25329
25459
|
throw new Error("dev supervisor state directory does not match its owned project");
|
|
25330
25460
|
}
|
|
@@ -25352,7 +25482,7 @@ var Supervisor = class {
|
|
|
25352
25482
|
updateVersion: opts.updateVersion,
|
|
25353
25483
|
dev: opts.dev,
|
|
25354
25484
|
status: () => {
|
|
25355
|
-
if (this.browserRestart || this.restartRunning) return { state: "restarting" };
|
|
25485
|
+
if (this.handoffDraining || this.browserRestart || this.restartRunning) return { state: "restarting" };
|
|
25356
25486
|
const failed = this.child === null && this.boot === null;
|
|
25357
25487
|
const artifactDigest = this.activeChildEnvironment.FRIZZ_STABLE_ARTIFACT;
|
|
25358
25488
|
return failed ? { state: "failed", message: "Frizz application server is not ready", ...artifactDigest ? { artifactDigest } : {} } : { state: "ready", ...artifactDigest ? { artifactDigest } : {} };
|
|
@@ -25505,7 +25635,7 @@ var Supervisor = class {
|
|
|
25505
25635
|
}
|
|
25506
25636
|
async updateFromBrowser() {
|
|
25507
25637
|
if (!this.updateRestart) return { state: "failed", message: "Update & Restart is unavailable in this launcher mode" };
|
|
25508
|
-
this.emitActivity("updating", "preparing the
|
|
25638
|
+
this.emitActivity("updating", "preparing the update \u2014 the running Frizz is untouched until it is ready");
|
|
25509
25639
|
const candidate = await this.updateRestart();
|
|
25510
25640
|
if (candidate.state !== "ready") {
|
|
25511
25641
|
this.emitActivity("failed", candidate.message ?? "the update could not be prepared");
|
|
@@ -25527,6 +25657,8 @@ var Supervisor = class {
|
|
|
25527
25657
|
} catch (error) {
|
|
25528
25658
|
const message = `durable supervisor handoff failed: ${error instanceof Error ? error.message : error}`;
|
|
25529
25659
|
return this.failDurableUpdate(message, handoffPreparationStarted);
|
|
25660
|
+
} finally {
|
|
25661
|
+
this.handoffDraining = false;
|
|
25530
25662
|
}
|
|
25531
25663
|
}
|
|
25532
25664
|
/**
|
|
@@ -25566,6 +25698,7 @@ var Supervisor = class {
|
|
|
25566
25698
|
if (!ready) throw new Error("the recovered control plane did not become ready");
|
|
25567
25699
|
}
|
|
25568
25700
|
async prepareDurableReexec() {
|
|
25701
|
+
this.handoffDraining = true;
|
|
25569
25702
|
this.closed = true;
|
|
25570
25703
|
this.clearCrashStability();
|
|
25571
25704
|
if (this.debounce) clearTimeout(this.debounce);
|
|
@@ -25598,7 +25731,13 @@ var Supervisor = class {
|
|
|
25598
25731
|
// The supervisor may itself run under `node --input-type`, `--test`, an inspector, etc. Those
|
|
25599
25732
|
// parent-only flags are invalid or dangerous for a file-backed control-plane child.
|
|
25600
25733
|
execArgv: [],
|
|
25601
|
-
stdio: ["inherit", "inherit", "inherit", "ipc"]
|
|
25734
|
+
stdio: ["inherit", "inherit", "inherit", "ipc"],
|
|
25735
|
+
// A registry update leaves this supervisor with no console on Windows (its successor starts
|
|
25736
|
+
// detached). A console program forked from a console-less parent gets a new, VISIBLE console
|
|
25737
|
+
// window, and closing that window would stop the board. `windowsHide` keeps the window from
|
|
25738
|
+
// appearing (measured 2026-09-07: hwnd 0 for the child and its children). No effect elsewhere.
|
|
25739
|
+
// `fork` passes it to `spawn` at runtime; `ForkOptions` in @types/node 24 does not declare it.
|
|
25740
|
+
...{ windowsHide: true }
|
|
25602
25741
|
});
|
|
25603
25742
|
} catch (error) {
|
|
25604
25743
|
const message = `child spawn failed: ${error instanceof Error ? error.message : error}; watching for a corrective edit`;
|
|
@@ -25774,6 +25913,21 @@ var Supervisor = class {
|
|
|
25774
25913
|
this.errorLine("[frizz] dev launcher re-exec returned unexpectedly; restart Frizz once");
|
|
25775
25914
|
this.resolveStopRequested();
|
|
25776
25915
|
}
|
|
25916
|
+
/**
|
|
25917
|
+
* Drain the control-plane child: ASK first, signal only a child that did not answer.
|
|
25918
|
+
*
|
|
25919
|
+
* The ask is `child.disconnect()` — closing the IPC channel — because dev-child already treats a
|
|
25920
|
+
* lost supervisor as an order to shut down (`process.once("disconnect")`), so it needs no second
|
|
25921
|
+
* protocol and it works on every platform. The ask used to be `kill("SIGTERM")`, which on POSIX
|
|
25922
|
+
* runs the same shutdown handler but on Windows is a TerminateProcess: Node maps EVERY signal it
|
|
25923
|
+
* can send to a hard kill there, so the child's `server.close()`, its shutdown fence and its
|
|
25924
|
+
* delegate release never ran, and every Restart and every update on Windows cut open RPCs and
|
|
25925
|
+
* socket writes mid-flight (audit 2026-09-11, finding 3). Only a child that has not exited within
|
|
25926
|
+
* CHILD_STOP_TIMEOUT_MS is signalled — SIGTERM then, CHILD_KILL_GRACE_MS later, SIGKILL on POSIX,
|
|
25927
|
+
* where a wedged event loop ignores the first; a single kill() on win32, where the first is final.
|
|
25928
|
+
* A child with no channel to ask over (already gone, or never had one) gets the signal at once,
|
|
25929
|
+
* which is exactly what it got before.
|
|
25930
|
+
*/
|
|
25777
25931
|
async stopChild() {
|
|
25778
25932
|
this.clearCrashStability();
|
|
25779
25933
|
const child = this.child;
|
|
@@ -25781,19 +25935,38 @@ var Supervisor = class {
|
|
|
25781
25935
|
this.stopping = child;
|
|
25782
25936
|
await new Promise((resolveStop) => {
|
|
25783
25937
|
let done = false;
|
|
25938
|
+
const timers = [];
|
|
25784
25939
|
const finish = () => {
|
|
25785
25940
|
if (done) return;
|
|
25786
25941
|
done = true;
|
|
25787
|
-
clearTimeout(
|
|
25942
|
+
for (const timer of timers) clearTimeout(timer);
|
|
25788
25943
|
resolveStop();
|
|
25789
25944
|
};
|
|
25945
|
+
const later = (callback, delayMs) => {
|
|
25946
|
+
const timer = setTimeout(callback, delayMs);
|
|
25947
|
+
timer.unref();
|
|
25948
|
+
timers.push(timer);
|
|
25949
|
+
};
|
|
25950
|
+
const who = `dev child ${child.pid ?? "?"}`;
|
|
25951
|
+
const signal = (name, why) => {
|
|
25952
|
+
this.errorLine(`[frizz] ${who} ${why}; ${name === "SIGTERM" ? "sending SIGTERM to" : "killing"} the control plane only`);
|
|
25953
|
+
if (!child.kill(name)) finish();
|
|
25954
|
+
};
|
|
25955
|
+
const escalate = (why) => {
|
|
25956
|
+
if (process.platform === "win32") {
|
|
25957
|
+
signal(void 0, why);
|
|
25958
|
+
return;
|
|
25959
|
+
}
|
|
25960
|
+
signal("SIGTERM", why);
|
|
25961
|
+
later(() => signal("SIGKILL", `ignored SIGTERM for ${CHILD_KILL_GRACE_MS}ms`), CHILD_KILL_GRACE_MS);
|
|
25962
|
+
};
|
|
25790
25963
|
child.once("exit", finish);
|
|
25791
|
-
|
|
25792
|
-
|
|
25793
|
-
|
|
25794
|
-
}
|
|
25795
|
-
|
|
25796
|
-
|
|
25964
|
+
if (!child.connected) {
|
|
25965
|
+
escalate("has no IPC channel to ask over");
|
|
25966
|
+
return;
|
|
25967
|
+
}
|
|
25968
|
+
later(() => escalate(`did not close in ${CHILD_STOP_TIMEOUT_MS}ms`), CHILD_STOP_TIMEOUT_MS);
|
|
25969
|
+
child.disconnect();
|
|
25797
25970
|
});
|
|
25798
25971
|
if (this.child === child) this.child = null;
|
|
25799
25972
|
if (this.childPort !== void 0) this.childPort = void 0;
|
|
@@ -25839,11 +26012,32 @@ async function startDevSupervisor(opts) {
|
|
|
25839
26012
|
}
|
|
25840
26013
|
|
|
25841
26014
|
// src/production-update.ts
|
|
26015
|
+
init_src();
|
|
25842
26016
|
import { execFile as execFile4, spawn as spawn3 } from "node:child_process";
|
|
25843
26017
|
import { existsSync as existsSync7 } from "node:fs";
|
|
25844
|
-
import { isAbsolute as isAbsolute5 } from "node:path";
|
|
26018
|
+
import { dirname as dirname12, isAbsolute as isAbsolute5, join as join14 } from "node:path";
|
|
26019
|
+
import { setTimeout as delay3 } from "node:timers/promises";
|
|
25845
26020
|
var PRODUCTION_REEXEC_FLAG = "--_frizz-production-reexec";
|
|
26021
|
+
function canReexecInPlace(platform = process.platform, execve = process.execve) {
|
|
26022
|
+
return platform !== "win32" && typeof execve === "function";
|
|
26023
|
+
}
|
|
25846
26024
|
var PRODUCTION_PRINT_LAUNCHER_FLAG = "--_frizz-print-launcher";
|
|
26025
|
+
function resolveNpmInvocation(env = process.env, execPath = process.execPath, exists = existsSync7, platform = process.platform) {
|
|
26026
|
+
const nodeDir = dirname12(execPath);
|
|
26027
|
+
const candidates = [
|
|
26028
|
+
// pnpm, yarn and bun set `npm_execpath` too, to their own entry file. Their directories hold no
|
|
26029
|
+
// `npm-cli.js`, so the existence check below skips them.
|
|
26030
|
+
env.npm_execpath ? join14(dirname12(env.npm_execpath), "npm-cli.js") : void 0,
|
|
26031
|
+
join14(nodeDir, "node_modules", "npm", "bin", "npm-cli.js"),
|
|
26032
|
+
join14(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
|
|
26033
|
+
].filter((candidate) => candidate !== void 0);
|
|
26034
|
+
const script = candidates.find((candidate) => exists(candidate));
|
|
26035
|
+
if (script) return { command: execPath, prefixArgs: [script] };
|
|
26036
|
+
if (platform === "win32") {
|
|
26037
|
+
throw new Error(`npm-cli.js not found beside ${execPath} (searched: ${candidates.join(", ")})`);
|
|
26038
|
+
}
|
|
26039
|
+
return { command: "npm", prefixArgs: [] };
|
|
26040
|
+
}
|
|
25847
26041
|
function compareReleaseVersions(a, b) {
|
|
25848
26042
|
const parse2 = (value) => {
|
|
25849
26043
|
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/u.exec(value);
|
|
@@ -25860,7 +26054,23 @@ function compareReleaseVersions(a, b) {
|
|
|
25860
26054
|
if (left.prerelease === right.prerelease) return 0;
|
|
25861
26055
|
if (!left.prerelease) return 1;
|
|
25862
26056
|
if (!right.prerelease) return -1;
|
|
25863
|
-
return left.prerelease
|
|
26057
|
+
return comparePrerelease(left.prerelease, right.prerelease);
|
|
26058
|
+
}
|
|
26059
|
+
function comparePrerelease(a, b) {
|
|
26060
|
+
const left = a.split(".");
|
|
26061
|
+
const right = b.split(".");
|
|
26062
|
+
for (let index = 0; index < Math.min(left.length, right.length); index++) {
|
|
26063
|
+
const l = left[index];
|
|
26064
|
+
const r = right[index];
|
|
26065
|
+
if (l === r) continue;
|
|
26066
|
+
const lNumeric = /^\d+$/u.test(l);
|
|
26067
|
+
const rNumeric = /^\d+$/u.test(r);
|
|
26068
|
+
if (lNumeric && rNumeric) return Number(l) < Number(r) ? -1 : 1;
|
|
26069
|
+
if (lNumeric !== rNumeric) return lNumeric ? -1 : 1;
|
|
26070
|
+
return l < r ? -1 : 1;
|
|
26071
|
+
}
|
|
26072
|
+
if (left.length === right.length) return 0;
|
|
26073
|
+
return left.length < right.length ? -1 : 1;
|
|
25864
26074
|
}
|
|
25865
26075
|
async function planRegistryUpdate(packageName, currentVersion, adapter) {
|
|
25866
26076
|
const latestVersion = (await adapter.latestVersion(packageName)).trim();
|
|
@@ -25873,6 +26083,20 @@ async function planRegistryUpdate(packageName, currentVersion, adapter) {
|
|
|
25873
26083
|
function successorArgs(port) {
|
|
25874
26084
|
return [PRODUCTION_REEXEC_FLAG, "--port", String(port)];
|
|
25875
26085
|
}
|
|
26086
|
+
function reexecArgv(rawArgs2) {
|
|
26087
|
+
const kept = [];
|
|
26088
|
+
for (let index = 0; index < rawArgs2.length; index++) {
|
|
26089
|
+
const arg = rawArgs2[index];
|
|
26090
|
+
if (arg === PRODUCTION_REEXEC_FLAG) continue;
|
|
26091
|
+
if (arg === "--port" || arg === "--sign-out") {
|
|
26092
|
+
kept.push(arg);
|
|
26093
|
+
if (index + 1 < rawArgs2.length) kept.push(rawArgs2[++index]);
|
|
26094
|
+
continue;
|
|
26095
|
+
}
|
|
26096
|
+
if (arg.startsWith("-")) kept.push(arg);
|
|
26097
|
+
}
|
|
26098
|
+
return kept;
|
|
26099
|
+
}
|
|
25876
26100
|
async function resolveRegistrySuccessor(plan, request, adapter) {
|
|
25877
26101
|
const result = await adapter.npmExec({
|
|
25878
26102
|
packageSpec: plan.packageSpec,
|
|
@@ -25913,52 +26137,168 @@ function handoffToRegistrySuccessor(successor, request, adapter) {
|
|
|
25913
26137
|
});
|
|
25914
26138
|
child.once("error", () => {
|
|
25915
26139
|
});
|
|
26140
|
+
if (child.pid === void 0) throw new Error(`could not start Frizz ${successor.plan.latestVersion} from ${successor.entry}`);
|
|
25916
26141
|
child.unref();
|
|
25917
|
-
|
|
25918
|
-
|
|
25919
|
-
|
|
25920
|
-
|
|
25921
|
-
|
|
25922
|
-
|
|
26142
|
+
return child;
|
|
26143
|
+
}
|
|
26144
|
+
var SUCCESSOR_READY_TIMEOUT_MS = 6e4;
|
|
26145
|
+
async function awaitRegistrySuccessor(child, expected2, watch) {
|
|
26146
|
+
const deadlineMs = watch.deadlineMs ?? SUCCESSOR_READY_TIMEOUT_MS;
|
|
26147
|
+
const intervalMs = watch.intervalMs ?? 250;
|
|
26148
|
+
const now = watch.now ?? Date.now;
|
|
26149
|
+
const sleep = watch.sleep ?? ((ms) => delay3(ms));
|
|
26150
|
+
const where = expected2.logFile ? `; its log is ${expected2.logFile}` : "";
|
|
26151
|
+
let exited = child.exitCode !== null || child.signalCode !== null ? describeExit(child.exitCode, child.signalCode) : void 0;
|
|
26152
|
+
const onExit = (code, signal) => {
|
|
26153
|
+
exited = describeExit(code, signal);
|
|
26154
|
+
};
|
|
26155
|
+
child.once("exit", onExit);
|
|
26156
|
+
try {
|
|
26157
|
+
const started = now();
|
|
26158
|
+
for (; ; ) {
|
|
26159
|
+
if (exited) throw new Error(`Frizz ${expected2.version} exited (${exited}) before it answered on port ${expected2.port}${where}`);
|
|
26160
|
+
const status = await watch.status();
|
|
26161
|
+
if (status?.version === expected2.version) return;
|
|
26162
|
+
if (now() - started >= deadlineMs) {
|
|
25923
26163
|
try {
|
|
25924
|
-
|
|
25925
|
-
resolveVersion(typeof parsed === "string" ? parsed : String(parsed));
|
|
26164
|
+
child.kill();
|
|
25926
26165
|
} catch {
|
|
25927
|
-
resolveVersion(stdout.trim().replaceAll('"', ""));
|
|
25928
26166
|
}
|
|
25929
|
-
|
|
26167
|
+
throw new Error(
|
|
26168
|
+
`Frizz ${expected2.version} did not answer on port ${expected2.port} within ${Math.round(deadlineMs / 1e3)}s${where}`
|
|
26169
|
+
);
|
|
26170
|
+
}
|
|
26171
|
+
await sleep(intervalMs);
|
|
26172
|
+
}
|
|
26173
|
+
} finally {
|
|
26174
|
+
child.off("exit", onExit);
|
|
26175
|
+
}
|
|
26176
|
+
}
|
|
26177
|
+
function describeExit(code, signal) {
|
|
26178
|
+
return signal ? `signal ${signal}` : `exit ${code ?? "unknown"}`;
|
|
26179
|
+
}
|
|
26180
|
+
function launcherControlHeaders(port) {
|
|
26181
|
+
return { origin: `http://127.0.0.1:${port}`, "cache-control": "no-store" };
|
|
26182
|
+
}
|
|
26183
|
+
async function readLauncherStatus(port, fetcher = fetch) {
|
|
26184
|
+
const controller = new AbortController();
|
|
26185
|
+
const timeout = setTimeout(() => controller.abort(), 1e3);
|
|
26186
|
+
timeout.unref?.();
|
|
26187
|
+
try {
|
|
26188
|
+
const response = await fetcher(`http://127.0.0.1:${port}${FRIZZ_ROUTE_PREFIX}/control/status`, {
|
|
26189
|
+
signal: controller.signal,
|
|
26190
|
+
headers: launcherControlHeaders(port)
|
|
25930
26191
|
});
|
|
25931
|
-
|
|
25932
|
-
|
|
25933
|
-
return
|
|
25934
|
-
|
|
25935
|
-
|
|
25936
|
-
|
|
25937
|
-
|
|
25938
|
-
|
|
25939
|
-
|
|
25940
|
-
|
|
25941
|
-
|
|
25942
|
-
|
|
25943
|
-
|
|
25944
|
-
|
|
25945
|
-
|
|
26192
|
+
if (!response.ok) return void 0;
|
|
26193
|
+
const body = await response.json();
|
|
26194
|
+
return {
|
|
26195
|
+
...typeof body.version === "string" ? { version: body.version } : {},
|
|
26196
|
+
...typeof body.state === "string" ? { state: body.state } : {}
|
|
26197
|
+
};
|
|
26198
|
+
} catch {
|
|
26199
|
+
return void 0;
|
|
26200
|
+
} finally {
|
|
26201
|
+
clearTimeout(timeout);
|
|
26202
|
+
}
|
|
26203
|
+
}
|
|
26204
|
+
function isGlobalInstall(bundleDir, env = process.env) {
|
|
26205
|
+
if (env.npm_execpath) return false;
|
|
26206
|
+
const segments = bundleDir.split(/[\\/]/u);
|
|
26207
|
+
return segments.includes("node_modules") && !segments.includes("_npx");
|
|
26208
|
+
}
|
|
26209
|
+
var GLOBAL_INSTALL_ENV = "FRIZZ_REGISTRY_GLOBAL_INSTALL";
|
|
26210
|
+
function keepUpdateHint(packageName, version) {
|
|
26211
|
+
return `this session only \u2014 run npm i -g ${packageName}@${version} to keep it`;
|
|
26212
|
+
}
|
|
26213
|
+
var NPM_VIEW_TIMEOUT_MS = 3e4;
|
|
26214
|
+
var NPM_EXEC_TIMEOUT_MS = 10 * 6e4;
|
|
26215
|
+
var NPM_KILL_SIGNAL = "SIGTERM";
|
|
26216
|
+
function formatTimeout(ms) {
|
|
26217
|
+
return ms >= 6e4 ? `${Math.ceil(ms / 6e4)}m` : `${Math.ceil(ms / 1e3)}s`;
|
|
26218
|
+
}
|
|
26219
|
+
function createNpmRegistryReleaseAdapter(options2 = {}) {
|
|
26220
|
+
const viewTimeoutMs = options2.viewTimeoutMs ?? NPM_VIEW_TIMEOUT_MS;
|
|
26221
|
+
const execTimeoutMs = options2.execTimeoutMs ?? NPM_EXEC_TIMEOUT_MS;
|
|
26222
|
+
const npmInvocation = options2.npm ?? (() => resolveNpmInvocation());
|
|
26223
|
+
return {
|
|
26224
|
+
latestVersion(packageName) {
|
|
26225
|
+
return new Promise((resolveVersion, reject) => {
|
|
26226
|
+
let npm;
|
|
26227
|
+
try {
|
|
26228
|
+
npm = npmInvocation();
|
|
26229
|
+
} catch (error) {
|
|
26230
|
+
return reject(error);
|
|
26231
|
+
}
|
|
26232
|
+
execFile4(
|
|
26233
|
+
npm.command,
|
|
26234
|
+
[...npm.prefixArgs, "view", `${packageName}@latest`, "version", "--json"],
|
|
26235
|
+
{ encoding: "utf8", windowsHide: true, timeout: viewTimeoutMs, killSignal: NPM_KILL_SIGNAL },
|
|
26236
|
+
(error, stdout) => {
|
|
26237
|
+
if (error) {
|
|
26238
|
+
const why = error.killed && error.signal === NPM_KILL_SIGNAL ? `npm view did not answer within ${formatTimeout(viewTimeoutMs)}` : error.message;
|
|
26239
|
+
return reject(new Error(`could not check npm for ${packageName}: ${why}`));
|
|
26240
|
+
}
|
|
26241
|
+
try {
|
|
26242
|
+
const parsed = JSON.parse(stdout);
|
|
26243
|
+
resolveVersion(typeof parsed === "string" ? parsed : String(parsed));
|
|
26244
|
+
} catch {
|
|
26245
|
+
resolveVersion(stdout.trim().replaceAll('"', ""));
|
|
26246
|
+
}
|
|
26247
|
+
}
|
|
26248
|
+
);
|
|
25946
26249
|
});
|
|
25947
|
-
|
|
26250
|
+
},
|
|
26251
|
+
npmExec({ packageSpec, bin, args: args2, cwd, env }) {
|
|
26252
|
+
return new Promise((settle) => {
|
|
26253
|
+
let npm;
|
|
26254
|
+
try {
|
|
26255
|
+
npm = npmInvocation();
|
|
26256
|
+
} catch (error) {
|
|
26257
|
+
return settle({ code: null, signal: null, stdout: "", stderr: error instanceof Error ? error.message : String(error) });
|
|
26258
|
+
}
|
|
26259
|
+
const started = Date.now();
|
|
26260
|
+
const child = spawn3(npm.command, [...npm.prefixArgs, "exec", "--yes", `--package=${packageSpec}`, "--", bin, ...args2], {
|
|
26261
|
+
cwd,
|
|
26262
|
+
env,
|
|
26263
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
26264
|
+
windowsHide: true,
|
|
26265
|
+
timeout: execTimeoutMs,
|
|
26266
|
+
killSignal: NPM_KILL_SIGNAL
|
|
26267
|
+
});
|
|
26268
|
+
let stdout = "";
|
|
26269
|
+
let stderr = "";
|
|
26270
|
+
child.stdout.setEncoding("utf8").on("data", (chunk) => {
|
|
26271
|
+
stdout += chunk;
|
|
26272
|
+
});
|
|
26273
|
+
child.stderr.setEncoding("utf8").on("data", (chunk) => {
|
|
26274
|
+
stderr += chunk;
|
|
26275
|
+
});
|
|
26276
|
+
child.once("error", (error) => settle({ code: null, signal: null, stdout, stderr: `${stderr}
|
|
25948
26277
|
${error.message}` }));
|
|
25949
|
-
|
|
25950
|
-
|
|
25951
|
-
|
|
25952
|
-
|
|
25953
|
-
|
|
25954
|
-
|
|
25955
|
-
}
|
|
26278
|
+
child.once("close", (code, signal) => {
|
|
26279
|
+
const timedOut = signal === NPM_KILL_SIGNAL && Date.now() - started >= execTimeoutMs;
|
|
26280
|
+
settle({
|
|
26281
|
+
code,
|
|
26282
|
+
signal,
|
|
26283
|
+
stdout,
|
|
26284
|
+
stderr: timedOut ? `${stderr}
|
|
26285
|
+
npm exec ${packageSpec} did not finish within ${formatTimeout(execTimeoutMs)} and was stopped` : stderr
|
|
26286
|
+
});
|
|
26287
|
+
});
|
|
26288
|
+
});
|
|
26289
|
+
},
|
|
26290
|
+
spawnDetached({ entry, args: args2, cwd, env }) {
|
|
26291
|
+
return spawn3(process.execPath, [entry, ...args2], { cwd, env, detached: true, stdio: "ignore", windowsHide: true });
|
|
26292
|
+
}
|
|
26293
|
+
};
|
|
26294
|
+
}
|
|
26295
|
+
var npmRegistryReleaseAdapter = createNpmRegistryReleaseAdapter();
|
|
25956
26296
|
|
|
25957
26297
|
// src/preflight.ts
|
|
25958
26298
|
import { spawnSync } from "node:child_process";
|
|
25959
26299
|
import { chmodSync as chmodSync2, statSync as statSync5 } from "node:fs";
|
|
25960
26300
|
import { createRequire } from "node:module";
|
|
25961
|
-
import { dirname as
|
|
26301
|
+
import { dirname as dirname13, join as join15 } from "node:path";
|
|
25962
26302
|
var SUPPORTED_NODE_LINES = [
|
|
25963
26303
|
{ major: 22, minor: 13 },
|
|
25964
26304
|
{ major: 23, minor: 4 }
|
|
@@ -26009,8 +26349,8 @@ function ensureNativeHelperPermissions(options2 = {}) {
|
|
|
26009
26349
|
const chmod = options2.chmod ?? ((path, mode) => chmodSync2(path, mode));
|
|
26010
26350
|
const resolvePty = options2.resolvePty ?? (() => createRequire(import.meta.url).resolve("node-pty/package.json"));
|
|
26011
26351
|
try {
|
|
26012
|
-
const helper =
|
|
26013
|
-
|
|
26352
|
+
const helper = join15(
|
|
26353
|
+
dirname13(resolvePty()),
|
|
26014
26354
|
"prebuilds",
|
|
26015
26355
|
`${platform}-${options2.arch ?? process.arch}`,
|
|
26016
26356
|
"spawn-helper"
|
|
@@ -26029,7 +26369,7 @@ init_project_identity();
|
|
|
26029
26369
|
var PACKAGE_NAME = process.env.FRIZZ_REGISTRY_PACKAGE ?? "frizz";
|
|
26030
26370
|
function resolvePackageVersion() {
|
|
26031
26371
|
try {
|
|
26032
|
-
const manifest = JSON.parse(readFileSync13(
|
|
26372
|
+
const manifest = JSON.parse(readFileSync13(join16(import.meta.dirname, "..", "package.json"), "utf8"));
|
|
26033
26373
|
if (typeof manifest.version === "string" && manifest.version.trim()) return manifest.version.trim();
|
|
26034
26374
|
} catch {
|
|
26035
26375
|
}
|
|
@@ -26042,7 +26382,7 @@ if (rawArgs.includes(PRODUCTION_PRINT_LAUNCHER_FLAG)) {
|
|
|
26042
26382
|
console.log(fileURLToPath2(import.meta.url));
|
|
26043
26383
|
process.exit(0);
|
|
26044
26384
|
}
|
|
26045
|
-
var args = rawArgs
|
|
26385
|
+
var args = reexec ? reexecArgv(rawArgs) : rawArgs;
|
|
26046
26386
|
var fail = (error) => {
|
|
26047
26387
|
console.error(`frizz: ${error instanceof Error ? error.message : error}`);
|
|
26048
26388
|
process.exit(1);
|
|
@@ -26074,6 +26414,8 @@ Options:
|
|
|
26074
26414
|
--link print a fresh single-use access link for the running board
|
|
26075
26415
|
--sessions list the devices signed in to the running board
|
|
26076
26416
|
--sign-out <id|all> sign one device out, or every one of them
|
|
26417
|
+
--status report the board running for this project: address, pid, version
|
|
26418
|
+
--stop stop the board running for this project (running agents keep going)
|
|
26077
26419
|
--debug stream the full event feed to the terminal instead of the compact readout
|
|
26078
26420
|
-h, --help show this help
|
|
26079
26421
|
|
|
@@ -26091,6 +26433,8 @@ var sandbox = options.sandbox ? prepareSandbox() : null;
|
|
|
26091
26433
|
if (sandbox) process.on("exit", () => cleanupSandbox(sandbox.home));
|
|
26092
26434
|
var remote = null;
|
|
26093
26435
|
var paneHost = null;
|
|
26436
|
+
var rearmPaneHost = null;
|
|
26437
|
+
var globalInstall = process.env[GLOBAL_INSTALL_ENV] === "1" || isGlobalInstall(import.meta.dirname);
|
|
26094
26438
|
var accessPane = null;
|
|
26095
26439
|
var activeAccessLink = null;
|
|
26096
26440
|
var launchIntent;
|
|
@@ -26117,6 +26461,34 @@ var workspace = (() => {
|
|
|
26117
26461
|
}
|
|
26118
26462
|
})();
|
|
26119
26463
|
process.chdir(workspace.root);
|
|
26464
|
+
if (options.stop) {
|
|
26465
|
+
try {
|
|
26466
|
+
const control = await resolveLaunchControlTarget({ stateDir: workspace.stateDir, target: workspaceLaunchTarget(workspace) });
|
|
26467
|
+
const where = control.host ? workspace.root : `${workspace.root} (the board was launched from ${control.target.projectDir})`;
|
|
26468
|
+
const result = await stopProjectLaunch({ stateDir: control.stateDir, target: control.target });
|
|
26469
|
+
console.log(
|
|
26470
|
+
result.kind !== "stopped" ? `Frizz is not running for ${where}` : result.stale ? `Frizz was not running for ${where}; cleared the record a dead board left behind` : `stopped Frizz for ${where}; running agents keep going \u2014 they are detached daemons`
|
|
26471
|
+
);
|
|
26472
|
+
process.exit(0);
|
|
26473
|
+
} catch (error) {
|
|
26474
|
+
fail(error);
|
|
26475
|
+
}
|
|
26476
|
+
}
|
|
26477
|
+
if (options.status) {
|
|
26478
|
+
const control = await resolveLaunchControlTarget({ stateDir: workspace.stateDir, target: workspaceLaunchTarget(workspace) });
|
|
26479
|
+
const running = await runningFrizzStatus({ stateDir: control.stateDir, target: control.target });
|
|
26480
|
+
if (!running) {
|
|
26481
|
+
console.log(`Frizz is not running for ${workspace.root}`);
|
|
26482
|
+
process.exit(1);
|
|
26483
|
+
}
|
|
26484
|
+
console.log(`running: http://127.0.0.1:${running.port}`);
|
|
26485
|
+
console.log(`workspace: ${workspace.root}`);
|
|
26486
|
+
if (!control.host) console.log(`launched from: ${control.target.projectDir} (one server serves every project)`);
|
|
26487
|
+
console.log(`supervisor pid: ${running.pid}`);
|
|
26488
|
+
console.log(`version: ${running.version ?? "unknown"}`);
|
|
26489
|
+
if (running.state && running.state !== "ready") console.log(`state: ${running.state}${running.message ? ` \u2014 ${running.message}` : ""}`);
|
|
26490
|
+
process.exit(0);
|
|
26491
|
+
}
|
|
26120
26492
|
if (options.sessions || options.signOut !== void 0) {
|
|
26121
26493
|
const running = liveWorkspaceOwner(workspace.stateDir, workspaceLaunchTarget(workspace));
|
|
26122
26494
|
if (!running?.port) {
|
|
@@ -26207,7 +26579,7 @@ async function openOrPrint(port, reused, path = "") {
|
|
|
26207
26579
|
readout?.begin("browser", options.appMode ? "requesting app window" : "requesting default browser");
|
|
26208
26580
|
try {
|
|
26209
26581
|
if (options.appMode) {
|
|
26210
|
-
await launchApp(url, { dataPath:
|
|
26582
|
+
await launchApp(url, { dataPath: join16(workspace.stateDir, "browser-profile") });
|
|
26211
26583
|
browser = reused ? "focused the Frizz app window" : "opened the Frizz app window";
|
|
26212
26584
|
} else {
|
|
26213
26585
|
await launchBrowserTab(url);
|
|
@@ -26265,13 +26637,13 @@ async function runSupervisor(port, token) {
|
|
|
26265
26637
|
target,
|
|
26266
26638
|
owner.token
|
|
26267
26639
|
);
|
|
26268
|
-
const webDist =
|
|
26269
|
-
const runtimeDir =
|
|
26270
|
-
const scriptsDir =
|
|
26271
|
-
const workerPluginDir =
|
|
26640
|
+
const webDist = join16(import.meta.dirname, "..", "web-dist");
|
|
26641
|
+
const runtimeDir = join16(import.meta.dirname, "..", "runtime");
|
|
26642
|
+
const scriptsDir = join16(runtimeDir, "board");
|
|
26643
|
+
const workerPluginDir = join16(runtimeDir, "cc-worker");
|
|
26272
26644
|
const childEntry = fileURLToPath2(new URL("./dev-child.js", import.meta.url));
|
|
26273
26645
|
let plannedSuccessor;
|
|
26274
|
-
let updateAvailable =
|
|
26646
|
+
let updateAvailable = false;
|
|
26275
26647
|
let updateVersion;
|
|
26276
26648
|
const refreshUpdateAvailable = async () => {
|
|
26277
26649
|
try {
|
|
@@ -26325,22 +26697,56 @@ async function runSupervisor(port, token) {
|
|
|
26325
26697
|
return { state: "failed", message: error instanceof Error ? error.message : String(error) };
|
|
26326
26698
|
}
|
|
26327
26699
|
},
|
|
26700
|
+
// The registry launcher promotes no pointer — the release sits in npm's own execution cache and
|
|
26701
|
+
// the running package is never touched — so there is nothing to roll back. Present and empty
|
|
26702
|
+
// rather than absent: the supervisor appends "rollback callback is unavailable" to every failed
|
|
26703
|
+
// handoff it cannot roll back, which for this launcher was noise on a message that already said
|
|
26704
|
+
// what went wrong (audit 2026-09-11, finding 4).
|
|
26705
|
+
rollbackUpdate: () => {
|
|
26706
|
+
},
|
|
26328
26707
|
durableReexec: async () => {
|
|
26329
26708
|
const successor = plannedSuccessor;
|
|
26330
26709
|
if (!successor) throw new Error("no update was prepared");
|
|
26331
26710
|
const { plan } = successor;
|
|
26332
|
-
const successorEnv = {
|
|
26333
|
-
|
|
26711
|
+
const successorEnv = {
|
|
26712
|
+
...env,
|
|
26713
|
+
FRIZZ_REGISTRY_PACKAGE: plan.packageName,
|
|
26714
|
+
FRIZZ_REGISTRY_VERSION: plan.latestVersion,
|
|
26715
|
+
...globalInstall ? { [GLOBAL_INSTALL_ENV]: "1" } : {}
|
|
26716
|
+
};
|
|
26717
|
+
if (canReexecInPlace()) {
|
|
26334
26718
|
activityReadout?.notice("progress", "Updating", `reloading this launcher in place on Frizz ${plan.latestVersion}`);
|
|
26335
26719
|
paneHost?.dispose();
|
|
26336
26720
|
remote?.stop();
|
|
26337
|
-
|
|
26721
|
+
try {
|
|
26722
|
+
reexecIntoRegistrySuccessor(successor, { port, env: successorEnv });
|
|
26723
|
+
} catch (error) {
|
|
26724
|
+
rearmPaneHost?.();
|
|
26725
|
+
try {
|
|
26726
|
+
await remote?.serveSaved();
|
|
26727
|
+
} catch (remoteError) {
|
|
26728
|
+
const message = remoteError instanceof Error ? remoteError.message : String(remoteError);
|
|
26729
|
+
logger.error("remote", `could not re-arm the saved remote setup after a failed update: ${message}`);
|
|
26730
|
+
}
|
|
26731
|
+
throw error;
|
|
26732
|
+
}
|
|
26338
26733
|
}
|
|
26339
|
-
handoffToRegistrySuccessor(successor, { port, cwd: workspace.root, env: successorEnv }, npmRegistryReleaseAdapter);
|
|
26340
|
-
|
|
26341
|
-
|
|
26342
|
-
|
|
26343
|
-
|
|
26734
|
+
const child = handoffToRegistrySuccessor(successor, { port, cwd: workspace.root, env: successorEnv }, npmRegistryReleaseAdapter);
|
|
26735
|
+
activityReadout?.notice("progress", "Updating", `starting Frizz ${plan.latestVersion} in the background and waiting for it to answer on port ${port}`);
|
|
26736
|
+
await awaitRegistrySuccessor(
|
|
26737
|
+
child,
|
|
26738
|
+
{ version: plan.latestVersion, port, logFile: successorEnv.FRIZZ_LOG_FILE },
|
|
26739
|
+
{ status: () => readLauncherStatus(port) }
|
|
26740
|
+
);
|
|
26741
|
+
paneHost?.dispose();
|
|
26742
|
+
remote?.stop();
|
|
26743
|
+
activityReadout?.notice("done", "Updated", `Frizz ${plan.latestVersion} is serving on port ${port}`);
|
|
26744
|
+
activityReadout?.note(
|
|
26745
|
+
`
|
|
26746
|
+
Frizz ${plan.latestVersion} now runs in the background \u2014 ctrl-c here no longer reaches it. Stop it with ${PACKAGE_NAME} --stop.${globalInstall ? `
|
|
26747
|
+
Update: ${keepUpdateHint(PACKAGE_NAME, plan.latestVersion)}.` : ""}
|
|
26748
|
+
`
|
|
26749
|
+
);
|
|
26344
26750
|
process.exit(0);
|
|
26345
26751
|
}
|
|
26346
26752
|
});
|
|
@@ -26364,7 +26770,12 @@ async function runSupervisor(port, token) {
|
|
|
26364
26770
|
onChanged: (config) => logger.info("remote", config ? `reached at https://${config.hostname}` : "loopback only"),
|
|
26365
26771
|
sandbox: sandbox !== null
|
|
26366
26772
|
});
|
|
26367
|
-
|
|
26773
|
+
const bindings = { l: accessPane, L: accessPane, r: remotePane, R: remotePane };
|
|
26774
|
+
const armPaneHost = () => {
|
|
26775
|
+
paneHost = installPaneHost({ bindings });
|
|
26776
|
+
};
|
|
26777
|
+
armPaneHost();
|
|
26778
|
+
rearmPaneHost = armPaneHost;
|
|
26368
26779
|
const stop = createSupervisorShutdownHandler({
|
|
26369
26780
|
close: () => supervisor.close(),
|
|
26370
26781
|
force: () => supervisor.forceStop(),
|
|
@@ -26398,7 +26809,13 @@ async function runSupervisor(port, token) {
|
|
|
26398
26809
|
process.on("SIGHUP", stop);
|
|
26399
26810
|
void supervisor.stopRequested.then(stop);
|
|
26400
26811
|
await supervisor.firstBoot;
|
|
26401
|
-
if (reexec)
|
|
26812
|
+
if (reexec) {
|
|
26813
|
+
activityReadout?.notice(
|
|
26814
|
+
"done",
|
|
26815
|
+
"Updated",
|
|
26816
|
+
`Frizz ${PACKAGE_VERSION} is serving on port ${port} \xB7 ctrl-c to stop${globalInstall ? ` \xB7 ${keepUpdateHint(PACKAGE_NAME, PACKAGE_VERSION)}` : ""}`
|
|
26817
|
+
);
|
|
26818
|
+
}
|
|
26402
26819
|
return await new Promise(() => {
|
|
26403
26820
|
});
|
|
26404
26821
|
}
|