elanous 0.2.4 → 0.2.6
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/README.md +7 -6
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/chunks/1169-696263ac7af8c4d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1883.c91a2648af4842fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1947-9d64872eeb9cfdec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2808-dc06482994b40f70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5080-1613752891fcadb4.js → 2984-977cfa339fcd65a5.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/3165-95515ca5f299a120.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8142-011e1f474efb8b33.js → 3190-e9282753e7ebde85.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3995-bee512a7063036ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 4240-7153881b0b377306.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4259-99614149577e77cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4283-329eabeaf233e6cd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4328-cb5058b1acc2de5e.js +25 -0
- package/apps/pwa/out/_next/static/chunks/4801-ecee6ef62b349b18.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5110-8058791dd25a2e14.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3403.4bc97b4066945a94.js → 5329.8b7e4bca684b6eec.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5330-c41e9670f594c38f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5423-e95fd125d1794349.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5478-b5eae07dc79ea619.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5787-96ee6642b9a661e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6448-79d72368589f98bc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6522-9866c002b5531836.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6729-b4a558b7aa891e0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6969-cb03f9410b7d2e03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7007-3b9861091bb8dd21.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5791-bb82743fa6299562.js → 763-7d0e1913b5074e98.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7633.0654fe6ea259c1ee.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7930-8dc7e20fc6fc19ca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8071-187edbc22a86741f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8198-d4101ad70cb9a579.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8250.4a2c5553a07cdf47.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8293-123b91e7b0330dc0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8296-d6d5d87dfa911d41.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8305-603963c33ee8eec3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8612-4a0066f20951b8fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2ea96958-e8c7e112de50b067.js → 8d0d9faf-97887ff99713b84e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9181-cf4e1b61c4783f92.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 91ff6dda-3b33d42d20657429.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9262-26c2ecbd5a67e4a2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9328-45abdebce4fbecb7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9355-dbc67205adf8745f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9763.255b90dd69875689.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9933-66d31ec25c0231af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-bd06fb55f4da0381.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-4e586142da455a25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-889ad5cddcf45b0d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-47ba401d56572c27.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-0b54f9c83458e038.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-4fcc296ef6c8ed90.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-fe9fda494a87f4e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-f9642e25ce129590.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-e1063e8ba5f3e2e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-9d0df30027d8aa9d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-bd06fb55f4da0381.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-d97adf2c9455b8d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-236b80d202110362.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-21a30f35f1a276ad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-b1a5be357c4fa25d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1705a60303f7f573.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-76b337c11ad0e237.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-7c0f85fbb56f64c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-65ca16b20617b44d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-e7f9b8fc29411c1d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-92ea6213d1aeec04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-a913a005aacb5476.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-2d78804a40dfdef6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-08a99148e780ac00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-deb674e7ed36f815.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-49f8de0534d192d7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-bd06fb55f4da0381.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-ba162a28d2176e18.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-1ff1a37b550ab41a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-ccaa698f56c0fbdb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-53b944082de1d7db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-9b70adf1552789bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-30d482aa63241fe8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-aecf786f54651d8a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6ab9b62c7b6e08f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-08949735455e0c9a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-a1479005234a46c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c3890e90bd232732.js +1 -0
- package/apps/pwa/out/_next/static/chunks/beb5cf10-9adcc10b83930090.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-d68d41c88e05c801.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-11c63971b7a9593b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-d09452353bd0d9cc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-184d727cebeca767.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-21bbbbac99b720b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{webpack-e5bea36f183b25e6.js → webpack-37b8bf78a3c6eec5.js} +1 -1
- package/apps/pwa/out/_next/static/css/eaa74e8bb2f62269.css +1 -0
- package/apps/pwa/out/_next/static/{zoQX5iTvXOsIvCjxCe1Ji → qMI0jnlZaBjjm4aIDYNGM}/_buildManifest.js +1 -1
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +29 -27
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +29 -27
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +29 -27
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +26 -24
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +26 -24
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +26 -24
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +29 -27
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +29 -27
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +29 -27
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/icons/elanous-16.png +0 -0
- package/apps/pwa/out/icons/elanous-180.png +0 -0
- package/apps/pwa/out/icons/elanous-192.png +0 -0
- package/apps/pwa/out/icons/elanous-32.png +0 -0
- package/apps/pwa/out/icons/elanous-512.png +0 -0
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +26 -24
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +29 -27
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +29 -27
- package/apps/pwa/out/manifest.webmanifest +5 -2
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +26 -24
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +26 -24
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +29 -27
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +29 -27
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +27 -25
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +29 -27
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +26 -24
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +29 -27
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +29 -27
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +29 -27
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +29 -27
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +29 -27
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +26 -24
- package/apps/pwa/out/sw-strategies.js +44 -0
- package/apps/pwa/out/sw.js +6 -44
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +29 -27
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +29 -27
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +29 -27
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +29 -27
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +29 -27
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +29 -27
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +29 -27
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +29 -27
- package/catalog/resources.yaml +6 -6
- package/docs/goal-context/steward-directives-2026-09-28.md +35 -37
- package/graphs/landing/landing-heal.yaml +1 -1
- package/graphs/release/recipes.yaml +11 -1
- package/graphs/release/release-loop.yaml +9 -2
- package/graphs/video/README.md +1 -0
- package/graphs/video/explainer-line.yaml +58 -0
- package/package.json +3 -1
- package/plugins/card-followup/README.md +33 -0
- package/plugins/card-followup/examples/card-sample.json +7 -0
- package/plugins/card-followup/graphs/card-followup.yaml +16 -0
- package/plugins/card-followup/graphs/recipes.yaml +12 -0
- package/plugins/card-followup/graphs/run-step.ts +172 -0
- package/plugins/card-followup/plugin.json +25 -0
- package/plugins/geo-check/README.md +13 -0
- package/plugins/geo-check/examples/brand-sample.json +8 -0
- package/plugins/geo-check/graphs/geo-check.yaml +20 -0
- package/plugins/geo-check/graphs/recipes.yaml +18 -0
- package/plugins/geo-check/graphs/run-step.ts +177 -0
- package/plugins/geo-check/plugin.json +24 -0
- package/plugins/job-coach/.codex-plugin/plugin.json +18 -1
- package/plugins/job-coach/README.md +42 -0
- package/plugins/job-coach/connectors/ncs/server.ts +4 -3
- package/plugins/job-coach/graphs/gap-judge.ts +44 -0
- package/plugins/job-coach/graphs/recipes.yaml +27 -0
- package/plugins/job-coach/graphs/report-enterprise.yaml +28 -0
- package/plugins/job-coach/graphs/run-step.ts +211 -17
- package/plugins/job-coach/plugin.json +16 -3
- package/plugins/job-coach/skills/enterprise-ai-fit/SKILL.md +8 -0
- package/plugins/job-coach/skills/enterprise-competency/SKILL.md +8 -0
- package/plugins/job-coach/skills/enterprise-needs/SKILL.md +8 -0
- package/plugins/job-coach/skills/enterprise-roadmap/SKILL.md +8 -0
- package/plugins/job-coach/skills/enterprise-task-analysis/SKILL.md +8 -0
- package/plugins/job-coach/skills/interview-to-profile/SKILL.md +18 -1
- package/scripts/backup/elanous-backup.sh +4 -1
- package/scripts/build-docs-site.ts +4 -3
- package/scripts/coord-channel-watch.sh +23 -4
- package/scripts/coord-post.sh +49 -12
- package/scripts/coord-tracks.json +5 -5
- package/scripts/daemon-port-baseline.txt +1 -2
- package/scripts/eval-bot-vs-grok.ts +79 -0
- package/scripts/eval-grok-live-baseline.ts +36 -0
- package/scripts/fixtures/front-route-corpus.sample.json +17 -0
- package/scripts/fleet/node-setup.sh +46 -7
- package/scripts/landing-heal/must-fix-match.ts +26 -0
- package/scripts/landing-heal/run-mission.ts +114 -20
- package/scripts/lib/android-test-device.ts +32 -0
- package/scripts/lib/front-route-measurement.ts +131 -0
- package/scripts/lib/tui-sim-keys.ts +42 -0
- package/scripts/measure-front-route-classifier.ts +56 -0
- package/scripts/media/ocr-leak-scan.sh +21 -0
- package/scripts/public-export.ts +2 -3
- package/scripts/public-import-pr.ts +80 -6
- package/scripts/publish-internal-dist.ts +2 -3
- package/scripts/red-sweep-diff.ts +1 -1
- package/scripts/release-loop/auto-approve-node.ts +72 -0
- package/scripts/release-loop/checklist-gate-node.ts +35 -0
- package/scripts/release-loop/gate-diff.ts +29 -0
- package/scripts/release-loop/gate-node.ts +366 -45
- package/scripts/release-loop/publish-node.ts +7 -3
- package/scripts/release-loop/release-docs.ts +20 -13
- package/scripts/release-loop/shard-plan.ts +47 -0
- package/scripts/release-loop/test-durations.ts +63 -0
- package/scripts/release-loop/upgrade-node.ts +3 -2
- package/scripts/test-audit-coverage-per-file.sh +16 -0
- package/scripts/test-audit-meaningless.ts +88 -0
- package/scripts/test-audit-overlap-and-weak.ts +73 -0
- package/scripts/test-deterministic.ts +27 -5
- package/scripts/tui-sim.ts +59 -14
- package/scripts/ux/bump-installed.sh +20 -0
- package/scripts/ux/lib/cdp.ts +72 -0
- package/scripts/ux/record-page.ts +53 -0
- package/skills/explainer-video/SKILL.md +117 -0
- package/skills/explainer-video/engine/brand/elanous-mark-on-dark.svg +1 -0
- package/skills/explainer-video/engine/build.mjs +431 -0
- package/skills/explainer-video/engine/reel.mjs +128 -0
- package/skills/explainer-video/engine/reel.sh +8 -0
- package/skills/explainer-video/engine/vo.ts +79 -0
- package/skills/explainer-video/examples/elanous-0.2.5/script.json +155 -0
- package/src/agent/nested-agent-env.ts +1 -0
- package/src/agent-mission/driver.ts +95 -16
- package/src/agent-mission/mission-cli.ts +6 -0
- package/src/agent-mission/resource-ladder.ts +73 -25
- package/src/auth/acp-token.ts +16 -0
- package/src/auth/github-app-token.ts +112 -0
- package/src/autopilot/gh-rest-fallback.ts +177 -0
- package/src/autopilot/mission-origin.ts +20 -4
- package/src/autopilot/mission-phase-track.ts +11 -1
- package/src/autopilot/pr-manager.ts +51 -4
- package/src/autopilot/track-agent.ts +3 -3
- package/src/autopilot/track-courier.ts +2 -2
- package/src/boot/acp-server.ts +2 -16
- package/src/boot/daemon-tools/web-search.ts +2 -1
- package/src/boot/ws-bridge.ts +11 -0
- package/src/chat/index.ts +37 -8
- package/src/chat/log-scroll-key.ts +12 -0
- package/src/chat/submit-trace.ts +30 -0
- package/src/cli/agent-cli.ts +7 -2
- package/src/cli/decisions-cli.ts +94 -0
- package/src/cli/doctor-cli.ts +40 -54
- package/src/cli/doctor-readiness.ts +16 -24
- package/src/cli/intake-cli.ts +1 -1
- package/src/cli/mcp-call.ts +9 -0
- package/src/cli/mcp-gateway-cli.ts +7 -3
- package/src/cli/nexus-ios-bind.ts +25 -8
- package/src/cli/phone-link.ts +117 -0
- package/src/cli/plugin-cli.ts +136 -11
- package/src/cli/pr-lineage.ts +2 -1
- package/src/cli/private-ledger-commands.ts +31 -0
- package/src/cli/pwa-start.ts +3 -0
- package/src/cli/release-cli.ts +97 -7
- package/src/cli/self-update.ts +7 -4
- package/src/cli/start-cli.ts +33 -14
- package/src/dashboard/acp-boot.ts +3 -0
- package/src/dashboard/index.ts +62 -13
- package/src/dashboard/input/no-provider-reply.ts +13 -0
- package/src/dashboard/slash-runtime/unknown-slash-reply.ts +78 -0
- package/src/dashboard/stale-install-check.ts +77 -0
- package/src/decisions/decision-ledger.ts +404 -0
- package/src/domains/outbound-alert.ts +13 -7
- package/src/domains/telegram-kind-route.ts +21 -0
- package/src/execution-loop/dispatch-task.ts +139 -0
- package/src/execution-loop/gate-decision-summary.ts +29 -0
- package/src/execution-loop/gates.ts +197 -0
- package/src/field/field-media.ts +245 -0
- package/src/graph-kinds/installed-plugin-nodes.ts +95 -0
- package/src/graph-kinds/plugin-nodes.ts +10 -2
- package/src/graph-runner/runner.ts +35 -5
- package/src/grounding/token.ts +12 -6
- package/src/harness/harness-cli-command.ts +68 -9
- package/src/harness/harness-pod-dispatch.ts +8 -2
- package/src/harness/harness-stop.ts +147 -18
- package/src/harness/self-send-decide.ts +26 -17
- package/src/harness/self-send-target.ts +22 -1
- package/src/harness/worktree-branch-prefix.ts +4 -3
- package/src/index.ts +50 -13
- package/src/instance/resolve.ts +6 -0
- package/src/intake-plane/collect-telegram-saved.ts +5 -0
- package/src/intake-plane/digest.ts +11 -2
- package/src/live/detail-switch.ts +8 -3
- package/src/llm/usable-llm.ts +32 -0
- package/src/loops/registry.ts +27 -5
- package/src/market/publish.ts +59 -3
- package/src/native-tool-catalog.ts +2 -2
- package/src/nexus/api/field-uploads.ts +143 -0
- package/src/nexus/api/graph-approvals.ts +174 -0
- package/src/nexus/api/harness-api.ts +219 -5
- package/src/nexus/api/http-server.ts +69 -6
- package/src/nexus/api/log-fabric.ts +10 -1
- package/src/nexus/api/mcp-oauth-hint.ts +10 -9
- package/src/nexus/api/merge-approvals.ts +2 -1
- package/src/nexus/api/meta-api.ts +14 -0
- package/src/nexus/api/plugins-credentials-api.ts +47 -0
- package/src/nexus/api/plugins-market.ts +87 -3
- package/src/nexus/api/pod-credential-api.ts +68 -14
- package/src/nexus/api/public-routes.ts +7 -0
- package/src/nexus/api/trace.ts +57 -6
- package/src/nexus/boot/register-mcp-clients.ts +99 -14
- package/src/nexus/index.ts +33 -32
- package/src/nexus/outbound/router.ts +1 -1
- package/src/notify/llm-budget-alert.ts +119 -0
- package/src/onboarding.ts +25 -2
- package/src/plugins/core/host.ts +14 -0
- package/src/plugins/install/market-fetch.ts +4 -3
- package/src/plugins/install/plugin-credentials.ts +106 -0
- package/src/plugins/install/plugin-install.ts +163 -32
- package/src/plugins/maker/plugin-maker.ts +208 -0
- package/src/prompt-library/universal-preamble.ts +8 -2
- package/src/relay/channel.ts +184 -0
- package/src/relay/mux.ts +182 -0
- package/src/relay/test-vectors.json +29 -0
- package/src/release-loop/checklist.ts +217 -0
- package/src/release-loop/release-note.ts +6 -3
- package/src/seat-address/seat-address.ts +34 -0
- package/src/self-dev/dev-cli.ts +40 -20
- package/src/self-dev/dev-pipeline.ts +77 -1
- package/src/self-implement/gate-baseline.ts +3 -1
- package/src/self-implement/goal-author.ts +18 -1
- package/src/self-implement/host-regate.ts +6 -2
- package/src/self-implement/orchestrator.ts +7 -2
- package/src/self-implement/run-ledger-compact.ts +1 -1
- package/src/self-implement/seams.ts +4 -2
- package/src/session/index.ts +23 -10
- package/src/skills/tools/dev-harness.ts +42 -0
- package/src/steward/steward-cards.ts +45 -0
- package/src/steward/triage.ts +50 -14
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +61 -3
- package/src/task-orchestrator/surfaces/pod-bun-cache.ts +18 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +36 -6
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +39 -9
- package/src/task-orchestrator/surfaces/pod-source-bundle.ts +16 -1
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +51 -13
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +172 -28
- package/src/telegram-report.ts +12 -6
- package/src/telegram.ts +108 -1
- package/src/tui-client/acp-transport-ws-client.ts +72 -5
- package/src/tui.ts +3 -2
- package/src/user-config.ts +32 -2
- package/src/util/spawn-sync-output.ts +15 -0
- package/src/version/code-revision.ts +1 -1
- package/src/version/packed-revision.json +1 -1
- package/src/video-pipeline/recipes/explainer.ts +213 -0
- package/src/video-pipeline/walk-line.ts +3 -2
- package/src/web-search/free.ts +77 -0
- package/src/web-search/index.ts +2 -0
- package/src/workflow-runtime/deps-bridge.ts +4 -3
- package/src/workflow-runtime/plugin-kind-node.ts +32 -4
- package/src/workflow-runtime/types.ts +2 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1191-7b13a24117a689fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2375-3fcae5186c64fe6b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2415.ed6428ff334c7ce2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
- package/apps/pwa/out/_next/static/chunks/319-d37df1b6e0cbeff4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4836-3c93795ab834381e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6090-1bd6077591603947.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7457-f5cb1cc8db9f7453.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8067-f74bf14d67ad98f1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8519-0059d82bdb4812bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9740-52467f244755917f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9804-64c02c3c127d5014.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-21c3261af6ab377c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-1991445b8ea86274.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-4ebfaee2369fe248.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-9fa879ebf5959096.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ca7c3cc305c3285a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-9951930add3d2051.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-4472ddf1e2458e69.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-4de08d4b766f134b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7a975e2b9db1dfb7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-49270714ef35bb96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-33fbdf353e2a5982.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-259f122e2dd64317.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-65b82726753658e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-4b8df3748dc06285.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-112f7e477bda77fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-542a5c0006da637c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-63ffb347831262ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-98e4e359d97263b4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-97e24ac675ce576e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ac6391f26391d89d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f45c9d45ffc43bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-36995b9cb5d98218.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-0c795b577988d63f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-b4311e2f71c6735a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-eb2381074df20dba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-b01336e64eba01ae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-7af7f21c1f2858ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-a98ecd364586c89b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-57f0502dfbfa089b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-3467d2e1abd8a14a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-7842ca23d53ba682.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-ae9ac882912b0198.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-3a0d72e3f783bcef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-f3b39fe8358c2a97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-5a22af3181ac2afb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-1457627bb302a22c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
- package/apps/pwa/out/_next/static/css/e66b7f5efc8df3f3.css +0 -1
- /package/apps/pwa/out/_next/static/{zoQX5iTvXOsIvCjxCe1Ji → qMI0jnlZaBjjm4aIDYNGM}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync } from 'node:fs';
|
|
3
|
+
import { dirname, isAbsolute, relative, resolve, sep } from 'node:path';
|
|
4
|
+
import type { RunResult } from './ffmpeg.js';
|
|
5
|
+
import { UNOBSERVED, type Recipe, type RecipeCtx, type RecipeResult } from './types.js';
|
|
6
|
+
|
|
7
|
+
type CommandRunner = (bin: string, args: readonly string[], timeoutMs: number, cwd?: string) => RunResult;
|
|
8
|
+
interface ExplainerDeps { readonly run?: CommandRunner; readonly engineDir?: string }
|
|
9
|
+
|
|
10
|
+
const ENGINE = resolve(import.meta.dir, '../../../skills/explainer-video/engine');
|
|
11
|
+
const ENGINE_MS = 600_000;
|
|
12
|
+
const QC_MS = 180_000;
|
|
13
|
+
|
|
14
|
+
function inside(root: string, candidate: string): boolean {
|
|
15
|
+
const rel = relative(root, candidate);
|
|
16
|
+
return rel === '' || (rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Resolve existing ancestors as well: an output directory may be a symlink before the engine writes into it.
|
|
20
|
+
function safeOutput(root: string, candidate: string): boolean {
|
|
21
|
+
const base = realpathSync(root);
|
|
22
|
+
if (!inside(resolve(root), resolve(candidate))) return false;
|
|
23
|
+
// Walk up to the deepest component that exists as a directory entry (lstat, not existsSync):
|
|
24
|
+
// a broken symlink is «there» and must be judged, not skipped as missing.
|
|
25
|
+
let path = resolve(candidate);
|
|
26
|
+
for (;;) {
|
|
27
|
+
let isLink: boolean;
|
|
28
|
+
try { isLink = lstatSync(path).isSymbolicLink(); } catch {
|
|
29
|
+
const parent = dirname(path);
|
|
30
|
+
if (parent === path) return false;
|
|
31
|
+
path = parent;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (isLink && !existsSync(path)) return false; // broken link — its target could be created outside the project
|
|
35
|
+
return inside(base, realpathSync(path));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function finish(ctx: RecipeCtx, name: string, result: RecipeResult): RecipeResult {
|
|
40
|
+
ctx.log(`explainer.${name}`, { outcome: result.outcome, ...result.produced, note: result.note });
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function scriptPath(ctx: RecipeCtx): string | null {
|
|
45
|
+
const value = ctx.state.script_path;
|
|
46
|
+
return typeof value === 'string' && value.trim() ? resolve(value) : null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function enginePath(deps: ExplainerDeps, file: string): string | null {
|
|
50
|
+
const path = resolve(deps.engineDir ?? ENGINE, file);
|
|
51
|
+
return existsSync(path) ? path : null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function runner(deps: ExplainerDeps, ctx: RecipeCtx): CommandRunner {
|
|
55
|
+
if (deps.run) return deps.run;
|
|
56
|
+
return (bin, args, timeoutMs, cwd) => {
|
|
57
|
+
const r = spawnSync(bin, [...args], {
|
|
58
|
+
cwd, timeout: timeoutMs, encoding: 'utf8',
|
|
59
|
+
env: { ...process.env, EXPLAINER_CACHE: resolve(ctx.workdir, 'explainer-cache') },
|
|
60
|
+
});
|
|
61
|
+
return { ok: r.status === 0, code: r.status, signal: r.signal ?? null,
|
|
62
|
+
err: (r.stderr ?? r.error?.message ?? '').trim(), out: (r.stdout ?? '').trim() };
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function unavailable(r: RunResult): boolean {
|
|
67
|
+
return r.signal === null && r.code === null && !r.ok;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function keys(script: unknown): string[] | null {
|
|
71
|
+
if (!script || typeof script !== 'object') return null;
|
|
72
|
+
const s = script as { intro?: { beats?: unknown }; chapters?: unknown; outro?: { beats?: unknown } };
|
|
73
|
+
if (!Array.isArray(s.intro?.beats) || !Array.isArray(s.chapters) || !Array.isArray(s.outro?.beats)) return null;
|
|
74
|
+
const chapters = s.chapters as { beats?: unknown }[];
|
|
75
|
+
if (!chapters.every((c) => c && Array.isArray(c.beats))) return null;
|
|
76
|
+
return [
|
|
77
|
+
...s.intro.beats.map((_, i) => `i-${i}`),
|
|
78
|
+
...chapters.flatMap((c, ci) => (c.beats as unknown[]).map((_, i) => `c${ci + 1}-${i}`)),
|
|
79
|
+
...s.outro.beats.map((_, i) => `o-${i}`),
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function explainerScript(): Recipe {
|
|
84
|
+
return async (ctx) => {
|
|
85
|
+
const path = scriptPath(ctx);
|
|
86
|
+
if (!path) return finish(ctx, 'script', { outcome: 'no-facts', note: 'script_path 가 state 에 없다 — 대본 저작이 필요하다' });
|
|
87
|
+
if (!existsSync(path)) return finish(ctx, 'script', { outcome: 'no-facts', note: `대본이 없다: ${path}` });
|
|
88
|
+
let script: unknown;
|
|
89
|
+
try { script = JSON.parse(readFileSync(path, 'utf8')); }
|
|
90
|
+
catch (e) { return finish(ctx, 'script', { outcome: UNOBSERVED, note: `대본 읽기 실패: ${String(e)}` }); }
|
|
91
|
+
const chapters = (script as { chapters?: unknown } | null)?.chapters;
|
|
92
|
+
const beatKeys = keys(script);
|
|
93
|
+
const voiced = (beat: unknown): boolean => beat !== null && typeof beat === 'object' &&
|
|
94
|
+
typeof (beat as { vo?: unknown }).vo === 'string' && (beat as { vo: string }).vo.trim().length > 0;
|
|
95
|
+
if (!beatKeys?.length || !Array.isArray(chapters) || chapters.length === 0 ||
|
|
96
|
+
!chapters.some((chapter: { beats: unknown[] }) => chapter.beats.some(voiced)) ||
|
|
97
|
+
![...(script as { intro: { beats: unknown[] } }).intro.beats,
|
|
98
|
+
...chapters.flatMap((chapter: { beats: unknown[] }) => chapter.beats),
|
|
99
|
+
...(script as { outro: { beats: unknown[] } }).outro.beats].every(voiced)) {
|
|
100
|
+
return finish(ctx, 'script', { outcome: 'no-facts', note: 'intro.beats · chapters[] · outro.beats 에 내용이 없거나 구조가 없다' });
|
|
101
|
+
}
|
|
102
|
+
return finish(ctx, 'script', { outcome: 'ok', produced: { script_path: path } });
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function explainerVo(deps: ExplainerDeps = {}): Recipe {
|
|
107
|
+
return async (ctx) => {
|
|
108
|
+
const path = scriptPath(ctx);
|
|
109
|
+
if (!path || !existsSync(path)) return finish(ctx, 'vo', { outcome: UNOBSERVED, note: 'script_path 를 못 읽는다' });
|
|
110
|
+
const engine = enginePath(deps, 'vo.ts');
|
|
111
|
+
if (!engine) return finish(ctx, 'vo', { outcome: UNOBSERVED, note: 'skills/explainer-video/engine/vo.ts 가 없다' });
|
|
112
|
+
const project = dirname(path);
|
|
113
|
+
const voDir = resolve(project, 'source/vo');
|
|
114
|
+
try {
|
|
115
|
+
const beatKeys = keys(JSON.parse(readFileSync(path, 'utf8')));
|
|
116
|
+
if (!beatKeys?.length) return finish(ctx, 'vo', { outcome: UNOBSERVED, note: '대본의 VO beat 를 못 읽었다' });
|
|
117
|
+
const outputs = beatKeys.flatMap((key) => [
|
|
118
|
+
resolve(voDir, `${key}.mp3`), resolve(voDir, `${key}.json`),
|
|
119
|
+
resolve(voDir, `${key}.tmp.aiff`), resolve(voDir, `${key}.tmp.mp3`),
|
|
120
|
+
]);
|
|
121
|
+
if (![voDir, ...outputs].every((p) => safeOutput(project, p))) {
|
|
122
|
+
return finish(ctx, 'vo', { outcome: UNOBSERVED, note: 'VO 출력이 대본 폴더 밖을 가리킨다' });
|
|
123
|
+
}
|
|
124
|
+
} catch (e) { return finish(ctx, 'vo', { outcome: UNOBSERVED, note: `VO 경로 확인 실패: ${String(e)}` }); }
|
|
125
|
+
let r: RunResult;
|
|
126
|
+
try { r = runner(deps, ctx)('bun', [engine, path], ENGINE_MS, project); }
|
|
127
|
+
catch (e) { return finish(ctx, 'vo', { outcome: UNOBSERVED, note: `bun vo.ts 를 못 불렀다: ${String(e)}` }); }
|
|
128
|
+
if (unavailable(r)) return finish(ctx, 'vo', { outcome: UNOBSERVED, note: `bun vo.ts 를 못 불렀다(code=${r.code} signal=${r.signal}): ${r.err}` });
|
|
129
|
+
if (!r.ok) return finish(ctx, 'vo', { outcome: 'error', note: `VO 엔진 실패: ${r.err.slice(0, 240)}` });
|
|
130
|
+
try {
|
|
131
|
+
const script = JSON.parse(readFileSync(path, 'utf8')) as unknown;
|
|
132
|
+
const beatKeys = keys(script);
|
|
133
|
+
if (!beatKeys?.length) throw new Error('대본에 VO beat 가 없다');
|
|
134
|
+
let seconds = 0;
|
|
135
|
+
for (const key of beatKeys) {
|
|
136
|
+
const audio = resolve(voDir, `${key}.mp3`);
|
|
137
|
+
const alignment = resolve(voDir, `${key}.json`);
|
|
138
|
+
if (!safeOutput(project, audio) || !safeOutput(project, alignment) || !existsSync(audio)) throw new Error(`${key} VO 파일이 없다`);
|
|
139
|
+
const j = JSON.parse(readFileSync(alignment, 'utf8')) as { alignment?: { character_end_times_seconds?: unknown } };
|
|
140
|
+
const ends = j.alignment?.character_end_times_seconds;
|
|
141
|
+
if (!Array.isArray(ends) || ends.length === 0 || !Number.isFinite(ends.at(-1)) || ends.at(-1) <= 0) throw new Error(`${key} 끝 시각을 못 읽었다`);
|
|
142
|
+
seconds += ends.at(-1) as number;
|
|
143
|
+
}
|
|
144
|
+
return finish(ctx, 'vo', { outcome: 'ok', produced: { vo_dir: voDir, narration_seconds: seconds } });
|
|
145
|
+
} catch (e) { return finish(ctx, 'vo', { outcome: UNOBSERVED, note: `VO 산출을 못 쟀다: ${String(e)}` }); }
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function explainerBuild(deps: ExplainerDeps = {}): Recipe {
|
|
150
|
+
return async (ctx) => {
|
|
151
|
+
const path = scriptPath(ctx);
|
|
152
|
+
if (!path || !existsSync(path)) return finish(ctx, 'build', { outcome: UNOBSERVED, note: 'script_path 를 못 읽는다' });
|
|
153
|
+
const engine = enginePath(deps, 'build.mjs');
|
|
154
|
+
if (!engine) return finish(ctx, 'build', { outcome: UNOBSERVED, note: 'skills/explainer-video/engine/build.mjs 가 없다' });
|
|
155
|
+
const project = dirname(path);
|
|
156
|
+
const hf = resolve(project, 'hf');
|
|
157
|
+
const timeline = resolve(project, 'timeline.json');
|
|
158
|
+
try {
|
|
159
|
+
mkdirSync(ctx.workdir, { recursive: true });
|
|
160
|
+
if (![hf, resolve(hf, 'assets'), resolve(hf, 'assets/fonts'), resolve(hf, 'assets/vo'), timeline].every((p) => safeOutput(project, p))
|
|
161
|
+
|| !safeOutput(ctx.workdir, resolve(ctx.workdir, 'explainer-cache'))) {
|
|
162
|
+
return finish(ctx, 'build', { outcome: UNOBSERVED, note: '빌드 출력/캐시가 허용된 폴더 밖을 가리킨다' });
|
|
163
|
+
}
|
|
164
|
+
} catch (e) { return finish(ctx, 'build', { outcome: UNOBSERVED, note: `빌드 경로 확인 실패: ${String(e)}` }); }
|
|
165
|
+
let r: RunResult;
|
|
166
|
+
try { r = runner(deps, ctx)('node', [engine, path], ENGINE_MS, project); }
|
|
167
|
+
catch (e) { return finish(ctx, 'build', { outcome: UNOBSERVED, note: `node build.mjs 를 못 불렀다: ${String(e)}` }); }
|
|
168
|
+
if (unavailable(r)) return finish(ctx, 'build', { outcome: UNOBSERVED, note: `node build.mjs 를 못 불렀다(code=${r.code} signal=${r.signal}): ${r.err}` });
|
|
169
|
+
if (!r.ok) {
|
|
170
|
+
const badScript = /unknown diagram|DIAGRAMS\[dia\] is not a function|(?:invalid|missing|unsupported) (?:script|diagram|beat|chapter)/i.test(r.err);
|
|
171
|
+
return finish(ctx, 'build', { outcome: badScript ? 'bad-script' : 'error', note: `빌드 실패: ${r.err.slice(0, 240)}` });
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
if (![resolve(hf, 'index.html'), timeline].every((p) => safeOutput(project, p) && existsSync(p))) {
|
|
175
|
+
return finish(ctx, 'build', { outcome: UNOBSERVED, note: '빌드가 hf/index.html 또는 timeline.json 을 내지 않았다' });
|
|
176
|
+
}
|
|
177
|
+
} catch (e) { return finish(ctx, 'build', { outcome: UNOBSERVED, note: `빌드 산출 확인 실패: ${String(e)}` }); }
|
|
178
|
+
return finish(ctx, 'build', { outcome: 'ok', produced: { hyperframes_project: hf, timeline_path: timeline } });
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function explainerQc(deps: ExplainerDeps = {}): Recipe {
|
|
183
|
+
return async (ctx) => {
|
|
184
|
+
const path = ctx.state.hf_render_path;
|
|
185
|
+
if (typeof path !== 'string' || !path || !existsSync(path)) {
|
|
186
|
+
return finish(ctx, 'qc', { outcome: UNOBSERVED, note: 'hf_render_path 를 못 읽는다' });
|
|
187
|
+
}
|
|
188
|
+
let r: RunResult;
|
|
189
|
+
try {
|
|
190
|
+
r = runner(deps, ctx)('ffmpeg', ['-hide_banner', '-nostats', '-i', resolve(path),
|
|
191
|
+
'-af', 'loudnorm=print_format=json', '-f', 'null', '-'], QC_MS, ctx.workdir);
|
|
192
|
+
} catch (e) { return finish(ctx, 'qc', { outcome: UNOBSERVED, note: `ffmpeg 를 못 불렀다: ${String(e)}` }); }
|
|
193
|
+
if (!r.ok) return finish(ctx, 'qc', { outcome: UNOBSERVED, note: `ffmpeg 음량 측정 실패(code=${r.code} signal=${r.signal}): ${r.err.slice(0, 240)}` });
|
|
194
|
+
const block = [...`${r.err}\n${r.out}`.matchAll(/\{[^{}]*"input_i"[^{}]*"input_tp"[^{}]*\}/g)].at(-1)?.[0];
|
|
195
|
+
try {
|
|
196
|
+
if (!block) throw new Error('loudnorm JSON 이 없다');
|
|
197
|
+
const j = JSON.parse(block) as { input_i?: unknown; input_tp?: unknown };
|
|
198
|
+
const loudness = Number(j.input_i);
|
|
199
|
+
const peak = Number(j.input_tp);
|
|
200
|
+
if (j.input_i == null || j.input_tp == null || !Number.isFinite(loudness) || !Number.isFinite(peak)) throw new Error('통합 음량/트루 피크가 비수다');
|
|
201
|
+
const produced = { loudness_lufs: loudness, true_peak_db: peak };
|
|
202
|
+
const outcome = loudness >= -16 && loudness <= -12 && peak <= -1 ? 'pass' : 'loudness';
|
|
203
|
+
return finish(ctx, 'qc', { outcome, produced, note: `${loudness} LUFS · ${peak} dBTP` });
|
|
204
|
+
} catch (e) { return finish(ctx, 'qc', { outcome: UNOBSERVED, note: `loudnorm 결과를 못 읽었다: ${String(e)}` }); }
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export const EXPLAINER: Readonly<Record<string, Recipe>> = {
|
|
209
|
+
'explainer-script': explainerScript(),
|
|
210
|
+
'explainer-vo': explainerVo(),
|
|
211
|
+
'explainer-build': explainerBuild(),
|
|
212
|
+
'explainer-qc': explainerQc(),
|
|
213
|
+
};
|
|
@@ -14,6 +14,7 @@ import { readdirSync, readFileSync } from 'node:fs';
|
|
|
14
14
|
import { join } from 'node:path';
|
|
15
15
|
import { BROLL } from './recipes/broll.js';
|
|
16
16
|
import { CHARACTER } from './recipes/character.js';
|
|
17
|
+
import { EXPLAINER } from './recipes/explainer.js';
|
|
17
18
|
import { FILM } from './recipes/film.js';
|
|
18
19
|
import { FREE_LINE } from './recipes/free-line.js';
|
|
19
20
|
import { HYPERFRAMES } from './recipes/hyperframes.js';
|
|
@@ -21,8 +22,8 @@ import { UPSTREAM } from './recipes/upstream.js';
|
|
|
21
22
|
import { VLOG } from './recipes/vlog.js';
|
|
22
23
|
import { UNOBSERVED, type Recipe, type RecipeCtx } from './recipes/types.js';
|
|
23
24
|
|
|
24
|
-
/** ⛔ 순서가 뜻이다 — 같은 이름이면 뒤가 이긴다. HYPERFRAMES
|
|
25
|
-
export const ALL_RECIPES: Readonly<Record<string, Recipe>> = { ...UPSTREAM, ...FREE_LINE, ...VLOG, ...FILM, ...CHARACTER, ...HYPERFRAMES, ...BROLL };
|
|
25
|
+
/** ⛔ 순서가 뜻이다 — 같은 이름이면 뒤가 이긴다. HYPERFRAMES · EXPLAINER 는 기존 키를 덮지 않는다. */
|
|
26
|
+
export const ALL_RECIPES: Readonly<Record<string, Recipe>> = { ...UPSTREAM, ...FREE_LINE, ...VLOG, ...FILM, ...CHARACTER, ...HYPERFRAMES, ...BROLL, ...EXPLAINER };
|
|
26
27
|
|
|
27
28
|
export interface GraphSpecLike {
|
|
28
29
|
readonly graph_id: string;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { debug } from '../debug/log.js';
|
|
2
|
+
import type { WebSearchHit, WebSearchProvider } from './provider.js';
|
|
3
|
+
|
|
4
|
+
const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36';
|
|
5
|
+
|
|
6
|
+
function decodeEntities(s: string): string {
|
|
7
|
+
return s
|
|
8
|
+
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
9
|
+
.replace(/"/g, '"').replace(/'/g, "'").replace(/'/gi, "'")
|
|
10
|
+
.replace(/ /g, ' ')
|
|
11
|
+
.replace(/&#(\d+);/g, (_, d) => String.fromCodePoint(Number(d)))
|
|
12
|
+
.replace(/&#x([0-9a-f]+);/gi, (_, h) => String.fromCodePoint(parseInt(h, 16)));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function stripTags(html: string): string {
|
|
16
|
+
return decodeEntities(html.replace(/<[^>]+>/g, '')).replace(/\s+/g, ' ').trim();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function unwrapDdgUrl(href: string): string {
|
|
20
|
+
try {
|
|
21
|
+
const u = href.startsWith('//') ? new URL('https:' + href) : new URL(href, 'https://duckduckgo.com');
|
|
22
|
+
const uddg = u.searchParams.get('uddg');
|
|
23
|
+
if (uddg) return uddg;
|
|
24
|
+
return href.startsWith('//') ? 'https:' + href : href;
|
|
25
|
+
} catch { return href; }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function buildFreeWebSearchProvider(deps: { fetch?: typeof fetch } = {}): WebSearchProvider {
|
|
29
|
+
return {
|
|
30
|
+
id: 'ddg-free',
|
|
31
|
+
displayName: 'DuckDuckGo (keyless)',
|
|
32
|
+
available: () => true,
|
|
33
|
+
search: async (q, signal) => {
|
|
34
|
+
const startedAt = Date.now();
|
|
35
|
+
const limit = Number.isFinite(q.limit) ? Math.max(1, Math.min(20, Math.floor(q.limit!))) : 5;
|
|
36
|
+
let status: number | undefined;
|
|
37
|
+
try {
|
|
38
|
+
const response = await (deps.fetch ?? fetch)('https://html.duckduckgo.com/html/', {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': UA },
|
|
41
|
+
body: new URLSearchParams({ q: q.query }).toString(),
|
|
42
|
+
signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(15_000)]) : AbortSignal.timeout(15_000),
|
|
43
|
+
});
|
|
44
|
+
status = response.status;
|
|
45
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
46
|
+
const html = await response.text();
|
|
47
|
+
const linkRe = /<a[^>]*class="result__a"[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/g;
|
|
48
|
+
const snipRe = /<a[^>]*class="result__snippet"[^>]*>([\s\S]*?)<\/a>/;
|
|
49
|
+
const blockRe = /<div[^>]*class="[^"]*\bresult\b[^"]*"[^>]*>/g;
|
|
50
|
+
const links = [...html.matchAll(linkRe)];
|
|
51
|
+
const blocks = [...html.matchAll(blockRe)].map(match => match.index);
|
|
52
|
+
const hits: WebSearchHit[] = [];
|
|
53
|
+
for (let i = 0; i < links.length && hits.length < limit; i++) {
|
|
54
|
+
const link = links[i];
|
|
55
|
+
const nextLink = links[i + 1]?.index ?? html.length;
|
|
56
|
+
const nextBlock = blocks.find(position => position > link.index);
|
|
57
|
+
const end = Math.min(nextLink, nextBlock ?? html.length);
|
|
58
|
+
const snippet = html.slice(link.index + link[0].length, end).match(snipRe);
|
|
59
|
+
const url = unwrapDdgUrl(link[1]);
|
|
60
|
+
const title = stripTags(link[2]);
|
|
61
|
+
if (url && title) hits.push({ url, title, snippet: snippet ? stripTags(snippet[1]) : '' });
|
|
62
|
+
}
|
|
63
|
+
if (hits.length === 0) throw new Error('No DuckDuckGo results parsed');
|
|
64
|
+
const durationMs = Date.now() - startedAt;
|
|
65
|
+
debug.log('web-search.free', 'search', { hits: hits.length, durationMs, status, queryLength: q.query.length });
|
|
66
|
+
return { hits, providerName: 'ddg-free', durationMs };
|
|
67
|
+
} catch (err) {
|
|
68
|
+
debug.log('web-search.free', 'failed', {
|
|
69
|
+
...(status !== undefined && status >= 400 ? { status } : { reason: signal?.aborted ? 'aborted' : 'request-or-parse-failed' }),
|
|
70
|
+
queryLength: q.query.length,
|
|
71
|
+
durationMs: Date.now() - startedAt,
|
|
72
|
+
});
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
package/src/web-search/index.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { buildGrokWebSearchProvider } from './grok.js';
|
|
9
9
|
import { buildFirecrawlWebSearchProvider } from './firecrawl.js';
|
|
10
10
|
import { buildTavilyWebSearchProvider } from './tavily.js';
|
|
11
|
+
import { buildFreeWebSearchProvider } from './free.js';
|
|
11
12
|
import { isTavilySearchEnabled } from '../user-config.js';
|
|
12
13
|
import {
|
|
13
14
|
type WebSearchProvider,
|
|
@@ -34,6 +35,7 @@ function registerBuiltins(): void {
|
|
|
34
35
|
if (isTavilySearchEnabled()) providers.push(buildTavilyWebSearchProvider());
|
|
35
36
|
providers.push(buildGrokWebSearchProvider());
|
|
36
37
|
providers.push(buildFirecrawlWebSearchProvider());
|
|
38
|
+
providers.push(buildFreeWebSearchProvider());
|
|
37
39
|
}
|
|
38
40
|
registerBuiltins();
|
|
39
41
|
|
|
@@ -40,11 +40,12 @@ import {
|
|
|
40
40
|
* optional `signal` is forwarded to the skill runner so workflow-level
|
|
41
41
|
* abort propagates. Returns the skill's full response text. */
|
|
42
42
|
export function buildRunSkill(opts: { signal?: AbortSignal } = {}) {
|
|
43
|
-
return async function runSkill(slug: string, args: string): Promise<string> {
|
|
44
|
-
|
|
43
|
+
return async function runSkill(slug: string, args: string, runOpts: { skillsDir?: string } = {}): Promise<string> {
|
|
44
|
+
// 플러그인 노드는 자기 팩의 `skills/` 를 먼저 본다 — 설치자 HOME 에 기대지 않는다(🅕 K3 실물 09-30).
|
|
45
|
+
const manifest = (runOpts.skillsDir ? parseSkillMd(slug, runOpts.skillsDir) : null) ?? parseSkillMd(slug, LOCAL_SKILLS_DIR);
|
|
45
46
|
if (!manifest) {
|
|
46
47
|
throw new Error(
|
|
47
|
-
`unknown skill '${slug}'. Skills are loaded from ${LOCAL_SKILLS_DIR} (or ~/.claude/skills) — check the slug or add a SKILL.md.`,
|
|
48
|
+
`unknown skill '${slug}'. Skills are loaded from ${runOpts.skillsDir ? `${runOpts.skillsDir}, then ` : ''}${LOCAL_SKILLS_DIR} (or ~/.claude/skills) — check the slug or add a SKILL.md.`,
|
|
48
49
|
);
|
|
49
50
|
}
|
|
50
51
|
let buffered = '';
|
|
@@ -5,11 +5,15 @@
|
|
|
5
5
|
// values are single-quoted so the substituted text cannot become shell syntax.
|
|
6
6
|
|
|
7
7
|
import { callDaemonMcpTool } from '../cli/mcp-call.js';
|
|
8
|
+
import { elanousStateRoot } from '../autopilot/state-paths.js';
|
|
9
|
+
import { pluginEnv } from '../plugins/install/plugin-credentials.js';
|
|
8
10
|
import { debug } from '../debug/log.js';
|
|
9
11
|
import { getNodeKind, type NodeKindEntry, type NodeKindRun } from '../graph-kinds/registry.js';
|
|
10
12
|
import { executeBashNode } from './nodes/bash.js';
|
|
11
13
|
import { executeHttpRequestNode } from './nodes/http.js';
|
|
12
14
|
import { executeSkillNode } from './nodes/skill.js';
|
|
15
|
+
import { listInstalledPlugins } from '../plugins/install/plugin-install.js';
|
|
16
|
+
import { join } from 'node:path';
|
|
13
17
|
import type { DagNode, NodeExecContext, NodeOutput, PluginKindNode, WorkflowDeps } from './types.js';
|
|
14
18
|
|
|
15
19
|
const PLACEHOLDER = /\{\{([^{}]*)\}\}/g;
|
|
@@ -93,7 +97,7 @@ export async function executePluginKindNode(
|
|
|
93
97
|
if ('mcp' in entry.run) {
|
|
94
98
|
const spec = entry.run.mcp;
|
|
95
99
|
const args = Object.fromEntries(Object.entries(spec.args ?? {}).map(([key, value]) => [key, substituteMcpArg(value, node.inputs)]));
|
|
96
|
-
const result = await callDaemonMcpTool({ tool: `${spec.server}.${spec.tool}`, arguments: args });
|
|
100
|
+
const result = await callDaemonMcpTool({ tool: `${spec.server}.${spec.tool}`, arguments: args, pluginKind: node.kind });
|
|
97
101
|
const record = result && typeof result === 'object' && !Array.isArray(result)
|
|
98
102
|
? result as { content?: unknown; structuredContent?: unknown }
|
|
99
103
|
: {};
|
|
@@ -104,7 +108,12 @@ export async function executePluginKindNode(
|
|
|
104
108
|
throw new Error('unsupported MCP tool result: expected text-only content');
|
|
105
109
|
}
|
|
106
110
|
const output = (record.content as Array<{ text: string }>).map((item) => item.text).join('\n');
|
|
107
|
-
|
|
111
|
+
let credentials: Record<string, string> = {};
|
|
112
|
+
try { credentials = pluginEnv(entry.plugin!, elanousStateRoot()); }
|
|
113
|
+
catch { /* Registered kinds may also be used without an installed plugin. */ }
|
|
114
|
+
const safe = Object.values(credentials).filter(value => value.length > 0)
|
|
115
|
+
.reduce((text, value) => text.replaceAll(value, '[REDACTED]'), output);
|
|
116
|
+
return { ok: true, output: safe, durationMs: Date.now() - startedAt };
|
|
108
117
|
}
|
|
109
118
|
if ('bash' in entry.run) {
|
|
110
119
|
const bash = substituteInputs(entry.run.bash, node.inputs, true);
|
|
@@ -122,16 +131,35 @@ export async function executePluginKindNode(
|
|
|
122
131
|
}, ctx, deps);
|
|
123
132
|
}
|
|
124
133
|
const spec = (entry.run as { skill: { name: string; prompt?: string } }).skill;
|
|
134
|
+
// 플러그인 kind 의 스킬은 그 플러그인 설치 폴더의 `skills/` 에서 먼저 찾는다(팩이 스킬 본체를 싣는다 · `elanous-hwp` → `hwp-write`).
|
|
135
|
+
let skillsDir: string | undefined;
|
|
136
|
+
if (entry.plugin) {
|
|
137
|
+
try {
|
|
138
|
+
const installed = listInstalledPlugins(elanousStateRoot()).find((item) => item.name === entry.plugin);
|
|
139
|
+
if (installed) skillsDir = join(installed.path, 'skills');
|
|
140
|
+
} catch { /* 설치 원장을 못 읽으면 종전 위치만 */ }
|
|
141
|
+
}
|
|
142
|
+
debug.log('workflow.plugin-kind', 'skill-dir', { plugin: entry.plugin ?? null, skill: spec.name, skillsDir: skillsDir ?? null });
|
|
143
|
+
const skillDeps: WorkflowDeps = skillsDir && deps.runSkill
|
|
144
|
+
? { ...deps, runSkill: (slug, args) => deps.runSkill!(slug, args, { skillsDir }) }
|
|
145
|
+
: deps;
|
|
125
146
|
return await executeSkillNode({
|
|
126
147
|
...node,
|
|
127
148
|
skill: substituteInputs(spec.name, node.inputs, false),
|
|
128
149
|
...(spec.prompt !== undefined ? { arguments: substituteInputs(spec.prompt, node.inputs, false) } : {}),
|
|
129
|
-
}, ctx,
|
|
150
|
+
}, ctx, skillDeps);
|
|
130
151
|
} catch (err) {
|
|
152
|
+
let message = err instanceof Error ? err.message : String(err);
|
|
153
|
+
if ('mcp' in entry.run && entry.plugin) {
|
|
154
|
+
try {
|
|
155
|
+
const credentials = pluginEnv(entry.plugin, elanousStateRoot());
|
|
156
|
+
for (const value of Object.values(credentials)) if (value) message = message.replaceAll(value, '[REDACTED]');
|
|
157
|
+
} catch { /* Registered kinds may also be used without an installed plugin. */ }
|
|
158
|
+
}
|
|
131
159
|
return {
|
|
132
160
|
ok: false,
|
|
133
161
|
output: '',
|
|
134
|
-
error:
|
|
162
|
+
error: message,
|
|
135
163
|
durationMs: Date.now() - startedAt,
|
|
136
164
|
};
|
|
137
165
|
}
|
|
@@ -672,7 +672,8 @@ export interface WorkflowDeps {
|
|
|
672
672
|
* `dispatchTaskCreate`. */
|
|
673
673
|
createTask?: (req: WorkflowTaskRequest) => Promise<WorkflowTaskResult>;
|
|
674
674
|
/** Invoke a registered skill by slug. */
|
|
675
|
-
|
|
675
|
+
/** `opts.skillsDir` — 먼저 찾을 스킬 폴더(플러그인 노드 = 그 플러그인의 `skills/`). 없으면 종전 위치. */
|
|
676
|
+
runSkill?: (slug: string, args: string, opts?: { skillsDir?: string }) => Promise<string>;
|
|
676
677
|
/** Invoke a CFT method by name. */
|
|
677
678
|
runCft?: (method: string, config: Record<string, unknown>) => Promise<unknown>;
|
|
678
679
|
/** Evaluate a declared judgment contract through an injected implementation. */
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1105],{15739:(t,n,e)=>{e.d(n,{A:()=>r});function r(t){return(t()-.5)*1e-6}},43062:(t,n,e)=>{e.d(n,{n5:()=>C});var r=e(84202),i=e(45861),u=e(11659),o=e(71236),a=e(41717),s=e(47303);let l=t=>()=>t;function h(t,{sourceEvent:n,target:e,selection:r,mode:i,dispatch:u}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:n,enumerable:!0,configurable:!0},target:{value:e,enumerable:!0,configurable:!0},selection:{value:r,enumerable:!0,configurable:!0},mode:{value:i,enumerable:!0,configurable:!0},_:{value:u}})}function c(t){t.preventDefault(),t.stopImmediatePropagation()}var f={name:"drag"},y={name:"space"},v={name:"handle"},d={name:"center"};let{abs:x,max:p,min:g}=Math;function _(t){return[+t[0],+t[1]]}function w(t){return[_(t[0]),_(t[1])]}var b={name:"x",handles:["w","e"].map(q),input:function(t,n){return null==t?null:[[+t[0],n[0][1]],[+t[1],n[1][1]]]},output:function(t){return t&&[t[0][0],t[1][0]]}},A={name:"y",handles:["n","s"].map(q),input:function(t,n){return null==t?null:[[n[0][0],+t[0]],[n[1][0],+t[1]]]},output:function(t){return t&&[t[0][1],t[1][1]]}};["n","w","e","s","nw","ne","sw","se"].map(q);var m={overlay:"crosshair",selection:"move",n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},N={e:"w",w:"e",nw:"ne",ne:"nw",se:"sw",sw:"se"},k={n:"s",s:"n",nw:"sw",ne:"se",se:"ne",sw:"nw"},M={overlay:1,selection:1,n:null,e:1,s:null,w:-1,nw:-1,ne:1,se:1,sw:-1},z={overlay:1,selection:1,n:-1,e:null,s:1,w:null,nw:-1,ne:-1,se:1,sw:1};function q(t){return{type:t}}function E(t){return!t.ctrlKey&&!t.button}function K(){var t=this.ownerSVGElement||this;return t.hasAttribute("viewBox")?[[(t=t.viewBox.baseVal).x,t.y],[t.x+t.width,t.y+t.height]]:[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]}function P(){return navigator.maxTouchPoints||"ontouchstart"in this}function T(t){for(;!t.__brush;)if(!(t=t.parentNode))return;return t.__brush}function C(){return function(t){var n,e=K,_=E,C=P,V=!0,j=(0,r.A)("start","brush","end"),D=6;function G(n){var e=n.property("__brush",J).selectAll(".overlay").data([q("overlay")]);e.enter().append("rect").attr("class","overlay").attr("pointer-events","all").attr("cursor",m.overlay).merge(e).each(function(){var t=T(this).extent;(0,o.A)(this).attr("x",t[0][0]).attr("y",t[0][1]).attr("width",t[1][0]-t[0][0]).attr("height",t[1][1]-t[0][1])}),n.selectAll(".selection").data([q("selection")]).enter().append("rect").attr("class","selection").attr("cursor",m.selection).attr("fill","#777").attr("fill-opacity",.3).attr("stroke","#fff").attr("shape-rendering","crispEdges");var r=n.selectAll(".handle").data(t.handles,function(t){return t.type});r.exit().remove(),r.enter().append("rect").attr("class",function(t){return"handle handle--"+t.type}).attr("cursor",function(t){return m[t.type]}),n.each(I).attr("fill","none").attr("pointer-events","all").on("mousedown.brush",O).filter(C).on("touchstart.brush",O).on("touchmove.brush",F).on("touchend.brush touchcancel.brush",H).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function I(){var t=(0,o.A)(this),n=T(this).selection;n?(t.selectAll(".selection").style("display",null).attr("x",n[0][0]).attr("y",n[0][1]).attr("width",n[1][0]-n[0][0]).attr("height",n[1][1]-n[0][1]),t.selectAll(".handle").style("display",null).attr("x",function(t){return"e"===t.type[t.type.length-1]?n[1][0]-D/2:n[0][0]-D/2}).attr("y",function(t){return"s"===t.type[0]?n[1][1]-D/2:n[0][1]-D/2}).attr("width",function(t){return"n"===t.type||"s"===t.type?n[1][0]-n[0][0]+D:D}).attr("height",function(t){return"e"===t.type||"w"===t.type?n[1][1]-n[0][1]+D:D})):t.selectAll(".selection,.handle").style("display","none").attr("x",null).attr("y",null).attr("width",null).attr("height",null)}function S(t,n,e){var r=t.__brush.emitter;return!r||e&&r.clean?new B(t,n,e):r}function B(t,n,e){this.that=t,this.args=n,this.state=t.__brush,this.active=0,this.clean=e}function O(e){if((!n||e.touches)&&_.apply(this,arguments)){var r,u,l,h,w,q,E,K,P,C,j,D=this,G=e.target.__data__.type,B=(V&&e.metaKey?G="overlay":G)==="selection"?f:V&&e.altKey?d:v,O=t===A?null:M[G],F=t===b?null:z[G],H=T(D),J=H.extent,L=H.selection,Q=J[0][0],R=J[0][1],U=J[1][0],W=J[1][1],X=0,Y=0,Z=O&&F&&V&&e.shiftKey,$=Array.from(e.touches||[e],t=>{let n=t.identifier;return(t=(0,a.A)(t,D)).point0=t.slice(),t.identifier=n,t});(0,s.G)(D);var tt=S(D,arguments,!0).beforestart();if("overlay"===G){L&&(P=!0);let n=[$[0],$[1]||$[0]];H.selection=L=[[r=t===A?Q:g(n[0][0],n[1][0]),l=t===b?R:g(n[0][1],n[1][1])],[w=t===A?U:p(n[0][0],n[1][0]),E=t===b?W:p(n[0][1],n[1][1])]],$.length>1&&tu(e)}else r=L[0][0],l=L[0][1],w=L[1][0],E=L[1][1];u=r,h=l,q=w,K=E;var tn=(0,o.A)(D).attr("pointer-events","none"),te=tn.selectAll(".overlay").attr("cursor",m[G]);if(e.touches)tt.moved=ti,tt.ended=to;else{var tr=(0,o.A)(e.view).on("mousemove.brush",ti,!0).on("mouseup.brush",to,!0);V&&tr.on("keydown.brush",function(t){switch(t.keyCode){case 16:Z=O&&F;break;case 18:B===v&&(O&&(w=q-X*O,r=u+X*O),F&&(E=K-Y*F,l=h+Y*F),B=d,tu(t));break;case 32:(B===v||B===d)&&(O<0?w=q-X:O>0&&(r=u-X),F<0?E=K-Y:F>0&&(l=h-Y),B=y,te.attr("cursor",m.selection),tu(t));break;default:return}c(t)},!0).on("keyup.brush",function(t){switch(t.keyCode){case 16:Z&&(C=j=Z=!1,tu(t));break;case 18:B===d&&(O<0?w=q:O>0&&(r=u),F<0?E=K:F>0&&(l=h),B=v,tu(t));break;case 32:B===y&&(t.altKey?(O&&(w=q-X*O,r=u+X*O),F&&(E=K-Y*F,l=h+Y*F),B=d):(O<0?w=q:O>0&&(r=u),F<0?E=K:F>0&&(l=h),B=v),te.attr("cursor",m[G]),tu(t));break;default:return}c(t)},!0),(0,i.A)(e.view)}I.call(D),tt.start(e,B.name)}function ti(t){for(let n of t.changedTouches||[t])for(let t of $)t.identifier===n.identifier&&(t.cur=(0,a.A)(n,D));if(Z&&!C&&!j&&1===$.length){let t=$[0];x(t.cur[0]-t[0])>x(t.cur[1]-t[1])?j=!0:C=!0}for(let t of $)t.cur&&(t[0]=t.cur[0],t[1]=t.cur[1]);P=!0,c(t),tu(t)}function tu(t){var n;let e=$[0],i=e.point0;switch(X=e[0]-i[0],Y=e[1]-i[1],B){case y:case f:O&&(X=p(Q-r,g(U-w,X)),u=r+X,q=w+X),F&&(Y=p(R-l,g(W-E,Y)),h=l+Y,K=E+Y);break;case v:$[1]?(O&&(u=p(Q,g(U,$[0][0])),q=p(Q,g(U,$[1][0])),O=1),F&&(h=p(R,g(W,$[0][1])),K=p(R,g(W,$[1][1])),F=1)):(O<0?(X=p(Q-r,g(U-r,X)),u=r+X,q=w):O>0&&(X=p(Q-w,g(U-w,X)),u=r,q=w+X),F<0?(Y=p(R-l,g(W-l,Y)),h=l+Y,K=E):F>0&&(Y=p(R-E,g(W-E,Y)),h=l,K=E+Y));break;case d:O&&(u=p(Q,g(U,r-X*O)),q=p(Q,g(U,w+X*O))),F&&(h=p(R,g(W,l-Y*F)),K=p(R,g(W,E+Y*F)))}q<u&&(O*=-1,n=r,r=w,w=n,n=u,u=q,q=n,G in N&&te.attr("cursor",m[G=N[G]])),K<h&&(F*=-1,n=l,l=E,E=n,n=h,h=K,K=n,G in k&&te.attr("cursor",m[G=k[G]])),H.selection&&(L=H.selection),C&&(u=L[0][0],q=L[1][0]),j&&(h=L[0][1],K=L[1][1]),(L[0][0]!==u||L[0][1]!==h||L[1][0]!==q||L[1][1]!==K)&&(H.selection=[[u,h],[q,K]],I.call(D),tt.brush(t,B.name))}function to(t){var e;if(t.stopImmediatePropagation(),t.touches){if(t.touches.length)return;n&&clearTimeout(n),n=setTimeout(function(){n=null},500)}else(0,i.y)(t.view,P),tr.on("keydown.brush keyup.brush mousemove.brush mouseup.brush",null);tn.attr("pointer-events","all"),te.attr("cursor",m.overlay),H.selection&&(L=H.selection),((e=L)[0][0]===e[1][0]||e[0][1]===e[1][1])&&(H.selection=null,I.call(D)),tt.end(t,B.name)}}function F(t){S(this,arguments).moved(t)}function H(t){S(this,arguments).ended(t)}function J(){var n=this.__brush||{selection:null};return n.extent=w(e.apply(this,arguments)),n.dim=t,n}return G.move=function(n,e,r){n.tween?n.on("start.brush",function(t){S(this,arguments).beforestart().start(t)}).on("interrupt.brush end.brush",function(t){S(this,arguments).end(t)}).tween("brush",function(){var n=this,r=n.__brush,i=S(n,arguments),o=r.selection,a=t.input("function"==typeof e?e.apply(this,arguments):e,r.extent),s=(0,u.A)(o,a);function l(t){r.selection=1===t&&null===a?null:s(t),I.call(n),i.brush()}return null!==o&&null!==a?l:l(1)}):n.each(function(){var n=arguments,i=this.__brush,u=t.input("function"==typeof e?e.apply(this,n):e,i.extent),o=S(this,n).beforestart();(0,s.G)(this),i.selection=null===u?null:u,I.call(this),o.start(r).brush(r).end(r)})},G.clear=function(t,n){G.move(t,null,n)},B.prototype={beforestart:function(){return 1==++this.active&&(this.state.emitter=this,this.starting=!0),this},start:function(t,n){return this.starting?(this.starting=!1,this.emit("start",t,n)):this.emit("brush",t),this},brush:function(t,n){return this.emit("brush",t,n),this},end:function(t,n){return 0==--this.active&&(delete this.state.emitter,this.emit("end",t,n)),this},emit:function(n,e,r){var i=(0,o.A)(this.that).datum();j.call(n,this.that,new h(n,{sourceEvent:e,target:G,selection:t.output(this.state.selection),mode:r,dispatch:j}),i)}},G.extent=function(t){return arguments.length?(e="function"==typeof t?t:l(w(t)),G):e},G.filter=function(t){return arguments.length?(_="function"==typeof t?t:l(!!t),G):_},G.touchable=function(t){return arguments.length?(C="function"==typeof t?t:l(!!t),G):C},G.handleSize=function(t){return arguments.length?(D=+t,G):D},G.keyModifiers=function(t){return arguments.length?(V=!!t,G):V},G.on=function(){var t=j.on.apply(j,arguments);return t===j?G:t},G}(b)}},46384:(t,n,e)=>{function r(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,u,o,a,s,l,h,c,f,y=t._root,v={data:r},d=t._x0,x=t._y0,p=t._x1,g=t._y1;if(!y)return t._root=v,t;for(;y.length;)if((l=n>=(u=(d+p)/2))?d=u:p=u,(h=e>=(o=(x+g)/2))?x=o:g=o,i=y,!(y=y[c=h<<1|l]))return i[c]=v,t;if(a=+t._x.call(null,y.data),s=+t._y.call(null,y.data),n===a&&e===s)return v.next=y,i?i[c]=v:t._root=v,t;do i=i?i[c]=[,,,,]:t._root=[,,,,],(l=n>=(u=(d+p)/2))?d=u:p=u,(h=e>=(o=(x+g)/2))?x=o:g=o;while((c=h<<1|l)==(f=(s>=o)<<1|a>=u));return i[f]=y,i[c]=v,t}function i(t,n,e,r,i){this.node=t,this.x0=n,this.y0=e,this.x1=r,this.y1=i}function u(t){return t[0]}function o(t){return t[1]}function a(t,n,e){var r=new s(null==n?u:n,null==e?o:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function s(t,n,e,r,i,u){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=u,this._root=void 0}function l(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}e.d(n,{A:()=>a});var h=a.prototype=s.prototype;h.copy=function(){var t,n,e=new s(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return e;if(!r.length)return e._root=l(r),e;for(t=[{source:r,target:e._root=[,,,,]}];r=t.pop();)for(var i=0;i<4;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=[,,,,]}):r.target[i]=l(n));return e},h.add=function(t){let n=+this._x.call(null,t),e=+this._y.call(null,t);return r(this.cover(n,e),n,e,t)},h.addAll=function(t){var n,e,i,u,o=t.length,a=Array(o),s=Array(o),l=1/0,h=1/0,c=-1/0,f=-1/0;for(e=0;e<o;++e)!(isNaN(i=+this._x.call(null,n=t[e]))||isNaN(u=+this._y.call(null,n)))&&(a[e]=i,s[e]=u,i<l&&(l=i),i>c&&(c=i),u<h&&(h=u),u>f&&(f=u));if(l>c||h>f)return this;for(this.cover(l,h).cover(c,f),e=0;e<o;++e)r(this,a[e],s[e],t[e]);return this},h.cover=function(t,n){if(isNaN(t*=1)||isNaN(n*=1))return this;var e=this._x0,r=this._y0,i=this._x1,u=this._y1;if(isNaN(e))i=(e=Math.floor(t))+1,u=(r=Math.floor(n))+1;else{for(var o,a,s=i-e||1,l=this._root;e>t||t>=i||r>n||n>=u;)switch(a=(n<r)<<1|t<e,(o=[,,,,])[a]=l,l=o,s*=2,a){case 0:i=e+s,u=r+s;break;case 1:e=i-s,u=r+s;break;case 2:i=e+s,r=u-s;break;case 3:e=i-s,r=u-s}this._root&&this._root.length&&(this._root=l)}return this._x0=e,this._y0=r,this._x1=i,this._y1=u,this},h.data=function(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t},h.extent=function(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]},h.find=function(t,n,e){var r,u,o,a,s,l,h,c=this._x0,f=this._y0,y=this._x1,v=this._y1,d=[],x=this._root;for(x&&d.push(new i(x,c,f,y,v)),null==e?e=1/0:(c=t-e,f=n-e,y=t+e,v=n+e,e*=e);l=d.pop();)if((x=l.node)&&!((u=l.x0)>y)&&!((o=l.y0)>v)&&!((a=l.x1)<c)&&!((s=l.y1)<f))if(x.length){var p=(u+a)/2,g=(o+s)/2;d.push(new i(x[3],p,g,a,s),new i(x[2],u,g,p,s),new i(x[1],p,o,a,g),new i(x[0],u,o,p,g)),(h=(n>=g)<<1|t>=p)&&(l=d[d.length-1],d[d.length-1]=d[d.length-1-h],d[d.length-1-h]=l)}else{var _=t-this._x.call(null,x.data),w=n-this._y.call(null,x.data),b=_*_+w*w;if(b<e){var A=Math.sqrt(e=b);c=t-A,f=n-A,y=t+A,v=n+A,r=x.data}}return r},h.remove=function(t){if(isNaN(u=+this._x.call(null,t))||isNaN(o=+this._y.call(null,t)))return this;var n,e,r,i,u,o,a,s,l,h,c,f,y=this._root,v=this._x0,d=this._y0,x=this._x1,p=this._y1;if(!y)return this;if(y.length)for(;;){if((l=u>=(a=(v+x)/2))?v=a:x=a,(h=o>=(s=(d+p)/2))?d=s:p=s,n=y,!(y=y[c=h<<1|l]))return this;if(!y.length)break;(n[c+1&3]||n[c+2&3]||n[c+3&3])&&(e=n,f=c)}for(;y.data!==t;)if(r=y,!(y=y.next))return this;return((i=y.next)&&delete y.next,r)?i?r.next=i:delete r.next:n?(i?n[c]=i:delete n[c],(y=n[0]||n[1]||n[2]||n[3])&&y===(n[3]||n[2]||n[1]||n[0])&&!y.length&&(e?e[f]=y:this._root=y)):this._root=i,this},h.removeAll=function(t){for(var n=0,e=t.length;n<e;++n)this.remove(t[n]);return this},h.root=function(){return this._root},h.size=function(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t},h.visit=function(t){var n,e,r,u,o,a,s=[],l=this._root;for(l&&s.push(new i(l,this._x0,this._y0,this._x1,this._y1));n=s.pop();)if(!t(l=n.node,r=n.x0,u=n.y0,o=n.x1,a=n.y1)&&l.length){var h=(r+o)/2,c=(u+a)/2;(e=l[3])&&s.push(new i(e,h,c,o,a)),(e=l[2])&&s.push(new i(e,r,c,h,a)),(e=l[1])&&s.push(new i(e,h,u,o,c)),(e=l[0])&&s.push(new i(e,r,u,h,c))}return this},h.visitAfter=function(t){var n,e=[],r=[];for(this._root&&e.push(new i(this._root,this._x0,this._y0,this._x1,this._y1));n=e.pop();){var u=n.node;if(u.length){var o,a=n.x0,s=n.y0,l=n.x1,h=n.y1,c=(a+l)/2,f=(s+h)/2;(o=u[0])&&e.push(new i(o,a,s,c,f)),(o=u[1])&&e.push(new i(o,c,s,l,f)),(o=u[2])&&e.push(new i(o,a,f,c,h)),(o=u[3])&&e.push(new i(o,c,f,l,h))}r.push(n)}for(;n=r.pop();)t(n.node,n.x0,n.y0,n.x1,n.y1);return this},h.x=function(t){return arguments.length?(this._x=t,this):this._x},h.y=function(t){return arguments.length?(this._y=t,this):this._y}},49454:(t,n,e)=>{e.d(n,{A:()=>r});let r=(0,e(89117).A)("crosshair",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"22",x2:"18",y1:"12",y2:"12",key:"l9bcsi"}],["line",{x1:"6",x2:"2",y1:"12",y2:"12",key:"13hhkx"}],["line",{x1:"12",x2:"12",y1:"6",y2:"2",key:"10w3f3"}],["line",{x1:"12",x2:"12",y1:"22",y2:"18",key:"15g9kq"}]])},54559:(t,n,e)=>{e.d(n,{A:()=>s,x:()=>u,y:()=>o});var r=e(84202),i=e(99430);function u(t){return t.x}function o(t){return t.y}var a=Math.PI*(3-Math.sqrt(5));function s(t){let n;var e,u=1,o=.001,s=1-Math.pow(.001,1/300),l=0,h=.6,c=new Map,f=(0,i.O1)(d),y=(0,r.A)("tick","end"),v=(n=1,()=>(n=(1664525*n+0x3c6ef35f)%0x100000000)/0x100000000);function d(){x(),y.call("tick",e),u<o&&(f.stop(),y.call("end",e))}function x(n){var r,i,o=t.length;void 0===n&&(n=1);for(var a=0;a<n;++a)for(u+=(l-u)*s,c.forEach(function(t){t(u)}),r=0;r<o;++r)null==(i=t[r]).fx?i.x+=i.vx*=h:(i.x=i.fx,i.vx=0),null==i.fy?i.y+=i.vy*=h:(i.y=i.fy,i.vy=0);return e}function p(){for(var n,e=0,r=t.length;e<r;++e){if((n=t[e]).index=e,null!=n.fx&&(n.x=n.fx),null!=n.fy&&(n.y=n.fy),isNaN(n.x)||isNaN(n.y)){var i=10*Math.sqrt(.5+e),u=e*a;n.x=i*Math.cos(u),n.y=i*Math.sin(u)}(isNaN(n.vx)||isNaN(n.vy))&&(n.vx=n.vy=0)}}function g(n){return n.initialize&&n.initialize(t,v),n}return null==t&&(t=[]),p(),e={tick:x,restart:function(){return f.restart(d),e},stop:function(){return f.stop(),e},nodes:function(n){return arguments.length?(t=n,p(),c.forEach(g),e):t},alpha:function(t){return arguments.length?(u=+t,e):u},alphaMin:function(t){return arguments.length?(o=+t,e):o},alphaDecay:function(t){return arguments.length?(s=+t,e):+s},alphaTarget:function(t){return arguments.length?(l=+t,e):l},velocityDecay:function(t){return arguments.length?(h=1-t,e):1-h},randomSource:function(t){return arguments.length?(v=t,c.forEach(g),e):v},force:function(t,n){return arguments.length>1?(null==n?c.delete(t):c.set(t,g(n)),e):c.get(t)},find:function(n,e,r){var i,u,o,a,s,l=0,h=t.length;for(null==r?r=1/0:r*=r,l=0;l<h;++l)(o=(i=n-(a=t[l]).x)*i+(u=e-a.y)*u)<r&&(s=a,r=o);return s},on:function(t,n){return arguments.length>1?(y.on(t,n),e):y.on(t)}}}},65036:(t,n,e)=>{e.d(n,{A:()=>a});var r=e(46384),i=e(70331),u=e(15739),o=e(54559);function a(){var t,n,e,a,s,l=(0,i.A)(-30),h=1,c=1/0,f=.81;function y(e){var i,u=t.length,s=(0,r.A)(t,o.x,o.y).visitAfter(d);for(a=e,i=0;i<u;++i)n=t[i],s.visit(x)}function v(){if(t){var n,e,r=t.length;for(n=0,s=Array(r);n<r;++n)s[(e=t[n]).index]=+l(e,n,t)}}function d(t){var n,e,r,i,u,o=0,a=0;if(t.length){for(r=i=u=0;u<4;++u)(n=t[u])&&(e=Math.abs(n.value))&&(o+=n.value,a+=e,r+=e*n.x,i+=e*n.y);t.x=r/a,t.y=i/a}else{(n=t).x=n.data.x,n.y=n.data.y;do o+=s[n.data.index];while(n=n.next)}t.value=o}function x(t,r,i,o){if(!t.value)return!0;var l=t.x-n.x,y=t.y-n.y,v=o-r,d=l*l+y*y;if(v*v/f<d)return d<c&&(0===l&&(d+=(l=(0,u.A)(e))*l),0===y&&(d+=(y=(0,u.A)(e))*y),d<h&&(d=Math.sqrt(h*d)),n.vx+=l*t.value*a/d,n.vy+=y*t.value*a/d),!0;if(!t.length&&!(d>=c)){(t.data!==n||t.next)&&(0===l&&(d+=(l=(0,u.A)(e))*l),0===y&&(d+=(y=(0,u.A)(e))*y),d<h&&(d=Math.sqrt(h*d)));do t.data!==n&&(v=s[t.data.index]*a/d,n.vx+=l*v,n.vy+=y*v);while(t=t.next)}}return y.initialize=function(n,r){t=n,e=r,v()},y.strength=function(t){return arguments.length?(l="function"==typeof t?t:(0,i.A)(+t),v(),y):l},y.distanceMin=function(t){return arguments.length?(h=t*t,y):Math.sqrt(h)},y.distanceMax=function(t){return arguments.length?(c=t*t,y):Math.sqrt(c)},y.theta=function(t){return arguments.length?(f=t*t,y):Math.sqrt(f)},y}},70331:(t,n,e)=>{e.d(n,{A:()=>r});function r(t){return function(){return t}}},74363:(t,n,e)=>{e.d(n,{A:()=>s});var r=e(46384),i=e(70331),u=e(15739);function o(t){return t.x+t.vx}function a(t){return t.y+t.vy}function s(t){var n,e,s,l=1,h=1;function c(){for(var t,i,c,y,v,d,x,p=n.length,g=0;g<h;++g)for(t=0,i=(0,r.A)(n,o,a).visitAfter(f);t<p;++t)x=(d=e[(c=n[t]).index])*d,y=c.x+c.vx,v=c.y+c.vy,i.visit(_);function _(t,n,e,r,i){var o=t.data,a=t.r,h=d+a;if(o){if(o.index>c.index){var f=y-o.x-o.vx,p=v-o.y-o.vy,g=f*f+p*p;g<h*h&&(0===f&&(g+=(f=(0,u.A)(s))*f),0===p&&(g+=(p=(0,u.A)(s))*p),g=(h-(g=Math.sqrt(g)))/g*l,c.vx+=(f*=g)*(h=(a*=a)/(x+a)),c.vy+=(p*=g)*h,o.vx-=f*(h=1-h),o.vy-=p*h)}return}return n>y+h||r<y-h||e>v+h||i<v-h}}function f(t){if(t.data)return t.r=e[t.data.index];for(var n=t.r=0;n<4;++n)t[n]&&t[n].r>t.r&&(t.r=t[n].r)}function y(){if(n){var r,i,u=n.length;for(r=0,e=Array(u);r<u;++r)e[(i=n[r]).index]=+t(i,r,n)}}return"function"!=typeof t&&(t=(0,i.A)(null==t?1:+t)),c.initialize=function(t,e){n=t,s=e,y()},c.iterations=function(t){return arguments.length?(h=+t,c):h},c.strength=function(t){return arguments.length?(l=+t,c):l},c.radius=function(n){return arguments.length?(t="function"==typeof n?n:(0,i.A)(+n),y(),c):t},c}},80687:(t,n,e)=>{e.d(n,{A:()=>a});var r=e(70331),i=e(15739);function u(t){return t.index}function o(t,n){var e=t.get(n);if(!e)throw Error("node not found: "+n);return e}function a(t){var n,e,a,s,l,h,c=u,f=function(t){return 1/Math.min(s[t.source.index],s[t.target.index])},y=(0,r.A)(30),v=1;function d(r){for(var u=0,o=t.length;u<v;++u)for(var a,s,c,f,y,d,x,p=0;p<o;++p)s=(a=t[p]).source,d=((d=Math.sqrt((f=(c=a.target).x+c.vx-s.x-s.vx||(0,i.A)(h))*f+(y=c.y+c.vy-s.y-s.vy||(0,i.A)(h))*y))-e[p])/d*r*n[p],f*=d,y*=d,c.vx-=f*(x=l[p]),c.vy-=y*x,s.vx+=f*(x=1-x),s.vy+=y*x}function x(){if(a){var r,i,u=a.length,h=t.length,f=new Map(a.map((t,n)=>[c(t,n,a),t]));for(r=0,s=Array(u);r<h;++r)(i=t[r]).index=r,"object"!=typeof i.source&&(i.source=o(f,i.source)),"object"!=typeof i.target&&(i.target=o(f,i.target)),s[i.source.index]=(s[i.source.index]||0)+1,s[i.target.index]=(s[i.target.index]||0)+1;for(r=0,l=Array(h);r<h;++r)i=t[r],l[r]=s[i.source.index]/(s[i.source.index]+s[i.target.index]);n=Array(h),p(),e=Array(h),g()}}function p(){if(a)for(var e=0,r=t.length;e<r;++e)n[e]=+f(t[e],e,t)}function g(){if(a)for(var n=0,r=t.length;n<r;++n)e[n]=+y(t[n],n,t)}return null==t&&(t=[]),d.initialize=function(t,n){a=t,h=n,x()},d.links=function(n){return arguments.length?(t=n,x(),d):t},d.id=function(t){return arguments.length?(c=t,d):c},d.iterations=function(t){return arguments.length?(v=+t,d):v},d.strength=function(t){return arguments.length?(f="function"==typeof t?t:(0,r.A)(+t),p(),d):f},d.distance=function(t){return arguments.length?(y="function"==typeof t?t:(0,r.A)(+t),g(),d):y},d}},93670:(t,n,e)=>{e.d(n,{A:()=>r});function r(t,n){var e,r=1;function i(){var i,u,o=e.length,a=0,s=0;for(i=0;i<o;++i)a+=(u=e[i]).x,s+=u.y;for(a=(a/o-t)*r,s=(s/o-n)*r,i=0;i<o;++i)u=e[i],u.x-=a,u.y-=s}return null==t&&(t=0),null==n&&(n=0),i.initialize=function(t){e=t},i.x=function(n){return arguments.length?(t=+n,i):t},i.y=function(t){return arguments.length?(n=+t,i):n},i.strength=function(t){return arguments.length?(r=+t,i):r},i}}}]);
|