@yorz/cli 0.1.2 → 0.1.4

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 (65) hide show
  1. package/README.md +5 -2
  2. package/dist/cli/index.js +302 -25
  3. package/dist/gui/assets/{abnfDiagram-VRR7QNED-DE_Lwnyj.js → abnfDiagram-VRR7QNED-BlILeZZA.js} +1 -1
  4. package/dist/gui/assets/{arc-0XKFeKL1.js → arc-C-xJpbjF.js} +1 -1
  5. package/dist/gui/assets/{architectureDiagram-ZJ3FMSHR-WVMr6CTB.js → architectureDiagram-ZJ3FMSHR-QdzNii0b.js} +1 -1
  6. package/dist/gui/assets/{blockDiagram-677ZJIJ3-JmkelTQ6.js → blockDiagram-677ZJIJ3-BQTAKTET.js} +1 -1
  7. package/dist/gui/assets/{c4Diagram-LMCZKHZV-BYvSE_vv.js → c4Diagram-LMCZKHZV-YRh3fqeb.js} +1 -1
  8. package/dist/gui/assets/channel-DGoXAS0B.js +1 -0
  9. package/dist/gui/assets/{chunk-2Q5K7J3B-cgJ3ifz_.js → chunk-2Q5K7J3B-Bgu-eeCS.js} +1 -1
  10. package/dist/gui/assets/{chunk-32BRIVSS-DR-AYVVA.js → chunk-32BRIVSS-DTLd8wsP.js} +1 -1
  11. package/dist/gui/assets/{chunk-5VM5RSS4-Di4z9gEz.js → chunk-5VM5RSS4-Cct8HJoz.js} +1 -1
  12. package/dist/gui/assets/{chunk-EX3LRPZG-CtCaJMGG.js → chunk-EX3LRPZG-DBgaA_1N.js} +1 -1
  13. package/dist/gui/assets/{chunk-JWPE2WC7-EjoKlGne.js → chunk-JWPE2WC7-DELoF8bV.js} +1 -1
  14. package/dist/gui/assets/{chunk-MOJQB5TN-ndMzM7-f.js → chunk-MOJQB5TN-Du6uREYs.js} +1 -1
  15. package/dist/gui/assets/{chunk-RYQCIY6F-CDdJsSDv.js → chunk-RYQCIY6F-CxO6cQdM.js} +1 -1
  16. package/dist/gui/assets/{chunk-V7JOEXUC-BptnbB4R.js → chunk-V7JOEXUC-BiILBcGA.js} +1 -1
  17. package/dist/gui/assets/{chunk-VR4S4FIN-CF8Dsx8K.js → chunk-VR4S4FIN-BfY2RvG4.js} +1 -1
  18. package/dist/gui/assets/{chunk-XXDRQBXY-CgGWri-V.js → chunk-XXDRQBXY-DmsZw6tB.js} +1 -1
  19. package/dist/gui/assets/classDiagram-OUVF2IWQ-B4zeZ0PC.js +1 -0
  20. package/dist/gui/assets/classDiagram-v2-EOCWNBFH-B4zeZ0PC.js +1 -0
  21. package/dist/gui/assets/{cose-bilkent-JH36ORCC-Bm9uE-P8.js → cose-bilkent-JH36ORCC-gX-8DSxS.js} +1 -1
  22. package/dist/gui/assets/{cynefin-VYW2F7L2-Dd-Apprt.js → cynefin-VYW2F7L2-vOfRo7cL.js} +1 -1
  23. package/dist/gui/assets/{cynefinDiagram-TSTJHNR4-DpGBOFX2.js → cynefinDiagram-TSTJHNR4-Dv66a7Rh.js} +1 -1
  24. package/dist/gui/assets/{dagre-VKFMJZFB-DmKBW-UB.js → dagre-VKFMJZFB-Rk64dDvT.js} +1 -1
  25. package/dist/gui/assets/{diagram-FQU43EPY-CYuUGN7Z.js → diagram-FQU43EPY-CyW3IjmQ.js} +1 -1
  26. package/dist/gui/assets/{diagram-G47NLZAW-BZ-zUUWn.js → diagram-G47NLZAW-Caav47lW.js} +1 -1
  27. package/dist/gui/assets/{diagram-NH7WQ7WH-D2qb5dA_.js → diagram-NH7WQ7WH-_X3ihqNf.js} +1 -1
  28. package/dist/gui/assets/{diagram-OA4YK3LP-BSy8-VUz.js → diagram-OA4YK3LP-CjbverOE.js} +1 -1
  29. package/dist/gui/assets/{diagram-WEI45ONY-B-vTVzM8.js → diagram-WEI45ONY-B93ZeTtT.js} +1 -1
  30. package/dist/gui/assets/{ebnfDiagram-CCIWWBDH-cKb33glS.js → ebnfDiagram-CCIWWBDH-CdDt4bWx.js} +1 -1
  31. package/dist/gui/assets/{erDiagram-Q63AITRT-DvWEFI1U.js → erDiagram-Q63AITRT-Bypq-rvj.js} +1 -1
  32. package/dist/gui/assets/{flowDiagram-23GEKE2U-CfvFgLP2.js → flowDiagram-23GEKE2U-b-l8_7KP.js} +1 -1
  33. package/dist/gui/assets/{ganttDiagram-NO4QXBWP-BnDujV-k.js → ganttDiagram-NO4QXBWP-BeZFHLhX.js} +1 -1
  34. package/dist/gui/assets/{gitGraphDiagram-IHSO6WYX-Sv91FaB5.js → gitGraphDiagram-IHSO6WYX-C0siPGLA.js} +1 -1
  35. package/dist/gui/assets/{index-Do-LzYBw.js → index-DKVgyltQ.js} +2 -2
  36. package/dist/gui/assets/{infoDiagram-FWYZ7A6U-BE3WS_us.js → infoDiagram-FWYZ7A6U-Bk8DNKgG.js} +1 -1
  37. package/dist/gui/assets/{ishikawaDiagram-FXEZZL3T-FObQPAd_.js → ishikawaDiagram-FXEZZL3T-DyS4wmJu.js} +1 -1
  38. package/dist/gui/assets/{journeyDiagram-5HDEW3XC-D3RAFL7x.js → journeyDiagram-5HDEW3XC-4jUY7Bzi.js} +1 -1
  39. package/dist/gui/assets/{kanban-definition-HUTT4EX6-Bx1DS2KG.js → kanban-definition-HUTT4EX6-BRiI4KbM.js} +1 -1
  40. package/dist/gui/assets/{linear-oevdTPQK.js → linear-C5JkbjyJ.js} +1 -1
  41. package/dist/gui/assets/{mermaid.core-jn1Xktvs.js → mermaid.core-ImB_5gdE.js} +4 -4
  42. package/dist/gui/assets/{mindmap-definition-LN4V7U3C-xLT5IJki.js → mindmap-definition-LN4V7U3C-9_Awmd2W.js} +1 -1
  43. package/dist/gui/assets/{pegDiagram-2B236MQR-DToAMrXG.js → pegDiagram-2B236MQR-DF_vIYzp.js} +1 -1
  44. package/dist/gui/assets/{pieDiagram-ENE6RG2P-Cw6tv4YJ.js → pieDiagram-ENE6RG2P-3TPwXSjQ.js} +1 -1
  45. package/dist/gui/assets/{quadrantDiagram-ABIIQ3AL-GW5Knopm.js → quadrantDiagram-ABIIQ3AL-jzJ30mNi.js} +1 -1
  46. package/dist/gui/assets/{railroadDiagram-RFXS5EU6-CuP1sa-2.js → railroadDiagram-RFXS5EU6-B-29q3CI.js} +1 -1
  47. package/dist/gui/assets/{requirementDiagram-TGXJPOKE-D8IcCo1X.js → requirementDiagram-TGXJPOKE-BanWpS6g.js} +1 -1
  48. package/dist/gui/assets/{sankeyDiagram-HTMAVEWB-CfT_C9uh.js → sankeyDiagram-HTMAVEWB-B_sxc9IV.js} +1 -1
  49. package/dist/gui/assets/{sequenceDiagram-DBY2YBRQ-BwUwWFYe.js → sequenceDiagram-DBY2YBRQ-BNVav9DA.js} +1 -1
  50. package/dist/gui/assets/{sizeCapture-X5ZJPWSS-DyBlcl4H.js → sizeCapture-X5ZJPWSS-DbaiKjno.js} +1 -1
  51. package/dist/gui/assets/{stateDiagram-2N3HPSRC-yv8DkbvF.js → stateDiagram-2N3HPSRC-jU5WBm6c.js} +1 -1
  52. package/dist/gui/assets/stateDiagram-v2-6OUMAXLB-GXq_r-DG.js +1 -0
  53. package/dist/gui/assets/{swimlanes-5IMT3BWC-BnOmKdmr.js → swimlanes-5IMT3BWC-Dcmb64x2.js} +2 -2
  54. package/dist/gui/assets/swimlanesDiagram-G3AALYLV-DDE-INgq.js +8 -0
  55. package/dist/gui/assets/{timeline-definition-FHXFAJF6-C6_-GVjE.js → timeline-definition-FHXFAJF6-COm9ow7j.js} +1 -1
  56. package/dist/gui/assets/{vennDiagram-L72KCM5P-D_N0uLk2.js → vennDiagram-L72KCM5P-DliDuTVY.js} +1 -1
  57. package/dist/gui/assets/{wardleyDiagram-EHGQE667-CnNoxFYY.js → wardleyDiagram-EHGQE667-C2O_2cpw.js} +1 -1
  58. package/dist/gui/assets/{xychartDiagram-FW5EYKEG-CloORw9z.js → xychartDiagram-FW5EYKEG-Ldmt9hoc.js} +1 -1
  59. package/dist/gui/index.html +1 -1
  60. package/package.json +4 -4
  61. package/dist/gui/assets/channel-BhMtSKKb.js +0 -1
  62. package/dist/gui/assets/classDiagram-OUVF2IWQ-DiPaZ7LY.js +0 -1
  63. package/dist/gui/assets/classDiagram-v2-EOCWNBFH-DiPaZ7LY.js +0 -1
  64. package/dist/gui/assets/stateDiagram-v2-6OUMAXLB-BspjtPpt.js +0 -1
  65. package/dist/gui/assets/swimlanesDiagram-G3AALYLV-BgPC3dJX.js +0 -8
