frizz 0.12.12 → 0.13.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/dist/frizz.js +752 -350
- package/package.json +12 -12
- package/dist/claude-agent-broker.js +0 -35911
- package/dist/codex-app-server-daemon.js +0 -423
- package/dist/dev-child.js +0 -56194
- package/runtime/board/agent-bindings.mjs +0 -287
- package/runtime/board/agent-liveness.mjs +0 -367
- package/runtime/board/agent-status.mjs +0 -178
- package/runtime/board/config.mjs +0 -993
- package/runtime/board/decisions.mjs +0 -97
- package/runtime/board/index.mjs +0 -704
- package/runtime/board/notify-shared.mjs +0 -90
- package/runtime/board/notify.mjs +0 -81
- package/runtime/board/ownership.mjs +0 -120
- package/runtime/board/rest-detect.mjs +0 -213
- package/runtime/board/thread-excerpt.mjs +0 -162
- package/runtime/board/thread-update.mjs +0 -289
- package/runtime/cc-worker/.claude-plugin/plugin.json +0 -10
- package/runtime/cc-worker/DECISIONS.md +0 -1172
- package/runtime/cc-worker/LICENSE +0 -21
- package/runtime/cc-worker/agents/high.md +0 -7
- package/runtime/cc-worker/agents/low.md +0 -7
- package/runtime/cc-worker/agents/max.md +0 -7
- package/runtime/cc-worker/agents/medium.md +0 -7
- package/runtime/cc-worker/agents/xhigh.md +0 -7
- package/runtime/cc-worker/bin/frizz +0 -17
- package/runtime/cc-worker/bin/frizz-mcp.mjs +0 -1612
- package/runtime/cc-worker/bin/frizz-update +0 -18
- package/runtime/cc-worker/hooks/agent-bind.mjs +0 -40
- package/runtime/cc-worker/hooks/agent-dispatch.mjs +0 -121
- package/runtime/cc-worker/hooks/bash-background.d.mts +0 -6
- package/runtime/cc-worker/hooks/bash-background.mjs +0 -247
- package/runtime/cc-worker/hooks/deny-ask.mjs +0 -39
- package/runtime/cc-worker/hooks/deny-plan.mjs +0 -62
- package/runtime/cc-worker/hooks/hooks.json +0 -102
- package/runtime/cc-worker/hooks/perm-policy.mjs +0 -211
- package/runtime/cc-worker/hooks/scratchpad.mjs +0 -417
- package/runtime/cc-worker/hooks/session-seed.mjs +0 -107
- package/runtime/cc-worker/scripts/frizz/agent-bindings.mjs +0 -9
- package/runtime/cc-worker/scripts/frizz/config.mjs +0 -12
- package/runtime/cc-worker/skills/gh/SKILL.md +0 -141
- package/runtime/cc-worker/skills/gh/scripts/ci-watch.mjs +0 -60
- package/runtime/cc-worker/skills/gh/scripts/github-watch.mjs +0 -130
- package/runtime/cc-worker/skills/gh/scripts/review-watch.mjs +0 -54
- package/web-dist/apple-touch-icon.png +0 -0
- package/web-dist/assets/TerminalPane-CTuT1746.js +0 -7
- package/web-dist/assets/abnfDiagram-VRR7QNED-C9lXEgoU.js +0 -1
- package/web-dist/assets/arc-BSyeo0Gb.js +0 -1
- package/web-dist/assets/architecture-TIHT7OUA-cPNCo9oK.js +0 -1
- package/web-dist/assets/architectureDiagram-ZJ3FMSHR-BmJyQxby.js +0 -36
- package/web-dist/assets/array-BifhSqXX.js +0 -1
- package/web-dist/assets/blockDiagram-677ZJIJ3-DYTepy7i.js +0 -132
- package/web-dist/assets/c4Diagram-LMCZKHZV-CNaJlw58.js +0 -10
- package/web-dist/assets/channel-D5dgm6BA.js +0 -1
- package/web-dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +0 -1
- package/web-dist/assets/chunk-32BRIVSS-uAMm81q2.js +0 -1
- package/web-dist/assets/chunk-52WLFC77-DjszZCE7.js +0 -10
- package/web-dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +0 -15
- package/web-dist/assets/chunk-7BUUIJ7U-Bb538aSH.js +0 -1
- package/web-dist/assets/chunk-C7G6YPKG-BuHoup14.js +0 -1
- package/web-dist/assets/chunk-EX3LRPZG-Bg9UEQvR.js +0 -231
- package/web-dist/assets/chunk-FWX5IMBZ-CHnQfTLw.js +0 -2
- package/web-dist/assets/chunk-HOUHSVGY-ByjeQLq2.js +0 -1
- package/web-dist/assets/chunk-ICXQ74PX-DeM9b_DJ.js +0 -2
- package/web-dist/assets/chunk-JWPE2WC7-DVXcaiue.js +0 -1
- package/web-dist/assets/chunk-KEIR6QF5-BfrZ3jm6.js +0 -161
- package/web-dist/assets/chunk-MOJQB5TN-DxLERy2q.js +0 -88
- package/web-dist/assets/chunk-OGEWGWER-sBPjsAxh.js +0 -1
- package/web-dist/assets/chunk-PUDLZKDR-CarEdLd9.js +0 -156
- package/web-dist/assets/chunk-Q4XR5HBZ-BfXpvkfr.js +0 -70
- package/web-dist/assets/chunk-RYQCIY6F-Cu_KplZW.js +0 -1
- package/web-dist/assets/chunk-V7JOEXUC-B3FaJqr_.js +0 -206
- package/web-dist/assets/chunk-VAUOI2AC-DHsDLPEL.js +0 -1
- package/web-dist/assets/chunk-VR4S4FIN-ObNNjO-z.js +0 -1
- package/web-dist/assets/chunk-WYO6CB5R-JZxgPfBf.js +0 -127
- package/web-dist/assets/chunk-XXDRQBXY-DYlTP5J-.js +0 -1
- package/web-dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +0 -1
- package/web-dist/assets/chunk-ZGVPDNZ5-rLSAye5U.js +0 -62
- package/web-dist/assets/chunk-ZIRB5QZD-C6fEPe3t.js +0 -32
- package/web-dist/assets/classDiagram-OUVF2IWQ-Bj_Hjv7y.js +0 -1
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-Bj_Hjv7y.js +0 -1
- package/web-dist/assets/cose-bilkent-JH36ORCC-BUIsLrGc.js +0 -1
- package/web-dist/assets/cynefin-VYW2F7L2-B0-Xy-xW.js +0 -1
- package/web-dist/assets/cynefinDiagram-TSTJHNR4-Dd3QCTMp.js +0 -62
- package/web-dist/assets/cytoscape.esm-B3I8pqwA.js +0 -321
- package/web-dist/assets/dagre-CXRCoUWR.js +0 -1
- package/web-dist/assets/dagre-VKFMJZFB-c_sDjRhh.js +0 -4
- package/web-dist/assets/defaultLocale-C8Fc0cco.js +0 -1
- package/web-dist/assets/diagram-FQU43EPY-DlrOA7Q2.js +0 -3
- package/web-dist/assets/diagram-G47NLZAW-DNwGdtwN.js +0 -24
- package/web-dist/assets/diagram-NH7WQ7WH-CPNunIAd.js +0 -24
- package/web-dist/assets/diagram-OA4YK3LP-BZVJWnon.js +0 -30
- package/web-dist/assets/diagram-WEI45ONY-B8UEevkd.js +0 -41
- package/web-dist/assets/dist-DoH_9pyS.js +0 -1
- package/web-dist/assets/ebnfDiagram-CCIWWBDH-BGCxDQf1.js +0 -1
- package/web-dist/assets/erDiagram-Q63AITRT-CKnUuelS.js +0 -85
- package/web-dist/assets/eventmodeling-45OFAUF4-DvqeSNur.js +0 -1
- package/web-dist/assets/flowDiagram-23GEKE2U-DT_LFo10.js +0 -1
- package/web-dist/assets/ganttDiagram-NO4QXBWP-2-k1ZZhN.js +0 -292
- package/web-dist/assets/gitGraph-TEB2WS4Q-Ci3lt5M_.js +0 -1
- package/web-dist/assets/gitGraphDiagram-IHSO6WYX-B_AQwuvk.js +0 -106
- package/web-dist/assets/graphlib-B8gBHxth.js +0 -1
- package/web-dist/assets/index-CSVjp00Q.css +0 -1
- package/web-dist/assets/index-D5VGTEZg.js +0 -319
- package/web-dist/assets/info-DKCQHKI2-m3mT757b.js +0 -1
- package/web-dist/assets/infoDiagram-FWYZ7A6U-CQw6f3Hj.js +0 -2
- package/web-dist/assets/init-D6jRqBbL.js +0 -1
- package/web-dist/assets/ishikawaDiagram-FXEZZL3T-C-7JgXGg.js +0 -70
- package/web-dist/assets/journeyDiagram-5HDEW3XC-DhPxGm-x.js +0 -139
- package/web-dist/assets/kanban-definition-HUTT4EX6-pYAdpAN-.js +0 -89
- package/web-dist/assets/katex-CddkPoXu.js +0 -257
- package/web-dist/assets/line-DtHJLrdk.js +0 -1
- package/web-dist/assets/linear-z2V0wJk9.js +0 -1
- package/web-dist/assets/map-DsCK-0Cs.js +0 -1
- package/web-dist/assets/mermaid-parser.core-CiDWeD1W.js +0 -7
- package/web-dist/assets/mermaid.core-BIRnljFs.js +0 -11
- package/web-dist/assets/mindmap-definition-LN4V7U3C-AwCgXi_v.js +0 -96
- package/web-dist/assets/ordinal-hYBb2elL.js +0 -1
- package/web-dist/assets/packet-7NZHBO7P-CnOMRKg1.js +0 -1
- package/web-dist/assets/path-BWPyau1x.js +0 -1
- package/web-dist/assets/pegDiagram-2B236MQR-KwEiKY6p.js +0 -1
- package/web-dist/assets/pie-RZYD4A2V-BXVw5n_F.js +0 -1
- package/web-dist/assets/pieDiagram-ENE6RG2P-BKeGzq7n.js +0 -39
- package/web-dist/assets/quadrantDiagram-ABIIQ3AL-_B_KnoiC.js +0 -7
- package/web-dist/assets/radar-I7S5WNFK-BDV-2CJh.js +0 -1
- package/web-dist/assets/railroad-3IZDKUUU-CJLCawbl.js +0 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-BLgEAPud.js +0 -1
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-Czt3Iqq1.js +0 -1
- package/web-dist/assets/railroad-peg-LSFZ7HO6-HPyLt5Zu.js +0 -1
- package/web-dist/assets/railroadDiagram-RFXS5EU6-BVV6ZmA7.js +0 -1
- package/web-dist/assets/requirementDiagram-TGXJPOKE-D3JoXNiN.js +0 -84
- package/web-dist/assets/rolldown-runtime-Bh1tDfsg.js +0 -1
- package/web-dist/assets/rough.esm-CSKSodPl.js +0 -1
- package/web-dist/assets/sankeyDiagram-HTMAVEWB-D7r0TcuX.js +0 -40
- package/web-dist/assets/sequenceDiagram-DBY2YBRQ-B35koHCj.js +0 -162
- package/web-dist/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +0 -1
- package/web-dist/assets/src-C4XfhTaE.js +0 -1
- package/web-dist/assets/stateDiagram-2N3HPSRC-DrFIFrPb.js +0 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-D57MsDPe.js +0 -1
- package/web-dist/assets/swimlanes-5IMT3BWC-D14gjDvr.js +0 -2
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-DC2nRhL8.js +0 -8
- package/web-dist/assets/timeline-definition-FHXFAJF6-DYuBi6LS.js +0 -120
- package/web-dist/assets/treeView-QDETBFTQ-DWCgtuaU.js +0 -1
- package/web-dist/assets/treemap-6X3UGDF4-QuJpQ-gt.js +0 -1
- package/web-dist/assets/vennDiagram-L72KCM5P-BgtM82oJ.js +0 -34
- package/web-dist/assets/wardley-OPB4EBWU-CWh_aioC.js +0 -1
- package/web-dist/assets/wardleyDiagram-EHGQE667-BNWSkBva.js +0 -78
- package/web-dist/assets/xychartDiagram-FW5EYKEG-Bc6i6hg5.js +0 -7
- package/web-dist/favicon-16.png +0 -0
- package/web-dist/favicon-32.png +0 -0
- package/web-dist/favicon.svg +0 -34
- package/web-dist/icon-192.png +0 -0
- package/web-dist/icon-512.png +0 -0
- package/web-dist/icon-maskable-512.png +0 -0
- package/web-dist/index.html +0 -44
- package/web-dist/manifest.webmanifest +0 -16
package/dist/frizz.js
CHANGED
|
@@ -4175,10 +4175,10 @@ var require_resolve_block_map = __commonJS({
|
|
|
4175
4175
|
let offset = bm.offset;
|
|
4176
4176
|
let commentEnd = null;
|
|
4177
4177
|
for (const collItem of bm.items) {
|
|
4178
|
-
const { start, key, sep:
|
|
4178
|
+
const { start, key, sep: sep5, value } = collItem;
|
|
4179
4179
|
const keyProps = resolveProps.resolveProps(start, {
|
|
4180
4180
|
indicator: "explicit-key-ind",
|
|
4181
|
-
next: key ??
|
|
4181
|
+
next: key ?? sep5?.[0],
|
|
4182
4182
|
offset,
|
|
4183
4183
|
onError,
|
|
4184
4184
|
parentIndent: bm.indent,
|
|
@@ -4192,7 +4192,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
4192
4192
|
else if ("indent" in key && key.indent !== bm.indent)
|
|
4193
4193
|
onError(offset, "BAD_INDENT", startColMsg);
|
|
4194
4194
|
}
|
|
4195
|
-
if (!keyProps.anchor && !keyProps.tag && !
|
|
4195
|
+
if (!keyProps.anchor && !keyProps.tag && !sep5) {
|
|
4196
4196
|
commentEnd = keyProps.end;
|
|
4197
4197
|
if (keyProps.comment) {
|
|
4198
4198
|
if (map.comment)
|
|
@@ -4216,7 +4216,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
4216
4216
|
ctx.atKey = false;
|
|
4217
4217
|
if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
|
|
4218
4218
|
onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
|
|
4219
|
-
const valueProps = resolveProps.resolveProps(
|
|
4219
|
+
const valueProps = resolveProps.resolveProps(sep5 ?? [], {
|
|
4220
4220
|
indicator: "map-value-ind",
|
|
4221
4221
|
next: value,
|
|
4222
4222
|
offset: keyNode.range[2],
|
|
@@ -4232,7 +4232,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
4232
4232
|
if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
|
|
4233
4233
|
onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
|
|
4234
4234
|
}
|
|
4235
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset,
|
|
4235
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep5, null, valueProps, onError);
|
|
4236
4236
|
if (ctx.schema.compat)
|
|
4237
4237
|
utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
|
|
4238
4238
|
offset = valueNode.range[2];
|
|
@@ -4323,7 +4323,7 @@ var require_resolve_end = __commonJS({
|
|
|
4323
4323
|
let comment = "";
|
|
4324
4324
|
if (end) {
|
|
4325
4325
|
let hasSpace = false;
|
|
4326
|
-
let
|
|
4326
|
+
let sep5 = "";
|
|
4327
4327
|
for (const token of end) {
|
|
4328
4328
|
const { source, type } = token;
|
|
4329
4329
|
switch (type) {
|
|
@@ -4337,13 +4337,13 @@ var require_resolve_end = __commonJS({
|
|
|
4337
4337
|
if (!comment)
|
|
4338
4338
|
comment = cb;
|
|
4339
4339
|
else
|
|
4340
|
-
comment +=
|
|
4341
|
-
|
|
4340
|
+
comment += sep5 + cb;
|
|
4341
|
+
sep5 = "";
|
|
4342
4342
|
break;
|
|
4343
4343
|
}
|
|
4344
4344
|
case "newline":
|
|
4345
4345
|
if (comment)
|
|
4346
|
-
|
|
4346
|
+
sep5 += source;
|
|
4347
4347
|
hasSpace = true;
|
|
4348
4348
|
break;
|
|
4349
4349
|
default:
|
|
@@ -4386,18 +4386,18 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4386
4386
|
let offset = fc.offset + fc.start.source.length;
|
|
4387
4387
|
for (let i = 0; i < fc.items.length; ++i) {
|
|
4388
4388
|
const collItem = fc.items[i];
|
|
4389
|
-
const { start, key, sep:
|
|
4389
|
+
const { start, key, sep: sep5, value } = collItem;
|
|
4390
4390
|
const props = resolveProps.resolveProps(start, {
|
|
4391
4391
|
flow: fcName,
|
|
4392
4392
|
indicator: "explicit-key-ind",
|
|
4393
|
-
next: key ??
|
|
4393
|
+
next: key ?? sep5?.[0],
|
|
4394
4394
|
offset,
|
|
4395
4395
|
onError,
|
|
4396
4396
|
parentIndent: fc.indent,
|
|
4397
4397
|
startOnNewline: false
|
|
4398
4398
|
});
|
|
4399
4399
|
if (!props.found) {
|
|
4400
|
-
if (!props.anchor && !props.tag && !
|
|
4400
|
+
if (!props.anchor && !props.tag && !sep5 && !value) {
|
|
4401
4401
|
if (i === 0 && props.comma)
|
|
4402
4402
|
onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
|
|
4403
4403
|
else if (i < fc.items.length - 1)
|
|
@@ -4451,8 +4451,8 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4451
4451
|
}
|
|
4452
4452
|
}
|
|
4453
4453
|
}
|
|
4454
|
-
if (!isMap && !
|
|
4455
|
-
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end,
|
|
4454
|
+
if (!isMap && !sep5 && !props.found) {
|
|
4455
|
+
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep5, null, props, onError);
|
|
4456
4456
|
coll.items.push(valueNode);
|
|
4457
4457
|
offset = valueNode.range[2];
|
|
4458
4458
|
if (isBlock(value))
|
|
@@ -4464,7 +4464,7 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4464
4464
|
if (isBlock(key))
|
|
4465
4465
|
onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
4466
4466
|
ctx.atKey = false;
|
|
4467
|
-
const valueProps = resolveProps.resolveProps(
|
|
4467
|
+
const valueProps = resolveProps.resolveProps(sep5 ?? [], {
|
|
4468
4468
|
flow: fcName,
|
|
4469
4469
|
indicator: "map-value-ind",
|
|
4470
4470
|
next: value,
|
|
@@ -4475,8 +4475,8 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4475
4475
|
});
|
|
4476
4476
|
if (valueProps.found) {
|
|
4477
4477
|
if (!isMap && !props.found && ctx.options.strict) {
|
|
4478
|
-
if (
|
|
4479
|
-
for (const st of
|
|
4478
|
+
if (sep5)
|
|
4479
|
+
for (const st of sep5) {
|
|
4480
4480
|
if (st === valueProps.found)
|
|
4481
4481
|
break;
|
|
4482
4482
|
if (st.type === "newline") {
|
|
@@ -4493,7 +4493,7 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
4493
4493
|
else
|
|
4494
4494
|
onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
|
|
4495
4495
|
}
|
|
4496
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end,
|
|
4496
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep5, null, valueProps, onError) : null;
|
|
4497
4497
|
if (valueNode) {
|
|
4498
4498
|
if (isBlock(value))
|
|
4499
4499
|
onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
@@ -4673,7 +4673,7 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
4673
4673
|
chompStart = i + 1;
|
|
4674
4674
|
}
|
|
4675
4675
|
let value = "";
|
|
4676
|
-
let
|
|
4676
|
+
let sep5 = "";
|
|
4677
4677
|
let prevMoreIndented = false;
|
|
4678
4678
|
for (let i = 0; i < contentStart; ++i)
|
|
4679
4679
|
value += lines[i][0].slice(trimIndent) + "\n";
|
|
@@ -4690,24 +4690,24 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
4690
4690
|
indent = "";
|
|
4691
4691
|
}
|
|
4692
4692
|
if (type === Scalar.Scalar.BLOCK_LITERAL) {
|
|
4693
|
-
value +=
|
|
4694
|
-
|
|
4693
|
+
value += sep5 + indent.slice(trimIndent) + content;
|
|
4694
|
+
sep5 = "\n";
|
|
4695
4695
|
} else if (indent.length > trimIndent || content[0] === " ") {
|
|
4696
|
-
if (
|
|
4697
|
-
|
|
4698
|
-
else if (!prevMoreIndented &&
|
|
4699
|
-
|
|
4700
|
-
value +=
|
|
4701
|
-
|
|
4696
|
+
if (sep5 === " ")
|
|
4697
|
+
sep5 = "\n";
|
|
4698
|
+
else if (!prevMoreIndented && sep5 === "\n")
|
|
4699
|
+
sep5 = "\n\n";
|
|
4700
|
+
value += sep5 + indent.slice(trimIndent) + content;
|
|
4701
|
+
sep5 = "\n";
|
|
4702
4702
|
prevMoreIndented = true;
|
|
4703
4703
|
} else if (content === "") {
|
|
4704
|
-
if (
|
|
4704
|
+
if (sep5 === "\n")
|
|
4705
4705
|
value += "\n";
|
|
4706
4706
|
else
|
|
4707
|
-
|
|
4707
|
+
sep5 = "\n";
|
|
4708
4708
|
} else {
|
|
4709
|
-
value +=
|
|
4710
|
-
|
|
4709
|
+
value += sep5 + content;
|
|
4710
|
+
sep5 = " ";
|
|
4711
4711
|
prevMoreIndented = false;
|
|
4712
4712
|
}
|
|
4713
4713
|
}
|
|
@@ -4889,25 +4889,25 @@ var require_resolve_flow_scalar = __commonJS({
|
|
|
4889
4889
|
if (!match)
|
|
4890
4890
|
return source;
|
|
4891
4891
|
let res = match[1];
|
|
4892
|
-
let
|
|
4892
|
+
let sep5 = " ";
|
|
4893
4893
|
let pos = first.lastIndex;
|
|
4894
4894
|
line.lastIndex = pos;
|
|
4895
4895
|
while (match = line.exec(source)) {
|
|
4896
4896
|
if (match[1] === "") {
|
|
4897
|
-
if (
|
|
4898
|
-
res +=
|
|
4897
|
+
if (sep5 === "\n")
|
|
4898
|
+
res += sep5;
|
|
4899
4899
|
else
|
|
4900
|
-
|
|
4900
|
+
sep5 = "\n";
|
|
4901
4901
|
} else {
|
|
4902
|
-
res +=
|
|
4903
|
-
|
|
4902
|
+
res += sep5 + match[1];
|
|
4903
|
+
sep5 = " ";
|
|
4904
4904
|
}
|
|
4905
4905
|
pos = line.lastIndex;
|
|
4906
4906
|
}
|
|
4907
4907
|
const last = /[ \t]*(.*)/sy;
|
|
4908
4908
|
last.lastIndex = pos;
|
|
4909
4909
|
match = last.exec(source);
|
|
4910
|
-
return res +
|
|
4910
|
+
return res + sep5 + (match?.[1] ?? "");
|
|
4911
4911
|
}
|
|
4912
4912
|
function doubleQuotedValue(source, onError) {
|
|
4913
4913
|
let res = "";
|
|
@@ -5717,14 +5717,14 @@ var require_cst_stringify = __commonJS({
|
|
|
5717
5717
|
}
|
|
5718
5718
|
}
|
|
5719
5719
|
}
|
|
5720
|
-
function stringifyItem({ start, key, sep:
|
|
5720
|
+
function stringifyItem({ start, key, sep: sep5, value }) {
|
|
5721
5721
|
let res = "";
|
|
5722
5722
|
for (const st of start)
|
|
5723
5723
|
res += st.source;
|
|
5724
5724
|
if (key)
|
|
5725
5725
|
res += stringifyToken(key);
|
|
5726
|
-
if (
|
|
5727
|
-
for (const st of
|
|
5726
|
+
if (sep5)
|
|
5727
|
+
for (const st of sep5)
|
|
5728
5728
|
res += st.source;
|
|
5729
5729
|
if (value)
|
|
5730
5730
|
res += stringifyToken(value);
|
|
@@ -6891,18 +6891,18 @@ var require_parser = __commonJS({
|
|
|
6891
6891
|
if (this.type === "map-value-ind") {
|
|
6892
6892
|
const prev = getPrevProps(this.peek(2));
|
|
6893
6893
|
const start = getFirstKeyStartProps(prev);
|
|
6894
|
-
let
|
|
6894
|
+
let sep5;
|
|
6895
6895
|
if (scalar.end) {
|
|
6896
|
-
|
|
6897
|
-
|
|
6896
|
+
sep5 = scalar.end;
|
|
6897
|
+
sep5.push(this.sourceToken);
|
|
6898
6898
|
delete scalar.end;
|
|
6899
6899
|
} else
|
|
6900
|
-
|
|
6900
|
+
sep5 = [this.sourceToken];
|
|
6901
6901
|
const map = {
|
|
6902
6902
|
type: "block-map",
|
|
6903
6903
|
offset: scalar.offset,
|
|
6904
6904
|
indent: scalar.indent,
|
|
6905
|
-
items: [{ start, key: scalar, sep:
|
|
6905
|
+
items: [{ start, key: scalar, sep: sep5 }]
|
|
6906
6906
|
};
|
|
6907
6907
|
this.onKeyLine = true;
|
|
6908
6908
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -7055,15 +7055,15 @@ var require_parser = __commonJS({
|
|
|
7055
7055
|
} else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
|
|
7056
7056
|
const start2 = getFirstKeyStartProps(it.start);
|
|
7057
7057
|
const key = it.key;
|
|
7058
|
-
const
|
|
7059
|
-
|
|
7058
|
+
const sep5 = it.sep;
|
|
7059
|
+
sep5.push(this.sourceToken);
|
|
7060
7060
|
delete it.key;
|
|
7061
7061
|
delete it.sep;
|
|
7062
7062
|
this.stack.push({
|
|
7063
7063
|
type: "block-map",
|
|
7064
7064
|
offset: this.offset,
|
|
7065
7065
|
indent: this.indent,
|
|
7066
|
-
items: [{ start: start2, key, sep:
|
|
7066
|
+
items: [{ start: start2, key, sep: sep5 }]
|
|
7067
7067
|
});
|
|
7068
7068
|
} else if (start.length > 0) {
|
|
7069
7069
|
it.sep = it.sep.concat(start, this.sourceToken);
|
|
@@ -7257,13 +7257,13 @@ var require_parser = __commonJS({
|
|
|
7257
7257
|
const prev = getPrevProps(parent);
|
|
7258
7258
|
const start = getFirstKeyStartProps(prev);
|
|
7259
7259
|
fixFlowSeqItems(fc);
|
|
7260
|
-
const
|
|
7261
|
-
|
|
7260
|
+
const sep5 = fc.end.splice(1, fc.end.length);
|
|
7261
|
+
sep5.push(this.sourceToken);
|
|
7262
7262
|
const map = {
|
|
7263
7263
|
type: "block-map",
|
|
7264
7264
|
offset: fc.offset,
|
|
7265
7265
|
indent: fc.indent,
|
|
7266
|
-
items: [{ start, key: fc, sep:
|
|
7266
|
+
items: [{ start, key: fc, sep: sep5 }]
|
|
7267
7267
|
};
|
|
7268
7268
|
this.onKeyLine = true;
|
|
7269
7269
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -16829,7 +16829,7 @@ var require_websocket = __commonJS({
|
|
|
16829
16829
|
var http = __require("http");
|
|
16830
16830
|
var net = __require("net");
|
|
16831
16831
|
var tls = __require("tls");
|
|
16832
|
-
var { randomBytes: randomBytes2, createHash:
|
|
16832
|
+
var { randomBytes: randomBytes2, createHash: createHash5 } = __require("crypto");
|
|
16833
16833
|
var { Duplex, Readable } = __require("stream");
|
|
16834
16834
|
var { URL: URL2 } = __require("url");
|
|
16835
16835
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -17497,7 +17497,7 @@ var require_websocket = __commonJS({
|
|
|
17497
17497
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
17498
17498
|
return;
|
|
17499
17499
|
}
|
|
17500
|
-
const digest =
|
|
17500
|
+
const digest = createHash5("sha1").update(key + GUID).digest("base64");
|
|
17501
17501
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
17502
17502
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
17503
17503
|
return;
|
|
@@ -17866,7 +17866,7 @@ var require_websocket_server = __commonJS({
|
|
|
17866
17866
|
var EventEmitter = __require("events");
|
|
17867
17867
|
var http = __require("http");
|
|
17868
17868
|
var { Duplex } = __require("stream");
|
|
17869
|
-
var { createHash:
|
|
17869
|
+
var { createHash: createHash5 } = __require("crypto");
|
|
17870
17870
|
var extension2 = require_extension();
|
|
17871
17871
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
17872
17872
|
var subprotocol2 = require_subprotocol();
|
|
@@ -18173,7 +18173,7 @@ var require_websocket_server = __commonJS({
|
|
|
18173
18173
|
);
|
|
18174
18174
|
}
|
|
18175
18175
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
18176
|
-
const digest =
|
|
18176
|
+
const digest = createHash5("sha1").update(key + GUID).digest("base64");
|
|
18177
18177
|
const headers = [
|
|
18178
18178
|
"HTTP/1.1 101 Switching Protocols",
|
|
18179
18179
|
"Upgrade: websocket",
|
|
@@ -18341,11 +18341,11 @@ function pruneRunLogs(dir, keep = RETAINED_RUNS, days = RETAINED_DAYS, now = Dat
|
|
|
18341
18341
|
}
|
|
18342
18342
|
}
|
|
18343
18343
|
}
|
|
18344
|
-
function formatDiskLine(
|
|
18345
|
-
const at = new Date(
|
|
18344
|
+
function formatDiskLine(record2) {
|
|
18345
|
+
const at = new Date(record2.at);
|
|
18346
18346
|
const pad = (value, width = 2) => String(value).padStart(width, "0");
|
|
18347
18347
|
const clock = `${pad(at.getHours())}:${pad(at.getMinutes())}:${pad(at.getSeconds())}.${pad(at.getMilliseconds(), 3)}`;
|
|
18348
|
-
return `${clock} ${
|
|
18348
|
+
return `${clock} ${record2.level.toUpperCase().padEnd(5)} ${record2.scope.padEnd(12)} ${record2.message}
|
|
18349
18349
|
`;
|
|
18350
18350
|
}
|
|
18351
18351
|
function openLogFile(path) {
|
|
@@ -18372,10 +18372,10 @@ function createLogger(options2 = {}) {
|
|
|
18372
18372
|
const listeners = /* @__PURE__ */ new Set();
|
|
18373
18373
|
const emit = (recordLevel, scope, message) => {
|
|
18374
18374
|
if (LEVEL_ORDER[recordLevel] < threshold) return;
|
|
18375
|
-
const
|
|
18375
|
+
const record2 = { at: now(), level: recordLevel, scope, message };
|
|
18376
18376
|
if (fd !== null) {
|
|
18377
18377
|
try {
|
|
18378
|
-
const line = formatDiskLine(
|
|
18378
|
+
const line = formatDiskLine(record2);
|
|
18379
18379
|
if (written + line.length > maxBytes) {
|
|
18380
18380
|
writeSync(fd, `--- log truncated at ${maxBytes} bytes ---
|
|
18381
18381
|
`);
|
|
@@ -18390,7 +18390,7 @@ function createLogger(options2 = {}) {
|
|
|
18390
18390
|
}
|
|
18391
18391
|
for (const listener of listeners) {
|
|
18392
18392
|
try {
|
|
18393
|
-
listener(
|
|
18393
|
+
listener(record2);
|
|
18394
18394
|
} catch {
|
|
18395
18395
|
}
|
|
18396
18396
|
}
|
|
@@ -18417,13 +18417,13 @@ function setAmbientLogger(logger2) {
|
|
|
18417
18417
|
ambient = logger2;
|
|
18418
18418
|
return logger2;
|
|
18419
18419
|
}
|
|
18420
|
-
function formatFeedLine(
|
|
18421
|
-
return formatDiskLine(
|
|
18420
|
+
function formatFeedLine(record2) {
|
|
18421
|
+
return formatDiskLine(record2).trimEnd();
|
|
18422
18422
|
}
|
|
18423
18423
|
function attachTerminalMirror(logger2, enabled = process.env.FRIZZ_DEBUG === "1") {
|
|
18424
18424
|
if (!enabled) return () => {
|
|
18425
18425
|
};
|
|
18426
|
-
return logger2.onRecord((
|
|
18426
|
+
return logger2.onRecord((record2) => process.stderr.write(`${formatFeedLine(record2)}
|
|
18427
18427
|
`));
|
|
18428
18428
|
}
|
|
18429
18429
|
function ambientLogger() {
|
|
@@ -19120,13 +19120,13 @@ function acquireMutationGuard(stateDir, timeoutMs = GUARD_TIMEOUT_MS, adapter =
|
|
|
19120
19120
|
let fd;
|
|
19121
19121
|
try {
|
|
19122
19122
|
fd = openSync3(path, "wx", 384);
|
|
19123
|
-
const
|
|
19123
|
+
const record2 = {
|
|
19124
19124
|
version: 1,
|
|
19125
19125
|
token,
|
|
19126
19126
|
at: new Date(adapter.now()).toISOString(),
|
|
19127
19127
|
...generation
|
|
19128
19128
|
};
|
|
19129
|
-
writeFileSync6(fd, `${JSON.stringify(
|
|
19129
|
+
writeFileSync6(fd, `${JSON.stringify(record2)}
|
|
19130
19130
|
`, "utf8");
|
|
19131
19131
|
fsyncSync2(fd);
|
|
19132
19132
|
closeSync2(fd);
|
|
@@ -19170,13 +19170,13 @@ function parseDelegates(value) {
|
|
|
19170
19170
|
const seen = /* @__PURE__ */ new Set();
|
|
19171
19171
|
for (const candidate of value) {
|
|
19172
19172
|
if (!candidate || typeof candidate !== "object") return null;
|
|
19173
|
-
const
|
|
19174
|
-
const generation = parseGeneration(
|
|
19175
|
-
if (!generation || !validDelegateRole(
|
|
19173
|
+
const record2 = candidate;
|
|
19174
|
+
const generation = parseGeneration(record2);
|
|
19175
|
+
if (!generation || !validDelegateRole(record2.role) || !validText(record2.registeredAt, 128)) return null;
|
|
19176
19176
|
const key = `${generation.pid}:${generation.processStart}`;
|
|
19177
19177
|
if (seen.has(key)) return null;
|
|
19178
19178
|
seen.add(key);
|
|
19179
|
-
delegates.push({ ...generation, role:
|
|
19179
|
+
delegates.push({ ...generation, role: record2.role, registeredAt: record2.registeredAt });
|
|
19180
19180
|
}
|
|
19181
19181
|
return delegates;
|
|
19182
19182
|
}
|
|
@@ -19210,11 +19210,11 @@ function projectLaunchOwnerPath(stateDir) {
|
|
|
19210
19210
|
function readProjectLaunchOwner(stateDir) {
|
|
19211
19211
|
return parseOwner(projectLaunchOwnerPath(stateDir));
|
|
19212
19212
|
}
|
|
19213
|
-
function sameTarget(
|
|
19214
|
-
return
|
|
19213
|
+
function sameTarget(record2, target2) {
|
|
19214
|
+
return record2.projectId === target2.projectId && record2.projectDir === target2.projectDir;
|
|
19215
19215
|
}
|
|
19216
|
-
function sameProjectIdentity(
|
|
19217
|
-
return
|
|
19216
|
+
function sameProjectIdentity(record2, target2) {
|
|
19217
|
+
return record2.projectId === target2.projectId;
|
|
19218
19218
|
}
|
|
19219
19219
|
function projectLaunchTokenProof(target2, token) {
|
|
19220
19220
|
if (!UUID_RE.test(token)) throw new Error("invalid Frizz project launch owner token");
|
|
@@ -19230,11 +19230,11 @@ function removeStatusesForToken(stateDir, token) {
|
|
|
19230
19230
|
}
|
|
19231
19231
|
}
|
|
19232
19232
|
}
|
|
19233
|
-
function writeNewOwner(path,
|
|
19233
|
+
function writeNewOwner(path, record2) {
|
|
19234
19234
|
let fd;
|
|
19235
19235
|
try {
|
|
19236
19236
|
fd = openSync3(path, "wx", 384);
|
|
19237
|
-
writeFileSync6(fd, `${JSON.stringify(
|
|
19237
|
+
writeFileSync6(fd, `${JSON.stringify(record2)}
|
|
19238
19238
|
`, "utf8");
|
|
19239
19239
|
fsyncSync2(fd);
|
|
19240
19240
|
closeSync2(fd);
|
|
@@ -19250,21 +19250,21 @@ function writeNewOwner(path, record) {
|
|
|
19250
19250
|
throw error;
|
|
19251
19251
|
}
|
|
19252
19252
|
}
|
|
19253
|
-
function makeLease(target2,
|
|
19253
|
+
function makeLease(target2, record2, adapter) {
|
|
19254
19254
|
let released = false;
|
|
19255
19255
|
return {
|
|
19256
19256
|
target: target2,
|
|
19257
|
-
token:
|
|
19258
|
-
pid:
|
|
19259
|
-
processStart:
|
|
19260
|
-
role:
|
|
19257
|
+
token: record2.token,
|
|
19258
|
+
pid: record2.pid,
|
|
19259
|
+
processStart: record2.processStart,
|
|
19260
|
+
role: record2.role,
|
|
19261
19261
|
release: () => {
|
|
19262
19262
|
if (released) return false;
|
|
19263
19263
|
const unlock = acquireMutationGuard(target2.stateDir, GUARD_TIMEOUT_MS, adapter);
|
|
19264
19264
|
try {
|
|
19265
19265
|
const path = projectLaunchOwnerPath(target2.stateDir);
|
|
19266
19266
|
const current = parseOwner(path);
|
|
19267
|
-
if (!current || !sameTarget(current, target2) || current.token !==
|
|
19267
|
+
if (!current || !sameTarget(current, target2) || current.token !== record2.token || current.pid !== record2.pid || current.processStart !== record2.processStart) {
|
|
19268
19268
|
released = true;
|
|
19269
19269
|
return false;
|
|
19270
19270
|
}
|
|
@@ -19299,15 +19299,15 @@ function newOwnerRecord(target2, role, adapter) {
|
|
|
19299
19299
|
}
|
|
19300
19300
|
function installNewOwner(target2, role, adapter) {
|
|
19301
19301
|
const path = projectLaunchOwnerPath(target2.stateDir);
|
|
19302
|
-
const
|
|
19302
|
+
const record2 = newOwnerRecord(target2, role, adapter);
|
|
19303
19303
|
try {
|
|
19304
|
-
writeNewOwner(path,
|
|
19304
|
+
writeNewOwner(path, record2);
|
|
19305
19305
|
} catch (error) {
|
|
19306
19306
|
if (errorCode3(error) === "EEXIST") return { kind: "contended", owner: parseOwner(path) };
|
|
19307
19307
|
throw error;
|
|
19308
19308
|
}
|
|
19309
19309
|
const committed = parseOwner(path);
|
|
19310
|
-
if (!committed || committed.token !==
|
|
19310
|
+
if (!committed || committed.token !== record2.token) return { kind: "contended", owner: committed };
|
|
19311
19311
|
return { kind: "acquired", lease: makeLease(target2, committed, adapter) };
|
|
19312
19312
|
}
|
|
19313
19313
|
function drainDelegates(delegates, options2) {
|
|
@@ -19828,12 +19828,19 @@ var init_project_registry = __esm({
|
|
|
19828
19828
|
}
|
|
19829
19829
|
});
|
|
19830
19830
|
|
|
19831
|
+
// packages/server/src/native-helper.ts
|
|
19832
|
+
var init_native_helper = __esm({
|
|
19833
|
+
"packages/server/src/native-helper.ts"() {
|
|
19834
|
+
"use strict";
|
|
19835
|
+
}
|
|
19836
|
+
});
|
|
19837
|
+
|
|
19831
19838
|
// src/production.ts
|
|
19832
19839
|
init_local_origin();
|
|
19833
|
-
import { readFileSync as
|
|
19840
|
+
import { readFileSync as readFileSync15 } from "node:fs";
|
|
19834
19841
|
import { homedir as homedir11 } from "node:os";
|
|
19835
19842
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19836
|
-
import { join as
|
|
19843
|
+
import { join as join17 } from "node:path";
|
|
19837
19844
|
|
|
19838
19845
|
// src/browser.ts
|
|
19839
19846
|
import { spawn, execFile } from "node:child_process";
|
|
@@ -19995,12 +20002,12 @@ function manifestIdFor(url) {
|
|
|
19995
20002
|
return url.endsWith("/") ? url : `${url}/`;
|
|
19996
20003
|
}
|
|
19997
20004
|
function execFileP(cmd, args2) {
|
|
19998
|
-
return new Promise((
|
|
20005
|
+
return new Promise((resolve7, reject) => {
|
|
19999
20006
|
execFile(
|
|
20000
20007
|
cmd,
|
|
20001
20008
|
args2,
|
|
20002
20009
|
{ encoding: "utf8", timeout: 1e4 },
|
|
20003
|
-
(err, stdout) => err ? reject(err) :
|
|
20010
|
+
(err, stdout) => err ? reject(err) : resolve7(stdout)
|
|
20004
20011
|
);
|
|
20005
20012
|
});
|
|
20006
20013
|
}
|
|
@@ -20079,9 +20086,9 @@ function openCdpSession(browserPath, dataPath) {
|
|
|
20079
20086
|
cmdPipe.on("error", failAll);
|
|
20080
20087
|
resPipe.on("error", failAll);
|
|
20081
20088
|
child.on("exit", () => failAll(new Error("chrome exited before the CDP handshake completed")));
|
|
20082
|
-
const call2 = (method, params = {}, timeoutMs = 2e4) => new Promise((
|
|
20089
|
+
const call2 = (method, params = {}, timeoutMs = 2e4) => new Promise((resolve7, reject) => {
|
|
20083
20090
|
const id = ++seq;
|
|
20084
|
-
pending.set(id, { resolve:
|
|
20091
|
+
pending.set(id, { resolve: resolve7, reject });
|
|
20085
20092
|
cmdPipe.write(JSON.stringify({ id, method, params }) + "\0");
|
|
20086
20093
|
setTimeout(() => {
|
|
20087
20094
|
if (pending.has(id)) {
|
|
@@ -20094,15 +20101,15 @@ function openCdpSession(browserPath, dataPath) {
|
|
|
20094
20101
|
await call2("Browser.close").catch(() => {
|
|
20095
20102
|
});
|
|
20096
20103
|
if (child.exitCode !== null || child.signalCode !== null) return;
|
|
20097
|
-
await new Promise((
|
|
20104
|
+
await new Promise((resolve7) => {
|
|
20098
20105
|
const t = setTimeout(() => {
|
|
20099
20106
|
child.kill();
|
|
20100
|
-
|
|
20107
|
+
resolve7();
|
|
20101
20108
|
}, 1e4);
|
|
20102
20109
|
t.unref();
|
|
20103
20110
|
child.once("exit", () => {
|
|
20104
20111
|
clearTimeout(t);
|
|
20105
|
-
|
|
20112
|
+
resolve7();
|
|
20106
20113
|
});
|
|
20107
20114
|
});
|
|
20108
20115
|
};
|
|
@@ -22619,6 +22626,7 @@ var RestartSupervisorProxy = class {
|
|
|
22619
22626
|
status() {
|
|
22620
22627
|
const delegated = this.options.status?.();
|
|
22621
22628
|
const updateVersion = this.options.updateVersion?.();
|
|
22629
|
+
const version = typeof this.options.version === "function" ? this.options.version() : this.options.version;
|
|
22622
22630
|
const owner = { state: this.state, ...this.message ? { message: this.message } : {} };
|
|
22623
22631
|
const reported = this.transition === "update" && delegated ? { ...delegated, ...delegated.state === "ready" ? { preparing: true } : {} } : this.restartInFlight !== null || this.state === "failed" ? owner : delegated ?? owner;
|
|
22624
22632
|
return {
|
|
@@ -22630,9 +22638,10 @@ var RestartSupervisorProxy = class {
|
|
|
22630
22638
|
// Sent ONLY when the launcher can actually answer it, so an older client — and frizz-dev, which
|
|
22631
22639
|
// has no notion of "already current" — keeps today's behaviour on its absence.
|
|
22632
22640
|
...this.options.updateAvailable ? { updateAvailable: this.options.updateAvailable() === true } : {},
|
|
22633
|
-
//
|
|
22634
|
-
// supervisors
|
|
22635
|
-
...
|
|
22641
|
+
// The active SERVER version changes on a child-only update. Its absence keeps frizz-dev and
|
|
22642
|
+
// old monolithic supervisors' status payload and versionless UI exactly as they were.
|
|
22643
|
+
...version ? { version } : {},
|
|
22644
|
+
...this.options.launcherVersion ? { launcherVersion: this.options.launcherVersion } : {},
|
|
22636
22645
|
...updateVersion ? { updateVersion } : {},
|
|
22637
22646
|
// Sent only when TRUE, so a published Frizz's payload is byte-identical to what it sends today
|
|
22638
22647
|
// and an older client is unaffected. Absent therefore means "not a development build".
|
|
@@ -23288,7 +23297,7 @@ function serveRelayRequest(frame, options2) {
|
|
|
23288
23297
|
const publicUrl = new URL(options2.publicOrigin);
|
|
23289
23298
|
let cancelled = false;
|
|
23290
23299
|
let abort;
|
|
23291
|
-
const done = new Promise((
|
|
23300
|
+
const done = new Promise((resolve7) => {
|
|
23292
23301
|
const send = (upFrame) => {
|
|
23293
23302
|
if (!cancelled) options2.send(upFrame);
|
|
23294
23303
|
};
|
|
@@ -23322,11 +23331,11 @@ function serveRelayRequest(frame, options2) {
|
|
|
23322
23331
|
});
|
|
23323
23332
|
res.on("end", () => {
|
|
23324
23333
|
send({ t: "res-end", id: frame.id });
|
|
23325
|
-
|
|
23334
|
+
resolve7();
|
|
23326
23335
|
});
|
|
23327
23336
|
res.on("error", () => {
|
|
23328
23337
|
send({ t: "res-end", id: frame.id });
|
|
23329
|
-
|
|
23338
|
+
resolve7();
|
|
23330
23339
|
});
|
|
23331
23340
|
return;
|
|
23332
23341
|
}
|
|
@@ -23343,7 +23352,7 @@ function serveRelayRequest(frame, options2) {
|
|
|
23343
23352
|
...body.byteLength > 0 ? { body: encodeBody(new Uint8Array(body)) } : {},
|
|
23344
23353
|
end: true
|
|
23345
23354
|
});
|
|
23346
|
-
|
|
23355
|
+
resolve7();
|
|
23347
23356
|
return;
|
|
23348
23357
|
}
|
|
23349
23358
|
send({ t: "res", id: frame.id, status: res.statusCode ?? 502, headers: outHeaders, end: false });
|
|
@@ -23355,11 +23364,11 @@ function serveRelayRequest(frame, options2) {
|
|
|
23355
23364
|
});
|
|
23356
23365
|
}
|
|
23357
23366
|
send({ t: "res-end", id: frame.id });
|
|
23358
|
-
|
|
23367
|
+
resolve7();
|
|
23359
23368
|
});
|
|
23360
23369
|
res.on("error", () => {
|
|
23361
23370
|
send({ t: "res", id: frame.id, status: 502, headers: [], end: true });
|
|
23362
|
-
|
|
23371
|
+
resolve7();
|
|
23363
23372
|
});
|
|
23364
23373
|
}
|
|
23365
23374
|
);
|
|
@@ -23372,13 +23381,13 @@ function serveRelayRequest(frame, options2) {
|
|
|
23372
23381
|
body: encodeBody(new TextEncoder().encode(`Frizz is not answering on this machine: ${error.message}`)),
|
|
23373
23382
|
end: true
|
|
23374
23383
|
});
|
|
23375
|
-
|
|
23384
|
+
resolve7();
|
|
23376
23385
|
});
|
|
23377
23386
|
if (frame.body) req.write(Buffer.from(decodeBody(frame.body)));
|
|
23378
23387
|
req.end();
|
|
23379
23388
|
abort = () => {
|
|
23380
23389
|
req.destroy();
|
|
23381
|
-
|
|
23390
|
+
resolve7();
|
|
23382
23391
|
};
|
|
23383
23392
|
});
|
|
23384
23393
|
return {
|
|
@@ -23512,9 +23521,9 @@ function connectRelay(options2) {
|
|
|
23512
23521
|
};
|
|
23513
23522
|
const scheduleRetry = (reason) => {
|
|
23514
23523
|
if (stopped) return;
|
|
23515
|
-
const
|
|
23516
|
-
options2.onStatus?.("retrying", `${reason}; retrying in ${Math.round(
|
|
23517
|
-
retryHandle = setTimer(() => void open(),
|
|
23524
|
+
const delay3 = backoff(attempt++);
|
|
23525
|
+
options2.onStatus?.("retrying", `${reason}; retrying in ${Math.round(delay3 / 1e3)}s`);
|
|
23526
|
+
retryHandle = setTimer(() => void open(), delay3);
|
|
23518
23527
|
};
|
|
23519
23528
|
const open = async () => {
|
|
23520
23529
|
if (stopped) return;
|
|
@@ -23937,9 +23946,9 @@ function createRemoteController(options2) {
|
|
|
23937
23946
|
import { execFile as execFile3 } from "node:child_process";
|
|
23938
23947
|
var PROBE_TIMEOUT_MS = 4e3;
|
|
23939
23948
|
function run2(command, args2) {
|
|
23940
|
-
return new Promise((
|
|
23949
|
+
return new Promise((resolve7) => {
|
|
23941
23950
|
execFile3(command, args2, { encoding: "utf8", timeout: PROBE_TIMEOUT_MS }, (error, stdout) => {
|
|
23942
|
-
|
|
23951
|
+
resolve7(error ? null : stdout);
|
|
23943
23952
|
});
|
|
23944
23953
|
});
|
|
23945
23954
|
}
|
|
@@ -25183,6 +25192,8 @@ var DEV_CRASH_STABLE_MS = 5e3;
|
|
|
25183
25192
|
var DEV_CRASH_RETRY_BASE_MS = 500;
|
|
25184
25193
|
var DEV_CRASH_RETRY_MAX_MS = 1e4;
|
|
25185
25194
|
var CHILD_STOP_TIMEOUT_MS = 15e3;
|
|
25195
|
+
var STABLE_UPDATE_READY_TIMEOUT_MS = 3e4;
|
|
25196
|
+
var STABLE_UPDATE_STABILIZE_MS = 1e3;
|
|
25186
25197
|
var CHILD_KILL_GRACE_MS = 5e3;
|
|
25187
25198
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".mjs", ".cjs", ".json"]);
|
|
25188
25199
|
var CONFIG_NAMES = /* @__PURE__ */ new Set(["package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml", ".npmrc"]);
|
|
@@ -25389,6 +25400,12 @@ var Supervisor = class {
|
|
|
25389
25400
|
debounce = null;
|
|
25390
25401
|
restartRunning = false;
|
|
25391
25402
|
restartAgain = false;
|
|
25403
|
+
/** Resolves when a pre-existing watcher restart has released the one child slot. */
|
|
25404
|
+
restartCompletion = null;
|
|
25405
|
+
/** Serializes an update candidate with watcher/browser restart requests. */
|
|
25406
|
+
updateChildRunning = false;
|
|
25407
|
+
/** A candidate never joins crash-retry until its selection has committed. */
|
|
25408
|
+
updateCandidate = null;
|
|
25392
25409
|
reloadLauncher = false;
|
|
25393
25410
|
crashAttempts = 0;
|
|
25394
25411
|
crashStableTimer = null;
|
|
@@ -25424,6 +25441,10 @@ var Supervisor = class {
|
|
|
25424
25441
|
lastActivity;
|
|
25425
25442
|
publicProxy;
|
|
25426
25443
|
updateRestart;
|
|
25444
|
+
updateMode;
|
|
25445
|
+
commitUpdate;
|
|
25446
|
+
updateReadyTimeoutMs;
|
|
25447
|
+
updateStabilizeMs;
|
|
25427
25448
|
rollbackUpdate;
|
|
25428
25449
|
durableReexec;
|
|
25429
25450
|
/** Environment of the generation that actually reached ready, never merely the latest pointer. */
|
|
@@ -25464,6 +25485,10 @@ var Supervisor = class {
|
|
|
25464
25485
|
this.errorLine = opts.error ?? ((line) => log.error("supervisor", stripPrefix(line)));
|
|
25465
25486
|
this.onActivity = opts.onActivity;
|
|
25466
25487
|
this.updateRestart = opts.updateRestart;
|
|
25488
|
+
this.updateMode = opts.updateMode ?? "durableReexec";
|
|
25489
|
+
this.commitUpdate = opts.commitUpdate;
|
|
25490
|
+
this.updateReadyTimeoutMs = Math.max(1, opts.updateReadyTimeoutMs ?? STABLE_UPDATE_READY_TIMEOUT_MS);
|
|
25491
|
+
this.updateStabilizeMs = Math.max(0, opts.updateStabilizeMs ?? STABLE_UPDATE_STABILIZE_MS);
|
|
25467
25492
|
this.rollbackUpdate = opts.rollbackUpdate;
|
|
25468
25493
|
this.durableReexec = opts.durableReexec;
|
|
25469
25494
|
this.publicProxy = new RestartSupervisorProxy({
|
|
@@ -25479,6 +25504,7 @@ var Supervisor = class {
|
|
|
25479
25504
|
updateRestart: this.updateRestart ? () => this.updateFromBrowser() : void 0,
|
|
25480
25505
|
updateAvailable: opts.updateAvailable,
|
|
25481
25506
|
version: opts.version,
|
|
25507
|
+
launcherVersion: opts.launcherVersion,
|
|
25482
25508
|
updateVersion: opts.updateVersion,
|
|
25483
25509
|
dev: opts.dev,
|
|
25484
25510
|
status: () => {
|
|
@@ -25570,6 +25596,10 @@ var Supervisor = class {
|
|
|
25570
25596
|
}
|
|
25571
25597
|
requestRestart(reason, immediate = false, reloadLauncher = false, delayMs = this.debounceMs) {
|
|
25572
25598
|
if (this.closed) return;
|
|
25599
|
+
if (this.updateChildRunning) {
|
|
25600
|
+
this.restartAgain = true;
|
|
25601
|
+
return;
|
|
25602
|
+
}
|
|
25573
25603
|
this.reloadLauncher ||= reloadLauncher;
|
|
25574
25604
|
if (this.debounce) clearTimeout(this.debounce);
|
|
25575
25605
|
const run3 = () => {
|
|
@@ -25585,11 +25615,20 @@ var Supervisor = class {
|
|
|
25585
25615
|
else this.debounce = setTimeout(run3, delayMs);
|
|
25586
25616
|
}
|
|
25587
25617
|
async restart() {
|
|
25618
|
+
if (this.updateChildRunning) {
|
|
25619
|
+
this.restartAgain = true;
|
|
25620
|
+
return;
|
|
25621
|
+
}
|
|
25588
25622
|
if (this.restartRunning) {
|
|
25589
25623
|
this.restartAgain = true;
|
|
25590
25624
|
return;
|
|
25591
25625
|
}
|
|
25592
25626
|
this.restartRunning = true;
|
|
25627
|
+
let completeRestart;
|
|
25628
|
+
const completion = new Promise((resolveCompletion) => {
|
|
25629
|
+
completeRestart = resolveCompletion;
|
|
25630
|
+
});
|
|
25631
|
+
this.restartCompletion = completion;
|
|
25593
25632
|
try {
|
|
25594
25633
|
let shouldReloadLauncher = false;
|
|
25595
25634
|
do {
|
|
@@ -25597,7 +25636,7 @@ var Supervisor = class {
|
|
|
25597
25636
|
shouldReloadLauncher ||= this.reloadLauncher;
|
|
25598
25637
|
this.reloadLauncher = false;
|
|
25599
25638
|
await this.stopChild();
|
|
25600
|
-
if (!this.closed) {
|
|
25639
|
+
if (!this.closed && !this.updateChildRunning) {
|
|
25601
25640
|
const ready = await this.spawnChild();
|
|
25602
25641
|
if (!ready) return;
|
|
25603
25642
|
}
|
|
@@ -25605,6 +25644,8 @@ var Supervisor = class {
|
|
|
25605
25644
|
if (shouldReloadLauncher && !this.closed) await this.reexecLauncher();
|
|
25606
25645
|
} finally {
|
|
25607
25646
|
this.restartRunning = false;
|
|
25647
|
+
completeRestart();
|
|
25648
|
+
if (this.restartCompletion === completion) this.restartCompletion = null;
|
|
25608
25649
|
}
|
|
25609
25650
|
}
|
|
25610
25651
|
/** Called only by the public supervisor control endpoint, never by ordinary document reloads. */
|
|
@@ -25635,6 +25676,7 @@ var Supervisor = class {
|
|
|
25635
25676
|
}
|
|
25636
25677
|
async updateFromBrowser() {
|
|
25637
25678
|
if (!this.updateRestart) return { state: "failed", message: "Update & Restart is unavailable in this launcher mode" };
|
|
25679
|
+
if (this.updateMode === "child") return this.updateChildFromBrowser();
|
|
25638
25680
|
this.emitActivity("updating", "preparing the update \u2014 the running Frizz is untouched until it is ready");
|
|
25639
25681
|
const candidate = await this.updateRestart();
|
|
25640
25682
|
if (candidate.state !== "ready") {
|
|
@@ -25661,6 +25703,114 @@ var Supervisor = class {
|
|
|
25661
25703
|
this.handoffDraining = false;
|
|
25662
25704
|
}
|
|
25663
25705
|
}
|
|
25706
|
+
/**
|
|
25707
|
+
* Update only the disposable application server while retaining the public listener and launcher.
|
|
25708
|
+
* There is deliberately no blue/green overlap: a Frizz child opens SQLite, tailers and schedulers
|
|
25709
|
+
* before it can report ready, so a candidate is started only after the old child is fully gone.
|
|
25710
|
+
*/
|
|
25711
|
+
async updateChildFromBrowser() {
|
|
25712
|
+
if (!this.commitUpdate || !this.rollbackUpdate) {
|
|
25713
|
+
return { state: "failed", message: "child-only Update & Restart requires commit and rollback callbacks" };
|
|
25714
|
+
}
|
|
25715
|
+
this.updateChildRunning = true;
|
|
25716
|
+
try {
|
|
25717
|
+
await this.restartCompletion;
|
|
25718
|
+
this.emitActivity("updating", "preparing the new build \u2014 the running one is untouched until it is ready");
|
|
25719
|
+
let prepared;
|
|
25720
|
+
try {
|
|
25721
|
+
prepared = await this.updateRestart();
|
|
25722
|
+
} catch (error) {
|
|
25723
|
+
return this.failChildUpdate(`the update could not be prepared: ${error instanceof Error ? error.message : error}`, false);
|
|
25724
|
+
}
|
|
25725
|
+
if (prepared.state !== "ready") {
|
|
25726
|
+
return this.failChildUpdate(prepared.message ?? "the update could not be prepared", false);
|
|
25727
|
+
}
|
|
25728
|
+
if (this.closed) return this.failChildUpdate("Frizz supervisor stopped while preparing the update", false);
|
|
25729
|
+
if (prepared.message) this.emitActivity("updating", prepared.message);
|
|
25730
|
+
this.handoffDraining = true;
|
|
25731
|
+
await this.stopChild();
|
|
25732
|
+
if (this.closed) return this.failChildUpdate("Frizz supervisor stopped while starting the update", true);
|
|
25733
|
+
const ready = await this.spawnChild({
|
|
25734
|
+
updateCandidate: true,
|
|
25735
|
+
readinessTimeoutMs: this.updateReadyTimeoutMs
|
|
25736
|
+
});
|
|
25737
|
+
const candidate = this.child;
|
|
25738
|
+
if (!ready || !candidate) {
|
|
25739
|
+
return this.failChildUpdate(this.lastRestartFailure ?? "the update candidate did not become ready", true);
|
|
25740
|
+
}
|
|
25741
|
+
if (!await this.stabilizeUpdateCandidate(candidate)) {
|
|
25742
|
+
return this.failChildUpdate("the update candidate stopped before it became stable", true);
|
|
25743
|
+
}
|
|
25744
|
+
try {
|
|
25745
|
+
await this.commitUpdate();
|
|
25746
|
+
} catch (error) {
|
|
25747
|
+
return this.failChildUpdate(`the update could not be committed: ${error instanceof Error ? error.message : error}`, true);
|
|
25748
|
+
}
|
|
25749
|
+
if (this.closed || this.child !== candidate || candidate.exitCode !== null || candidate.signalCode !== null) {
|
|
25750
|
+
return this.failChildUpdate("the update candidate stopped while committing the update", true);
|
|
25751
|
+
}
|
|
25752
|
+
this.updateCandidate = null;
|
|
25753
|
+
this.lastRestartFailure = void 0;
|
|
25754
|
+
return { state: "ready" };
|
|
25755
|
+
} finally {
|
|
25756
|
+
this.updateChildRunning = false;
|
|
25757
|
+
this.handoffDraining = false;
|
|
25758
|
+
if (this.restartAgain && !this.closed) {
|
|
25759
|
+
this.restartAgain = false;
|
|
25760
|
+
this.requestRestart("changes received while updating", true);
|
|
25761
|
+
}
|
|
25762
|
+
}
|
|
25763
|
+
}
|
|
25764
|
+
/** Wait past a ready event so an immediate post-boot crash cannot be made durable. */
|
|
25765
|
+
async stabilizeUpdateCandidate(candidate) {
|
|
25766
|
+
if (this.child !== candidate || candidate.exitCode !== null || candidate.signalCode !== null) return false;
|
|
25767
|
+
if (this.updateStabilizeMs === 0) return true;
|
|
25768
|
+
return new Promise((resolveStable) => {
|
|
25769
|
+
let settled = false;
|
|
25770
|
+
const finish = (stable) => {
|
|
25771
|
+
if (settled) return;
|
|
25772
|
+
settled = true;
|
|
25773
|
+
clearTimeout(timer);
|
|
25774
|
+
candidate.removeListener("exit", exited);
|
|
25775
|
+
resolveStable(stable);
|
|
25776
|
+
};
|
|
25777
|
+
const exited = () => finish(false);
|
|
25778
|
+
const timer = setTimeout(() => finish(this.child === candidate && !this.closed), this.updateStabilizeMs);
|
|
25779
|
+
timer.unref();
|
|
25780
|
+
candidate.once("exit", exited);
|
|
25781
|
+
});
|
|
25782
|
+
}
|
|
25783
|
+
/** Restore the prepared selection and, if it was drained, put the known-good child back. */
|
|
25784
|
+
async failChildUpdate(message, restoreChild) {
|
|
25785
|
+
const failures = [];
|
|
25786
|
+
const candidate = this.updateCandidate;
|
|
25787
|
+
if (candidate && this.child === candidate) await this.stopChild();
|
|
25788
|
+
this.updateCandidate = null;
|
|
25789
|
+
let rolledBack = false;
|
|
25790
|
+
if (!this.rollbackUpdate) failures.push("rollback callback is unavailable");
|
|
25791
|
+
else {
|
|
25792
|
+
try {
|
|
25793
|
+
await this.rollbackUpdate();
|
|
25794
|
+
rolledBack = true;
|
|
25795
|
+
} catch (error) {
|
|
25796
|
+
failures.push(`rollback failed: ${error instanceof Error ? error.message : error}`);
|
|
25797
|
+
}
|
|
25798
|
+
}
|
|
25799
|
+
if (restoreChild && rolledBack && !this.closed) {
|
|
25800
|
+
try {
|
|
25801
|
+
const restored = await this.spawnChild();
|
|
25802
|
+
if (!restored) failures.push(`control plane recovery failed: ${this.lastRestartFailure ?? "the previous child did not become ready"}`);
|
|
25803
|
+
} catch (error) {
|
|
25804
|
+
failures.push(`control plane recovery failed: ${error instanceof Error ? error.message : error}`);
|
|
25805
|
+
}
|
|
25806
|
+
} else if (restoreChild && !rolledBack) {
|
|
25807
|
+
failures.push("control plane was not restarted because rollback did not restore a known-good selection");
|
|
25808
|
+
}
|
|
25809
|
+
const detail = failures.length > 0 ? `${message}; ${failures.join("; ")}` : message;
|
|
25810
|
+
this.errorLine(`[frizz] ${detail}`);
|
|
25811
|
+
if (!this.closed) this.writeStatus("failed", detail, this.boot);
|
|
25812
|
+
return { state: "failed", message: detail };
|
|
25813
|
+
}
|
|
25664
25814
|
/**
|
|
25665
25815
|
* A promoted pointer is not committed until its durable owner has actually been replaced. If
|
|
25666
25816
|
* that handoff cannot happen, put the previous pointer back before reporting the failure. When
|
|
@@ -25709,7 +25859,7 @@ var Supervisor = class {
|
|
|
25709
25859
|
await this.publicProxy.close();
|
|
25710
25860
|
this.writeStatus("restarting", "immutable artifact promoted; re-executing durable supervisor", null);
|
|
25711
25861
|
}
|
|
25712
|
-
async spawnChild() {
|
|
25862
|
+
async spawnChild(options2 = {}) {
|
|
25713
25863
|
const privatePort = await allocatePrivateDevPort(this.port);
|
|
25714
25864
|
let launch;
|
|
25715
25865
|
try {
|
|
@@ -25748,16 +25898,34 @@ var Supervisor = class {
|
|
|
25748
25898
|
return;
|
|
25749
25899
|
}
|
|
25750
25900
|
this.child = child;
|
|
25901
|
+
if (options2.updateCandidate) this.updateCandidate = child;
|
|
25751
25902
|
this.childPort = privatePort;
|
|
25752
25903
|
this.boot = null;
|
|
25753
25904
|
let started = false;
|
|
25754
25905
|
let ownershipRejected = false;
|
|
25755
25906
|
let spawnSettled = false;
|
|
25907
|
+
let readinessTimer;
|
|
25756
25908
|
const settleSpawn = (ready) => {
|
|
25757
25909
|
if (spawnSettled) return;
|
|
25758
25910
|
spawnSettled = true;
|
|
25911
|
+
if (readinessTimer) clearTimeout(readinessTimer);
|
|
25759
25912
|
settled(ready);
|
|
25760
25913
|
};
|
|
25914
|
+
if (options2.readinessTimeoutMs !== void 0) {
|
|
25915
|
+
readinessTimer = setTimeout(() => {
|
|
25916
|
+
if (spawnSettled) return;
|
|
25917
|
+
const message = `update candidate did not become ready within ${options2.readinessTimeoutMs}ms`;
|
|
25918
|
+
this.lastRestartFailure = message;
|
|
25919
|
+
this.errorLine(`[frizz] ${message}`);
|
|
25920
|
+
this.writeStatus("failed", message, null);
|
|
25921
|
+
try {
|
|
25922
|
+
child.kill("SIGTERM");
|
|
25923
|
+
} catch {
|
|
25924
|
+
}
|
|
25925
|
+
settleSpawn(false);
|
|
25926
|
+
}, options2.readinessTimeoutMs);
|
|
25927
|
+
readinessTimer.unref();
|
|
25928
|
+
}
|
|
25761
25929
|
child.on("message", (message) => {
|
|
25762
25930
|
if (stopOwnerMessage(message) && message.token === this.ownerToken) {
|
|
25763
25931
|
this.resolveStopRequested();
|
|
@@ -25799,7 +25967,7 @@ var Supervisor = class {
|
|
|
25799
25967
|
this.boot = null;
|
|
25800
25968
|
this.activeChildEnvironment = {};
|
|
25801
25969
|
}
|
|
25802
|
-
const expected2 = this.closed || this.stopping === child || ownershipRejected;
|
|
25970
|
+
const expected2 = this.closed || this.stopping === child || ownershipRejected || this.updateCandidate === child;
|
|
25803
25971
|
this.clearCrashStability();
|
|
25804
25972
|
if (!expected2) {
|
|
25805
25973
|
const why = signal ? `signal ${signal}` : `exit ${code ?? "unknown"}`;
|
|
@@ -26012,15 +26180,11 @@ async function startDevSupervisor(opts) {
|
|
|
26012
26180
|
}
|
|
26013
26181
|
|
|
26014
26182
|
// src/production-update.ts
|
|
26015
|
-
init_src();
|
|
26016
26183
|
import { execFile as execFile4, spawn as spawn3 } from "node:child_process";
|
|
26017
26184
|
import { existsSync as existsSync7 } from "node:fs";
|
|
26018
26185
|
import { dirname as dirname12, isAbsolute as isAbsolute5, join as join14 } from "node:path";
|
|
26019
|
-
|
|
26186
|
+
init_src();
|
|
26020
26187
|
var PRODUCTION_REEXEC_FLAG = "--_frizz-production-reexec";
|
|
26021
|
-
function canReexecInPlace(platform = process.platform, execve = process.execve) {
|
|
26022
|
-
return platform !== "win32" && typeof execve === "function";
|
|
26023
|
-
}
|
|
26024
26188
|
var PRODUCTION_PRINT_LAUNCHER_FLAG = "--_frizz-print-launcher";
|
|
26025
26189
|
function resolveNpmInvocation(env = process.env, execPath = process.execPath, exists = existsSync7, platform = process.platform) {
|
|
26026
26190
|
const nodeDir = dirname12(execPath);
|
|
@@ -26040,9 +26204,11 @@ function resolveNpmInvocation(env = process.env, execPath = process.execPath, ex
|
|
|
26040
26204
|
}
|
|
26041
26205
|
function compareReleaseVersions(a, b) {
|
|
26042
26206
|
const parse2 = (value) => {
|
|
26043
|
-
const match = /^v?(\d
|
|
26207
|
+
const match = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u.exec(value);
|
|
26044
26208
|
if (!match) return null;
|
|
26045
|
-
|
|
26209
|
+
const prerelease = match[4]?.split(".");
|
|
26210
|
+
if (prerelease?.some((part) => /^0\d+$/u.test(part))) return null;
|
|
26211
|
+
return { numeric: [BigInt(match[1]), BigInt(match[2]), BigInt(match[3])], prerelease };
|
|
26046
26212
|
};
|
|
26047
26213
|
const left = parse2(a);
|
|
26048
26214
|
const right = parse2(b);
|
|
@@ -26051,26 +26217,22 @@ function compareReleaseVersions(a, b) {
|
|
|
26051
26217
|
const delta = left.numeric[index] - right.numeric[index];
|
|
26052
26218
|
if (delta) return delta < 0 ? -1 : 1;
|
|
26053
26219
|
}
|
|
26054
|
-
if (left.prerelease
|
|
26220
|
+
if (!left.prerelease && !right.prerelease) return 0;
|
|
26055
26221
|
if (!left.prerelease) return 1;
|
|
26056
26222
|
if (!right.prerelease) return -1;
|
|
26057
|
-
|
|
26058
|
-
|
|
26059
|
-
|
|
26060
|
-
|
|
26061
|
-
|
|
26062
|
-
|
|
26063
|
-
const
|
|
26064
|
-
const
|
|
26065
|
-
if (
|
|
26066
|
-
|
|
26067
|
-
|
|
26068
|
-
|
|
26069
|
-
|
|
26070
|
-
return l < r ? -1 : 1;
|
|
26071
|
-
}
|
|
26072
|
-
if (left.length === right.length) return 0;
|
|
26073
|
-
return left.length < right.length ? -1 : 1;
|
|
26223
|
+
for (let index = 0; index < Math.max(left.prerelease.length, right.prerelease.length); index++) {
|
|
26224
|
+
const a2 = left.prerelease[index];
|
|
26225
|
+
const b2 = right.prerelease[index];
|
|
26226
|
+
if (a2 === b2) continue;
|
|
26227
|
+
if (a2 === void 0) return -1;
|
|
26228
|
+
if (b2 === void 0) return 1;
|
|
26229
|
+
const aNumeric = /^\d+$/u.test(a2);
|
|
26230
|
+
const bNumeric = /^\d+$/u.test(b2);
|
|
26231
|
+
if (aNumeric && bNumeric) return BigInt(a2) < BigInt(b2) ? -1 : 1;
|
|
26232
|
+
if (aNumeric !== bNumeric) return aNumeric ? -1 : 1;
|
|
26233
|
+
return a2 < b2 ? -1 : 1;
|
|
26234
|
+
}
|
|
26235
|
+
return 0;
|
|
26074
26236
|
}
|
|
26075
26237
|
async function planRegistryUpdate(packageName, currentVersion, adapter) {
|
|
26076
26238
|
const latestVersion = (await adapter.latestVersion(packageName)).trim();
|
|
@@ -26080,9 +26242,6 @@ async function planRegistryUpdate(packageName, currentVersion, adapter) {
|
|
|
26080
26242
|
if (comparison >= 0) return null;
|
|
26081
26243
|
return { packageName, currentVersion, latestVersion, packageSpec: `${packageName}@${latestVersion}` };
|
|
26082
26244
|
}
|
|
26083
|
-
function successorArgs(port) {
|
|
26084
|
-
return [PRODUCTION_REEXEC_FLAG, "--port", String(port)];
|
|
26085
|
-
}
|
|
26086
26245
|
function reexecArgv(rawArgs2) {
|
|
26087
26246
|
const kept = [];
|
|
26088
26247
|
for (let index = 0; index < rawArgs2.length; index++) {
|
|
@@ -26097,110 +26256,6 @@ function reexecArgv(rawArgs2) {
|
|
|
26097
26256
|
}
|
|
26098
26257
|
return kept;
|
|
26099
26258
|
}
|
|
26100
|
-
async function resolveRegistrySuccessor(plan, request, adapter) {
|
|
26101
|
-
const result = await adapter.npmExec({
|
|
26102
|
-
packageSpec: plan.packageSpec,
|
|
26103
|
-
// The published bin name tracks the package name (frizz). Never hardcode a stale bin here or
|
|
26104
|
-
// a renamed release would resolve the new package but invoke a bin that no longer exists.
|
|
26105
|
-
bin: plan.packageName,
|
|
26106
|
-
args: [PRODUCTION_PRINT_LAUNCHER_FLAG],
|
|
26107
|
-
cwd: request.cwd,
|
|
26108
|
-
env: request.env
|
|
26109
|
-
});
|
|
26110
|
-
if (result.code !== 0) {
|
|
26111
|
-
const how = result.signal ? `signal ${result.signal}` : `exit ${result.code}`;
|
|
26112
|
-
const tail = result.stderr.trim().split("\n").slice(-6).join("\n").trim();
|
|
26113
|
-
throw new Error(`npm exec ${plan.packageSpec} failed (${how})${tail ? `: ${tail}` : ""}`);
|
|
26114
|
-
}
|
|
26115
|
-
const entry = result.stdout.trim().split("\n").map((line) => line.trim()).filter(Boolean).at(-1) ?? "";
|
|
26116
|
-
if (!isAbsolute5(entry) || !existsSync7(entry))
|
|
26117
|
-
throw new Error(`${plan.packageSpec} did not report its launcher entry (got ${JSON.stringify(entry)})`);
|
|
26118
|
-
return { plan, entry };
|
|
26119
|
-
}
|
|
26120
|
-
function reexecIntoRegistrySuccessor(successor, request, execve = process.execve.bind(process)) {
|
|
26121
|
-
return execve(process.execPath, [process.execPath, successor.entry, ...successorArgs(request.port)], {
|
|
26122
|
-
...request.env,
|
|
26123
|
-
FRIZZ_REGISTRY_PACKAGE: successor.plan.packageName,
|
|
26124
|
-
FRIZZ_REGISTRY_VERSION: successor.plan.latestVersion
|
|
26125
|
-
});
|
|
26126
|
-
}
|
|
26127
|
-
function handoffToRegistrySuccessor(successor, request, adapter) {
|
|
26128
|
-
const child = adapter.spawnDetached({
|
|
26129
|
-
entry: successor.entry,
|
|
26130
|
-
args: successorArgs(request.port),
|
|
26131
|
-
cwd: request.cwd,
|
|
26132
|
-
env: {
|
|
26133
|
-
...request.env,
|
|
26134
|
-
FRIZZ_REGISTRY_PACKAGE: successor.plan.packageName,
|
|
26135
|
-
FRIZZ_REGISTRY_VERSION: successor.plan.latestVersion
|
|
26136
|
-
}
|
|
26137
|
-
});
|
|
26138
|
-
child.once("error", () => {
|
|
26139
|
-
});
|
|
26140
|
-
if (child.pid === void 0) throw new Error(`could not start Frizz ${successor.plan.latestVersion} from ${successor.entry}`);
|
|
26141
|
-
child.unref();
|
|
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) {
|
|
26163
|
-
try {
|
|
26164
|
-
child.kill();
|
|
26165
|
-
} catch {
|
|
26166
|
-
}
|
|
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)
|
|
26191
|
-
});
|
|
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
26259
|
function isGlobalInstall(bundleDir, env = process.env) {
|
|
26205
26260
|
if (env.npm_execpath) return false;
|
|
26206
26261
|
const segments = bundleDir.split(/[\\/]/u);
|
|
@@ -26294,11 +26349,386 @@ npm exec ${packageSpec} did not finish within ${formatTimeout(execTimeoutMs)} an
|
|
|
26294
26349
|
}
|
|
26295
26350
|
var npmRegistryReleaseAdapter = createNpmRegistryReleaseAdapter();
|
|
26296
26351
|
|
|
26352
|
+
// src/server-release.ts
|
|
26353
|
+
init_frizz_paths();
|
|
26354
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
26355
|
+
import { createHash as createHash4, randomUUID as randomUUID6 } from "node:crypto";
|
|
26356
|
+
import {
|
|
26357
|
+
closeSync as closeSync5,
|
|
26358
|
+
existsSync as existsSync8,
|
|
26359
|
+
fsyncSync as fsyncSync5,
|
|
26360
|
+
mkdirSync as mkdirSync12,
|
|
26361
|
+
openSync as openSync6,
|
|
26362
|
+
readFileSync as readFileSync13,
|
|
26363
|
+
realpathSync as realpathSync6,
|
|
26364
|
+
renameSync as renameSync6,
|
|
26365
|
+
rmSync as rmSync9,
|
|
26366
|
+
statSync as statSync5,
|
|
26367
|
+
writeFileSync as writeFileSync11
|
|
26368
|
+
} from "node:fs";
|
|
26369
|
+
import { delimiter as delimiter2, dirname as dirname13, isAbsolute as isAbsolute6, join as join15, relative as relative3, resolve as resolve6, sep as sep4 } from "node:path";
|
|
26370
|
+
var SERVER_PROTOCOL = 1;
|
|
26371
|
+
var SERVER_DATA_EPOCH = 1;
|
|
26372
|
+
var VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u;
|
|
26373
|
+
var PACKAGE = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/u;
|
|
26374
|
+
var GENERATION = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u;
|
|
26375
|
+
var CURRENT_COMPATIBILITY = { protocol: SERVER_PROTOCOL, dataEpoch: SERVER_DATA_EPOCH };
|
|
26376
|
+
function assertSpecShape(spec) {
|
|
26377
|
+
if (typeof spec.package !== "string" || typeof spec.version !== "string" || !PACKAGE.test(spec.package) || !VERSION.test(spec.version))
|
|
26378
|
+
throw new Error("invalid exact Frizz server package/version");
|
|
26379
|
+
if (!Number.isSafeInteger(spec.protocol) || spec.protocol < 1 || !Number.isSafeInteger(spec.dataEpoch) || spec.dataEpoch < 1)
|
|
26380
|
+
throw new Error("invalid Frizz server protocol/data epoch");
|
|
26381
|
+
}
|
|
26382
|
+
function assertSpec(spec, compatibility = CURRENT_COMPATIBILITY) {
|
|
26383
|
+
assertSpecShape(spec);
|
|
26384
|
+
if (spec.protocol !== compatibility.protocol || spec.dataEpoch !== compatibility.dataEpoch)
|
|
26385
|
+
throw new Error("this Frizz server requires a newer launcher or a data migration; restart with a compatible Frizz release");
|
|
26386
|
+
}
|
|
26387
|
+
function readJson(path) {
|
|
26388
|
+
return JSON.parse(readFileSync13(path, "utf8"));
|
|
26389
|
+
}
|
|
26390
|
+
function record(value) {
|
|
26391
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("invalid Frizz server manifest");
|
|
26392
|
+
return value;
|
|
26393
|
+
}
|
|
26394
|
+
function serverReleaseSpec(manifest, packageOverride) {
|
|
26395
|
+
const metadata = record(record(manifest).frizzServer);
|
|
26396
|
+
const spec = {
|
|
26397
|
+
package: packageOverride ?? metadata.package,
|
|
26398
|
+
version: metadata.version,
|
|
26399
|
+
protocol: metadata.protocol,
|
|
26400
|
+
dataEpoch: metadata.dataEpoch
|
|
26401
|
+
};
|
|
26402
|
+
assertSpec(spec);
|
|
26403
|
+
return spec;
|
|
26404
|
+
}
|
|
26405
|
+
function containedFile(root, name, directory = false) {
|
|
26406
|
+
const path = realpathSync6(join15(root, name));
|
|
26407
|
+
const rel = relative3(realpathSync6(root), path);
|
|
26408
|
+
if (rel === ".." || rel.startsWith(`..${sep4}`) || isAbsolute6(rel))
|
|
26409
|
+
throw new Error(`Frizz server artifact escapes its package: ${name}`);
|
|
26410
|
+
const stat = statSync5(path);
|
|
26411
|
+
if (directory ? !stat.isDirectory() : !stat.isFile()) throw new Error(`invalid Frizz server artifact: ${name}`);
|
|
26412
|
+
return path;
|
|
26413
|
+
}
|
|
26414
|
+
function validateServerGeneration(root, spec, id, compatibility = CURRENT_COMPATIBILITY) {
|
|
26415
|
+
assertSpec(spec, compatibility);
|
|
26416
|
+
if (!GENERATION.test(id)) throw new Error("invalid Frizz server generation id");
|
|
26417
|
+
const manifest = record(readJson(join15(root, "package.json")));
|
|
26418
|
+
const metadata = record(manifest.frizzServer);
|
|
26419
|
+
if (manifest.name !== spec.package || manifest.version !== spec.version)
|
|
26420
|
+
throw new Error(`Frizz server install did not contain ${spec.package}@${spec.version}`);
|
|
26421
|
+
if (metadata.protocol !== spec.protocol || metadata.dataEpoch !== spec.dataEpoch)
|
|
26422
|
+
throw new Error("Frizz server protocol/data epoch is incompatible; the current server has not been stopped");
|
|
26423
|
+
const entry = containedFile(root, "dist/dev-child.js");
|
|
26424
|
+
containedFile(root, "dist/codex-app-server-daemon.js");
|
|
26425
|
+
containedFile(root, "dist/claude-agent-broker.js");
|
|
26426
|
+
containedFile(root, "web-dist/index.html");
|
|
26427
|
+
containedFile(root, "runtime/board/index.mjs");
|
|
26428
|
+
containedFile(root, "runtime/cc-worker/.claude-plugin/plugin.json");
|
|
26429
|
+
return { ...spec, id, root: realpathSync6(root), entry };
|
|
26430
|
+
}
|
|
26431
|
+
function serverGenerationLaunch(generation) {
|
|
26432
|
+
return {
|
|
26433
|
+
entry: generation.entry,
|
|
26434
|
+
environment: {
|
|
26435
|
+
FRIZZ_STABLE_ARTIFACT: `npm:${generation.package}@${generation.version}`,
|
|
26436
|
+
FRIZZ_STABLE_WEB_DIST: join15(generation.root, "web-dist"),
|
|
26437
|
+
FRIZZ_SCRIPTS_DIR: join15(generation.root, "runtime/board"),
|
|
26438
|
+
FRIZZ_WORKER_PLUGIN_DIR: join15(generation.root, "runtime/cc-worker")
|
|
26439
|
+
}
|
|
26440
|
+
};
|
|
26441
|
+
}
|
|
26442
|
+
function resolveNpmCli(env = process.env, executable = process.execPath) {
|
|
26443
|
+
const candidates = [];
|
|
26444
|
+
if (env.npm_execpath?.endsWith("npm-cli.js")) candidates.push(env.npm_execpath);
|
|
26445
|
+
for (const directory of [dirname13(executable), ...(env.PATH ?? env.Path ?? "").split(delimiter2).filter(Boolean)]) {
|
|
26446
|
+
candidates.push(join15(directory, "node_modules/npm/bin/npm-cli.js"), join15(directory, "../lib/node_modules/npm/bin/npm-cli.js"));
|
|
26447
|
+
try {
|
|
26448
|
+
const path = realpathSync6(join15(directory, "npm"));
|
|
26449
|
+
if (path.endsWith("npm-cli.js")) candidates.push(path);
|
|
26450
|
+
} catch {
|
|
26451
|
+
}
|
|
26452
|
+
}
|
|
26453
|
+
const found = candidates.find((path) => existsSync8(path) && statSync5(path).isFile());
|
|
26454
|
+
if (!found) throw new Error("npm was not found beside Node or on PATH; install Node with npm to install Frizz server releases");
|
|
26455
|
+
return resolve6(found);
|
|
26456
|
+
}
|
|
26457
|
+
function npmServerPackageInstaller(env = process.env) {
|
|
26458
|
+
const run3 = (args2, cwd) => new Promise((resolveOutput, reject) => {
|
|
26459
|
+
let cli;
|
|
26460
|
+
try {
|
|
26461
|
+
cli = resolveNpmCli(env);
|
|
26462
|
+
} catch (error) {
|
|
26463
|
+
reject(error);
|
|
26464
|
+
return;
|
|
26465
|
+
}
|
|
26466
|
+
execFile5(process.execPath, [cli, ...args2], {
|
|
26467
|
+
env,
|
|
26468
|
+
cwd,
|
|
26469
|
+
encoding: "utf8",
|
|
26470
|
+
windowsHide: true,
|
|
26471
|
+
timeout: 18e4,
|
|
26472
|
+
killSignal: "SIGKILL",
|
|
26473
|
+
maxBuffer: 4 * 1024 * 1024
|
|
26474
|
+
}, (error, stdout, stderr) => {
|
|
26475
|
+
if (error) {
|
|
26476
|
+
const tail = stderr.trim().split("\n").slice(-8).join("\n");
|
|
26477
|
+
reject(new Error(`Frizz server npm operation failed: ${tail || error.message}`));
|
|
26478
|
+
} else resolveOutput(stdout);
|
|
26479
|
+
});
|
|
26480
|
+
});
|
|
26481
|
+
return {
|
|
26482
|
+
async install(prefix, spec) {
|
|
26483
|
+
assertSpec(spec);
|
|
26484
|
+
await run3([
|
|
26485
|
+
"install",
|
|
26486
|
+
"--prefix",
|
|
26487
|
+
prefix,
|
|
26488
|
+
"--global=false",
|
|
26489
|
+
"--ignore-scripts",
|
|
26490
|
+
"--no-audit",
|
|
26491
|
+
"--no-fund",
|
|
26492
|
+
"--engine-strict",
|
|
26493
|
+
"--install-strategy=hoisted",
|
|
26494
|
+
"--include=optional",
|
|
26495
|
+
"--omit=dev",
|
|
26496
|
+
"--save-exact",
|
|
26497
|
+
`${spec.package}@${spec.version}`
|
|
26498
|
+
], prefix);
|
|
26499
|
+
},
|
|
26500
|
+
async latestVersion(packageName) {
|
|
26501
|
+
if (!PACKAGE.test(packageName)) throw new Error("invalid Frizz server package name");
|
|
26502
|
+
const version = JSON.parse(await run3(["view", `${packageName}@latest`, "version", "--json"]));
|
|
26503
|
+
if (typeof version !== "string" || !VERSION.test(version)) throw new Error("npm returned an invalid Frizz server version");
|
|
26504
|
+
return version;
|
|
26505
|
+
}
|
|
26506
|
+
};
|
|
26507
|
+
}
|
|
26508
|
+
function atomicJson2(path, value) {
|
|
26509
|
+
mkdirSync12(dirname13(path), { recursive: true, mode: 448 });
|
|
26510
|
+
const temp = `${path}.${randomUUID6()}.tmp`;
|
|
26511
|
+
try {
|
|
26512
|
+
const fd = openSync6(temp, "wx", 384);
|
|
26513
|
+
try {
|
|
26514
|
+
writeFileSync11(fd, `${JSON.stringify(value)}
|
|
26515
|
+
`);
|
|
26516
|
+
fsyncSync5(fd);
|
|
26517
|
+
} finally {
|
|
26518
|
+
closeSync5(fd);
|
|
26519
|
+
}
|
|
26520
|
+
renameSync6(temp, path);
|
|
26521
|
+
try {
|
|
26522
|
+
const directory = openSync6(dirname13(path), "r");
|
|
26523
|
+
try {
|
|
26524
|
+
fsyncSync5(directory);
|
|
26525
|
+
} finally {
|
|
26526
|
+
closeSync5(directory);
|
|
26527
|
+
}
|
|
26528
|
+
} catch {
|
|
26529
|
+
}
|
|
26530
|
+
} finally {
|
|
26531
|
+
rmSync9(temp, { force: true });
|
|
26532
|
+
}
|
|
26533
|
+
}
|
|
26534
|
+
var ServerReleaseStore = class {
|
|
26535
|
+
constructor(spec, installer, roots = frizzPaths(), compatibility = CURRENT_COMPATIBILITY) {
|
|
26536
|
+
this.spec = spec;
|
|
26537
|
+
this.installer = installer;
|
|
26538
|
+
this.roots = roots;
|
|
26539
|
+
this.compatibility = compatibility;
|
|
26540
|
+
assertSpec(spec, compatibility);
|
|
26541
|
+
const key = createHash4("sha256").update(spec.package).digest("hex").slice(0, 16);
|
|
26542
|
+
this.generations = join15(roots.cache, "server-releases", key);
|
|
26543
|
+
this.selection = join15(roots.state, "server-releases", key, "active.json");
|
|
26544
|
+
this.compatibilityMarker = join15(roots.state, "server-releases", "data-compatibility.json");
|
|
26545
|
+
}
|
|
26546
|
+
generations;
|
|
26547
|
+
selection;
|
|
26548
|
+
/** One global data marker: every package override opens the same Frizz databases. */
|
|
26549
|
+
compatibilityMarker;
|
|
26550
|
+
packageRoot(id) {
|
|
26551
|
+
return join15(this.generations, id, "node_modules", this.spec.package);
|
|
26552
|
+
}
|
|
26553
|
+
readCompatibilityMarker() {
|
|
26554
|
+
if (!existsSync8(this.compatibilityMarker)) return void 0;
|
|
26555
|
+
try {
|
|
26556
|
+
const marker = record(readJson(this.compatibilityMarker));
|
|
26557
|
+
const compatibility = { protocol: marker.protocol, dataEpoch: marker.dataEpoch };
|
|
26558
|
+
assertSpecShape({ package: this.spec.package, version: this.spec.version, ...compatibility });
|
|
26559
|
+
return compatibility;
|
|
26560
|
+
} catch {
|
|
26561
|
+
throw new Error("invalid saved Frizz server data compatibility marker; refusing to risk a data downgrade");
|
|
26562
|
+
}
|
|
26563
|
+
}
|
|
26564
|
+
assertMarkerIsSupported() {
|
|
26565
|
+
const marker = this.readCompatibilityMarker();
|
|
26566
|
+
if (!marker) return;
|
|
26567
|
+
if (marker.protocol !== this.compatibility.protocol || marker.dataEpoch > this.compatibility.dataEpoch)
|
|
26568
|
+
throw new Error("this Frizz server requires a newer launcher or a data migration; restart with a compatible Frizz release");
|
|
26569
|
+
}
|
|
26570
|
+
/**
|
|
26571
|
+
* Advance the global epoch only after the exact replacement has been staged and validated, but
|
|
26572
|
+
* before handing it to the caller that can launch it. A crash before first boot must never let an
|
|
26573
|
+
* older shell reopen the database the candidate may already have migrated.
|
|
26574
|
+
*/
|
|
26575
|
+
markCompatibilityBeforeLaunch() {
|
|
26576
|
+
const marker = this.readCompatibilityMarker();
|
|
26577
|
+
if (marker?.protocol !== void 0 && marker.protocol !== this.compatibility.protocol)
|
|
26578
|
+
throw new Error("this Frizz server requires a newer launcher or a data migration; restart with a compatible Frizz release");
|
|
26579
|
+
if ((marker?.dataEpoch ?? 0) > this.compatibility.dataEpoch)
|
|
26580
|
+
throw new Error("this Frizz server requires a newer launcher or a data migration; restart with a compatible Frizz release");
|
|
26581
|
+
if (marker?.dataEpoch === this.compatibility.dataEpoch) return;
|
|
26582
|
+
atomicJson2(this.compatibilityMarker, this.compatibility);
|
|
26583
|
+
}
|
|
26584
|
+
async prepareInitial(version) {
|
|
26585
|
+
const generation = await this.prepare(version);
|
|
26586
|
+
this.markCompatibilityBeforeLaunch();
|
|
26587
|
+
return generation;
|
|
26588
|
+
}
|
|
26589
|
+
async load() {
|
|
26590
|
+
this.assertMarkerIsSupported();
|
|
26591
|
+
if (!existsSync8(this.selection)) return this.prepareInitial(this.spec.version);
|
|
26592
|
+
const selected = record(readJson(this.selection));
|
|
26593
|
+
const spec = selected;
|
|
26594
|
+
assertSpecShape(spec);
|
|
26595
|
+
if (spec.package !== this.spec.package || typeof selected.id !== "string" || !GENERATION.test(selected.id))
|
|
26596
|
+
throw new Error("invalid saved Frizz server selection; refusing to fall back to an older server");
|
|
26597
|
+
if (spec.protocol !== this.compatibility.protocol)
|
|
26598
|
+
throw new Error("this Frizz server requires a newer launcher or a data migration; restart with a compatible Frizz release");
|
|
26599
|
+
if (spec.dataEpoch < this.compatibility.dataEpoch) return this.prepareInitial(this.spec.version);
|
|
26600
|
+
if (spec.dataEpoch > this.compatibility.dataEpoch)
|
|
26601
|
+
throw new Error("this Frizz server requires a newer launcher or a data migration; restart with a compatible Frizz release");
|
|
26602
|
+
const root = this.packageRoot(selected.id);
|
|
26603
|
+
const generation = !existsSync8(root) ? await this.prepare(spec.version) : validateServerGeneration(root, spec, selected.id, this.compatibility);
|
|
26604
|
+
this.markCompatibilityBeforeLaunch();
|
|
26605
|
+
return generation;
|
|
26606
|
+
}
|
|
26607
|
+
async prepare(version) {
|
|
26608
|
+
const spec = { ...this.spec, version };
|
|
26609
|
+
assertSpec(spec, this.compatibility);
|
|
26610
|
+
mkdirSync12(this.generations, { recursive: true, mode: 448 });
|
|
26611
|
+
const id = randomUUID6();
|
|
26612
|
+
const staging = join15(this.generations, `${id}.staging`);
|
|
26613
|
+
const destination = join15(this.generations, id);
|
|
26614
|
+
mkdirSync12(staging, { mode: 448 });
|
|
26615
|
+
try {
|
|
26616
|
+
writeFileSync11(join15(staging, "package.json"), '{"private":true}\n', { mode: 384 });
|
|
26617
|
+
await this.installer.install(staging, spec);
|
|
26618
|
+
validateServerGeneration(join15(staging, "node_modules", spec.package), spec, id, this.compatibility);
|
|
26619
|
+
renameSync6(staging, destination);
|
|
26620
|
+
return validateServerGeneration(this.packageRoot(id), spec, id, this.compatibility);
|
|
26621
|
+
} finally {
|
|
26622
|
+
rmSync9(staging, { recursive: true, force: true });
|
|
26623
|
+
}
|
|
26624
|
+
}
|
|
26625
|
+
commit(generation) {
|
|
26626
|
+
if (generation.package !== this.spec.package || generation.root !== realpathSync6(this.packageRoot(generation.id)))
|
|
26627
|
+
throw new Error("cannot select a Frizz server outside this release store");
|
|
26628
|
+
validateServerGeneration(generation.root, generation, generation.id, this.compatibility);
|
|
26629
|
+
const { package: packageName, version, protocol, dataEpoch, id } = generation;
|
|
26630
|
+
atomicJson2(this.selection, { package: packageName, version, protocol, dataEpoch, id });
|
|
26631
|
+
}
|
|
26632
|
+
};
|
|
26633
|
+
|
|
26634
|
+
// src/server-owner.ts
|
|
26635
|
+
init_frizz_paths();
|
|
26636
|
+
init_project_launch();
|
|
26637
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
26638
|
+
import { mkdirSync as mkdirSync13, readFileSync as readFileSync14, realpathSync as realpathSync7 } from "node:fs";
|
|
26639
|
+
import { join as join16 } from "node:path";
|
|
26640
|
+
var STABLE_SERVER_OWNER_NAME = "frizz-server";
|
|
26641
|
+
var STABLE_SERVER_OWNER_PROJECT_ID = "c1fd5810-0f8a-4c1d-91a0-6d7445d28e5a";
|
|
26642
|
+
var ADDRESS_NAME = "address.json";
|
|
26643
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;
|
|
26644
|
+
function rootsFor(roots) {
|
|
26645
|
+
return roots ?? frizzPaths();
|
|
26646
|
+
}
|
|
26647
|
+
function stableServerOwnerTarget(roots) {
|
|
26648
|
+
const resolved = rootsFor(roots);
|
|
26649
|
+
mkdirSync13(resolved.data, { recursive: true, mode: 448 });
|
|
26650
|
+
return {
|
|
26651
|
+
projectId: STABLE_SERVER_OWNER_PROJECT_ID,
|
|
26652
|
+
projectDir: realpathSync7(resolved.data),
|
|
26653
|
+
stateDir: join16(resolved.state, STABLE_SERVER_OWNER_NAME)
|
|
26654
|
+
};
|
|
26655
|
+
}
|
|
26656
|
+
function matchingTarget(owner, target2) {
|
|
26657
|
+
return owner.projectId === target2.projectId && owner.projectDir === target2.projectDir;
|
|
26658
|
+
}
|
|
26659
|
+
function readAddress(path) {
|
|
26660
|
+
try {
|
|
26661
|
+
const value = JSON.parse(readFileSync14(path, "utf8"));
|
|
26662
|
+
if (value.version !== 1 || typeof value.ownerToken !== "string" || !UUID_RE2.test(value.ownerToken) || typeof value.publisherToken !== "string" || !UUID_RE2.test(value.publisherToken) || typeof value.pid !== "number" || !Number.isInteger(value.pid) || value.pid <= 0 || typeof value.processStart !== "string" || value.processStart.length === 0 || typeof value.port !== "number" || !Number.isInteger(value.port) || value.port < 1 || value.port > 65535) return null;
|
|
26663
|
+
return value;
|
|
26664
|
+
} catch {
|
|
26665
|
+
return null;
|
|
26666
|
+
}
|
|
26667
|
+
}
|
|
26668
|
+
function readStableServerOwner(roots) {
|
|
26669
|
+
const target2 = stableServerOwnerTarget(roots);
|
|
26670
|
+
const owner = readProjectLaunchOwner(target2.stateDir);
|
|
26671
|
+
if (!owner || !matchingTarget(owner, target2) || processGenerationIsStale(owner)) return { kind: "idle" };
|
|
26672
|
+
const address = readAddress(join16(target2.stateDir, ADDRESS_NAME));
|
|
26673
|
+
if (!address || address.ownerToken !== owner.token || address.pid !== owner.pid || address.processStart !== owner.processStart) return { kind: "busy", owner };
|
|
26674
|
+
return { kind: "running", port: address.port, owner };
|
|
26675
|
+
}
|
|
26676
|
+
function wrapLease(lease) {
|
|
26677
|
+
return {
|
|
26678
|
+
target: lease.target,
|
|
26679
|
+
token: lease.token,
|
|
26680
|
+
pid: lease.pid,
|
|
26681
|
+
processStart: lease.processStart,
|
|
26682
|
+
publisherToken: randomUUID7()
|
|
26683
|
+
};
|
|
26684
|
+
}
|
|
26685
|
+
function acquireStableServerOwner(roots) {
|
|
26686
|
+
const target2 = stableServerOwnerTarget(roots);
|
|
26687
|
+
const attempt = tryAcquireProjectLaunchOwner(target2, "server");
|
|
26688
|
+
if (attempt.kind === "acquired") return { kind: "acquired", lease: holdLease(attempt.lease) };
|
|
26689
|
+
const observed = readStableServerOwner(roots);
|
|
26690
|
+
return observed.kind === "running" || observed.kind === "busy" ? observed : { kind: "busy", owner: attempt.owner };
|
|
26691
|
+
}
|
|
26692
|
+
function publishStableServerAddress(lease, port) {
|
|
26693
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error(`invalid stable Frizz server port: ${port}`);
|
|
26694
|
+
const owner = readProjectLaunchOwner(lease.target.stateDir);
|
|
26695
|
+
if (!owner || !matchingTarget(owner, lease.target) || owner.token !== lease.token || owner.pid !== lease.pid || owner.processStart !== lease.processStart || processGenerationIsStale(owner)) throw new Error("cannot publish an address without the exact live stable Frizz server owner");
|
|
26696
|
+
writeProjectStatus(join16(lease.target.stateDir, ADDRESS_NAME), {
|
|
26697
|
+
version: 1,
|
|
26698
|
+
ownerToken: lease.token,
|
|
26699
|
+
pid: lease.pid,
|
|
26700
|
+
processStart: lease.processStart,
|
|
26701
|
+
publisherToken: lease.publisherToken,
|
|
26702
|
+
port
|
|
26703
|
+
});
|
|
26704
|
+
}
|
|
26705
|
+
function releaseStableServerOwner(lease) {
|
|
26706
|
+
return releaseHeldLease(lease);
|
|
26707
|
+
}
|
|
26708
|
+
var heldLeases = /* @__PURE__ */ new Map();
|
|
26709
|
+
function holdLease(lease) {
|
|
26710
|
+
const wrapped = wrapLease(lease);
|
|
26711
|
+
heldLeases.set(wrapped.publisherToken, lease);
|
|
26712
|
+
return wrapped;
|
|
26713
|
+
}
|
|
26714
|
+
function releaseHeldLease(lease) {
|
|
26715
|
+
const held = heldLeases.get(lease.publisherToken);
|
|
26716
|
+
if (!held || held.token !== lease.token || held.pid !== lease.pid || held.processStart !== lease.processStart) return false;
|
|
26717
|
+
const released = held.release();
|
|
26718
|
+
if (!released) return false;
|
|
26719
|
+
heldLeases.delete(lease.publisherToken);
|
|
26720
|
+
removeProjectStatus(join16(lease.target.stateDir, ADDRESS_NAME), {
|
|
26721
|
+
ownerToken: lease.token,
|
|
26722
|
+
pid: lease.pid,
|
|
26723
|
+
processStart: lease.processStart,
|
|
26724
|
+
publisherToken: lease.publisherToken
|
|
26725
|
+
});
|
|
26726
|
+
return true;
|
|
26727
|
+
}
|
|
26728
|
+
|
|
26297
26729
|
// src/preflight.ts
|
|
26730
|
+
init_native_helper();
|
|
26298
26731
|
import { spawnSync } from "node:child_process";
|
|
26299
|
-
import { chmodSync as chmodSync2, statSync as statSync5 } from "node:fs";
|
|
26300
|
-
import { createRequire } from "node:module";
|
|
26301
|
-
import { dirname as dirname13, join as join15 } from "node:path";
|
|
26302
26732
|
var SUPPORTED_NODE_LINES = [
|
|
26303
26733
|
{ major: 22, minor: 13 },
|
|
26304
26734
|
{ major: 23, minor: 4 }
|
|
@@ -26342,25 +26772,6 @@ function assertLaunchPrerequisites(options2 = {}) {
|
|
|
26342
26772
|
);
|
|
26343
26773
|
assertRequiredExecutables(options2.command ?? commandIsAvailable);
|
|
26344
26774
|
}
|
|
26345
|
-
function ensureNativeHelperPermissions(options2 = {}) {
|
|
26346
|
-
const platform = options2.platform ?? process.platform;
|
|
26347
|
-
if (platform === "win32") return;
|
|
26348
|
-
const stat = options2.stat ?? ((path) => statSync5(path));
|
|
26349
|
-
const chmod = options2.chmod ?? ((path, mode) => chmodSync2(path, mode));
|
|
26350
|
-
const resolvePty = options2.resolvePty ?? (() => createRequire(import.meta.url).resolve("node-pty/package.json"));
|
|
26351
|
-
try {
|
|
26352
|
-
const helper = join15(
|
|
26353
|
-
dirname13(resolvePty()),
|
|
26354
|
-
"prebuilds",
|
|
26355
|
-
`${platform}-${options2.arch ?? process.arch}`,
|
|
26356
|
-
"spawn-helper"
|
|
26357
|
-
);
|
|
26358
|
-
const mode = stat(helper).mode;
|
|
26359
|
-
if ((mode & 73) === 73) return;
|
|
26360
|
-
chmod(helper, mode | 493);
|
|
26361
|
-
} catch {
|
|
26362
|
-
}
|
|
26363
|
-
}
|
|
26364
26775
|
|
|
26365
26776
|
// src/production.ts
|
|
26366
26777
|
init_src();
|
|
@@ -26369,7 +26780,7 @@ init_project_identity();
|
|
|
26369
26780
|
var PACKAGE_NAME = process.env.FRIZZ_REGISTRY_PACKAGE ?? "frizz";
|
|
26370
26781
|
function resolvePackageVersion() {
|
|
26371
26782
|
try {
|
|
26372
|
-
const manifest = JSON.parse(
|
|
26783
|
+
const manifest = JSON.parse(readFileSync15(join17(import.meta.dirname, "..", "package.json"), "utf8"));
|
|
26373
26784
|
if (typeof manifest.version === "string" && manifest.version.trim()) return manifest.version.trim();
|
|
26374
26785
|
} catch {
|
|
26375
26786
|
}
|
|
@@ -26433,10 +26844,13 @@ var sandbox = options.sandbox ? prepareSandbox() : null;
|
|
|
26433
26844
|
if (sandbox) process.on("exit", () => cleanupSandbox(sandbox.home));
|
|
26434
26845
|
var remote = null;
|
|
26435
26846
|
var paneHost = null;
|
|
26436
|
-
var rearmPaneHost = null;
|
|
26437
26847
|
var globalInstall = process.env[GLOBAL_INSTALL_ENV] === "1" || isGlobalInstall(import.meta.dirname);
|
|
26438
26848
|
var accessPane = null;
|
|
26439
26849
|
var activeAccessLink = null;
|
|
26850
|
+
var serverOwner;
|
|
26851
|
+
process.on("exit", () => {
|
|
26852
|
+
if (serverOwner) releaseStableServerOwner(serverOwner);
|
|
26853
|
+
});
|
|
26440
26854
|
var launchIntent;
|
|
26441
26855
|
var workspace = (() => {
|
|
26442
26856
|
try {
|
|
@@ -26522,15 +26936,15 @@ if (options.link) {
|
|
|
26522
26936
|
var logger = setAmbientLogger(
|
|
26523
26937
|
process.env.FRIZZ_LOG_FILE ? createLogger({ file: process.env.FRIZZ_LOG_FILE, owner: false }) : createLogger({ file: runLogPath(workspace.stateDir) })
|
|
26524
26938
|
);
|
|
26525
|
-
var readout = reexec || process.env.FRIZZ_PRODUCTION_SUPERVISOR === "1" ? void 0 : new Readout({ debug: options.debug
|
|
26526
|
-
var activityReadout = readout ?? (reexec && process.stdout.isTTY ? noticeOnlyReadout({
|
|
26939
|
+
var readout = reexec || process.env.FRIZZ_PRODUCTION_SUPERVISOR === "1" ? void 0 : new Readout({ debug: options.debug });
|
|
26940
|
+
var activityReadout = readout ?? (reexec && process.stdout.isTTY ? noticeOnlyReadout({}) : void 0);
|
|
26527
26941
|
attachTerminalMirror(logger, options.debug || process.env.FRIZZ_DEBUG === "1");
|
|
26528
26942
|
readout?.plan([
|
|
26529
26943
|
{ key: "server", label: "Server" },
|
|
26530
26944
|
{ key: "browser", label: options.noApp ? "Address" : "Browser" }
|
|
26531
26945
|
]);
|
|
26532
26946
|
readout?.begin("server", "starting");
|
|
26533
|
-
logger.info("launcher", `
|
|
26947
|
+
logger.info("launcher", `Frizz launcher ${PACKAGE_VERSION} starting for ${workspace.root}`);
|
|
26534
26948
|
var target = workspaceLaunchTarget(workspace);
|
|
26535
26949
|
var expected = expectedOwnerHealth(target, readProjectLaunchOwner(workspace.stateDir));
|
|
26536
26950
|
async function existingPort() {
|
|
@@ -26579,7 +26993,7 @@ async function openOrPrint(port, reused, path = "") {
|
|
|
26579
26993
|
readout?.begin("browser", options.appMode ? "requesting app window" : "requesting default browser");
|
|
26580
26994
|
try {
|
|
26581
26995
|
if (options.appMode) {
|
|
26582
|
-
await launchApp(url, { dataPath:
|
|
26996
|
+
await launchApp(url, { dataPath: join17(workspace.stateDir, "browser-profile") });
|
|
26583
26997
|
browser = reused ? "focused the Frizz app window" : "opened the Frizz app window";
|
|
26584
26998
|
} else {
|
|
26585
26999
|
await launchBrowserTab(url);
|
|
@@ -26598,7 +27012,7 @@ async function openOrPrint(port, reused, path = "") {
|
|
|
26598
27012
|
const warnings = [];
|
|
26599
27013
|
if (sandbox) warnings.push(`Sandbox: everything here is throwaway (${sandbox.home}) and is deleted when this terminal closes.`);
|
|
26600
27014
|
if (!readout) {
|
|
26601
|
-
console.log(`${reused ? "reusing" : "started"} Frizz
|
|
27015
|
+
console.log(`${reused ? "reusing" : "started"} Frizz for ${workspace.root}`);
|
|
26602
27016
|
console.log(url);
|
|
26603
27017
|
if (publicOrigin) console.log(activeAccessLink?.url ?? `${publicOrigin}/`);
|
|
26604
27018
|
for (const warning of warnings) console.log(warning);
|
|
@@ -26623,31 +27037,40 @@ async function openOrPrint(port, reused, path = "") {
|
|
|
26623
27037
|
}
|
|
26624
27038
|
);
|
|
26625
27039
|
}
|
|
26626
|
-
async function runSupervisor(port, token) {
|
|
27040
|
+
async function runSupervisor(port, token, onPrepared = () => {
|
|
27041
|
+
}) {
|
|
26627
27042
|
assertLaunchPrerequisites();
|
|
26628
|
-
|
|
27043
|
+
if (!serverOwner) throw new Error("stable server launch is missing global ownership");
|
|
26629
27044
|
const owner = adoptProjectLaunchOwner(target, token, "supervisor");
|
|
26630
27045
|
const env = projectLaunchEnvironment(
|
|
26631
27046
|
{
|
|
26632
27047
|
...process.env,
|
|
26633
27048
|
FRIZZ_PRODUCTION_SUPERVISOR: "1",
|
|
27049
|
+
FRIZZ_SERVER_OWNERSHIP: JSON.stringify(projectLaunchEnvironment({}, serverOwner.target, serverOwner.token)),
|
|
26634
27050
|
...logEnvironment(logger, options.debug ? "debug" : "info"),
|
|
26635
27051
|
...options.debug ? { FRIZZ_DEBUG: "1" } : {}
|
|
26636
27052
|
},
|
|
26637
27053
|
target,
|
|
26638
27054
|
owner.token
|
|
26639
27055
|
);
|
|
26640
|
-
const
|
|
26641
|
-
|
|
26642
|
-
|
|
26643
|
-
|
|
26644
|
-
const
|
|
26645
|
-
|
|
27056
|
+
const spec = serverReleaseSpec(
|
|
27057
|
+
JSON.parse(readFileSync15(join17(import.meta.dirname, "..", "package.json"), "utf8")),
|
|
27058
|
+
process.env.FRIZZ_SERVER_PACKAGE
|
|
27059
|
+
);
|
|
27060
|
+
const installer = npmServerPackageInstaller(env);
|
|
27061
|
+
const store = new ServerReleaseStore(spec, installer);
|
|
27062
|
+
activityReadout?.notice("progress", "Starting", "loading the selected Frizz server release");
|
|
27063
|
+
let active = await store.load();
|
|
27064
|
+
let pending;
|
|
27065
|
+
let previous = active;
|
|
27066
|
+
onPrepared();
|
|
26646
27067
|
let updateAvailable = false;
|
|
26647
27068
|
let updateVersion;
|
|
26648
27069
|
const refreshUpdateAvailable = async () => {
|
|
26649
27070
|
try {
|
|
26650
|
-
const
|
|
27071
|
+
const checkedVersion = active.version;
|
|
27072
|
+
const plan = await planRegistryUpdate(spec.package, checkedVersion, installer);
|
|
27073
|
+
if (active.version !== checkedVersion) return;
|
|
26651
27074
|
updateAvailable = plan !== null;
|
|
26652
27075
|
updateVersion = plan?.latestVersion;
|
|
26653
27076
|
} catch {
|
|
@@ -26673,83 +27096,48 @@ async function runSupervisor(port, token) {
|
|
|
26673
27096
|
launchOwnerToken: owner.token,
|
|
26674
27097
|
env,
|
|
26675
27098
|
watch: false,
|
|
26676
|
-
|
|
26677
|
-
|
|
27099
|
+
childLaunchProvider: () => serverGenerationLaunch(pending ?? active),
|
|
27100
|
+
updateMode: "child",
|
|
26678
27101
|
updateAvailable: () => updateAvailable,
|
|
26679
|
-
version:
|
|
27102
|
+
version: () => active.version,
|
|
27103
|
+
launcherVersion: PACKAGE_VERSION,
|
|
26680
27104
|
updateVersion: () => updateVersion,
|
|
26681
27105
|
// The terminal that owns the board says so when the board goes down and comes back. Everything
|
|
26682
27106
|
// here is triggered from a browser tab or by a crash, so without this the foreground process is
|
|
26683
27107
|
// the last place to learn what happened to it.
|
|
26684
27108
|
onActivity: (event) => renderSupervisorActivity(activityReadout, event),
|
|
26685
27109
|
updateRestart: async () => {
|
|
27110
|
+
previous = active;
|
|
26686
27111
|
try {
|
|
26687
|
-
const plan = await planRegistryUpdate(
|
|
27112
|
+
const plan = await planRegistryUpdate(spec.package, active.version, installer);
|
|
26688
27113
|
if (!plan) {
|
|
26689
27114
|
updateAvailable = false;
|
|
26690
27115
|
updateVersion = void 0;
|
|
26691
|
-
return { state: "failed", message: `Frizz ${
|
|
27116
|
+
return { state: "failed", message: `Frizz ${active.version} is already current` };
|
|
26692
27117
|
}
|
|
27118
|
+
updateAvailable = true;
|
|
26693
27119
|
updateVersion = plan.latestVersion;
|
|
26694
|
-
|
|
26695
|
-
return { state: "ready", message: `Frizz ${plan.latestVersion} is installed
|
|
27120
|
+
pending = await store.prepare(plan.latestVersion);
|
|
27121
|
+
return { state: "ready", message: `Frizz ${plan.latestVersion} is installed and compatible` };
|
|
26696
27122
|
} catch (error) {
|
|
26697
27123
|
return { state: "failed", message: error instanceof Error ? error.message : String(error) };
|
|
26698
27124
|
}
|
|
26699
27125
|
},
|
|
26700
|
-
|
|
26701
|
-
|
|
26702
|
-
|
|
26703
|
-
|
|
26704
|
-
|
|
26705
|
-
|
|
27126
|
+
commitUpdate: () => {
|
|
27127
|
+
if (!pending) throw new Error("no server update was prepared");
|
|
27128
|
+
store.commit(pending);
|
|
27129
|
+
active = pending;
|
|
27130
|
+
pending = void 0;
|
|
27131
|
+
updateAvailable = false;
|
|
27132
|
+
updateVersion = void 0;
|
|
26706
27133
|
},
|
|
26707
|
-
|
|
26708
|
-
|
|
26709
|
-
|
|
26710
|
-
|
|
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()) {
|
|
26718
|
-
activityReadout?.notice("progress", "Updating", `reloading this launcher in place on Frizz ${plan.latestVersion}`);
|
|
26719
|
-
paneHost?.dispose();
|
|
26720
|
-
remote?.stop();
|
|
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
|
-
}
|
|
26733
|
-
}
|
|
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
|
-
);
|
|
26750
|
-
process.exit(0);
|
|
27134
|
+
rollbackUpdate: () => {
|
|
27135
|
+
if (active.id !== previous.id) store.commit(previous);
|
|
27136
|
+
active = previous;
|
|
27137
|
+
pending = void 0;
|
|
26751
27138
|
}
|
|
26752
27139
|
});
|
|
27140
|
+
publishStableServerAddress(serverOwner, port);
|
|
26753
27141
|
remote = createRemoteController({ host: supervisor, port, log: logger, say: (message) => console.error(`frizz: ${message}`) });
|
|
26754
27142
|
try {
|
|
26755
27143
|
await remote.serveSaved();
|
|
@@ -26770,16 +27158,14 @@ async function runSupervisor(port, token) {
|
|
|
26770
27158
|
onChanged: (config) => logger.info("remote", config ? `reached at https://${config.hostname}` : "loopback only"),
|
|
26771
27159
|
sandbox: sandbox !== null
|
|
26772
27160
|
});
|
|
26773
|
-
|
|
26774
|
-
const armPaneHost = () => {
|
|
26775
|
-
paneHost = installPaneHost({ bindings });
|
|
26776
|
-
};
|
|
26777
|
-
armPaneHost();
|
|
26778
|
-
rearmPaneHost = armPaneHost;
|
|
27161
|
+
paneHost = installPaneHost({ bindings: { l: accessPane, L: accessPane, r: remotePane, R: remotePane } });
|
|
26779
27162
|
const stop = createSupervisorShutdownHandler({
|
|
26780
27163
|
close: () => supervisor.close(),
|
|
26781
27164
|
force: () => supervisor.forceStop(),
|
|
26782
|
-
release: () =>
|
|
27165
|
+
release: () => {
|
|
27166
|
+
owner.release();
|
|
27167
|
+
if (serverOwner) releaseStableServerOwner(serverOwner);
|
|
27168
|
+
},
|
|
26783
27169
|
// Acknowledge the first signal on the spot; the drain that follows is bounded but not instant.
|
|
26784
27170
|
onStop: () => {
|
|
26785
27171
|
logger.info("launcher", "stop signal received; draining the control plane");
|
|
@@ -26809,17 +27195,28 @@ async function runSupervisor(port, token) {
|
|
|
26809
27195
|
process.on("SIGHUP", stop);
|
|
26810
27196
|
void supervisor.stopRequested.then(stop);
|
|
26811
27197
|
await supervisor.firstBoot;
|
|
27198
|
+
store.commit(active);
|
|
27199
|
+
activityReadout?.notice("done", "Server", `${active.version} \xB7 launcher ${PACKAGE_VERSION}`);
|
|
26812
27200
|
if (reexec) {
|
|
26813
27201
|
activityReadout?.notice(
|
|
26814
27202
|
"done",
|
|
26815
27203
|
"Updated",
|
|
26816
|
-
`Frizz ${
|
|
27204
|
+
`Frizz ${active.version} is serving on port ${port} \xB7 ctrl-c to stop${globalInstall ? ` \xB7 ${keepUpdateHint(PACKAGE_NAME, PACKAGE_VERSION)}` : ""}`
|
|
26817
27205
|
);
|
|
26818
27206
|
}
|
|
26819
27207
|
return await new Promise(() => {
|
|
26820
27208
|
});
|
|
26821
27209
|
}
|
|
26822
27210
|
try {
|
|
27211
|
+
const globalClaim = acquireStableServerOwner();
|
|
27212
|
+
if (globalClaim.kind === "busy") throw new Error("Frizz is starting or recovering on this machine; retry shortly");
|
|
27213
|
+
if (globalClaim.kind === "running") {
|
|
27214
|
+
if (options.port && options.port !== globalClaim.port)
|
|
27215
|
+
throw new Error(`Frizz is already running on port ${globalClaim.port}; --port cannot change a running server`);
|
|
27216
|
+
await openOrPrint(globalClaim.port, true, slugPath());
|
|
27217
|
+
process.exit(0);
|
|
27218
|
+
}
|
|
27219
|
+
serverOwner = globalClaim.lease;
|
|
26823
27220
|
if (process.env.FRIZZ_PRODUCTION_SUPERVISOR === "1" || reexec) {
|
|
26824
27221
|
if (!options.port) throw new Error("internal registry supervisor launch is missing --port");
|
|
26825
27222
|
const token = projectLaunchOwnerTokenFromEnvironment(process.env);
|
|
@@ -26844,9 +27241,14 @@ try {
|
|
|
26844
27241
|
const allocation = await allocatePort(options.port, readPreferredPort(workspace.stateDir), { host: LOOPBACK_BIND_HOST });
|
|
26845
27242
|
const port = allocation.port;
|
|
26846
27243
|
portReservation = allocation.release;
|
|
26847
|
-
|
|
27244
|
+
let didPrepare;
|
|
27245
|
+
const prepared = new Promise((resolve7) => {
|
|
27246
|
+
didPrepare = resolve7;
|
|
27247
|
+
});
|
|
27248
|
+
const running = runSupervisor(port, claim.lease.token, didPrepare);
|
|
26848
27249
|
release();
|
|
26849
27250
|
release = void 0;
|
|
27251
|
+
await Promise.race([prepared, running]);
|
|
26850
27252
|
await Promise.race([
|
|
26851
27253
|
waitForWorkspace(
|
|
26852
27254
|
port,
|