elanous 0.2.6 → 0.2.8
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 +4 -0
- 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/{3995-bee512a7063036ce.js → 2375-cb6debea56cce4fb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2415.ed6428ff334c7ce2.js +1 -0
- 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/{8d0d9faf-97887ff99713b84e.js → 2ea96958-e8c7e112de50b067.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5329.8b7e4bca684b6eec.js → 3403.4bc97b4066945a94.js} +2 -2
- 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/{7633.0654fe6ea259c1ee.js → 4323.c5dfb6f503304775.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4836-3084c58c1725a40b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2984-977cfa339fcd65a5.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/{763-7d0e1913b5074e98.js → 5791-bb82743fa6299562.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4240-7153881b0b377306.js → 6062-73e68343a9814f6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6090-85a3f05f954e5697.js +1 -0
- 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/7032-f4ef698518fba61c.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/{91ff6dda-3b33d42d20657429.js → 8046cadf-211ca3c0e00f2b72.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8067-d976b441a104ab74.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8519-5632377cce994f86.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8894-7317998f6cb97d8c.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-8f5ff96c522b5f55.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-9aa47b0bc6d570ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f4d2ecbbae6088d6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-2053e49930c82748.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-d4b6df905f185055.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-a70ba27c33003dd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-186fc6952f027acc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-18166f885d831d3e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-1c9d6cfe68b121c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-cbbe03c0da7b081a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-c108ff1fdb665c97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-147a328753d983e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-799395a9df7d95aa.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-6a8158b71d1fe9d7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-9567560270857531.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-e7ed3d010153d818.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-c0c0d19d51342d3e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2e002ad8faa43291.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-b672e02e4bec8deb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-1ba4a5d857276334.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-9db2226f38c542fb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-70ee65f5f7a151dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-0bb8e43203efb23b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-092e1bcf27d751cc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-eb52580c4b75b905.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7464c1987dd76e6d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-e573437b0a1c728f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-294300625e49e4d3.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-085847b088675978.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-9fe9d38c36999eb4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-d8ab4d1489223459.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-6141f67f531d8b6a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-295a02b1026b8255.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-1eb9a0e1e054209d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-82efa177a30f3741.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d0be51cec4f62606.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-2e367075ffdbc062.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-647ed2b66c1d49f1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ba058c56e38f2792.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-37b8bf78a3c6eec5.js → webpack-e5bea36f183b25e6.js} +1 -1
- package/apps/pwa/out/_next/static/css/5ef72a618a8994f3.css +1 -0
- package/apps/pwa/out/_next/static/lywc8m_HDzH9MKSDQhyEj/_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/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 +10 -0
- package/graphs/release/release-loop.yaml +10 -3
- package/graphs/test-diet/recipes.yaml +9 -0
- package/graphs/test-diet/test-diet.yaml +22 -0
- package/package.json +6 -5
- package/persona-presets/_index.yaml +10 -0
- package/persona-presets/_schema.json +146 -0
- package/persona-presets/dana.yaml +26 -0
- package/persona-presets/haru.yaml +27 -0
- package/persona-presets/kai.yaml +27 -0
- package/persona-presets/leo.yaml +27 -0
- package/persona-presets/mira.yaml +30 -0
- package/persona-presets/nari.yaml +27 -0
- package/persona-presets/sora.yaml +27 -0
- package/persona-presets/yuna.yaml +27 -0
- package/plugins/card-followup/README.md +13 -4
- package/plugins/card-followup/graphs/card-followup.yaml +3 -1
- package/plugins/card-followup/graphs/recipes.yaml +5 -1
- package/plugins/card-followup/graphs/run-step.ts +122 -18
- package/plugins/card-followup/graphs/sales-strategy.ts +173 -0
- package/plugins/card-followup/plugin.json +1 -1
- 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 +3 -1
- package/plugins/geo-check/graphs/run-step.ts +58 -13
- package/plugins/geo-check/plugin.json +1 -1
- package/plugins/job-coach/.codex-plugin/plugin.json +1 -1
- package/plugins/job-coach/README.md +1 -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/field-feed/deliver-node.ts +57 -0
- package/scripts/field-feed/feed-node.ts +67 -0
- package/scripts/field-feed/lib.ts +164 -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 +109 -21
- package/scripts/landing-heal/clean-checkout.ts +114 -0
- package/scripts/landing-heal/run-mission.ts +38 -3
- package/scripts/lib/pwa-scenarios/scenarios.ts +2 -1
- package/scripts/persona-presets/lint.ts +79 -0
- 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 +2 -2
- package/scripts/release-loop/env-known-failures.ts +31 -0
- package/scripts/release-loop/gate-node.ts +108 -22
- package/scripts/release-loop/known-issues-node.ts +159 -0
- package/scripts/release-loop/npm-publish-node.ts +124 -0
- package/scripts/release-loop/ops-upgrade-node.ts +95 -0
- package/scripts/release-loop/publish-node.ts +23 -1
- package/scripts/release-loop/release-readiness.ts +58 -0
- package/scripts/release-loop/shard-plan.ts +17 -0
- package/scripts/release-loop/unattended-release.ts +93 -0
- package/scripts/storyboard/storyboard.ts +167 -0
- package/scripts/test-diet/lib.ts +88 -0
- package/scripts/test-diet/node.ts +102 -0
- package/scripts/ux/measure-first-text.ts +102 -0
- 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 +12 -9
- package/skills/explainer-video/engine/build.mjs +1 -1
- package/skills/explainer-video/engine/reel.mjs +138 -31
- package/skills/explainer-video/engine/reel.sh +2 -1
- 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/auth-methods.ts +30 -0
- package/src/acp/elanous-aware-peers.ts +30 -0
- package/src/acp/server.ts +96 -20
- 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/track-agent-shadow.ts +151 -0
- package/src/autopilot/track-agent.ts +23 -3
- 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/channel-import/detect.ts +191 -0
- package/src/channel-import/run.ts +111 -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/config-test-sync.ts +4 -0
- package/src/cli/decisions-cli.ts +13 -3
- package/src/cli/dependence-gauge.ts +237 -0
- package/src/cli/doctor-bundle.ts +128 -0
- package/src/cli/doctor-cli.ts +41 -1
- package/src/cli/doctor-local-llm.ts +95 -0
- package/src/cli/doctor-modes.ts +48 -0
- package/src/cli/import-cli.ts +60 -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/mcp-login.ts +13 -4
- package/src/cli/msg-cli.ts +137 -0
- package/src/cli/persona-cli.ts +116 -0
- package/src/cli/plugin-cli.ts +25 -0
- package/src/cli/pr-cli.ts +36 -0
- package/src/cli/provider-cli.ts +5 -0
- package/src/cli/release-cli.ts +50 -8
- 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/skills-cli.ts +173 -0
- package/src/cli/start-cli.ts +13 -4
- package/src/cli/usage-cli.ts +11 -1
- package/src/codex/setup.ts +37 -16
- package/src/dashboard/index.ts +18 -2
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +2 -2
- package/src/dashboard/slash-runtime/help-from-registry.ts +4 -2
- package/src/decisions/decision-cards.ts +291 -0
- package/src/decisions/decision-ledger.ts +5 -2
- package/src/decisions/discord-decision-cards.ts +133 -0
- package/src/decisions/telegram-decision-cards.ts +100 -0
- package/src/directives/version-at.ts +77 -0
- package/src/discord.ts +73 -6
- package/src/domains/core-tools.ts +37 -14
- package/src/domains/outbound-alert.ts +94 -12
- package/src/domains/repeated-failure.ts +1 -1
- package/src/error-report/report.ts +200 -0
- package/src/exec-requests/planner.ts +146 -0
- package/src/exec-requests/runner.ts +378 -0
- package/src/exec-requests/store.ts +78 -0
- package/src/field/field-feed-auto.ts +48 -0
- package/src/field/field-media.ts +8 -3
- package/src/field/field-reel.ts +203 -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/hooks/error-report.ts +210 -0
- package/src/hooks/receiver.ts +41 -1
- package/src/import/apply.ts +128 -0
- package/src/import/plan.ts +197 -0
- package/src/index.ts +168 -21
- package/src/input-core/text-entry.ts +13 -5
- 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-answer.ts +96 -0
- package/src/intake-plane/seat-doc-route.ts +221 -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 +128 -0
- package/src/nexus/api/discord-trigger-bot.ts +3 -0
- package/src/nexus/api/error-reports.ts +108 -0
- package/src/nexus/api/exec-requests.ts +51 -0
- package/src/nexus/api/field-uploads.ts +40 -3
- package/src/nexus/api/graph-approvals-feed.ts +140 -0
- package/src/nexus/api/graph-approvals.ts +71 -4
- package/src/nexus/api/http-server.ts +82 -8
- package/src/nexus/api/outbound-report.ts +7 -0
- package/src/nexus/api/running-runs-background.ts +68 -0
- package/src/nexus/api/running-runs-child.ts +6 -0
- package/src/nexus/api/seat-requests.ts +254 -0
- package/src/nexus/api/share-captures.ts +91 -0
- package/src/nexus/api/skill-problems.ts +56 -0
- package/src/nexus/api/terminals.ts +24 -8
- package/src/nexus/api/trace-run-scan.ts +37 -0
- package/src/nexus/api/trace.ts +19 -3
- package/src/nexus/index.ts +28 -1
- package/src/nexus/setup-status.ts +11 -7
- package/src/notify/llm-budget-alert.ts +16 -10
- package/src/oauth/browser-availability.ts +14 -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-quota-policy.ts +16 -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 +34 -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 +90 -0
- package/src/onboarding.ts +287 -26
- package/src/persona/presets.ts +105 -0
- 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 +19 -7
- 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/relay-cli.ts +20 -0
- package/src/relay/relay-server.ts +220 -0
- package/src/release-loop/checklist.ts +37 -13
- package/src/self-dev/decompose.ts +1 -0
- package/src/self-dev/dev-pipeline.ts +6 -3
- package/src/self-dev/orchestrate.ts +18 -11
- 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/session/chat.ts +17 -5
- package/src/shell-env-bootstrap.ts +44 -7
- package/src/skills/connect-claude-plugin.ts +142 -0
- package/src/skills/connect.ts +70 -0
- package/src/skills/index.ts +29 -1
- package/src/skills/repair.ts +124 -0
- package/src/skills/runner.ts +11 -2
- package/src/skills/shared-agent-skill-roots.ts +25 -0
- package/src/skills/trigger-extract.ts +1 -1
- 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-command-job.ts +16 -8
- 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-commands.ts +13 -0
- package/src/telegram.ts +72 -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 +189 -15
- package/src/version/packed-revision.json +1 -1
- package/src/video-pipeline/recipes/character.ts +42 -5
- 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/apps/pwa/out/_next/static/chunks/1169-696263ac7af8c4d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1883.c91a2648af4842fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1947-9d64872eeb9cfdec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2808-dc06482994b40f70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3165-95515ca5f299a120.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3190-e9282753e7ebde85.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4259-99614149577e77cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4283-329eabeaf233e6cd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4328-cb5058b1acc2de5e.js +0 -25
- package/apps/pwa/out/_next/static/chunks/4801-ecee6ef62b349b18.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5110-8058791dd25a2e14.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5330-c41e9670f594c38f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5423-e95fd125d1794349.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5478-b5eae07dc79ea619.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5787-96ee6642b9a661e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6448-79d72368589f98bc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6522-9866c002b5531836.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6729-b4a558b7aa891e0c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6969-cb03f9410b7d2e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7007-3b9861091bb8dd21.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7930-8dc7e20fc6fc19ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8071-187edbc22a86741f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8198-d4101ad70cb9a579.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8250.4a2c5553a07cdf47.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8293-123b91e7b0330dc0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8296-d6d5d87dfa911d41.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8305-603963c33ee8eec3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8612-4a0066f20951b8fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9181-cf4e1b61c4783f92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9262-26c2ecbd5a67e4a2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9328-45abdebce4fbecb7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9355-dbc67205adf8745f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9763.255b90dd69875689.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9933-66d31ec25c0231af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-bd06fb55f4da0381.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-4e586142da455a25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-889ad5cddcf45b0d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-47ba401d56572c27.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-0b54f9c83458e038.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-4fcc296ef6c8ed90.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-fe9fda494a87f4e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-f9642e25ce129590.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-e1063e8ba5f3e2e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-9d0df30027d8aa9d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-bd06fb55f4da0381.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-d97adf2c9455b8d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-236b80d202110362.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-21a30f35f1a276ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-b1a5be357c4fa25d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1705a60303f7f573.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-76b337c11ad0e237.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-7c0f85fbb56f64c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-65ca16b20617b44d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-e7f9b8fc29411c1d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-92ea6213d1aeec04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-a913a005aacb5476.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-2d78804a40dfdef6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-08a99148e780ac00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-deb674e7ed36f815.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-49f8de0534d192d7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-bd06fb55f4da0381.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-ba162a28d2176e18.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-1ff1a37b550ab41a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-ccaa698f56c0fbdb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-53b944082de1d7db.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-9b70adf1552789bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-30d482aa63241fe8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-aecf786f54651d8a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6ab9b62c7b6e08f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-08949735455e0c9a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-a1479005234a46c2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c3890e90bd232732.js +0 -1
- package/apps/pwa/out/_next/static/chunks/beb5cf10-9adcc10b83930090.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-d68d41c88e05c801.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-11c63971b7a9593b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-d09452353bd0d9cc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-184d727cebeca767.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-21bbbbac99b720b1.js +0 -1
- package/apps/pwa/out/_next/static/css/eaa74e8bb2f62269.css +0 -1
- package/apps/pwa/out/_next/static/qMI0jnlZaBjjm4aIDYNGM/_buildManifest.js +0 -1
- /package/apps/pwa/out/_next/static/{qMI0jnlZaBjjm4aIDYNGM → lywc8m_HDzH9MKSDQhyEj}/_ssgManifest.js +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
|
+
import { isMainThread, parentPort, Worker } from 'node:worker_threads';
|
|
3
|
+
import { debug } from '../debug/log.js';
|
|
2
4
|
import type { LLMToolSpec } from '../llm.js';
|
|
3
5
|
import type { NativeToolCatalogEntry } from '../native-tool-catalog.js';
|
|
4
|
-
import type { ToolRunResult, ToolRuntime } from './types.js';
|
|
6
|
+
import type { ToolRunResult, ToolRuntime, ToolRuntimeContext } from './types.js';
|
|
5
7
|
|
|
6
8
|
/** Canonical names for the read-only self-cognition surface. */
|
|
7
9
|
export const SELF_COGNITION_TOOL_NAMES = [
|
|
@@ -12,6 +14,7 @@ export const SELF_COGNITION_TOOL_NAMES = [
|
|
|
12
14
|
] as const;
|
|
13
15
|
|
|
14
16
|
type SelfCognitionToolName = (typeof SELF_COGNITION_TOOL_NAMES)[number];
|
|
17
|
+
type RecallToolName = 'memory_recall' | 'self_recall';
|
|
15
18
|
type CoreToolsModule = typeof import('../domains/core-tools.js');
|
|
16
19
|
|
|
17
20
|
const require = createRequire(import.meta.url);
|
|
@@ -32,12 +35,167 @@ function toToolRunResult(result: unknown): ToolRunResult {
|
|
|
32
35
|
: { output: String(result) };
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
const PROGRESS_MS = 10_000;
|
|
39
|
+
const DEFAULT_BUDGET_MS = 60_000;
|
|
40
|
+
const MAX_TIMER_MS = 2_147_483_647;
|
|
41
|
+
|
|
42
|
+
function hitCount(result: ToolRunResult): number {
|
|
43
|
+
const data: Record<string, unknown> = result;
|
|
44
|
+
return Array.isArray(data.hits) ? data.hits.length
|
|
45
|
+
: Array.isArray(data.events) ? data.events.length
|
|
46
|
+
: data.restored ? 1 : 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function partialResult(name: RecallToolName, result: ToolRunResult | undefined, budgetMs: number): ToolRunResult {
|
|
50
|
+
const fallback = name === 'memory_recall' ? { hits: [], count: 0 } : { events: [], count: 0, docs: null };
|
|
51
|
+
const snapshot: Record<string, unknown> = result ?? fallback;
|
|
52
|
+
const budgetSeconds = budgetMs / 1000;
|
|
53
|
+
return {
|
|
54
|
+
...snapshot,
|
|
55
|
+
partial: true,
|
|
56
|
+
note: `${typeof snapshot.note === 'string' ? `${snapshot.note}\n` : ''}(찾던 중 ${budgetSeconds}초에서 멈췄습니다 — 더 찾을까요?)`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** A deadline returns the latest completed search stage; late results cannot replace it. */
|
|
61
|
+
export async function runBudgetedRecall(
|
|
62
|
+
name: RecallToolName,
|
|
63
|
+
args: Record<string, unknown>,
|
|
64
|
+
ctx: ToolRuntimeContext,
|
|
65
|
+
search: (onPartial: (result: ToolRunResult) => void) => Promise<ToolRunResult>,
|
|
66
|
+
stop: () => void = () => {},
|
|
67
|
+
progressAfterMs = PROGRESS_MS,
|
|
68
|
+
): Promise<ToolRunResult> {
|
|
69
|
+
const started = Date.now();
|
|
70
|
+
const budgetMs = typeof args.timeBudgetMs === 'number' && Number.isFinite(args.timeBudgetMs) && args.timeBudgetMs > 0
|
|
71
|
+
? Math.min(args.timeBudgetMs, MAX_TIMER_MS) : DEFAULT_BUDGET_MS;
|
|
72
|
+
let latest: ToolRunResult | undefined;
|
|
73
|
+
let settled = false;
|
|
74
|
+
const query = typeof args.query === 'string' && args.query.trim()
|
|
75
|
+
? args.query.trim().replace(/\s+/g, ' ').slice(0, 80)
|
|
76
|
+
: name === 'self_recall' ? '자기 구현·자율행동 이력' : '최근 발송·대화';
|
|
77
|
+
const log = (event: 'progress' | 'budget-hit' | 'done', result?: ToolRunResult) => {
|
|
78
|
+
debug.log('tool.memory-recall', event, { elapsedMs: Date.now() - started, hits: hitCount(result ?? latest ?? {}) });
|
|
79
|
+
};
|
|
80
|
+
let progressTimer: ReturnType<typeof setTimeout> | undefined;
|
|
81
|
+
let budgetTimer: ReturnType<typeof setTimeout> | undefined;
|
|
82
|
+
return new Promise<ToolRunResult>((resolve, reject) => {
|
|
83
|
+
const finish = (result: ToolRunResult, budgetHit: boolean) => {
|
|
84
|
+
if (settled) return;
|
|
85
|
+
settled = true;
|
|
86
|
+
clearTimeout(progressTimer);
|
|
87
|
+
clearTimeout(budgetTimer);
|
|
88
|
+
log(budgetHit ? 'budget-hit' : 'done', result);
|
|
89
|
+
if (budgetHit) stop();
|
|
90
|
+
resolve(result);
|
|
91
|
+
};
|
|
92
|
+
progressTimer = setTimeout(() => {
|
|
93
|
+
if (settled) return;
|
|
94
|
+
const line = `기억을 찾는 중 — ${query}`;
|
|
95
|
+
ctx.emitFeedback?.({
|
|
96
|
+
envelopeVersion: 1,
|
|
97
|
+
sessionId: ctx.sessionId ?? '',
|
|
98
|
+
blockId: `${ctx.sessionId ?? 'recall'}:tool:${ctx.toolCallId ?? name}:progress`,
|
|
99
|
+
parentToolCallId: ctx.toolCallId,
|
|
100
|
+
kind: 'tool.progress', phase: 'delta', emittedAt: Date.now(), seq: 1,
|
|
101
|
+
payload: { stream: 'generic', lines: [line] }, asciiFallback: [line],
|
|
102
|
+
});
|
|
103
|
+
log('progress');
|
|
104
|
+
}, progressAfterMs);
|
|
105
|
+
budgetTimer = setTimeout(() => finish(partialResult(name, latest, budgetMs), true), budgetMs);
|
|
106
|
+
try {
|
|
107
|
+
void search(result => { if (!settled) latest = result; }).then(
|
|
108
|
+
result => finish(result, false),
|
|
109
|
+
error => {
|
|
110
|
+
if (settled) return;
|
|
111
|
+
settled = true;
|
|
112
|
+
clearTimeout(progressTimer);
|
|
113
|
+
clearTimeout(budgetTimer);
|
|
114
|
+
stop();
|
|
115
|
+
reject(error);
|
|
116
|
+
},
|
|
117
|
+
);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
settled = true;
|
|
120
|
+
clearTimeout(progressTimer);
|
|
121
|
+
clearTimeout(budgetTimer);
|
|
122
|
+
stop();
|
|
123
|
+
reject(error);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Separate thread: synchronous SQLite and S3 restore must not block progress/deadline timers.
|
|
129
|
+
if (!isMainThread && parentPort) {
|
|
130
|
+
parentPort.on('message', async ({ name, args }: { name: RecallToolName; args: Record<string, unknown> }) => {
|
|
131
|
+
try {
|
|
132
|
+
if (name === 'self_recall') {
|
|
133
|
+
const { existsSync } = await import('node:fs');
|
|
134
|
+
const { surfaceEventsDbPath, openSurfaceEventsDb, recallEvents } = await import('../domains/surface-events.js');
|
|
135
|
+
if (existsSync(surfaceEventsDbPath())) {
|
|
136
|
+
const db = openSurfaceEventsDb();
|
|
137
|
+
try {
|
|
138
|
+
const query = typeof args.query === 'string' ? args.query : '';
|
|
139
|
+
const hits = recallEvents(db, {
|
|
140
|
+
domain: 'elanous',
|
|
141
|
+
sinceHours: typeof args.sinceHours === 'number' ? args.sinceHours : 720,
|
|
142
|
+
limit: typeof args.limit === 'number' ? args.limit : 8,
|
|
143
|
+
...(query ? { query } : {}),
|
|
144
|
+
});
|
|
145
|
+
const events = hits.map(h => ({
|
|
146
|
+
when: h.ts, tool: h.surface, kind: h.kind ?? 'impl',
|
|
147
|
+
summary: (h.summary ?? h.text).slice(0, 300), score: Math.round(h.score * 1000) / 1000,
|
|
148
|
+
}));
|
|
149
|
+
parentPort?.postMessage({ stage: 'partial', result: { events, count: events.length, docs: null } });
|
|
150
|
+
} catch { /* self_recall's episode stage is fail-soft */ } finally { db.close(); }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const result = await coreTools().dispatchRecallUnbudgeted(name, args, partial => {
|
|
154
|
+
parentPort?.postMessage({ stage: 'partial', result: partial });
|
|
155
|
+
});
|
|
156
|
+
parentPort?.postMessage({ stage: 'done', result });
|
|
157
|
+
} catch (error) {
|
|
158
|
+
parentPort?.postMessage({ stage: 'error', error: error instanceof Error ? error.message : String(error) });
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export type RecallSearch = (name: RecallToolName, args: Record<string, unknown>, onPartial: (result: ToolRunResult) => void) => Promise<ToolRunResult>;
|
|
164
|
+
|
|
165
|
+
export function runRecall(name: RecallToolName, args: Record<string, unknown>, ctx: ToolRuntimeContext, injectedSearch?: RecallSearch, onPartial?: (result: ToolRunResult) => void): Promise<ToolRunResult> {
|
|
166
|
+
const worker = injectedSearch ? undefined : new Worker(new URL(import.meta.url));
|
|
167
|
+
let active = true;
|
|
168
|
+
const search = (capture: (result: ToolRunResult) => void) => {
|
|
169
|
+
const report = (result: ToolRunResult) => {
|
|
170
|
+
if (!active) return;
|
|
171
|
+
capture(result);
|
|
172
|
+
onPartial?.(result);
|
|
173
|
+
};
|
|
174
|
+
return injectedSearch
|
|
175
|
+
? injectedSearch(name, args, report)
|
|
176
|
+
: new Promise<ToolRunResult>((resolve, reject) => {
|
|
177
|
+
worker!.on('message', (message: { stage: string; result?: unknown; error?: string }) => {
|
|
178
|
+
if (message.stage === 'partial') report(toToolRunResult(message.result));
|
|
179
|
+
else if (message.stage === 'done') resolve(toToolRunResult(message.result));
|
|
180
|
+
else if (message.stage === 'error') reject(new Error(message.error));
|
|
181
|
+
});
|
|
182
|
+
worker!.on('error', reject);
|
|
183
|
+
worker!.on('exit', code => { if (code !== 0) reject(new Error(`Recall worker exited: ${code}`)); });
|
|
184
|
+
worker!.postMessage({ name, args });
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
return runBudgetedRecall(name, args, ctx, search, () => { active = false; if (worker) void worker.terminate(); })
|
|
188
|
+
.finally(() => { active = false; if (worker) void worker.terminate(); });
|
|
189
|
+
}
|
|
190
|
+
|
|
35
191
|
export const SELF_COGNITION_RUNTIMES: readonly ToolRuntime[] = SELF_COGNITION_TOOL_NAMES.map(name => ({
|
|
36
192
|
id: name,
|
|
37
193
|
get spec() {
|
|
38
194
|
return coreSpec(name);
|
|
39
195
|
},
|
|
40
|
-
run: async (args) =>
|
|
196
|
+
run: async (args, ctx) => name === 'memory_recall' || name === 'self_recall'
|
|
197
|
+
? runRecall(name, args, ctx)
|
|
198
|
+
: toToolRunResult(await coreTools().buildCoreTools().dispatch(name, args)),
|
|
41
199
|
}));
|
|
42
200
|
|
|
43
201
|
/** MCP catalog metadata derived from the same name ledger as the runtimes. */
|
package/src/user-config.ts
CHANGED
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
GLM_MODEL,
|
|
48
48
|
} from './config.js';
|
|
49
49
|
import type { SkillTier } from './skills/runner.js';
|
|
50
|
+
import { sharedAgentSkillRoots } from './skills/shared-agent-skill-roots.js';
|
|
50
51
|
import {
|
|
51
52
|
isModelTier,
|
|
52
53
|
isModelTierPersona,
|
|
@@ -436,9 +437,28 @@ const LLM_DEFAULTS: LLMConfig = { provider: 'auto' };
|
|
|
436
437
|
export type SkillSetName =
|
|
437
438
|
| 'claudecode' | 'opencode' | 'codex' | 'hermes' | 'openclaw' | 'custom';
|
|
438
439
|
|
|
440
|
+
export type SkillSourceKind = 'preset' | 'shared' | 'connected' | 'package';
|
|
441
|
+
|
|
442
|
+
/** One skill root elanous reads. `mode` is always `ref` today (the folder is read where it is). */
|
|
443
|
+
export interface SkillSource {
|
|
444
|
+
id: string;
|
|
445
|
+
path: string;
|
|
446
|
+
kind: SkillSourceKind;
|
|
447
|
+
enabled: boolean;
|
|
448
|
+
}
|
|
449
|
+
|
|
439
450
|
export interface SkillsConfig {
|
|
440
451
|
activeSet: SkillSetName;
|
|
441
452
|
dirs: string[];
|
|
453
|
+
/** Include the existing shared ~/.agents/skills directory. Default true; false opts out. */
|
|
454
|
+
includeSharedAgentSkills?: boolean;
|
|
455
|
+
/**
|
|
456
|
+
* EN5 — the one source list. On disk it holds only what `elanous connect` registered (kind `connected`, read in
|
|
457
|
+
* place, never copied); the preset (`activeSet`/`dirs`), the shared `~/.agents/skills` root and Claude package
|
|
458
|
+
* roots are derived at read time by `resolveSkillSources()`. The dev-only `connected: string[]` key (EN9, never
|
|
459
|
+
* released) is read and folded in here; the next save writes `sources` instead.
|
|
460
|
+
*/
|
|
461
|
+
sources?: SkillSource[];
|
|
442
462
|
/** Explicit skill-name allowlist. When set and non-empty, the skill
|
|
443
463
|
* index filters to this list — all other skills are hidden from
|
|
444
464
|
* routing, autocompletion, and `/run-skill`. Use when a project
|
|
@@ -505,6 +525,8 @@ export interface DefaultSkillDirsOptions {
|
|
|
505
525
|
pluginsRoot?: string;
|
|
506
526
|
/** Override the installed package root. Tests pass a temp root; production omits this. */
|
|
507
527
|
bundledSkillsRoot?: string;
|
|
528
|
+
/** Override the shared-agent home for isolated discovery tests. */
|
|
529
|
+
sharedAgentHome?: string;
|
|
508
530
|
}
|
|
509
531
|
|
|
510
532
|
/** Resolve the `skills/` directory shipped with this installed package. */
|
|
@@ -512,25 +534,84 @@ export function bundledSkillsDir(packageRoot: string = dirname(import.meta.dir))
|
|
|
512
534
|
return join(packageRoot, 'skills');
|
|
513
535
|
}
|
|
514
536
|
|
|
515
|
-
|
|
516
|
-
cfg
|
|
517
|
-
|
|
518
|
-
|
|
537
|
+
function packageOptIn(cfg?: UserConfig): boolean {
|
|
538
|
+
try { return (cfg ?? getUserConfig()).skills.includeClaudePackageSkills === true; } catch { return false; }
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/** Stable id for a connected root: the agent it belongs to, else the folder (plugin) name. */
|
|
542
|
+
export function skillSourceId(path: string): string {
|
|
543
|
+
if (/[/\\]\.codex[/\\]skills\/?$/.test(path)) return 'codex';
|
|
544
|
+
if (/[/\\]\.claude[/\\]skills\/?$/.test(path)) return 'claude';
|
|
545
|
+
const parts = path.split(/[/\\]/).filter(Boolean);
|
|
546
|
+
const last = parts[parts.length - 1] === 'skills' ? parts[parts.length - 2] : parts[parts.length - 1];
|
|
547
|
+
return `plugin:${last ?? 'skills'}`;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/** Parse persisted `skills.sources` ⊕ the dev-only `skills.connected` key into connected sources (deduped by path). */
|
|
551
|
+
export function parsePersistedSkillSources(rawSources: unknown, legacyConnected: unknown): SkillSource[] | undefined {
|
|
552
|
+
const out: SkillSource[] = [];
|
|
553
|
+
const seen = new Set<string>();
|
|
554
|
+
const push = (source: SkillSource) => { if (!seen.has(source.path)) { seen.add(source.path); out.push(source); } };
|
|
555
|
+
if (Array.isArray(rawSources)) {
|
|
556
|
+
for (const row of rawSources) {
|
|
557
|
+
if (!row || typeof row !== 'object') continue;
|
|
558
|
+
const r = row as Record<string, unknown>;
|
|
559
|
+
if (typeof r.path !== 'string' || !r.path.trim()) continue;
|
|
560
|
+
const path = r.path.trim();
|
|
561
|
+
push({ id: typeof r.id === 'string' && r.id.trim() ? r.id.trim() : skillSourceId(path), path, kind: 'connected', enabled: r.enabled !== false });
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
if (Array.isArray(legacyConnected)) {
|
|
565
|
+
for (const path of legacyConnected) if (typeof path === 'string' && path.trim()) push({ id: skillSourceId(path.trim()), path: path.trim(), kind: 'connected', enabled: true });
|
|
566
|
+
}
|
|
567
|
+
return out.length ? out : undefined;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* ★ EN5 — the ONE function every reader uses (loader · setup checklist · connect · onboarding).
|
|
572
|
+
* Order is the historical order, so an old config resolves to exactly the old directory list:
|
|
573
|
+
* preset (activeSet/dirs) → shared ~/.agents/skills (only when it exists) → connected → Claude package roots (opt-in).
|
|
574
|
+
* Packaged `skills/` is appended by defaultSkillDirs, not listed here.
|
|
575
|
+
*/
|
|
576
|
+
export function resolveSkillSources(cfg?: UserConfig, opts?: DefaultSkillDirsOptions): SkillSource[] {
|
|
519
577
|
const claudecode = skillSetDir('claudecode')!; // = ~/.claude/skills (LOCAL_SKILLS_DIR)
|
|
520
|
-
|
|
578
|
+
const preset = (paths: string[], id: string): SkillSource[] => paths.map((path, i) => ({ id: paths.length > 1 ? `${id}:${i + 1}` : id, path, kind: 'preset', enabled: true }));
|
|
579
|
+
let sources: SkillSource[] = preset([claudecode], 'claudecode');
|
|
521
580
|
try {
|
|
522
581
|
const sk = (cfg ?? getUserConfig()).skills;
|
|
523
582
|
if (sk.activeSet !== 'custom') {
|
|
524
583
|
const d = skillSetDir(sk.activeSet);
|
|
525
|
-
if (d)
|
|
526
|
-
else if (sk.dirs.length > 0)
|
|
584
|
+
if (d) sources = preset([d], sk.activeSet);
|
|
585
|
+
else if (sk.dirs.length > 0) sources = preset([...sk.dirs], 'custom');
|
|
527
586
|
} else if (sk.dirs.length > 0) {
|
|
528
|
-
|
|
587
|
+
sources = preset([...sk.dirs], 'custom');
|
|
588
|
+
}
|
|
589
|
+
const has = (path: string) => sources.some((source) => source.path === path);
|
|
590
|
+
const shared = sharedAgentSkillRoots({
|
|
591
|
+
home: opts?.sharedAgentHome ?? REMOTE_HOME,
|
|
592
|
+
includeSharedAgentSkills: sk.includeSharedAgentSkills !== false,
|
|
593
|
+
});
|
|
594
|
+
try { debug.log('skills.roots', 'shared-agent', { found: shared.length }); }
|
|
595
|
+
catch { /* discovery remains fail-soft when observation is unavailable */ }
|
|
596
|
+
for (const path of shared) if (!has(path)) sources.push({ id: 'agents', path, kind: 'shared', enabled: true });
|
|
597
|
+
for (const source of sk.sources ?? []) if (!has(source.path)) sources.push({ ...source, kind: 'connected' });
|
|
598
|
+
if (sk.includeClaudePackageSkills === true) {
|
|
599
|
+
for (const path of appendClaudePackageSkillDirs([], opts?.pluginsRoot)) {
|
|
600
|
+
if (!has(path)) sources.push({ id: `package:${skillSourceId(path).replace(/^plugin:/, '')}`, path, kind: 'package', enabled: true });
|
|
601
|
+
}
|
|
529
602
|
}
|
|
530
|
-
base = sk.includeClaudePackageSkills === true
|
|
531
|
-
? appendClaudePackageSkillDirs(base, opts?.pluginsRoot)
|
|
532
|
-
: base;
|
|
533
603
|
} catch { /* fail-soft — config 없거나 파싱 실패 시 기본 경로 */ }
|
|
604
|
+
return sources;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
export function defaultSkillDirs(
|
|
608
|
+
cfg?: UserConfig,
|
|
609
|
+
opts?: DefaultSkillDirsOptions,
|
|
610
|
+
): string[] {
|
|
611
|
+
const sources = resolveSkillSources(cfg, opts);
|
|
612
|
+
const paths = sources.filter((source) => source.enabled).map((source) => source.path);
|
|
613
|
+
// Historical: the package opt-in path also collapsed duplicate user dirs; the plain path kept them (index dedupes later).
|
|
614
|
+
const base = sources.some((source) => source.kind === 'package') || packageOptIn(cfg) ? uniqueSkillDirsPreserveOrder(paths) : paths;
|
|
534
615
|
return appendBundledSkillsDir(base, opts?.bundledSkillsRoot);
|
|
535
616
|
}
|
|
536
617
|
|
|
@@ -685,6 +766,7 @@ function skillsDefaults(): SkillsConfig {
|
|
|
685
766
|
return {
|
|
686
767
|
activeSet: 'claudecode',
|
|
687
768
|
dirs: d ? [d] : [],
|
|
769
|
+
includeSharedAgentSkills: true,
|
|
688
770
|
allow: [],
|
|
689
771
|
deny: [],
|
|
690
772
|
urlRouting: urlRoutingDefaults(),
|
|
@@ -886,6 +968,9 @@ export interface DiscordConfig {
|
|
|
886
968
|
allowedUsers: string[];
|
|
887
969
|
/** Channel snowflake for cron / push output (optional). */
|
|
888
970
|
homeChannel?: string;
|
|
971
|
+
/** EV12c — guild text channels where the production bot chats like a DM (allowlist still applies).
|
|
972
|
+
* Empty / absent = DM-only, as before. */
|
|
973
|
+
chatChannels?: string[];
|
|
889
974
|
/** Standalone `elanous discord-test` scope — same token, dedicated
|
|
890
975
|
* channel, isolated state. See DiscordTestChannel. */
|
|
891
976
|
testChannel?: DiscordTestChannel;
|
|
@@ -896,6 +981,7 @@ const DISCORD_DEFAULTS: DiscordConfig = { enabled: false, allowedUsers: [] };
|
|
|
896
981
|
// ── Onboarding ───────────────────────────────────────────────────────
|
|
897
982
|
|
|
898
983
|
export interface OnboardingConfig {
|
|
984
|
+
webFirst?: boolean;
|
|
899
985
|
completed: boolean;
|
|
900
986
|
completedAt?: string;
|
|
901
987
|
version: number;
|
|
@@ -1365,7 +1451,31 @@ export interface ChatCompactConfig {
|
|
|
1365
1451
|
archiveRetentionMb: number;
|
|
1366
1452
|
}
|
|
1367
1453
|
|
|
1454
|
+
/** ER1 — 액티브 덤퍼(오류 자동 보고). 기본 켬(첫 실행 안내 한 번 · 대표 10-01) · 신원(email/telegramUser)은 따로 «예»일 때만. */
|
|
1455
|
+
export interface ErrorReportsConfig {
|
|
1456
|
+
/** false = never send. Absent = on (the first-run notice says how to turn it off). */
|
|
1457
|
+
enabled?: boolean;
|
|
1458
|
+
/** true = also send email / telegramUser below with each report. Default false. */
|
|
1459
|
+
identity?: boolean;
|
|
1460
|
+
email?: string;
|
|
1461
|
+
telegramUser?: string;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
export function parseErrorReportsConfig(raw: unknown): ErrorReportsConfig | undefined {
|
|
1465
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
|
|
1466
|
+
const r = raw as Record<string, unknown>;
|
|
1467
|
+
const out: ErrorReportsConfig = {};
|
|
1468
|
+
if (r.enabled === false || r.enabled === 'false') out.enabled = false;
|
|
1469
|
+
else if (r.enabled === true || r.enabled === 'true') out.enabled = true;
|
|
1470
|
+
if (r.identity === true || r.identity === 'true') out.identity = true;
|
|
1471
|
+
if (typeof r.email === 'string' && r.email.trim()) out.email = r.email.trim();
|
|
1472
|
+
if (typeof r.telegramUser === 'string' && r.telegramUser.trim()) out.telegramUser = r.telegramUser.trim();
|
|
1473
|
+
return Object.keys(out).length ? out : undefined;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1368
1476
|
export interface ChatConfig {
|
|
1477
|
+
/** Short questions may receive a tool-free first reply. Default true. */
|
|
1478
|
+
fastPath: boolean;
|
|
1369
1479
|
conciseness: ChatConcisenessConfig;
|
|
1370
1480
|
toolOutput: ChatToolOutputConfig;
|
|
1371
1481
|
autoCompact: ChatAutoCompactConfig;
|
|
@@ -1392,6 +1502,7 @@ const CHAT_CONCISENESS_DEFAULTS: ChatConcisenessConfig = {
|
|
|
1392
1502
|
};
|
|
1393
1503
|
|
|
1394
1504
|
export const CHAT_DEFAULTS: ChatConfig = {
|
|
1505
|
+
fastPath: true,
|
|
1395
1506
|
conciseness: { ...CHAT_CONCISENESS_DEFAULTS },
|
|
1396
1507
|
toolOutput: {
|
|
1397
1508
|
persistOnOverflow: true,
|
|
@@ -3324,9 +3435,16 @@ export function resolveRoleModel(role: ModelRole, config: UserConfig = getUserCo
|
|
|
3324
3435
|
}
|
|
3325
3436
|
|
|
3326
3437
|
|
|
3438
|
+
export type SeatLoopMode = 'off' | 'shadow' | 'on';
|
|
3439
|
+
|
|
3440
|
+
export interface SeatLoopConfig {
|
|
3441
|
+
/** No seat actions by default; shadow observes without execution, on permits the seat loop to act. */
|
|
3442
|
+
mode: SeatLoopMode;
|
|
3443
|
+
}
|
|
3444
|
+
|
|
3327
3445
|
export interface UserConfig {
|
|
3328
|
-
/** Steward
|
|
3329
|
-
loops?: { steward?: { mode?: 'observe' | 'act'; linearTeam?: string; roles?: Record<string, { maxConcurrent?: number }>; budget?: number; tracks?: Record<string, string
|
|
3446
|
+
/** Steward and seat loops are parsed independently. An absent seat remains off. */
|
|
3447
|
+
loops?: { steward?: { mode?: 'observe' | 'act'; linearTeam?: string; roles?: Record<string, { maxConcurrent?: number }>; budget?: number; tracks?: Record<string, string>; alertAfterFailures?: number }; seat?: SeatLoopConfig };
|
|
3330
3448
|
/** 🔐 Pod 의 Grok API 키 과금은 명시 opt-in 만. 생략·잘못된 값은 false.
|
|
3331
3449
|
* budgetGate 와 같은 `harness` 객체다 — 중복 선언이면 뒤 타입이 앞을 지운다. */
|
|
3332
3450
|
harness?: { pod?: { grokApiKeyOptIn: boolean }; budgetGate?: HarnessBudgetGateConfig; defaultRepo?: string; substrate?: 'local' | 'pod'; podPool?: string };
|
|
@@ -3344,6 +3462,8 @@ export interface UserConfig {
|
|
|
3344
3462
|
logs: LogsConfig;
|
|
3345
3463
|
shell: ShellConfig;
|
|
3346
3464
|
chat: ChatConfig;
|
|
3465
|
+
/** ER1 — optional so older fixtures stay valid; absent = defaults. */
|
|
3466
|
+
errorReports?: ErrorReportsConfig;
|
|
3347
3467
|
voice: VoiceConfig;
|
|
3348
3468
|
intake: IntakeConfig;
|
|
3349
3469
|
dashboard: DashboardConfig;
|
|
@@ -3430,7 +3550,7 @@ export interface UserConfig {
|
|
|
3430
3550
|
/** 승인 뒤 조율 채널 페이즈 배달(기본 OFF) 및 트랙 에이전트(기본 OFF, 최대 동시 2개). */
|
|
3431
3551
|
autopilot?: {
|
|
3432
3552
|
trackCourier?: { enabled?: boolean; channelPr?: number; handoffMinutes?: number };
|
|
3433
|
-
trackAgent?: { enabled: boolean; maxConcurrent: number };
|
|
3553
|
+
trackAgent?: { enabled: boolean; maxConcurrent: number; shadow: boolean; shadowMaxDecisionsPerDay: number };
|
|
3434
3554
|
};
|
|
3435
3555
|
/** 하니스 예산 게이트 설정. 판정은 P15 — 여기선 칸만 싣는다. 파서는 항상 기본을 채운다.
|
|
3436
3556
|
* 선택이다 — 기존 UserConfig 리터럴이 이 칸 없이 컴파일되게 한다. 해석기는 없으면 기본을 쓴다.
|
|
@@ -3618,6 +3738,10 @@ function parseAutopilotConfig(raw: unknown): UserConfig['autopilot'] | undefined
|
|
|
3618
3738
|
enabled: v.enabled === true,
|
|
3619
3739
|
maxConcurrent: typeof v.maxConcurrent === 'number' && Number.isSafeInteger(v.maxConcurrent) && v.maxConcurrent > 0
|
|
3620
3740
|
? Math.min(v.maxConcurrent, 2) : 2,
|
|
3741
|
+
shadow: v.shadow === true,
|
|
3742
|
+
shadowMaxDecisionsPerDay: typeof v.shadowMaxDecisionsPerDay === 'number'
|
|
3743
|
+
&& Number.isSafeInteger(v.shadowMaxDecisionsPerDay) && v.shadowMaxDecisionsPerDay >= 0
|
|
3744
|
+
? v.shadowMaxDecisionsPerDay : 20,
|
|
3621
3745
|
};
|
|
3622
3746
|
}
|
|
3623
3747
|
return Object.keys(parsed).length > 0 ? parsed : undefined;
|
|
@@ -3649,6 +3773,7 @@ function parseRoleLlmConfig(raw: unknown): RoleLlmConfig | undefined {
|
|
|
3649
3773
|
|
|
3650
3774
|
function defaultConfig(): UserConfig {
|
|
3651
3775
|
return {
|
|
3776
|
+
loops: { seat: { mode: 'off' } },
|
|
3652
3777
|
skillRouter: { ...SR_DEFAULTS },
|
|
3653
3778
|
llm: { ...LLM_DEFAULTS },
|
|
3654
3779
|
skills: skillsDefaults(),
|
|
@@ -3661,6 +3786,7 @@ function defaultConfig(): UserConfig {
|
|
|
3661
3786
|
logs: { retention: { ...LOGS_DEFAULTS.retention } },
|
|
3662
3787
|
shell: { ...SHELL_DEFAULTS },
|
|
3663
3788
|
chat: {
|
|
3789
|
+
fastPath: CHAT_DEFAULTS.fastPath,
|
|
3664
3790
|
conciseness: { ...CHAT_CONCISENESS_DEFAULTS },
|
|
3665
3791
|
toolOutput: { ...CHAT_DEFAULTS.toolOutput },
|
|
3666
3792
|
autoCompact: { ...CHAT_DEFAULTS.autoCompact },
|
|
@@ -4126,6 +4252,14 @@ function parseStewardTracks(input: unknown): Record<string, string> | undefined
|
|
|
4126
4252
|
return Object.keys(out).length ? out : undefined;
|
|
4127
4253
|
}
|
|
4128
4254
|
|
|
4255
|
+
function parseSeatLoopsConfig(input: unknown): SeatLoopConfig {
|
|
4256
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)) return { mode: 'off' };
|
|
4257
|
+
const seat = (input as Record<string, unknown>).seat;
|
|
4258
|
+
if (!seat || typeof seat !== 'object' || Array.isArray(seat)) return { mode: 'off' };
|
|
4259
|
+
const mode = (seat as Record<string, unknown>).mode;
|
|
4260
|
+
return { mode: mode === 'on' || mode === 'shadow' ? mode : 'off' };
|
|
4261
|
+
}
|
|
4262
|
+
|
|
4129
4263
|
function parseStewardLoopsConfig(input: unknown): UserConfig['loops'] {
|
|
4130
4264
|
if (!input || typeof input !== 'object' || Array.isArray(input)) return undefined;
|
|
4131
4265
|
const value = (input as Record<string, unknown>).steward;
|
|
@@ -4144,6 +4278,7 @@ function parseStewardLoopsConfig(input: unknown): UserConfig['loops'] {
|
|
|
4144
4278
|
...(typeof s.linearTeam === 'string' && s.linearTeam.trim() ? { linearTeam: s.linearTeam.trim() } : {}),
|
|
4145
4279
|
...(Object.keys(roles).length ? { roles } : {}),
|
|
4146
4280
|
...(typeof s.budget === 'number' && Number.isFinite(s.budget) && s.budget >= 0 ? { budget: s.budget } : {}),
|
|
4281
|
+
...(typeof s.alertAfterFailures === 'number' && Number.isSafeInteger(s.alertAfterFailures) && s.alertAfterFailures > 0 ? { alertAfterFailures: s.alertAfterFailures } : {}),
|
|
4147
4282
|
...(parseStewardTracks(s.tracks) ? { tracks: parseStewardTracks(s.tracks)! } : {}),
|
|
4148
4283
|
} };
|
|
4149
4284
|
}
|
|
@@ -4374,6 +4509,8 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
4374
4509
|
skills: {
|
|
4375
4510
|
activeSet: normalizeSkillSet(sk.activeSet),
|
|
4376
4511
|
dirs: strArray(sk.dirs, skillsDefaults().dirs),
|
|
4512
|
+
includeSharedAgentSkills: sk.includeSharedAgentSkills !== false,
|
|
4513
|
+
...(() => { const sources = parsePersistedSkillSources(sk.sources, sk.connected); return sources ? { sources } : {}; })(),
|
|
4377
4514
|
allow: strArray(sk.allow, []),
|
|
4378
4515
|
deny: strArray(sk.deny, []),
|
|
4379
4516
|
urlRouting: parseUrlRouting(sk.urlRouting),
|
|
@@ -4409,6 +4546,9 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
4409
4546
|
homeChannel: typeof dc.homeChannel === 'string' ? dc.homeChannel
|
|
4410
4547
|
: typeof dc.homeChannel === 'number' ? String(dc.homeChannel) : undefined,
|
|
4411
4548
|
testChannel: normalizeDiscordTestChannel((dc as Record<string, unknown>).testChannel),
|
|
4549
|
+
...(Array.isArray(dc.chatChannels)
|
|
4550
|
+
? { chatChannels: (dc.chatChannels as unknown[]).map(v => String(v).trim()).filter(Boolean) }
|
|
4551
|
+
: {}),
|
|
4412
4552
|
// Sprint 21 wiring sub-block (2026-05-01)
|
|
4413
4553
|
},
|
|
4414
4554
|
finance: {
|
|
@@ -4452,6 +4592,7 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
4452
4592
|
relaxedGates: fin.relaxedGates === true,
|
|
4453
4593
|
},
|
|
4454
4594
|
onboarding: {
|
|
4595
|
+
...(typeof ob2.webFirst === 'boolean' ? { webFirst: ob2.webFirst } : {}),
|
|
4455
4596
|
completed: ob2.completed === true,
|
|
4456
4597
|
completedAt: str(ob2.completedAt),
|
|
4457
4598
|
version: typeof ob2.version === 'number' ? ob2.version : 0,
|
|
@@ -4497,7 +4638,9 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
4497
4638
|
// false required to short-circuit `buildDashboardOptionalToolSpecs`.
|
|
4498
4639
|
allowDashboardOptionalTools: sh.allowDashboardOptionalTools !== false,
|
|
4499
4640
|
},
|
|
4641
|
+
...((): { errorReports?: ErrorReportsConfig } => { const er = parseErrorReportsConfig(rawObj.errorReports); return er ? { errorReports: er } : {}; })(),
|
|
4500
4642
|
chat: {
|
|
4643
|
+
fastPath: chat.fastPath === false || chat.fastPath === 'false' ? false : CHAT_DEFAULTS.fastPath,
|
|
4501
4644
|
conciseness: {
|
|
4502
4645
|
enabled: chatConciseness.enabled === false ? false : CHAT_CONCISENESS_DEFAULTS.enabled,
|
|
4503
4646
|
finalMessageMaxLines: clampNum(
|
|
@@ -4876,7 +5019,7 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
4876
5019
|
goals: parseGoalsConfig(rawObj.goals),
|
|
4877
5020
|
registry: parseRegistryConfig(rawObj.registry),
|
|
4878
5021
|
tools: parseToolsConfig(rawObj.tools),
|
|
4879
|
-
...(stewardLoops
|
|
5022
|
+
loops: { ...(stewardLoops ?? {}), seat: parseSeatLoopsConfig(rawObj.loops) },
|
|
4880
5023
|
// M1-1: sparse — undefined when the user hasn't set anything, so
|
|
4881
5024
|
// resolvers fall through to zero-config defaults.
|
|
4882
5025
|
...spreadIfDefined('modelTier', parseModelTierConfig(rawObj.modelTier)),
|
|
@@ -5450,6 +5593,11 @@ export function saveUserConfig(
|
|
|
5450
5593
|
const rawHarness = rawRest.harness && typeof rawRest.harness === 'object' && !Array.isArray(rawRest.harness)
|
|
5451
5594
|
? rawRest.harness as Record<string, unknown> : {};
|
|
5452
5595
|
delete rawRest.harness;
|
|
5596
|
+
const rawAutopilot = rawRest.autopilot && typeof rawRest.autopilot === 'object' && !Array.isArray(rawRest.autopilot)
|
|
5597
|
+
? rawRest.autopilot as Record<string, unknown> : {};
|
|
5598
|
+
const rawLoops = rawRest.loops && typeof rawRest.loops === 'object' && !Array.isArray(rawRest.loops)
|
|
5599
|
+
? rawRest.loops as Record<string, unknown> : {};
|
|
5600
|
+
if (cfg.loops) delete rawRest.loops;
|
|
5453
5601
|
if (cfg.pod?.hostMirror) {
|
|
5454
5602
|
const rawPod = rawRest.pod && typeof rawRest.pod === 'object' && !Array.isArray(rawRest.pod)
|
|
5455
5603
|
? rawRest.pod as Record<string, unknown> : {};
|
|
@@ -5466,6 +5614,24 @@ export function saveUserConfig(
|
|
|
5466
5614
|
podPool: cfg.harness?.podPool,
|
|
5467
5615
|
}),
|
|
5468
5616
|
...rawRest,
|
|
5617
|
+
...(cfg.loops ? { loops: {
|
|
5618
|
+
...rawLoops,
|
|
5619
|
+
...(cfg.loops.seat ? { seat: { mode: cfg.loops.seat.mode } } : {}),
|
|
5620
|
+
} } : {}),
|
|
5621
|
+
...(cfg.autopilot ? { autopilot: {
|
|
5622
|
+
...rawAutopilot,
|
|
5623
|
+
...cfg.autopilot,
|
|
5624
|
+
...(cfg.autopilot.trackAgent ? { trackAgent: {
|
|
5625
|
+
...(rawAutopilot.trackAgent && typeof rawAutopilot.trackAgent === 'object' && !Array.isArray(rawAutopilot.trackAgent)
|
|
5626
|
+
? rawAutopilot.trackAgent as Record<string, unknown> : {}),
|
|
5627
|
+
...cfg.autopilot.trackAgent,
|
|
5628
|
+
} } : {}),
|
|
5629
|
+
...(cfg.autopilot.trackCourier ? { trackCourier: {
|
|
5630
|
+
...(rawAutopilot.trackCourier && typeof rawAutopilot.trackCourier === 'object' && !Array.isArray(rawAutopilot.trackCourier)
|
|
5631
|
+
? rawAutopilot.trackCourier as Record<string, unknown> : {}),
|
|
5632
|
+
...cfg.autopilot.trackCourier,
|
|
5633
|
+
} } : {}),
|
|
5634
|
+
} } : {}),
|
|
5469
5635
|
skillRouter: cfg.skillRouter,
|
|
5470
5636
|
llm: stripUndef({
|
|
5471
5637
|
provider: cfg.llm.provider,
|
|
@@ -5517,6 +5683,10 @@ export function saveUserConfig(
|
|
|
5517
5683
|
skills: stripUndef({
|
|
5518
5684
|
activeSet: cfg.skills.activeSet,
|
|
5519
5685
|
dirs: [...cfg.skills.dirs],
|
|
5686
|
+
// EN5 — only connected roots are persisted (preset/shared/package are derived). The dev-only `connected` key is not written back.
|
|
5687
|
+
sources: cfg.skills.sources && cfg.skills.sources.some((source) => source.kind === 'connected')
|
|
5688
|
+
? cfg.skills.sources.filter((source) => source.kind === 'connected').map(({ id, path, enabled }) => ({ id, path, enabled }))
|
|
5689
|
+
: undefined,
|
|
5520
5690
|
// Omit allow/deny when empty to keep disk JSON minimal for the
|
|
5521
5691
|
// common "no filter" case.
|
|
5522
5692
|
allow: cfg.skills.allow && cfg.skills.allow.length > 0 ? [...cfg.skills.allow] : undefined,
|
|
@@ -5575,6 +5745,7 @@ export function saveUserConfig(
|
|
|
5575
5745
|
botToken: cfg.discord.botToken,
|
|
5576
5746
|
allowedUsers: [...cfg.discord.allowedUsers],
|
|
5577
5747
|
homeChannel: cfg.discord.homeChannel,
|
|
5748
|
+
chatChannels: cfg.discord.chatChannels ? [...cfg.discord.chatChannels] : undefined,
|
|
5578
5749
|
testChannel: cfg.discord.testChannel
|
|
5579
5750
|
? stripUndef({
|
|
5580
5751
|
channelId: cfg.discord.testChannel.channelId,
|
|
@@ -5601,6 +5772,7 @@ export function saveUserConfig(
|
|
|
5601
5772
|
relaxedGates: cfg.finance.relaxedGates,
|
|
5602
5773
|
}),
|
|
5603
5774
|
onboarding: stripUndef({
|
|
5775
|
+
webFirst: cfg.onboarding.webFirst,
|
|
5604
5776
|
completed: cfg.onboarding.completed,
|
|
5605
5777
|
completedAt: cfg.onboarding.completedAt,
|
|
5606
5778
|
version: cfg.onboarding.version,
|
|
@@ -5608,7 +5780,9 @@ export function saveUserConfig(
|
|
|
5608
5780
|
debug: cfg.debug,
|
|
5609
5781
|
logs: cfg.logs,
|
|
5610
5782
|
shell: cfg.shell,
|
|
5783
|
+
errorReports: cfg.errorReports ? stripUndef({ ...cfg.errorReports }) : undefined,
|
|
5611
5784
|
chat: stripUndef({
|
|
5785
|
+
fastPath: cfg.chat.fastPath,
|
|
5612
5786
|
conciseness: stripUndef({
|
|
5613
5787
|
enabled: cfg.chat.conciseness.enabled,
|
|
5614
5788
|
finalMessageMaxLines: cfg.chat.conciseness.finalMessageMaxLines,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"commit":"
|
|
1
|
+
{"commit":"eca73b4a3a106df99424c22206165f2fe4e5e910"}
|
|
@@ -14,8 +14,10 @@
|
|
|
14
14
|
* (📏 2026-09-23: 연출 있는 shot2 = 0.708 < 연출 없는 대조군 0.851).
|
|
15
15
|
*/
|
|
16
16
|
import { spawnSync } from 'node:child_process';
|
|
17
|
-
import { existsSync, readdirSync } from 'node:fs';
|
|
17
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
18
|
+
import { homedir } from 'node:os';
|
|
18
19
|
import { join } from 'node:path';
|
|
20
|
+
import { searchVflowReferences } from '../vflow-reference.js';
|
|
19
21
|
import { run } from './ffmpeg.js';
|
|
20
22
|
import { resolvePython } from '../../python/resolve-python.js';
|
|
21
23
|
import { UNOBSERVED, type Recipe } from './types.js';
|
|
@@ -111,14 +113,49 @@ export const identityHoldsGate: Recipe = async (ctx) => {
|
|
|
111
113
|
export const directedShots: Recipe = async (ctx) => {
|
|
112
114
|
const src = ctx.state.shot_sources as Record<string, string> | undefined;
|
|
113
115
|
if (!src) return need('shot_sources');
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
+
const prompts = ctx.state.shot_prompts as Record<string, string> | undefined;
|
|
117
|
+
const existingShots = Object.entries(src).filter(([, path]) => existsSync(path));
|
|
118
|
+
const shot_paths = existingShots.map(([, path]) => path);
|
|
119
|
+
const promptedShots = existingShots.filter(([shot]) => prompts?.[shot] !== undefined);
|
|
120
|
+
const shot_references: Record<string, { url: string; videoUrl: string | null; model: string; name: string; author: string | null; authorUrl: string | null; camera: string[] }[]> = {};
|
|
121
|
+
let referenceNote = '';
|
|
122
|
+
if (prompts && Object.keys(prompts).length && shot_paths.length) {
|
|
123
|
+
const file = (ctx.state.vflow_file as string | undefined) ?? join(homedir(), 'docs', 'ref', 'vflow', 'prompts.ndjson');
|
|
124
|
+
const taxonomy = readFileSync(join(import.meta.dir, '../../../graphs/video/reference/vflow-taxonomy.yaml'), 'utf8');
|
|
125
|
+
const cameraAxis = taxonomy.match(/^ camera_movement:.*\n((?:^ .*\n)*)/m)?.[1] ?? '';
|
|
126
|
+
const cameraTerms = [...cameraAxis.matchAll(/term:\s*([^,}]+)/g)].map((match) => match[1]!.trim());
|
|
127
|
+
// These shot-prompt camera terms supplement the site's taxonomy axis.
|
|
128
|
+
cameraTerms.push('crash zoom', 'dolly', 'static');
|
|
129
|
+
const cameraPatterns = cameraTerms.map((term) => {
|
|
130
|
+
const escaped = term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
131
|
+
return { term, pattern: new RegExp(`(?<![\\p{L}\\p{N}])${escaped}(?![\\p{L}\\p{N}])`, 'iu') };
|
|
132
|
+
});
|
|
133
|
+
let found = 0;
|
|
134
|
+
for (const [shot] of promptedShots) {
|
|
135
|
+
const prompt = prompts[shot]!;
|
|
136
|
+
const camera = cameraPatterns.filter(({ pattern }) => pattern.test(prompt)).map(({ term }) => term);
|
|
137
|
+
const result = searchVflowReferences(file, { camera, model: ctx.state.shot_model as string | undefined, limit: camera.length ? 3 : 0 });
|
|
138
|
+
if (!result.available) {
|
|
139
|
+
referenceNote = `vflow DB 없음(${result.reason})`;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
shot_references[shot] = result.rows.map((row) => ({
|
|
143
|
+
url: row.url, videoUrl: row.video?.url ?? null, model: row.model, name: row.name,
|
|
144
|
+
author: row.author, authorUrl: row.authorUrl, camera: row.spec?.camera ?? [],
|
|
145
|
+
}));
|
|
146
|
+
if (shot_references[shot]!.length) found++;
|
|
147
|
+
}
|
|
148
|
+
if (!referenceNote) referenceNote = `vflow 참고 ${found}샷/${shot_paths.length}샷`;
|
|
149
|
+
}
|
|
150
|
+
const note = (text: string) => referenceNote ? `${text}\n${referenceNote}` : text;
|
|
151
|
+
if (shot_paths.length === 0) return { outcome: 'error', produced: prompts ? { shot_references } : undefined, note: note('샷 0 — ⛔ 이 러너는 크레딧을 안 쓴다(Seedance·Kling 생성은 스킬 세션의 몫)') };
|
|
152
|
+
const produced = { shot_paths, shot_count: shot_paths.length, ...(prompts ? { shot_references } : {}) };
|
|
116
153
|
// ⛔⭐ 되돌이 수렴(🩸 2026-09-23 실물: fullbleed → shots → «같은» 샷 → fullbleed … 예산 소진).
|
|
117
154
|
// 리프레임 자가 「그 비율로 다시 렌더하라」고 돌려보냈는데 이 러너는 다시 그릴 수 없다(크레딧 무사용)
|
|
118
155
|
// ⇒ 같은 샷을 또 내면 같은 판정이 난다. 「못 다시 그린다」를 error 로 말해 `rendered-unedited` 로 끝낸다.
|
|
119
156
|
const pending = (ctx.state.fullbleed_cuts as string[] | undefined) ?? [];
|
|
120
|
-
if (pending.length) return { outcome: 'error', produced
|
|
121
|
-
return { outcome: 'ok', produced
|
|
157
|
+
if (pending.length) return { outcome: 'error', produced, note: note(`전용 비율 재렌더가 필요한 샷 ${pending.join(', ')} — ⛔ 이 러너는 다시 그리지 않는다(크레딧 무사용) · 그 비율 렌더를 스킬 세션에서 만든 뒤 native 로 넘겨라`) };
|
|
158
|
+
return { outcome: 'ok', produced, note: note(`샷 ${shot_paths.length}개 · ⚠️ 이미 생성된 것을 받았다`) };
|
|
122
159
|
};
|
|
123
160
|
|
|
124
161
|
/** `08_shot_ruler.py` 의 `shot_variation` 한 칸만 읽는다(그 자가 «살아남은 유일한 칸»이라 스스로 적었다). */
|