@tea-agent/loop-agent 0.39.0-beta.2 → 0.39.0-beta.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 (202) hide show
  1. package/AGENTS.md +4 -1
  2. package/CHANGELOG.md +187 -92
  3. package/README.md +9 -5
  4. package/bin/loop-agent.js +7 -3
  5. package/dist/application/task-lifecycle/recommendations.js +13 -2
  6. package/dist/build-stamp.json +3 -3
  7. package/dist/cli/command-definitions.js +16 -5
  8. package/dist/cli/program.js +16 -2
  9. package/dist/cli/update/notifier.js +2 -2
  10. package/dist/cli.js +2 -1
  11. package/dist/commands/dag-rerun.js +55 -1
  12. package/dist/commands/init-model-catalog.js +464 -0
  13. package/dist/commands/init-upgrade.js +265 -97
  14. package/dist/commands/init.js +429 -28
  15. package/dist/commands/inspect-next.js +8 -0
  16. package/dist/executors/dag-pi-executor.js +1691 -29
  17. package/dist/executors/pi-extension-resolver.js +233 -0
  18. package/dist/executors/pi-playwright-cli-tool.js +51 -12
  19. package/dist/executors/pi-sdk-executor.js +180 -33
  20. package/dist/executors/shell-executor.js +1152 -171
  21. package/dist/executors/shell-write-guard.js +14 -0
  22. package/dist/shared/dag-prompt-override.js +28 -0
  23. package/dist/shared/openspec-spec.js +70 -4
  24. package/dist/shared/operator/capabilities.js +32 -0
  25. package/dist/shared/playwright-cli-command-policy.js +15 -0
  26. package/dist/shared/update/console-notifier.js +100 -0
  27. package/dist/{cli → shared}/update/npm-client.js +41 -8
  28. package/dist/{cli → shared}/update/state.js +41 -13
  29. package/dist/task/config-types.js +19 -5
  30. package/dist/task/contract/project.js +3 -0
  31. package/dist/task/contract/schema.js +2 -1
  32. package/dist/task/frontend-project-capability.js +60 -17
  33. package/dist/task/source-prepare/parse-intent.js +24 -4
  34. package/dist/task/source-prepare/prepare.js +36 -0
  35. package/dist/worker/cli.js +31 -1
  36. package/dist/worker/console/chat/pi-console-config.js +81 -10
  37. package/dist/worker/console/chat/routes.js +1 -0
  38. package/dist/worker/console/dag-execution-receipt.js +33 -0
  39. package/dist/worker/console/frontend-human-decision-adapter.js +19 -0
  40. package/dist/worker/console/frontend-split-operation-adapter.js +20 -0
  41. package/dist/worker/console/index.js +3 -0
  42. package/dist/worker/console/operation-store.js +226 -6
  43. package/dist/worker/console/operator-actions.js +263 -0
  44. package/dist/worker/console/operator-user-error.js +2 -2
  45. package/dist/worker/console/routes.js +43 -2
  46. package/dist/worker/console/security.js +63 -9
  47. package/dist/worker/console/server.js +151 -6
  48. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4kVYweA.js → abnfDiagram-N423BO3Z-zsNyvGaH.js} +1 -1
  49. package/dist/worker/console/static/assets/{arc-Bj2M8iO5.js → arc-BDjZ5kE1.js} +1 -1
  50. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CLlXe4-6.js → architectureDiagram-T3A2C74G-BkgaujnN.js} +1 -1
  51. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-psEp5xH0.js → blockDiagram-VBNYF7ZC-CqxOJi0j.js} +1 -1
  52. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DeKcOCGJ.js → c4Diagram-5PPSVZJV-C2JHLdRi.js} +1 -1
  53. package/dist/worker/console/static/assets/channel-BuqaGKAT.js +1 -0
  54. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-K0C744p1.js → chunk-2GRJ4B5K-DF_YSvOS.js} +1 -1
  55. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-xbNw4J9-.js → chunk-2Q5K7J3B-D3Ort5Vo.js} +1 -1
  56. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DjLaSDUO.js → chunk-5RXB4S5H-XfAfZeUC.js} +1 -1
  57. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-CtiPlKel.js → chunk-5VM5RSS4-SLBibhf5.js} +1 -1
  58. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DZtolir7.js → chunk-6Q2QTUOP-Dz29Ye_f.js} +1 -1
  59. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CPcdNeew.js → chunk-GF5L2VYU-DB2G4H8V.js} +1 -1
  60. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-NgHc6V37.js → chunk-JWPE2WC7-CIoGkxdu.js} +1 -1
  61. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DQ_T-hg8.js → chunk-KBJHAD2P-CG78FGkn.js} +1 -1
  62. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DgLsxcVP.js → chunk-RYQCIY6F-ZDHAvXPd.js} +1 -1
  63. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-UrVoM9z1.js → chunk-XXDRQBXY-BKkkC4VA.js} +1 -1
  64. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DNdSHjH9.js +1 -0
  65. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DNdSHjH9.js +1 -0
  66. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CLkYvTb3.js → cose-bilkent-JH36ORCC-SposUZsO.js} +1 -1
  67. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BwT_xKrE.js → cynefin-VYW2F7L2-BSCtQpD7.js} +1 -1
  68. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Bi9tuzif.js → cynefinDiagram-MW4NZA55-DgFHrw9l.js} +1 -1
  69. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BCIqkWBV.js → dagre-VZM6K2ZE-BVBasYbj.js} +1 -1
  70. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-Dip6l9_Z.js → diagram-7IWD3JNH-6r_4rN_c.js} +1 -1
  71. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B-xkh_wK.js → diagram-B4RE2ZJO-JmuaB41P.js} +1 -1
  72. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DZO0kTt_.js → diagram-LBJQPF4R-xXvAY3sk.js} +1 -1
  73. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-D6ZplNbZ.js → diagram-Q27KOJAE-D2B3lY2o.js} +1 -1
  74. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BPekbhoS.js → diagram-UB23O5K3-tK54tMEX.js} +1 -1
  75. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BtmaJpK5.js → ebnfDiagram-BXEA7PRR-CNtELzV-.js} +1 -1
  76. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-6DS0Xc44.js → erDiagram-JOGREHBK-C1xKMKcW.js} +1 -1
  77. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CihnROSm.js → flowDiagram-UKHOOZJN-CZ7dlPMz.js} +1 -1
  78. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CZC4zOE2.js → ganttDiagram-PKOTCBZU-BqGb42Xe.js} +1 -1
  79. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Dq1fhzGN.js → gitGraphDiagram-DS77QQ5N-D_BlXEtt.js} +1 -1
  80. package/dist/worker/console/static/assets/{index-DTZOKgAn.js → index-D5zGX6fG.js} +68 -68
  81. package/dist/worker/console/static/assets/index-DBbhESQ_.css +1 -0
  82. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DlSl4BGx.js → infoDiagram-6WML65LV-Vce2vmIe.js} +1 -1
  83. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-snnzFl_U.js → ishikawaDiagram-WSZJBQD7-DDwVBAvI.js} +1 -1
  84. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-BDE7qpMx.js → journeyDiagram-NVQOT4AX-y_Ew-wv4.js} +1 -1
  85. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-CD2Ci04G.js → kanban-definition-27J2QSJJ-CjXJFp1K.js} +1 -1
  86. package/dist/worker/console/static/assets/{linear-DdnapKIH.js → linear-1itMst1Q.js} +1 -1
  87. package/dist/worker/console/static/assets/{mermaid.core-BVjAT9b8.js → mermaid.core-C-D3ZRUa.js} +5 -5
  88. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-D0yJk-zA.js → mindmap-definition-FAOFIHXS-BiYywmZc.js} +1 -1
  89. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BVo9tFP-.js → pegDiagram-VL7TDLO6-l2fydNWA.js} +1 -1
  90. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DnOV-mZ_.js → pieDiagram-7S7Q4E2Y-Dz0hNbYW.js} +1 -1
  91. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-CzUJo58i.js → quadrantDiagram-CIZ2JOQS-BujI_mLZ.js} +1 -1
  92. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Bvikrolh.js → railroadDiagram-AXF67PYL-pWe84beb.js} +1 -1
  93. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DtaSVCap.js → requirementDiagram-LRYGKXZP-ByYu2frg.js} +1 -1
  94. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-C2c9A0wW.js → sankeyDiagram-W5VNT64P-CoPnilFP.js} +1 -1
  95. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DmXJcU7r.js → sequenceDiagram-SI44F4Z6-1Md2LnS0.js} +1 -1
  96. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B4GUFW92.js → sizeCapture-X5ZJPWSS-DqqqAoSH.js} +1 -1
  97. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Dsad2MXf.js → stateDiagram-OKZ733FA-C4sGkf--.js} +1 -1
  98. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8rmop_9.js +1 -0
  99. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DGq48Fbi.js → swimlanes-SLNWSIFB-ByxJrUzW.js} +2 -2
  100. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-B0ky-kBM.js +8 -0
  101. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CSSi6OFf.js → timeline-definition-Z64GVDOM-D8MLgM0O.js} +1 -1
  102. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BqyzPrWv.js → vennDiagram-T6HMQDX7-DnBis-wZ.js} +1 -1
  103. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DlznVb6S.js → wardleyDiagram-T6FBY63Y-uuyYT7UO.js} +1 -1
  104. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CfBcgJ_K.js → xychartDiagram-ELKLHX3M-BjgabhwK.js} +1 -1
  105. package/dist/worker/console/static/index.html +2 -2
  106. package/dist/worker/console/static-src/active-run-badge.js +17 -0
  107. package/dist/worker/console/static-src/operator-chat/mutation-gate.js +1 -1
  108. package/dist/worker/loop-agent/loop-agent-client.js +7 -3
  109. package/dist/worker/materialize/frontend-split-task-materializer.js +72 -0
  110. package/dist/worker/observe/node-input.js +74 -3
  111. package/dist/worker/observe/node-process.js +377 -0
  112. package/dist/worker/observe/routes.js +36 -3
  113. package/dist/worker/observe/shell-handler-keys.js +34 -0
  114. package/dist/worker/observe/static/api.js +66 -0
  115. package/dist/worker/observe/static/constants.js +8 -1
  116. package/dist/worker/observe/static/dag-history-labels.js +4 -0
  117. package/dist/worker/observe/static/format.js +23 -0
  118. package/dist/worker/observe/static/markdown-render.js +20 -1
  119. package/dist/worker/observe/static/operator-chrome.js +4 -0
  120. package/dist/worker/observe/static/state.js +13 -2
  121. package/dist/worker/observe/static/styles.css +73 -0
  122. package/dist/worker/observe/static/views/dag-inspector.js +612 -8
  123. package/dist/worker/observe/static/views/dag.js +8 -1
  124. package/dist/worker/observe/static/views/failures.js +5 -2
  125. package/dist/worker/observe/static/views/session-timeline.js +78 -9
  126. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +20 -2
  127. package/dist/workflows/dag/contract-output-registry.js +15 -0
  128. package/dist/workflows/dag/contract-validator-registrations.js +1 -2
  129. package/dist/workflows/dag/failure-category.js +12 -0
  130. package/dist/workflows/dag/frontend-closeout.js +221 -0
  131. package/dist/workflows/dag/frontend-design-policy.js +366 -0
  132. package/dist/workflows/dag/frontend-human-decision.js +182 -0
  133. package/dist/workflows/dag/frontend-implementation-contract.js +378 -160
  134. package/dist/workflows/dag/frontend-prewrite-gate.js +343 -391
  135. package/dist/workflows/dag/frontend-provider-capability-matrix.js +159 -0
  136. package/dist/workflows/dag/frontend-recovery-capsule.js +455 -0
  137. package/dist/workflows/dag/frontend-recovery-controller.js +201 -0
  138. package/dist/workflows/dag/frontend-recovery-lineage.js +178 -0
  139. package/dist/workflows/dag/frontend-recovery-plan.js +17 -10
  140. package/dist/workflows/dag/frontend-recovery-run.js +33 -20
  141. package/dist/workflows/dag/frontend-repair.js +7 -424
  142. package/dist/workflows/dag/frontend-review-context.js +195 -8
  143. package/dist/workflows/dag/frontend-risk.js +15 -2
  144. package/dist/workflows/dag/frontend-shadow-dual-write.js +665 -0
  145. package/dist/workflows/dag/frontend-shape-capsule-store.js +191 -0
  146. package/dist/workflows/dag/frontend-shape-facts.js +409 -0
  147. package/dist/workflows/dag/frontend-shape.js +425 -0
  148. package/dist/workflows/dag/frontend-split-application-service.js +203 -0
  149. package/dist/workflows/dag/frontend-split-orchestrator.js +899 -0
  150. package/dist/workflows/dag/frontend-test-case-checklist.js +26 -2
  151. package/dist/workflows/dag/frontend-test-case-manifest.js +5 -0
  152. package/dist/workflows/dag/frontend-test-case-quality.js +5 -13
  153. package/dist/workflows/dag/frontend-test-environment-probe.js +227 -0
  154. package/dist/workflows/dag/frontend-test-markdown.js +61 -0
  155. package/dist/workflows/dag/frontend-test-result-contract.js +160 -28
  156. package/dist/workflows/dag/frontend-test-standard-scenarios.js +68 -0
  157. package/dist/workflows/dag/frontend-typed-event-store.js +439 -0
  158. package/dist/workflows/dag/frontend-typed-event-transaction.js +180 -0
  159. package/dist/workflows/dag/frontend-verification-trace.js +52 -17
  160. package/dist/workflows/dag/frontend-worktree-diff.js +97 -18
  161. package/dist/workflows/dag/frontend-writer-admission.js +260 -0
  162. package/dist/workflows/dag/frontend-writer-status.js +244 -0
  163. package/dist/workflows/dag/init-hybrid.js +572 -500
  164. package/dist/workflows/dag/node-execution.js +307 -70
  165. package/dist/workflows/dag/prompt.js +10 -18
  166. package/dist/workflows/dag/rerun-plan.js +144 -5
  167. package/dist/workflows/dag/rerun-run.js +58 -6
  168. package/dist/workflows/dag/retry-policy.js +228 -4
  169. package/dist/workflows/dag/runner.js +314 -119
  170. package/dist/workflows/dag/scheduler.js +114 -16
  171. package/dist/workflows/dag/structured-output-repair.js +712 -0
  172. package/dist/workflows/dag/types.js +235 -23
  173. package/dist/workflows/dag/upstream-artifacts.js +0 -4
  174. package/dist/workflows/dag/validate.js +60 -10
  175. package/docs/init-surface.manifest.json +5 -0
  176. package/docs/operations/README.md +1 -1
  177. package/docs/templates/agent-dag.schema.json +44 -0
  178. package/docs/templates/frontend-test-dag.json +8 -10
  179. package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +1 -1
  180. package/docs/templates/init-managed-agents.md +13 -3
  181. package/harness.json +3 -3
  182. package/package.json +5 -1
  183. package/scripts/next-info.mjs +356 -0
  184. package/scripts/next-publish-gate.mjs +238 -0
  185. package/scripts/release-source-binding.mjs +251 -0
  186. package/skills/codebase-scout/SKILL.md +1 -1
  187. package/skills/fe-test-ui-scout/SKILL.md +65 -0
  188. package/skills/fe-test-ui-scout/references/ledger-schema.md +62 -0
  189. package/skills/fe-test-ui-scout/references/recon-protocol.md +54 -0
  190. package/skills/frontend-implementation/SKILL.md +4 -4
  191. package/skills/frontend-implementation/references/design-spec.md +11 -7
  192. package/skills/frontend-implementation/references/node-contracts.md +20 -11
  193. package/skills/loop-agent/references/command-reference.md +11 -4
  194. package/skills/loop-agent/references/hybrid-dag.md +1 -1
  195. package/skills/playwright-cli/SKILL.md +22 -0
  196. package/skills/playwright-cli-case-generator/SKILL.md +20 -1
  197. package/dist/worker/console/static/assets/channel-CPF4N7pf.js +0 -1
  198. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C2DwA_Y1.js +0 -1
  199. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C2DwA_Y1.js +0 -1
  200. package/dist/worker/console/static/assets/index-Ya5FE7cD.css +0 -1
  201. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8FB_cNk.js +0 -1
  202. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CrZYaWfx.js +0 -8
