@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.
- package/AGENTS.md +4 -1
- package/CHANGELOG.md +187 -92
- package/README.md +9 -5
- package/bin/loop-agent.js +7 -3
- package/dist/application/task-lifecycle/recommendations.js +13 -2
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +16 -5
- package/dist/cli/program.js +16 -2
- package/dist/cli/update/notifier.js +2 -2
- package/dist/cli.js +2 -1
- package/dist/commands/dag-rerun.js +55 -1
- package/dist/commands/init-model-catalog.js +464 -0
- package/dist/commands/init-upgrade.js +265 -97
- package/dist/commands/init.js +429 -28
- package/dist/commands/inspect-next.js +8 -0
- package/dist/executors/dag-pi-executor.js +1691 -29
- package/dist/executors/pi-extension-resolver.js +233 -0
- package/dist/executors/pi-playwright-cli-tool.js +51 -12
- package/dist/executors/pi-sdk-executor.js +180 -33
- package/dist/executors/shell-executor.js +1152 -171
- package/dist/executors/shell-write-guard.js +14 -0
- package/dist/shared/dag-prompt-override.js +28 -0
- package/dist/shared/openspec-spec.js +70 -4
- package/dist/shared/operator/capabilities.js +32 -0
- package/dist/shared/playwright-cli-command-policy.js +15 -0
- package/dist/shared/update/console-notifier.js +100 -0
- package/dist/{cli → shared}/update/npm-client.js +41 -8
- package/dist/{cli → shared}/update/state.js +41 -13
- package/dist/task/config-types.js +19 -5
- package/dist/task/contract/project.js +3 -0
- package/dist/task/contract/schema.js +2 -1
- package/dist/task/frontend-project-capability.js +60 -17
- package/dist/task/source-prepare/parse-intent.js +24 -4
- package/dist/task/source-prepare/prepare.js +36 -0
- package/dist/worker/cli.js +31 -1
- package/dist/worker/console/chat/pi-console-config.js +81 -10
- package/dist/worker/console/chat/routes.js +1 -0
- package/dist/worker/console/dag-execution-receipt.js +33 -0
- package/dist/worker/console/frontend-human-decision-adapter.js +19 -0
- package/dist/worker/console/frontend-split-operation-adapter.js +20 -0
- package/dist/worker/console/index.js +3 -0
- package/dist/worker/console/operation-store.js +226 -6
- package/dist/worker/console/operator-actions.js +263 -0
- package/dist/worker/console/operator-user-error.js +2 -2
- package/dist/worker/console/routes.js +43 -2
- package/dist/worker/console/security.js +63 -9
- package/dist/worker/console/server.js +151 -6
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4kVYweA.js → abnfDiagram-N423BO3Z-zsNyvGaH.js} +1 -1
- package/dist/worker/console/static/assets/{arc-Bj2M8iO5.js → arc-BDjZ5kE1.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CLlXe4-6.js → architectureDiagram-T3A2C74G-BkgaujnN.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-psEp5xH0.js → blockDiagram-VBNYF7ZC-CqxOJi0j.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DeKcOCGJ.js → c4Diagram-5PPSVZJV-C2JHLdRi.js} +1 -1
- package/dist/worker/console/static/assets/channel-BuqaGKAT.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-K0C744p1.js → chunk-2GRJ4B5K-DF_YSvOS.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-xbNw4J9-.js → chunk-2Q5K7J3B-D3Ort5Vo.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DjLaSDUO.js → chunk-5RXB4S5H-XfAfZeUC.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-CtiPlKel.js → chunk-5VM5RSS4-SLBibhf5.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DZtolir7.js → chunk-6Q2QTUOP-Dz29Ye_f.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CPcdNeew.js → chunk-GF5L2VYU-DB2G4H8V.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-NgHc6V37.js → chunk-JWPE2WC7-CIoGkxdu.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DQ_T-hg8.js → chunk-KBJHAD2P-CG78FGkn.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DgLsxcVP.js → chunk-RYQCIY6F-ZDHAvXPd.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-UrVoM9z1.js → chunk-XXDRQBXY-BKkkC4VA.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DNdSHjH9.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DNdSHjH9.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CLkYvTb3.js → cose-bilkent-JH36ORCC-SposUZsO.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BwT_xKrE.js → cynefin-VYW2F7L2-BSCtQpD7.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Bi9tuzif.js → cynefinDiagram-MW4NZA55-DgFHrw9l.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BCIqkWBV.js → dagre-VZM6K2ZE-BVBasYbj.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-Dip6l9_Z.js → diagram-7IWD3JNH-6r_4rN_c.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B-xkh_wK.js → diagram-B4RE2ZJO-JmuaB41P.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DZO0kTt_.js → diagram-LBJQPF4R-xXvAY3sk.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-D6ZplNbZ.js → diagram-Q27KOJAE-D2B3lY2o.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-BPekbhoS.js → diagram-UB23O5K3-tK54tMEX.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BtmaJpK5.js → ebnfDiagram-BXEA7PRR-CNtELzV-.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-6DS0Xc44.js → erDiagram-JOGREHBK-C1xKMKcW.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CihnROSm.js → flowDiagram-UKHOOZJN-CZ7dlPMz.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CZC4zOE2.js → ganttDiagram-PKOTCBZU-BqGb42Xe.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Dq1fhzGN.js → gitGraphDiagram-DS77QQ5N-D_BlXEtt.js} +1 -1
- package/dist/worker/console/static/assets/{index-DTZOKgAn.js → index-D5zGX6fG.js} +68 -68
- package/dist/worker/console/static/assets/index-DBbhESQ_.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DlSl4BGx.js → infoDiagram-6WML65LV-Vce2vmIe.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-snnzFl_U.js → ishikawaDiagram-WSZJBQD7-DDwVBAvI.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-BDE7qpMx.js → journeyDiagram-NVQOT4AX-y_Ew-wv4.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-CD2Ci04G.js → kanban-definition-27J2QSJJ-CjXJFp1K.js} +1 -1
- package/dist/worker/console/static/assets/{linear-DdnapKIH.js → linear-1itMst1Q.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-BVjAT9b8.js → mermaid.core-C-D3ZRUa.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-D0yJk-zA.js → mindmap-definition-FAOFIHXS-BiYywmZc.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BVo9tFP-.js → pegDiagram-VL7TDLO6-l2fydNWA.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DnOV-mZ_.js → pieDiagram-7S7Q4E2Y-Dz0hNbYW.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-CzUJo58i.js → quadrantDiagram-CIZ2JOQS-BujI_mLZ.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Bvikrolh.js → railroadDiagram-AXF67PYL-pWe84beb.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DtaSVCap.js → requirementDiagram-LRYGKXZP-ByYu2frg.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-C2c9A0wW.js → sankeyDiagram-W5VNT64P-CoPnilFP.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DmXJcU7r.js → sequenceDiagram-SI44F4Z6-1Md2LnS0.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B4GUFW92.js → sizeCapture-X5ZJPWSS-DqqqAoSH.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Dsad2MXf.js → stateDiagram-OKZ733FA-C4sGkf--.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8rmop_9.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DGq48Fbi.js → swimlanes-SLNWSIFB-ByxJrUzW.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-B0ky-kBM.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CSSi6OFf.js → timeline-definition-Z64GVDOM-D8MLgM0O.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BqyzPrWv.js → vennDiagram-T6HMQDX7-DnBis-wZ.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DlznVb6S.js → wardleyDiagram-T6FBY63Y-uuyYT7UO.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CfBcgJ_K.js → xychartDiagram-ELKLHX3M-BjgabhwK.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/active-run-badge.js +17 -0
- package/dist/worker/console/static-src/operator-chat/mutation-gate.js +1 -1
- package/dist/worker/loop-agent/loop-agent-client.js +7 -3
- package/dist/worker/materialize/frontend-split-task-materializer.js +72 -0
- package/dist/worker/observe/node-input.js +74 -3
- package/dist/worker/observe/node-process.js +377 -0
- package/dist/worker/observe/routes.js +36 -3
- package/dist/worker/observe/shell-handler-keys.js +34 -0
- package/dist/worker/observe/static/api.js +66 -0
- package/dist/worker/observe/static/constants.js +8 -1
- package/dist/worker/observe/static/dag-history-labels.js +4 -0
- package/dist/worker/observe/static/format.js +23 -0
- package/dist/worker/observe/static/markdown-render.js +20 -1
- package/dist/worker/observe/static/operator-chrome.js +4 -0
- package/dist/worker/observe/static/state.js +13 -2
- package/dist/worker/observe/static/styles.css +73 -0
- package/dist/worker/observe/static/views/dag-inspector.js +612 -8
- package/dist/worker/observe/static/views/dag.js +8 -1
- package/dist/worker/observe/static/views/failures.js +5 -2
- package/dist/worker/observe/static/views/session-timeline.js +78 -9
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +20 -2
- package/dist/workflows/dag/contract-output-registry.js +15 -0
- package/dist/workflows/dag/contract-validator-registrations.js +1 -2
- package/dist/workflows/dag/failure-category.js +12 -0
- package/dist/workflows/dag/frontend-closeout.js +221 -0
- package/dist/workflows/dag/frontend-design-policy.js +366 -0
- package/dist/workflows/dag/frontend-human-decision.js +182 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +378 -160
- package/dist/workflows/dag/frontend-prewrite-gate.js +343 -391
- package/dist/workflows/dag/frontend-provider-capability-matrix.js +159 -0
- package/dist/workflows/dag/frontend-recovery-capsule.js +455 -0
- package/dist/workflows/dag/frontend-recovery-controller.js +201 -0
- package/dist/workflows/dag/frontend-recovery-lineage.js +178 -0
- package/dist/workflows/dag/frontend-recovery-plan.js +17 -10
- package/dist/workflows/dag/frontend-recovery-run.js +33 -20
- package/dist/workflows/dag/frontend-repair.js +7 -424
- package/dist/workflows/dag/frontend-review-context.js +195 -8
- package/dist/workflows/dag/frontend-risk.js +15 -2
- package/dist/workflows/dag/frontend-shadow-dual-write.js +665 -0
- package/dist/workflows/dag/frontend-shape-capsule-store.js +191 -0
- package/dist/workflows/dag/frontend-shape-facts.js +409 -0
- package/dist/workflows/dag/frontend-shape.js +425 -0
- package/dist/workflows/dag/frontend-split-application-service.js +203 -0
- package/dist/workflows/dag/frontend-split-orchestrator.js +899 -0
- package/dist/workflows/dag/frontend-test-case-checklist.js +26 -2
- package/dist/workflows/dag/frontend-test-case-manifest.js +5 -0
- package/dist/workflows/dag/frontend-test-case-quality.js +5 -13
- package/dist/workflows/dag/frontend-test-environment-probe.js +227 -0
- package/dist/workflows/dag/frontend-test-markdown.js +61 -0
- package/dist/workflows/dag/frontend-test-result-contract.js +160 -28
- package/dist/workflows/dag/frontend-test-standard-scenarios.js +68 -0
- package/dist/workflows/dag/frontend-typed-event-store.js +439 -0
- package/dist/workflows/dag/frontend-typed-event-transaction.js +180 -0
- package/dist/workflows/dag/frontend-verification-trace.js +52 -17
- package/dist/workflows/dag/frontend-worktree-diff.js +97 -18
- package/dist/workflows/dag/frontend-writer-admission.js +260 -0
- package/dist/workflows/dag/frontend-writer-status.js +244 -0
- package/dist/workflows/dag/init-hybrid.js +572 -500
- package/dist/workflows/dag/node-execution.js +307 -70
- package/dist/workflows/dag/prompt.js +10 -18
- package/dist/workflows/dag/rerun-plan.js +144 -5
- package/dist/workflows/dag/rerun-run.js +58 -6
- package/dist/workflows/dag/retry-policy.js +228 -4
- package/dist/workflows/dag/runner.js +314 -119
- package/dist/workflows/dag/scheduler.js +114 -16
- package/dist/workflows/dag/structured-output-repair.js +712 -0
- package/dist/workflows/dag/types.js +235 -23
- package/dist/workflows/dag/upstream-artifacts.js +0 -4
- package/dist/workflows/dag/validate.js +60 -10
- package/docs/init-surface.manifest.json +5 -0
- package/docs/operations/README.md +1 -1
- package/docs/templates/agent-dag.schema.json +44 -0
- package/docs/templates/frontend-test-dag.json +8 -10
- package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +1 -1
- package/docs/templates/init-managed-agents.md +13 -3
- package/harness.json +3 -3
- package/package.json +5 -1
- package/scripts/next-info.mjs +356 -0
- package/scripts/next-publish-gate.mjs +238 -0
- package/scripts/release-source-binding.mjs +251 -0
- package/skills/codebase-scout/SKILL.md +1 -1
- package/skills/fe-test-ui-scout/SKILL.md +65 -0
- package/skills/fe-test-ui-scout/references/ledger-schema.md +62 -0
- package/skills/fe-test-ui-scout/references/recon-protocol.md +54 -0
- package/skills/frontend-implementation/SKILL.md +4 -4
- package/skills/frontend-implementation/references/design-spec.md +11 -7
- package/skills/frontend-implementation/references/node-contracts.md +20 -11
- package/skills/loop-agent/references/command-reference.md +11 -4
- package/skills/loop-agent/references/hybrid-dag.md +1 -1
- package/skills/playwright-cli/SKILL.md +22 -0
- package/skills/playwright-cli-case-generator/SKILL.md +20 -1
- package/dist/worker/console/static/assets/channel-CPF4N7pf.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C2DwA_Y1.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C2DwA_Y1.js +0 -1
- package/dist/worker/console/static/assets/index-Ya5FE7cD.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8FB_cNk.js +0 -1
- 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
|
|
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
|
-
|
|
7
|
-
|
|
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
|
-
`${
|
|
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
|
|
19
|
-
|
|
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
|
|
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,
|
|
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
|
|
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 =
|
|
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(
|
|
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-
|
|
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-
|
|
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};
|