@tea-agent/loop-agent 0.43.0-next.16 → 0.43.0-next.18

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 (154) hide show
  1. package/CHANGELOG.md +8 -1
  2. package/dist/application/dag/args.js +8 -0
  3. package/dist/build-stamp.json +3 -3
  4. package/dist/cli/command-definitions.js +2 -0
  5. package/dist/cli/program.js +3 -1
  6. package/dist/cli/update/init-surface-notifier.js +2 -0
  7. package/dist/cli/update/policy.js +2 -0
  8. package/dist/commands/cursor-prompt.js +2 -0
  9. package/dist/commands/dag-approve.js +2 -0
  10. package/dist/commands/dag-final-verification.js +2 -0
  11. package/dist/commands/dag-init-hybrid.js +2 -0
  12. package/dist/commands/dag-reconcile-tasks.js +2 -0
  13. package/dist/commands/dag-reject.js +2 -0
  14. package/dist/commands/dag-report.js +2 -0
  15. package/dist/commands/dag-rerun.js +2 -0
  16. package/dist/commands/dag-resume.js +2 -0
  17. package/dist/commands/dag-workflow-compile.js +2 -0
  18. package/dist/commands/dag-workflow-plan.js +2 -0
  19. package/dist/commands/dag-workflow-validate.js +2 -0
  20. package/dist/commands/delegate.js +2 -0
  21. package/dist/commands/examples.js +2 -0
  22. package/dist/commands/import-prd.js +2 -0
  23. package/dist/commands/init-model-catalog.js +2 -0
  24. package/dist/commands/init.js +6 -4
  25. package/dist/commands/instructions.js +2 -0
  26. package/dist/commands/knowledge.js +2 -0
  27. package/dist/commands/loop-benchmark.js +2 -0
  28. package/dist/commands/pi-prompt.js +2 -0
  29. package/dist/commands/pi-reuse-benchmark.js +2 -0
  30. package/dist/commands/promote-run.js +2 -0
  31. package/dist/commands/stats.js +1 -1
  32. package/dist/commands/study-init.js +2 -0
  33. package/dist/commands/task-advance.js +2 -0
  34. package/dist/commands/task-source-prepare.js +2 -0
  35. package/dist/commands/worktree-create.js +2 -0
  36. package/dist/commands/worktree-remove.js +2 -0
  37. package/dist/executors/dag-pi-executor.js +25 -6
  38. package/dist/executors/shell-verification.js +3 -0
  39. package/dist/governance/exec-plans.js +6 -3
  40. package/dist/infrastructure/console/app-data.js +6 -0
  41. package/dist/shared/artifacts-core.js +2 -0
  42. package/dist/shared/git-progress.js +2 -0
  43. package/dist/shared/one-shot-prompt-args.js +2 -0
  44. package/dist/shared/package-metadata.js +6 -4
  45. package/dist/shared/pi-context-pressure/sift-bridge.js +1 -1
  46. package/dist/shared/reference-context.js +2 -0
  47. package/dist/task/contract/recover.js +6 -0
  48. package/dist/task/source-prepare/artifact-meta.js +9 -2
  49. package/dist/task/source-prepare/fragment-inventory.js +4 -1
  50. package/dist/task/source-prepare/parse-intent.js +36 -11
  51. package/dist/task/task-demand-routing.js +5 -2
  52. package/dist/worker/console/chat/browser-automation.js +468 -308
  53. package/dist/worker/console/chat/browser-routes.js +175 -57
  54. package/dist/worker/console/chat/explore-tools.js +5 -2
  55. package/dist/worker/console/chat/pi-runtime/custom-tools/browser-tools.js +115 -20
  56. package/dist/worker/console/chat/pi-runtime.js +9 -1
  57. package/dist/worker/console/chat/routes.js +1 -1
  58. package/dist/worker/console/chat/sdd-data-alignment.js +1 -1
  59. package/dist/worker/console/chat/session-mode.js +1 -1
  60. package/dist/worker/console/chat/tools.js +7 -1
  61. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4NXyedy.js → abnfDiagram-N423BO3Z-B_UDknhR.js} +1 -1
  62. package/dist/worker/console/static/assets/{arc-NZ3qXvBI.js → arc-D6hU0drN.js} +1 -1
  63. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-COZSRvml.js → architectureDiagram-T3A2C74G-DmVikdRK.js} +1 -1
  64. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Ck0Gxi9C.js → blockDiagram-VBNYF7ZC-DydABCRg.js} +1 -1
  65. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BX5HQ4Ox.js → c4Diagram-5PPSVZJV-DrXKC2Jl.js} +1 -1
  66. package/dist/worker/console/static/assets/channel-Drecd94a.js +1 -0
  67. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-CoviemSL.js → chunk-2GRJ4B5K-D2-qFxr7.js} +1 -1
  68. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DbOdOkbZ.js → chunk-2Q5K7J3B-ChfeF41P.js} +1 -1
  69. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BsG2pmdQ.js → chunk-5RXB4S5H-Drwrz55x.js} +1 -1
  70. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-DGdvrNm8.js → chunk-5VM5RSS4-CAQGErL7.js} +1 -1
  71. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BAy7Yd6y.js → chunk-6Q2QTUOP-DHO38w5U.js} +1 -1
  72. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-D9UA7hUb.js → chunk-GF5L2VYU-EYIN0EOI.js} +1 -1
  73. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-DPz7SZ8V.js → chunk-JWPE2WC7-CrFLKqkT.js} +1 -1
  74. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BmuEOIh7.js → chunk-KBJHAD2P-DMchffoo.js} +1 -1
  75. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CIhBWnd8.js → chunk-RYQCIY6F-DaSvtKQa.js} +1 -1
  76. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CScR6mDD.js → chunk-XXDRQBXY-DcW8W9Qj.js} +1 -1
  77. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-8Udu0t8-.js +1 -0
  78. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-8Udu0t8-.js +1 -0
  79. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BjpfWaUr.js → cose-bilkent-JH36ORCC-BUirrMEi.js} +1 -1
  80. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BFQohJgT.js → cynefin-VYW2F7L2-BXzO8iXR.js} +1 -1
  81. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-D3gzRJnS.js → cynefinDiagram-MW4NZA55-DAtgaxIn.js} +1 -1
  82. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-5eojkhoA.js → dagre-VZM6K2ZE-C1re9Noh.js} +1 -1
  83. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CpD8LWu_.js → diagram-7IWD3JNH-N8Kj08J9.js} +1 -1
  84. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B8_4qJ2a.js → diagram-B4RE2ZJO-D6BpSLs3.js} +1 -1
  85. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-HOsXf0eu.js → diagram-LBJQPF4R-C2Vlgnl4.js} +1 -1
  86. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BqwRwiWP.js → diagram-Q27KOJAE-CMbqtVLS.js} +1 -1
  87. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BRVCNZe1.js → diagram-UB23O5K3-A770Eb-0.js} +1 -1
  88. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Cvb1TgGh.js → ebnfDiagram-BXEA7PRR-LV2w_2pT.js} +1 -1
  89. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DS0O0qG9.js → erDiagram-JOGREHBK-bwqf56ah.js} +1 -1
  90. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-BHIRvRr3.js → flowDiagram-UKHOOZJN-BnVtHhZh.js} +1 -1
  91. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DcCJ1JWx.js → ganttDiagram-PKOTCBZU-BGVToEqc.js} +1 -1
  92. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-B9ia5ony.js → gitGraphDiagram-DS77QQ5N-DL2l7Vne.js} +1 -1
  93. package/dist/worker/console/static/assets/{index-wXlQohNs.js → index-B_V4wvXs.js} +44 -44
  94. package/dist/worker/console/static/assets/{index-B9goN3S5.css → index-DcudonhZ.css} +1 -1
  95. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-3ogpgegn.js → infoDiagram-6WML65LV-BWIpubOx.js} +1 -1
  96. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-4tgpQ5SL.js → ishikawaDiagram-WSZJBQD7-DjYBD8vv.js} +1 -1
  97. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DNfgHqFx.js → journeyDiagram-NVQOT4AX-C0_mBaHb.js} +1 -1
  98. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-Dz7ngC8z.js → kanban-definition-27J2QSJJ-Cy71zbX6.js} +1 -1
  99. package/dist/worker/console/static/assets/{linear-DI7Jv62E.js → linear-Dt3_w3Vn.js} +1 -1
  100. package/dist/worker/console/static/assets/{mermaid.core-CQA4Nzmo.js → mermaid.core-DnNOlfEP.js} +5 -5
  101. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-CtsMc8Mf.js → mindmap-definition-FAOFIHXS-DAbTspwq.js} +1 -1
  102. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-ByppE9yH.js → pegDiagram-VL7TDLO6-NNiM141p.js} +1 -1
  103. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B5PtgFgt.js → pieDiagram-7S7Q4E2Y-CN80Z1Do.js} +1 -1
  104. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-Cq4p0k2K.js → quadrantDiagram-CIZ2JOQS-Bxyfh0JU.js} +1 -1
  105. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-DjfkyljN.js → railroadDiagram-AXF67PYL-BlWnC79M.js} +1 -1
  106. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DzynNRSl.js → requirementDiagram-LRYGKXZP-BrEu4P_e.js} +1 -1
  107. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Cj7TCpTJ.js → sankeyDiagram-W5VNT64P-Bt70igBr.js} +1 -1
  108. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-C73C6ykA.js → sequenceDiagram-SI44F4Z6-C8DQR-r9.js} +1 -1
  109. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-BiNLgN2x.js → sizeCapture-X5ZJPWSS-DEMinJAT.js} +1 -1
  110. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-UwvjS64-.js → stateDiagram-OKZ733FA-DDdDBzQc.js} +1 -1
  111. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-CyCiS0Lt.js +1 -0
  112. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-CC7DH98r.js → swimlanes-SLNWSIFB-G2wcBs3T.js} +2 -2
  113. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-U0lhi6N0.js +8 -0
  114. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-LSBXTR70.js → timeline-definition-Z64GVDOM-Dzn4g2gJ.js} +1 -1
  115. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BAuxWwGP.js → vennDiagram-T6HMQDX7-5v2rP9oO.js} +1 -1
  116. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y--E5_gjZx.js → wardleyDiagram-T6FBY63Y-B4EOx7ew.js} +1 -1
  117. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-dJWNmyzF.js → xychartDiagram-ELKLHX3M-CQ1v8eYP.js} +1 -1
  118. package/dist/worker/console/static/index.html +2 -2
  119. package/dist/worker/console/static-src/operator-chat/slash-palette-nav.js +15 -5
  120. package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +2 -0
  121. package/dist/worker/console/static-src/prd-file-import.js +3 -1
  122. package/dist/worker/console/workspace-context.js +6 -1
  123. package/dist/worker/delivery/git-transaction.js +2 -0
  124. package/dist/worker/feature/fullstack-validate.js +2 -0
  125. package/dist/worker/loop-agent/loop-agent-client.js +8 -2
  126. package/dist/worker/materialize/harness-task-materializer.js +4 -1
  127. package/dist/worker/metrics/projector.js +1 -1
  128. package/dist/worker/observability/event-store.js +4 -1
  129. package/dist/worker/observability/read-model.js +4 -1
  130. package/dist/worker/observe/node-transparency.js +23 -1
  131. package/dist/worker/observe/routes.js +4 -0
  132. package/dist/worker/outcomes/declared-artifacts.js +2 -0
  133. package/dist/worker/preflight.js +3 -0
  134. package/dist/worker/task-spec/validate.js +4 -1
  135. package/dist/workflows/dag/decision-envelope.js +2 -0
  136. package/dist/workflows/dag/dynamic-runtime/shared.js +2 -2
  137. package/dist/workflows/dag/frontend-verification-trace.js +14 -10
  138. package/dist/workflows/dag/init-hybrid.js +105 -11
  139. package/dist/workflows/dag/interrupt-request.js +2 -0
  140. package/dist/workflows/dag/lifecycle.js +4 -0
  141. package/dist/workflows/dag/node-execution.js +2 -0
  142. package/dist/workflows/dag/reconcile-run.js +2 -0
  143. package/dist/workflows/dag/repair-artifact.js +3 -1
  144. package/dist/workflows/dag/report.js +2 -0
  145. package/dist/workflows/dag/rerun-task.js +2 -0
  146. package/dist/workflows/dag/types.js +21 -6
  147. package/dist/workflows/dag/validate.js +4 -0
  148. package/docs/governance/README.md +1 -0
  149. package/package.json +3 -1
  150. package/dist/worker/console/static/assets/channel-BxdTlb_5.js +0 -1
  151. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-_ByA1Nf8.js +0 -1
  152. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-_ByA1Nf8.js +0 -1
  153. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-nLgMZ0D3.js +0 -1
  154. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BcYqTady.js +0 -8