package/README.md CHANGED
@@ -34,13 +34,15 @@ npx -p @yorz/cli yorz <command>
34
34
  yorz serve
35
35
  ```
36
36
 
37
- This launches the YorZ Service (HTTP + SSE + static GUI). Open `http://localhost:7423` in your browser to access the dashboard.
37
+ This launches the YorZ Service (HTTP + SSE + static GUI) in the background by default. Open `http://localhost:7423` in your browser to access the dashboard.
38
38
 
39
39
  Options:
40
40
 
41
41
  ```bash
42
42
  yorz serve --port 8080 # custom port
43
43
  yorz serve --open # auto-open browser
44
+ yorz serve --foreground # run in foreground
45
+ yorz serve stop # stop the background service
44
46
  ```
45
47
 
46
48
  ### Step 2 — Add a Project
@@ -75,7 +77,8 @@ Then ask your agent (Claude Code / OpenCode) to process it. The skill handles th
75
77
 
76
78
  | Command | Description |
77
79
  | ----------------------- | ---------------------------------------------------------------- |
78
- | `yorz serve` | Start the YorZ Service (HTTP + SSE + static GUI). Multi-project. |
80
+ | `yorz serve` | Start or reuse the YorZ Service in the background. Multi-project. |
81
+ | `yorz serve stop` | Stop the background YorZ Service. |
79
82
  | `yorz add <path>` | Initialize and register a directory as a YorZ project. |
