frizz-server 0.14.0 → 0.14.2

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.
Files changed (92) hide show
  1. package/dist/claude-agent-broker.js +10859 -10590
  2. package/dist/dev-child.js +91 -57
  3. package/package.json +1 -1
  4. package/web-dist/assets/{TerminalPane-DcNJcvz9.js → TerminalPane-ftTy20h9.js} +1 -1
  5. package/web-dist/assets/{abnfDiagram-VRR7QNED-BFKPkR0J.js → abnfDiagram-VRR7QNED-DPYIADCF.js} +1 -1
  6. package/web-dist/assets/architecture-TIHT7OUA-C4ce4EvA.js +1 -0
  7. package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-BugbGvF7.js → architectureDiagram-ZJ3FMSHR-CslwHJ59.js} +1 -1
  8. package/web-dist/assets/{blockDiagram-677ZJIJ3-B1drPHOm.js → blockDiagram-677ZJIJ3-C_YKDTK3.js} +1 -1
  9. package/web-dist/assets/{c4Diagram-LMCZKHZV-jA8etf56.js → c4Diagram-LMCZKHZV-CN2XoHEM.js} +1 -1
  10. package/web-dist/assets/channel-46DdEyrY.js +1 -0
  11. package/web-dist/assets/{chunk-32BRIVSS-BfMUf_Yy.js → chunk-32BRIVSS-CqQFWcuW.js} +1 -1
  12. package/web-dist/assets/{chunk-52WLFC77-Fo52YmmC.js → chunk-52WLFC77-DIA4ep-j.js} +1 -1
  13. package/web-dist/assets/{chunk-C7G6YPKG-CPiVGUnC.js → chunk-C7G6YPKG-uYEufieL.js} +1 -1
  14. package/web-dist/assets/{chunk-EX3LRPZG-DllbzsPn.js → chunk-EX3LRPZG-Ctuj9M07.js} +1 -1
  15. package/web-dist/assets/{chunk-FWX5IMBZ-Cr7SCNOQ.js → chunk-FWX5IMBZ-BSeGDrvG.js} +2 -2
  16. package/web-dist/assets/{chunk-HOUHSVGY-D2qjbRMK.js → chunk-HOUHSVGY-DFtB1XOE.js} +1 -1
  17. package/web-dist/assets/{chunk-ICXQ74PX-Dl8ZZqX4.js → chunk-ICXQ74PX-DvvNMH3B.js} +1 -1
  18. package/web-dist/assets/{chunk-MOJQB5TN-C7X9x33F.js → chunk-MOJQB5TN-blCgZYTp.js} +1 -1
  19. package/web-dist/assets/{chunk-OGEWGWER-DrlPoLRT.js → chunk-OGEWGWER-DiKWBhls.js} +1 -1
  20. package/web-dist/assets/{chunk-PUDLZKDR-C1WS3qVH.js → chunk-PUDLZKDR-CEZ-LRny.js} +1 -1
  21. package/web-dist/assets/{chunk-Q4XR5HBZ-CNhqnN4i.js → chunk-Q4XR5HBZ-BO1Y_Z4a.js} +1 -1
  22. package/web-dist/assets/{chunk-V7JOEXUC-BQsiP60Y.js → chunk-V7JOEXUC-ouWDihRg.js} +1 -1
  23. package/web-dist/assets/{chunk-VAUOI2AC-DeQswo6G.js → chunk-VAUOI2AC-DCCN8ceH.js} +1 -1
  24. package/web-dist/assets/{chunk-VR4S4FIN-QCzpzy3F.js → chunk-VR4S4FIN-D8VxxNLW.js} +1 -1
  25. package/web-dist/assets/{chunk-WYO6CB5R-DYEAXxaM.js → chunk-WYO6CB5R-_B7FSzZM.js} +1 -1
  26. package/web-dist/assets/{chunk-ZGVPDNZ5-BRwJsVqD.js → chunk-ZGVPDNZ5-BErRylCv.js} +1 -1
  27. package/web-dist/assets/classDiagram-OUVF2IWQ-BvKONN2o.js +1 -0
  28. package/web-dist/assets/classDiagram-v2-EOCWNBFH-BvKONN2o.js +1 -0
  29. package/web-dist/assets/{cynefin-VYW2F7L2-DFY4wScy.js → cynefin-VYW2F7L2-CgH8n1RK.js} +1 -1
  30. package/web-dist/assets/{cynefinDiagram-TSTJHNR4-BFd6vF05.js → cynefinDiagram-TSTJHNR4-Cp3iB5ig.js} +1 -1
  31. package/web-dist/assets/{dagre-VKFMJZFB-BTSZ-kNz.js → dagre-VKFMJZFB-DEJ5M2UQ.js} +1 -1
  32. package/web-dist/assets/{diagram-FQU43EPY-CM5L_Teo.js → diagram-FQU43EPY-B7TBBYyA.js} +1 -1
  33. package/web-dist/assets/{diagram-G47NLZAW-DMEMjhev.js → diagram-G47NLZAW-Djy0qteu.js} +1 -1
  34. package/web-dist/assets/{diagram-NH7WQ7WH-BINXDe2x.js → diagram-NH7WQ7WH-C7ASxlCE.js} +1 -1
  35. package/web-dist/assets/{diagram-OA4YK3LP-DhKBXS5G.js → diagram-OA4YK3LP-DQs7Hn4c.js} +1 -1
  36. package/web-dist/assets/{diagram-WEI45ONY-QaICPLa1.js → diagram-WEI45ONY-DvjYq10q.js} +1 -1
  37. package/web-dist/assets/{ebnfDiagram-CCIWWBDH-DDQ6NAEt.js → ebnfDiagram-CCIWWBDH-D5dvO41S.js} +1 -1
  38. package/web-dist/assets/{erDiagram-Q63AITRT-eftnFvxT.js → erDiagram-Q63AITRT-DGMDAMz2.js} +1 -1
  39. package/web-dist/assets/eventmodeling-45OFAUF4-eNNW0zlr.js +1 -0
  40. package/web-dist/assets/flowDiagram-23GEKE2U-C5RJ-lqT.js +1 -0
  41. package/web-dist/assets/{ganttDiagram-NO4QXBWP-CBUUxbvO.js → ganttDiagram-NO4QXBWP-DE4sBbug.js} +1 -1
  42. package/web-dist/assets/{gitGraph-TEB2WS4Q-B4j6N6bC.js → gitGraph-TEB2WS4Q-6iwymAqh.js} +1 -1
  43. package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-mrIlQ6c3.js → gitGraphDiagram-IHSO6WYX-B8M8HMMa.js} +1 -1
  44. package/web-dist/assets/{index-BI0k4RW8.js → index-C-jkL60P.js} +85 -85
  45. package/web-dist/assets/index-D0gz-Bx-.css +1 -0
  46. package/web-dist/assets/{info-DKCQHKI2-Dj4G-7Y8.js → info-DKCQHKI2-D1rdRKv2.js} +1 -1
  47. package/web-dist/assets/{infoDiagram-FWYZ7A6U-Baz07f6h.js → infoDiagram-FWYZ7A6U-DfXxAWG-.js} +1 -1
  48. package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-C4og8CF4.js → ishikawaDiagram-FXEZZL3T-C6huyjB4.js} +1 -1
  49. package/web-dist/assets/{journeyDiagram-5HDEW3XC-B0WV30vH.js → journeyDiagram-5HDEW3XC-Cz0dAdxo.js} +1 -1
  50. package/web-dist/assets/{kanban-definition-HUTT4EX6-BgDiY6B1.js → kanban-definition-HUTT4EX6-CnOJ2JGq.js} +1 -1
  51. package/web-dist/assets/{line-D0SxxXfr.js → line-BsyJpb4L.js} +1 -1
  52. package/web-dist/assets/{mermaid-parser.core-CWj7pjCH.js → mermaid-parser.core-B2YDnnfc.js} +3 -3
  53. package/web-dist/assets/{mermaid.core-Dpi4Z-WK.js → mermaid.core-DZmxOzX_.js} +3 -3
  54. package/web-dist/assets/{mindmap-definition-LN4V7U3C-DLmQQ7LC.js → mindmap-definition-LN4V7U3C-C-cB8iLg.js} +1 -1
  55. package/web-dist/assets/{packet-7NZHBO7P-T7pVIfFz.js → packet-7NZHBO7P-ByYSVaHA.js} +1 -1
  56. package/web-dist/assets/{pegDiagram-2B236MQR-BvVxzZmj.js → pegDiagram-2B236MQR-CiIbvo6V.js} +1 -1
  57. package/web-dist/assets/{pie-RZYD4A2V-BGz-hjIz.js → pie-RZYD4A2V-DT0L5Lbg.js} +1 -1
  58. package/web-dist/assets/{pieDiagram-ENE6RG2P-pdOHyNTd.js → pieDiagram-ENE6RG2P-BpX1rkMn.js} +1 -1
  59. package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-fLy3coW3.js → quadrantDiagram-ABIIQ3AL-Bl6eITpX.js} +1 -1
  60. package/web-dist/assets/{radar-I7S5WNFK-C-VKX4OE.js → radar-I7S5WNFK-Dc5znSZ_.js} +1 -1
  61. package/web-dist/assets/{railroad-3IZDKUUU-BwC-mtji.js → railroad-3IZDKUUU-Ho4iVXCL.js} +1 -1
  62. package/web-dist/assets/railroad-abnf-AHOZXSZD-JkQWwE17.js +1 -0
  63. package/web-dist/assets/railroad-ebnf-EBAXGLYW-grVU10Bk.js +1 -0
  64. package/web-dist/assets/railroad-peg-LSFZ7HO6-BTqoHLa0.js +1 -0
  65. package/web-dist/assets/{railroadDiagram-RFXS5EU6-BxPp9neb.js → railroadDiagram-RFXS5EU6-D5afWytG.js} +1 -1
  66. package/web-dist/assets/{requirementDiagram-TGXJPOKE-P_BvOjKp.js → requirementDiagram-TGXJPOKE-0L5V-_bC.js} +1 -1
  67. package/web-dist/assets/{sankeyDiagram-HTMAVEWB-DUv1nZCv.js → sankeyDiagram-HTMAVEWB-CH-xRkM4.js} +1 -1
  68. package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-DWNx793M.js → sequenceDiagram-DBY2YBRQ-CMUPviAU.js} +1 -1
  69. package/web-dist/assets/{stateDiagram-2N3HPSRC-CaOUtkvy.js → stateDiagram-2N3HPSRC-ayE6u0KZ.js} +1 -1
  70. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-DAjtM6iw.js +1 -0
  71. package/web-dist/assets/{swimlanes-5IMT3BWC-D764GMah.js → swimlanes-5IMT3BWC-BggKIJzJ.js} +1 -1
  72. package/web-dist/assets/swimlanesDiagram-G3AALYLV-BS0jxTx_.js +8 -0
  73. package/web-dist/assets/{timeline-definition-FHXFAJF6-DeKz_jJG.js → timeline-definition-FHXFAJF6-B4mcBscv.js} +1 -1
  74. package/web-dist/assets/{treeView-QDETBFTQ-D3UnDOk3.js → treeView-QDETBFTQ-DAH6PHIx.js} +1 -1
  75. package/web-dist/assets/{treemap-6X3UGDF4-VItEAzU3.js → treemap-6X3UGDF4-CUipyr2w.js} +1 -1
  76. package/web-dist/assets/{vennDiagram-L72KCM5P-DuzNjZFZ.js → vennDiagram-L72KCM5P-CuKqAm0J.js} +1 -1
  77. package/web-dist/assets/{wardley-OPB4EBWU-B1uIoPVb.js → wardley-OPB4EBWU-D5Wfkjy9.js} +1 -1
  78. package/web-dist/assets/{wardleyDiagram-EHGQE667-H60TjU5y.js → wardleyDiagram-EHGQE667-M5MDAf53.js} +1 -1
  79. package/web-dist/assets/{xychartDiagram-FW5EYKEG-BqTqYEwv.js → xychartDiagram-FW5EYKEG-BaSJmtNq.js} +1 -1
  80. package/web-dist/index.html +2 -2
  81. package/web-dist/assets/architecture-TIHT7OUA-3cEHc0mh.js +0 -1
  82. package/web-dist/assets/channel-BYQQkw21.js +0 -1
  83. package/web-dist/assets/classDiagram-OUVF2IWQ-BgM58S9B.js +0 -1
  84. package/web-dist/assets/classDiagram-v2-EOCWNBFH-BgM58S9B.js +0 -1
  85. package/web-dist/assets/eventmodeling-45OFAUF4-KZNoVoEu.js +0 -1
  86. package/web-dist/assets/flowDiagram-23GEKE2U-m4sDfmpP.js +0 -1
  87. package/web-dist/assets/index-CzN-tCOl.css +0 -1
  88. package/web-dist/assets/railroad-abnf-AHOZXSZD-CNsCN0k6.js +0 -1
  89. package/web-dist/assets/railroad-ebnf-EBAXGLYW-Bjabtkan.js +0 -1
  90. package/web-dist/assets/railroad-peg-LSFZ7HO6-DjPlt8Lc.js +0 -1
  91. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-CbgDxwEv.js +0 -1
  92. package/web-dist/assets/swimlanesDiagram-G3AALYLV-QPzvJba6.js +0 -8