@@ -1,10 +1,7 @@
1
1
  /**
2
- * HTTP routes for the Operator Chat browser panel: one read-only probe
3
- * endpoint the panel uses to explain an iframe refusal (X-Frame-Options /
4
- * CSP frame-ancestors are exactly the signals the browser enforces when it
5
- * refuses to embed a site). The probe is display-only (headers back to the
6
- * caller), restricted to http(s) URLs, with a hard timeout. Local addresses
7
- * are allowed — the panel routinely browses local dev servers.
2
+ * HTTP API for the Console Browser panel. The panel renders screenshots from
3
+ * the controlled browser and sends pointer/keyboard input back to the same
4
+ * Playwright page used by Operator Chat tools.
8
5
  */
9
6
  import { embeddabilityOf, extractFrameAncestors, normalizeBrowserUrl, } from "./browser-policy.js";
10
7
  function workspaceIdOf(req) {
@@ -22,7 +19,38 @@ function sendJson(res, status, body) {
22
19
  });
23
20
  res.end(JSON.stringify(body));
24
21
  }
25
- /** Route dispatcher; returns true when the request was handled. */
22
+ function errorPayload(error) {
23
+ return {
24
+ code: error instanceof Error && "code" in error
25
+ ? String(error.code)
26
+ : "BROWSER_OPERATION_FAILED",
27
+ message: error instanceof Error ? error.message : String(error),
28
+ };
29
+ }
30
+ function requireScope(req, deps) {
31
+ const ws = workspaceIdOf(req);
32
+ if (!ws) {
33
+ return { ok: false, status: 400, code: "WORKSPACE_REQUIRED", message: "workspaceId is required" };
34
+ }
35
+ if (deps.requireWorkspace && !deps.requireWorkspace(req).ok) {
36
+ return { ok: false, status: 403, code: "WORKSPACE_DENIED", message: "workspace scope mismatch" };
37
+ }
38
+ return { ok: true };
39
+ }
40
+ async function readJson(req) {
41
+ const chunks = [];
42
+ let size = 0;
43
+ for await (const chunk of req) {
44
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
45
+ size += buffer.byteLength;
46
+ if (size > 1024 * 1024)
47
+ throw new Error("request body exceeds 1MB");
48
+ chunks.push(buffer);
49
+ }
50
+ if (chunks.length === 0)
51
+ return {};
52
+ return JSON.parse(Buffer.concat(chunks).toString("utf8"));
53
+ }
26
54
  export async function handleBrowserRequest(req, res, deps, pathname) {
27
55
  if (!pathname.startsWith("/api/operator/v1/chat/browser"))
28
56
  return false;
@@ -31,27 +59,33 @@ export async function handleBrowserRequest(req, res, deps, pathname) {
31
59
  const parts = rest.split("/").filter(Boolean);
32
60
  const sub = parts[0] ?? "";
33
61
  try {
34
- if (method === "GET" && sub === "probe" && parts.length === 1) {
35
- // Fail-closed: the probe needs a workspaceId like every chat API.
36
- if (deps.requireWorkspace) {
37
- const ws = deps.requireWorkspace(req);
38
- if (!ws.ok) {
39
- sendJson(res, 400, {
40
- ok: false,
41
- error: { code: "WORKSPACE_REQUIRED", message: "workspaceId is required" },
42
- });
43
- return true;
44
- }
62
+ if (method === "GET" && sub === "state" && parts.length === 1) {
63
+ const scope = requireScope(req, deps);
64
+ if (!scope.ok) {
65
+ sendJson(res, scope.status, {
66
+ ok: false,
67
+ error: { code: scope.code, message: scope.message },
68
+ });
69
+ return true;
45
70
  }
46
- else if (!workspaceIdOf(req)) {
47
- sendJson(res, 400, {
71
+ if (!deps.automation) {
72
+ sendJson(res, 200, { ok: true, data: { page: null } });
73
+ return true;
74
+ }
75
+ const page = await deps.automation.state();
76
+ sendJson(res, 200, { ok: true, data: { page } });
77
+ return true;
78
+ }
79
+ if (method === "GET" && sub === "probe" && parts.length === 1) {
80
+ const scope = requireScope(req, deps);
81
+ if (!scope.ok) {
82
+ sendJson(res, scope.status, {
48
83
  ok: false,
49
- error: { code: "WORKSPACE_REQUIRED", message: "workspaceId is required" },
84
+ error: { code: scope.code, message: scope.message },
50
85
  });
51
86
  return true;
52
87
  }
53
- const url = new URL(req.url ?? "/", "http://localhost");
54
- const raw = url.searchParams.get("url") ?? "";
88
+ const raw = new URL(req.url ?? "/", "http://localhost").searchParams.get("url") ?? "";
55
89
  const normalized = normalizeBrowserUrl(raw);
56
90
  if (normalized.kind !== "ok") {
57
91
  sendJson(res, 400, {
@@ -65,26 +99,22 @@ export async function handleBrowserRequest(req, res, deps, pathname) {
65
99
  });
66
100
  return true;
67
101
  }
68
- const parsed = new URL(normalized.url);
69
102
  const controller = new AbortController();
70
103
  const timer = setTimeout(() => controller.abort(), 8000);
71
104
  try {
72
- let response = await fetch(parsed, {
105
+ let response = await fetch(normalized.url, {
73
106
  method: "HEAD",
74
107
  redirect: "follow",
75
108
  signal: controller.signal,
76
109
  });
77
- // Some servers answer HEAD with 405/501; retry once as GET
78
- // (the body is discarded — only the headers matter).
79
110
  if (response.status === 405 || response.status === 501) {
80
- response = await fetch(parsed, {
111
+ response = await fetch(normalized.url, {
81
112
  method: "GET",
82
113
  redirect: "follow",
83
114
  signal: controller.signal,
84
115
  });
85
116
  }
86
- const csp = response.headers.get("content-security-policy");
87
- const frameAncestors = extractFrameAncestors(csp);
117
+ const frameAncestors = extractFrameAncestors(response.headers.get("content-security-policy"));
88
118
  const xFrameOptions = response.headers.get("x-frame-options");
89
119
  const probe = {
90
120
  reachable: true,
@@ -100,11 +130,12 @@ export async function handleBrowserRequest(req, res, deps, pathname) {
100
130
  return true;
101
131
  }
102
132
  catch {
103
- // DNS / TLS / connection / timeout: nothing to judge — the
104
- // client keeps the plain iframe.
105
133
  sendJson(res, 200, {
106
134
  ok: true,
107
- data: { probe: { reachable: false }, verdict: "unknown" },
135
+ data: {
136
+ probe: { reachable: false },
137
+ verdict: "unknown",
138
+ },
108
139
  });
109
140
  return true;
110
141
  }
@@ -112,30 +143,25 @@ export async function handleBrowserRequest(req, res, deps, pathname) {
112
143
  clearTimeout(timer);
113
144
  }
114
145
  }
115
- if (method === "GET" && sub === "commands" && parts.length === 1) {
116
- const ws = workspaceIdOf(req);
117
- if (!ws) {
118
- sendJson(res, 400, {
146
+ if (method === "POST" && parts.length >= 1) {
147
+ const scope = requireScope(req, deps);
148
+ if (!scope.ok) {
149
+ sendJson(res, scope.status, {
119
150
  ok: false,
120
- error: { code: "WORKSPACE_REQUIRED", message: "workspaceId is required" },
151
+ error: { code: scope.code, message: scope.message },
121
152
  });
122
153
  return true;
123
154
  }
124
- if (deps.requireWorkspace) {
125
- const scope = deps.requireWorkspace(req);
126
- if (!scope.ok) {
127
- sendJson(res, 403, {
128
- ok: false,
129
- error: { code: "WORKSPACE_DENIED", message: "workspace scope mismatch" },
130
- });
131
- return true;
132
- }
133
- }
134
155
  if (!deps.automation) {
135
- sendJson(res, 200, { ok: true, data: { commands: [] } });
156
+ sendJson(res, 503, {
157
+ ok: false,
158
+ error: { code: "BROWSER_UNAVAILABLE", message: "browser service unavailable" },
159
+ });
136
160
  return true;
137
161
  }
138
- sendJson(res, 200, { ok: true, data: { commands: deps.automation.take() } });
162
+ const body = await readJson(req);
163
+ const result = await dispatchBrowserPost(deps.automation, sub, body);
164
+ sendJson(res, 200, { ok: true, data: result });
139
165
  return true;
140
166
  }
141
167
  sendJson(res, 404, {
@@ -146,13 +172,7 @@ export async function handleBrowserRequest(req, res, deps, pathname) {
146
172
  }
147
173
  catch (error) {
148
174
  if (!res.headersSent) {
149
- sendJson(res, 500, {
150
- ok: false,
151
- error: {
152
- code: "BROWSER_INTERNAL",
153
- message: error instanceof Error ? error.message : String(error),
154
- },
155
- });
175
+ sendJson(res, 500, { ok: false, error: errorPayload(error) });
156
176
  }
157
177
  else {
158
178
  res.end();
@@ -160,3 +180,101 @@ export async function handleBrowserRequest(req, res, deps, pathname) {
160
180
  return true;
161
181
  }
162
182
  }
183
+ async function dispatchBrowserPost(automation, action, body) {
184
+ switch (action) {
185
+ case "navigate": {
186
+ const result = await automation.navigate(string(body.url));
187
+ if (!result.ok)
188
+ throw new BrowserRouteError(result.code, result.error);
189
+ return result.page;
190
+ }
191
+ case "focus":
192
+ return automation.focus();
193
+ case "reload":
194
+ return automation.reload();
195
+ case "back":
196
+ return automation.goBack();
197
+ case "forward":
198
+ return automation.goForward();
199
+ case "scroll":
200
+ return automation.scroll({
201
+ direction: body.direction === "up" ? "up" : "down",
202
+ amount: numberOrUndefined(body.amount),
203
+ });
204
+ case "tab":
205
+ if (body.mode === "new")
206
+ return automation.newTab(optionalString(body.url));
207
+ if (body.mode === "close")
208
+ return automation.closeTab(numberOrUndefined(body.tabId));
209
+ return automation.selectTab(number(body.tabId));
210
+ case "dialog":
211
+ return automation.handleDialog(body.action === "dismiss" ? "dismiss" : "accept", optionalString(body.promptText));
212
+ case "pointer": {
213
+ const type = string(body.type);
214
+ if (!["mousemove", "mousedown", "mouseup", "wheel"].includes(type)) {
215
+ throw new Error("invalid pointer event type");
216
+ }
217
+ const event = type === "wheel"
218
+ ? {
219
+ type,
220
+ x: number(body.x),
221
+ y: number(body.y),
222
+ deltaX: number(body.deltaX ?? 0),
223
+ deltaY: number(body.deltaY ?? 0),
224
+ }
225
+ : {
226
+ type,
227
+ x: number(body.x),
228
+ y: number(body.y),
229
+ ...(body.button === "middle" || body.button === "right"
230
+ ? { button: body.button }
231
+ : {}),
232
+ };
233
+ return automation.dispatchPointer(event);
234
+ }
235
+ case "keyboard": {
236
+ const type = string(body.type);
237
+ if (type !== "keydown" && type !== "keyup")
238
+ throw new Error("invalid keyboard event type");
239
+ const key = string(body.key);
240
+ if (!isPanelKeyboardKey(key)) {
241
+ throw new Error("invalid keyboard key; use the text action for printable characters");
242
+ }
243
+ return automation.dispatchKeyboard({ type, key });
244
+ }
245
+ case "text":
246
+ return automation.inputText(string(body.text));
247
+ case "wait":
248
+ return automation.waitFor(number(body.ms ?? 500));
249
+ default:
250
+ throw new Error(`unknown browser action: ${action}`);
251
+ }
252
+ }
253
+ class BrowserRouteError extends Error {
254
+ code;
255
+ constructor(code, message) {
256
+ super(message);
257
+ this.code = code;
258
+ this.name = "BrowserRouteError";
259
+ }
260
+ }
261
+ function string(value) {
262
+ if (typeof value !== "string")
263
+ throw new Error("expected string");
264
+ return value;
265
+ }
266
+ function optionalString(value) {
267
+ return typeof value === "string" ? value : undefined;
268
+ }
269
+ function number(value) {
270
+ if (typeof value !== "number" || !Number.isFinite(value))
271
+ throw new Error("expected finite number");
272
+ return value;
273
+ }
274
+ function numberOrUndefined(value) {
275
+ return value === undefined || value === null ? undefined : number(value);
276
+ }
277
+ function isPanelKeyboardKey(key) {
278
+ return /^(Control|Meta|Alt|Shift)(\+[A-Za-z0-9][A-Za-z0-9]*)?$/.test(key)
279
+ || (key.length > 1 && /^[A-Za-z][A-Za-z0-9]*$/.test(key));
280
+ }
@@ -279,8 +279,11 @@ export async function safeGrep(repoRoot, pattern, options) {
279
279
  for (let i = 0; i < lines.length; i++) {
280
280
  if (matches.length >= GREP_MATCH_LIMIT)
281
281
  break;
282
- if (re.test(lines[i])) {
283
- const { scrubbed, redactions } = scrubSecrets(lines[i]);
282
+ const line = lines[i];
283
+ if (line === undefined)
284
+ continue;
285
+ if (re.test(line)) {
286
+ const { scrubbed, redactions } = scrubSecrets(line);
284
287
  if (redactions.length > 0) {
285
288
  for (const r of redactions) {
286
289
  const found = totalRedactions.find((t) => t.name === r.name);
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Session-independent browser tools shared by workflow and Pi chat modes.
3
- * Navigation is visible in the Console sidebar; inspection is server-side and
4
- * bounded to avoid exposing raw credentials or arbitrary page scripts.
2
+ * Session-independent Playwright browser tools shared by workflow and Pi chat
3
+ * modes. Actions use refs from the AI-mode aria snapshot and return a fresh
4
+ * snapshot. Screenshots are captured only by the explicit screenshot tool.
5
5
  */
6
- const BROWSER_TOOLS_DESCRIPTION = "Operate the Console sidebar browser. `browser_navigate` shows a URL in the panel; `browser_search` opens a search URL and returns elements; `browser_inspect` returns title/links/form controls; `browser_act` fills/submits a static GET form or clicks a static link. For natural-language search requests, prefer `browser_search` over navigating to a homepage and simulating its form. It never edits the workspace and cannot execute browser scripts. Dynamic-page and POST-form operations are out of scope.";
6
+ const BROWSER_TOOLS_DESCRIPTION = "Operate the workspace-controlled visible external browser. The Console sidebar stays an iframe and does not proxy page input. `browser_navigate` opens a URL in the external window; `browser_snapshot` returns the current aria snapshot with element refs; `browser_act` clicks/fills/presses/hovers a ref; `browser_search` fills and submits the real search form; `browser_tabs`, `browser_scroll`, `browser_press`, `browser_dialog`, `browser_wait`, and `browser_screenshot` manage state. Use refs only from the immediately preceding snapshot. It never edits workspace files and does not execute page JavaScript.";
7
7
  export async function buildBrowserTools(options) {
8
8
  const [{ Type }, { defineTool }] = await Promise.all([
9
9
  import("typebox"),
@@ -11,7 +11,10 @@ export async function buildBrowserTools(options) {
11
11
  ]);
12
12
  const automation = options.automation;
13
13
  const urlParameter = Type.String({
14
- description: "Absolute http(s) URL. Prefer URLs/element selectors returned by prior browser tools.",
14
+ description: "Absolute http(s) URL.",
15
+ });
16
+ const refParameter = Type.String({
17
+ description: "Element ref from the most recent browser_snapshot (for example e12).",
15
18
  });
16
19
  async function execute(operation) {
17
20
  try {
@@ -37,17 +40,17 @@ export async function buildBrowserTools(options) {
37
40
  return [
38
41
  defineTool({
39
42
  name: "browser_navigate",
40
- label: "Sidebar browser navigate",
43
+ label: "Browser navigate",
41
44
  description: BROWSER_TOOLS_DESCRIPTION,
42
45
  promptSnippet: BROWSER_TOOLS_DESCRIPTION,
43
46
  parameters: Type.Object({ url: urlParameter }, { additionalProperties: false }),
44
47
  async execute(_toolCallId, params) {
45
- return execute(() => automation.navigate(params.url, { includeSnapshot: true }));
48
+ return execute(() => automation.navigate(params.url));
46
49
  },
47
50
  }),
48
51
  defineTool({
49
52
  name: "browser_search",
50
- label: "Sidebar browser search",
53
+ label: "Browser search",
51
54
  description: BROWSER_TOOLS_DESCRIPTION,
52
55
  promptSnippet: BROWSER_TOOLS_DESCRIPTION,
53
56
  parameters: Type.Object({
@@ -59,30 +62,122 @@ export async function buildBrowserTools(options) {
59
62
  },
60
63
  }),
61
64
  defineTool({
62
- name: "browser_inspect",
63
- label: "Sidebar browser inspect",
65
+ name: "browser_snapshot",
66
+ label: "Browser snapshot",
64
67
  description: BROWSER_TOOLS_DESCRIPTION,
65
68
  promptSnippet: BROWSER_TOOLS_DESCRIPTION,
66
- parameters: Type.Object({ url: urlParameter }, { additionalProperties: false }),
67
- async execute(_toolCallId, params) {
68
- return execute(() => automation.inspect(params.url));
69
+ parameters: Type.Object({}, { additionalProperties: false }),
70
+ async execute() {
71
+ return execute(() => automation.snapshot({ screenshot: false }));
69
72
  },
70
73
  }),
71
74
  defineTool({
72
75
  name: "browser_act",
73
- label: "Sidebar browser act",
76
+ label: "Browser act",
74
77
  description: BROWSER_TOOLS_DESCRIPTION,
75
78
  promptSnippet: BROWSER_TOOLS_DESCRIPTION,
76
79
  parameters: Type.Object({
77
- url: urlParameter,
78
- type: Type.Union([Type.Literal("click"), Type.Literal("fill")]),
79
- selector: Type.String({ description: "Selector returned by browser_inspect." }),
80
+ type: Type.Union([
81
+ Type.Literal("click"),
82
+ Type.Literal("fill"),
83
+ Type.Literal("press"),
84
+ Type.Literal("hover"),
85
+ ]),
86
+ ref: refParameter,
80
87
  value: Type.Optional(Type.String()),
88
+ key: Type.Optional(Type.String()),
89
+ }, { additionalProperties: false }),
90
+ async execute(_toolCallId, params) {
91
+ return execute(() => automation.act(params.type === "fill"
92
+ ? { type: "fill", ref: params.ref, value: params.value ?? "" }
93
+ : params.type === "press"
94
+ ? { type: "press", ref: params.ref, key: params.key ?? "Enter" }
95
+ : { type: params.type, ref: params.ref }));
96
+ },
97
+ }),
98
+ defineTool({
99
+ name: "browser_tabs",
100
+ label: "Browser tabs",
101
+ description: BROWSER_TOOLS_DESCRIPTION,
102
+ promptSnippet: BROWSER_TOOLS_DESCRIPTION,
103
+ parameters: Type.Object({
104
+ action: Type.Union([
105
+ Type.Literal("list"),
106
+ Type.Literal("new"),
107
+ Type.Literal("select"),
108
+ Type.Literal("close"),
109
+ ]),
110
+ tabId: Type.Optional(Type.Integer()),
111
+ url: Type.Optional(urlParameter),
112
+ }, { additionalProperties: false }),
113
+ async execute(_toolCallId, params) {
114
+ return execute(() => {
115
+ if (params.action === "list")
116
+ return automation.snapshot({ screenshot: false });
117
+ if (params.action === "new")
118
+ return automation.newTab(params.url);
119
+ if (params.tabId === undefined)
120
+ throw new Error("tabId is required");
121
+ return params.action === "select"
122
+ ? automation.selectTab(params.tabId)
123
+ : automation.closeTab(params.tabId);
124
+ });
125
+ },
126
+ }),
127
+ defineTool({
128
+ name: "browser_scroll",
129
+ label: "Browser scroll",
130
+ description: BROWSER_TOOLS_DESCRIPTION,
131
+ promptSnippet: BROWSER_TOOLS_DESCRIPTION,
132
+ parameters: Type.Object({
133
+ direction: Type.Union([Type.Literal("up"), Type.Literal("down")]),
134
+ amount: Type.Optional(Type.Integer({ minimum: 50, maximum: 3000 })),
135
+ }, { additionalProperties: false }),
136
+ async execute(_toolCallId, params) {
137
+ return execute(() => automation.scroll(params));
138
+ },
139
+ }),
140
+ defineTool({
141
+ name: "browser_press",
142
+ label: "Browser press key",
143
+ description: BROWSER_TOOLS_DESCRIPTION,
144
+ promptSnippet: BROWSER_TOOLS_DESCRIPTION,
145
+ parameters: Type.Object({ key: Type.String() }, { additionalProperties: false }),
146
+ async execute(_toolCallId, params) {
147
+ return execute(() => automation.pressKey(params.key));
148
+ },
149
+ }),
150
+ defineTool({
151
+ name: "browser_dialog",
152
+ label: "Browser dialog",
153
+ description: BROWSER_TOOLS_DESCRIPTION,
154
+ promptSnippet: BROWSER_TOOLS_DESCRIPTION,
155
+ parameters: Type.Object({
156
+ action: Type.Union([Type.Literal("accept"), Type.Literal("dismiss")]),
157
+ promptText: Type.Optional(Type.String()),
81
158
  }, { additionalProperties: false }),
82
159
  async execute(_toolCallId, params) {
83
- return execute(() => automation.act(params.url, params.type === "click"
84
- ? { type: "click", selector: params.selector }
85
- : { type: "fill", selector: params.selector, value: params.value ?? "" }));
160
+ return execute(() => automation.handleDialog(params.action, params.promptText));
161
+ },
162
+ }),
163
+ defineTool({
164
+ name: "browser_wait",
165
+ label: "Browser wait",
166
+ description: BROWSER_TOOLS_DESCRIPTION,
167
+ promptSnippet: BROWSER_TOOLS_DESCRIPTION,
168
+ parameters: Type.Object({ ms: Type.Integer({ minimum: 0, maximum: 10_000 }) }, { additionalProperties: false }),
169
+ async execute(_toolCallId, params) {
170
+ return execute(() => automation.waitFor(params.ms));
171
+ },
172
+ }),
173
+ defineTool({
174
+ name: "browser_screenshot",
175
+ label: "Browser screenshot",
176
+ description: BROWSER_TOOLS_DESCRIPTION,
177
+ promptSnippet: BROWSER_TOOLS_DESCRIPTION,
178
+ parameters: Type.Object({}, { additionalProperties: false }),
179
+ async execute() {
180
+ return execute(() => automation.screenshot());
86
181
  },
87
182
  }),
88
183
  ];
@@ -418,11 +418,17 @@ export class ConsolePiRuntime {
418
418
  exploreOrchestrator;
419
419
  bindings;
420
420
  browserAutomation;
421
+ ownsBrowserAutomation;
421
422
  constructor(options) {
422
423
  this.options = options;
423
424
  this.loader = createOperatorChatResourceLoader();
424
425
  this.bindings = options.bindings ?? createDefaultPiSdkBindings();
425
- this.browserAutomation = options.browserAutomation ?? new BrowserAutomationService();
426
+ this.ownsBrowserAutomation = options.browserAutomation === undefined;
427
+ this.browserAutomation = options.browserAutomation ?? new BrowserAutomationService({
428
+ profileDir: path.join(this.options.sessionDir, "..", "browser-profile"),
429
+ downloadsDir: path.join(this.options.sessionDir, "..", "browser-downloads"),
430
+ screenshotsDir: path.join(this.options.sessionDir, "..", "browser-screenshots"),
431
+ });
426
432
  this.exploreOrchestrator = new ExploreOrchestrator({
427
433
  cwd: this.options.cwd,
428
434
  bindings: this.bindings,
@@ -2202,6 +2208,8 @@ export class ConsolePiRuntime {
2202
2208
  for (const id of [...this.sessions.keys()])
2203
2209
  this.dispose(id);
2204
2210
  void this.exploreOrchestrator.abortAll();
2211
+ if (this.ownsBrowserAutomation)
2212
+ void this.browserAutomation.dispose();
2205
2213
  }
2206
2214
  }
2207
2215
  function mapAssistantMessageEvent(type, sessionId, message) {
@@ -4279,7 +4279,7 @@ async function dispatchChatRequest(req, res, deps, pathname, workspaceScope) {
4279
4279
  return true;
4280
4280
  }
4281
4281
  }
4282
- // Browser probe API (read-only; explains iframe refusals to the panel).
4282
+ // Shared real-browser API for the Browser panel and chat browser tools.
4283
4283
  if (await handleBrowserRequest(req, res, {
4284
4284
  automation: deps.browserAutomation,
4285
4285
  requireWorkspace: () => workspaceScope
@@ -144,7 +144,7 @@ export class SddDataAlignmentError extends Error {
144
144
  }
145
145
  export function selectRandomSddSkillName(random = Math.random) {
146
146
  const index = Math.min(SDD_SKILL_NAMES.length - 1, Math.max(0, Math.floor(random() * SDD_SKILL_NAMES.length)));
147
- return SDD_SKILL_NAMES[index];
147
+ return SDD_SKILL_NAMES[index] ?? "";
148
148
  }
149
149
  export function normalizeSddSkillName(value, random = Math.random) {
150
150
  if (value !== undefined && typeof value !== "string") {
@@ -74,7 +74,7 @@ export const PI_CHAT_SYSTEM_PROMPT_BASE = [
74
74
  "Use read/write/edit/bash/grep/find/ls to inspect and change the workspace. apply_patch, full-tools, shell and coding-chat are denied.",
75
75
  "Agent (Explore) is a built-in read-only subagent for path-uncertain codebase search. Do not use it for a known single-file read. Prefer safe-read/safe-grep for secret-safe probes.",
76
76
  "ask_user_question pauses for a real user answer. todo_write tracks the current work and is restored after compression; it is not a workflow auto-continue signal. The persistent terminal tool is available.",
77
- "Sidebar browser tools (browser_navigate/search/inspect/act) drive the visible Browser panel for user-requested web research and static automation; they never edit workspace files or execute page scripts.",
77
+ "Browser tools (navigate/search/snapshot/act/tabs/scroll/press/dialog/wait/screenshot) drive the workspace-controlled real browser shown in the Browser panel. Use refs from the latest page inspection for element actions; they never edit workspace files or execute page scripts. browser_snapshot means browser page inspection, not workspace snapshots.",
78
78
  "Goal tools (get_goal / create_goal / update_goal) track the session's durable cross-turn objective. Create a Goal only when the user explicitly asks to start one; iterate in bounded rounds until complete or blocked.",
79
79
  "This session keeps Console compression (L0/L1/L2, sift, strict checkpoint) and existing Aimax / SDD access. Do not create tasks, run DAGs, or start requirement interviews from this session.",
80
80
  "Obey repository AGENTS.md, skills and extensions when they apply. Choosing Pi mode is not extra write authorization and does not bypass Console access control or output scrubbing.",
@@ -27,8 +27,14 @@ export const OPERATOR_CHAT_BUILTIN_CUSTOM_TOOLS = Object.freeze([
27
27
  "scm",
28
28
  "browser_navigate",
29
29
  "browser_search",
30
- "browser_inspect",
30
+ "browser_snapshot",
31
31
  "browser_act",
32
+ "browser_tabs",
33
+ "browser_scroll",
34
+ "browser_press",
35
+ "browser_dialog",
36
+ "browser_wait",
37
+ "browser_screenshot",
32
38
  ]);
33
39
  /**
34
40
  * Actions the model MAY invoke. Derived from the registry but filtered by the
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-BAy7Yd6y.js";import{p as f}from"./chunk-JWPE2WC7-DPz7SZ8V.js";import{_ as n,l as o}from"./mermaid.core-CQA4Nzmo.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BFQohJgT.js";import"./index-wXlQohNs.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-6Q2QTUOP-DHO38w5U.js";import{p as f}from"./chunk-JWPE2WC7-CrFLKqkT.js";import{_ as n,l as o}from"./mermaid.core-DnNOlfEP.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BXzO8iXR.js";import"./index-B_V4wvXs.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-CQA4Nzmo.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-DnNOlfEP.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};