80
83
  | `yorz install skills` | Install the yorz-spec skill into Claude Code / OpenCode. |
81
84
  | `yorz uninstall skills` | Remove the yorz-spec skill from agents. |
package/dist/cli/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { homedir, networkInterfaces } from "node:os";
3
3
  import { Command, Option } from "commander";
4
- import { stat, rm, mkdir, writeFile, readFile, access, rename, readdir, copyFile, open } from "node:fs/promises";
4
+ import { stat, rm, mkdir, writeFile, readFile, access, rename, readdir, copyFile, open, appendFile } from "node:fs/promises";
5
5
  import { join, dirname, extname, resolve, sep, isAbsolute, basename as basename$1, relative, normalize } from "node:path";
6
6
  import { spawn, execFile } from "node:child_process";
7
7
  import { existsSync, statSync, mkdirSync, watch, readFileSync, createWriteStream } from "node:fs";
@@ -16,7 +16,7 @@ import chokidar from "chokidar";
16
16
  import { EventEmitter } from "node:events";
17
17
  import { createInterface } from "node:readline/promises";
18
18
  import MarkdownIt from "markdown-it";
19
- const version = "0.1.2";
19
+ const version = "0.1.4";
20
20
  const pkg = {
21
21
  version
22
22
  };
@@ -68,6 +68,13 @@ const claudeAdapter = {
68
68
  return join(ctx.cwd, ".claude", "skills");
69
69
  }
70
70
  };
