elanous 0.2.5 → 0.2.7
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/.env.example +10 -7
- package/README.md +9 -4
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5391-8793f88b03b30161.js → 2375-cb6debea56cce4fb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1751.50b96ea9c37b49b6.js → 2415.ed6428ff334c7ce2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +25 -0
- package/apps/pwa/out/_next/static/chunks/{4daa2798-1363d725c79f3593.js → 2ea96958-e8c7e112de50b067.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +5 -0
- package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +1 -0
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8617.465ca22a319c95b3.js → 4323.c5dfb6f503304775.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4836-2eba6079f31b88d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8918-482b30ce2a8ebf4c.js → 5080-1613752891fcadb4.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5348-bbf838e119661eee.js → 5791-bb82743fa6299562.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9704-3221c102623c8d73.js → 6062-73e68343a9814f6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4440-18bb160d95819f4e.js → 6090-85a3f05f954e5697.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6284-69db415193d5f8bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{f6f3850d-7f324c6566002113.js → 8046cadf-211ca3c0e00f2b72.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8067-f74bf14d67ad98f1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8519-f6b5d8a5833a7603.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8894-e92491a164192cc1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9454-a3e0953307216c58.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9740-67051141115ce775.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9804-64c02c3c127d5014.js +1 -0
- package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d5ebde04844689e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/{page-f89e9a303515a033.js → page-10ed24f413ed66e9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/board/{page-4f403cd060442c95.js → page-211810b6c93ab66a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-0ac5d053f0444d21.js → page-624f7a2f89b60c8f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-5a5fb385a4df0ffe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-80497e93a878ddc5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-7457f52683562161.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-cee86394de407aa6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-4ff8edab44196b8c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-92e4f44428d5e290.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-b7dcf5d48a854b76.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-51480757e7d68b92.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-2a05dfe80c8bdf16.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-d9979633aa82f8e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-30533117beb53625.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-f7857826c2f97ad7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-07267f1391b96aba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-bccce0babceae30f.js → page-55d50e9b0006a91d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-9699b1786be6171d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-43dd772aee8af75f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-a7e37af7d0399cb8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-973ab7af59c718b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-a9f8d3865b91e436.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-15e5a15db84c56aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a2e572e4511f2a16.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-dd107bf1c7d52a90.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-d42b99cdfb9f27c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-2764ff40dad5a995.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-c5f1152db116ff96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-f933bca81ea38a6f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-c1c95739c0bff3b8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-a7aaffcf771662d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-71d18eec33b9c667.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-56adbe1a1f1379bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-2c4e59079ee357ac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-a81f113f3ef89d72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-5d422f38c052967e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fc27b00e20733146.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-6870f30ea99f8346.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{webpack-2bf59c720fe9542c.js → webpack-e5bea36f183b25e6.js} +1 -1
- package/apps/pwa/out/_next/static/css/f537bdb19c69306a.css +1 -0
- package/apps/pwa/out/_next/static/keajW7DDyghEs1y8oJe6T/_buildManifest.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -0
- package/apps/pwa/out/consult/index.txt +32 -0
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -0
- package/apps/pwa/out/exec/index.txt +32 -0
- package/apps/pwa/out/field/index.html +1 -0
- package/apps/pwa/out/field/index.txt +32 -0
- 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 +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/bin/elanous.cjs +107 -0
- package/graphs/field/field-feed.yaml +24 -0
- package/graphs/field/recipes.yaml +12 -0
- package/graphs/landing/landing-heal.yaml +3 -1
- package/graphs/landing/recipes.yaml +3 -0
- package/graphs/release/recipes.yaml +13 -0
- package/graphs/release/release-loop.yaml +13 -4
- package/package.json +5 -5
- package/plugins/card-followup/README.md +42 -0
- package/plugins/card-followup/examples/card-sample.json +7 -0
- package/plugins/card-followup/graphs/card-followup.yaml +18 -0
- package/plugins/card-followup/graphs/recipes.yaml +16 -0
- package/plugins/card-followup/graphs/run-step.ts +276 -0
- package/plugins/card-followup/graphs/sales-strategy.ts +173 -0
- package/plugins/card-followup/plugin.json +25 -0
- package/plugins/doc-draft/README.md +13 -0
- package/plugins/doc-draft/examples/brief-sample.json +8 -0
- package/plugins/doc-draft/graphs/doc-draft.yaml +14 -0
- package/plugins/doc-draft/graphs/recipes.yaml +9 -0
- package/plugins/doc-draft/graphs/run-step.ts +113 -0
- package/plugins/doc-draft/plugin.json +24 -0
- package/plugins/geo-check/README.md +15 -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 +198 -0
- package/plugins/geo-check/plugin.json +24 -0
- package/plugins/job-coach/.codex-plugin/plugin.json +1 -1
- package/plugins/job-coach/README.md +31 -1
- package/plugins/job-coach/graphs/run-step.ts +2 -2
- package/plugins/job-coach/plugin.json +1 -1
- package/plugins/job-coach/plugin.ts +1 -1
- package/scripts/affinity/endcard.sh +3 -2
- package/scripts/affinity/reframe.sh +3 -1
- package/scripts/ci-public-export-leak-gate.ts +48 -0
- package/scripts/codex-quota-alert.ts +122 -258
- package/scripts/coord-tracks.json +4 -4
- package/scripts/daemon-port-baseline.txt +1 -2
- package/scripts/field-feed/deliver-node.ts +52 -0
- package/scripts/field-feed/feed-node.ts +67 -0
- package/scripts/field-feed/lib.ts +162 -0
- package/scripts/field-feed/reel-node.ts +24 -0
- package/scripts/field-feed/start.ts +62 -0
- package/scripts/fixtures/vflow-sample.ndjson +6 -0
- package/scripts/install.sh +92 -13
- package/scripts/landing-heal/clean-checkout.ts +114 -0
- package/scripts/landing-heal/run-mission.ts +38 -3
- package/scripts/lib/android-test-device.ts +32 -0
- package/scripts/lib/pwa-scenarios/scenarios.ts +2 -1
- package/scripts/public-export.ts +8 -4
- package/scripts/release-loop/baseline-from-logs.ts +92 -0
- package/scripts/release-loop/checklist-gate-node.ts +35 -0
- package/scripts/release-loop/env-known-failures.ts +31 -0
- package/scripts/release-loop/gate-diff.ts +29 -0
- package/scripts/release-loop/gate-node.ts +124 -29
- package/scripts/release-loop/known-issues-node.ts +159 -0
- package/scripts/release-loop/npm-publish-node.ts +118 -0
- package/scripts/release-loop/ops-upgrade-node.ts +87 -0
- package/scripts/release-loop/release-readiness.ts +58 -0
- package/scripts/release-loop/shard-plan.ts +47 -0
- package/scripts/release-loop/unattended-release.ts +93 -0
- package/scripts/ux/measure-first-text.ts +102 -0
- package/scripts/ux/record-page.ts +4 -1
- package/scripts/vflow-collect.ts +20 -7
- package/scripts/vflow-search.ts +73 -0
- package/scripts/video-free-line-test-walker.ts +36 -0
- package/scripts/video-pipeline.ts +2 -2
- package/skills/explainer-video/SKILL.md +24 -3
- package/skills/explainer-video/engine/brand/elanous-mark-on-dark.svg +1 -1
- package/skills/explainer-video/engine/build.mjs +2 -2
- package/skills/explainer-video/engine/reel.mjs +235 -0
- package/skills/explainer-video/engine/reel.sh +9 -0
- package/skills/explainer-video/engine/vo.ts +58 -16
- package/skills/explainer-video/examples/elanous-0.2.5/script.json +1 -1
- package/skills/grill-me/SKILL.md +1 -1
- package/skills/omni-digest/docs/diagrams/noncode-terminal-promotion-path-2026-08-13.mmd +1 -1
- package/src/a2a/server.ts +2 -0
- package/src/acp/elanous-aware-peers.ts +30 -0
- package/src/acp/server.ts +91 -15
- package/src/agent/monad-agent-turn.ts +25 -6
- package/src/agent/shared-app-tools.ts +5 -3
- package/src/agent-substrate/review-intent.ts +6 -2
- package/src/agent-substrate/shard-boundary-intent.ts +70 -0
- package/src/auth/github-app-token.ts +4 -1
- package/src/autopilot/mission-origin.ts +20 -4
- package/src/autopilot/mission-phase-track.ts +11 -1
- package/src/autopilot/track-agent-shadow.ts +151 -0
- package/src/autopilot/track-agent.ts +26 -6
- package/src/autopilot/track-courier.ts +2 -2
- package/src/boot/acp-server-help.ts +16 -0
- package/src/boot/daemon-prompt-turn.ts +31 -10
- package/src/boot/daemon-tools/index.ts +7 -1
- package/src/budget/codex-credit-pace.ts +84 -0
- package/src/budget/codex-credit-plan.ts +154 -0
- package/src/budget/codex-reset-credit-state.ts +2 -0
- package/src/chat/chat-cli.ts +4 -1
- package/src/chat/short-question.ts +40 -0
- package/src/cli/agent-cli.ts +24 -15
- package/src/cli/ask-bare.ts +42 -0
- package/src/cli/cli-user-error.ts +25 -0
- package/src/cli/codex-credit-plan-view.ts +25 -0
- package/src/cli/dependence-gauge.ts +237 -0
- package/src/cli/doctor-cli.ts +5 -0
- package/src/cli/doctor-modes.ts +48 -0
- package/src/cli/intake-cli.ts +12 -2
- package/src/cli/intake-source-cli.ts +58 -0
- package/src/cli/machine-cli.ts +23 -0
- package/src/cli/msg-cli.ts +137 -0
- package/src/cli/nexus-ios-bind.ts +25 -8
- package/src/cli/phone-link.ts +117 -0
- package/src/cli/plugin-cli.ts +52 -0
- package/src/cli/pr-cli.ts +36 -0
- package/src/cli/private-ledger-commands.ts +31 -0
- package/src/cli/provider-cli.ts +5 -0
- package/src/cli/release-cli.ts +56 -12
- package/src/cli/release-run-if-ready.ts +48 -0
- package/src/cli/setup-cli.ts +27 -6
- package/src/cli/setup-recommend.ts +8 -0
- package/src/cli/usage-cli.ts +11 -1
- package/src/codex/setup.ts +27 -8
- package/src/dashboard/index.ts +1 -1
- package/src/discord.ts +56 -6
- package/src/domains/core-tools.ts +37 -14
- package/src/domains/outbound-alert.ts +55 -16
- package/src/exec-requests/planner.ts +140 -0
- package/src/exec-requests/runner.ts +338 -0
- package/src/exec-requests/store.ts +76 -0
- package/src/field/field-media.ts +250 -0
- package/src/field/field-reel.ts +196 -0
- package/src/grok/credential.ts +7 -5
- package/src/harness/aside-run-status.ts +33 -0
- package/src/harness/browser-verify.ts +48 -17
- package/src/harness/harness-cli-command.ts +25 -3
- package/src/harness/image-load-state.ts +21 -0
- package/src/harness/process-garbage.ts +45 -0
- package/src/index.ts +104 -38
- package/src/instance/leader.ts +13 -1
- package/src/intake-plane/collect-github.ts +5 -3
- package/src/intake-plane/collect-telegram-saved.ts +15 -3
- package/src/intake-plane/discord-seat-work.ts +56 -0
- package/src/intake-plane/intake-sources.ts +202 -0
- package/src/intake-plane/items.ts +28 -12
- package/src/intake-plane/seat-doc-route.ts +207 -0
- package/src/intake-plane/submit-intake-work.ts +9 -1
- package/src/intake-plane/telegram-seat-work.ts +72 -0
- package/src/llm/model-defaults.ts +24 -1
- package/src/llm.ts +5 -4
- package/src/machines/machine-ledger.ts +127 -0
- package/src/market/pack-internal-refs.ts +28 -0
- package/src/market/publish.ts +31 -4
- package/src/maturity/feature-maturity.ts +65 -0
- package/src/model-tier/turn-tier.ts +24 -0
- package/src/msg/msg-store.ts +149 -0
- package/src/native-tool-catalog.ts +2 -1
- package/src/nexus/api/chat-fast-path-config.ts +28 -0
- package/src/nexus/api/consult-requests.ts +117 -0
- package/src/nexus/api/discord-trigger-bot.ts +3 -0
- package/src/nexus/api/exec-requests.ts +51 -0
- package/src/nexus/api/field-uploads.ts +180 -0
- package/src/nexus/api/graph-approvals-feed.ts +140 -0
- package/src/nexus/api/graph-approvals.ts +120 -4
- package/src/nexus/api/harness-api.ts +219 -5
- package/src/nexus/api/http-server.ts +68 -5
- package/src/nexus/api/seat-requests.ts +254 -0
- package/src/nexus/api/trace-run-scan.ts +37 -0
- package/src/nexus/api/trace.ts +19 -3
- package/src/nexus/index.ts +3 -0
- package/src/nexus/setup-status.ts +4 -5
- package/src/notify/llm-budget-alert.ts +125 -0
- package/src/oauth/codex-account-rotation.ts +26 -4
- package/src/oauth/codex-account-store.ts +20 -2
- package/src/oauth/codex-browser-login.ts +173 -0
- package/src/oauth/codex.ts +4 -1
- package/src/oauth/fallback-chain.ts +5 -5
- package/src/oauth/store.ts +42 -5
- package/src/onboarding/continue-here.ts +29 -0
- package/src/onboarding/entry-hints.ts +8 -0
- package/src/onboarding/full-screen-io.ts +35 -3
- package/src/onboarding/help/skills.md +1 -1
- package/src/onboarding/non-interactive.ts +1 -0
- package/src/onboarding/subscription-hint.ts +27 -0
- package/src/onboarding/web-first.ts +83 -0
- package/src/onboarding.ts +230 -23
- package/src/plugins/maker/node-install.ts +92 -0
- package/src/plugins/maker/node-maker.ts +139 -0
- package/src/plugins/maker/plugin-maker.ts +220 -0
- package/src/policy/llm-policy.ts +268 -0
- package/src/prompt-library/session-guidance.ts +7 -1
- package/src/prompt-library/universal-preamble.ts +2 -2
- package/src/relay/channel.ts +184 -0
- package/src/relay/mux.ts +182 -0
- package/src/relay/relay-cli.ts +20 -0
- package/src/relay/relay-server.ts +220 -0
- package/src/relay/test-vectors.json +29 -0
- package/src/release-loop/checklist.ts +36 -9
- package/src/seat-address/seat-address.ts +34 -0
- package/src/self-dev/decompose.ts +1 -0
- package/src/self-dev/dev-pipeline.ts +6 -3
- package/src/self-dev/run-record-mirror.ts +44 -0
- package/src/self-dev/run-store.ts +12 -3
- package/src/self-implement/harness-policy-gates.ts +4 -1
- package/src/self-implement/report-origin.ts +12 -1
- package/src/self-implement/run-ledger-compact.ts +1 -1
- package/src/session/chat.ts +17 -5
- package/src/session/index.ts +23 -10
- package/src/skills/shared-agent-skill-roots.ts +25 -0
- package/src/steward/failure-streak.ts +78 -0
- package/src/steward/steward-cards.ts +24 -0
- package/src/steward/triage-budget.ts +127 -0
- package/src/steward/triage-plan.ts +75 -0
- package/src/steward/triage.ts +244 -42
- package/src/task-cards/card-store.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-bun-cache.ts +18 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +12 -3
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +11 -5
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +68 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +78 -4
- package/src/telegram.ts +145 -2
- package/src/tool-runtime/elanous-skills-list-runtime.ts +3 -3
- package/src/tool-runtime/self-cognition-runtimes.ts +160 -2
- package/src/user-config.ts +84 -4
- package/src/version/packed-revision.json +1 -1
- package/src/video-pipeline/recipes/character.ts +42 -5
- package/src/video-pipeline/recipes/explainer.ts +213 -0
- package/src/video-pipeline/recipes/ffmpeg.ts +1 -1
- package/src/video-pipeline/recipes/free-line.ts +16 -3
- package/src/video-pipeline/recipes/remote.ts +7 -1
- package/src/video-pipeline/vflow-reference.ts +109 -0
- package/src/video-pipeline/walk-line.ts +3 -2
- package/apps/pwa/out/_next/static/chunks/06ef2eba-d1b99ac6d2ea663c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1413-7179a49332db5a80.js +0 -1
- package/apps/pwa/out/_next/static/chunks/150-25c277137a9638ab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1640-bc99ec23bbe29d12.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2300-de059d0ab2a16630.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2684-05b0a81e75298c16.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3026-2ed7e317d9b02102.js +0 -25
- package/apps/pwa/out/_next/static/chunks/3611-77496ada38cd6358.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3717-68957c4dc9ceec90.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3929-46ba9af6f9d895cc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4015-62c5a3744698a8da.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4217-3c4317a7905f9eeb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4240-3230f230fae2d7d5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4271-e53e075ebd48593b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4377.3b125fef79576dfd.js +0 -5
- package/apps/pwa/out/_next/static/chunks/4853-35fdbe6bdbcdc0fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5007-6a3b30e23ff68a6e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5244-12b424c42070f5ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5611-df00af3e4e4a61bb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5890-dca2321773be829a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6123-37c9dc57ddaa7ab0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6588-b7975304a302ab91.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6604-c03961962b6273b6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7109-cf8c87e968e83a65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7178-30f77877525a2efb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7262-871563fc9663730b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7294-f0eeebb92aa93459.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7429-881af44deed6958f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7527.943753b6ed829f09.js +0 -1
- package/apps/pwa/out/_next/static/chunks/764-a01e858525a190c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7868-e35d5f7985ecd3f1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8320-51484af7b01fdfa5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9131-52f5fad51cceca04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9238.2cd5f47f4bf7a2c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-70c404c7bb6d7f0f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-3ffd80166b1050aa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-4bcc63e272ae8205.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-880734bd07d62882.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-72bd384898d88955.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1018bbc9586ecae5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-de86f8c38076dd7b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-70c404c7bb6d7f0f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-cd6447196d8bafe6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-e733630c47fa102b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-d1c1a8357b161875.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-60c514128e81d787.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8b637b7e325e13c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-63301d11dbe73836.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-a8cf0dc472060db2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-02fba54881ccfa49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-d5e8e90f0038f8de.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-b1ef6824f494466a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-d589bb0f233b1009.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c9bbaebef4cda059.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-3639ce7916b92fed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7450ae7478955653.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-70c404c7bb6d7f0f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-b41ca4abfd618452.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-b333dd79ebee3fa9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-8be1227492793655.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-6e03e9371b552e0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-911411e9fca18d03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-792170e649b37088.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-c40463466937bc91.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-509c798b80384536.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-1cac2aa21d77c417.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-9626799d9b4a2cd1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-84cd419494e16b0f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-361487d2da603917.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-607f5beb94cb2e07.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-d0222d219e29dddf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-a26980a31126decc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-edb2b37decf23e4d.js +0 -1
- package/apps/pwa/out/_next/static/css/eaa74e8bb2f62269.css +0 -1
- package/apps/pwa/out/_next/static/ktMqfrBbf8BMGac0jqLrb/_buildManifest.js +0 -1
- /package/apps/pwa/out/_next/static/{ktMqfrBbf8BMGac0jqLrb → keajW7DDyghEs1y8oJe6T}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="150 150 724 724"><path d="M842 512 L838.6 517.2 L835.4 522.4 L832.2 527.5 L828.9 532.5 L825.7 537.4 L822.4 542.2 L819 547 L815.7 551.6 L812.2 556.1 L808.8 560.5 L805.3 564.8 L801.7 569 L798.2 573.1 L794.5 577.1 L790.9 581 L787.2 584.8 L783.5 588.5 L779.7 592.1 L776 595.6 L772.2 599 L768.4 602.3 L764.5 605.5 L760.7 608.6 L756.8 611.6 L752.9 614.5 L749 617.4 L745.1 620.1 L741.2 622.7 L737.3 625.2 L733.4 627.7 L729.5 630 L725.6 632.3 L721.7 634.5 L717.8 636.6 L713.9 638.6 L710 640.5 L706.1 642.3 L702.2 644.1 L698.3 645.8 L694.5 647.4 L690.7 648.9 L686.9 650.3 L683.1 651.7 L679.3 653 L675.5 654.2 L671.8 655.4 L668.1 656.5 L664.4 657.5 L660.7 658.5 L657.1 659.3 L653.5 660.2 L649.9 661 L646.3 661.7 L642.8 662.3 L639.3 662.9 L635.8 663.5 L632.4 664 L629 664.4 L625.6 664.8 L622.2 665.2 L618.9 665.5 L615.6 665.7 L612.4 665.9 L609.1 666.1 L605.9 666.2 L602.8 666.3 L599.6 666.4 L596.5 666.4 L593.4 666.4 L590.4 666.3 L587.4 666.2 L584.4 666.1 L581.4 666 L578.5 665.8 L575.6 665.6 L572.7 665.3 L569.9 665.1 L567 664.8 L564.2 664.5 L561.5 664.1 L558.7 663.7 L556 663.4 L553.3 663 L550.6 662.5 L548 662.1 L545.4 661.6 L542.8 661.1 L540.2 660.6 L537.6 660.1 L535.1 659.5 L532.5 658.9 L530 658.3 L527.5 657.7 L525.1 657.1 L522.6 656.5 L520.2 655.8 L517.7 655.1 L515.3 654.4 L512.9 653.7 L510.5 653 L508.2 652.2 L505.8 651.4 L503.5 650.6 L501.1 649.8 L498.8 649 L496.5 648.1 L494.2 647.3 L491.9 646.4 L489.6 645.5 L487.3 644.5 L485.1 643.6 L482.8 642.6 L480.6 641.6 L478.3 640.6 L476.1 639.5 L473.9 638.4 L471.7 637.3 L469.5 636.2 L467.3 635 L465.1 633.9 L462.9 632.6 L460.7 631.4 L458.6 630.1 L456.4 628.8 L454.3 627.5 L452.2 626.1 L450 624.7 L447.9 623.3 L445.8 621.9 L443.8 620.4 L441.7 618.8 L439.6 617.3 L437.6 615.7 L435.6 614 L433.6 612.3 L431.6 610.6 L429.6 608.9 L427.6 607.1 L425.7 605.2 L423.8 603.4 L421.9 601.4 L420 599.5 L418.1 597.5 L416.3 595.4 L414.5 593.3 L412.7 591.2 L410.9 589 L409.2 586.8 L407.5 584.6 L405.8 582.3 L404.1 579.9 L402.5 577.5 L400.9 575.1 L399.3 572.6 L397.8 570 L396.2 567.4 L394.7 564.8 L393.2 562.1 L391.6 559.3 L389.8 556.5 L389.8 556.5 L387.3 558.7 L385.1 561.2 L383 563.7 L381.1 566.4 L379.3 569.1 L377.5 572 L375.8 574.9 L374.3 577.9 L372.8 581.1 L371.4 584.2 L370.1 587.5 L368.9 590.9 L367.8 594.3 L366.8 597.7 L365.8 601.3 L365 604.9 L364.3 608.6 L363.7 612.3 L363.2 616.1 L362.8 619.9 L362.5 623.8 L362.3 627.7 L362.2 631.7 L362.3 635.7 L362.4 639.7 L362.7 643.8 L363.1 647.9 L363.6 652 L364.2 656.1 L364.9 660.3 L365.8 664.4 L366.7 668.6 L367.8 672.8 L369 677 L370.4 681.1 L371.8 685.3 L373.4 689.5 L375.1 693.6 L377 697.8 L378.9 701.9 L381 706 L383.2 710.1 L385.5 714.1 L387.9 718.1 L390.5 722.1 L393.1 726 L395.9 729.9 L398.8 733.7 L401.8 737.5 L405 741.3 L408.2 744.9 L411.6 748.5 L415 752.1 L418.6 755.6 L422.3 759 L426.1 762.3 L430 765.5 L434 768.7 L438.1 771.8 L442.3 774.8 L446.5 777.7 L450.9 780.5 L455.4 783.3 L459.9 785.9 L464.6 788.4 L469.3 790.9 L474.1 793.2 L479 795.4 L483.9 797.5 L488.9 799.5 L494 801.4 L499.2 803.1 L504.4 804.8 L509.7 806.3 L515 807.7 L520.4 809 L525.8 810.2 L531.3 811.2 L536.8 812.1 L542.4 812.9 L548 813.5 L553.6 814.1 L559.3 814.5 L565 814.7 L570.7 814.8 L576.4 814.8 L582.2 814.7 L587.9 814.4 L593.7 814 L599.5 813.4 L605.3 812.8 L611 811.9 L616.8 811 L622.6 809.9 L628.3 808.7 L634 807.3 L639.8 805.8 L645.5 804.2 L651.1 802.4 L656.8 800.5 L662.4 798.5 L667.9 796.3 L673.5 794 L678.9 791.6 L684.4 789.1 L689.8 786.4 L695.1 783.6 L700.4 780.7 L705.6 777.6 L710.8 774.5 L715.9 771.2 L720.9 767.8 L725.9 764.3 L730.8 760.7 L735.6 756.9 L740.4 753.1 L745 749.1 L749.6 745 L754.1 740.9 L758.5 736.6 L762.8 732.2 L767 727.8 L771.2 723.2 L775.2 718.5 L779.1 713.8 L782.9 709 L786.7 704.1 L790.3 699.1 L793.8 694 L797.2 688.8 L800.5 683.6 L803.7 678.3 L806.8 672.9 L809.7 667.5 L812.6 662 L815.3 656.4 L817.9 650.8 L820.4 645.1 L822.8 639.4 L825 633.6 L827.2 627.8 L829.2 621.9 L831 616 L832.8 610.1 L834.4 604.1 L835.9 598.1 L837.3 592.1 L838.5 586 L839.6 579.9 L840.6 573.8 L841.4 567.7 L842.1 561.5 L842.7 555.4 L843.1 549.2 L843.4 543 L843.5 536.8 L843.5 530.6 L843.2 524.4 L842.8 518.2 L842 512.0Z" fill="#F2F1EE"/><path d="M347 797.8 L344.2 792.2 L341.3 786.8 L338.5 781.5 L335.8 776.2 L333.1 770.9 L330.6 765.7 L328.2 760.4 L325.9 755.2 L323.7 750 L321.6 744.8 L319.6 739.6 L317.8 734.4 L316 729.3 L314.4 724.1 L312.8 719 L311.4 713.9 L310 708.9 L308.8 703.8 L307.6 698.8 L306.6 693.8 L305.6 688.9 L304.8 683.9 L304 679 L303.3 674.2 L302.7 669.4 L302.2 664.6 L301.8 659.9 L301.5 655.2 L301.3 650.5 L301.1 645.9 L301 641.3 L301 636.8 L301.1 632.3 L301.2 627.9 L301.5 623.5 L301.7 619.2 L302.1 614.9 L302.5 610.7 L303 606.5 L303.5 602.4 L304.1 598.3 L304.8 594.3 L305.5 590.3 L306.2 586.4 L307.1 582.5 L307.9 578.7 L308.8 574.9 L309.8 571.2 L310.8 567.6 L311.8 564 L312.9 560.4 L314.1 556.9 L315.2 553.5 L316.4 550.1 L317.6 546.8 L318.9 543.5 L320.2 540.3 L321.5 537.1 L322.9 534 L324.2 530.9 L325.6 527.9 L327.1 524.9 L328.5 522 L330 519.1 L331.5 516.2 L333 513.4 L334.5 510.7 L336 508 L337.6 505.3 L339.2 502.7 L340.7 500.2 L342.3 497.6 L344 495.1 L345.6 492.7 L347.2 490.3 L348.9 487.9 L350.5 485.6 L352.2 483.3 L353.8 481 L355.5 478.8 L357.2 476.6 L358.9 474.4 L360.6 472.3 L362.3 470.2 L364 468.1 L365.8 466.1 L367.5 464.1 L369.2 462.1 L371 460.2 L372.7 458.2 L374.5 456.3 L376.3 454.4 L378 452.6 L379.8 450.8 L381.6 449 L383.4 447.2 L385.2 445.4 L387 443.7 L388.8 442 L390.7 440.3 L392.5 438.6 L394.3 436.9 L396.2 435.3 L398.1 433.7 L400 432.1 L401.8 430.5 L403.8 428.9 L405.7 427.4 L407.6 425.9 L409.6 424.4 L411.5 422.9 L413.5 421.4 L415.5 420 L417.5 418.6 L419.5 417.2 L421.6 415.8 L423.6 414.4 L425.7 413.1 L427.8 411.7 L429.9 410.4 L432.1 409.2 L434.2 407.9 L436.4 406.7 L438.6 405.5 L440.8 404.3 L443.1 403.1 L445.3 402 L447.6 400.9 L449.9 399.8 L452.3 398.7 L454.6 397.7 L457 396.7 L459.4 395.7 L461.9 394.8 L464.3 393.9 L466.8 393 L469.3 392.2 L471.9 391.4 L474.4 390.6 L477 389.9 L479.6 389.2 L482.3 388.6 L484.9 388 L487.6 387.4 L490.3 386.9 L493.1 386.4 L495.8 385.9 L498.6 385.5 L501.4 385.2 L504.3 384.9 L507.1 384.6 L510 384.4 L512.9 384.3 L515.9 384.1 L518.9 384.1 L521.9 384 L524.9 384 L528 384.1 L531.2 384.1 L534.6 384 L534.6 384 L533.9 380.6 L532.9 377.5 L531.7 374.5 L530.4 371.4 L528.9 368.5 L527.3 365.5 L525.6 362.6 L523.8 359.7 L521.8 356.9 L519.7 354.1 L517.6 351.3 L515.3 348.6 L512.9 346 L510.4 343.3 L507.8 340.8 L505 338.3 L502.2 335.8 L499.3 333.4 L496.3 331.1 L493.2 328.8 L489.9 326.6 L486.6 324.5 L483.3 322.4 L479.8 320.5 L476.2 318.6 L472.5 316.8 L468.8 315.1 L465 313.5 L461.1 311.9 L457.1 310.5 L453.1 309.1 L449 307.9 L444.8 306.8 L440.6 305.7 L436.3 304.8 L432 304 L427.6 303.2 L423.1 302.6 L418.6 302.2 L414.1 301.8 L409.5 301.5 L404.9 301.4 L400.2 301.4 L395.5 301.5 L390.8 301.7 L386.1 302 L381.3 302.5 L376.6 303.1 L371.8 303.8 L367 304.7 L362.2 305.7 L357.4 306.8 L352.6 308 L347.8 309.4 L343 310.8 L338.2 312.5 L333.4 314.2 L328.7 316.1 L324 318.1 L319.3 320.2 L314.6 322.4 L310 324.8 L305.4 327.3 L300.8 330 L296.3 332.7 L291.9 335.6 L287.4 338.6 L283.1 341.7 L278.8 344.9 L274.5 348.3 L270.4 351.7 L266.3 355.3 L262.2 359 L258.3 362.8 L254.4 366.7 L250.6 370.8 L246.9 374.9 L243.2 379.1 L239.7 383.5 L236.2 387.9 L232.9 392.4 L229.6 397 L226.4 401.7 L223.3 406.5 L220.4 411.4 L217.5 416.4 L214.8 421.4 L212.1 426.6 L209.6 431.8 L207.2 437 L204.9 442.4 L202.7 447.8 L200.7 453.3 L198.7 458.8 L196.9 464.4 L195.2 470 L193.7 475.7 L192.2 481.5 L190.9 487.3 L189.8 493.1 L188.7 499 L187.8 504.9 L187 510.8 L186.4 516.8 L185.9 522.7 L185.5 528.8 L185.2 534.8 L185.1 540.8 L185.1 546.9 L185.3 552.9 L185.6 559 L186 565 L186.6 571.1 L187.3 577.2 L188.1 583.2 L189.1 589.2 L190.2 595.2 L191.4 601.2 L192.8 607.2 L194.2 613.2 L195.9 619.1 L197.6 625 L199.5 630.8 L201.5 636.7 L203.7 642.4 L205.9 648.2 L208.3 653.8 L210.9 659.5 L213.5 665.1 L216.3 670.6 L219.1 676.1 L222.1 681.5 L225.2 686.8 L228.5 692.1 L231.8 697.3 L235.3 702.5 L238.8 707.5 L242.5 712.5 L246.3 717.5 L250.1 722.3 L254.1 727 L258.2 731.7 L262.4 736.3 L266.7 740.8 L271 745.2 L275.5 749.5 L280 753.7 L284.7 757.8 L289.4 761.8 L294.2 765.7 L299.1 769.4 L304.1 773.1 L309.1 776.7 L314.3 780.1 L319.5 783.5 L324.8 786.7 L330.1 789.7 L335.6 792.6 L341.2 795.4 L347 797.8Z" fill="#F2F1EE"/><path d="M347 226.2 L353.2 226.6 L359.3 226.8 L365.4 227 L371.3 227.3 L377.2 227.6 L383 228.1 L388.7 228.6 L394.4 229.2 L400 229.9 L405.6 230.7 L411.1 231.6 L416.5 232.6 L421.8 233.6 L427.1 234.8 L432.3 236 L437.5 237.3 L442.5 238.6 L447.5 240.1 L452.4 241.6 L457.3 243.2 L462 244.8 L466.7 246.6 L471.3 248.3 L475.9 250.2 L480.3 252.1 L484.7 254 L489 256.1 L493.3 258.1 L497.4 260.3 L501.5 262.4 L505.5 264.6 L509.4 266.9 L513.2 269.2 L517 271.5 L520.7 273.9 L524.3 276.3 L527.8 278.8 L531.3 281.2 L534.7 283.7 L538 286.3 L541.2 288.8 L544.4 291.4 L547.5 294 L550.5 296.6 L553.4 299.3 L556.3 301.9 L559.1 304.6 L561.8 307.3 L564.5 310 L567.1 312.7 L569.6 315.4 L572 318.1 L574.4 320.8 L576.8 323.6 L579.1 326.3 L581.3 329 L583.4 331.7 L585.5 334.5 L587.5 337.2 L589.5 339.9 L591.4 342.7 L593.3 345.4 L595.1 348.1 L596.9 350.8 L598.6 353.5 L600.3 356.2 L601.9 358.9 L603.4 361.6 L605 364.3 L606.4 367 L607.9 369.6 L609.3 372.3 L610.6 374.9 L611.9 377.5 L613.2 380.1 L614.4 382.8 L615.6 385.4 L616.8 387.9 L617.9 390.5 L619 393.1 L620.1 395.7 L621.1 398.2 L622.1 400.7 L623 403.3 L624 405.8 L624.9 408.3 L625.7 410.8 L626.6 413.3 L627.4 415.8 L628.2 418.3 L629 420.8 L629.7 423.2 L630.4 425.7 L631.1 428.1 L631.8 430.6 L632.4 433 L633.1 435.5 L633.7 437.9 L634.2 440.3 L634.8 442.8 L635.3 445.2 L635.8 447.6 L636.3 450.1 L636.8 452.5 L637.2 454.9 L637.7 457.4 L638.1 459.8 L638.4 462.2 L638.8 464.7 L639.1 467.1 L639.4 469.5 L639.7 472 L639.9 474.4 L640.2 476.9 L640.4 479.3 L640.5 481.8 L640.7 484.3 L640.8 486.7 L640.9 489.2 L641 491.7 L641 494.2 L641 496.7 L641 499.2 L641 501.7 L640.9 504.2 L640.8 506.7 L640.6 509.3 L640.4 511.8 L640.2 514.4 L640 516.9 L639.7 519.5 L639.3 522 L639 524.6 L638.6 527.2 L638.1 529.8 L637.6 532.4 L637.1 534.9 L636.5 537.5 L635.9 540.1 L635.2 542.7 L634.5 545.4 L633.8 548 L633 550.6 L632.1 553.2 L631.2 555.8 L630.3 558.4 L629.3 561 L628.2 563.6 L627.1 566.2 L625.9 568.9 L624.7 571.5 L623.5 574.1 L622.2 576.7 L620.8 579.3 L619.4 581.9 L617.9 584.5 L616.4 587.2 L614.8 589.8 L613.2 592.6 L611.6 595.6 L611.6 595.6 L614.8 596.6 L618 597.3 L621.3 597.8 L624.5 598.2 L627.9 598.4 L631.2 598.5 L634.6 598.5 L638 598.3 L641.4 598 L644.9 597.6 L648.3 597.1 L651.8 596.5 L655.4 595.8 L658.9 594.9 L662.4 593.9 L665.9 592.8 L669.5 591.6 L673 590.3 L676.5 588.8 L680.1 587.3 L683.6 585.6 L687.1 583.8 L690.5 581.9 L694 579.8 L697.4 577.7 L700.8 575.4 L704.1 573.1 L707.4 570.6 L710.7 568 L713.9 565.3 L717.1 562.4 L720.3 559.5 L723.3 556.5 L726.3 553.3 L729.3 550.1 L732.2 546.7 L735 543.3 L737.7 539.7 L740.4 536.1 L743 532.3 L745.5 528.5 L748 524.5 L750.3 520.5 L752.6 516.4 L754.7 512.2 L756.8 507.9 L758.7 503.6 L760.6 499.1 L762.4 494.6 L764.1 490.1 L765.6 485.4 L767.1 480.7 L768.4 475.9 L769.6 471.1 L770.7 466.2 L771.7 461.2 L772.6 456.3 L773.3 451.2 L774 446.1 L774.5 441 L774.9 435.8 L775.1 430.6 L775.2 425.4 L775.2 420.1 L775.1 414.9 L774.9 409.6 L774.5 404.2 L773.9 398.9 L773.3 393.6 L772.5 388.2 L771.6 382.9 L770.5 377.5 L769.4 372.2 L768.1 366.9 L766.6 361.5 L765 356.2 L763.3 350.9 L761.5 345.7 L759.5 340.4 L757.4 335.2 L755.1 330 L752.8 324.9 L750.3 319.8 L747.7 314.8 L744.9 309.7 L742 304.8 L739 299.9 L735.9 295 L732.7 290.2 L729.3 285.5 L725.8 280.9 L722.2 276.3 L718.5 271.7 L714.7 267.3 L710.8 262.9 L706.7 258.7 L702.6 254.5 L698.3 250.3 L693.9 246.3 L689.5 242.4 L684.9 238.5 L680.3 234.8 L675.5 231.2 L670.7 227.6 L665.8 224.2 L660.8 220.8 L655.7 217.6 L650.5 214.5 L645.2 211.5 L639.9 208.6 L634.5 205.8 L629.1 203.2 L623.5 200.6 L617.9 198.2 L612.3 195.9 L606.6 193.7 L600.8 191.7 L595 189.7 L589.2 187.9 L583.3 186.2 L577.3 184.7 L571.3 183.3 L565.3 182 L559.3 180.8 L553.2 179.8 L547.1 178.9 L541 178.1 L534.8 177.5 L528.7 177 L522.5 176.6 L516.3 176.3 L510.2 176.2 L504 176.2 L497.8 176.4 L491.6 176.7 L485.4 177.1 L479.2 177.7 L473.1 178.3 L466.9 179.1 L460.8 180.1 L454.7 181.2 L448.6 182.4 L442.6 183.7 L436.6 185.1 L430.6 186.7 L424.6 188.4 L418.7 190.3 L412.8 192.2 L407 194.3 L401.2 196.6 L395.5 198.9 L389.8 201.4 L384.2 204 L378.7 206.7 L373.2 209.5 L367.7 212.5 L362.4 215.6 L357.1 218.9 L352 222.4 L347 226.2Z" fill="#F2F1EE"/><circle cx="512" cy="512" r="62" fill="#E95047"/></svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="150 150 724 724"><path d="M842 512 L838.6 517.2 L835.4 522.4 L832.2 527.5 L828.9 532.5 L825.7 537.4 L822.4 542.2 L819 547 L815.7 551.6 L812.2 556.1 L808.8 560.5 L805.3 564.8 L801.7 569 L798.2 573.1 L794.5 577.1 L790.9 581 L787.2 584.8 L783.5 588.5 L779.7 592.1 L776 595.6 L772.2 599 L768.4 602.3 L764.5 605.5 L760.7 608.6 L756.8 611.6 L752.9 614.5 L749 617.4 L745.1 620.1 L741.2 622.7 L737.3 625.2 L733.4 627.7 L729.5 630 L725.6 632.3 L721.7 634.5 L717.8 636.6 L713.9 638.6 L710 640.5 L706.1 642.3 L702.2 644.1 L698.3 645.8 L694.5 647.4 L690.7 648.9 L686.9 650.3 L683.1 651.7 L679.3 653 L675.5 654.2 L671.8 655.4 L668.1 656.5 L664.4 657.5 L660.7 658.5 L657.1 659.3 L653.5 660.2 L649.9 661 L646.3 661.7 L642.8 662.3 L639.3 662.9 L635.8 663.5 L632.4 664 L629 664.4 L625.6 664.8 L622.2 665.2 L618.9 665.5 L615.6 665.7 L612.4 665.9 L609.1 666.1 L605.9 666.2 L602.8 666.3 L599.6 666.4 L596.5 666.4 L593.4 666.4 L590.4 666.3 L587.4 666.2 L584.4 666.1 L581.4 666 L578.5 665.8 L575.6 665.6 L572.7 665.3 L569.9 665.1 L567 664.8 L564.2 664.5 L561.5 664.1 L558.7 663.7 L556 663.4 L553.3 663 L550.6 662.5 L548 662.1 L545.4 661.6 L542.8 661.1 L540.2 660.6 L537.6 660.1 L535.1 659.5 L532.5 658.9 L530 658.3 L527.5 657.7 L525.1 657.1 L522.6 656.5 L520.2 655.8 L517.7 655.1 L515.3 654.4 L512.9 653.7 L510.5 653 L508.2 652.2 L505.8 651.4 L503.5 650.6 L501.1 649.8 L498.8 649 L496.5 648.1 L494.2 647.3 L491.9 646.4 L489.6 645.5 L487.3 644.5 L485.1 643.6 L482.8 642.6 L480.6 641.6 L478.3 640.6 L476.1 639.5 L473.9 638.4 L471.7 637.3 L469.5 636.2 L467.3 635 L465.1 633.9 L462.9 632.6 L460.7 631.4 L458.6 630.1 L456.4 628.8 L454.3 627.5 L452.2 626.1 L450 624.7 L447.9 623.3 L445.8 621.9 L443.8 620.4 L441.7 618.8 L439.6 617.3 L437.6 615.7 L435.6 614 L433.6 612.3 L431.6 610.6 L429.6 608.9 L427.6 607.1 L425.7 605.2 L423.8 603.4 L421.9 601.4 L420 599.5 L418.1 597.5 L416.3 595.4 L414.5 593.3 L412.7 591.2 L410.9 589 L409.2 586.8 L407.5 584.6 L405.8 582.3 L404.1 579.9 L402.5 577.5 L400.9 575.1 L399.3 572.6 L397.8 570 L396.2 567.4 L394.7 564.8 L393.2 562.1 L391.6 559.3 L389.8 556.5 L389.8 556.5 L387.3 558.7 L385.1 561.2 L383 563.7 L381.1 566.4 L379.3 569.1 L377.5 572 L375.8 574.9 L374.3 577.9 L372.8 581.1 L371.4 584.2 L370.1 587.5 L368.9 590.9 L367.8 594.3 L366.8 597.7 L365.8 601.3 L365 604.9 L364.3 608.6 L363.7 612.3 L363.2 616.1 L362.8 619.9 L362.5 623.8 L362.3 627.7 L362.2 631.7 L362.3 635.7 L362.4 639.7 L362.7 643.8 L363.1 647.9 L363.6 652 L364.2 656.1 L364.9 660.3 L365.8 664.4 L366.7 668.6 L367.8 672.8 L369 677 L370.4 681.1 L371.8 685.3 L373.4 689.5 L375.1 693.6 L377 697.8 L378.9 701.9 L381 706 L383.2 710.1 L385.5 714.1 L387.9 718.1 L390.5 722.1 L393.1 726 L395.9 729.9 L398.8 733.7 L401.8 737.5 L405 741.3 L408.2 744.9 L411.6 748.5 L415 752.1 L418.6 755.6 L422.3 759 L426.1 762.3 L430 765.5 L434 768.7 L438.1 771.8 L442.3 774.8 L446.5 777.7 L450.9 780.5 L455.4 783.3 L459.9 785.9 L464.6 788.4 L469.3 790.9 L474.1 793.2 L479 795.4 L483.9 797.5 L488.9 799.5 L494 801.4 L499.2 803.1 L504.4 804.8 L509.7 806.3 L515 807.7 L520.4 809 L525.8 810.2 L531.3 811.2 L536.8 812.1 L542.4 812.9 L548 813.5 L553.6 814.1 L559.3 814.5 L565 814.7 L570.7 814.8 L576.4 814.8 L582.2 814.7 L587.9 814.4 L593.7 814 L599.5 813.4 L605.3 812.8 L611 811.9 L616.8 811 L622.6 809.9 L628.3 808.7 L634 807.3 L639.8 805.8 L645.5 804.2 L651.1 802.4 L656.8 800.5 L662.4 798.5 L667.9 796.3 L673.5 794 L678.9 791.6 L684.4 789.1 L689.8 786.4 L695.1 783.6 L700.4 780.7 L705.6 777.6 L710.8 774.5 L715.9 771.2 L720.9 767.8 L725.9 764.3 L730.8 760.7 L735.6 756.9 L740.4 753.1 L745 749.1 L749.6 745 L754.1 740.9 L758.5 736.6 L762.8 732.2 L767 727.8 L771.2 723.2 L775.2 718.5 L779.1 713.8 L782.9 709 L786.7 704.1 L790.3 699.1 L793.8 694 L797.2 688.8 L800.5 683.6 L803.7 678.3 L806.8 672.9 L809.7 667.5 L812.6 662 L815.3 656.4 L817.9 650.8 L820.4 645.1 L822.8 639.4 L825 633.6 L827.2 627.8 L829.2 621.9 L831 616 L832.8 610.1 L834.4 604.1 L835.9 598.1 L837.3 592.1 L838.5 586 L839.6 579.9 L840.6 573.8 L841.4 567.7 L842.1 561.5 L842.7 555.4 L843.1 549.2 L843.4 543 L843.5 536.8 L843.5 530.6 L843.2 524.4 L842.8 518.2 L842 512.0Z" fill="#F2F1EE"/><path d="M347 797.8 L344.2 792.2 L341.3 786.8 L338.5 781.5 L335.8 776.2 L333.1 770.9 L330.6 765.7 L328.2 760.4 L325.9 755.2 L323.7 750 L321.6 744.8 L319.6 739.6 L317.8 734.4 L316 729.3 L314.4 724.1 L312.8 719 L311.4 713.9 L310 708.9 L308.8 703.8 L307.6 698.8 L306.6 693.8 L305.6 688.9 L304.8 683.9 L304 679 L303.3 674.2 L302.7 669.4 L302.2 664.6 L301.8 659.9 L301.5 655.2 L301.3 650.5 L301.1 645.9 L301 641.3 L301 636.8 L301.1 632.3 L301.2 627.9 L301.5 623.5 L301.7 619.2 L302.1 614.9 L302.5 610.7 L303 606.5 L303.5 602.4 L304.1 598.3 L304.8 594.3 L305.5 590.3 L306.2 586.4 L307.1 582.5 L307.9 578.7 L308.8 574.9 L309.8 571.2 L310.8 567.6 L311.8 564 L312.9 560.4 L314.1 556.9 L315.2 553.5 L316.4 550.1 L317.6 546.8 L318.9 543.5 L320.2 540.3 L321.5 537.1 L322.9 534 L324.2 530.9 L325.6 527.9 L327.1 524.9 L328.5 522 L330 519.1 L331.5 516.2 L333 513.4 L334.5 510.7 L336 508 L337.6 505.3 L339.2 502.7 L340.7 500.2 L342.3 497.6 L344 495.1 L345.6 492.7 L347.2 490.3 L348.9 487.9 L350.5 485.6 L352.2 483.3 L353.8 481 L355.5 478.8 L357.2 476.6 L358.9 474.4 L360.6 472.3 L362.3 470.2 L364 468.1 L365.8 466.1 L367.5 464.1 L369.2 462.1 L371 460.2 L372.7 458.2 L374.5 456.3 L376.3 454.4 L378 452.6 L379.8 450.8 L381.6 449 L383.4 447.2 L385.2 445.4 L387 443.7 L388.8 442 L390.7 440.3 L392.5 438.6 L394.3 436.9 L396.2 435.3 L398.1 433.7 L400 432.1 L401.8 430.5 L403.8 428.9 L405.7 427.4 L407.6 425.9 L409.6 424.4 L411.5 422.9 L413.5 421.4 L415.5 420 L417.5 418.6 L419.5 417.2 L421.6 415.8 L423.6 414.4 L425.7 413.1 L427.8 411.7 L429.9 410.4 L432.1 409.2 L434.2 407.9 L436.4 406.7 L438.6 405.5 L440.8 404.3 L443.1 403.1 L445.3 402 L447.6 400.9 L449.9 399.8 L452.3 398.7 L454.6 397.7 L457 396.7 L459.4 395.7 L461.9 394.8 L464.3 393.9 L466.8 393 L469.3 392.2 L471.9 391.4 L474.4 390.6 L477 389.9 L479.6 389.2 L482.3 388.6 L484.9 388 L487.6 387.4 L490.3 386.9 L493.1 386.4 L495.8 385.9 L498.6 385.5 L501.4 385.2 L504.3 384.9 L507.1 384.6 L510 384.4 L512.9 384.3 L515.9 384.1 L518.9 384.1 L521.9 384 L524.9 384 L528 384.1 L531.2 384.1 L534.6 384 L534.6 384 L533.9 380.6 L532.9 377.5 L531.7 374.5 L530.4 371.4 L528.9 368.5 L527.3 365.5 L525.6 362.6 L523.8 359.7 L521.8 356.9 L519.7 354.1 L517.6 351.3 L515.3 348.6 L512.9 346 L510.4 343.3 L507.8 340.8 L505 338.3 L502.2 335.8 L499.3 333.4 L496.3 331.1 L493.2 328.8 L489.9 326.6 L486.6 324.5 L483.3 322.4 L479.8 320.5 L476.2 318.6 L472.5 316.8 L468.8 315.1 L465 313.5 L461.1 311.9 L457.1 310.5 L453.1 309.1 L449 307.9 L444.8 306.8 L440.6 305.7 L436.3 304.8 L432 304 L427.6 303.2 L423.1 302.6 L418.6 302.2 L414.1 301.8 L409.5 301.5 L404.9 301.4 L400.2 301.4 L395.5 301.5 L390.8 301.7 L386.1 302 L381.3 302.5 L376.6 303.1 L371.8 303.8 L367 304.7 L362.2 305.7 L357.4 306.8 L352.6 308 L347.8 309.4 L343 310.8 L338.2 312.5 L333.4 314.2 L328.7 316.1 L324 318.1 L319.3 320.2 L314.6 322.4 L310 324.8 L305.4 327.3 L300.8 330 L296.3 332.7 L291.9 335.6 L287.4 338.6 L283.1 341.7 L278.8 344.9 L274.5 348.3 L270.4 351.7 L266.3 355.3 L262.2 359 L258.3 362.8 L254.4 366.7 L250.6 370.8 L246.9 374.9 L243.2 379.1 L239.7 383.5 L236.2 387.9 L232.9 392.4 L229.6 397 L226.4 401.7 L223.3 406.5 L220.4 411.4 L217.5 416.4 L214.8 421.4 L212.1 426.6 L209.6 431.8 L207.2 437 L204.9 442.4 L202.7 447.8 L200.7 453.3 L198.7 458.8 L196.9 464.4 L195.2 470 L193.7 475.7 L192.2 481.5 L190.9 487.3 L189.8 493.1 L188.7 499 L187.8 504.9 L187 510.8 L186.4 516.8 L185.9 522.7 L185.5 528.8 L185.2 534.8 L185.1 540.8 L185.1 546.9 L185.3 552.9 L185.6 559 L186 565 L186.6 571.1 L187.3 577.2 L188.1 583.2 L189.1 589.2 L190.2 595.2 L191.4 601.2 L192.8 607.2 L194.2 613.2 L195.9 619.1 L197.6 625 L199.5 630.8 L201.5 636.7 L203.7 642.4 L205.9 648.2 L208.3 653.8 L210.9 659.5 L213.5 665.1 L216.3 670.6 L219.1 676.1 L222.1 681.5 L225.2 686.8 L228.5 692.1 L231.8 697.3 L235.3 702.5 L238.8 707.5 L242.5 712.5 L246.3 717.5 L250.1 722.3 L254.1 727 L258.2 731.7 L262.4 736.3 L266.7 740.8 L271 745.2 L275.5 749.5 L280 753.7 L284.7 757.8 L289.4 761.8 L294.2 765.7 L299.1 769.4 L304.1 773.1 L309.1 776.7 L314.3 780.1 L319.5 783.5 L324.8 786.7 L330.1 789.7 L335.6 792.6 L341.2 795.4 L347 797.8Z" fill="#F2F1EE"/><path d="M347 226.2 L353.2 226.6 L359.3 226.8 L365.4 227 L371.3 227.3 L377.2 227.6 L383 228.1 L388.7 228.6 L394.4 229.2 L400 229.9 L405.6 230.7 L411.1 231.6 L416.5 232.6 L421.8 233.6 L427.1 234.8 L432.3 236 L437.5 237.3 L442.5 238.6 L447.5 240.1 L452.4 241.6 L457.3 243.2 L462 244.8 L466.7 246.6 L471.3 248.3 L475.9 250.2 L480.3 252.1 L484.7 254 L489 256.1 L493.3 258.1 L497.4 260.3 L501.5 262.4 L505.5 264.6 L509.4 266.9 L513.2 269.2 L517 271.5 L520.7 273.9 L524.3 276.3 L527.8 278.8 L531.3 281.2 L534.7 283.7 L538 286.3 L541.2 288.8 L544.4 291.4 L547.5 294 L550.5 296.6 L553.4 299.3 L556.3 301.9 L559.1 304.6 L561.8 307.3 L564.5 310 L567.1 312.7 L569.6 315.4 L572 318.1 L574.4 320.8 L576.8 323.6 L579.1 326.3 L581.3 329 L583.4 331.7 L585.5 334.5 L587.5 337.2 L589.5 339.9 L591.4 342.7 L593.3 345.4 L595.1 348.1 L596.9 350.8 L598.6 353.5 L600.3 356.2 L601.9 358.9 L603.4 361.6 L605 364.3 L606.4 367 L607.9 369.6 L609.3 372.3 L610.6 374.9 L611.9 377.5 L613.2 380.1 L614.4 382.8 L615.6 385.4 L616.8 387.9 L617.9 390.5 L619 393.1 L620.1 395.7 L621.1 398.2 L622.1 400.7 L623 403.3 L624 405.8 L624.9 408.3 L625.7 410.8 L626.6 413.3 L627.4 415.8 L628.2 418.3 L629 420.8 L629.7 423.2 L630.4 425.7 L631.1 428.1 L631.8 430.6 L632.4 433 L633.1 435.5 L633.7 437.9 L634.2 440.3 L634.8 442.8 L635.3 445.2 L635.8 447.6 L636.3 450.1 L636.8 452.5 L637.2 454.9 L637.7 457.4 L638.1 459.8 L638.4 462.2 L638.8 464.7 L639.1 467.1 L639.4 469.5 L639.7 472 L639.9 474.4 L640.2 476.9 L640.4 479.3 L640.5 481.8 L640.7 484.3 L640.8 486.7 L640.9 489.2 L641 491.7 L641 494.2 L641 496.7 L641 499.2 L641 501.7 L640.9 504.2 L640.8 506.7 L640.6 509.3 L640.4 511.8 L640.2 514.4 L640 516.9 L639.7 519.5 L639.3 522 L639 524.6 L638.6 527.2 L638.1 529.8 L637.6 532.4 L637.1 534.9 L636.5 537.5 L635.9 540.1 L635.2 542.7 L634.5 545.4 L633.8 548 L633 550.6 L632.1 553.2 L631.2 555.8 L630.3 558.4 L629.3 561 L628.2 563.6 L627.1 566.2 L625.9 568.9 L624.7 571.5 L623.5 574.1 L622.2 576.7 L620.8 579.3 L619.4 581.9 L617.9 584.5 L616.4 587.2 L614.8 589.8 L613.2 592.6 L611.6 595.6 L611.6 595.6 L614.8 596.6 L618 597.3 L621.3 597.8 L624.5 598.2 L627.9 598.4 L631.2 598.5 L634.6 598.5 L638 598.3 L641.4 598 L644.9 597.6 L648.3 597.1 L651.8 596.5 L655.4 595.8 L658.9 594.9 L662.4 593.9 L665.9 592.8 L669.5 591.6 L673 590.3 L676.5 588.8 L680.1 587.3 L683.6 585.6 L687.1 583.8 L690.5 581.9 L694 579.8 L697.4 577.7 L700.8 575.4 L704.1 573.1 L707.4 570.6 L710.7 568 L713.9 565.3 L717.1 562.4 L720.3 559.5 L723.3 556.5 L726.3 553.3 L729.3 550.1 L732.2 546.7 L735 543.3 L737.7 539.7 L740.4 536.1 L743 532.3 L745.5 528.5 L748 524.5 L750.3 520.5 L752.6 516.4 L754.7 512.2 L756.8 507.9 L758.7 503.6 L760.6 499.1 L762.4 494.6 L764.1 490.1 L765.6 485.4 L767.1 480.7 L768.4 475.9 L769.6 471.1 L770.7 466.2 L771.7 461.2 L772.6 456.3 L773.3 451.2 L774 446.1 L774.5 441 L774.9 435.8 L775.1 430.6 L775.2 425.4 L775.2 420.1 L775.1 414.9 L774.9 409.6 L774.5 404.2 L773.9 398.9 L773.3 393.6 L772.5 388.2 L771.6 382.9 L770.5 377.5 L769.4 372.2 L768.1 366.9 L766.6 361.5 L765 356.2 L763.3 350.9 L761.5 345.7 L759.5 340.4 L757.4 335.2 L755.1 330 L752.8 324.9 L750.3 319.8 L747.7 314.8 L744.9 309.7 L742 304.8 L739 299.9 L735.9 295 L732.7 290.2 L729.3 285.5 L725.8 280.9 L722.2 276.3 L718.5 271.7 L714.7 267.3 L710.8 262.9 L706.7 258.7 L702.6 254.5 L698.3 250.3 L693.9 246.3 L689.5 242.4 L684.9 238.5 L680.3 234.8 L675.5 231.2 L670.7 227.6 L665.8 224.2 L660.8 220.8 L655.7 217.6 L650.5 214.5 L645.2 211.5 L639.9 208.6 L634.5 205.8 L629.1 203.2 L623.5 200.6 L617.9 198.2 L612.3 195.9 L606.6 193.7 L600.8 191.7 L595 189.7 L589.2 187.9 L583.3 186.2 L577.3 184.7 L571.3 183.3 L565.3 182 L559.3 180.8 L553.2 179.8 L547.1 178.9 L541 178.1 L534.8 177.5 L528.7 177 L522.5 176.6 L516.3 176.3 L510.2 176.2 L504 176.2 L497.8 176.4 L491.6 176.7 L485.4 177.1 L479.2 177.7 L473.1 178.3 L466.9 179.1 L460.8 180.1 L454.7 181.2 L448.6 182.4 L442.6 183.7 L436.6 185.1 L430.6 186.7 L424.6 188.4 L418.7 190.3 L412.8 192.2 L407 194.3 L401.2 196.6 L395.5 198.9 L389.8 201.4 L384.2 204 L378.7 206.7 L373.2 209.5 L367.7 212.5 L362.4 215.6 L357.1 218.9 L352 222.4 L347 226.2Z" fill="#F2F1EE"/><circle cx="512" cy="512" r="76" fill="#E95047"/></svg>
|
|
@@ -22,11 +22,11 @@ const W = 1920, H = 1080, FPS = 30;
|
|
|
22
22
|
// ── palette (Elanvital CI · RCBC guide) ─────────────────────────────────────────
|
|
23
23
|
const C = { deep: "#1D2751", deep2: "#141C3D", black: "#000000", ink: "#F2F1EE", red: "#E95047", muted: "rgba(242,241,238,0.62)", line: "rgba(242,241,238,0.86)", faint: "rgba(242,241,238,0.10)" };
|
|
24
24
|
|
|
25
|
-
// ── mark (V6 «엘랑 소용돌이»,
|
|
25
|
+
// ── mark (V6 «엘랑 소용돌이», engine/brand/) ─────────────────────────────────────
|
|
26
26
|
const markSrc = readFileSync(process.env.ELANOUS_MARK ?? join(here, "brand", "elanous-mark-on-dark.svg"), "utf8");
|
|
27
27
|
const markPaths = [...markSrc.matchAll(/<path d="([^"]*)"/g)].map((m) => m[1]);
|
|
28
28
|
const mark = (size, blade = C.ink, dot = C.red, cls = "") =>
|
|
29
|
-
`<svg class="${cls}" width="${size}" height="${size}" viewBox="150 150 724 724">${markPaths.map((d) => `<path d="${d}" fill="${blade}"/>`).join("")}<circle cx="512" cy="512" r="
|
|
29
|
+
`<svg class="${cls}" width="${size}" height="${size}" viewBox="150 150 724 724">${markPaths.map((d) => `<path d="${d}" fill="${blade}"/>`).join("")}<circle cx="512" cy="512" r="76" fill="${dot}"/></svg>`;
|
|
30
30
|
|
|
31
31
|
// ── timing from alignment ───────────────────────────────────────────────────────
|
|
32
32
|
const vo = (key) => JSON.parse(readFileSync(join(proj, "source", "vo", `${key}.json`), "utf8"));
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// Field reel — a folder of phone photos / short clips → one vertical HyperFrames composition (EV10 · EV10b).
|
|
2
|
+
// Usage: node reel.mjs <folder> [--title "마케터의 밤"] [--sub "2026.10.02 · 서울"] [--max 60] [--min 24] [--part full|body]
|
|
3
|
+
// <folder>/captions.txt (optional): one line per item — `파일명 | 자막` (a line without « | » is ignored).
|
|
4
|
+
// Photos without a caption get one line from a vision model (codex · parallel · FIELD_REEL_VISION=0 turns it off);
|
|
5
|
+
// if that fails the caption is «현장 N». A slug-like title (`field-2026-10-01`) is replaced by a vision headline.
|
|
6
|
+
// BGM: FIELD_REEL_BGM=<wav/mp3> or ~/.cache/elanous-explainer/bgm/field.wav — cut to length, faded and leveled here.
|
|
7
|
+
// --part body: photos only, no intro/end cards and no music (the instant version stitches cached cards around it).
|
|
8
|
+
// Output: <folder>/reel/hf/ (HyperFrames project) ⊕ reel/timeline.json. Render: npx hyperframes render --fps 30 in reel/hf.
|
|
9
|
+
// Look = Elanvital CI: Real Black ground · Icarus Red single accent · V6 mark · Pretendard. Order = capture time (then name).
|
|
10
|
+
import { readFileSync, writeFileSync, mkdirSync, copyFileSync, existsSync, readdirSync, statSync } from "node:fs";
|
|
11
|
+
import { join, dirname, resolve, extname, basename } from "node:path";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
|
|
16
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const argv = process.argv.slice(2);
|
|
18
|
+
const opt = (k, d) => { const i = argv.indexOf(`--${k}`); return i >= 0 ? argv[i + 1] : d; };
|
|
19
|
+
const folder = resolve(argv.find((a, i) => !a.startsWith("--") && !(i > 0 && argv[i - 1].startsWith("--"))) ?? ".");
|
|
20
|
+
const PART = opt("part", "full");
|
|
21
|
+
const MAX = Number(opt("max", 60)), MIN = Number(opt("min", 24));
|
|
22
|
+
const W = 1080, H = 1920, PHOTO = 4.2, CLIP_MAX = 5, XF = 0.5;
|
|
23
|
+
const INTRO = PART === "body" ? 0 : 3.0, END = PART === "body" ? 0 : 3.4;
|
|
24
|
+
const out = join(folder, "reel"), hf = join(out, "hf"), media = join(hf, "assets", "media");
|
|
25
|
+
mkdirSync(media, { recursive: true }); mkdirSync(join(hf, "assets", "fonts"), { recursive: true });
|
|
26
|
+
const T0 = Date.now(), lap = (s) => console.log(`reel: ${s} · ${((Date.now() - T0) / 1000).toFixed(1)}s`);
|
|
27
|
+
|
|
28
|
+
// ── collect & order ────────────────────────────────────────────────────────────
|
|
29
|
+
const IMG = [".jpg", ".jpeg", ".png", ".heic", ".webp"], VID = [".mp4", ".mov", ".m4v"];
|
|
30
|
+
const run = (bin, args) => spawnSync(bin, args, { encoding: "utf8" });
|
|
31
|
+
// Uploads from the field endpoint are named `20261002T193012Z-<device>-<name>` (capture time, UTC) — trust that first.
|
|
32
|
+
const stamped = (f) => { const m = /^(\d{8})T(\d{6})Z-/.exec(f); return m ? Date.parse(`${m[1].slice(0, 4)}-${m[1].slice(4, 6)}-${m[1].slice(6)}T${m[2].slice(0, 2)}:${m[2].slice(2, 4)}:${m[2].slice(4)}Z`) : NaN; };
|
|
33
|
+
const created = (p) => {
|
|
34
|
+
const st = stamped(basename(p)); if (Number.isFinite(st)) return st;
|
|
35
|
+
const m = run("mdls", ["-raw", "-name", "kMDItemContentCreationDate", p]).stdout?.trim();
|
|
36
|
+
const t = m && m !== "(null)" ? Date.parse(m.replace(" +0000", "Z").replace(" ", "T")) : NaN;
|
|
37
|
+
return Number.isFinite(t) ? t : statSync(p).mtimeMs;
|
|
38
|
+
};
|
|
39
|
+
const probeDur = (p) => Number(run("ffprobe", ["-v", "error", "-show_entries", "format=duration", "-of", "csv=p=0", p]).stdout.trim()) || 0;
|
|
40
|
+
const caps = Object.fromEntries((existsSync(join(folder, "captions.txt")) ? readFileSync(join(folder, "captions.txt"), "utf8") : "")
|
|
41
|
+
.split("\n").filter((l) => l.includes("|")).map((l) => l.split("|").map((s) => s.trim())));
|
|
42
|
+
let items = readdirSync(folder).filter((f) => [...IMG, ...VID].includes(extname(f).toLowerCase()))
|
|
43
|
+
.map((f) => ({ f, p: join(folder, f), video: VID.includes(extname(f).toLowerCase()), t: created(join(folder, f)) }))
|
|
44
|
+
.sort((a, b) => a.t - b.t || a.f.localeCompare(b.f));
|
|
45
|
+
if (!items.length) throw new Error(`no photos or clips in ${folder}`);
|
|
46
|
+
|
|
47
|
+
// ── durations: fit into [MIN, MAX] ─────────────────────────────────────────────
|
|
48
|
+
for (const it of items) it.dur = it.video ? Math.min(CLIP_MAX, Math.max(1.5, probeDur(it.p))) : PHOTO;
|
|
49
|
+
const body = () => items.reduce((a, it) => a + it.dur, 0);
|
|
50
|
+
while (INTRO + body() + END > MAX && items.length > 1) items.splice(Math.floor(items.length / 2), 1); // drop from the middle, keep first & last
|
|
51
|
+
if (PART !== "body" && INTRO + body() + END < MIN) { const photos = items.filter((i) => !i.video); const need = MIN - (INTRO + body() + END); for (const p of photos) p.dur += need / Math.max(1, photos.length); }
|
|
52
|
+
|
|
53
|
+
// ── media prep: HEIC → jpg · big photos down to 2160 · a small copy for the vision model · clips re-encoded short & muted ──
|
|
54
|
+
let t = INTRO;
|
|
55
|
+
items.forEach((it, i) => {
|
|
56
|
+
it.start = +t.toFixed(3); t += it.dur;
|
|
57
|
+
if (it.video) {
|
|
58
|
+
it.src = `m${i}.mp4`;
|
|
59
|
+
const r = run("ffmpeg", ["-v", "error", "-y", "-i", it.p, "-t", String(it.dur), "-an", "-vf", `scale=${W}:${H}:force_original_aspect_ratio=increase,crop=${W}:${H},fps=30`, "-c:v", "libx264", "-preset", "veryfast", "-crf", "20", "-pix_fmt", "yuv420p", join(media, it.src)]);
|
|
60
|
+
if (r.status !== 0) throw new Error(`clip ${it.f}: ${r.stderr.slice(0, 200)}`);
|
|
61
|
+
} else {
|
|
62
|
+
it.src = `m${i}.jpg`;
|
|
63
|
+
const r = run("sips", ["-s", "format", "jpeg", "-Z", "2160", it.p, "--out", join(media, it.src)]);
|
|
64
|
+
if (r.status !== 0) throw new Error(`photo ${it.f}: ${r.stderr.slice(0, 200)}`);
|
|
65
|
+
const dim = run("sips", ["-g", "pixelWidth", "-g", "pixelHeight", join(media, it.src)]).stdout;
|
|
66
|
+
const pw = Number(/pixelWidth: (\d+)/.exec(dim)?.[1]), ph = Number(/pixelHeight: (\d+)/.exec(dim)?.[1]);
|
|
67
|
+
it.wide = pw > 0 && ph > 0 && pw / ph > 0.75; // anything wider than 3:4 is shown whole over a blurred fill
|
|
68
|
+
run("sips", ["-s", "format", "jpeg", "-Z", "1024", it.p, "--out", join(out, `v${i}.jpg`)]);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
const TOTAL = +(t + END).toFixed(3);
|
|
72
|
+
lap(`${items.length} items prepared`);
|
|
73
|
+
|
|
74
|
+
// ── vision: one caption line per photo, in parallel; a headline when the title is only a slug ──
|
|
75
|
+
const CODEX = process.env.FIELD_REEL_CODEX_BIN || "codex";
|
|
76
|
+
const VISION = process.env.FIELD_REEL_VISION !== "0";
|
|
77
|
+
const ask = (prompt, images, ms = 30000) => new Promise((done) => {
|
|
78
|
+
const args = ["exec", "--skip-git-repo-check", "-c", "model_reasoning_effort=low", prompt, ...images.flatMap((im) => ["-i", im])];
|
|
79
|
+
let buf = "", settled = false;
|
|
80
|
+
const finish = (v) => { if (!settled) { settled = true; done(v); } };
|
|
81
|
+
let child;
|
|
82
|
+
try { child = spawn(CODEX, args, { stdio: ["ignore", "pipe", "ignore"] }); } catch { return finish(""); }
|
|
83
|
+
const timer = setTimeout(() => { child.kill("SIGKILL"); finish(""); }, ms);
|
|
84
|
+
child.stdout.on("data", (d) => { buf += d; });
|
|
85
|
+
child.on("error", () => { clearTimeout(timer); finish(""); });
|
|
86
|
+
child.on("close", (code) => { clearTimeout(timer); finish(code === 0 ? buf : ""); });
|
|
87
|
+
});
|
|
88
|
+
const oneLine = (s, max) => {
|
|
89
|
+
const line = s.split("\n").map((l) => l.trim().replace(/^["'«“]|["'»”]$/g, "")).filter(Boolean).pop() ?? "";
|
|
90
|
+
return line.length >= 2 && line.length <= max ? line.replace(/[.。]$/, "") : "";
|
|
91
|
+
};
|
|
92
|
+
const CAP_PROMPT = "행사 현장 사진이다. 세로 영상 자막으로 쓸 한국어 한 줄을 출력하라 — 18자 이내 · 마침표 없이 · 보이는 장면만 · 사람 이름·외모 묘사·추측 금지 · 화면 속 글자(행사명·회사명)는 읽히면 써도 된다. 그 한 줄만.";
|
|
93
|
+
const HEAD_PROMPT = "같은 행사에서 찍은 사진들이다. 영상 첫 화면 제목으로 쓸 한국어 행사 이름 한 줄을 출력하라 — 16자 이내 · 화면 속 글자에서 읽히는 행사·회사 이름을 우선 · 읽히지 않으면 장면을 짧게(예: «상장 기념식 현장») · 추측 금지. 그 한 줄만.";
|
|
94
|
+
const slugTitle = (s) => !s || /^[a-z0-9]+(?:-[a-z0-9]+)*$/i.test(s);
|
|
95
|
+
let TITLE = opt("title", ""), SUB = opt("sub", "");
|
|
96
|
+
const photos = items.filter((it) => !it.video);
|
|
97
|
+
const VT0 = Date.now();
|
|
98
|
+
const jobs = VISION ? [
|
|
99
|
+
...photos.filter((it) => !caps[it.f]).map(async (it) => { it.vcap = oneLine(await ask(CAP_PROMPT, [join(out, `v${items.indexOf(it)}.jpg`)]), 22); }),
|
|
100
|
+
...(PART !== "body" && slugTitle(TITLE) && photos.length ? [(async () => { TITLE = oneLine(await ask(HEAD_PROMPT, photos.slice(0, 3).map((it) => join(out, `v${items.indexOf(it)}.jpg`))), 20) || TITLE; })()] : []),
|
|
101
|
+
] : [];
|
|
102
|
+
await Promise.all(jobs);
|
|
103
|
+
const visionMs = Date.now() - VT0;
|
|
104
|
+
items.forEach((it, i) => { it.cap = caps[it.f] || it.vcap || (it.video ? "" : `현장 ${i + 1}`); });
|
|
105
|
+
if (slugTitle(TITLE)) TITLE = "현장 스케치";
|
|
106
|
+
if (!SUB) { const d = new Date(items[0].t + 9 * 3600e3); SUB = `${d.getUTCFullYear()}.${String(d.getUTCMonth() + 1).padStart(2, "0")}.${String(d.getUTCDate()).padStart(2, "0")}`; }
|
|
107
|
+
lap(`vision ${jobs.length ? `${items.filter((i) => i.vcap).length}/${photos.filter((p) => !caps[p.f]).length} captions` : "off"} · title «${TITLE}»`);
|
|
108
|
+
|
|
109
|
+
// ── assets (same cache as build.mjs) ───────────────────────────────────────────
|
|
110
|
+
const CACHE = process.env.EXPLAINER_CACHE ?? join(homedir(), ".cache", "elanous-explainer");
|
|
111
|
+
const PD = "https://cdn.jsdelivr.net/npm/pretendard@1.3.9/dist/web/static/woff2/";
|
|
112
|
+
const ASSETS = { "fonts/Pretendard-Bold.woff2": PD + "Pretendard-Bold.woff2", "fonts/Pretendard-ExtraBold.woff2": PD + "Pretendard-ExtraBold.woff2", "fonts/Pretendard-Black.woff2": PD + "Pretendard-Black.woff2", "gsap.min.js": "https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js" };
|
|
113
|
+
for (const [rel, url] of Object.entries(ASSETS)) {
|
|
114
|
+
const c = join(CACHE, rel);
|
|
115
|
+
if (!existsSync(c)) { const res = await fetch(url); if (!res.ok) throw new Error(`asset ${rel}: HTTP ${res.status}`); mkdirSync(dirname(c), { recursive: true }); writeFileSync(c, Buffer.from(await res.arrayBuffer())); }
|
|
116
|
+
copyFileSync(c, join(hf, "assets", rel));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ── music: cut to length · fade in/out · level to about -16 LUFS (the whole mix is music) ──
|
|
120
|
+
const BGM = process.env.FIELD_REEL_BGM || join(CACHE, "bgm", "field.wav");
|
|
121
|
+
let music = "";
|
|
122
|
+
if (PART !== "body" && existsSync(BGM)) {
|
|
123
|
+
const r = run("ffmpeg", ["-v", "error", "-y", "-i", BGM, "-t", String(TOTAL), "-af", `afade=t=in:d=0.4,afade=t=out:st=${f(TOTAL - 1.6)}:d=1.6,loudnorm=I=-16:TP=-1.5:LRA=9`, "-ar", "48000", "-ac", "2", join(media, "bgm.wav")]);
|
|
124
|
+
if (r.status === 0) music = "bgm.wav"; else console.error(`reel: music skipped — ${r.stderr.slice(0, 160)}`);
|
|
125
|
+
}
|
|
126
|
+
function f(x) { return +x.toFixed(3); }
|
|
127
|
+
|
|
128
|
+
const markPaths = [...readFileSync(join(here, "brand", "elanous-mark-on-dark.svg"), "utf8").matchAll(/<path d="([^"]*)"/g)].map((m) => m[1]);
|
|
129
|
+
const mark = (s, cls = "") => `<svg class="${cls}" width="${s}" height="${s}" viewBox="150 150 724 724">${markPaths.map((d) => `<path d="${d}" fill="#F2F1EE"/>`).join("")}<circle cx="512" cy="512" r="76" fill="#E95047"/></svg>`;
|
|
130
|
+
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<");
|
|
131
|
+
const words = (s, cls) => s.split(/\s+/).filter(Boolean).map((w) => `<span class="${cls}">${esc(w)}</span>`).join(" ");
|
|
132
|
+
|
|
133
|
+
// ── composition ────────────────────────────────────────────────────────────────
|
|
134
|
+
// Each photo: blurred fill + the whole photo (wide) or a full-bleed crop (tall) · slow push · a cross-move into the next ·
|
|
135
|
+
// a red wipe on the cut · counter «0N / 0M» · caption words rising one by one.
|
|
136
|
+
const tw = [];
|
|
137
|
+
const n = items.length;
|
|
138
|
+
const clips = items.map((it, i) => {
|
|
139
|
+
const s = it.start, d = it.dur, last = i === n - 1;
|
|
140
|
+
const span = last ? d : d + XF; // overlap the next item so the move reads as one motion
|
|
141
|
+
let vis;
|
|
142
|
+
if (it.video) {
|
|
143
|
+
vis = `<video id="v${i}" class="clip med" src="assets/media/${it.src}" muted playsinline data-start="${f(s)}" data-duration="${f(d)}" data-track-index="1"></video>`;
|
|
144
|
+
} else if (it.wide) {
|
|
145
|
+
vis = `<div class="clip med" data-start="${f(s)}" data-duration="${f(span)}" data-track-index="${1 + (i % 2)}"><div class="g g${i}">`
|
|
146
|
+
+ `<img class="fill" src="assets/media/${it.src}"/><div class="dim"></div>`
|
|
147
|
+
+ `<div class="frame fr${i}"><img src="assets/media/${it.src}"/></div></div></div>`;
|
|
148
|
+
tw.push(`tl.fromTo(".fr${i}", {scale:1.0, x:${i % 2 ? 30 : -30}}, {scale:1.12, x:${i % 2 ? -30 : 30}, duration:${f(span)}, ease:"none"}, ${f(s)});`);
|
|
149
|
+
tw.push(`tl.fromTo(".g${i} .fill", {scale:1.25}, {scale:1.4, duration:${f(span)}, ease:"none"}, ${f(s)});`);
|
|
150
|
+
} else {
|
|
151
|
+
vis = `<div class="clip med" data-start="${f(s)}" data-duration="${f(span)}" data-track-index="${1 + (i % 2)}"><div class="g g${i}"><img class="kb k${i}" src="assets/media/${it.src}"/></div></div>`;
|
|
152
|
+
tw.push(`tl.fromTo(".k${i}", {scale:1.02, x:0}, {scale:1.12, x:${i % 2 ? -28 : 28}, duration:${f(span)}, ease:"none"}, ${f(s)});`);
|
|
153
|
+
}
|
|
154
|
+
if (!it.video && i > 0) tw.push(`tl.fromTo(".g${i}", {opacity:0, xPercent:${i % 2 ? 14 : -14}}, {opacity:1, xPercent:0, duration:${XF}, ease:"power3.out"}, ${f(s - XF)});`);
|
|
155
|
+
if (i > 0) tw.push(`tl.fromTo(".wipe", {scaleY:0, transformOrigin:"50% 100%"}, {scaleY:1, duration:${XF / 2}, ease:"power2.in", immediateRender:false}, ${f(s - XF / 2)});`
|
|
156
|
+
+ `tl.to(".wipe", {scaleY:0, transformOrigin:"50% 0%", duration:${XF / 2}, ease:"power2.out"}, ${f(s)});`);
|
|
157
|
+
const no = `${String(i + 1).padStart(2, "0")} <i>/ ${String(n).padStart(2, "0")}</i>`;
|
|
158
|
+
const cap = it.cap ? `<div class="clip capw" data-start="${f(s)}" data-duration="${f(d)}" data-track-index="4"><div class="no n${i}">${no}</div><div class="cap c${i}">${words(it.cap, `w w${i}`)}</div><div class="rule r${i}"></div></div>` : "";
|
|
159
|
+
if (it.cap) {
|
|
160
|
+
tw.push(`tl.fromTo(".n${i}", {opacity:0, x:-24}, {opacity:1, x:0, duration:0.35, ease:"power3.out"}, ${f(s + 0.2)});`);
|
|
161
|
+
tw.push(`tl.fromTo(".r${i}", {scaleX:0}, {scaleX:1, duration:0.5, ease:"power3.out"}, ${f(s + 0.25)});`);
|
|
162
|
+
tw.push(`tl.fromTo(".w${i}", {opacity:0, y:46}, {opacity:1, y:0, duration:0.45, stagger:0.09, ease:"power3.out"}, ${f(s + 0.35)});`);
|
|
163
|
+
if (!last) tw.push(`tl.to(".c${i}, .n${i}, .r${i}", {opacity:0, duration:0.25}, ${f(s + d - 0.3)});`);
|
|
164
|
+
}
|
|
165
|
+
return vis + cap;
|
|
166
|
+
}).join("\n");
|
|
167
|
+
|
|
168
|
+
const intro = PART === "body" ? "" : `<section class="clip card" data-start="0" data-duration="${INTRO}" data-track-index="6">`
|
|
169
|
+
+ `<div class="kick ik">현장 스케치</div>${mark(200, "im")}<h1>${words(TITLE, "it")}</h1><div class="line il"></div><p class="is">${esc(SUB)}</p></section>`;
|
|
170
|
+
const end = PART === "body" ? "" : `<section class="clip card" data-start="${f(t)}" data-duration="${END}" data-track-index="6">`
|
|
171
|
+
+ `${mark(230, "em")}<h1 class="et">Elanous</h1><p class="et">사진을 올리면, 영상이 됩니다</p><p class="et red">elanous.ai</p></section>`;
|
|
172
|
+
if (PART !== "body") {
|
|
173
|
+
tw.push(`tl.fromTo(".ik", {opacity:0, letterSpacing:"0.6em"}, {opacity:1, letterSpacing:"0.28em", duration:0.8, ease:"power3.out"}, 0.1);`);
|
|
174
|
+
tw.push(`tl.fromTo(".im", {rotation:-160, scale:0.6, opacity:0}, {rotation:0, scale:1, opacity:1, duration:1.0, ease:"power3.out"}, 0.0);`);
|
|
175
|
+
tw.push(`tl.fromTo(".it", {opacity:0, y:50}, {opacity:1, y:0, duration:0.55, stagger:0.1, ease:"power3.out"}, 0.45);`);
|
|
176
|
+
tw.push(`tl.fromTo(".il", {scaleX:0}, {scaleX:1, duration:0.6, ease:"power3.inOut"}, 0.9);`);
|
|
177
|
+
tw.push(`tl.fromTo(".is", {opacity:0, y:16}, {opacity:1, y:0, duration:0.45, ease:"power3.out"}, 1.15);`);
|
|
178
|
+
tw.push(`tl.fromTo(".em", {rotation:-200, scale:0.5}, {rotation:0, scale:1, duration:1.2, ease:"power3.out"}, ${f(t)});`);
|
|
179
|
+
tw.push(`tl.fromTo(".et", {opacity:0, y:20}, {opacity:1, y:0, duration:0.5, stagger:0.14, ease:"power3.out"}, ${f(t + 0.5)});`);
|
|
180
|
+
}
|
|
181
|
+
tw.unshift(`tl.set(".wipe", {scaleY:0}, 0);`);
|
|
182
|
+
tw.push(`tl.fromTo(".bar i", {scaleX:0}, {scaleX:1, duration:${TOTAL}, ease:"none"}, 0);`);
|
|
183
|
+
const audio = music ? `<audio id="bgm" src="assets/media/${music}" data-start="0" data-duration="${TOTAL}" data-track-index="9"></audio>` : "";
|
|
184
|
+
const html = `<!doctype html><html lang="ko"><head><meta charset="UTF-8"/><meta name="viewport" content="width=${W}, height=${H}"/><title>${esc(TITLE)}</title><script src="assets/gsap.min.js"></script><style>
|
|
185
|
+
@font-face{font-family:"Pretendard";src:url("assets/fonts/Pretendard-Bold.woff2") format("woff2");font-weight:700}
|
|
186
|
+
@font-face{font-family:"Pretendard";src:url("assets/fonts/Pretendard-ExtraBold.woff2") format("woff2");font-weight:800}
|
|
187
|
+
@font-face{font-family:"Pretendard";src:url("assets/fonts/Pretendard-Black.woff2") format("woff2");font-weight:900}
|
|
188
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
189
|
+
#root{position:relative;width:100%;height:100%;overflow:hidden;background:#000;font-family:"Pretendard",sans-serif;color:#F2F1EE;word-break:keep-all}
|
|
190
|
+
.med{position:absolute;inset:0;width:100%;height:100%;overflow:hidden}
|
|
191
|
+
.g{position:absolute;inset:0;overflow:hidden}
|
|
192
|
+
.kb{width:100%;height:100%;object-fit:cover;display:block}
|
|
193
|
+
.fill{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:blur(42px) saturate(1.2);opacity:.85}
|
|
194
|
+
.dim{position:absolute;inset:0;background:rgba(0,0,0,.42)}
|
|
195
|
+
.frame{position:absolute;left:0;right:0;top:420px;height:960px;overflow:hidden;box-shadow:0 30px 80px rgba(0,0,0,.55)}
|
|
196
|
+
.frame img{width:100%;height:100%;object-fit:cover;display:block}
|
|
197
|
+
.shade{z-index:3;position:absolute;left:0;right:0;bottom:0;height:42%;background:linear-gradient(to top,rgba(0,0,0,.82),rgba(0,0,0,0));pointer-events:none}
|
|
198
|
+
.top{z-index:5;position:absolute;left:56px;right:56px;top:72px;display:flex;align-items:center;gap:18px;font-weight:800;font-size:34px;text-shadow:0 2px 12px rgba(0,0,0,.6)}
|
|
199
|
+
.top b{color:#E95047;font-weight:800}
|
|
200
|
+
.capw{z-index:4;position:absolute;left:64px;right:64px;bottom:210px}
|
|
201
|
+
.no{font-weight:800;font-size:34px;letter-spacing:.12em;color:#E95047}
|
|
202
|
+
.no i{font-style:normal;color:rgba(242,241,238,.55)}
|
|
203
|
+
.cap{margin-top:18px;font-weight:900;font-size:76px;line-height:1.18;letter-spacing:-0.03em;text-shadow:0 3px 18px rgba(0,0,0,.7)}
|
|
204
|
+
.w{display:inline-block}
|
|
205
|
+
.rule{margin-top:26px;width:120px;height:8px;background:#E95047;transform-origin:0 50%}
|
|
206
|
+
.wipe{z-index:8;position:absolute;inset:0;background:#E95047}
|
|
207
|
+
.card{z-index:7;position:absolute;inset:0;background:#000;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:0 80px}
|
|
208
|
+
.kick{margin-bottom:56px;font-weight:800;font-size:32px;letter-spacing:.28em;color:#E95047}
|
|
209
|
+
.card h1{margin-top:56px;font-weight:900;font-size:100px;line-height:1.12;letter-spacing:-0.03em}
|
|
210
|
+
.card h1 span{display:inline-block}
|
|
211
|
+
.line{margin-top:40px;width:160px;height:8px;background:#E95047}
|
|
212
|
+
.card p{margin-top:28px;font-weight:700;font-size:42px;color:rgba(242,241,238,.66)}
|
|
213
|
+
.card .red{color:#E95047}
|
|
214
|
+
.bar{z-index:9;position:absolute;left:0;right:0;bottom:0;height:10px;background:rgba(242,241,238,.12)}
|
|
215
|
+
.bar i{position:absolute;inset:0;background:#E95047;transform-origin:0 50%;display:block}
|
|
216
|
+
</style></head><body>
|
|
217
|
+
<div id="root" data-composition-id="main" data-start="0" data-width="${W}" data-height="${H}" data-duration="${TOTAL}">
|
|
218
|
+
${intro}
|
|
219
|
+
${clips}
|
|
220
|
+
<div class="shade"></div>
|
|
221
|
+
<div class="top">${mark(60)}<span>Elanous <b>·</b> ${esc(TITLE)}</span></div>
|
|
222
|
+
<div class="wipe"></div>
|
|
223
|
+
${end}
|
|
224
|
+
<div class="bar"><i></i></div>
|
|
225
|
+
${audio}
|
|
226
|
+
</div>
|
|
227
|
+
<script>const tl = gsap.timeline({ paused: true });
|
|
228
|
+
${tw.join("\n")}
|
|
229
|
+
window.__timelines["main"] = tl;</script></body></html>`;
|
|
230
|
+
writeFileSync(join(hf, "index.html"), html);
|
|
231
|
+
writeFileSync(join(hf, "hyperframes.json"), JSON.stringify({ $schema: "https://hyperframes.heygen.com/schema/hyperframes.json", paths: { assets: "assets" }, media: { autoProxy: true } }, null, 2) + "\n");
|
|
232
|
+
writeFileSync(join(hf, "meta.json"), JSON.stringify({ id: "reel", name: "reel" }, null, 2) + "\n");
|
|
233
|
+
writeFileSync(join(out, "timeline.json"), JSON.stringify({ total: TOTAL, part: PART, title: TITLE, sub: SUB, music: Boolean(music),
|
|
234
|
+
vision: { enabled: VISION, calls: jobs.length, captioned: items.filter((i) => i.vcap).length, fallback: items.filter((i) => !i.video && !caps[i.f] && !i.vcap).length, ms: visionMs }, items: items.map(({ f: file, video, start, dur, cap, vcap }) => ({ file, video, start, dur: f(dur), cap, vision: Boolean(vcap) })) }, null, 2));
|
|
235
|
+
console.log(`reel: ${items.length} items · ${TOTAL}s · ${items.filter((i) => i.vcap).length} vision captions · music ${music ? "on" : "off"} → ${hf}`);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/bin/zsh
|
|
2
|
+
# Field reel in one command: folder of phone photos/clips → <folder>/reel/<name>-9x16.mp4 · prints the elapsed seconds.
|
|
3
|
+
# The layout/contrast check is advisory: phone photos behind captions often miss 3:1, and a failed check must not stop the reel.
|
|
4
|
+
# Usage: zsh reel.sh <folder> [--title "…"] [--sub "…"] (captions: <folder>/captions.txt — `파일 | 자막`)
|
|
5
|
+
E=${0:A:h}; F=${1:A}; shift
|
|
6
|
+
[[ -d $F ]] || { print -u2 "reel: no folder $F"; exit 2 }
|
|
7
|
+
T0=$(date +%s)
|
|
8
|
+
rm -rf $F/reel && node $E/reel.mjs $F "$@" && (cd $F/reel/hf && { npx -y hyperframes@${HYPERFRAMES_VERSION:-0.8.95} check >../render.log 2>&1 || print "reel: check reported issues (continuing — user photos vary; see above)" >>../render.log }; npx -y hyperframes@${HYPERFRAMES_VERSION:-0.8.95} render --fps 30 --workers 4 --output ../reel-9x16.mp4 >>../render.log 2>&1) || { print -u2 "reel: FAILED — see $F/reel/render.log"; exit 1 }
|
|
9
|
+
print "reel: $F/reel/reel-9x16.mp4 · $(( $(date +%s) - T0 ))s"
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
// Explainer VO — one
|
|
2
|
-
// Usage: ELEVENLABS_API_KEY=… bun vo.ts <project>/script.json
|
|
3
|
-
//
|
|
4
|
-
|
|
1
|
+
// Explainer VO — one voice file per beat plus per-character times; the times drive caption & highlight timing.
|
|
2
|
+
// Usage: ELEVENLABS_API_KEY=… bun vo.ts <project>/script.json (ElevenLabs /with-timestamps — exact word times)
|
|
3
|
+
// bun vo.ts <project>/script.json (no key → macOS `say`, times spread evenly — a draft voice)
|
|
4
|
+
// Writes source/vo/<key>.mp3 ⊕ <key>.json (alignment ⊕ text hash ⊕ engine). Skips a beat whose hash is unchanged. Never prints the key.
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
5
6
|
import { createHash } from 'node:crypto';
|
|
7
|
+
import { spawnSync } from 'node:child_process';
|
|
6
8
|
import { join, dirname, resolve } from 'node:path';
|
|
7
9
|
|
|
8
|
-
const KEY = process.env.ELEVENLABS_API_KEY;
|
|
9
|
-
if (!KEY) throw new Error('ELEVENLABS_API_KEY missing — set it from the plugin connector (elanous plugin credentials video-explainer)');
|
|
10
|
+
const KEY = process.env.ELEVENLABS_API_KEY?.trim();
|
|
10
11
|
const scriptPath = resolve(process.argv[2] ?? 'script.json');
|
|
11
12
|
const script = JSON.parse(readFileSync(scriptPath, 'utf8'));
|
|
12
13
|
const dir = join(dirname(scriptPath), 'source', 'vo');
|
|
@@ -20,18 +21,59 @@ export function beatKeys(s: any): { key: string; vo: string }[] {
|
|
|
20
21
|
return out;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (existsSync(jf) && JSON.parse(readFileSync(jf, 'utf8')).hash === hash) { console.log(`${key} cached`); continue; }
|
|
24
|
+
type Alignment = { characters: string[]; character_start_times_seconds: number[]; character_end_times_seconds: number[] };
|
|
25
|
+
|
|
26
|
+
async function elevenlabs(vo: string): Promise<{ mp3: Buffer; alignment: Alignment }> {
|
|
27
27
|
const res = await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${script.voice.id}/with-timestamps?output_format=mp3_44100_192`, {
|
|
28
28
|
method: 'POST',
|
|
29
|
-
headers: { 'xi-api-key': KEY
|
|
29
|
+
headers: { 'xi-api-key': KEY!, 'content-type': 'application/json' },
|
|
30
30
|
body: JSON.stringify({ text: vo, model_id: script.voice.model, language_code: 'ko' }),
|
|
31
31
|
});
|
|
32
|
-
if (!res.ok) throw new Error(
|
|
33
|
-
const data = await res.json() as { audio_base64: string; alignment:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
if (!res.ok) throw new Error(`ElevenLabs HTTP ${res.status} ${(await res.text()).slice(0, 200)}`);
|
|
33
|
+
const data = await res.json() as { audio_base64: string; alignment: Alignment };
|
|
34
|
+
return { mp3: Buffer.from(data.audio_base64, 'base64'), alignment: data.alignment };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Keyless draft voice: macOS `say` → mp3 · character times spread in proportion over the measured length. */
|
|
38
|
+
function sayVoice(): string {
|
|
39
|
+
const want = process.env.EXPLAINER_SAY_VOICE;
|
|
40
|
+
if (want) return want;
|
|
41
|
+
const list = spawnSync('say', ['-v', '?'], { encoding: 'utf8' });
|
|
42
|
+
if (list.status !== 0) throw new Error('no ELEVENLABS_API_KEY and `say` is unavailable (macOS only) — set the key via the plugin connector');
|
|
43
|
+
const ko = list.stdout.split('\n').filter((l) => /\bko_KR\b/.test(l)).map((l) => l.split(/\s{2,}|\s+\(/)[0].trim());
|
|
44
|
+
const pick = ko.find((v) => /^Yuna/.test(v)) ?? ko[0];
|
|
45
|
+
if (!pick) throw new Error('no Korean `say` voice installed — System Settings › Accessibility › Spoken Content, or set ELEVENLABS_API_KEY');
|
|
46
|
+
return pick;
|
|
47
|
+
}
|
|
48
|
+
function say(vo: string, key: string): { mp3: Buffer; alignment: Alignment } {
|
|
49
|
+
const voice = sayVoice();
|
|
50
|
+
const aiff = join(dir, `${key}.tmp.aiff`), mp3 = join(dir, `${key}.tmp.mp3`);
|
|
51
|
+
const r = spawnSync('say', ['-v', voice, '-o', aiff, vo], { encoding: 'utf8' });
|
|
52
|
+
if (r.status !== 0) throw new Error(`say failed: ${r.stderr.slice(0, 200)}`);
|
|
53
|
+
const f = spawnSync('ffmpeg', ['-v', 'error', '-y', '-i', aiff, '-ar', '44100', '-b:a', '192k', mp3], { encoding: 'utf8' });
|
|
54
|
+
if (f.status !== 0) throw new Error(`ffmpeg failed: ${f.stderr.slice(0, 200)}`);
|
|
55
|
+
const p = spawnSync('ffprobe', ['-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', mp3], { encoding: 'utf8' });
|
|
56
|
+
const dur = Number(p.stdout.trim());
|
|
57
|
+
if (!(dur > 0)) throw new Error('ffprobe could not measure the say output');
|
|
58
|
+
const chars = [...vo];
|
|
59
|
+
const weight = chars.map((c) => (/\s/.test(c) ? 0.3 : /[,.·!?]/.test(c) ? 0.8 : 1));
|
|
60
|
+
const total = weight.reduce((a, b) => a + b, 0);
|
|
61
|
+
const starts: number[] = [], ends: number[] = [];
|
|
62
|
+
let t = 0;
|
|
63
|
+
for (const w of weight) { starts.push(+t.toFixed(3)); t += (w / total) * dur; ends.push(+t.toFixed(3)); }
|
|
64
|
+
const out = readFileSync(mp3);
|
|
65
|
+
rmSync(aiff, { force: true }); rmSync(mp3, { force: true });
|
|
66
|
+
return { mp3: out, alignment: { characters: chars, character_start_times_seconds: starts, character_end_times_seconds: ends } };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const engine = KEY ? 'elevenlabs' : 'say';
|
|
70
|
+
if (!KEY) console.log('no ELEVENLABS_API_KEY — draft voice with macOS `say` (caption times are estimates)');
|
|
71
|
+
for (const { key, vo } of beatKeys(script)) {
|
|
72
|
+
const hash = createHash('sha256').update(`${engine === 'say' ? 'say|' : ''}${script.voice.id}|${script.voice.model}|${vo}`).digest('hex').slice(0, 16);
|
|
73
|
+
const jf = join(dir, `${key}.json`);
|
|
74
|
+
if (existsSync(jf) && JSON.parse(readFileSync(jf, 'utf8')).hash === hash) { console.log(`${key} cached`); continue; }
|
|
75
|
+
const { mp3, alignment } = KEY ? await elevenlabs(vo) : say(vo, key);
|
|
76
|
+
writeFileSync(join(dir, `${key}.mp3`), mp3);
|
|
77
|
+
writeFileSync(jf, JSON.stringify({ hash, engine, vo, alignment }));
|
|
78
|
+
console.log(`${key} ${(alignment.character_end_times_seconds.at(-1) ?? 0).toFixed(2)}s ${engine} ${vo}`);
|
|
37
79
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "Seulki",
|
|
6
6
|
"model": "eleven_v3"
|
|
7
7
|
},
|
|
8
|
-
"sources": "
|
|
8
|
+
"sources": "elanous 0.2.5 release notes — https://github.com/ElanvitalAI/elanous/releases/tag/v0.2.5",
|
|
9
9
|
"intro": {
|
|
10
10
|
"beats": [
|
|
11
11
|
{
|
package/skills/grill-me/SKILL.md
CHANGED
|
@@ -123,7 +123,7 @@ requires: []
|
|
|
123
123
|
| 다음 | 언제 | 어떻게 |
|
|
124
124
|
|---|---|---|
|
|
125
125
|
| 🧹 **`first-principles`** | 요구가 많이 나왔을 때 | ⭐ ***캐낸 다음엔 «지운다»*** — 5단계 ①의심 ②삭제 가 순서상 여기다 |
|
|
126
|
-
| 🎯 **골 문면** (
|
|
126
|
+
| 🎯 **골 문면** (골 파일) | 하니스가 구현할 일일 때 | 카드의 `S`·`C`·`Q` 가 그대로 ask 의 세 칸이 된다 |
|
|
127
127
|
| 📄 **문서** (`docs/`) | 결정을 남길 일일 때 | `## ✅ 정해진 것` 표가 그대로 결정 기록이다 |
|
|
128
128
|
| 🧑🤝🧑 **팀 짜기** | 일이 여럿으로 갈릴 때 | ⭐ 목표를 심은 뒤 *"이 일을 할 팀을 짜 보라"* — 인터뷰의 «응용»이다 |
|
|
129
129
|
|
|
@@ -14,7 +14,7 @@ flowchart TD
|
|
|
14
14
|
H{nonCodeOutcome exists?}:::gate
|
|
15
15
|
I[observe deploy-no-changes<br/>return { ok:false, kind:none }]:::fail
|
|
16
16
|
J{Evidence is artifact-created?}:::gate
|
|
17
|
-
K{
|
|
17
|
+
K{2026-08-13<br/>existsSync(resolve(cwd, ref))?}:::gate
|
|
18
18
|
L[observe deploy-noncode-blocked<br/>reason: artifact-created-ref-missing<br/>then deploy-no-changes]:::fail
|
|
19
19
|
M[Do not treat ref as a file<br/>published-url / execution-completed]:::data
|
|
20
20
|
N[observe deploy-noncode<br/>return terminal:<br/>published or executed]:::pass
|
package/src/a2a/server.ts
CHANGED
|
@@ -91,6 +91,8 @@ export function startA2AServer(opts: A2AServerOptions): Bun.Server<undefined> {
|
|
|
91
91
|
history ??= new DaemonSessionHistory();
|
|
92
92
|
const result = await (opts.runDaemonTurn ?? runDaemonPromptTurn)({
|
|
93
93
|
history,
|
|
94
|
+
// A peer agent delegates work, not small talk: never drop its tools for a short message (#22430 fast path).
|
|
95
|
+
fastPathEnabled: false,
|
|
94
96
|
request: {
|
|
95
97
|
sessionId: contextId,
|
|
96
98
|
userText: text,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ClientCapabilities } from '@agentclientprotocol/sdk';
|
|
2
|
+
|
|
3
|
+
/** The server's sessionPeers registry remains the source of truth for which
|
|
4
|
+
* connections are attached to a session. Awareness belongs to the connection,
|
|
5
|
+
* not the session: a plain client can load an aware client's session. */
|
|
6
|
+
export class ElanousAwarePeers<Peer extends object> {
|
|
7
|
+
private readonly aware = new WeakSet<Peer>();
|
|
8
|
+
|
|
9
|
+
constructor(private readonly sessionPeers: ReadonlyMap<string, ReadonlySet<Peer>>) {}
|
|
10
|
+
|
|
11
|
+
markPeer(connectionOrSessionId: Peer, clientCapabilities: ClientCapabilities | undefined | null): void {
|
|
12
|
+
const elanous = (clientCapabilities?._meta as Record<string, unknown> | undefined)?.elanous;
|
|
13
|
+
if (elanous !== null && typeof elanous === 'object' && !Array.isArray(elanous)) {
|
|
14
|
+
this.aware.add(connectionOrSessionId);
|
|
15
|
+
} else {
|
|
16
|
+
this.aware.delete(connectionOrSessionId);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
isPeerAware(peer: Peer): boolean {
|
|
21
|
+
return this.aware.has(peer);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
isElanousAware(sessionId: string): boolean {
|
|
25
|
+
for (const peer of this.sessionPeers.get(sessionId) ?? []) {
|
|
26
|
+
if (this.isPeerAware(peer)) return true;
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|