elanous 0.2.10 → 0.2.12
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/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/-6XrAoD3eU7NyMHAE4xPS/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1147-466ec15afacc1a65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1394-ee3795b112907122.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
- package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3869-3cd46526879f454c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
- package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
- package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
- package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7277-0b2fc7c16ba2d64b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7758-0b018a9e4fc56200.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
- package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8605-0259994816604c49.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9920-5cfdc5e8fd209825.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-cb169620945d1952.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cefe8169e36cf62a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-d2e35228bc497119.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-5c05b0da4bc1392c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e0ccdb576812b523.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-813c4a52c9d05ca8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-4731f2c215358937.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a022b257950f39e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-a2ffc717e04b8b0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-b59ee4e70fc18fcf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a67e11ba962337b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-c172dabd796eb7a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-1efd0cb9e0ed9d13.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-d5dc7ff69a37b4cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-e71c84189e8c683e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-1d6a533ce5a6efcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-dfca9b7d2de0b135.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-793fa536b3a6ef37.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-6dd3bfbbde2a5c2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-490653e8d4cc8852.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-77447356baad75d2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-29e961191f6057df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-c822f55b884d9104.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fa4ccfc432424e52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-6d604227e1664b71.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-9c7e8f744a765daf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-4048543b4b7ad5e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-4c3a3126abed551a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-64b0aecb1ca75e75.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4292d0149020e8a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-db14d0be7f1c460c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-e5d8072cd7cfef73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-9547b5cec7cf76bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-e6dcb83265530636.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-45248f08d6aecae5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-2cddeb9e2aeedc55.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-e297866051595d81.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-baba2e047872fb0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-e895da4ec9cac345.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4344faf20216233b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-698bb29f11864b89.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-bd6a6dc1ddc273f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-2e9e2fb01c9da1c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d62ceb13411ebba4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2ea96958-e8c7e112de50b067.js → f48170cc-d05d28bf87a43bf4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +1 -0
- package/apps/pwa/out/_next/static/css/128fb7fb670b2fbf.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -0
- package/apps/pwa/out/inside/index.txt +31 -0
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -0
- package/apps/pwa/out/outputs/index.txt +30 -0
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -24
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -24
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/context/nightly-condense.yaml +21 -0
- package/graphs/context/recipes.yaml +12 -0
- package/graphs/demo/inside-seed.yaml +20 -0
- package/graphs/demo/recipes.yaml +12 -0
- package/graphs/drafts/draft-cleanup.yaml +19 -0
- package/graphs/drafts/recipes.yaml +23 -0
- package/graphs/intake/intake-daily.yaml +2 -1
- package/graphs/ops/recipes.yaml +3 -0
- package/graphs/ops/secret-exposure.yaml +24 -0
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +4 -1
- package/graphs/video/explainer-line.yaml +2 -2
- package/package.json +2 -1
- package/plugins/card-followup/examples/sample-card.png +0 -0
- package/plugins/elanous-hwp/README.md +25 -0
- package/plugins/elanous-hwp/cli.ts +22 -0
- package/plugins/elanous-hwp/converter.ts +237 -0
- package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
- package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
- package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
- package/plugins/elanous-hwp/plugin.json +16 -0
- package/plugins/elanous-hwp/plugin.ts +40 -0
- package/scripts/ci-public-export-leak-gate.ts +75 -14
- package/scripts/ci-public-leak-gate.ts +44 -9
- package/scripts/context-hooks/claude-stop.sh +4 -0
- package/scripts/context-hooks/emit.ts +24 -0
- package/scripts/context-hooks/post-tool-use.sh +4 -0
- package/scripts/coord-channel-watch.sh +12 -0
- package/scripts/coord-requests-bridge.ts +143 -0
- package/scripts/field-feed/lib.ts +4 -0
- package/scripts/fleet/node-setup.sh +20 -3
- package/scripts/homebrew-formula-bump.ts +69 -0
- package/scripts/lib/telegram-inject-args.ts +31 -0
- package/scripts/marketing/measure-site-numbers.ts +169 -0
- package/scripts/measure-gate-shards.ts +309 -0
- package/scripts/measure-pod-memory-by-goal.ts +130 -0
- package/scripts/mission-request-judge.ts +31 -1
- package/scripts/morning-report.ts +2 -2
- package/scripts/opportunity-scan.ts +1 -1
- package/scripts/release-loop/auto-approve-node.ts +21 -4
- package/scripts/release-loop/checklist-gate-node.ts +2 -1
- package/scripts/release-loop/cut-branch.ts +84 -0
- package/scripts/release-loop/gate-node.ts +22 -15
- package/scripts/release-loop/mac-smoke-node.ts +229 -0
- package/scripts/release-loop/node-verdict.ts +3 -3
- package/scripts/release-loop/ops-upgrade-node.ts +47 -6
- package/scripts/release-loop/publish-node.ts +4 -1
- package/scripts/release-loop/tui-node-checks.ts +42 -0
- package/scripts/release-loop/tui-sim-node.ts +32 -8
- package/scripts/release-loop/unattended-release.ts +5 -3
- package/scripts/release-loop/version-node.ts +74 -13
- package/scripts/signal-digest-cycle.ts +2 -7
- package/scripts/signal-digest-photo.ts +11 -0
- package/scripts/tech1-public-measure.ts +94 -0
- package/scripts/telegram-inject.ts +14 -6
- package/scripts/test-diet/node.ts +1 -1
- package/scripts/test-diet/remeasure-list.ts +112 -0
- package/scripts/tui-regress.ts +2 -2
- package/scripts/ux/demo-rehearsal.ts +247 -0
- package/scripts/ux/demo-seed.ts +108 -0
- package/scripts/ux/lib/rehearsal-verdict.ts +80 -0
- package/skills/diagram-master/SKILL.md +366 -0
- package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
- package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
- package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
- package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
- package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
- package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
- package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
- package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
- package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
- package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
- package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
- package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
- package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
- package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
- package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
- package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
- package/skills/diagram-master/references/examples/README.md +69 -0
- package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
- package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
- package/skills/diagram-master/references/pyproject.toml +16 -0
- package/skills/diagram-master/references/quality-checklist.md +33 -0
- package/skills/diagram-master/references/routing-guide.md +164 -0
- package/skills/diagram-master/references/uv.lock +1356 -0
- package/skills/google-workspace/SKILL.md +33 -0
- package/skills/google-workspace/scripts/gws-safe.sh +177 -0
- package/skills/grill-me/SKILL.md +1 -1
- package/skills/lecture-note-digitizer/SKILL.md +926 -0
- package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
- package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
- package/skills/lecture-note-digitizer/references/html-template.md +167 -0
- package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
- package/skills/omni-crawl/SKILL.md +21 -11
- package/skills/omni-crawl/scripts/main.ts +6 -6
- package/skills/omni-crawl/src/router.ts +3 -3
- package/skills/omni-digest/SKILL.md +17 -9
- package/skills/omni-digest/digest.md +2 -2
- package/skills/omni-digest/src/fetch.ts +30 -3
- package/skills/pitch-deck/SKILL.md +2 -2
- package/skills/pitch-deck/template.html +2 -2
- package/skills/youtube-master/SKILL.md +163 -0
- package/skills/youtube-master/package-lock.json +558 -0
- package/skills/youtube-master/package.json +13 -0
- package/skills/youtube-master/references/study-note-template.md +124 -0
- package/skills/youtube-master/scripts/main.ts +435 -0
- package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
- package/skills/youtube-master/src/audio.ts +63 -0
- package/skills/youtube-master/src/domain-staging.ts +50 -0
- package/skills/youtube-master/src/env.ts +36 -0
- package/skills/youtube-master/src/obsidian.ts +155 -0
- package/skills/youtube-master/src/router.ts +110 -0
- package/skills/youtube-master/src/stt.ts +199 -0
- package/skills/youtube-master/src/study-note.ts +175 -0
- package/skills/youtube-master/src/summarize.ts +358 -0
- package/skills/youtube-master/src/transcript.ts +76 -0
- package/skills/youtube-master/src/types.ts +91 -0
- package/skills/youtube-master/src/util.ts +93 -0
- package/skills/youtube-master/src/youtube.ts +70 -0
- package/skills/youtube-master/tsconfig.json +13 -0
- package/src/acp/server.ts +5 -2
- package/src/agent-mission/driver.ts +215 -23
- package/src/agent-mission/pty-decision.ts +71 -0
- package/src/agent-mission/review-loop.ts +30 -0
- package/src/autopilot/build/llm-conflict-merge.ts +16 -3
- package/src/autopilot/pty-control-loop.ts +4 -1
- package/src/autopilot/tool-registry.ts +2 -0
- package/src/boot/daemon-prompt-turn.ts +5 -0
- package/src/boot/daemon-runtime.ts +9 -3
- package/src/boot/daemon-tools/web-search.ts +3 -0
- package/src/card-followup/core.ts +109 -0
- package/src/chat/index.ts +2 -0
- package/src/cli/drive-input-jail.ts +101 -0
- package/src/cli/hooks-cli.ts +17 -3
- package/src/cli/make-cli.ts +43 -0
- package/src/cli/persona-cli.ts +98 -9
- package/src/cli/plugin-cli.ts +31 -22
- package/src/cli/pod-cli.ts +36 -9
- package/src/cli/pod-memory-advice.ts +35 -0
- package/src/cli/pr-cli.ts +51 -15
- package/src/cli/pty-drive-cli.ts +41 -7
- package/src/cli/pty-drive-verdict.ts +40 -0
- package/src/cli/release-cli.ts +63 -10
- package/src/cli/setup-cli.ts +43 -1
- package/src/cli/skills-cli.ts +17 -1
- package/src/context-bus/claude-hooks-install.ts +10 -0
- package/src/context-bus/context-now-surfaces.ts +65 -0
- package/src/context-bus/context-now.ts +104 -0
- package/src/context-bus/coord-events.ts +2 -2
- package/src/context-bus/external-events.ts +52 -0
- package/src/context-bus/long-term-memory.ts +108 -0
- package/src/context-bus/nightly-condense.ts +153 -0
- package/src/context-bus/session-events.ts +35 -0
- package/src/dashboard/dashboard-status-lines.ts +2 -0
- package/src/dashboard/index.ts +17 -4
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +31 -1
- package/src/decisions/decision-cards.ts +10 -3
- package/src/decisions/decision-ledger.ts +13 -5
- package/src/discord/sprint21-runtime.ts +5 -1
- package/src/discord-self-message.ts +32 -0
- package/src/discord-slash-wire.ts +5 -1
- package/src/discord.ts +17 -1
- package/src/domains/core-tools.ts +3 -2
- package/src/domains/outbound-alert.ts +105 -32
- package/src/domains/outbound-log-probe.ts +8 -0
- package/src/domains/telegram-kind-route.ts +51 -13
- package/src/exec-requests/default-outputs.ts +25 -0
- package/src/exec-requests/planner.ts +10 -2
- package/src/exec-requests/runner.ts +20 -6
- package/src/exec-requests/store.ts +3 -0
- package/src/execution-loop/launch-gate.ts +109 -0
- package/src/field/field-reel.ts +5 -1
- package/src/field-note/index.ts +201 -0
- package/src/field-note/telegram.ts +142 -0
- package/src/field-note/transcribe.ts +248 -0
- package/src/graph-kinds/registry.ts +3 -3
- package/src/graph-runner/graph-cli.ts +61 -1
- package/src/graph-runner/graph-grow-llm.ts +47 -0
- package/src/graph-runner/graph-grow.ts +50 -0
- package/src/graph-runner/runner.ts +329 -33
- package/src/grok/agent-search.ts +8 -2
- package/src/guardian/secret-exposure-scan.ts +101 -0
- package/src/harness/harness-cli-command.ts +375 -13
- package/src/harness/harness-pod-dispatch.ts +43 -23
- package/src/harness/harness-seams.ts +38 -4
- package/src/harness/harness-stop.ts +23 -4
- package/src/harness/launch-registry.ts +91 -0
- package/src/harness/process-garbage.ts +5 -3
- package/src/hooks/consult-intake.ts +153 -0
- package/src/hooks/dispatch.ts +82 -0
- package/src/hooks/expose.ts +254 -0
- package/src/hooks/github-shadow.ts +108 -0
- package/src/hooks/providers.ts +71 -5
- package/src/hooks/queue.ts +1 -1
- package/src/hooks/receiver.ts +94 -16
- package/src/index.ts +76 -14
- package/src/intake-plane/categorize.ts +18 -46
- package/src/intake-plane/discord-seat-work.ts +38 -2
- package/src/intake-plane/front-route-classifier.ts +33 -39
- package/src/intake-plane/persona-answer.ts +30 -0
- package/src/intake-plane/runtime-callables.ts +8 -1
- package/src/intake-plane/telegram-seat-work.ts +36 -2
- package/src/intake-plane/wish-card.ts +33 -0
- package/src/intake-plane/wish-folder.ts +67 -0
- package/src/intent-gate/gate.ts +30 -10
- package/src/live/detail-switch.ts +5 -0
- package/src/llm/difficulty.ts +57 -0
- package/src/llm/judge-layer.ts +101 -0
- package/src/llm/mission-router.ts +33 -19
- package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
- package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
- package/src/loops/contract/examples/steward.loop.yaml +50 -0
- package/src/loops/contract/loop-agent.schema.json +138 -0
- package/src/loops/contract/validate.ts +64 -0
- package/src/loops/registry.ts +20 -6
- package/src/market/signed-index.ts +4 -0
- package/src/maturity/bot-command-maturity.ts +45 -0
- package/src/maturity/feature-maturity.ts +27 -4
- package/src/model-tier/index.ts +2 -2
- package/src/model-tier/tier-resolver.ts +20 -20
- package/src/model-tier/types.ts +6 -6
- package/src/mss/logging/log-store.ts +15 -0
- package/src/nexus/api/config-model-tier.ts +5 -4
- package/src/nexus/api/fabric-plans.ts +53 -0
- package/src/nexus/api/harness-api.ts +5 -1
- package/src/nexus/api/health.ts +2 -0
- package/src/nexus/api/http-server.ts +67 -8
- package/src/nexus/api/inside-events.ts +226 -0
- package/src/nexus/api/meta-api.ts +21 -8
- package/src/nexus/api/missions.ts +6 -1
- package/src/nexus/api/ops-seats.ts +33 -0
- package/src/nexus/api/outbound-report.ts +40 -7
- package/src/nexus/api/outputs-route.ts +44 -0
- package/src/nexus/api/personas.ts +95 -53
- package/src/nexus/api/seat-requests.ts +44 -2
- package/src/nexus/api/sessions-store.ts +17 -38
- package/src/nexus/api/sub-seat-charters.ts +34 -0
- package/src/nexus/api/tabs-mutations.ts +3 -1
- package/src/nexus/api/task-cards-api.ts +19 -0
- package/src/nexus/api/trace.ts +18 -6
- package/src/nexus/api/workflow-history.ts +88 -0
- package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
- package/src/nexus/api/workflows.ts +132 -6
- package/src/nexus/index.ts +2 -0
- package/src/nexus/kinds/webterm.ts +2 -1
- package/src/nexus/outbound/delivery-ledger.ts +17 -8
- package/src/nexus/outbound/router.ts +8 -3
- package/src/nexus/webterm/pty.ts +6 -2
- package/src/onboarding/cli-auth-status.ts +80 -0
- package/src/onboarding/voice-ai.ts +3 -3
- package/src/org/seat-budget.ts +48 -0
- package/src/org/stall-escalation.ts +63 -0
- package/src/outputs/ledger.ts +120 -0
- package/src/persona/persona-todo.ts +79 -0
- package/src/persona/presets.ts +123 -2
- package/src/persona/team-set.ts +155 -0
- package/src/plugins/install/plugin-install.ts +14 -0
- package/src/plugins/maker/market-bundle.ts +110 -0
- package/src/plugins/maker/plugin-maker.ts +254 -11
- package/src/plugins/maker/wizard-generate.ts +103 -0
- package/src/pod-lease/admission.ts +150 -0
- package/src/pod-lease/dependency-state.ts +85 -0
- package/src/pod-lease/host-lease.ts +127 -0
- package/src/project/project-suggestion.ts +16 -0
- package/src/project/session-context.ts +24 -0
- package/src/release-loop/checklist.ts +17 -5
- package/src/release-loop/feature-store.ts +29 -13
- package/src/release-loop/landed-but-yellow.ts +48 -0
- package/src/release-loop/next-md-merge.ts +58 -0
- package/src/release-loop/release-note.ts +59 -4
- package/src/seat-dispatch/seat-ask.ts +130 -0
- package/src/seat-dispatch/seat-questions.ts +100 -0
- package/src/seat-loop/seat-loop.ts +709 -29
- package/src/seat-loop/seat-report.ts +37 -2
- package/src/self-dev/dev-cli.ts +4 -1
- package/src/self-dev/dev-pipeline.ts +37 -1
- package/src/self-dev/draft-sweep.ts +79 -40
- package/src/self-dev/draft-triage-rules.ts +62 -7
- package/src/self-dev/fabric-plan-core.ts +297 -0
- package/src/self-dev/orchestrate.ts +36 -4
- package/src/self-dev/release-path-guard.ts +62 -0
- package/src/self-dev/shard-aggregate.ts +230 -0
- package/src/self-dev/shard-placement.ts +60 -0
- package/src/self-dev/shard-plan.ts +48 -0
- package/src/self-dev/shard-pod-run.ts +77 -0
- package/src/self-dev/shard-run.ts +105 -0
- package/src/self-implement/budget-gate.ts +29 -12
- package/src/self-implement/gate-baseline.ts +1 -1
- package/src/self-implement/gate-candidate-ranking.ts +60 -0
- package/src/self-implement/gate-cli.ts +40 -1
- package/src/self-implement/gate-scope.ts +44 -13
- package/src/self-implement/graph-variant.ts +171 -0
- package/src/self-implement/harness-policy-gates.ts +1 -1
- package/src/self-implement/headless-elanous-driver.ts +27 -3
- package/src/self-implement/host-regate.ts +22 -1
- package/src/self-implement/importer-test-index.ts +2 -1
- package/src/self-implement/l8-merge-queue.ts +130 -0
- package/src/self-implement/orchestrator.ts +257 -9
- package/src/self-implement/route-consumer-test-index.ts +122 -0
- package/src/self-implement/seams.ts +72 -11
- package/src/self-implement/test-seams.ts +2 -0
- package/src/self-implement/uncommitted-work.ts +59 -0
- package/src/session/index.ts +36 -13
- package/src/skills/gift-install.ts +215 -0
- package/src/skills/tools/web-search.ts +4 -1
- package/src/steward/launch.ts +42 -26
- package/src/steward/steward-cards.ts +17 -9
- package/src/steward/triage.ts +46 -14
- package/src/task-cards/card-cli.ts +25 -1
- package/src/task-orchestrator/mission.ts +5 -0
- package/src/task-orchestrator/store.ts +12 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +43 -17
- package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
- package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +222 -40
- package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
- package/src/task-orchestrator/types.ts +2 -0
- package/src/telegram-card-followup.ts +16 -96
- package/src/telegram-commands.ts +31 -1
- package/src/telegram-project-command.ts +145 -0
- package/src/telegram-report.ts +21 -17
- package/src/telegram.ts +61 -8
- package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
- package/src/user-config.ts +110 -24
- package/src/version/packed-revision.json +1 -1
- package/src/web-search/grok.ts +7 -1
- package/src/web-search/index.ts +28 -1
- package/src/web-search/provider.ts +4 -0
- package/src/web-search/x-intent.ts +5 -0
- package/src/workflow-runtime/executor.ts +277 -47
- package/src/workflow-runtime/index.ts +1 -0
- package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
- package/src/workflow-runtime/plugin-kind-node.ts +1 -1
- package/src/workflow-runtime/schema.ts +79 -4
- package/src/workflow-runtime/types.ts +35 -4
- package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
- package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
- package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
- package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
- package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
- package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
- /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → -6XrAoD3eU7NyMHAE4xPS}/_ssgManifest.js +0 -0
package/src/telegram.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
25
25
|
import { buildTurnOutputTextBlocks } from './input/turn-output-block.js';
|
|
26
26
|
import { selectTurnOutputTextForSink } from './input/turn-output-sink-registry.js';
|
|
27
27
|
import { debug } from './debug/log.js';
|
|
28
|
+
import { botAudienceFor, filterBotCommands, readBotAudience } from './maturity/bot-command-maturity.js';
|
|
28
29
|
import { resolveChannelBotToken } from './channel-bot-token.js';
|
|
29
30
|
import type { TelegramVoiceAdapter } from './voice/channel-adapters/telegram-voice-adapter.js';
|
|
30
31
|
import { createTelegramSurfaceHitl, type TelegramSurfaceHitl } from './hitl/telegram-surface-hitl.js';
|
|
@@ -67,11 +68,15 @@ import { runUrlRoute } from './skills/url-route-exec.js';
|
|
|
67
68
|
import { recordRoutedLinkAbsorbed } from './intake-plane/link-ledger.js';
|
|
68
69
|
import { classifyFrontInput } from './intake-plane/front-classifier.js';
|
|
69
70
|
import { handleTelegramSeatWork, type TelegramSeatWorkDeps } from './intake-plane/telegram-seat-work.js';
|
|
71
|
+
import { deliverSeatAnswers } from './seat-dispatch/seat-ask.js';
|
|
70
72
|
import { effectiveInstanceRoot } from './instance/resolve.js';
|
|
71
73
|
import { getElanousConfigDir } from './elanous-config-dir.js';
|
|
72
74
|
import { defaultFieldEvent, FieldUploadError, parseFieldCaption, resolveFieldMime, saveFieldMedia } from './field/field-media.js';
|
|
73
75
|
import { scheduleFieldReel, type FieldReelOptions } from './field/field-reel.js';
|
|
76
|
+
import { handleTelegramFieldNote } from './field-note/telegram.js';
|
|
77
|
+
import type { TranscriptionEngine, FieldAudio } from './field-note/transcribe.js';
|
|
74
78
|
import { maybeHandleCardPhoto, type CardPhotoDeps } from './telegram-card-followup.js';
|
|
79
|
+
import { attachTelegramProjectButtons } from './telegram-project-command.js';
|
|
75
80
|
|
|
76
81
|
export type TgAttachmentKind = 'photo' | 'voice' | 'audio' | 'document';
|
|
77
82
|
|
|
@@ -99,6 +104,8 @@ export interface TgIncoming {
|
|
|
99
104
|
text: string;
|
|
100
105
|
messageId: number;
|
|
101
106
|
threadId?: number;
|
|
107
|
+
/** Telegram message timestamp, not poll time. */
|
|
108
|
+
receivedAt?: string;
|
|
102
109
|
isDm: boolean;
|
|
103
110
|
isGroup: boolean;
|
|
104
111
|
/** Zero or more attached media — populated by parseUpdate from
|
|
@@ -217,6 +224,9 @@ export interface TelegramBotOpts {
|
|
|
217
224
|
fieldRootDir?: () => string;
|
|
218
225
|
/** 시험에서는 실제 렌더 대신 가짜 실행기를 주입한다. */
|
|
219
226
|
fieldReel?: FieldReelOptions;
|
|
227
|
+
/** NOTE3a engine and audio decoder are injected; no transcription provider is assumed. */
|
|
228
|
+
fieldNoteEngine?: TranscriptionEngine;
|
|
229
|
+
fieldNoteDecodeAudio?: (file: string, recordedAt: string) => FieldAudio;
|
|
220
230
|
/** Test seam for the business-card graph and its private run root. */
|
|
221
231
|
cardFollowupDeps?: Pick<CardPhotoDeps, 'runGraph' | 'rootDir' | 'ocrText'>;
|
|
222
232
|
}
|
|
@@ -276,7 +286,7 @@ export function classifyTelegramText(
|
|
|
276
286
|
|
|
277
287
|
export class TelegramBot {
|
|
278
288
|
private readonly token: string;
|
|
279
|
-
|
|
289
|
+
readonly botId: string;
|
|
280
290
|
private readonly allowedUsers: Set<number>;
|
|
281
291
|
private readonly onMessage: TelegramBotOpts['onMessage'];
|
|
282
292
|
private readonly fetchImpl: typeof fetch;
|
|
@@ -336,8 +346,11 @@ export class TelegramBot {
|
|
|
336
346
|
private readonly fieldDefaultEventOpt?: string;
|
|
337
347
|
private readonly fieldRootDir: () => string;
|
|
338
348
|
private readonly fieldReel?: FieldReelOptions;
|
|
349
|
+
private readonly fieldNoteEngine?: TranscriptionEngine;
|
|
350
|
+
private readonly fieldNoteDecodeAudio?: (file: string, recordedAt: string) => FieldAudio;
|
|
339
351
|
private readonly cardFollowupDeps: Pick<CardPhotoDeps, 'runGraph' | 'rootDir' | 'ocrText'>;
|
|
340
352
|
private readonly seatWorkDeps: TelegramSeatWorkDeps;
|
|
353
|
+
private seatAskTimer: ReturnType<typeof setInterval> | null = null;
|
|
341
354
|
/** 앨범 id → `#현장` 행사 · 답장 디바운스. 태그된 앨범만 들어온다. */
|
|
342
355
|
private readonly fieldGroups = new Map<string, {
|
|
343
356
|
event: string; mode?: 'instant'; at: number; chatId: number; threadId?: number; replyTo: number; count: number;
|
|
@@ -372,8 +385,18 @@ export class TelegramBot {
|
|
|
372
385
|
this.fieldDefaultEventOpt = opts.fieldDefaultEvent;
|
|
373
386
|
this.fieldRootDir = opts.fieldRootDir ?? getElanousConfigDir;
|
|
374
387
|
this.fieldReel = opts.fieldReel;
|
|
388
|
+
this.fieldNoteEngine = opts.fieldNoteEngine;
|
|
389
|
+
this.fieldNoteDecodeAudio = opts.fieldNoteDecodeAudio;
|
|
375
390
|
this.cardFollowupDeps = opts.cardFollowupDeps ?? {};
|
|
376
|
-
this.seatWorkDeps = opts.seatWorkDeps
|
|
391
|
+
this.seatWorkDeps = { ...opts.seatWorkDeps, askDeps: { ...opts.seatWorkDeps?.askDeps,
|
|
392
|
+
channel: 'telegram', botId: this.botId,
|
|
393
|
+
send: opts.seatWorkDeps?.askDeps?.send ?? (async (origin, text) => {
|
|
394
|
+
if (origin.channel !== 'telegram') throw new Error('seat ask belongs to another surface');
|
|
395
|
+
const posted = await this.sendMessage(Number(origin.chatId), text, { replyTo: origin.messageId, threadId: origin.threadId });
|
|
396
|
+
if (!posted) throw new Error('Telegram seat ask reply was not posted');
|
|
397
|
+
}),
|
|
398
|
+
} };
|
|
399
|
+
|
|
377
400
|
if (opts.onTriggerTap) {
|
|
378
401
|
// Assign through `as unknown` to bypass `readonly` + private —
|
|
379
402
|
// the tap is set once at construction and never reassigned.
|
|
@@ -1120,6 +1143,9 @@ export class TelegramBot {
|
|
|
1120
1143
|
async start(): Promise<void> {
|
|
1121
1144
|
this.running = true;
|
|
1122
1145
|
this.log(`telegram bot starting (allowlist size ${this.allowedUsers.size})`);
|
|
1146
|
+
this.seatAskTimer = setInterval(() => {
|
|
1147
|
+
void deliverSeatAnswers(this.seatWorkDeps.askDeps!).catch((error) => this.log(`seat ask delivery failed: ${String(error)}`));
|
|
1148
|
+
}, 10_000);
|
|
1123
1149
|
if (this.allowedUsers.size === 0) this.log('telegram.owner-gate empty-allowlist');
|
|
1124
1150
|
|
|
1125
1151
|
// Publish the slash-command menu to Telegram. Clients pick up the
|
|
@@ -1128,9 +1154,16 @@ export class TelegramBot {
|
|
|
1128
1154
|
// still processes `/commands` via the incoming-message dispatch
|
|
1129
1155
|
// path, users just don't get the autocomplete.
|
|
1130
1156
|
if (this.slashCommands.length > 0) {
|
|
1157
|
+
const audience = this.slashContext
|
|
1158
|
+
? readBotAudience((this.slashContext.userConfig.raw?.telegram as { commandAudience?: unknown } | undefined)?.commandAudience)
|
|
1159
|
+
: botAudienceFor('telegram');
|
|
1160
|
+
const commands = filterBotCommands('telegram', this.slashCommands, audience);
|
|
1161
|
+
debug.log('telegram.command', 'menu-filtered', {
|
|
1162
|
+
total: this.slashCommands.length, shown: commands.length, ...audience,
|
|
1163
|
+
});
|
|
1131
1164
|
try {
|
|
1132
1165
|
const result = await this.apiCall<unknown>('setMyCommands', {
|
|
1133
|
-
commands: toTelegramBotCommands(
|
|
1166
|
+
commands: toTelegramBotCommands(commands),
|
|
1134
1167
|
});
|
|
1135
1168
|
debug.log('telegram.command', 'published', { success: true, result });
|
|
1136
1169
|
this.log(`telegram: setMyCommands published (${String(result)})`);
|
|
@@ -1151,6 +1184,7 @@ export class TelegramBot {
|
|
|
1151
1184
|
const CONFLICT_BACKOFF_CAP = 60_000;
|
|
1152
1185
|
while (this.running) {
|
|
1153
1186
|
try {
|
|
1187
|
+
await deliverSeatAnswers(this.seatWorkDeps.askDeps!);
|
|
1154
1188
|
const wantCallbackQuery = this.callbackHandlers.size > 0;
|
|
1155
1189
|
const wantReaction = this.reactionHandlers.size > 0;
|
|
1156
1190
|
// allowed_updates 는 명시한 것만 받으므로 등록된 핸들러 종류만 추가(비파괴 — 핸들러
|
|
@@ -1192,6 +1226,7 @@ export class TelegramBot {
|
|
|
1192
1226
|
userId: cq.from.id,
|
|
1193
1227
|
userName: cq.from.username ?? cq.from.first_name,
|
|
1194
1228
|
chatId: cq.message?.chat.id,
|
|
1229
|
+
threadId: cq.message?.message_thread_id,
|
|
1195
1230
|
messageId: cq.message?.message_id,
|
|
1196
1231
|
data: cq.data ?? '',
|
|
1197
1232
|
};
|
|
@@ -1292,7 +1327,11 @@ export class TelegramBot {
|
|
|
1292
1327
|
this.log('telegram bot stopped');
|
|
1293
1328
|
}
|
|
1294
1329
|
|
|
1295
|
-
stop(): void {
|
|
1330
|
+
stop(): void {
|
|
1331
|
+
this.running = false;
|
|
1332
|
+
if (this.seatAskTimer) clearInterval(this.seatAskTimer);
|
|
1333
|
+
this.seatAskTimer = null;
|
|
1334
|
+
}
|
|
1296
1335
|
|
|
1297
1336
|
/** Download + normalize this message's attachments into the shape
|
|
1298
1337
|
* the ACP content-blocks module consumes. Called lazily by slash
|
|
@@ -1502,6 +1541,13 @@ export class TelegramBot {
|
|
|
1502
1541
|
}
|
|
1503
1542
|
// 현장 업로드 — `#현장` 캡션(또는 태그된 앨범의 나머지)의 사진·영상은 LLM 대신 현장 폴더로.
|
|
1504
1543
|
if (await this.tryHandleFieldUpload(ctx)) return;
|
|
1544
|
+
if (await handleTelegramFieldNote(ctx, {
|
|
1545
|
+
rootDir: this.fieldRootDir(),
|
|
1546
|
+
download: (fileId) => this.downloadFile(fileId),
|
|
1547
|
+
reply: async (incoming, text) => { await this.sendMessage(incoming.chatId, text, { replyTo: incoming.messageId, threadId: incoming.threadId }); },
|
|
1548
|
+
engine: this.fieldNoteEngine, decodeAudio: this.fieldNoteDecodeAudio,
|
|
1549
|
+
now: () => new Date(this.nowImpl()),
|
|
1550
|
+
})) return;
|
|
1505
1551
|
if (await maybeHandleCardPhoto(ctx, {
|
|
1506
1552
|
isOwner: (userId) => this.isOwnerAllowed(userId),
|
|
1507
1553
|
isFieldAlbum: (id) => this.fieldGroups.has(id),
|
|
@@ -1801,6 +1847,7 @@ export class TelegramBot {
|
|
|
1801
1847
|
const reply = await slashParse.cmd.handler(slashParse.args, ctx, {
|
|
1802
1848
|
userConfig: this.slashContext.userConfig,
|
|
1803
1849
|
allCommands: this.slashCommands,
|
|
1850
|
+
sendButtons: async (text, buttons) => { await this.sendInlineKeyboard(ctx.chatId, text, buttons, { replyTo: ctx.messageId, threadId: ctx.threadId }); },
|
|
1804
1851
|
downloadAttachments: () => this.downloadCtxAttachments(ctx),
|
|
1805
1852
|
daemonBridge: this.slashContext.daemonBridge,
|
|
1806
1853
|
hitlConfirmChannel: this.hitlConfirmChannelForChat(ctx.chatId, ctx.threadId),
|
|
@@ -1985,6 +2032,7 @@ export class TelegramBot {
|
|
|
1985
2032
|
return await slashParse.cmd.handler(slashParse.args, ctx, {
|
|
1986
2033
|
userConfig: this.slashContext!.userConfig,
|
|
1987
2034
|
allCommands: this.slashCommands,
|
|
2035
|
+
sendButtons: async (text, buttons) => { await this.sendInlineKeyboard(ctx.chatId, text, buttons, { replyTo: ctx.messageId, threadId: ctx.threadId }); },
|
|
1988
2036
|
streamer,
|
|
1989
2037
|
downloadAttachments: () => this.downloadCtxAttachments(ctx),
|
|
1990
2038
|
daemonBridge: this.slashContext!.daemonBridge,
|
|
@@ -2004,6 +2052,7 @@ export class TelegramBot {
|
|
|
2004
2052
|
return await runAcpViaSlash(activeBackend, [ctx.text], ctx, {
|
|
2005
2053
|
userConfig: this.slashContext!.userConfig,
|
|
2006
2054
|
allCommands: this.slashCommands,
|
|
2055
|
+
sendButtons: async (text, buttons) => { await this.sendInlineKeyboard(ctx.chatId, text, buttons, { replyTo: ctx.messageId, threadId: ctx.threadId }); },
|
|
2007
2056
|
streamer,
|
|
2008
2057
|
downloadAttachments: () => this.downloadCtxAttachments(ctx),
|
|
2009
2058
|
daemonBridge: this.slashContext!.daemonBridge,
|
|
@@ -2244,6 +2293,7 @@ interface RawUpdate {
|
|
|
2244
2293
|
update_id: number;
|
|
2245
2294
|
message?: {
|
|
2246
2295
|
message_id: number;
|
|
2296
|
+
date?: number;
|
|
2247
2297
|
from?: { id: number; first_name?: string; username?: string };
|
|
2248
2298
|
chat: { id: number; type: 'private' | 'group' | 'supergroup' | 'channel' };
|
|
2249
2299
|
text?: string;
|
|
@@ -2260,7 +2310,7 @@ interface RawUpdate {
|
|
|
2260
2310
|
callback_query?: {
|
|
2261
2311
|
id: string;
|
|
2262
2312
|
from: { id: number; first_name?: string; username?: string };
|
|
2263
|
-
message?: { message_id: number; chat: { id: number } };
|
|
2313
|
+
message?: { message_id: number; message_thread_id?: number; chat: { id: number } };
|
|
2264
2314
|
data?: string;
|
|
2265
2315
|
chat_instance?: string;
|
|
2266
2316
|
};
|
|
@@ -2279,6 +2329,7 @@ export interface TgCallbackQuery {
|
|
|
2279
2329
|
userId: number;
|
|
2280
2330
|
userName?: string;
|
|
2281
2331
|
chatId?: number;
|
|
2332
|
+
threadId?: number;
|
|
2282
2333
|
messageId?: number;
|
|
2283
2334
|
data: string;
|
|
2284
2335
|
}
|
|
@@ -2371,6 +2422,7 @@ export function parseUpdate(u: RawUpdate): TgIncoming | null {
|
|
|
2371
2422
|
text: (typeof m.text === 'string' ? m.text : (m.caption ?? '')),
|
|
2372
2423
|
messageId: m.message_id,
|
|
2373
2424
|
threadId: m.message_thread_id,
|
|
2425
|
+
...(typeof m.date === 'number' ? { receivedAt: new Date(m.date * 1000).toISOString() } : {}),
|
|
2374
2426
|
isDm,
|
|
2375
2427
|
isGroup: !isDm,
|
|
2376
2428
|
attachments,
|
|
@@ -2886,9 +2938,10 @@ export function botFromConfig(opts: BotFromConfigOpts): TelegramBot {
|
|
|
2886
2938
|
botRef.ensureSurfaceHitl();
|
|
2887
2939
|
// DEC-TG(대표 10-02) — decision cards on the MAIN bot only (other channel pollers carry other tokens). The ticker
|
|
2888
2940
|
// itself sends only while this bot polls, so a send-only nexus bot never duplicates the standalone poller's cards.
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2941
|
+
const mainToken = resolveChannelBotToken('telegram', opts.userConfig)?.token;
|
|
2942
|
+
if (mainToken && botToken === mainToken) {
|
|
2943
|
+
attachTelegramProjectButtons(botRef, opts.userConfig);
|
|
2944
|
+
if (opts.userConfig.raw?.decisions === undefined || (opts.userConfig.raw.decisions as { cards?: unknown }).cards !== false) {
|
|
2892
2945
|
const bot = botRef;
|
|
2893
2946
|
void import('./decisions/telegram-decision-cards.js')
|
|
2894
2947
|
.then(({ attachTelegramDecisionCards }) => { attachTelegramDecisionCards(bot, opts.userConfig); })
|
|
@@ -11,6 +11,7 @@ export const SELF_COGNITION_TOOL_NAMES = [
|
|
|
11
11
|
'logs_query',
|
|
12
12
|
'ops_status',
|
|
13
13
|
'memory_recall',
|
|
14
|
+
'context_now',
|
|
14
15
|
] as const;
|
|
15
16
|
|
|
16
17
|
type SelfCognitionToolName = (typeof SELF_COGNITION_TOOL_NAMES)[number];
|
|
@@ -23,7 +24,14 @@ function coreTools(): CoreToolsModule {
|
|
|
23
24
|
return require('../domains/core-tools.js') as CoreToolsModule;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
export const CONTEXT_NOW_SPEC: LLMToolSpec = {
|
|
28
|
+
name: 'context_now',
|
|
29
|
+
description: '지금 무엇이 돌고 있는지 릴리스 칸·열린 결정·자리 원장·최근 맥락 이벤트의 출처 있는 요약을 읽는다. 원문 대화는 반환하지 않는다.',
|
|
30
|
+
parameters: { type: 'object', properties: { topic: { type: 'string', description: '칸 id·제목 또는 이벤트 요약에 들어 있는 낱말(선택).' } }, required: [] },
|
|
31
|
+
};
|
|
32
|
+
|
|
26
33
|
function coreSpec(name: SelfCognitionToolName): LLMToolSpec {
|
|
34
|
+
if (name === 'context_now') return CONTEXT_NOW_SPEC;
|
|
27
35
|
const spec = coreTools().CORE_TOOL_SPECS.find(candidate => candidate.name === name);
|
|
28
36
|
if (!spec) throw new Error(`Missing core tool spec for self-cognition runtime '${name}'`);
|
|
29
37
|
return spec;
|
|
@@ -193,9 +201,11 @@ export const SELF_COGNITION_RUNTIMES: readonly ToolRuntime[] = SELF_COGNITION_TO
|
|
|
193
201
|
get spec() {
|
|
194
202
|
return coreSpec(name);
|
|
195
203
|
},
|
|
196
|
-
run: async (args, ctx) => name === '
|
|
197
|
-
?
|
|
198
|
-
:
|
|
204
|
+
run: async (args, ctx) => name === 'context_now'
|
|
205
|
+
? (await import('../context-bus/context-now.js')).contextNow({ ...(typeof args.topic === 'string' ? { topic: args.topic } : {}) })
|
|
206
|
+
: name === 'memory_recall' || name === 'self_recall'
|
|
207
|
+
? runRecall(name, args, ctx)
|
|
208
|
+
: toToolRunResult(await coreTools().buildCoreTools().dispatch(name, args)),
|
|
199
209
|
}));
|
|
200
210
|
|
|
201
211
|
/** MCP catalog metadata derived from the same name ledger as the runtimes. */
|
package/src/user-config.ts
CHANGED
|
@@ -50,7 +50,7 @@ import type { SkillTier } from './skills/runner.js';
|
|
|
50
50
|
import { sharedAgentSkillRoots } from './skills/shared-agent-skill-roots.js';
|
|
51
51
|
import {
|
|
52
52
|
isModelTier,
|
|
53
|
-
|
|
53
|
+
isModelTierProfile,
|
|
54
54
|
type BudgetUserConfig,
|
|
55
55
|
type ModelTier,
|
|
56
56
|
type ModelTierUserConfig,
|
|
@@ -450,6 +450,8 @@ export interface SkillSource {
|
|
|
450
450
|
export interface SkillsConfig {
|
|
451
451
|
activeSet: SkillSetName;
|
|
452
452
|
dirs: string[];
|
|
453
|
+
/** Gift redemption API origin; defaults to https://elanous.ai. */
|
|
454
|
+
giftEndpoint?: string;
|
|
453
455
|
/** Include the existing shared ~/.agents/skills directory. Default true; false opts out. */
|
|
454
456
|
includeSharedAgentSkills?: boolean;
|
|
455
457
|
/**
|
|
@@ -766,6 +768,7 @@ function skillsDefaults(): SkillsConfig {
|
|
|
766
768
|
return {
|
|
767
769
|
activeSet: 'claudecode',
|
|
768
770
|
dirs: d ? [d] : [],
|
|
771
|
+
giftEndpoint: 'https://elanous.ai',
|
|
769
772
|
includeSharedAgentSkills: true,
|
|
770
773
|
allow: [],
|
|
771
774
|
deny: [],
|
|
@@ -912,8 +915,8 @@ export interface TelegramConfig {
|
|
|
912
915
|
/** 누가 Q&A 폴링을 하나 — 기본(없음·`'nexus'`)은 넥서스 데몬, `'standalone'` 이면
|
|
913
916
|
* 넥서스는 폴링하지 않고 `elanous telegram run` 이 맡는다. */
|
|
914
917
|
poller?: 'nexus' | 'standalone';
|
|
915
|
-
/**
|
|
916
|
-
*
|
|
918
|
+
/** 레거시 kind→역할 설정(읽기 호환). 선택한 채널의 봇이 kind 정책의
|
|
919
|
+
* 운영/매매 경계를 지킬 때만 발송 라우팅에 적용한다. */
|
|
917
920
|
kindRoles?: Record<string, string>;
|
|
918
921
|
/** `#현장` 캡션에 행사 슬러그가 없을 때 쓸 기본 행사(예: `marketers-night-2026-10`). 없으면 `field-<로컬 날짜>`. */
|
|
919
922
|
fieldDefaultEvent?: string;
|
|
@@ -2023,7 +2026,12 @@ function parseModelTierFieldOrUndefined(v: unknown): ModelTier | undefined {
|
|
|
2023
2026
|
function parseModelTierConfig(raw: unknown): ModelTierUserConfig | undefined {
|
|
2024
2027
|
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
|
|
2025
2028
|
const r = raw as Record<string, unknown>;
|
|
2026
|
-
|
|
2029
|
+
// Compatibility is read-only: the normalized config and subsequent writes use profile.
|
|
2030
|
+
let profile = isModelTierProfile(r.profile) ? r.profile : undefined;
|
|
2031
|
+
if (r.profile === undefined && r.persona !== undefined) {
|
|
2032
|
+
debug.log('config', 'deprecated-key', { from: 'modelTier.persona', to: 'modelTier.profile' });
|
|
2033
|
+
if (isModelTierProfile(r.persona)) profile = r.persona;
|
|
2034
|
+
}
|
|
2027
2035
|
const preset = typeof r.preset === 'string' && r.preset.trim().length > 0
|
|
2028
2036
|
? r.preset.trim()
|
|
2029
2037
|
: undefined;
|
|
@@ -2057,7 +2065,7 @@ function parseModelTierConfig(raw: unknown): ModelTierUserConfig | undefined {
|
|
|
2057
2065
|
const embedding = parseModelTierFieldOrUndefined(r.embedding);
|
|
2058
2066
|
const vision = parseModelTierFieldOrUndefined(r.vision);
|
|
2059
2067
|
const out: ModelTierUserConfig = {
|
|
2060
|
-
...spreadIfDefined('
|
|
2068
|
+
...spreadIfDefined('profile', profile),
|
|
2061
2069
|
...spreadIfDefined('preset', preset),
|
|
2062
2070
|
...spreadIfDefined('voice', voice),
|
|
2063
2071
|
...spreadIfDefined('llm', llm),
|
|
@@ -3232,7 +3240,7 @@ export interface AutoReviewConfig {
|
|
|
3232
3240
|
};
|
|
3233
3241
|
}
|
|
3234
3242
|
|
|
3235
|
-
export type ModelRole = 'implement' | 'review' | 'research' | 'planning' | 'audit' | 'classify';
|
|
3243
|
+
export type ModelRole = 'implement' | 'review' | 'research' | 'planning' | 'audit' | 'classify' | 'graph-grow';
|
|
3236
3244
|
|
|
3237
3245
|
export interface RoleModelConfig {
|
|
3238
3246
|
implement?: string;
|
|
@@ -3241,6 +3249,7 @@ export interface RoleModelConfig {
|
|
|
3241
3249
|
planning?: string;
|
|
3242
3250
|
audit?: string;
|
|
3243
3251
|
classify?: string;
|
|
3252
|
+
'graph-grow'?: string;
|
|
3244
3253
|
}
|
|
3245
3254
|
|
|
3246
3255
|
/** Sparse provider-agnostic model tier preferences by execution role. */
|
|
@@ -3307,6 +3316,7 @@ export const ROLE_MODEL_DEFAULTS: Record<ModelRole, { environment: string; tier:
|
|
|
3307
3316
|
planning: { environment: 'ELANOUS_SKILL_PLAN_MODEL', tier: 'best' },
|
|
3308
3317
|
audit: { environment: 'ELANOUS_MEMORY_JUDGE_MODEL', tier: 'better' },
|
|
3309
3318
|
classify: { environment: 'ELANOUS_ACTION_CLASSIFIER_MODEL', tier: 'budget' },
|
|
3319
|
+
'graph-grow': { environment: 'ELANOUS_GRAPH_GROW_MODEL', tier: 'better' },
|
|
3310
3320
|
};
|
|
3311
3321
|
|
|
3312
3322
|
/** Resolve `auto` through the same runtime provider selector that dispatches LLM calls.
|
|
@@ -3429,7 +3439,9 @@ export interface RoleLlmResolveOptions {
|
|
|
3429
3439
|
* ⛔ 아무 override 도 없으면 ③~⑥ 만 타므로 산출이 종전과 «같다»(§4f 불변식 · NL 진입 무변경). */
|
|
3430
3440
|
export function resolveRoleLlm(role: ModelRole, opts: RoleLlmResolveOptions = {}): RoleLlmResolution {
|
|
3431
3441
|
const config = opts.config ?? getUserConfig();
|
|
3432
|
-
|
|
3442
|
+
// 전역 provider 는 필요할 때만 푼다 — 역할이 provider 를 명시했으면 전역 provider 가 없어도 해석된다.
|
|
3443
|
+
let activeProvider: LLMProviderName | undefined;
|
|
3444
|
+
const globalProvider = (): LLMProviderName => (activeProvider ??= resolveActiveProvider(config));
|
|
3433
3445
|
// 명시 인자가 있으면 그것이 진실 — 없을 때만 발사 시점에 정해진 값을 읽는다(둘 다 source='flag').
|
|
3434
3446
|
const flagSpec = (opts.overrides ?? launchRoleLlmOverrides)?.[role];
|
|
3435
3447
|
const layers: ReadonlyArray<readonly [RoleLlmSpec | undefined, RoleLlmSource]> = [
|
|
@@ -3438,7 +3450,7 @@ export function resolveRoleLlm(role: ModelRole, opts: RoleLlmResolveOptions = {}
|
|
|
3438
3450
|
];
|
|
3439
3451
|
for (const [spec, source] of layers) {
|
|
3440
3452
|
if (!spec) continue;
|
|
3441
|
-
const provider = spec.provider ?? globalProvider;
|
|
3453
|
+
const provider = spec.provider ?? globalProvider();
|
|
3442
3454
|
const pinned = spec.model?.trim();
|
|
3443
3455
|
let resolution: RoleLlmResolution | undefined;
|
|
3444
3456
|
if (pinned) resolution = { model: pinned, provider, ...(spec.tier ? { tier: spec.tier } : {}), source };
|
|
@@ -3447,7 +3459,7 @@ export function resolveRoleLlm(role: ModelRole, opts: RoleLlmResolveOptions = {}
|
|
|
3447
3459
|
if (resolution) { observeRoleLlm(role, resolution, spec); return resolution; }
|
|
3448
3460
|
// 세 칸이 «다 비었으면» 아래 층으로 흘린다 — 빈 칸은 선언이 아니다.
|
|
3449
3461
|
}
|
|
3450
|
-
const baseline = resolveRoleLlmBaseline(role, config, globalProvider);
|
|
3462
|
+
const baseline = resolveRoleLlmBaseline(role, config, globalProvider());
|
|
3451
3463
|
if (opts.overrides || launchRoleLlmOverrides || config.roleLlm?.[role]) observeRoleLlm(role, baseline, flagSpec);
|
|
3452
3464
|
return baseline;
|
|
3453
3465
|
}
|
|
@@ -3463,17 +3475,49 @@ export function resolveRoleModel(role: ModelRole, config: UserConfig = getUserCo
|
|
|
3463
3475
|
}
|
|
3464
3476
|
|
|
3465
3477
|
|
|
3478
|
+
export type StewardLoopMode = 'off' | 'shadow' | 'live';
|
|
3479
|
+
|
|
3466
3480
|
export type SeatLoopMode = 'off' | 'shadow' | 'on';
|
|
3467
3481
|
|
|
3482
|
+
export interface PersonaLoopConfig { enabled: boolean }
|
|
3483
|
+
|
|
3468
3484
|
export interface SeatLoopConfig {
|
|
3469
3485
|
/** No seat actions by default; shadow observes without execution, on permits the seat loop to act. */
|
|
3470
3486
|
mode: SeatLoopMode;
|
|
3487
|
+
/** Seat-to-seat and human questions default to shadow even when the checklist loop is on. */
|
|
3488
|
+
questions?: 'shadow' | 'on';
|
|
3471
3489
|
seats?: string[];
|
|
3472
3490
|
podPool?: string;
|
|
3473
3491
|
reportPr?: number;
|
|
3492
|
+
/** Parent routing and age limits for checklist stalls; omitted values use findStalls defaults. */
|
|
3493
|
+
stall?: { parents?: Record<string, string>; redMinutes?: number; blockedMinutes?: number };
|
|
3494
|
+
}
|
|
3495
|
+
|
|
3496
|
+
export type EventSeat = 'OP' | 'TC' | 'MK' | 'UX';
|
|
3497
|
+
export interface EventRoute { source: 'linear' | 'asana' | 'github'; kind: string; seat: EventSeat; loop: 'seat' }
|
|
3498
|
+
export interface EventsConfig { mode: 'shadow' | 'on'; routes: EventRoute[]; linearAssignees: Record<string, EventSeat> }
|
|
3499
|
+
|
|
3500
|
+
export function parseEventsConfig(input: unknown): EventsConfig {
|
|
3501
|
+
const events = input && typeof input === 'object' && !Array.isArray(input) ? input as Record<string, unknown> : {};
|
|
3502
|
+
const routes: EventRoute[] = [];
|
|
3503
|
+
const linearAssignees: Record<string, EventSeat> = Object.create(null);
|
|
3504
|
+
if (events.linearAssignees && typeof events.linearAssignees === 'object' && !Array.isArray(events.linearAssignees)) {
|
|
3505
|
+
for (const [id, seat] of Object.entries(events.linearAssignees)) {
|
|
3506
|
+
if (id.trim() && (seat === 'OP' || seat === 'TC' || seat === 'MK' || seat === 'UX')) linearAssignees[id] = seat;
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
if (Array.isArray(events.routes)) for (const value of events.routes) {
|
|
3510
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) continue;
|
|
3511
|
+
const route = value as Record<string, unknown>;
|
|
3512
|
+
if ((route.source === 'linear' || route.source === 'asana' || route.source === 'github') && typeof route.kind === 'string' && route.kind.trim()
|
|
3513
|
+
&& (route.seat === 'OP' || route.seat === 'TC' || route.seat === 'MK' || route.seat === 'UX') && route.loop === 'seat')
|
|
3514
|
+
routes.push({ source: route.source, kind: route.kind, seat: route.seat, loop: route.loop });
|
|
3515
|
+
}
|
|
3516
|
+
return { mode: events.mode === 'on' ? 'on' : 'shadow', routes, linearAssignees };
|
|
3474
3517
|
}
|
|
3475
3518
|
|
|
3476
3519
|
export interface UserConfig {
|
|
3520
|
+
events?: EventsConfig;
|
|
3477
3521
|
/** Explicit HTTPS destination for doctor diagnostics; absent means no upload. */
|
|
3478
3522
|
diagnostics?: { uploadUrl?: string };
|
|
3479
3523
|
/** Root CLI help audience; absent or invalid means owner. */
|
|
@@ -3482,12 +3526,14 @@ export interface UserConfig {
|
|
|
3482
3526
|
hitl?: { executionDeadlineMinutes?: number };
|
|
3483
3527
|
coo?: { linearProject?: string };
|
|
3484
3528
|
decisions?: { linearProjection: { enabled: boolean } };
|
|
3529
|
+
/** Per-seat goal and Pod limits; missing or invalid limits use seat-budget defaults. */
|
|
3530
|
+
org?: { budget?: Record<string, { dailyGoals?: number; concurrentPods?: number }> };
|
|
3485
3531
|
/** Steward and seat loops are parsed independently. An absent seat remains off. */
|
|
3486
|
-
loops?: { steward?: { mode?:
|
|
3532
|
+
loops?: { steward?: { mode?: StewardLoopMode; linearTeam?: string; roles?: Record<string, { maxConcurrent?: number }>; budget?: number; tracks?: Record<string, string>; alertAfterFailures?: number; launch?: 'off' | 'shadow' | 'live'; maxParallel?: number; podPool?: string }; seat?: SeatLoopConfig; persona?: PersonaLoopConfig };
|
|
3487
3533
|
/** 🔐 Pod 의 Grok API 키 과금은 명시 opt-in 만. 생략·잘못된 값은 false.
|
|
3488
3534
|
* budgetGate 와 같은 `harness` 객체다 — 중복 선언이면 뒤 타입이 앞을 지운다. */
|
|
3489
|
-
harness?: { pod?: { grokApiKeyOptIn: boolean }; budgetGate?: HarnessBudgetGateConfig; defaultRepo?: string; substrate?: 'local' | 'pod'; podPool?: string; worktreeAddTimeoutSec?: number };
|
|
3490
|
-
/** ☸️ Pod 실행 칸 — `pool` = 기존 기본 풀(`컨텍스트[@ssh호스트][:상한]` 쉼표 · 앞이 우선). harness 실행은 인자·ELANOUS_POD_POOL·harness.podPool 다음으로 읽는다. */
|
|
3535
|
+
harness?: { pod?: { grokApiKeyOptIn: boolean }; budgetGate?: HarnessBudgetGateConfig; difficultyPlacement?: boolean; defaultRepo?: string; substrate?: 'local' | 'pod'; podPool?: string; worktreeAddTimeoutSec?: number };
|
|
3536
|
+
/** ☸️ Pod 실행 칸 — `pool` = 기존 기본 풀(`컨텍스트[@ssh호스트][:상한][#k3d-레지스트리:포트]` 쉼표 · 앞이 우선). harness 실행은 인자·ELANOUS_POD_POOL·harness.podPool 다음으로 읽는다. */
|
|
3491
3537
|
pod?: { pool?: string; /** 호스트 Git 미러 디렉터리 — Pod Job 에 읽기 전용으로 마운트한다. */ hostMirror?: string; /** 원격 그라운딩 엔드포인트(호스트 nexus · tailnet 주소) — Pod 가 토큰으로 «질의→인용»만 묻는다(P13). */ groundingUrl?: string; /** 읽기 전용 Pod lease 권장에 쓰는 계정별 동시 수. */ lease?: { perAccount?: number } };
|
|
3492
3538
|
skillRouter: SkillRouterConfig;
|
|
3493
3539
|
llm: LLMConfig;
|
|
@@ -3656,7 +3702,7 @@ export function parseRoleLlmEntry(raw: unknown): { ok: true; spec: RoleLlmSpec }
|
|
|
3656
3702
|
return { ok: true, spec };
|
|
3657
3703
|
}
|
|
3658
3704
|
|
|
3659
|
-
export const MODEL_ROLES: readonly ModelRole[] = ['implement', 'review', 'research', 'planning', 'audit', 'classify'];
|
|
3705
|
+
export const MODEL_ROLES: readonly ModelRole[] = ['implement', 'review', 'research', 'planning', 'audit', 'classify', 'graph-grow'];
|
|
3660
3706
|
|
|
3661
3707
|
export function isModelRole(v: unknown): v is ModelRole {
|
|
3662
3708
|
return typeof v === 'string' && (MODEL_ROLES as readonly string[]).includes(v);
|
|
@@ -3815,7 +3861,7 @@ function defaultConfig(): UserConfig {
|
|
|
3815
3861
|
cli: { helpRole: 'owner' },
|
|
3816
3862
|
coo: { linearProject: '외부 행정·큰 일 (COO)' },
|
|
3817
3863
|
decisions: { linearProjection: { enabled: false } },
|
|
3818
|
-
loops: { seat: { mode: 'off', seats: ['MK'], podPool: 'pool-node-b@node-b:8' } },
|
|
3864
|
+
loops: { steward: { mode: 'shadow' }, seat: { mode: 'off', questions: 'shadow', seats: ['MK'], podPool: 'pool-node-b@node-b:8' }, persona: { enabled: false } },
|
|
3819
3865
|
skillRouter: { ...SR_DEFAULTS },
|
|
3820
3866
|
llm: { ...LLM_DEFAULTS },
|
|
3821
3867
|
skills: skillsDefaults(),
|
|
@@ -3884,7 +3930,7 @@ function defaultConfig(): UserConfig {
|
|
|
3884
3930
|
nativeStructure: { ...TOOLS_DEFAULTS.nativeStructure },
|
|
3885
3931
|
selfImplement: { ...TOOLS_DEFAULTS.selfImplement },
|
|
3886
3932
|
},
|
|
3887
|
-
harness: { budgetGate: { ...DEFAULT_BUDGET_GATE } },
|
|
3933
|
+
harness: { budgetGate: { ...DEFAULT_BUDGET_GATE }, difficultyPlacement: false },
|
|
3888
3934
|
grounding: { sources: [] },
|
|
3889
3935
|
raw: {},
|
|
3890
3936
|
};
|
|
@@ -4296,7 +4342,7 @@ function parseStewardTracks(input: unknown): Record<string, string> | undefined
|
|
|
4296
4342
|
}
|
|
4297
4343
|
|
|
4298
4344
|
function parseSeatLoopsConfig(input: unknown): SeatLoopConfig {
|
|
4299
|
-
const defaults: SeatLoopConfig = { mode: 'off', seats: ['MK'], podPool: 'pool-node-b@node-b:8' };
|
|
4345
|
+
const defaults: SeatLoopConfig = { mode: 'off', questions: 'shadow', seats: ['MK'], podPool: 'pool-node-b@node-b:8' };
|
|
4300
4346
|
if (!input || typeof input !== 'object' || Array.isArray(input)) return defaults;
|
|
4301
4347
|
const seat = (input as Record<string, unknown>).seat;
|
|
4302
4348
|
if (!seat || typeof seat !== 'object' || Array.isArray(seat)) return defaults;
|
|
@@ -4304,20 +4350,35 @@ function parseSeatLoopsConfig(input: unknown): SeatLoopConfig {
|
|
|
4304
4350
|
const mode = values.mode;
|
|
4305
4351
|
return {
|
|
4306
4352
|
mode: mode === 'on' || mode === 'shadow' ? mode : 'off',
|
|
4353
|
+
questions: values.questions === 'on' ? 'on' : 'shadow',
|
|
4307
4354
|
seats: Array.isArray(values.seats) && values.seats.length > 0
|
|
4308
4355
|
&& values.seats.every((value) => typeof value === 'string' && /^(?:MK|OP|TC|UX)$/.test(value))
|
|
4309
4356
|
? [...new Set(values.seats as string[])] : ['MK'],
|
|
4310
4357
|
podPool: typeof values.podPool === 'string' && values.podPool.trim() ? values.podPool.trim() : defaults.podPool,
|
|
4311
4358
|
...(typeof values.reportPr === 'number' && Number.isSafeInteger(values.reportPr) && values.reportPr > 0
|
|
4312
4359
|
? { reportPr: values.reportPr } : {}),
|
|
4360
|
+
...(() => {
|
|
4361
|
+
const stall = values.stall;
|
|
4362
|
+
if (!stall || typeof stall !== 'object' || Array.isArray(stall)) return {};
|
|
4363
|
+
const raw = stall as Record<string, unknown>;
|
|
4364
|
+
const parents = raw.parents && typeof raw.parents === 'object' && !Array.isArray(raw.parents)
|
|
4365
|
+
? Object.fromEntries(Object.entries(raw.parents).filter(([from, to]) =>
|
|
4366
|
+
/^(?:MK|OP|TC|UX)$/.test(from) && typeof to === 'string' && /^(?:MK|OP|TC|UX)$/.test(to) && from !== to))
|
|
4367
|
+
: undefined;
|
|
4368
|
+
const minutes = (value: unknown): value is number => typeof value === 'number' && Number.isFinite(value) && value >= 0;
|
|
4369
|
+
return { stall: {
|
|
4370
|
+
...(parents ? { parents } : {}),
|
|
4371
|
+
...(minutes(raw.redMinutes) ? { redMinutes: raw.redMinutes } : {}),
|
|
4372
|
+
...(minutes(raw.blockedMinutes) ? { blockedMinutes: raw.blockedMinutes } : {}),
|
|
4373
|
+
} };
|
|
4374
|
+
})(),
|
|
4313
4375
|
};
|
|
4314
4376
|
}
|
|
4315
4377
|
|
|
4316
4378
|
function parseStewardLoopsConfig(input: unknown): UserConfig['loops'] {
|
|
4317
|
-
|
|
4318
|
-
const value =
|
|
4319
|
-
|
|
4320
|
-
const s = value as Record<string, unknown>;
|
|
4379
|
+
const loops = input && typeof input === 'object' && !Array.isArray(input) ? input as Record<string, unknown> : {};
|
|
4380
|
+
const value = loops.steward;
|
|
4381
|
+
const s = value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {};
|
|
4321
4382
|
const roles: NonNullable<NonNullable<UserConfig['loops']>['steward']>['roles'] = {};
|
|
4322
4383
|
if (s.roles && typeof s.roles === 'object' && !Array.isArray(s.roles)) {
|
|
4323
4384
|
for (const [role, entry] of Object.entries(s.roles)) {
|
|
@@ -4327,8 +4388,9 @@ function parseStewardLoopsConfig(input: unknown): UserConfig['loops'] {
|
|
|
4327
4388
|
}
|
|
4328
4389
|
}
|
|
4329
4390
|
return { steward: {
|
|
4330
|
-
mode: s.mode === '
|
|
4331
|
-
|
|
4391
|
+
mode: s.mode === 'off' || s.mode === 'shadow' || s.mode === 'live' ? s.mode :
|
|
4392
|
+
s.launch === 'off' || s.launch === 'shadow' || s.launch === 'live' ? s.launch : 'shadow',
|
|
4393
|
+
// A valid legacy launch setting remains effective when mode is absent; explicit mode always wins.
|
|
4332
4394
|
...(s.launch === 'off' || s.launch === 'shadow' || s.launch === 'live' ? { launch: s.launch } : {}),
|
|
4333
4395
|
...(typeof s.maxParallel === 'number' && Number.isSafeInteger(s.maxParallel) && s.maxParallel > 0 ? { maxParallel: s.maxParallel } : {}),
|
|
4334
4396
|
...(typeof s.podPool === 'string' && s.podPool.trim() ? { podPool: s.podPool.trim() } : {}),
|
|
@@ -4450,8 +4512,22 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
4450
4512
|
const rawNotifications = rawGlobalObj?.notifications ?? rawObj.notifications;
|
|
4451
4513
|
const autopilotConfig = parseAutopilotConfig(rawObj.autopilot);
|
|
4452
4514
|
const stewardLoops = parseStewardLoopsConfig(rawObj.loops);
|
|
4515
|
+
const orgRaw = rawObj.org && typeof rawObj.org === 'object' && !Array.isArray(rawObj.org) ? rawObj.org as Record<string, unknown> : {};
|
|
4516
|
+
const budgetRaw = orgRaw.budget && typeof orgRaw.budget === 'object' && !Array.isArray(orgRaw.budget) ? orgRaw.budget as Record<string, unknown> : {};
|
|
4517
|
+
const seatBudgets: NonNullable<NonNullable<UserConfig['org']>['budget']> = Object.create(null);
|
|
4518
|
+
for (const [seat, value] of Object.entries(budgetRaw)) {
|
|
4519
|
+
if (!seat || !value || typeof value !== 'object' || Array.isArray(value)) continue;
|
|
4520
|
+
const row = value as Record<string, unknown>;
|
|
4521
|
+
const dailyGoals = row.dailyGoals;
|
|
4522
|
+
const concurrentPods = row.concurrentPods;
|
|
4523
|
+
seatBudgets[seat] = {
|
|
4524
|
+
...(typeof dailyGoals === 'number' && Number.isSafeInteger(dailyGoals) && dailyGoals >= 0 ? { dailyGoals } : {}),
|
|
4525
|
+
...(typeof concurrentPods === 'number' && Number.isSafeInteger(concurrentPods) && concurrentPods >= 0 ? { concurrentPods } : {}),
|
|
4526
|
+
};
|
|
4527
|
+
}
|
|
4453
4528
|
|
|
4454
4529
|
return {
|
|
4530
|
+
...(Object.keys(seatBudgets).length ? { org: { budget: seatBudgets } } : {}),
|
|
4455
4531
|
pod: {
|
|
4456
4532
|
...(typeof legacyPod.pool === 'string' && legacyPod.pool.trim() ? { pool: legacyPod.pool.trim() } : {}),
|
|
4457
4533
|
...(typeof legacyPod.hostMirror === 'string' && legacyPod.hostMirror.trim() ? { hostMirror: legacyPod.hostMirror.trim() } : {}),
|
|
@@ -4465,6 +4541,7 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
4465
4541
|
},
|
|
4466
4542
|
harness: {
|
|
4467
4543
|
pod: { grokApiKeyOptIn: harnessPod.grokApiKeyOptIn === true },
|
|
4544
|
+
difficultyPlacement: harness.difficultyPlacement === true,
|
|
4468
4545
|
...(harness.substrate === 'local' || harness.substrate === 'pod' ? { substrate: harness.substrate } : {}),
|
|
4469
4546
|
...(typeof harness.podPool === 'string' && harness.podPool.trim() ? { podPool: harness.podPool.trim() } : {}),
|
|
4470
4547
|
...(typeof harness.worktreeAddTimeoutSec === 'number' && Number.isSafeInteger(harness.worktreeAddTimeoutSec)
|
|
@@ -4583,6 +4660,7 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
4583
4660
|
skills: {
|
|
4584
4661
|
activeSet: normalizeSkillSet(sk.activeSet),
|
|
4585
4662
|
dirs: strArray(sk.dirs, skillsDefaults().dirs),
|
|
4663
|
+
giftEndpoint: str(sk.giftEndpoint) ?? 'https://elanous.ai',
|
|
4586
4664
|
includeSharedAgentSkills: sk.includeSharedAgentSkills !== false,
|
|
4587
4665
|
...(() => { const sources = parsePersistedSkillSources(sk.sources, sk.connected); return sources ? { sources } : {}; })(),
|
|
4588
4666
|
allow: strArray(sk.allow, []),
|
|
@@ -5112,7 +5190,9 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
|
|
|
5112
5190
|
coo: { linearProject: typeof (rawObj.coo as { linearProject?: unknown } | undefined)?.linearProject === 'string' && (rawObj.coo as { linearProject: string }).linearProject.trim()
|
|
5113
5191
|
? (rawObj.coo as { linearProject: string }).linearProject.trim() : '외부 행정·큰 일 (COO)' },
|
|
5114
5192
|
decisions: { linearProjection: { enabled: ((rawObj.decisions as { linearProjection?: { enabled?: unknown } } | undefined)?.linearProjection?.enabled === true) } },
|
|
5115
|
-
loops: { ...(stewardLoops ?? {}), seat: parseSeatLoopsConfig(rawObj.loops)
|
|
5193
|
+
loops: { ...(stewardLoops ?? {}), seat: parseSeatLoopsConfig(rawObj.loops),
|
|
5194
|
+
persona: { enabled: (rawObj.loops as { persona?: { enabled?: unknown } } | undefined)?.persona?.enabled === true } },
|
|
5195
|
+
events: parseEventsConfig(rawObj.events),
|
|
5116
5196
|
// M1-1: sparse — undefined when the user hasn't set anything, so
|
|
5117
5197
|
// resolvers fall through to zero-config defaults.
|
|
5118
5198
|
...spreadIfDefined('modelTier', parseModelTierConfig(rawObj.modelTier)),
|
|
@@ -5692,6 +5772,8 @@ export function saveUserConfig(
|
|
|
5692
5772
|
? rawRest.autopilot as Record<string, unknown> : {};
|
|
5693
5773
|
const rawLoops = rawRest.loops && typeof rawRest.loops === 'object' && !Array.isArray(rawRest.loops)
|
|
5694
5774
|
? rawRest.loops as Record<string, unknown> : {};
|
|
5775
|
+
const rawSteward = rawLoops.steward && typeof rawLoops.steward === 'object' && !Array.isArray(rawLoops.steward)
|
|
5776
|
+
? rawLoops.steward as Record<string, unknown> : {};
|
|
5695
5777
|
if (cfg.loops) delete rawRest.loops;
|
|
5696
5778
|
if (cfg.pod?.hostMirror) {
|
|
5697
5779
|
const rawPod = rawRest.pod && typeof rawRest.pod === 'object' && !Array.isArray(rawRest.pod)
|
|
@@ -5704,6 +5786,7 @@ export function saveUserConfig(
|
|
|
5704
5786
|
...rawHarness,
|
|
5705
5787
|
pod: cfg.harness?.pod ?? rawHarness.pod,
|
|
5706
5788
|
budgetGate: cfg.harness?.budgetGate ?? rawHarness.budgetGate,
|
|
5789
|
+
difficultyPlacement: cfg.harness?.difficultyPlacement ?? rawHarness.difficultyPlacement,
|
|
5707
5790
|
defaultRepo: cfg.harness?.defaultRepo ?? rawHarness.defaultRepo,
|
|
5708
5791
|
substrate: cfg.harness?.substrate,
|
|
5709
5792
|
podPool: cfg.harness?.podPool,
|
|
@@ -5711,8 +5794,10 @@ export function saveUserConfig(
|
|
|
5711
5794
|
...rawRest,
|
|
5712
5795
|
...(cfg.loops ? { loops: {
|
|
5713
5796
|
...rawLoops,
|
|
5797
|
+
...(cfg.loops.steward ? { steward: { ...rawSteward, mode: cfg.loops.steward.mode ?? cfg.loops.steward.launch ?? 'shadow' } } : {}),
|
|
5714
5798
|
...(cfg.loops.seat ? { seat: {
|
|
5715
5799
|
mode: cfg.loops.seat.mode,
|
|
5800
|
+
questions: cfg.loops.seat.questions ?? 'shadow',
|
|
5716
5801
|
seats: cfg.loops.seat.seats ?? ['MK'],
|
|
5717
5802
|
podPool: cfg.loops.seat.podPool ?? 'pool-node-b@node-b:8',
|
|
5718
5803
|
...(cfg.loops.seat.reportPr === undefined ? {} : { reportPr: cfg.loops.seat.reportPr }),
|
|
@@ -5783,6 +5868,7 @@ export function saveUserConfig(
|
|
|
5783
5868
|
skills: stripUndef({
|
|
5784
5869
|
activeSet: cfg.skills.activeSet,
|
|
5785
5870
|
dirs: [...cfg.skills.dirs],
|
|
5871
|
+
giftEndpoint: cfg.skills.giftEndpoint === 'https://elanous.ai' ? undefined : cfg.skills.giftEndpoint,
|
|
5786
5872
|
// EN5 — only connected roots are persisted (preset/shared/package are derived). The dev-only `connected` key is not written back.
|
|
5787
5873
|
sources: cfg.skills.sources && cfg.skills.sources.some((source) => source.kind === 'connected')
|
|
5788
5874
|
? cfg.skills.sources.filter((source) => source.kind === 'connected').map(({ id, path, enabled }) => ({ id, path, enabled }))
|
|
@@ -6039,7 +6125,7 @@ export function saveUserConfig(
|
|
|
6039
6125
|
...(cfg.tabs && Object.keys(cfg.tabs).length > 0 ? { tabs: cfg.tabs } : {}),
|
|
6040
6126
|
// M1-2b: sparse — emit only when explicitly set. Keeps Path-A-only
|
|
6041
6127
|
// users' file clean (no empty modelTier:{} blobs).
|
|
6042
|
-
...(cfg.modelTier ? { modelTier: cfg.modelTier } : {}),
|
|
6128
|
+
...(cfg.modelTier ? { modelTier: parseModelTierConfig(cfg.modelTier) } : {}),
|
|
6043
6129
|
...(cfg.sessionFabric ? { sessionFabric: cfg.sessionFabric } : {}),
|
|
6044
6130
|
...(cfg.nextFluent ? { nextFluent: cfg.nextFluent } : {}),
|
|
6045
6131
|
...(cfg.taste ? { taste: cfg.taste } : {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"commit":"
|
|
1
|
+
{"commit":"27045f4612b148543fb0f91b82d37592d1d6c9f2"}
|
package/src/web-search/grok.ts
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import { getGrokApiKey } from '../config.js';
|
|
21
21
|
import { grokAgentSearch, GROK_SEARCH_MODEL } from '../grok/agent-search.js';
|
|
22
|
+
import { wantsXSearch } from './x-intent.js';
|
|
22
23
|
import type { WebSearchHit, WebSearchProvider, WebSearchResult } from './provider.js';
|
|
23
24
|
|
|
24
25
|
const DEFAULT_LIMIT = 5;
|
|
@@ -52,10 +53,15 @@ export function buildGrokWebSearchProvider(): WebSearchProvider {
|
|
|
52
53
|
|
|
53
54
|
if (!r.ok) throw new Error(r.error ?? 'grok search failed');
|
|
54
55
|
|
|
55
|
-
const
|
|
56
|
+
const xSourceUrls = new Set(r.xSearchSources ?? []);
|
|
57
|
+
const citations = wantsXSearch(q.query)
|
|
58
|
+
? [...r.citations.filter(c => xSourceUrls.has(c.url)), ...r.citations.filter(c => !xSourceUrls.has(c.url))]
|
|
59
|
+
: r.citations;
|
|
60
|
+
const hits: WebSearchHit[] = citations.slice(0, limit).map(c => ({
|
|
56
61
|
url: c.url,
|
|
57
62
|
title: c.title ?? c.url,
|
|
58
63
|
snippet: '',
|
|
64
|
+
...(xSourceUrls.has(c.url) ? { xSearchSource: true } : {}),
|
|
59
65
|
}));
|
|
60
66
|
|
|
61
67
|
const note = r.text.length > 0 ? r.text.slice(0, 1500) : undefined;
|