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
package/src/index.ts
CHANGED
|
@@ -9,6 +9,9 @@ import { LOGS_SINCE_OPTION, registerLogsCommands } from './cli/logs-cli.js';
|
|
|
9
9
|
import { registerDocsCommands } from './cli/docs-cli.js';
|
|
10
10
|
import { registerA2ACommands } from './cli/a2a-cli.js';
|
|
11
11
|
import { registerPluginCommands } from './cli/plugin-cli.js';
|
|
12
|
+
import { registerConnectCommand, registerSkillsCommands } from './cli/skills-cli.js';
|
|
13
|
+
import { registerImportCommand } from './cli/import-cli.js';
|
|
14
|
+
import { registerPersonaCommands } from './cli/persona-cli.js';
|
|
12
15
|
import { registerFleetCommands } from './cli/fleet-cli.js';
|
|
13
16
|
import { readPipedStdin } from './cli/piped-stdin.js';
|
|
14
17
|
import { writeStdoutJson } from './cli/stdout-json.js';
|
|
@@ -62,6 +65,7 @@ import { registerModelWatchCommand } from './cli/model-watch-cli.js';
|
|
|
62
65
|
import { registerIntakeCommands } from './cli/intake-cli.js';
|
|
63
66
|
import { registerTasksCommands } from './cli/tasks-cli.js';
|
|
64
67
|
import { registerLabelsCommands } from './cli/labels-cli.js';
|
|
68
|
+
import { registerMsgCommands } from './cli/msg-cli.js';
|
|
65
69
|
import { registerDoctorCommand } from './cli/doctor-cli.js';
|
|
66
70
|
import { registerProviderCommands } from './cli/provider-cli.js';
|
|
67
71
|
export { buildCodexAccountImportGuidance, setCodexAccountLogSinkModuleForTesting } from './cli/provider-cli.js';
|
|
@@ -74,6 +78,7 @@ import { registerGraphCommands } from './graph-runner/graph-cli.js';
|
|
|
74
78
|
import { registerLoopCommands } from './loops/loop-cli.js';
|
|
75
79
|
import { registerCardCommand } from './task-cards/card-cli.js';
|
|
76
80
|
import { registerLaunchHeadCommands } from './launch-head/launch-head-cli.js';
|
|
81
|
+
import { acpServerHelpText } from './boot/acp-server-help.js';
|
|
77
82
|
// IMPORTANT: parse `--config-dir <dir>` + `--test-state-dir <dir>`
|
|
78
83
|
// BEFORE Commander loads — the resolvers are read at module-init
|
|
79
84
|
// time by several config-touching imports below, so the override
|
|
@@ -95,7 +100,8 @@ import type { AdPipelinePlan, AdPipelineResult } from './ad-pipeline/run.js';
|
|
|
95
100
|
import type { AcpPermissionApprover } from './acp/client.js';
|
|
96
101
|
import { runGitCommand } from './git-fs/runner.js';
|
|
97
102
|
import { debug, redactSecretText, redactSecrets } from './debug/log.js';
|
|
98
|
-
import {
|
|
103
|
+
import { installHarnessCliCommand, type HarnessAskSayChildLlmOptions, type HarnessAskSayOptions, type HarnessPlanOptions } from './harness/harness-cli-command.js';
|
|
104
|
+
import { formatCliUserError, isCliUserError } from './cli/cli-user-error.js';
|
|
99
105
|
import { dispatchSolveMission } from './skills/tools/solve-mission.js';
|
|
100
106
|
import { performBrowserAction, type BrowserActionDeps, type BrowserActionResult } from './harness/browser-act.js';
|
|
101
107
|
import { decideTypeAction, type TypeActionDecision, type TypeTarget } from './harness/browser-act-type.js';
|
|
@@ -152,7 +158,7 @@ async function readStdinLine(prompt: string = ''): Promise<string> {
|
|
|
152
158
|
finally { rl.close(); }
|
|
153
159
|
}
|
|
154
160
|
import { loginWithCodex, CODEX_DEVICE_LOGIN_URL } from './oauth/codex.js';
|
|
155
|
-
import { authStorePath, loadTokens, deleteTokens, listProviders as listAuthProviders } from './oauth/store.js';
|
|
161
|
+
import { authStorePath, loadTokens, deleteTokens, saveTokens, listProviders as listAuthProviders, type CodexMirrorResult } from './oauth/store.js';
|
|
156
162
|
import { renderKeyHelp, CONTEXT_LABELS, type KeyContext } from './keybindings.js';
|
|
157
163
|
import { auditKeybindings, renderKeymapAudit } from './keymap-audit.js';
|
|
158
164
|
import { runCodexSetup } from './codex/setup.js';
|
|
@@ -164,6 +170,7 @@ import { initSessionWorkingDir } from './session/working-dir.js';
|
|
|
164
170
|
import { rewriteBareNexusToStatus } from './cli/nexus-entry.js';
|
|
165
171
|
import { registerIngestTokenCommands } from './cli/ingest-token-cli.js';
|
|
166
172
|
import { registerMcpGatewayCommands } from './cli/mcp-gateway-cli.js';
|
|
173
|
+
import { registerRelayCommand } from './relay/relay-cli.js';
|
|
167
174
|
import type { ReviewImage } from './agent-substrate/pr-reviewer.js';
|
|
168
175
|
import {
|
|
169
176
|
describeMissionRouting,
|
|
@@ -864,6 +871,14 @@ registerDoctorCommand(program);
|
|
|
864
871
|
registerControlCommands(program);
|
|
865
872
|
registerHooksCommands(program);
|
|
866
873
|
registerSetupCommand(program);
|
|
874
|
+
program.commands.find(command => command.name() === 'setup')!
|
|
875
|
+
.option('--terminal', 'Run the terminal onboarding wizard')
|
|
876
|
+
.hook('preAction', async (_command, action) => {
|
|
877
|
+
if (action.name() === 'setup' && action.opts().terminal) {
|
|
878
|
+
const completed = await runOnboardingForCli();
|
|
879
|
+
process.exit(completed ? 0 : (process.exitCode || 2));
|
|
880
|
+
}
|
|
881
|
+
});
|
|
867
882
|
registerStartCommand(program);
|
|
868
883
|
registerGroundingSourcesCli(program);
|
|
869
884
|
registerGraphCommands(program);
|
|
@@ -873,6 +888,10 @@ registerCardCommand(program);
|
|
|
873
888
|
registerLaunchHeadCommands(program);
|
|
874
889
|
registerA2ACommands(program);
|
|
875
890
|
registerPluginCommands(program);
|
|
891
|
+
registerSkillsCommands(program);
|
|
892
|
+
registerConnectCommand(program);
|
|
893
|
+
registerImportCommand(program);
|
|
894
|
+
registerPersonaCommands(program);
|
|
876
895
|
|
|
877
896
|
const marketCmd = program.command('market').description('Signed plugin marketplace');
|
|
878
897
|
marketCmd.command('publish').description('Publish a local signed marketplace index and archives')
|
|
@@ -905,6 +924,10 @@ marketCmd.command('publish').description('Publish a local signed marketplace ind
|
|
|
905
924
|
console.log(`Published ${result.published.length} plugins (sequence ${result.sequence}); skipped ${result.skipped.length}`);
|
|
906
925
|
for (const warning of result.warnings) console.warn(`⚠ ${warning.dir}: ${warning.graph} uses recipes it does not ship (${warning.recipes.join(', ')}) — third-party graphs should use their own recipes.yaml or custom nodes`);
|
|
907
926
|
}
|
|
927
|
+
for (const item of result.skipped) {
|
|
928
|
+
for (const hit of item.hits ?? []) console.error(`${item.dir}/${hit.file}:${hit.line}: ${hit.marker}`);
|
|
929
|
+
}
|
|
930
|
+
if (!result.ok) process.exitCode = 1;
|
|
908
931
|
} catch (error) {
|
|
909
932
|
console.error(`market publish: ${error instanceof Error ? error.message : 'failed'}`);
|
|
910
933
|
process.exitCode = 1;
|
|
@@ -1002,7 +1025,7 @@ program.command('self-update')
|
|
|
1002
1025
|
|
|
1003
1026
|
program
|
|
1004
1027
|
.name('elanous')
|
|
1005
|
-
.description('
|
|
1028
|
+
.description('말 한 줄로 시작: elanous harness say "…" — 끝까지 간다 · 다 보인다 · 스스로를 만들었다')
|
|
1006
1029
|
.version(cliVersion())
|
|
1007
1030
|
// Documentation-only entry — the flag is extracted from argv by
|
|
1008
1031
|
// `applyConfigDirFlagFromArgv` at module init (above) so Commander
|
|
@@ -1028,6 +1051,7 @@ program
|
|
|
1028
1051
|
'--test',
|
|
1029
1052
|
'격리 테스트 인스턴스로 실행 — cwd 의 git 트리(worktree 포함)에서 `<트리>/.elanous-test` 를 루트로 잡고 state·config 두 축을 함께 격리한다. config 사본이 없으면 자동 물질화. `--test=<dir>` 로 루트 직접 지정 가능(값 문법은 `=` 형태 하나 — 모호함 없음). ELANOUS_STATE_DIR/--config-dir 을 손으로 줄 필요가 없다.',
|
|
1030
1053
|
);
|
|
1054
|
+
program.addHelpText('after', acpServerHelpText());
|
|
1031
1055
|
|
|
1032
1056
|
program
|
|
1033
1057
|
.command('measure-fabric-arc-ab')
|
|
@@ -1076,6 +1100,8 @@ const mcpCmd = program
|
|
|
1076
1100
|
.description('MCP (Model Context Protocol) server / client integration');
|
|
1077
1101
|
registerMcpGatewayCommands(mcpCmd);
|
|
1078
1102
|
|
|
1103
|
+
registerRelayCommand(program);
|
|
1104
|
+
|
|
1079
1105
|
mcpCmd
|
|
1080
1106
|
.command('serve')
|
|
1081
1107
|
.description('Run a stdio MCP server exposing the configured mcp.servers as proxy tools (used by `claude mcp add elanous -- elanous mcp serve`)')
|
|
@@ -2952,6 +2978,9 @@ const harnessOrchestrateCmd = registerHarnessOrchestrateCapabilityOptions(
|
|
|
2952
2978
|
|
|
2953
2979
|
const selfCmd = program.command('self').description('Self-awareness memory — 외부 도구(Claude Code/Codex)가 구현/변경 이력을 elanous 기억에 주입·회상');
|
|
2954
2980
|
|
|
2981
|
+
// M12 Claude Code 의존도 계기판 — `elanous self dependence [--since] [--until] [--json]`(읽기만).
|
|
2982
|
+
{ const { registerDependenceCommand } = await import('./cli/dependence-gauge.js'); registerDependenceCommand(selfCmd); }
|
|
2983
|
+
|
|
2955
2984
|
function printExtendedOrchestrateHelp(command: Command, positional = '[goals...]'): void {
|
|
2956
2985
|
const optionLines = command.options
|
|
2957
2986
|
.filter((option) => option.long !== '--help-all')
|
|
@@ -4155,6 +4184,9 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4155
4184
|
});
|
|
4156
4185
|
process.env[HARNESS_RUN_ID_ENV] = runId;
|
|
4157
4186
|
reportRunId = runId;
|
|
4187
|
+
// HS1 — `harness stop <runId>` must find this process from the moment the run ID exists.
|
|
4188
|
+
try { (await import('./self-dev/orchestrate.js')).writeRunPidRecord(runId); }
|
|
4189
|
+
catch (error) { debug.log('self-dev.orchestrate', 'early-pid-failed', { runId, error: String(error) }, { level: 'warn' }); }
|
|
4158
4190
|
const createdAt = prior?.createdAt ?? Date.now();
|
|
4159
4191
|
const { bindOrchestrateRunLedger } = await import('./self-dev/self-orchestrate-runtime.js');
|
|
4160
4192
|
const { checkpoint } = bindOrchestrateRunLedger({
|
|
@@ -4280,7 +4312,26 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4280
4312
|
grokApiKeyOptIn = getUserConfig().harness?.pod?.grokApiKeyOptIn === true;
|
|
4281
4313
|
const credential = resolveGrokCredential();
|
|
4282
4314
|
const { resolveCodexQuotaPolicy, codexPolicyAllowsCredits, codexPolicyAllowsFallback } = await import('./oauth/codex-quota-policy.js');
|
|
4283
|
-
const
|
|
4315
|
+
const resolvedQuota = resolveCodexQuotaPolicy(getUserConfig().llm);
|
|
4316
|
+
const quotaPolicy = resolvedQuota.policy;
|
|
4317
|
+
// POL1 — say which policy this launch uses and where it came from; warn when a test universe disagrees with production.
|
|
4318
|
+
try {
|
|
4319
|
+
const { effectiveInstanceRoot, prodInstanceRoot } = await import('./instance/resolve.js');
|
|
4320
|
+
const { describeLaunchQuotaPolicy } = await import('./oauth/codex-quota-policy.js');
|
|
4321
|
+
const root = effectiveInstanceRoot();
|
|
4322
|
+
const kind = root === prodInstanceRoot() ? 'prod' as const : 'test' as const;
|
|
4323
|
+
let production: ReturnType<typeof resolveCodexQuotaPolicy> | undefined;
|
|
4324
|
+
if (kind === 'test') {
|
|
4325
|
+
try {
|
|
4326
|
+
const { readFileSync } = await import('node:fs');
|
|
4327
|
+
const prodLlm = (JSON.parse(readFileSync(`${prodInstanceRoot()}/config.json`, 'utf8')) as { llm?: Record<string, unknown> }).llm;
|
|
4328
|
+
production = resolveCodexQuotaPolicy(prodLlm);
|
|
4329
|
+
} catch { /* no production config on this machine */ }
|
|
4330
|
+
}
|
|
4331
|
+
const described = describeLaunchQuotaPolicy({ current: resolvedQuota, universe: { kind, root }, ...(production ? { production } : {}) });
|
|
4332
|
+
debug.log('self-implement.pod', 'quota-policy', { policy: resolvedQuota.policy, source: resolvedQuota.source, universe: kind, productionPolicy: production?.policy ?? null });
|
|
4333
|
+
if (!opts.json) { ui.info(described.line); if (described.warning) ui.warn(described.warning); }
|
|
4334
|
+
} catch { /* the line is advice; the launch goes on */ }
|
|
4284
4335
|
const plan = planPodProvider({
|
|
4285
4336
|
codexCandidates: inspectCodexRotation().candidates,
|
|
4286
4337
|
// Per-account caps (대표 default:97) override the Pod default cap — without them default was dropped at 60%.
|
|
@@ -7019,6 +7070,7 @@ missionCmd
|
|
|
7019
7070
|
|
|
7020
7071
|
registerTasksCommands(program);
|
|
7021
7072
|
registerLabelsCommands(program);
|
|
7073
|
+
registerMsgCommands(program);
|
|
7022
7074
|
|
|
7023
7075
|
// ── ask alias (script-friendly one-shot query) ──
|
|
7024
7076
|
program
|
|
@@ -7027,7 +7079,28 @@ program
|
|
|
7027
7079
|
.option('--reuse', 'Reuse the active CLI session instead of creating a new one')
|
|
7028
7080
|
.option('--session <id>', 'Continue an explicit session (id or unique prefix). Overrides --reuse and active session.')
|
|
7029
7081
|
.option('--json', 'Emit a single JSON line {sessionId, provider, model, reply, logPath, budget} instead of streaming text + ui.info trailer. Stable shape for LLM self-spawn.')
|
|
7030
|
-
.
|
|
7082
|
+
.option('--bare', 'Send only this text to the model: no Elanous preamble, project tree, memory, tools or session')
|
|
7083
|
+
.action(async (parts: string[], opts: { reuse?: boolean; session?: string; json?: boolean; bare?: boolean }) => {
|
|
7084
|
+
if (opts.bare) {
|
|
7085
|
+
try {
|
|
7086
|
+
const { askBare } = await import('./cli/ask-bare.js');
|
|
7087
|
+
const llm = await import('./llm.js');
|
|
7088
|
+
const { getUserConfig } = await import('./user-config.js');
|
|
7089
|
+
const { trimToBudget } = await import('./tokens.js');
|
|
7090
|
+
const result = await askBare({ text: parts.join(' '), deps: {
|
|
7091
|
+
getUserConfig, decideProviderForConfig: llm.decideProviderForConfig, getProviderForConfig: llm.getProviderForConfig,
|
|
7092
|
+
streamLLM: llm.streamLLM, trimToBudget,
|
|
7093
|
+
} });
|
|
7094
|
+
if (opts.json) process.stdout.write(JSON.stringify({ sessionId: null, ...result, logPath: null, budget: null, bare: true }) + '\n');
|
|
7095
|
+
else process.stdout.write(result.reply.endsWith('\n') ? result.reply : `${result.reply}\n`);
|
|
7096
|
+
} catch (error) {
|
|
7097
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7098
|
+
if (opts.json) process.stdout.write(JSON.stringify({ error: message, bare: true }) + '\n');
|
|
7099
|
+
else console.error(`ask --bare failed: ${message}`);
|
|
7100
|
+
process.exitCode = 1;
|
|
7101
|
+
}
|
|
7102
|
+
return;
|
|
7103
|
+
}
|
|
7031
7104
|
const cfg = reloadUserConfig();
|
|
7032
7105
|
await runChatTurnCli({
|
|
7033
7106
|
cfg,
|
|
@@ -7193,9 +7266,13 @@ program
|
|
|
7193
7266
|
});
|
|
7194
7267
|
|
|
7195
7268
|
// ── login (provider OAuth) ──
|
|
7196
|
-
export function codexLoginSuccessMessage(mirrorResult?:
|
|
7269
|
+
export function codexLoginSuccessMessage(mirrorResult?: CodexMirrorResult): string {
|
|
7197
7270
|
const prefix = `Signed in. Tokens at ${authStorePath()}.`;
|
|
7198
7271
|
if (mirrorResult === 'written') return `${prefix} Mirrored to ~/.codex/auth.json.`;
|
|
7272
|
+
if (mirrorResult === 'skipped-different-account') {
|
|
7273
|
+
return `${prefix} Your Codex CLI login (~/.codex/auth.json) belongs to a different account — left unchanged. To switch it, run \`elanous login openai-codex --replace-codex-cli-login\`.`;
|
|
7274
|
+
}
|
|
7275
|
+
if (mirrorResult === 'skipped-unknown-account') return `${prefix} Codex CLI login left unchanged.`;
|
|
7199
7276
|
if (mirrorResult === 'not-created-missing-cli-fields') {
|
|
7200
7277
|
return `${prefix} Codex CLI mirror was not created because this login response lacked its required fields; run \`codex login\` once to initialize ~/.codex/auth.json.`;
|
|
7201
7278
|
}
|
|
@@ -7208,17 +7285,33 @@ const loginCmd = program.command('login').description('Authenticate to an LLM pr
|
|
|
7208
7285
|
loginCmd
|
|
7209
7286
|
.command('openai-codex')
|
|
7210
7287
|
.description('Sign in to OpenAI Codex via the ChatGPT device-code flow')
|
|
7211
|
-
.
|
|
7212
|
-
|
|
7288
|
+
.option('--replace-codex-cli-login', 'if the Codex CLI (~/.codex/auth.json) is signed in to a different account, replace it with this login')
|
|
7289
|
+
.action(async (opts: { replaceCodexCliLogin?: boolean }) => {
|
|
7290
|
+
// OB5d — say why there is no browser (ssh · no display) and what to do instead; otherwise try the browser first.
|
|
7291
|
+
const { browserUnavailableReason } = await import('./oauth/browser-availability.js');
|
|
7292
|
+
const noBrowser = browserUnavailableReason();
|
|
7293
|
+
let browserState: Awaited<ReturnType<typeof import('./oauth/codex-browser-login.js')['loginWithCodexBrowser']>> | null = null;
|
|
7294
|
+
if (!noBrowser) {
|
|
7295
|
+
ui.header('OpenAI Codex — 브라우저 로그인');
|
|
7296
|
+
console.log(' 브라우저에서 로그인을 마치세요 — 끝나면 자동으로 이어집니다.');
|
|
7297
|
+
try {
|
|
7298
|
+
const { loginWithCodexBrowser } = await import('./oauth/codex-browser-login.js');
|
|
7299
|
+
browserState = await loginWithCodexBrowser();
|
|
7300
|
+
} catch {
|
|
7301
|
+
console.log(' 브라우저 로그인이 안 됐습니다 — 코드로 이어갑니다.');
|
|
7302
|
+
}
|
|
7303
|
+
}
|
|
7304
|
+
if (!browserState) ui.header('OpenAI Codex — 코드로 로그인');
|
|
7305
|
+
if (noBrowser) console.log(` ${noBrowser}`);
|
|
7213
7306
|
try {
|
|
7214
|
-
const state = await loginWithCodex({
|
|
7307
|
+
const state = browserState ?? await loginWithCodex({
|
|
7215
7308
|
onProgress: (p) => {
|
|
7216
7309
|
if (p.type === 'user_code' && p.userCode) {
|
|
7217
7310
|
console.log('');
|
|
7218
|
-
console.log(` 1)
|
|
7219
|
-
console.log(` 2)
|
|
7311
|
+
console.log(` 1) 아무 브라우저에서 열기: ${p.loginUrl}`);
|
|
7312
|
+
console.log(` 2) 코드 입력: ${p.userCode}`);
|
|
7220
7313
|
console.log('');
|
|
7221
|
-
console.log('
|
|
7314
|
+
console.log(' 로그인을 기다리는 중… (취소: Ctrl+C)');
|
|
7222
7315
|
}
|
|
7223
7316
|
if (p.type === 'polling' && p.pollAttempt === 1) {
|
|
7224
7317
|
process.stdout.write(' .');
|
|
@@ -7233,7 +7326,21 @@ loginCmd
|
|
|
7233
7326
|
}
|
|
7234
7327
|
},
|
|
7235
7328
|
});
|
|
7236
|
-
|
|
7329
|
+
// AUTH1 — another account's Codex CLI login is left alone unless the user says to replace it.
|
|
7330
|
+
let mirrorResult = state.codexMirrorResult;
|
|
7331
|
+
if (mirrorResult === 'skipped-different-account') {
|
|
7332
|
+
let replace = opts.replaceCodexCliLogin === true;
|
|
7333
|
+
if (!replace && process.stdin.isTTY && process.stdout.isTTY) {
|
|
7334
|
+
const { createInterface } = await import('node:readline/promises');
|
|
7335
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
7336
|
+
try {
|
|
7337
|
+
const answer = await rl.question(' Your Codex CLI (~/.codex/auth.json) is signed in to a different account. Replace it with this login? [y/N] ');
|
|
7338
|
+
replace = /^y(es)?$/i.test(answer.trim());
|
|
7339
|
+
} finally { rl.close(); }
|
|
7340
|
+
}
|
|
7341
|
+
if (replace) mirrorResult = saveTokens('openai-codex', state.tokens, { replaceDifferentCodexAccount: true }).codexMirrorResult;
|
|
7342
|
+
}
|
|
7343
|
+
ui.info(codexLoginSuccessMessage(mirrorResult));
|
|
7237
7344
|
ui.info(`Expires in ~${state.tokens.expiresAt ? Math.round((state.tokens.expiresAt - Date.now()) / 60000) : '?'}min; auto-refresh on next use.`);
|
|
7238
7345
|
} catch (err: any) {
|
|
7239
7346
|
ui.error(`login failed: ${err?.message ?? err}`);
|
|
@@ -7821,6 +7928,15 @@ sessionCmd
|
|
|
7821
7928
|
console.log(res.formatted ?? '(no context)');
|
|
7822
7929
|
});
|
|
7823
7930
|
|
|
7931
|
+
async function runFirstSetupForCli(cfg: ReturnType<typeof getUserConfig>, announceFallback = false): Promise<boolean> {
|
|
7932
|
+
if (cfg.onboarding.webFirst === true) {
|
|
7933
|
+
const { runWebFirstSetup } = await import('./onboarding/web-first.js');
|
|
7934
|
+
if (await runWebFirstSetup({ config: cfg }) === 'link-shown') return false;
|
|
7935
|
+
if (announceFallback) ui.info('No config yet — launching setup wizard first.');
|
|
7936
|
+
}
|
|
7937
|
+
return runOnboardingForCli();
|
|
7938
|
+
}
|
|
7939
|
+
|
|
7824
7940
|
async function runOnboardingForCli(): Promise<boolean> {
|
|
7825
7941
|
try {
|
|
7826
7942
|
await runOnboarding();
|
|
@@ -7856,8 +7972,8 @@ program
|
|
|
7856
7972
|
if (opts.tools) announceChatToolsCompatibility();
|
|
7857
7973
|
const cfg = getUserConfig();
|
|
7858
7974
|
if (needsOnboarding(cfg)) {
|
|
7859
|
-
ui.info('No config yet — launching setup wizard first.');
|
|
7860
|
-
if (!await
|
|
7975
|
+
if (cfg.onboarding.webFirst !== true) ui.info('No config yet — launching setup wizard first.');
|
|
7976
|
+
if (!await runFirstSetupForCli(cfg, true)) return;
|
|
7861
7977
|
}
|
|
7862
7978
|
const refreshed = reloadUserConfig();
|
|
7863
7979
|
// ★ 관측갭 수리(2026-07-21·제1원칙·트랙A) — self-implement 자식 goal-loop(`chat --goal-loop`)은 데몬과
|
|
@@ -7923,8 +8039,8 @@ program
|
|
|
7923
8039
|
}
|
|
7924
8040
|
const cfg = getUserConfig();
|
|
7925
8041
|
if (needsOnboarding(cfg)) {
|
|
7926
|
-
ui.info('No config yet — launching setup wizard first.');
|
|
7927
|
-
if (!await
|
|
8042
|
+
if (cfg.onboarding.webFirst !== true) ui.info('No config yet — launching setup wizard first.');
|
|
8043
|
+
if (!await runFirstSetupForCli(cfg, true)) return;
|
|
7928
8044
|
}
|
|
7929
8045
|
const refreshed = reloadUserConfig();
|
|
7930
8046
|
const { runRepl } = await import('./repl/index.js');
|
|
@@ -9725,6 +9841,23 @@ nexusChannelBotCmd
|
|
|
9725
9841
|
process.exit(result.exitCode);
|
|
9726
9842
|
});
|
|
9727
9843
|
|
|
9844
|
+
// EN13 — bring an existing Telegram/Discord bot over from OpenClaw · Hermes · the previous elanous (~/.monad).
|
|
9845
|
+
nexusChannelBotCmd
|
|
9846
|
+
.command('import')
|
|
9847
|
+
.description('Find Telegram/Discord bot settings you already use (OpenClaw, Hermes, previous elanous), preview them with the token masked, and store them after you agree.')
|
|
9848
|
+
.option('--yes', 'Import without asking')
|
|
9849
|
+
.action(async (opts: { yes?: boolean }) => {
|
|
9850
|
+
const { runChannelImport } = await import('./channel-import/run.js');
|
|
9851
|
+
const { createInterface } = await import('node:readline/promises');
|
|
9852
|
+
const ask = process.stdin.isTTY ? async (question: string): Promise<boolean> => {
|
|
9853
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
9854
|
+
try { const answer = (await rl.question(question)).trim(); return answer === '' || /^(y|yes|예|네)$/i.test(answer); }
|
|
9855
|
+
finally { rl.close(); }
|
|
9856
|
+
} : undefined;
|
|
9857
|
+
const result = await runChannelImport({ yes: opts.yes, ...(ask ? { ask } : {}) });
|
|
9858
|
+
process.exit(result.exitCode);
|
|
9859
|
+
});
|
|
9860
|
+
|
|
9728
9861
|
// FU A6-real P5 (2026-05-11) — interactive Firecrawl setup.
|
|
9729
9862
|
// Walks the user through CLI detection + API key entry + persist to
|
|
9730
9863
|
// `registry.discovery.firecrawl.apiKey`. `--api-key <value>` skips
|
|
@@ -10389,6 +10522,14 @@ async function main(): Promise<void> {
|
|
|
10389
10522
|
// elanous --acp-server --transport=unix-socket --socket-path=/tmp/x.sock
|
|
10390
10523
|
// elanous --acp-server --transport=websocket --port=31415
|
|
10391
10524
|
// elanous --acp-server --transport=websocket --no-auth # skip token check
|
|
10525
|
+
if (rawArgs.includes('--acp-server') && rawArgs.includes('--login')) {
|
|
10526
|
+
// EN10a — an ACP client's terminal auth re-launches `elanous --acp-server --login`: run the sign-in in that terminal and exit with its status.
|
|
10527
|
+
const { ACP_LOGIN_SUBCOMMAND, currentLaunch } = await import('./acp/auth-methods.js');
|
|
10528
|
+
const launch = currentLaunch();
|
|
10529
|
+
const { spawnSync } = await import('node:child_process');
|
|
10530
|
+
const run = spawnSync(launch.command, [...launch.args, ...ACP_LOGIN_SUBCOMMAND], { stdio: 'inherit' });
|
|
10531
|
+
process.exit(run.status ?? 1);
|
|
10532
|
+
}
|
|
10392
10533
|
if (rawArgs.includes('--acp-server')) {
|
|
10393
10534
|
const { bootAcpServer, parseAcpBootArgs } = await import('./boot/acp-server.js');
|
|
10394
10535
|
const { createDaemonRuntime } = await import('./boot/daemon-runtime.js');
|
|
@@ -10597,7 +10738,7 @@ async function main(): Promise<void> {
|
|
|
10597
10738
|
// gates on config completeness — no entry-mode branch.)
|
|
10598
10739
|
const cfg = getUserConfig();
|
|
10599
10740
|
if (needsOnboarding(cfg)) {
|
|
10600
|
-
if (!await
|
|
10741
|
+
if (!await runFirstSetupForCli(cfg)) return;
|
|
10601
10742
|
}
|
|
10602
10743
|
|
|
10603
10744
|
// Active-provider banner so users know WHICH model/auth is about to
|
|
@@ -10679,12 +10820,18 @@ async function main(): Promise<void> {
|
|
|
10679
10820
|
* 회귀 방어 = `src/cli-entry.test.ts`(실물 `bin/elanous.mjs` 를 spawn 한다).
|
|
10680
10821
|
*/
|
|
10681
10822
|
export function runCli(): void {
|
|
10682
|
-
main().catch((err) => {
|
|
10823
|
+
main().catch(async (err) => {
|
|
10683
10824
|
closeTui();
|
|
10684
|
-
if (err
|
|
10685
|
-
console.error(
|
|
10825
|
+
if (isCliUserError(err)) {
|
|
10826
|
+
console.error(formatCliUserError(err));
|
|
10686
10827
|
process.exit(1);
|
|
10687
10828
|
}
|
|
10829
|
+
// ER1 — a real crash is reported once (consented · scrubbed · never blocks more than the send timeout).
|
|
10830
|
+
try {
|
|
10831
|
+
const { reportError } = await import('./error-report/report.js');
|
|
10832
|
+
const outcome = await reportError({ code: 'cli-crash', message: err instanceof Error ? `${err.name}: ${err.message}` : String(err), ...(err instanceof Error && err.stack ? { stack: err.stack } : {}), surface: 'cli' });
|
|
10833
|
+
if (outcome.sent) console.error(`오류를 운영팀에 알렸습니다${outcome.reportId ? ` (보고 번호 ${outcome.reportId})` : ''}.`);
|
|
10834
|
+
} catch { /* the crash itself is what matters */ }
|
|
10688
10835
|
throw err;
|
|
10689
10836
|
});
|
|
10690
10837
|
}
|
|
@@ -40,15 +40,23 @@ export function keyEventToTextInsertion(
|
|
|
40
40
|
return preservePrintableText(ev, name);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/** Hangul Compatibility Jamo (ㄱ…ㅣ · ㅋㅋ · ㅠㅠ). The key parser maps a lone jamo keystroke to the QWERTY key
|
|
44
|
+
* on the same position so hotkeys work under the Korean IME — but as TEXT it must stay the jamo the person typed
|
|
45
|
+
* (U1 · 2026-10-02: «ㅋㅋㅋ ㅠㅠ» came out as «zzz bb» in the chat input). */
|
|
46
|
+
const COMPAT_JAMO = /^[\u3131-\u318E]$/;
|
|
47
|
+
|
|
43
48
|
function preservePrintableText(ev: KeyEvent, name: string): string {
|
|
49
|
+
// The chat composer passes the TUI key (original bytes on `raw`); other composers pass a KeyEvent (`sequence`).
|
|
50
|
+
const sequence = ev.sequence ?? (ev as { raw?: string }).raw;
|
|
51
|
+
if (sequence && name.length === 1 && COMPAT_JAMO.test(sequence)) return sequence;
|
|
44
52
|
if (
|
|
45
|
-
|
|
46
|
-
&&
|
|
53
|
+
sequence
|
|
54
|
+
&& sequence.length === 1
|
|
47
55
|
&& name.length === 1
|
|
48
|
-
&&
|
|
49
|
-
&&
|
|
56
|
+
&& sequence !== name
|
|
57
|
+
&& sequence.toLowerCase() === name.toLowerCase()
|
|
50
58
|
) {
|
|
51
|
-
return
|
|
59
|
+
return sequence;
|
|
52
60
|
}
|
|
53
61
|
if (name.length === 1) return ev.shift ? name.toUpperCase() : name;
|
|
54
62
|
return name;
|
package/src/instance/leader.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { INSTALLED_PACKAGE_MARKERS, isInstalledPackagePath } from './installed-package.js';
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, realpathSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
|
-
import { dirname, join, resolve } from 'node:path';
|
|
5
|
+
import { dirname, join, resolve, basename } from 'node:path';
|
|
6
6
|
|
|
7
7
|
export interface LeaderRefusalRecord {
|
|
8
8
|
refusedAt: string;
|
|
@@ -53,10 +53,22 @@ export function normalizeTree(p: string): string {
|
|
|
53
53
|
try { return realpathSync(abs); } catch { return abs; }
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/** npm/Homebrew/nvm `<prefix>/lib/node_modules` · bun `…/install/global/node_modules` · pnpm `…/global/<n>/node_modules`. */
|
|
57
|
+
export function isGlobalNodeModules(dir: string): boolean {
|
|
58
|
+
if (basename(dir) !== 'node_modules') return false;
|
|
59
|
+
const parent = basename(dirname(dir));
|
|
60
|
+
return parent === 'lib' || parent === 'global' || (/^\d+$/.test(parent) && basename(dirname(dirname(dir))) === 'global');
|
|
61
|
+
}
|
|
62
|
+
|
|
56
63
|
export function treeFromScriptPath(scriptPath: string): string | null {
|
|
57
64
|
let dir = dirname(normalizeTree(scriptPath));
|
|
58
65
|
for (let i = 0; i < 30; i++) {
|
|
59
66
|
if (existsSync(join(dir, '.git'))) return dir;
|
|
67
|
+
// A GLOBAL install stops at its node_modules: a git repo around the install prefix (Homebrew's /opt/homebrew
|
|
68
|
+
// is one; so is a dotfiles-managed home) is not this code's source tree. Without this stop `npm i -g` under
|
|
69
|
+
// Homebrew ran as a «source tree» test universe writing config to /opt/homebrew/.elanous-test (OB3 · 10-01).
|
|
70
|
+
// A project-local <checkout>/node_modules/elanous still resolves to the checkout (the existing design).
|
|
71
|
+
if (isGlobalNodeModules(dir)) return null;
|
|
60
72
|
const parent = dirname(dir);
|
|
61
73
|
if (parent === dir) return null;
|
|
62
74
|
dir = parent;
|
|
@@ -131,7 +131,7 @@ export function signalsFromSnapshot(stars: number, prev: StarSnapshot | undefine
|
|
|
131
131
|
return { stars, starsDelta, starsPerDay: starsDelta / span };
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
function
|
|
134
|
+
export function appendGithubStarSnapshots(root: string, rows: StarSnapshot[]): void {
|
|
135
135
|
if (!rows.length) return;
|
|
136
136
|
mkdirSync(intakeLedgerDir(root), { recursive: true });
|
|
137
137
|
appendFileSync(githubStarsFile(root), rows.map((r) => JSON.stringify(r)).join('\n') + '\n');
|
|
@@ -154,6 +154,8 @@ export interface CollectGithubOpts {
|
|
|
154
154
|
/** 스냅숏·비교의 «오늘». 생략하면 UTC 날짜. */
|
|
155
155
|
day?: string;
|
|
156
156
|
now?: () => Date;
|
|
157
|
+
/** 등록 원천이 질의 하나만 수집할 때; 생략 시 기존 관심 질의 전부. */
|
|
158
|
+
queries?: readonly string[];
|
|
157
159
|
}
|
|
158
160
|
|
|
159
161
|
/**
|
|
@@ -173,7 +175,7 @@ export async function collectGithubStars(
|
|
|
173
175
|
const found: GithubStarRepo[] = [];
|
|
174
176
|
// «급상승»은 최근에 생긴 저장소 중 별 순이다 — 전체 기간 별 순이면 활발한 거대 저장소가 매일 같은 목록으로 나온다(2026-09-26 검토).
|
|
175
177
|
const windowStart = new Date(Date.parse(`${day}T00:00:00.000Z`) - days * 86_400_000).toISOString().slice(0, 10);
|
|
176
|
-
for (const query of GITHUB_STAR_QUERIES) {
|
|
178
|
+
for (const query of opts.queries ?? GITHUB_STAR_QUERIES) {
|
|
177
179
|
const rows = await search(`${query} created:>=${windowStart}`, perQuery);
|
|
178
180
|
const recent = rows.filter((r) => isRecentRepo(r, day, days));
|
|
179
181
|
queries.push({ query, received: recent.length });
|
|
@@ -208,7 +210,7 @@ export async function collectGithubStars(
|
|
|
208
210
|
day, days, perQuery, dryRun: !!opts.dryRun, queries, repos, raws: raws.length,
|
|
209
211
|
};
|
|
210
212
|
if (!opts.dryRun) {
|
|
211
|
-
|
|
213
|
+
appendGithubStarSnapshots(root, repos.map((row) => ({ day, repo: row.repo, stars: row.stars })));
|
|
212
214
|
result.ingest = ingestIntakeItems(root, 'github', raws);
|
|
213
215
|
}
|
|
214
216
|
debug.log('intake.collect', 'github-stars', {
|
|
@@ -60,14 +60,26 @@ export async function collectTelegramSaved(root: string, fetch: FetchSavedMessag
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/** GramJS 사용자 세션으로 `me` 대화를 읽는 실제 구현. 자격이 없으면 이유를 담아 던진다(값은 싣지 않는다). */
|
|
63
|
-
|
|
63
|
+
type GramjsModules = { TelegramClient: typeof import('telegram').TelegramClient; StringSession: typeof import('telegram/sessions').StringSession };
|
|
64
|
+
const loadGramjs = async (): Promise<GramjsModules> => ({
|
|
65
|
+
TelegramClient: (await import('telegram')).TelegramClient,
|
|
66
|
+
StringSession: (await import('telegram/sessions')).StringSession,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export async function gramjsFetchSaved(
|
|
70
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
71
|
+
load: () => Promise<GramjsModules> = loadGramjs,
|
|
72
|
+
): Promise<{ fetch: FetchSavedMessages; close: () => Promise<void> }> {
|
|
64
73
|
const apiId = Number(env.TELEGRAM_API_ID ?? 0);
|
|
65
74
|
const apiHash = env.TELEGRAM_API_HASH ?? '';
|
|
66
75
|
const session = env.TELEGRAM_USER_SESSION ?? '';
|
|
67
76
|
const missing = [!apiId && 'TELEGRAM_API_ID', !apiHash && 'TELEGRAM_API_HASH', !session && 'TELEGRAM_USER_SESSION'].filter(Boolean);
|
|
68
77
|
if (missing.length) throw new Error(`텔레그램 사용자 세션 자격이 없다: ${missing.join(' · ')} (docs/manual/MANUAL-telegram-unmanned-test-2026-07-21.md §1~§3)`);
|
|
69
|
-
|
|
70
|
-
|
|
78
|
+
// `telegram` is an optional dependency: its native websocket helpers have no Linux ARM64 build, so npm may leave it out.
|
|
79
|
+
let modules: GramjsModules;
|
|
80
|
+
try { modules = await load(); }
|
|
81
|
+
catch { throw new Error('텔레그램 사용자 세션 모듈(telegram)이 이 설치에 없다 — 선택 의존이라 Linux ARM64 등에서는 빠진다(npm i -g telegram 으로 따로 깔 수 있다)'); }
|
|
82
|
+
const { TelegramClient, StringSession } = modules;
|
|
71
83
|
const client = new TelegramClient(new StringSession(session), apiId, apiHash, { connectionRetries: 3 });
|
|
72
84
|
client.setLogLevel('error' as never); // 연결 로그가 표준출력을 채우지 않게
|
|
73
85
|
await client.connect();
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { parseSeatAddress, resolveSeat } from '../seat-address/seat-address.js';
|
|
2
|
+
import {
|
|
3
|
+
submitIntakeWork,
|
|
4
|
+
type SubmitIntakeWorkDeps,
|
|
5
|
+
} from './submit-intake-work.js';
|
|
6
|
+
|
|
7
|
+
export interface DiscordSeatWorkMessage {
|
|
8
|
+
channelId: string;
|
|
9
|
+
messageId: string;
|
|
10
|
+
threadId?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface DiscordSeatWorkDeps extends SubmitIntakeWorkDeps {
|
|
14
|
+
submit?: typeof submitIntakeWork;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Addressed Discord work goes through the graph intake door, not the chat turn. */
|
|
18
|
+
export async function handleDiscordSeatWork(
|
|
19
|
+
text: string,
|
|
20
|
+
msg: DiscordSeatWorkMessage,
|
|
21
|
+
deps: DiscordSeatWorkDeps = {},
|
|
22
|
+
): Promise<string | null> {
|
|
23
|
+
const address = parseSeatAddress(text);
|
|
24
|
+
if (!address) return null;
|
|
25
|
+
|
|
26
|
+
const seats = address.seats.map((name) => ({ name, seat: resolveSeat(name) }));
|
|
27
|
+
const unknown = seats.filter(({ seat }) => !seat).map(({ name }) => `@${name}`);
|
|
28
|
+
if (unknown.length) return `어느 좌석을 말씀하시나요? ${unknown.join(', ')}은(는) 등록된 좌석이 아닙니다. 좌석을 확인해 다시 보내 주세요.`;
|
|
29
|
+
const body = address.body.trim();
|
|
30
|
+
if (!body) return '어떤 일을 맡길까요? 좌석 주소 뒤에 요청 내용을 적어 다시 보내 주세요.';
|
|
31
|
+
|
|
32
|
+
const reportTo = {
|
|
33
|
+
channel: 'discord' as const,
|
|
34
|
+
channelId: msg.channelId,
|
|
35
|
+
...(msg.threadId ? { discordThreadId: msg.threadId } : {}),
|
|
36
|
+
};
|
|
37
|
+
const replies: string[] = [];
|
|
38
|
+
for (const { seat } of seats) {
|
|
39
|
+
if (!seat) continue;
|
|
40
|
+
const label = seat.title ?? seat.id;
|
|
41
|
+
const result = await (deps.submit ?? submitIntakeWork)({
|
|
42
|
+
text: `@${label} ${body}`,
|
|
43
|
+
track: 'graph',
|
|
44
|
+
origin: {
|
|
45
|
+
kind: 'external', ledgerSource: 'memo', provider: 'other',
|
|
46
|
+
ref: `discord:${msg.channelId}:${msg.messageId}`, reportTo,
|
|
47
|
+
},
|
|
48
|
+
}, deps);
|
|
49
|
+
if (result.ok && result.track === 'graph') {
|
|
50
|
+
replies.push(`@${label} 접수번호: ${result.acceptanceId}`);
|
|
51
|
+
} else {
|
|
52
|
+
replies.push(`@${label} 접수 실패 — ${result.ok ? '접수번호가 없습니다' : result.reason.split('\n')[0]!.slice(0, 200)}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return replies.join('\n');
|
|
56
|
+
}
|