package/dist/dev-child.js CHANGED
@@ -20915,8 +20915,8 @@ var init_settings = __esm({
20915
20915
  MachineSettingsRecord = Settings.partial();
20916
20916
  defaultSettings = () => ({
20917
20917
  // `bypassPermissions` = claude's --dangerously-skip-permissions: a headless worker never stops on an
20918
- // approval card. Shipped default since 0.7.2 (maintainer 2026-08-24); the Settings "Permissions"
20919
- // (under Claude) control can lower it to `auto` — the CLI's classifier mode, where risky actions
20918
+ // approval card. Shipped default since 0.7.2 (maintainer 2026-08-24); the "Permissions" control
20919
+ // behind the Claude Code gear in the model picker can lower it to `auto` — the CLI's classifier mode, where risky actions
20920
20920
  // still surface an approval card in the thread. Those are the only two values a headless worker can
20921
20921
  // run in: the dispatch floor (WORKER_DISPATCH_PERMISSION) stays `auto`, and workerDispatchPermission
20922
20922
  // honors exactly one deviation from it, which is this one.
@@ -30508,14 +30508,18 @@ function tomlString(value) {
30508
30508
  function inlineTable(entries2) {
30509
30509
  return `{${entries2.map(([k, v]) => `${k}=${v}`).join(",")}}`;
30510
30510
  }
30511
- function serverTable(command, args, env) {
30511
+ function serverTable(command, args, cwd, env) {
30512
30512
  const entries2 = [
30513
30513
  ["command", tomlString(command)],
30514
- ["args", `[${args.map(tomlString).join(",")}]`]
30514
+ ["args", `[${args.map(tomlString).join(",")}]`],
30515
+ // Where the child RUNS, pinned so it never depends on the thread's own cwd — see
30516
+ // codexThreadMcpConfig for the rename that took a thread's tools with it.
30517
+ ["cwd", tomlString(cwd)]
30515
30518
  ];
30516
30519
  if (env && Object.keys(env).length > 0) {
30517
30520
  entries2.push(["env", inlineTable(Object.entries(env).map(([k, v]) => [k, tomlString(v)]))]);
30518
30521
  }
30522
+ entries2.push(["default_tools_approval_mode", tomlString("approve")]);
30519
30523
  return inlineTable(entries2);
30520
30524
  }
30521
30525
  function codexMcpConfigArgs(frizzMcp, nodeBin = process.execPath) {
@@ -30523,7 +30527,7 @@ function codexMcpConfigArgs(frizzMcp, nodeBin = process.execPath) {
30523
30527
  if (frizzMcp) {
30524
30528
  args.push(
30525
30529
  "-c",
30526
- `mcp_servers.${FRIZZ_MCP.name}=${serverTable(nodeBin, [frizzMcp.scriptPath], frizzMcpEnv(frizzMcp))}`
30530
+ `mcp_servers.${FRIZZ_MCP.name}=${serverTable(nodeBin, [frizzMcp.scriptPath], frizzMcp.stateDir, frizzMcpEnv(frizzMcp))}`
30527
30531
  );
30528
30532
  }
30529
30533
  args.push("-c", `default_tools_approval_mode=${tomlString("approve")}`);
@@ -30537,6 +30541,7 @@ function codexThreadMcpConfig(frizzMcp, slug, nodeBin = process.execPath) {
30537
30541
  // The ABSOLUTE node path, for the same reason the argv mount pins it — see codexMcpConfigArgs.
30538
30542
  command: nodeBin,
30539
30543
  args: [frizzMcp.scriptPath],
30544
+ cwd: frizzMcp.stateDir,
30540
30545
  env: frizzMcpEnv({ ...frizzMcp, slug }),
30541
30546
  default_tools_approval_mode: "approve"
30542
30547
  }
@@ -31822,6 +31827,7 @@ var init_codex_execution_health = __esm({
31822
31827
 
31823
31828
  // packages/server/src/backend/codex-app-server.ts
31824
31829
  import { createHash as createHash10, randomUUID as randomUUID11 } from "node:crypto";
31830
+ import { existsSync as existsSync8 } from "node:fs";
31825
31831
  import { StringDecoder as StringDecoder3 } from "node:string_decoder";
31826
31832
  function selectCodexHostKind(flagValue, platform3, hasSpawn) {
31827
31833
  if (hasSpawn) return "direct";
@@ -32486,11 +32492,11 @@ var init_codex_app_server = __esm({
32486
32492
  init_logging();
32487
32493
  CODEX_APP_SERVER_PROVIDER = "codex-app-server";
32488
32494
  CODEX_NATIVE_LISTEN_FLAG = "FRIZZ_CODEX_NATIVE_LISTEN";
32489
- CODEX_APP_SERVER_SUPPORTED_VERSION = "0.155.0";
32495
+ CODEX_APP_SERVER_SUPPORTED_VERSION = "0.155.1";
32490
32496
  CODEX_APP_SERVER_PROTOCOL_REVISION = Object.freeze({
32491
32497
  packageVersion: CODEX_APP_SERVER_SUPPORTED_VERSION,
32492
- sourceTag: "rust-v0.155.0",
32493
- sourceCommit: "f0a1b8f0849d90960bc406b848f32e5a129b0457"
32498
+ sourceTag: "rust-v0.155.1",
32499
+ sourceCommit: "be2951ea34f0d295ed0becf97079f92fa5f6950e"
32494
32500
  });
32495
32501
  PROTOCOL_FINGERPRINT = [
32496
32502
  CODEX_APP_SERVER_PROTOCOL_REVISION.sourceTag,
@@ -33194,11 +33200,13 @@ var init_codex_app_server = __esm({
33194
33200
  }
33195
33201
  if (binding.state === "active" && binding.connection_epoch === this.connectionEpoch) return bindingFromRow(binding);
33196
33202
  if (binding.ephemeral === 1) throw new Error("disposable Codex app-server session is detached");
33203
+ const cwdOverride = this.resumeCwdOverride(binding);
33197
33204
  const rawResponse = await connection.request("thread/resume", {
33198
33205
  threadId: binding.codex_thread_id,
33199
33206
  excludeTurns: true,
33200
33207
  approvalsReviewer: "user",
33201
33208
  ...this.resumeSandboxOverride(binding),
33209
+ ...cwdOverride,
33202
33210
  // A resume by an app-server that ALREADY holds this thread keeps the MCP child it started
33203
33211
  // with, so this changes nothing there. It matters on a resume by a FRESH app-server — the
33204
33212
  // one after a daemon death or a frizz restart — which is exactly when the thread would
@@ -33210,6 +33218,7 @@ var init_codex_app_server = __esm({
33210
33218
  throw new Error("Codex app-server resumed a different or disposable thread");
33211
33219
  }
33212
33220
  this.updateResumedBinding(binding, response.thread.sessionId, effectiveResumeSandbox(rawResponse));
33221
+ this.recordResumedCwd(binding, cwdOverride);
33213
33222
  return bindingFromRow(this.bindingForScope(threadSlug, sessionId));
33214
33223
  } finally {
33215
33224
  releaseOperation();
@@ -34024,14 +34033,26 @@ var init_codex_app_server = __esm({
34024
34033
  continue;
34025
34034
  }
34026
34035
  try {
34036
+ const cwdOverride = this.resumeCwdOverride(row);
34027
34037
  const rawResponse = await connection.request("thread/resume", {
34028
34038
  threadId: row.codex_thread_id,
34029
34039
  excludeTurns: true,
34030
34040
  approvalsReviewer: "user",
34031
- ...this.resumeSandboxOverride(row)
34041
+ ...this.resumeSandboxOverride(row),
34042
+ ...cwdOverride,
34043
+ // The per-thread frizz MCP mount, exactly as resumeOwnedSession sends it. THIS is the resume a
34044
+ // Frizz restart issues for every thread that was mid-turn when the app-server died, and it
34045
+ // was the one resume that did not carry it (2026-09-18, hypergres/this-is-a-fresh-project-i:
34046
+ // the 0.13.9 restart replaced the daemon, this path resumed the thread with no mount, and the
34047
+ // worker's next registry probe listed no `mcp__frizz__*` at all — "The restart removed
34048
+ // Frizz's question-registration tool"). The argv mount is not a fallback here: a thread
34049
+ // resumed onto a FRESH app-server gets its MCP children from this call, so without the
34050
+ // override it keeps neither its identity nor, in practice, the tools.
34051
+ ...this.threadConfig(row.thread_slug)
34032
34052
  });
34033
34053
  const response = ThreadResponse.parse(rawResponse);
34034
34054
  if (response.thread.id !== row.codex_thread_id || response.thread.ephemeral) throw new Error("resume ownership mismatch");
34055
+ this.recordResumedCwd(row, cwdOverride);
34035
34056
  const interruptedTurn = row.current_turn_id;
34036
34057
  if (interruptedTurn && row.capability_revision === this.capabilityRevision && resumedThreadHasLiveTurn(rawResponse)) {
34037
34058
  this.scope.prepare(`
@@ -34197,6 +34218,29 @@ var init_codex_app_server = __esm({
34197
34218
  const intent = (isCodexSandboxMode(row.intended_sandbox) ? row.intended_sandbox : void 0) ?? this.options.sandboxFor?.(row.thread_slug, row.frizz_session_id) ?? CODEX_DEFAULT_SANDBOX;
34198
34219
  return { sandbox: intent, approvalPolicy: CODEX_APPROVAL_POLICY };
34199
34220
  }
34221
+ /**
34222
+ * The `cwd` to attach to a `thread/resume` — and only when the recorded one is GONE.
34223
+ *
34224
+ * A thread's cwd is fixed at thread/start and every resume reads it back from the rollout. A project
34225
+ * directory rename (3baa6371 reopens the project at its new path) leaves every existing codex thread
34226
+ * recorded at a path that no longer exists, and codex does not merely fail the thread's next command:
34227
+ * it spawns NO stdio MCP child for the thread at all, so the worker's registry lists no
34228
+ * `mcp__frizz__*` and it cannot ask, sign off or name itself. Measured 2026-09-18 with
34229
+ * `_live_codex_resume_mcp.mts` (`STALE_CWD=1`: no child spawned, the model answers NOTOOL) after
34230
+ * hypergres → porg took `this-is-a-fresh-project-i` down exactly that way. `thread/resume` takes a
34231
+ * `cwd` override, so a resume whose recorded cwd is missing retargets the thread at the project's
34232
+ * CURRENT directory — the only path a frizz worker was ever dispatched into — and the binding is
34233
+ * re-recorded on success (recordResumedCwd). A cwd that still exists is left alone: an adopted
34234
+ * external rollout may legitimately live somewhere else.
34235
+ */
34236
+ resumeCwdOverride(row) {
34237
+ if (existsSync8(row.cwd)) return {};
34238
+ return { cwd: this.options.projectDir };
34239
+ }
34240
+ recordResumedCwd(row, override) {
34241
+ if (!override.cwd) return;
34242
+ this.scope.prepare("UPDATE codex_app_server_session SET cwd = ?, updated_at = ? WHERE project_id = @project_id AND frizz_session_id = ?").run(override.cwd, this.now().toISOString(), row.frizz_session_id);
34243
+ }
34200
34244
  /**
34201
34245
  * Change a LIVE thread's sandbox, eagerly, without waiting for a resume.
34202
34246
  *
@@ -35251,7 +35295,7 @@ var init_local_path = __esm({
35251
35295
 
35252
35296
  // packages/server/src/local-file.ts
35253
35297
  import { spawn as spawn5 } from "node:child_process";
35254
- import { existsSync as existsSync8, readFileSync as readFileSync18, realpathSync as realpathSync6, statSync as statSync13 } from "node:fs";
35298
+ import { existsSync as existsSync9, readFileSync as readFileSync18, realpathSync as realpathSync6, statSync as statSync13 } from "node:fs";
35255
35299
  import { homedir as homedir11 } from "node:os";
35256
35300
  import { dirname as dirname10, isAbsolute as isAbsolute4, join as join26, resolve as resolve5, sep as sep2 } from "node:path";
35257
35301
  function isUnder(real, root) {
@@ -35354,7 +35398,7 @@ function localFileOpenCommand(path3, selected, options = {}) {
35354
35398
  if (selected === "finder") return { command: "explorer.exe", args: [`/select,${path3}`] };
35355
35399
  const editor = WINDOWS_EDITOR_EXE[selected];
35356
35400
  const env = options.env ?? process.env;
35357
- const exists = options.exists ?? existsSync8;
35401
+ const exists = options.exists ?? existsSync9;
35358
35402
  const localAppData = env.LOCALAPPDATA;
35359
35403
  if (localAppData) {
35360
35404
  const exe = join26(localAppData, ...editor.exe);
@@ -35716,17 +35760,17 @@ var init_project_mcp_servers = __esm({
35716
35760
  });
35717
35761
 
35718
35762
  // packages/server/src/worker-plugin-dir.ts
35719
- import { existsSync as existsSync9 } from "node:fs";
35763
+ import { existsSync as existsSync10 } from "node:fs";
35720
35764
  import { dirname as dirname12, join as join29 } from "node:path";
35721
35765
  import { fileURLToPath as fileURLToPath3 } from "node:url";
35722
35766
  function resolveWorkerPluginDir(moduleUrl = import.meta.url, env = process.env) {
35723
35767
  const override = env.FRIZZ_WORKER_PLUGIN_DIR;
35724
- if (override && existsSync9(join29(override, ".claude-plugin", "plugin.json")))
35768
+ if (override && existsSync10(join29(override, ".claude-plugin", "plugin.json")))
35725
35769
  return override;
35726
35770
  let current = dirname12(fileURLToPath3(moduleUrl));
35727
35771
  for (; ; ) {
35728
35772
  const candidate = join29(current, "cc-worker");
35729
- if (existsSync9(join29(candidate, ".claude-plugin", "plugin.json"))) return candidate;
35773
+ if (existsSync10(join29(candidate, ".claude-plugin", "plugin.json"))) return candidate;
35730
35774
  const parent = dirname12(current);
35731
35775
  if (parent === current) return void 0;
35732
35776
  current = parent;
@@ -37699,7 +37743,7 @@ var init_claude_agent_broker_bridge = __esm({
37699
37743
  });
37700
37744
 
37701
37745
  // packages/server/src/dispatch.ts
37702
- import { closeSync as closeSync12, constants as constants2, existsSync as existsSync10, fstatSync as fstatSync2, lstatSync as lstatSync3, openSync as openSync13, readFileSync as readFileSync20, realpathSync as realpathSync8, statSync as statSync15, writeFileSync as writeFileSync10, mkdirSync as mkdirSync13, rmSync as rmSync9 } from "node:fs";
37746
+ import { closeSync as closeSync12, constants as constants2, existsSync as existsSync11, fstatSync as fstatSync2, lstatSync as lstatSync3, openSync as openSync13, readFileSync as readFileSync20, realpathSync as realpathSync8, statSync as statSync15, writeFileSync as writeFileSync10, mkdirSync as mkdirSync13, rmSync as rmSync9 } from "node:fs";
37703
37747
  import { basename as basename6, join as join31, dirname as dirname13 } from "node:path";
37704
37748
  import { createHash as createHash11, randomUUID as randomUUID13 } from "node:crypto";
37705
37749
  function fallbackTitle(prompt) {
@@ -37719,7 +37763,7 @@ function fallbackTitle(prompt) {
37719
37763
  }
37720
37764
  function resolveSlug(frizzDir, base, taken) {
37721
37765
  base = ThreadSlug.parse(base);
37722
- const isTaken = (slug) => existsSync10(join31(frizzDir, `${slug}.md`)) || (taken?.(slug) ?? false);
37766
+ const isTaken = (slug) => existsSync11(join31(frizzDir, `${slug}.md`)) || (taken?.(slug) ?? false);
37723
37767
  if (!isTaken(base)) return base;
37724
37768
  for (let n = 2; ; n++) {
37725
37769
  const suffix = `-${n}`;
@@ -37816,7 +37860,7 @@ function monitorScriptsDir() {
37816
37860
  const plugin = workerPluginDir();
37817
37861
  if (!plugin) return void 0;
37818
37862
  const dir = join31(plugin, "skills", "gh", "scripts");
37819
- return existsSync10(join31(dir, "ci-watch.mjs")) ? dir : void 0;
37863
+ return existsSync11(join31(dir, "ci-watch.mjs")) ? dir : void 0;
37820
37864
  }
37821
37865
  function codexScratchpadHookConfig(hookScript, sessionId) {
37822
37866
  if (!hookScript || !sessionId) return {};
@@ -37915,7 +37959,7 @@ function resolveFrizzMcp(target, moduleUrl = import.meta.url, env = process.env,
37915
37959
  const pluginDir = resolveWorkerPluginDir(moduleUrl, env);
37916
37960
  if (!pluginDir) return void 0;
37917
37961
  const scriptPath = join31(pluginDir, "bin", FRIZZ_MCP.script);
37918
- if (!existsSync10(scriptPath)) return void 0;
37962
+ if (!existsSync11(scriptPath)) return void 0;
37919
37963
  return {
37920
37964
  scriptPath,
37921
37965
  stateDir,
@@ -42368,7 +42412,7 @@ var init_claude = __esm({
42368
42412
  });
42369
42413
 
42370
42414
  // packages/server/src/backend/acp-transcript.ts
42371
- import { appendFileSync as appendFileSync3, existsSync as existsSync12, mkdirSync as mkdirSync14, readFileSync as readFileSync21 } from "node:fs";
42415
+ import { appendFileSync as appendFileSync3, existsSync as existsSync13, mkdirSync as mkdirSync14, readFileSync as readFileSync21 } from "node:fs";
42372
42416
  import { dirname as dirname15, join as join34 } from "node:path";
42373
42417
  function acpTranscriptPath(stateDir, sessionId) {
42374
42418
  return join34(stateDir, ACP_TRANSCRIPT_DIR, `${sessionId}.jsonl`);
@@ -42573,7 +42617,7 @@ var init_acp_transcript = __esm({
42573
42617
  constructor(path3) {
42574
42618
  this.path = path3;
42575
42619
  mkdirSync14(dirname15(path3), { recursive: true });
42576
- if (!existsSync12(path3)) appendFileSync3(path3, "");
42620
+ if (!existsSync13(path3)) appendFileSync3(path3, "");
42577
42621
  }
42578
42622
  append(record) {
42579
42623
  appendFileSync3(this.path, JSON.stringify(record) + "\n");
@@ -47500,7 +47544,7 @@ var init_server = __esm({
47500
47544
  });
47501
47545
 
47502
47546
  // packages/server/src/repair.ts
47503
- import { existsSync as existsSync13, readFileSync as readFileSync23, writeFileSync as writeFileSync11 } from "node:fs";
47547
+ import { existsSync as existsSync14, readFileSync as readFileSync23, writeFileSync as writeFileSync11 } from "node:fs";
47504
47548
  import { basename as basename7, dirname as dirname17, resolve as resolve8 } from "node:path";
47505
47549
  function quoteValue(v) {
47506
47550
  if (/^[\w./#:+-]+$/.test(v)) return v;
@@ -47515,7 +47559,7 @@ function repairThreadFile(frizzDir, file) {
47515
47559
  const abs = resolve8(root, file);
47516
47560
  if (dirname17(abs) !== root) throw new RepairError(`refusing to repair "${file}": not directly under .frizz/`);
47517
47561
  if (!abs.endsWith(".md")) throw new RepairError(`refusing to repair "${file}": not a .md thread file`);
47518
- if (!existsSync13(abs)) throw new RepairError(`no thread file to repair: ${basename7(abs)}`);
47562
+ if (!existsSync14(abs)) throw new RepairError(`no thread file to repair: ${basename7(abs)}`);
47519
47563
  const content = readFileSync23(abs, "utf8");
47520
47564
  const firstLine2 = content.replace(/^/, "").split(/\r?\n/).find((l) => l.trim() !== "");
47521
47565
  if (firstLine2?.trim() === "---") {
@@ -47873,7 +47917,7 @@ var init_bash_background = __esm({
47873
47917
  });
47874
47918
 
47875
47919
  // packages/server/src/transcript.ts
47876
- import { closeSync as closeSync13, existsSync as existsSync14, fstatSync as fstatSync3, mkdirSync as mkdirSync16, openSync as openSync14, readdirSync as readdirSync9, readFileSync as readFileSync25, readSync as readSync7, renameSync as renameSync9, statSync as statSync17, unlinkSync as unlinkSync5, writeFileSync as writeFileSync12 } from "node:fs";
47920
+ import { closeSync as closeSync13, existsSync as existsSync15, fstatSync as fstatSync3, mkdirSync as mkdirSync16, openSync as openSync14, readdirSync as readdirSync9, readFileSync as readFileSync25, readSync as readSync7, renameSync as renameSync9, statSync as statSync17, unlinkSync as unlinkSync5, writeFileSync as writeFileSync12 } from "node:fs";
47877
47921
  import { createHash as createHash13 } from "node:crypto";
47878
47922
  import { StringDecoder as StringDecoder5 } from "node:string_decoder";
47879
47923
  import { join as join38 } from "node:path";
@@ -48495,7 +48539,7 @@ function persistBase64Image(mediaType, data, idKey) {
48495
48539
  const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
48496
48540
  const path3 = join38(SCREENSHOT_CACHE_DIR, `${name}.${ext}`);
48497
48541
  try {
48498
- if (existsSync14(path3)) return path3;
48542
+ if (existsSync15(path3)) return path3;
48499
48543
  if (data.length > SCREENSHOT_MAX_BASE64) return void 0;
48500
48544
  const buf = Buffer.from(data, "base64");
48501
48545
  if (buf.length === 0 || !looksLikeImage(buf, ext)) return void 0;
@@ -48516,7 +48560,7 @@ function persistSentFile(srcPath, idKey) {
48516
48560
  try {
48517
48561
  const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
48518
48562
  const dest = join38(SCREENSHOT_CACHE_DIR, `${name}.${outExt}`);
48519
- if (existsSync14(dest)) return dest;
48563
+ if (existsSync15(dest)) return dest;
48520
48564
  const size = statSync17(srcPath).size;
48521
48565
  if (size === 0 || size > SENT_IMAGE_MAX_BYTES) return void 0;
48522
48566
  const buf = readFileSync25(srcPath);
@@ -50057,7 +50101,7 @@ function sourceForThread(project, storage, slug, backendFor) {
50057
50101
  }
50058
50102
  if (!FOREIGN_SESSION_ID_RE.test(slug)) return void 0;
50059
50103
  const claudePath = resolveTranscriptPath(project, slug);
50060
- if (existsSync14(claudePath)) {
50104
+ if (existsSync15(claudePath)) {
50061
50105
  return { slug, sessionId: slug, nativeId: slug, backend: "claude", runtimeGeneration: 0, path: claudePath };
50062
50106
  }
50063
50107
  const rollout = (backendFor?.("codex") ?? defaultCodexBackend()).transcriptPath(slug);
@@ -51195,7 +51239,7 @@ import { readFileSync as readFileSync26, statSync as statSync19 } from "node:fs"
51195
51239
  import { join as join39, resolve as resolve9 } from "node:path";
51196
51240
  import { randomUUID as randomUUID16 } from "node:crypto";
51197
51241
  import { basename as basename9, dirname as dirname18 } from "node:path";
51198
- import { existsSync as existsSync15, mkdirSync as mkdirSync17, rmSync as rmSync10, writeFileSync as writeFileSync13 } from "node:fs";
51242
+ import { existsSync as existsSync16, mkdirSync as mkdirSync17, rmSync as rmSync10, writeFileSync as writeFileSync13 } from "node:fs";
51199
51243
  import { homedir as homedir17 } from "node:os";
51200
51244
  function validateGithubDispatchProfile(input) {
51201
51245
  if (input.backend === "acp") return;
@@ -53497,7 +53541,7 @@ Say which way you went and why in your write-up, so the human can course-correct
53497
53541
  }
53498
53542
  const updated = clearProjectIcon(input.id);
53499
53543
  if (!updated) throw new Error("No such project.");
53500
- return projectCard(updated, !existsSync15(updated.path));
53544
+ return projectCard(updated, !existsSync16(updated.path));
53501
53545
  }
53502
53546
  }),
53503
53547
  /**
@@ -53538,7 +53582,7 @@ Say which way you went and why in your write-up, so the human can course-correct
53538
53582
  }
53539
53583
  const updated = renameProject(entry.id, { name: name === basename9(path3) ? null : name, slug: name });
53540
53584
  if (!updated) throw new Error("No such project.");
53541
- return projectCard(updated, !existsSync15(updated.path));
53585
+ return projectCard(updated, !existsSync16(updated.path));
53542
53586
  }
53543
53587
  }),
53544
53588
  /**
@@ -53607,16 +53651,6 @@ Say which way you went and why in your write-up, so the human can course-correct
53607
53651
  output: Settings,
53608
53652
  handler: async ({ input }) => ctx.setSettings(input)
53609
53653
  }),
53610
- // Context controls live in the new-thread picker. Patch only the chosen field against the
53611
- // latest settings, synchronously, rather than replacing unrelated settings from a stale drawer.
53612
- contextWindowSet: mutation({
53613
- input: external_exports.object({ backend: external_exports.enum(["claude", "codex"]), tokens: external_exports.number().int().positive().nullable() }),
53614
- output: Settings,
53615
- handler: async ({ input }) => ctx.setSettings({
53616
- ...ctx.getSettings(),
53617
- [input.backend === "claude" ? "autoCompactWindow" : "codexContextWindow"]: input.tokens ?? void 0
53618
- })
53619
- }),
53620
53654
  // Clear the stored settings blob so defaults (incl. the shipped default preamble) apply again.
53621
53655
  settingsReset: mutation({
53622
53656
  input: external_exports.object({}),
@@ -55962,12 +55996,12 @@ var init_boot_progress = __esm({
55962
55996
  });
55963
55997
 
55964
55998
  // packages/server/src/runtime-lease.ts
55965
- import { existsSync as existsSync16, mkdirSync as mkdirSync20, readdirSync as readdirSync12, readFileSync as readFileSync31, unlinkSync as unlinkSync6, writeFileSync as writeFileSync16 } from "node:fs";
55999
+ import { existsSync as existsSync17, mkdirSync as mkdirSync20, readdirSync as readdirSync12, readFileSync as readFileSync31, unlinkSync as unlinkSync6, writeFileSync as writeFileSync16 } from "node:fs";
55966
56000
  import { dirname as dirname22, join as join44 } from "node:path";
55967
56001
  function runtimeVersionDir(bin) {
55968
56002
  let dir = dirname22(bin);
55969
56003
  for (let step = 0; step < MAX_ASCENT; step++) {
55970
- if (existsSync16(join44(dir, PROVISIONED_MARKER))) return dir;
56004
+ if (existsSync17(join44(dir, PROVISIONED_MARKER))) return dir;
55971
56005
  const parent = dirname22(dir);
55972
56006
  if (parent === dir) return void 0;
55973
56007
  dir = parent;
@@ -56047,7 +56081,7 @@ import { createHash as createHash15 } from "node:crypto";
56047
56081
  import {
56048
56082
  chmodSync as chmodSync2,
56049
56083
  closeSync as closeSync16,
56050
- existsSync as existsSync17,
56084
+ existsSync as existsSync18,
56051
56085
  mkdirSync as mkdirSync21,
56052
56086
  openSync as openSync17,
56053
56087
  readFileSync as readFileSync32,
@@ -56091,7 +56125,7 @@ function provisionedBinary(backend, root, label) {
56091
56125
  }
56092
56126
  if (typeof marker.binary !== "string" || marker.label !== label) return void 0;
56093
56127
  const bin = join45(dir, marker.binary);
56094
- return existsSync17(bin) ? bin : void 0;
56128
+ return existsSync18(bin) ? bin : void 0;
56095
56129
  }
56096
56130
  function octal(buffer, offset, length) {
56097
56131
  const text2 = buffer.toString("latin1", offset, offset + length).replace(/\0.*$/su, "").trim();
@@ -56113,7 +56147,7 @@ function safeEntryPath(dest, name) {
56113
56147
  function locateBinary(dir, backend, binary) {
56114
56148
  if (backend === "claude") {
56115
56149
  const direct = join45(dir, binary);
56116
- return existsSync17(direct) ? direct : void 0;
56150
+ return existsSync18(direct) ? direct : void 0;
56117
56151
  }
56118
56152
  const vendor = join45(dir, "vendor");
56119
56153
  let triples;
@@ -56124,7 +56158,7 @@ function locateBinary(dir, backend, binary) {
56124
56158
  }
56125
56159
  for (const triple of triples) {
56126
56160
  const candidate = join45(vendor, triple, "bin", binary);
56127
- if (existsSync17(candidate)) return candidate;
56161
+ if (existsSync18(candidate)) return candidate;
56128
56162
  }
56129
56163
  return void 0;
56130
56164
  }
@@ -56197,7 +56231,7 @@ async function provisionRuntime(backend, options) {
56197
56231
  rename2(partial, finalDir);
56198
56232
  break;
56199
56233
  } catch (err) {
56200
- if (attempt >= RENAME_ATTEMPTS || !TRANSIENT_HANDLE_CODES.has(errorCode4(err) ?? "") || existsSync17(finalDir)) throw err;
56234
+ if (attempt >= RENAME_ATTEMPTS || !TRANSIENT_HANDLE_CODES.has(errorCode4(err) ?? "") || existsSync18(finalDir)) throw err;
56201
56235
  await new Promise((resolve12) => setTimeout(resolve12, options.retryDelayMs ?? RENAME_RETRY_DELAY_MS));
56202
56236
  }
56203
56237
  }
@@ -56319,8 +56353,8 @@ var init_runtimes = __esm({
56319
56353
  init_codex_app_server();
56320
56354
  init_frizz_paths();
56321
56355
  init_runtime_lease();
56322
- CLAUDE_AGENT_SDK_VERSION = "0.3.275";
56323
- CLAUDE_CODE_VERSION = "2.1.275";
56356
+ CLAUDE_AGENT_SDK_VERSION = "0.3.277";
56357
+ CLAUDE_CODE_VERSION = "2.1.277";
56324
56358
  CODEX_VERSION = CODEX_APP_SERVER_SUPPORTED_VERSION;
56325
56359
  RUNTIMES_MODE_ENV = "FRIZZ_RUNTIMES";
56326
56360
  RUNTIMES_DIR_ENV = "FRIZZ_RUNTIMES_DIR";
@@ -56998,7 +57032,7 @@ var init_legacy_project_db = __esm({
56998
57032
  });
56999
57033
 
57000
57034
  // packages/server/src/frizz-db.ts
57001
- import { existsSync as existsSync18, mkdirSync as mkdirSync22, readdirSync as readdirSync14, renameSync as renameSync12, statSync as statSync25 } from "node:fs";
57035
+ import { existsSync as existsSync19, mkdirSync as mkdirSync22, readdirSync as readdirSync14, renameSync as renameSync12, statSync as statSync25 } from "node:fs";
57002
57036
  import { basename as basename13, dirname as dirname24, join as join46 } from "node:path";
57003
57037
  function frizzDatabaseLocation(options) {
57004
57038
  if (options.stateDir !== void 0) {
@@ -57083,7 +57117,7 @@ function openFrizzDatabase(options = {}) {
57083
57117
  };
57084
57118
  }
57085
57119
  function projectIdsWithFile(projectsDir, file) {
57086
- if (!existsSync18(projectsDir)) return [];
57120
+ if (!existsSync19(projectsDir)) return [];
57087
57121
  return readdirSync14(projectsDir).filter((name) => {
57088
57122
  try {
57089
57123
  return statSync25(join46(projectsDir, name, file)).isFile();
@@ -57096,7 +57130,7 @@ function legacyProjectIds(projectsDir) {
57096
57130
  return projectIdsWithFile(projectsDir, "ui.db");
57097
57131
  }
57098
57132
  function retiredLegacyProjectIds(projectsDir) {
57099
- return projectIdsWithFile(projectsDir, "ui.db.imported").filter((id) => !existsSync18(join46(projectsDir, id, "ui.db")));
57133
+ return projectIdsWithFile(projectsDir, "ui.db.imported").filter((id) => !existsSync19(join46(projectsDir, id, "ui.db")));
57100
57134
  }
57101
57135
  function tableColumns(db, schema, table) {
57102
57136
  return db.prepare(`PRAGMA ${schema}.table_info(${table})`).all().map((c) => c.name);
@@ -57301,7 +57335,7 @@ __export(index_exports, {
57301
57335
  unknownProjectPage: () => unknownProjectPage
57302
57336
  });
57303
57337
  import { createServer } from "node:http";
57304
- import { readFileSync as readFileSync33, existsSync as existsSync19, statSync as statSync26 } from "node:fs";
57338
+ import { readFileSync as readFileSync33, existsSync as existsSync20, statSync as statSync26 } from "node:fs";
57305
57339
  import { dirname as dirname26, join as join47, resolve as resolve11, extname as extname4, posix as posix2, sep as sep6 } from "node:path";
57306
57340
  function readServerAddressHolder(path3) {
57307
57341
  try {
@@ -57432,7 +57466,7 @@ function serveStatic(distDir, req, res) {
57432
57466
  const rel = posix2.normalize((req.url ?? "/").split("?")[0].replace(/\\/g, "/")).replace(/^(\.\.[/\\])+/, "");
57433
57467
  let file = join47(distDir, rel === "/" ? "index.html" : rel);
57434
57468
  if (!file.startsWith(distDir + sep6)) file = join47(distDir, "index.html");
57435
- if (!existsSync19(file)) file = join47(distDir, "index.html");
57469
+ if (!existsSync20(file)) file = join47(distDir, "index.html");
57436
57470
  try {
57437
57471
  const stats = statSync26(file);
57438
57472
  const cacheControl = file.startsWith(join47(distDir, "assets") + sep6) ? STATIC_CACHE_IMMUTABLE : STATIC_CACHE_REVALIDATE;
@@ -57941,7 +57975,7 @@ async function startServer(opts = {}) {
57941
57975
  });
57942
57976
  return;
57943
57977
  }
57944
- if (existsSync19(distDir)) {
57978
+ if (existsSync20(distDir)) {
57945
57979
  serveStatic(distDir, req, res);
57946
57980
  return;
57947
57981
  }
@@ -58162,7 +58196,7 @@ init_project();
58162
58196
  init_project_launch();
58163
58197
  init_shutdown();
58164
58198
  init_logging();
58165
- import { existsSync as existsSync20 } from "node:fs";
58199
+ import { existsSync as existsSync21 } from "node:fs";
58166
58200
  import { join as join48 } from "node:path";
58167
58201
 
58168
58202
  // packages/server/src/native-helper.ts
@@ -58240,9 +58274,9 @@ try {
58240
58274
  ["FRIZZ_SCRIPTS_DIR", process.env.FRIZZ_SCRIPTS_DIR, "index.mjs"],
58241
58275
  ["FRIZZ_WORKER_PLUGIN_DIR", process.env.FRIZZ_WORKER_PLUGIN_DIR, ".claude-plugin/plugin.json"]
58242
58276
  ];
58243
- if (!existsSync20(stableWebDist)) throw new Error("stable artifact launch is missing its verified web directory");
58277
+ if (!existsSync21(stableWebDist)) throw new Error("stable artifact launch is missing its verified web directory");
58244
58278
  for (const [name, directory, requiredFile] of required) {
58245
- if (!directory || !existsSync20(join48(directory, requiredFile)))
58279
+ if (!directory || !existsSync21(join48(directory, requiredFile)))
58246
58280
  throw new Error(`stable artifact launch is missing verified ${name}`);
58247
58281
  }
58248
58282
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frizz-server",
3
- "version": "0.14.0",
3
+ "version": "0.14.2",
4
4
  "private": false,
5
5
  "description": "Replaceable Frizz server runtime",
6
6
  "license": "MIT",