71
+ const codexAdapter = {
72
+ name: "codex",
73
+ resolveSkillsDir(scope, ctx) {
74
+ if (scope === "user") return join(ctx.home, ".codex", "skills");
75
+ return join(ctx.cwd, ".codex", "skills");
76
+ }
77
+ };
71
78
  const opencodeAdapter = {
72
79
  name: "opencode",
73
80
  resolveSkillsDir(scope, ctx) {
@@ -77,7 +84,8 @@ const opencodeAdapter = {
77
84
  };
78
85
  const ADAPTERS = {
79
86
  claude: claudeAdapter,
80
- opencode: opencodeAdapter
87
+ opencode: opencodeAdapter,
88
+ codex: codexAdapter
81
89
  };
82
90
  function getAdapter(name) {
83
91
  if (name in ADAPTERS) return ADAPTERS[name];
@@ -1395,15 +1403,19 @@ class EventsHub {
1395
1403
  return await next;
1396
1404
  }
1397
1405
  emit(s, topic, event, data) {
1398
- const frame = {
1399
- event: "msg",
1400
- data: JSON.stringify({ topic, event, data })
1401
- };
1402
- if (s.stream && !s.closed) {
1403
- void s.stream.writeSSE(frame).catch(() => {
1404
- });
1405
- } else {
1406
- s.queue.push(frame);
1406
+ try {
1407
+ const frame = {
1408
+ event: "msg",
1409
+ data: JSON.stringify({ topic, event, data })
1410
+ };
1411
+ if (s.stream && !s.closed) {
1412
+ void s.stream.writeSSE(frame).catch(() => {
1413
+ });
1414
+ } else {
1415
+ s.queue.push(frame);
1416
+ }
1417
+ } catch (err) {
1418
+ console.error("[yorz] SSE emit error:", err);
1407
1419
  }
1408
1420
  }
1409
1421
  async flush(s) {
@@ -1722,12 +1734,14 @@ function normalizeConfig$1(value) {
1722
1734
  function normalizeAgent(value) {
1723
1735
  if (typeof value === "string") {
1724
1736
  if (value === "opencode") return { kind: "opencode" };
1737
+ if (value === "codex") return { kind: "codex" };
1725
1738
  return { kind: "claude" };
1726
1739
  }
1727
1740
  if (!value || typeof value !== "object") return { kind: "claude" };
1728
1741
  const obj = value;
1729
1742
  const kind = obj.kind;
1730
1743
  if (kind === "opencode") return { kind: "opencode" };
1744
+ if (kind === "codex") return { kind: "codex" };
1731
1745
  if (kind === "custom") {
1732
1746
  const cmd = typeof obj.cmd === "string" ? obj.cmd.trim() : "";
1733
1747
  if (!cmd) return { kind: "claude" };
@@ -1806,6 +1820,7 @@ function parseAgent(value) {
1806
1820
  const kind = obj.kind;
1807
1821
  if (kind === "claude") return { value: { kind: "claude" } };
1808
1822
  if (kind === "opencode") return { value: { kind: "opencode" } };
1823
+ if (kind === "codex") return { value: { kind: "codex" } };
1809
1824
  if (kind === "custom") {
1810
1825
  const cmd = obj.cmd;
1811
1826
  if (typeof cmd !== "string" || !cmd.trim()) {
@@ -1826,7 +1841,7 @@ function parseAgent(value) {
1826
1841
  }
1827
1842
  return { value: { kind: "custom", cmd: cmd.trim(), args } };
1828
1843
  }
1829
- return { error: "agent.kind must be claude | opencode | custom" };
1844
+ return { error: "agent.kind must be claude | opencode | codex | custom" };
1830
1845
  }
1831
1846
  function parseSpecsDir(value) {
1832
1847
  const fallback = defaultProjectConfig().specsDir;
@@ -2804,6 +2819,10 @@ function createApp(opts) {
2804
2819
  api.route("/", createEventsRoutes(resolveProject, opts.registry, projectsBus));
2805
2820
  app.route("/api", api);
2806
2821
  app.route("/", createStaticRoutes(opts.guiRoot));
2822
+ app.onError((err, c) => {
2823
+ console.error("[yorz] route error:", err);
2824
+ return c.json({ error: "Internal Server Error", message: err.message }, 500);
2825
+ });
2807
2826
  return app;
2808
2827
  }
2809
2828
  const SECTIONS = [
@@ -3367,6 +3386,22 @@ const BUILTIN = {
3367
3386
  env: (cwd) => ({
3368
3387
  PWD: cwd
3369
3388
  })
3389
+ },
3390
+ codex: {
3391
+ cmd: "codex",
3392
+ // Codex CLI 的无人值守入口是 `codex exec <prompt>`。这里显式传入目标 cwd,
3393
+ // 并用 exec 支持的 bypass 参数关闭审批/沙箱,以对齐 claude bypassPermissions
3394
+ // 与 opencode skip-permissions 的后台执行语义;服务端 spawn 的 cwd 也会设置
3395
+ // 为同一个目录,作为进程工作目录兜底。
3396
+ args: (prompt, cwd) => [
3397
+ "exec",
3398
+ "--cd",
3399
+ cwd ?? ".",
3400
+ "--skip-git-repo-check",
3401
+ "--dangerously-bypass-approvals-and-sandbox",
3402
+ prompt
3403
+ ],
3404
+ streamFormat: "text"
3370
3405
  }
3371
3406
  };
3372
3407
  function resolveAgentCmd(opts) {
@@ -3402,11 +3437,13 @@ function readAgentCmd(cwd) {
3402
3437
  const agent = data.agent;
3403
3438
  if (typeof agent === "string") {
3404
3439
  if (agent === "opencode") return BUILTIN.opencode;
3440
+ if (agent === "codex") return BUILTIN.codex;
3405
3441
  return BUILTIN.claude;
3406
3442
  }
3407
3443
  if (!agent || typeof agent !== "object") return BUILTIN.claude;
3408
3444
  const kind = agent.kind;
3409
3445
  if (kind === "opencode") return BUILTIN.opencode;
3446
+ if (kind === "codex") return BUILTIN.codex;
3410
3447
  if (kind === "custom") {
3411
3448
  const cmd = agent.cmd;
3412
3449
  const argsRaw = agent.args;
@@ -3566,15 +3603,19 @@ class AgentRunner {
3566
3603
  void run();
3567
3604
  };
3568
3605
  const pushStdout = (text) => {
3569
- if (!text) return;
3570
- append(text);
3571
- writeToLog(text);
3572
- emitter.emit("stdout", text);
3606
+ try {
3607
+ if (!text) return;
3608
+ append(text);
3609
+ writeToLog(text);
3610
+ emitter.emit("stdout", text);
3611
+ } catch (err) {
3612
+ console.error("[yorz] pushStdout error:", err);
3613
+ }
3573
3614
  };
3574
3615
  const cmd = this.resolveCmd();
3575
3616
  let child;
3576
3617
  try {
3577
- child = spawn(cmd.cmd, cmd.args(input.prompt), {
3618
+ child = spawn(cmd.cmd, cmd.args(input.prompt, this.cwd), {
3578
3619
  cwd: this.cwd,
3579
3620
  env: { ...process.env, ...cmd.env?.(this.cwd) ?? {} },
3580
3621
  stdio: ["ignore", "pipe", "pipe"],
@@ -4205,6 +4246,7 @@ async function start(opts = {}) {
4205
4246
  console.log(` - ${p.name} -> ${p.path}`);
4206
4247
  }
4207
4248
  console.log(`agent heartbeat enabled (interval=${HEARTBEAT_INTERVAL_MS / 1e3}s)`);
4249
+ installGlobalErrorHandlers();
4208
4250
  if (opts.open) await tryOpenBrowser(url);
4209
4251
  return {
4210
4252
  url,
@@ -4269,18 +4311,61 @@ async function tryOpenBrowser(url) {
4269
4311
  } catch {
4270
4312
  }
4271
4313
  }
4314
+ let errorLogReady = false;
4315
+ async function ensureErrorLogDir() {
4316
+ const dir = join(resolveGlobalConfigDir(), "logs");
4317
+ if (!errorLogReady) {
4318
+ await mkdir(dir, { recursive: true });
4319
+ errorLogReady = true;
4320
+ }
4321
+ return join(dir, "serve-errors.log");
4322
+ }
4323
+ function logCrash(kind, payload) {
4324
+ const ts = (/* @__PURE__ */ new Date()).toISOString();
4325
+ const body = payload instanceof Error ? payload.stack ?? payload.message : String(payload);
4326
+ const line = `[${ts}] [${kind}] ${body}
4327
+ `;
4328
+ console.error(`[yorz] ${kind}:`, payload);
4329
+ void ensureErrorLogDir().then((fp) => appendFile(fp, line, "utf8")).catch(() => {
4330
+ });
4331
+ }
4332
+ function installGlobalErrorHandlers() {
4333
+ if (process.listenerCount("uncaughtException") > 0) return;
4334
+ process.on("uncaughtException", (err) => {
4335
+ logCrash("uncaughtException", err);
4336
+ });
4337
+ process.on("unhandledRejection", (reason) => {
4338
+ logCrash("unhandledRejection", reason);
4339
+ });
4340
+ }
4341
+ const DEFAULT_SERVE_PORT = 7423;
4342
+ const RUNTIME_FILE = "runtime.json";
4343
+ const START_LOCK_DIR = "serve.lock";
4344
+ const START_WAIT_MS = 5e3;
4272
4345
  async function runServe(opts) {
4346
+ if (!opts.foreground) {
4347
+ return startBackgroundServe(opts);
4348
+ }
4273
4349
  const handle = await start({
4274
4350
  port: opts.port,
4275
4351
  open: opts.open,
4276
4352
  cwd: opts.cwd ?? process.cwd(),
4277
4353
  noRegisterCwd: opts.noRegisterCwd
4278
4354
  });
4355
+ await writeRuntime({
4356
+ version: 1,
4357
+ pid: process.pid,
4358
+ port: handle.port,
4359
+ url: handle.url,
4360
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
4361
+ });
4362
+ console.log(`Stop with: yorz serve stop`);
4279
4363
  const shutdown = async () => {
4280
4364
  console.log("\nShutting down YorZ Service…");
4281
4365
  try {
4282
4366
  await handle.close();
4283
4367
  } finally {
4368
+ await removeRuntimeForPid(process.pid);
4284
4369
  process.exit(0);
4285
4370
  }
4286
4371
  };
@@ -4288,6 +4373,190 @@ async function runServe(opts) {
4288
4373
  process.once("SIGTERM", () => void shutdown());
4289
4374
  return handle;
4290
4375
  }
4376
+ function startBackgroundServe(opts) {
4377
+ return withStartLock(async () => {
4378
+ const existing = await readLiveRuntime();
4379
+ if (existing) {
4380
+ console.log(`YorZ Service is already running in background (pid=${existing.pid}).`);
4381
+ console.log(`Open ${existing.url}`);
4382
+ console.log(`Stop with: yorz serve stop`);
4383
+ return {
4384
+ background: true,
4385
+ reused: true,
4386
+ pid: existing.pid,
4387
+ port: existing.port,
4388
+ url: existing.url
4389
+ };
4390
+ }
4391
+ const entry = process.argv[1];
4392
+ if (!entry) throw new Error("Cannot resolve CLI entrypoint for background service");
4393
+ const child = spawn(process.execPath, [entry, "serve", ...backgroundArgs(opts)], {
4394
+ detached: true,
4395
+ stdio: "ignore"
4396
+ });
4397
+ child.unref();
4398
+ const runtime = await waitForRuntime(child.pid, START_WAIT_MS);
4399
+ const port = runtime?.port ?? opts.port ?? DEFAULT_SERVE_PORT;
4400
+ const url = runtime?.url ?? `http://localhost:${port}/`;
4401
+ console.log(`YorZ Service started in background (pid=${child.pid ?? "unknown"}).`);
4402
+ console.log(`Open ${url}${runtime ? "" : ` (or the next free port if ${port} is busy).`}`);
4403
+ console.log(`Stop with: yorz serve stop`);
4404
+ return {
4405
+ background: true,
4406
+ pid: child.pid,
4407
+ url,
4408
+ port
4409
+ };
4410
+ });
4411
+ }
4412
+ function backgroundArgs(opts) {
4413
+ const args = ["--foreground"];
4414
+ if (opts.port !== void 0) args.push("--port", String(opts.port));
4415
+ if (opts.open) args.push("--open");
4416
+ if (opts.cwd) args.push("--cwd", opts.cwd);
4417
+ if (opts.noRegisterCwd) args.push("--no-register-cwd");
4418
+ return args;
4419
+ }
4420
+ async function runStopServe() {
4421
+ const runtime = await readRuntime();
4422
+ if (!runtime) {
4423
+ return {
4424
+ stopped: false,
4425
+ message: "YorZ Service is not running."
4426
+ };
4427
+ }
4428
+ if (!isProcessAlive(runtime.pid)) {
4429
+ await removeRuntime();
4430
+ return {
4431
+ stopped: false,
4432
+ pid: runtime.pid,
4433
+ url: runtime.url,
4434
+ message: `YorZ Service was not running; removed stale runtime for pid=${runtime.pid}.`
4435
+ };
4436
+ }
4437
+ try {
4438
+ process.kill(runtime.pid, "SIGTERM");
4439
+ } catch (err) {
4440
+ await removeRuntime();
4441
+ return {
4442
+ stopped: false,
4443
+ pid: runtime.pid,
4444
+ url: runtime.url,
4445
+ message: `Failed to stop YorZ Service pid=${runtime.pid}: ${err.message}`
4446
+ };
4447
+ }
4448
+ let stopped = await waitForProcessExit(runtime.pid, 2e3);
4449
+ if (!stopped) {
4450
+ try {
4451
+ process.kill(runtime.pid, "SIGKILL");
4452
+ } catch {
4453
+ }
4454
+ stopped = await waitForProcessExit(runtime.pid, 2e3);
4455
+ }
4456
+ if (stopped) await removeRuntime();
4457
+ return {
4458
+ stopped,
4459
+ pid: runtime.pid,
4460
+ url: runtime.url,
4461
+ message: stopped ? `Stopped YorZ Service (pid=${runtime.pid}).` : `Tried to stop YorZ Service (pid=${runtime.pid}), but it is still running.`
4462
+ };
4463
+ }
4464
+ function runtimePath() {
4465
+ return join(resolveGlobalConfigDir(), RUNTIME_FILE);
4466
+ }
4467
+ function startLockPath() {
4468
+ return join(resolveGlobalConfigDir(), START_LOCK_DIR);
4469
+ }
4470
+ async function withStartLock(fn) {
4471
+ const lockPath = startLockPath();
4472
+ await mkdir(resolveGlobalConfigDir(), { recursive: true });
4473
+ try {
4474
+ await mkdir(lockPath, { recursive: false });
4475
+ } catch (err) {
4476
+ const code = err.code;
4477
+ if (code !== "EEXIST") throw err;
4478
+ const existing = await waitForLiveRuntime(START_WAIT_MS);
4479
+ if (existing) return await fn();
4480
+ await rm(lockPath, { recursive: true, force: true });
4481
+ await mkdir(lockPath, { recursive: false });
4482
+ }
4483
+ try {
4484
+ return await fn();
4485
+ } finally {
4486
+ await rm(lockPath, { recursive: true, force: true });
4487
+ }
4488
+ }
4489
+ async function waitForLiveRuntime(timeoutMs) {
4490
+ const until = Date.now() + timeoutMs;
4491
+ while (Date.now() < until) {
4492
+ const runtime = await readLiveRuntime();
4493
+ if (runtime) return runtime;
4494
+ await sleep(100);
4495
+ }
4496
+ return null;
4497
+ }
4498
+ async function waitForRuntime(pid, timeoutMs) {
4499
+ const until = Date.now() + timeoutMs;
4500
+ while (Date.now() < until) {
4501
+ const runtime = await readLiveRuntime();
4502
+ if (runtime && (pid === void 0 || runtime.pid === pid)) return runtime;
4503
+ await sleep(100);
4504
+ }
4505
+ return null;
4506
+ }
4507
+ async function readLiveRuntime() {
4508
+ const runtime = await readRuntime();
4509
+ if (!runtime) return null;
4510
+ if (isProcessAlive(runtime.pid)) return runtime;
4511
+ await removeRuntime();
4512
+ return null;
4513
+ }
4514
+ async function readRuntime() {
4515
+ const path = runtimePath();
4516
+ if (!existsSync(path)) return null;
4517
+ try {
4518
+ const raw = await readFile(path, "utf8");
4519
+ const parsed = JSON.parse(raw);
4520
+ if (parsed.version !== 1 || typeof parsed.pid !== "number" || typeof parsed.port !== "number" || typeof parsed.url !== "string" || typeof parsed.startedAt !== "string") {
4521
+ return null;
4522
+ }
4523
+ return parsed;
4524
+ } catch {
4525
+ return null;
4526
+ }
4527
+ }
4528
+ async function writeRuntime(runtime) {
4529
+ const path = runtimePath();
4530
+ await mkdir(resolveGlobalConfigDir(), { recursive: true });
4531
+ await writeFile(path, `${JSON.stringify(runtime, null, 2)}
4532
+ `, "utf8");
4533
+ }
4534
+ async function removeRuntimeForPid(pid) {
4535
+ const runtime = await readRuntime();
4536
+ if (!runtime || runtime.pid === pid) await removeRuntime();
4537
+ }
4538
+ async function removeRuntime() {
4539
+ await rm(runtimePath(), { force: true });
4540
+ }
4541
+ function isProcessAlive(pid) {
4542
+ try {
4543
+ process.kill(pid, 0);
4544
+ return true;
4545
+ } catch {
4546
+ return false;
4547
+ }
4548
+ }
4549
+ async function waitForProcessExit(pid, timeoutMs) {
4550
+ const until = Date.now() + timeoutMs;
4551
+ while (Date.now() < until) {
4552
+ if (!isProcessAlive(pid)) return true;
4553
+ await sleep(100);
4554
+ }
4555
+ return !isProcessAlive(pid);
4556
+ }
4557
+ function sleep(ms) {
4558
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
4559
+ }
4291
4560
  class AddGitAbortedError extends Error {
4292
4561
  constructor(message) {
4293
4562
  super(message);
@@ -5331,11 +5600,11 @@ function installScopeTip(scopeSource) {
5331
5600
  }
5332
5601
  return null;
5333
5602
  }
5334
- const ALL_AGENTS = ["claude", "opencode"];
5603
+ const ALL_AGENTS = ["claude", "opencode", "codex"];
5335
5604
  function parseAgents(value) {
5336
5605
  if (value === "all") return ALL_AGENTS;
5337
- if (value === "claude" || value === "opencode") return [value];
5338
- throw new Error(`Invalid --agent: ${value}. Use 'claude' | 'opencode' | 'all'.`);
5606
+ if (value === "claude" || value === "opencode" || value === "codex") return [value];
5607
+ throw new Error(`Invalid --agent: ${value}. Use 'claude' | 'opencode' | 'codex' | 'all'.`);
5339
5608
  }
5340
5609
  function parseScope(value) {
5341
5610
  if (value === "user" || value === "project") return value;
@@ -5347,7 +5616,7 @@ const installCmd = program.command("install").description("Install YorZ artifact
5347
5616
  installCmd.action(() => {
5348
5617
  installCmd.help();
5349
5618
  });
5350
- installCmd.command("skills").description("Install the yorz-spec skill into the target agent(s).").option("-a, --agent <agent>", "target agent: claude | opencode | all", "all").addOption(
5619
+ installCmd.command("skills").description("Install the yorz-spec skill into the target agent(s).").option("-a, --agent <agent>", "target agent: claude | opencode | codex | all", "all").addOption(
5351
5620
  new Option("-s, --scope <scope>", "install scope: user | project").default(
5352
5621
  INSTALL_SCOPE_DEFAULT
5353
5622
  )
@@ -5371,7 +5640,7 @@ const uninstallCmd = program.command("uninstall").description("Remove YorZ artif
5371
5640
  uninstallCmd.action(() => {
5372
5641
  uninstallCmd.help();
5373
5642
  });
5374
- uninstallCmd.command("skills").description("Remove the yorz-spec skill from the target agent(s).").option("-a, --agent <agent>", "target agent: claude | opencode | all", "all").option("-s, --scope <scope>", "uninstall scope: user | project", INSTALL_SCOPE_DEFAULT).action(async (opts) => {
5643
+ uninstallCmd.command("skills").description("Remove the yorz-spec skill from the target agent(s).").option("-a, --agent <agent>", "target agent: claude | opencode | codex | all", "all").option("-s, --scope <scope>", "uninstall scope: user | project", INSTALL_SCOPE_DEFAULT).action(async (opts) => {
5375
5644
  const agents = parseAgents(opts.agent);
5376
5645
  const scope = parseScope(opts.scope);
5377
5646
  for (const agent of agents) {
@@ -5413,10 +5682,13 @@ program.command("lint [paths...]").description("Lint spec.md / review.md files f
5413
5682
  });
5414
5683
  if (result.exitCode !== 0) process.exit(result.exitCode);
5415
5684
  });
5416
- program.command("serve").description("Start the YorZ Service (HTTP + SSE + static GUI; multi-project).").option("-p, --port <port>", "port to listen on", "7423").option("--open", "open the GUI in the default browser", false).option(
5685
+ const serveCmd = program.command("serve").description("Start the YorZ Service (HTTP + SSE + static GUI; multi-project).").option("-p, --port <port>", "port to listen on", "7423").option("--open", "open the GUI in the default browser", false).option("--foreground", "run the service in the foreground", false).option("--background", "run the service in the background (default)", false).option(
5417
5686
  "--cwd <path>",
5418
5687
  "directory to auto-register when it contains .yorz/ (default: process.cwd())"
5419
5688
  ).option("--no-register-cwd", "do not auto-register the current directory").action(async (opts) => {
5689
+ if (opts.foreground && opts.background) {
5690
+ throw new Error("Use either --foreground or --background, not both");
5691
+ }
5420
5692
  const port = opts.port === void 0 ? void 0 : Number.parseInt(opts.port, 10);
5421
5693
  if (port !== void 0 && (!Number.isFinite(port) || port < 0)) {
5422
5694
  throw new Error(`Invalid --port: ${opts.port}`);
@@ -5425,9 +5697,14 @@ program.command("serve").description("Start the YorZ Service (HTTP + SSE + stati
5425
5697
  port,
5426
5698
  open: opts.open,
5427
5699
  cwd: opts.cwd,
5428
- noRegisterCwd: opts.noRegisterCwd === false ? true : false
5700
+ noRegisterCwd: opts.registerCwd === false,
5701
+ foreground: opts.foreground === true
5429
5702
  });
5430
5703
  });
5704
+ serveCmd.command("stop").description("Stop the background YorZ Service.").action(async () => {
5705
+ const result = await runStopServe();
5706
+ console.log(result.message);
5707
+ });
5431
5708
  program.parseAsync(process.argv).catch((err) => {
5432
5709
  console.error(`error: ${err.message}`);
5433
5710
  process.exit(1);
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-ndMzM7-f.js";import{p as f}from"./chunk-JWPE2WC7-EjoKlGne.js";import{_ as n,l as o}from"./mermaid.core-jn1Xktvs.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-Dd-Apprt.js";import"./index-Do-LzYBw.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
1
+ import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-Du6uREYs.js";import{p as f}from"./chunk-JWPE2WC7-DELoF8bV.js";import{_ as n,l as o}from"./mermaid.core-ImB_5gdE.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-vOfRo7cL.js";import"./index-DKVgyltQ.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
@@ -1 +1 @@
1
- import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-jn1Xktvs.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
1
+ import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-ImB_5gdE.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};