@@ -116,6 +116,7 @@ async function handleRecoveryCandidates(_req, res, ctx, url) {
116
116
  }
117
117
  async function handleSessionPing(req, res, ctx) {
118
118
  const failure = evaluateMutationGate(req, {
119
+ cookieName: ctx.bootToken.cookieName,
119
120
  bootToken: ctx.bootToken.value,
120
121
  confirmationToken: ctx.bootToken.confirmationToken,
121
122
  consoleOrigin: ctx.getConsoleOrigin(),
@@ -130,6 +131,16 @@ async function handleSessionPing(req, res, ctx) {
130
131
  }
131
132
  sendJson(res, 200, { ok: true, pong: true });
132
133
  }
134
+ /**
135
+ * Actions the inspect-scoped mutation token may dispatch. Deliberately
136
+ * minimal: the experimental prompt-override rerun tab needs plan preflight +
137
+ * execution only. Everything else (task creation, runDag, reconcile, chat,
138
+ * worker actions…) requires the general Console token.
139
+ */
140
+ export const INSPECT_MUTATION_ALLOWED_ACTIONS = new Set([
141
+ "dagRerunPlan",
142
+ "dagRerun",
143
+ ]);
133
144
  async function handleCreateOperation(req, res, ctx) {
134
145
  if (!ctx.operator) {
135
146
  sendJson(res, 503, {
@@ -141,12 +152,31 @@ async function handleCreateOperation(req, res, ctx) {
141
152
  });
142
153
  return;
143
154
  }
144
- const failure = evaluateMutationGate(req, {
155
+ const generalGateContext = {
156
+ cookieName: ctx.bootToken.cookieName,
145
157
  bootToken: ctx.bootToken.value,
146
158
  confirmationToken: ctx.bootToken.confirmationToken,
147
159
  consoleOrigin: ctx.getConsoleOrigin(),
148
160
  allowNonLoopbackAccess: ctx.allowNonLoopbackAccess === true,
149
- });
161
+ };
162
+ let failure = evaluateMutationGate(req, generalGateContext);
163
+ let inspectScoped = false;
164
+ if (failure && ctx.inspectBootToken) {
165
+ // Scoped /inspect credentials: try the inspect gate before failing. The
166
+ // general gate already rejected, so passing here only ever yields the
167
+ // allowlisted actions below — never general write capability.
168
+ const scopedFailure = evaluateMutationGate(req, {
169
+ cookieName: ctx.inspectBootToken.cookieName,
170
+ bootToken: ctx.inspectBootToken.value,
171
+ confirmationToken: ctx.inspectBootToken.confirmationToken,
172
+ consoleOrigin: ctx.getConsoleOrigin(),
173
+ allowNonLoopbackAccess: ctx.allowNonLoopbackAccess === true,
174
+ });
175
+ if (!scopedFailure) {
176
+ inspectScoped = true;
177
+ failure = undefined;
178
+ }
179
+ }
150
180
  if (failure) {
151
181
  sendJson(res, failure.status, {
152
182
  ok: false,
@@ -173,6 +203,16 @@ async function handleCreateOperation(req, res, ctx) {
173
203
  ? body.actionParams
174
204
  : {};
175
205
  const clientRequestId = typeof body.clientRequestId === "string" ? body.clientRequestId : undefined;
206
+ if (inspectScoped && !INSPECT_MUTATION_ALLOWED_ACTIONS.has(action)) {
207
+ sendJson(res, 403, {
208
+ ok: false,
209
+ error: {
210
+ code: "ACTION_NOT_IN_INSPECT_SCOPE",
211
+ message: `inspect-scoped token only allows: ${[...INSPECT_MUTATION_ALLOWED_ACTIONS].join(", ")}`,
212
+ },
213
+ });
214
+ return;
215
+ }
176
216
  const result = await dispatchOperatorAction(ctx.operator.actionContext, {
177
217
  action,
178
218
  actionParams,
@@ -428,6 +468,7 @@ export async function handleConsoleOperatorRequest(req, res, ctx) {
428
468
  }
429
469
  if (isMutationMethod(method)) {
430
470
  const failure = evaluateMutationGate(req, {
471
+ cookieName: ctx.bootToken.cookieName,
431
472
  bootToken: ctx.bootToken.value,
432
473
  confirmationToken: ctx.bootToken.confirmationToken,
433
474
  consoleOrigin: ctx.getConsoleOrigin(),
@@ -1,24 +1,78 @@
1
- import { randomBytes, timingSafeEqual } from "node:crypto";
1
+ import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
2
2
  import { isLoopbackHost } from "./loopback.js";
3
+ /** Prefix for instance-scoped Cookie names; not a lookup name. */
3
4
  export const BOOT_CAPABILITY_COOKIE = "loop_console_capability";
4
5
  /** Custom mutation confirmation header (design §9). JS-readable; not the HttpOnly boot cookie. */
5
6
  export const CONFIRMATION_TOKEN_HEADER = "x-loop-console-confirmation";
6
- /** Issue per-process unguessable boot capability + confirmation tokens. */
7
- export function issueBootCapabilityToken() {
7
+ function normalizeInstanceScope(scope) {
8
+ const repoFingerprint = scope.repoFingerprint.trim();
9
+ if (!repoFingerprint) {
10
+ throw new Error("console instance scope requires a non-empty repoFingerprint");
11
+ }
12
+ const bindHost = scope.bindHost.trim();
13
+ if (!bindHost) {
14
+ throw new Error("console instance scope requires a non-empty bindHost");
15
+ }
16
+ if (!Number.isInteger(scope.configuredPort) || scope.configuredPort < 0) {
17
+ throw new Error(`console instance scope configuredPort must be an integer >= 0, got ${String(scope.configuredPort)}`);
18
+ }
19
+ const instanceNonce = scope.instanceNonce?.trim();
20
+ if (scope.configuredPort === 0) {
21
+ if (!instanceNonce) {
22
+ throw new Error("console instance scope requires a non-empty instanceNonce when configuredPort is 0");
23
+ }
24
+ return {
25
+ repoFingerprint,
26
+ bindHost,
27
+ configuredPort: 0,
28
+ instanceNonce,
29
+ };
30
+ }
31
+ return {
32
+ repoFingerprint,
33
+ bindHost,
34
+ configuredPort: scope.configuredPort,
35
+ };
36
+ }
37
+ /** Deterministic Cookie name for one Console instance; never includes repo path or token. */
38
+ export function deriveBootCapabilityCookieName(scope, variant) {
39
+ const normalized = normalizeInstanceScope(scope);
40
+ const digest = createHash("sha256")
41
+ .update("loop-console-capability-v1\0", "utf8")
42
+ .update(normalized.repoFingerprint, "utf8")
43
+ .update("\0", "utf8")
44
+ .update(normalized.bindHost, "utf8")
45
+ .update("\0", "utf8")
46
+ .update(String(normalized.configuredPort), "utf8")
47
+ .update("\0", "utf8")
48
+ .update(normalized.instanceNonce ?? "", "utf8")
49
+ .update("\0", "utf8")
50
+ .update(variant ?? "", "utf8")
51
+ .digest("hex")
52
+ .slice(0, 32);
53
+ return `${BOOT_CAPABILITY_COOKIE}_${digest}`;
54
+ }
55
+ /** Issue per-process unguessable boot capability + confirmation tokens.
56
+ * `variant` (e.g. "inspect") derives a separate cookie name so scoped
57
+ * credentials cannot be replayed against the general mutation surface. */
58
+ export function issueBootCapabilityToken(scope, options = {}) {
59
+ const cookieName = deriveBootCapabilityCookieName(scope, options.variant);
8
60
  const value = randomBytes(32).toString("base64url");
9
61
  const confirmationToken = randomBytes(32).toString("base64url");
10
62
  const setCookieHeader = [
11
- `${BOOT_CAPABILITY_COOKIE}=${value}`,
63
+ `${cookieName}=${value}`,
12
64
  "HttpOnly",
13
65
  "SameSite=Strict",
14
66
  "Path=/",
15
67
  ].join("; ");
16
- return { value, setCookieHeader, confirmationToken };
68
+ return { cookieName, value, setCookieHeader, confirmationToken };
17
69
  }
18
- /** Inject confirmation token into HTML so the SPA can send the mutation header. */
19
- export function injectConfirmationTokenScript(html, confirmationToken) {
70
+ /** Inject confirmation token into HTML so the SPA can send the mutation
71
+ * header. `varName` separates the general Console token from the scoped
72
+ * inspect token on the read-only /inspect surface. */
73
+ export function injectConfirmationTokenScript(html, confirmationToken, varName = "__CONSOLE_CONFIRMATION_TOKEN__") {
20
74
  const source = typeof html === "string" ? html : html.toString("utf8");
21
- const script = `<script>window.__CONSOLE_CONFIRMATION_TOKEN__=${JSON.stringify(confirmationToken)};</script>`;
75
+ const script = `<script>window.${varName}=${JSON.stringify(confirmationToken)};</script>`;
22
76
  if (source.includes("</head>")) {
23
77
  return Buffer.from(source.replace("</head>", `${script}</head>`), "utf8");
24
78
  }
@@ -74,7 +128,7 @@ function loopbackOriginMatches(origin, consoleOrigin) {
74
128
  return originKey !== null && consoleKey !== null && originKey === consoleKey;
75
129
  }
76
130
  export function evaluateMutationGate(req, ctx) {
77
- const cookieToken = parseCookieHeader(req.headers.cookie, BOOT_CAPABILITY_COOKIE);
131
+ const cookieToken = parseCookieHeader(req.headers.cookie, ctx.cookieName);
78
132
  if (!cookieToken) {
79
133
  return {
80
134
  status: 403,
@@ -1,11 +1,12 @@
1
1
  import { randomBytes } from "node:crypto";
2
2
  import { existsSync } from "node:fs";
3
+ import { rm } from "node:fs/promises";
3
4
  import { createServer } from "node:http";
4
5
  import path from "node:path";
5
6
  import { fileURLToPath } from "node:url";
6
7
  import { LoopAgentClient } from "../loop-agent/loop-agent-client.js";
7
8
  import { DAG_ABSOLUTE_MAX_WALL_CLOCK_MS } from "../../shared/timeout-policy.js";
8
- import { openConsoleAppData } from "./app-data.js";
9
+ import { openConsoleAppData, sha256Json, writeSecureJson } from "./app-data.js";
9
10
  import { DagConfirmationStore } from "./dag-confirmation.js";
10
11
  import { DagExecutionReceiptStore } from "./dag-execution-receipt.js";
11
12
  import { DraftStore } from "./draft-store.js";
@@ -19,10 +20,14 @@ import { ConsolePiRuntime } from "./chat/pi-runtime.js";
19
20
  import { handleChatRequest, recoverDeferredTurns, } from "./chat/routes.js";
20
21
  import { createOperationEventStore, } from "./operation-sse.js";
21
22
  import { OperationStore } from "./operation-store.js";
23
+ import { createFrontendSplitOperationAdapter, } from "./frontend-split-operation-adapter.js";
24
+ import { createFrontendHumanDecisionAdapter } from "./frontend-human-decision-adapter.js";
25
+ import { FrontendSplitTaskMaterializer, } from "../materialize/frontend-split-task-materializer.js";
22
26
  import { probePiReadiness, } from "./pi-readiness.js";
23
27
  import { handleConsoleHealthRequest, handleConsoleOperatorRequest, sendJson, serveConsoleStatic, } from "./routes.js";
24
- import { issueBootCapabilityToken } from "./security.js";
28
+ import { issueBootCapabilityToken, injectConfirmationTokenScript, } from "./security.js";
25
29
  import { resolveSiblingLoopAgentBin } from "./sibling-controller.js";
30
+ import { isDagRerunPromptOverrideEnabled } from "../../shared/dag-prompt-override.js";
26
31
  import { NightAuxTicker } from "./night-aux-ticker.js";
27
32
  import { deriveObserveRouteCapabilities } from "../observe/health.js";
28
33
  import { createObserveRouteContext, defaultObserveStaticDir, handleMatchedObserveRoute, matchObserveGetRoute, ROUTES, serveObserveStatic, } from "../observe/routes.js";
@@ -66,7 +71,7 @@ export async function createConsoleServer(options) {
66
71
  process.stderr.write(`console: binding non-loopback host ${host} (Operator mutations enabled; no network auth — expose only on trusted networks)\n`);
67
72
  }
68
73
  const repoRoot = path.resolve(options.repoRoot);
69
- const port = options.port ?? 8790;
74
+ const configuredPort = options.port ?? 8790;
70
75
  const debug = options.debug === true;
71
76
  const keepAliveTimeoutMs = options.keepAliveTimeoutMs ?? 65_000;
72
77
  const staticDir = options.staticDir ?? defaultConsoleStaticDir();
@@ -74,16 +79,135 @@ export async function createConsoleServer(options) {
74
79
  const observeRouteContext = createObserveRouteContext(repoRoot, {
75
80
  staticDir: inspectStaticDir,
76
81
  });
77
- const bootToken = issueBootCapabilityToken();
78
82
  const operatorSessionId = `sess_${randomBytes(16).toString("hex")}`;
79
83
  const appData = openConsoleAppData({
80
84
  repoRoot,
81
85
  appDataRoot: options.appDataRoot,
82
86
  });
87
+ const instanceNonce = configuredPort === 0 ? randomBytes(16).toString("hex") : undefined;
88
+ const bootToken = issueBootCapabilityToken({
89
+ repoFingerprint: appData.fingerprint,
90
+ bindHost: host,
91
+ configuredPort,
92
+ ...(instanceNonce ? { instanceNonce } : {}),
93
+ });
94
+ // Scoped credentials for the experimental /inspect prompt-override rerun:
95
+ // separate cookie name + confirmation token so the read-only inspect page
96
+ // can never replay them against the general Console mutation surface.
97
+ const inspectBootToken = issueBootCapabilityToken({
98
+ repoFingerprint: appData.fingerprint,
99
+ bindHost: host,
100
+ configuredPort,
101
+ ...(instanceNonce ? { instanceNonce } : {}),
102
+ }, { variant: "inspect" });
83
103
  const operations = new OperationStore(appData);
84
104
  const events = createOperationEventStore({
85
105
  persistenceDir: path.join(appData.operations, "events"),
86
106
  });
107
+ // Frontend split production wiring (C): deterministic, idempotent
108
+ // materialization backend over OperationStore + canonical orchestrator
109
+ // adapter. runtimeSupportsSplit stays false here (Task AB owns the real
110
+ // runner); schedule records a durable idempotent intent fact instead of
111
+ // invoking scheduleOperation, and child/integration terminal states arrive
112
+ // via childCallback / integrationCallback.
113
+ const splitScheduleDir = path.join(appData.root, "frontend-split-schedule");
114
+ const splitAuditDir = path.join(appData.root, "frontend-split-audit");
115
+ const splitAggregateDir = path.join(appData.root, "frontend-split-aggregate");
116
+ const splitMaterializationBackend = {
117
+ async ensureTask({ taskId }) {
118
+ // Child/integration identity is already validated by the materializer
119
+ // request schema; Console keeps no separate durable task record.
120
+ return { taskId, complete: true };
121
+ },
122
+ async ensureOperation({ taskId, operationId, payloadDigest, request }) {
123
+ const action = request.kind === "child" ? "frontendSplitChild" : "frontendSplitIntegration";
124
+ const { operation } = await operations.ensureSplitMaterializedOperation({
125
+ operationId,
126
+ taskId,
127
+ action,
128
+ actionParams: request,
129
+ payloadHash: payloadDigest,
130
+ });
131
+ return {
132
+ taskId: operation.taskId ?? taskId,
133
+ operationId: operation.operationId,
134
+ complete: true,
135
+ };
136
+ },
137
+ };
138
+ const materializer = new FrontendSplitTaskMaterializer(splitMaterializationBackend);
139
+ const schedule = async (input) => {
140
+ const fact = {
141
+ schemaVersion: 1,
142
+ kind: "frontend-split-schedule-intent",
143
+ operationId: input.operationId,
144
+ generation: input.generation,
145
+ bindingDigest: input.bindingDigest,
146
+ recordedAt: new Date().toISOString(),
147
+ };
148
+ const name = `${sha256Json({
149
+ operationId: input.operationId,
150
+ generation: input.generation,
151
+ bindingDigest: input.bindingDigest,
152
+ })}.json`;
153
+ await writeSecureJson(path.join(splitScheduleDir, name), fact);
154
+ };
155
+ const auditStale = async (input) => {
156
+ const fact = {
157
+ schemaVersion: 1,
158
+ kind: "frontend-split-stale-audit",
159
+ operationId: input.operationId,
160
+ reason: input.reason,
161
+ fact: input.fact,
162
+ recordedAt: new Date().toISOString(),
163
+ };
164
+ const name = `${sha256Json(fact)}.json`;
165
+ await writeSecureJson(path.join(splitAuditDir, name), fact);
166
+ };
167
+ const prepareAggregate = async ({ operationId, aggregate, }) => {
168
+ const before = await operations.get(operationId);
169
+ if (!before) {
170
+ throw new Error(`cannot prepare aggregate: parent operation not found: ${operationId}`);
171
+ }
172
+ const aggregateFile = path.join(splitAggregateDir, `${aggregate.digest}.json`);
173
+ let parentRecordPath = "";
174
+ let wroteAggregate = false;
175
+ let wroteParent = false;
176
+ return {
177
+ committedRef: {
178
+ ref: aggregateFile,
179
+ digest: aggregate.digest,
180
+ commitState: "committed",
181
+ },
182
+ async commit(input) {
183
+ parentRecordPath = input.parentRecordPath;
184
+ await writeSecureJson(aggregateFile, {
185
+ schemaVersion: 1,
186
+ kind: "frontend-split-aggregate-closeout",
187
+ operationId,
188
+ aggregate,
189
+ });
190
+ wroteAggregate = true;
191
+ await writeSecureJson(input.parentRecordPath, input.parentRecord);
192
+ wroteParent = true;
193
+ },
194
+ async rollback() {
195
+ if (wroteAggregate)
196
+ await rm(aggregateFile, { force: true });
197
+ if (wroteParent && parentRecordPath) {
198
+ await writeSecureJson(parentRecordPath, before);
199
+ }
200
+ },
201
+ };
202
+ };
203
+ const splitOrchestrator = createFrontendSplitOperationAdapter({
204
+ store: operations,
205
+ materializer,
206
+ schedule,
207
+ auditStale,
208
+ prepareAggregate,
209
+ });
210
+ const humanDecisionAdapter = createFrontendHumanDecisionAdapter(operations);
87
211
  const drafts = new DraftStore(appData);
88
212
  const confirmations = new DagConfirmationStore(appData, bootToken.confirmationToken);
89
213
  const dagExecutionReceipts = new DagExecutionReceiptStore(appData);
@@ -123,6 +247,9 @@ export async function createConsoleServer(options) {
123
247
  client,
124
248
  operations,
125
249
  events,
250
+ splitOrchestrator,
251
+ humanDecisionAdapter,
252
+ materializer,
126
253
  drafts,
127
254
  confirmations,
128
255
  dagExecutionReceipts,
@@ -137,7 +264,7 @@ export async function createConsoleServer(options) {
137
264
  getConsoleOrigin: () => `http://${boundHost}:${boundPort}`,
138
265
  };
139
266
  let boundHost = host;
140
- let boundPort = port;
267
+ let boundPort = configuredPort;
141
268
  const getConsoleOrigin = () => `http://${boundHost}:${boundPort}`;
142
269
  // Phase 4: General Operator Chat runtime. The actionContext is forwarded so
143
270
  // custom-tool execute() calls dispatch into the operator action layer (Gate 3).
@@ -188,6 +315,7 @@ export async function createConsoleServer(options) {
188
315
  repoRoot,
189
316
  staticDir,
190
317
  bootToken,
318
+ inspectBootToken,
191
319
  getConsoleOrigin,
192
320
  allowNonLoopbackAccess: !loopbackBind,
193
321
  inspect: {
@@ -277,8 +405,22 @@ export async function createConsoleServer(options) {
277
405
  }
278
406
  }
279
407
  if (pathname.startsWith("/inspect")) {
408
+ // Experimental prompt-override rerun: only while the internal switch
409
+ // is enabled do we hand the inspect page SCOPED mutation
410
+ // credentials (separate cookie + token, only strong enough for
411
+ // INSPECT_MUTATION_ALLOWED_ACTIONS — see routes.ts). Default stays
412
+ // strictly read-only: no token, no cookie, no tab.
413
+ const htmlEnhancer = isDagRerunPromptOverrideEnabled()
414
+ ? (html) => ({
415
+ content: injectConfirmationTokenScript(html, routeContext.inspectBootToken?.confirmationToken ??
416
+ routeContext.bootToken.confirmationToken, "__INSPECT_MUTATION_TOKEN__"),
417
+ setCookie: routeContext.inspectBootToken?.setCookieHeader ??
418
+ routeContext.bootToken.setCookieHeader,
419
+ })
420
+ : undefined;
280
421
  await serveObserveStatic(req, res, inspectStaticDir, {
281
422
  urlPrefix: "/inspect",
423
+ ...(htmlEnhancer ? { htmlEnhancer } : {}),
282
424
  });
283
425
  return;
284
426
  }
@@ -289,7 +431,7 @@ export async function createConsoleServer(options) {
289
431
  await serveConsoleStatic(req, res, routeContext);
290
432
  }
291
433
  server.on("error", reject);
292
- server.listen(port, host, () => {
434
+ server.listen(configuredPort, host, () => {
293
435
  const addr = server.address();
294
436
  if (!addr || typeof addr === "string") {
295
437
  reject(new Error("Failed to get console server address"));
@@ -311,6 +453,9 @@ export async function createConsoleServer(options) {
311
453
  appData,
312
454
  operations,
313
455
  events,
456
+ splitOrchestrator,
457
+ humanDecisionAdapter,
458
+ materializer,
314
459
  getReadiness,
315
460
  operatorSessionId,
316
461
  close: () => new Promise((closeResolve, closeReject) => {
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-DZtolir7.js";import{p as f}from"./chunk-JWPE2WC7-NgHc6V37.js";import{_ as n,l as o}from"./mermaid.core-BVjAT9b8.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BwT_xKrE.js";import"./index-DTZOKgAn.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-Dz29Ye_f.js";import{p as f}from"./chunk-JWPE2WC7-CIoGkxdu.js";import{_ as n,l as o}from"./mermaid.core-C-D3ZRUa.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BSCtQpD7.js";import"./index-D5zGX6fG.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-BVjAT9b8.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-C-D3ZRUa.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};