elanous 0.2.10 → 0.2.11
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/Y4zKzL62sakG5momz3SoQ/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1394-556de6d71bbdb0fb.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/2310-7a59f043f6db207e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2548-6e316138d347cefe.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-a39d1d9921e10d43.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/507-5acd98bd6dab2d8a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5445-745eb795c5963d79.js +1 -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/{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/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-ea5bee9dfae512c7.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/app/_not-found/page-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-1dcdc58fc2de2454.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-6a061bd97f0b9398.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-cb95a7432c9ee744.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-b12b6d2f8d2d1aea.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-b9efe868bfd36255.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-7c97dcdfe2e37a60.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-8fd36984f549270a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-5721537ca8a3598c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-b654240a572e4c48.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-b9750abc897508c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-4cd1de371f8ad048.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-d99f89657828421c.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-50cb2a0eb15e6c83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c8b1ccda6ba7ae98.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-d6b1d156fb95e74b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-2a9932ddb62d76bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-9688f5b4f1ff950f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6b15dd6456c5df09.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-35414e0a007b4082.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-e7a529e0507ac86c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-e001823c35c9dd67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-371423d1a573d64b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4b764b125339ac17.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cdf8e4b01067bcf1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a24072b35470157.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-94c82eb0ae5abb32.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-0be8d4b2ced75ba0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d37cb0d52f9b6bd5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-686da0df9bf23e5c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4dc614f3ce043e63.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-53f80edc6b8dc07c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-d02c782fc792e2af.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-239c17b911b84e72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-dc6a79fb003f746c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-0fffb84cafdc9da6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-1218753c82d585f6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-4b5935e67531efb5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-3285bc87caf1eaa5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-ad553b0e06505ecd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-fca096e3e860306f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ebfa78f0d9885c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-3dc5f21f7e39622d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-c6da2b468454532d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-93bc70e36f595414.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/543f56bcb1f79fca.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/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/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/marketing/measure-site-numbers.ts +169 -0
- package/scripts/measure-gate-shards.ts +309 -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/cut-branch.ts +84 -0
- package/scripts/release-loop/gate-node.ts +14 -13
- package/scripts/release-loop/mac-smoke-node.ts +229 -0
- package/scripts/release-loop/node-verdict.ts +3 -3
- 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 +61 -10
- 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/test-diet/node.ts +1 -1
- package/scripts/tui-regress.ts +2 -2
- package/scripts/ux/demo-rehearsal.ts +243 -0
- package/scripts/ux/lib/rehearsal-verdict.ts +73 -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 +80 -10
- 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/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 +1 -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 +90 -4
- package/src/cli/plugin-cli.ts +31 -22
- package/src/cli/pod-cli.ts +19 -9
- 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 +17 -4
- 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 +48 -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/dashboard/index.ts +9 -4
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +7 -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 +6 -1
- 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 +100 -0
- package/src/field/field-reel.ts +5 -1
- package/src/field-note/index.ts +201 -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 +37 -0
- package/src/graph-runner/graph-grow.ts +47 -0
- package/src/graph-runner/runner.ts +317 -25
- package/src/grok/agent-search.ts +8 -2
- package/src/guardian/secret-exposure-scan.ts +101 -0
- package/src/harness/harness-cli-command.ts +247 -7
- 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/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 +21 -20
- package/src/index.ts +52 -14
- package/src/intake-plane/categorize.ts +18 -46
- package/src/intake-plane/discord-seat-work.ts +10 -0
- 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-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 +26 -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 +36 -0
- 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/outputs-route.ts +44 -0
- 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/trace.ts +18 -6
- package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
- package/src/nexus/api/workflows.ts +80 -6
- package/src/nexus/index.ts +2 -0
- package/src/nexus/kinds/webterm.ts +2 -1
- 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 +116 -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 +109 -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 +2 -2
- package/src/release-loop/feature-store.ts +5 -3
- 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 +548 -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 +38 -33
- package/src/self-dev/draft-triage-rules.ts +8 -5
- 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/gate-baseline.ts +1 -1
- package/src/self-implement/gate-cli.ts +40 -1
- package/src/self-implement/gate-scope.ts +37 -7
- 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 +22 -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 +242 -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 +1 -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 +29 -7
- 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 +214 -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 +10 -1
- package/src/telegram-project-command.ts +71 -0
- package/src/telegram-report.ts +21 -17
- package/src/telegram.ts +29 -3
- package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
- package/src/user-config.ts +102 -20
- 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 → Y4zKzL62sakG5momz3SoQ}/_ssgManifest.js +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { chmodSync, mkdirSync, readFileSync,
|
|
1
|
+
import { chmodSync, mkdirSync, readFileSync, rmSync } from 'node:fs';
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
3
|
import { join, resolve } from 'node:path';
|
|
4
4
|
import { randomUUID } from 'node:crypto';
|
|
5
5
|
import { debug } from './debug/log.js';
|
|
6
6
|
import { effectiveInstanceRoot } from './instance/resolve.js';
|
|
7
|
-
import {
|
|
7
|
+
import { runGraph } from './graph-runner/runner.js';
|
|
8
|
+
import { cardShape, detectCard, runCardFollowup, NotACardError, type CardDetectDecision } from './card-followup/core.js';
|
|
8
9
|
import type { TgIncoming } from './telegram.js';
|
|
9
10
|
|
|
10
|
-
const GRAPH = resolve(import.meta.dir, '../plugins/card-followup/graphs/card-followup.yaml');
|
|
11
11
|
// Latin keywords are whole words only — «postcard» or «cardinal» is not a card request (review round 3).
|
|
12
12
|
const KEYWORD = /명함|전략|메일\s*초안|초안|팔로업|\bcard\b|\bCRM\b/i;
|
|
13
13
|
/** Untagged albums start one graph run, not one per photo (chatId:mediaGroupId → first seen at). */
|
|
@@ -22,30 +22,7 @@ function firstOfAlbum(chatId: number, mediaGroupId: string | undefined, now: num
|
|
|
22
22
|
return true;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
export type CardDetectDecision = 'card' | 'skip' | 'ambiguous';
|
|
27
|
-
export function cardShape(width?: number, height?: number): { decision: 'skip' | 'pass'; signal: string } {
|
|
28
|
-
if (!width || !height) return { decision: 'pass', signal: 'ratio:unknown' };
|
|
29
|
-
const ratio = Math.max(width, height) / Math.min(width, height);
|
|
30
|
-
if (ratio < 1.15) return { decision: 'skip', signal: 'ratio:square' };
|
|
31
|
-
if (ratio > 2.0) return { decision: 'skip', signal: 'ratio:screenshot' };
|
|
32
|
-
return { decision: 'pass', signal: `ratio:${ratio.toFixed(2)}` };
|
|
33
|
-
}
|
|
34
|
-
const EMAIL = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i;
|
|
35
|
-
const PHONE = /(?:\+?\d{1,3}[\s.-]?)?\(?\d{2,4}\)?[\s.-]?\d{3,4}[\s.-]?\d{4}/;
|
|
36
|
-
const WEB = /\b(?:https?:\/\/|www\.)\S+|\b[a-z0-9-]+\.(?:com|co\.kr|kr|io|ai|net|org)\b/i;
|
|
37
|
-
const TITLE = /대표|이사|팀장|부장|과장|실장|매니저|주식회사|\(주\)|\b(?:CEO|CTO|COO|CFO|Director|Manager|Founder|Inc|Ltd|Corp)\b/i;
|
|
38
|
-
/** Card text is short and carries contact patterns; long text is a document. Returns signal names only, never the text. */
|
|
39
|
-
export function cardText(ocr: string | null): { decision: CardDetectDecision; signal: string } {
|
|
40
|
-
if (ocr === null) return { decision: 'ambiguous', signal: 'ocr:unavailable' };
|
|
41
|
-
const chars = ocr.replace(/\s+/g, '').length;
|
|
42
|
-
if (chars < 15) return { decision: 'ambiguous', signal: `ocr:chars<15` };
|
|
43
|
-
if (chars > 700) return { decision: 'skip', signal: 'ocr:document' };
|
|
44
|
-
const hits = ([['email', EMAIL], ['phone', PHONE], ['web', WEB], ['title', TITLE]] as const).filter(([, re]) => re.test(ocr)).map(([name]) => name);
|
|
45
|
-
const signal = `ocr:${hits.join(',') || 'none'}`;
|
|
46
|
-
if (hits.length >= 2) return { decision: 'card', signal };
|
|
47
|
-
return { decision: hits.length === 0 ? 'skip' : 'ambiguous', signal };
|
|
48
|
-
}
|
|
25
|
+
export { cardShape, cardText } from './card-followup/core.js';
|
|
49
26
|
const OCR_SCRIPT = resolve(import.meta.dir, '../scripts/ocr-text-regions.swift');
|
|
50
27
|
/** Local macOS Vision OCR (no network · no new dependency); null where it cannot run. */
|
|
51
28
|
export function localOcrText(path: string, timeoutMs = 30_000): Promise<string | null> {
|
|
@@ -78,36 +55,6 @@ export interface CardPhotoDeps {
|
|
|
78
55
|
ocrText?: (path: string) => Promise<string | null>;
|
|
79
56
|
}
|
|
80
57
|
|
|
81
|
-
const obj = (value: unknown): Record<string, unknown> => value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {};
|
|
82
|
-
const text = (value: unknown): string => typeof value === 'string' ? value.trim() : '';
|
|
83
|
-
const line = (value: unknown): string => (typeof value === 'number' && Number.isFinite(value) ? String(value) : text(value)).replace(/[\r\n]+/g, ' ') || '—';
|
|
84
|
-
|
|
85
|
-
function isNotACard(state: GraphRunState): boolean {
|
|
86
|
-
if (state.status !== 'failed') return false;
|
|
87
|
-
const read = state.nodes.find((node) => node.nodeId === 'read-card');
|
|
88
|
-
if (!read || !read.ok) return false;
|
|
89
|
-
const output = lastJsonObject(read.output);
|
|
90
|
-
if (output?.outcome === 'ok' && output.card && typeof output.card === 'object') {
|
|
91
|
-
const card = obj(output.card);
|
|
92
|
-
return !['name', 'company', 'title', 'email', 'phone', 'url', 'linkedin'].some((field) => text(card[field]));
|
|
93
|
-
}
|
|
94
|
-
return output?.outcome === 'fail' && typeof output.reason === 'string'
|
|
95
|
-
&& /\bnot a (?:business )?card\b|명함이?\s*아님|명함이?\s*아닙니다/i.test(output.reason);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function validateReport(report: Record<string, unknown>): void {
|
|
99
|
-
const card = obj(report.card), fit = obj(report.fit), approach = obj(report.approach);
|
|
100
|
-
const next = obj(report.nextAction), draft = obj(report.draft);
|
|
101
|
-
const score = fit.score;
|
|
102
|
-
if (report.sent !== false || !text(card.name) || !text(card.company)
|
|
103
|
-
|| !(score === null || (typeof score === 'number' && Number.isFinite(score)))
|
|
104
|
-
|| !text(fit.label) || !text(approach.problem) || !text(approach.proposal)
|
|
105
|
-
|| !text(approach.channel) || !text(next.what) || !text(next.due)
|
|
106
|
-
|| !text(draft.subject) || !text(draft.body)) {
|
|
107
|
-
throw new Error('incomplete or sent card report');
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
58
|
function pick(caption: string): Picked {
|
|
112
59
|
if (/\bCRM\b/i.test(caption)) return 'crm';
|
|
113
60
|
if (/메일\s*초안|초안/i.test(caption)) return 'draft';
|
|
@@ -149,7 +96,7 @@ export async function maybeHandleCardPhoto(ctx: TgIncoming, deps: CardPhotoDeps)
|
|
|
149
96
|
const { localPath } = await deps.downloadFile(photo.fileId, dir);
|
|
150
97
|
chmodSync(localPath, 0o600);
|
|
151
98
|
if (!caption) {
|
|
152
|
-
const verdict =
|
|
99
|
+
const verdict = detectCard({ width: photo.width, height: photo.height, ocrText: await (deps.ocrText ?? localOcrText)(localPath) });
|
|
153
100
|
detect(verdict.decision, verdict.signal);
|
|
154
101
|
if (verdict.decision !== 'card') { rmSync(dir, { recursive: true, force: true }); return null; }
|
|
155
102
|
}
|
|
@@ -166,38 +113,22 @@ export async function maybeHandleCardPhoto(ctx: TgIncoming, deps: CardPhotoDeps)
|
|
|
166
113
|
try { localPath = await prepare(); } catch { log('failed'); return; }
|
|
167
114
|
if (!localPath) return;
|
|
168
115
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
for (const file of readdirSync(contexts)) chmodSync(join(contexts, file), 0o600);
|
|
179
|
-
} catch (error) {
|
|
180
|
-
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
if (isNotACard(state)) {
|
|
184
|
-
log('not-a-card');
|
|
185
|
-
return;
|
|
116
|
+
let result;
|
|
117
|
+
try {
|
|
118
|
+
result = await runCardFollowup({ imagePath: localPath!, ocrText: null,
|
|
119
|
+
runGraph: deps.runGraph ?? runGraph, rootDir: root, outDir: dir, runId,
|
|
120
|
+
...(caption ? { context: caption } : {}),
|
|
121
|
+
});
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (error instanceof NotACardError) { log('not-a-card'); return; }
|
|
124
|
+
throw error;
|
|
186
125
|
}
|
|
187
|
-
|
|
188
|
-
const report = obj(JSON.parse(readFileSync(join(dir, 'followup.json'), 'utf8')));
|
|
189
|
-
validateReport(report);
|
|
190
|
-
const card = obj(report.card), fit = obj(report.fit), approach = obj(report.approach);
|
|
191
|
-
const next = obj(report.nextAction), draft = obj(report.draft);
|
|
192
|
-
const summary = `① 요약\n${line(card.name)} · ${line(card.company)} · ${line(card.title)}\n타겟 판정: ${line(fit.score)} · ${line(fit.label)}`;
|
|
193
|
-
const strategy = `② 전략\n${[approach.problem, approach.proposal, approach.channel].map(line).join('\n')}\n다음 행동: ${line(next.what)} · ${line(next.due)}`;
|
|
194
|
-
const mail = `③ 팔로업 초안 (보내지 않았습니다)\n제목: ${line(draft.subject)}\n${text(draft.body)}`;
|
|
195
|
-
const markdown = readFileSync(join(dir, 'followup.md'));
|
|
126
|
+
const markdown = readFileSync(result.followupPath!);
|
|
196
127
|
const crmLine = picked === 'crm'
|
|
197
128
|
? /^## ② CRM 한 줄\r?\n파일: [^\r\n]*\r?\n([^\r\n]+)/m.exec(markdown.toString('utf8'))?.[1]
|
|
198
129
|
: undefined;
|
|
199
130
|
if (picked === 'crm' && !crmLine) throw new Error('CRM row missing from report');
|
|
200
|
-
const messages = picked === 'strategy' ? [
|
|
131
|
+
const messages = picked === 'strategy' ? [result.replies[1]] : picked === 'draft' ? [result.replies[2]] : picked === 'crm' ? [`CRM 한 줄\n${crmLine}`] : result.replies;
|
|
201
132
|
for (const message of messages) await deps.sendMessage(ctx.chatId, message, reply);
|
|
202
133
|
const sent = await deps.sendDocument(ctx.chatId, markdown, 'followup.md', { ...reply, mimeType: 'text/markdown' });
|
|
203
134
|
if (sent === undefined) throw new Error('document delivery failed');
|
|
@@ -207,17 +138,6 @@ export async function maybeHandleCardPhoto(ctx: TgIncoming, deps: CardPhotoDeps)
|
|
|
207
138
|
try {
|
|
208
139
|
await deps.sendMessage(ctx.chatId, '명함 정리에 실패했습니다. 다시 시도해 주세요.', reply);
|
|
209
140
|
} catch { /* Telegram delivery itself failed; the failure is already observed. */ }
|
|
210
|
-
} finally {
|
|
211
|
-
if (!deps.runGraph) {
|
|
212
|
-
// The runner may throw before returning its state; seal any partial state and contexts too.
|
|
213
|
-
const statePath = join(base, `${runId}.json`);
|
|
214
|
-
try { chmodSync(statePath, 0o600); } catch { /* no state yet */ }
|
|
215
|
-
const contexts = `${statePath}.contexts`;
|
|
216
|
-
try {
|
|
217
|
-
chmodSync(contexts, 0o700);
|
|
218
|
-
for (const file of readdirSync(contexts)) chmodSync(join(contexts, file), 0o600);
|
|
219
|
-
} catch { /* no contexts yet */ }
|
|
220
|
-
}
|
|
221
141
|
}
|
|
222
142
|
})();
|
|
223
143
|
} catch {
|
package/src/telegram-commands.ts
CHANGED
|
@@ -44,6 +44,9 @@ import { readDaemonSessionHistory } from './telegram/daemon-history-reader.js';
|
|
|
44
44
|
import { renderTelegramReplayPreviewHtml } from './telegram/replay-preview.js';
|
|
45
45
|
import { classifyIntake } from './ad-pipeline/intake.js';
|
|
46
46
|
import { createAdPipelineDeps, runAdPipeline } from './ad-pipeline/run.js';
|
|
47
|
+
import { projectCommand } from './telegram-project-command.js';
|
|
48
|
+
import { telegramNowSlash } from './context-bus/context-now-surfaces.js';
|
|
49
|
+
import type { ContextNowDeps } from './context-bus/context-now.js';
|
|
47
50
|
|
|
48
51
|
/** How many prior user/assistant turns to pass into `executeSkill` as
|
|
49
52
|
* the `## Recent conversation` block. Mirrors the dashboard default
|
|
@@ -291,7 +294,7 @@ function dropChatSessionReply(ctx: TgIncoming): string {
|
|
|
291
294
|
/** Build the default command set for a Telegram bot wired via
|
|
292
295
|
* botFromConfig. Returns the array rather than mutating globals so
|
|
293
296
|
* tests can construct a variant set with stubbed handlers. */
|
|
294
|
-
export function defaultTelegramCommands(): TgSlashCommand[] {
|
|
297
|
+
export function defaultTelegramCommands(nowDeps?: ContextNowDeps): TgSlashCommand[] {
|
|
295
298
|
return [
|
|
296
299
|
{
|
|
297
300
|
name: 'help',
|
|
@@ -304,6 +307,11 @@ export function defaultTelegramCommands(): TgSlashCommand[] {
|
|
|
304
307
|
return lines.join('\n');
|
|
305
308
|
},
|
|
306
309
|
},
|
|
310
|
+
{
|
|
311
|
+
name: 'now',
|
|
312
|
+
description: 'Show current release, decisions, seats and context: /now [topic]',
|
|
313
|
+
handler: async (args) => telegramNowSlash(args, nowDeps),
|
|
314
|
+
},
|
|
307
315
|
{
|
|
308
316
|
name: 'status',
|
|
309
317
|
description: 'Show bot identity, current session, provider + model',
|
|
@@ -581,6 +589,7 @@ export function defaultTelegramCommands(): TgSlashCommand[] {
|
|
|
581
589
|
return lines.join('\n');
|
|
582
590
|
},
|
|
583
591
|
},
|
|
592
|
+
projectCommand(),
|
|
584
593
|
{
|
|
585
594
|
name: 'fork',
|
|
586
595
|
description: 'Fork the current chat session (or /fork <prefix>) and continue HERE on the fork · time-travel: /fork before:N',
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { debug } from './debug/log.js';
|
|
2
|
+
import { getProject, listProjects, type Project } from './project/project-store.js';
|
|
3
|
+
import { findSessionByTelegramChat, updateSessionMeta } from './session/index.js';
|
|
4
|
+
import type { TgSlashCommand } from './telegram-commands.js';
|
|
5
|
+
|
|
6
|
+
export interface TelegramProjectCommandDeps {
|
|
7
|
+
list: () => Project[];
|
|
8
|
+
find: (id: string) => Project | null;
|
|
9
|
+
update: typeof updateSessionMeta;
|
|
10
|
+
findSession: typeof findSessionByTelegramChat;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function projectCommand(deps: TelegramProjectCommandDeps = {
|
|
14
|
+
list: listProjects,
|
|
15
|
+
find: getProject,
|
|
16
|
+
update: updateSessionMeta,
|
|
17
|
+
findSession: findSessionByTelegramChat,
|
|
18
|
+
}): TgSlashCommand {
|
|
19
|
+
return {
|
|
20
|
+
name: 'project',
|
|
21
|
+
description: '이 대화의 프로젝트 보기·옮기기',
|
|
22
|
+
handler: async (args, ctx) => {
|
|
23
|
+
const session = deps.findSession(ctx.chatId, ctx.threadId, ctx.botId);
|
|
24
|
+
if (!session) {
|
|
25
|
+
debug.log('telegram.project', 'rejected', { projects: [], reason: 'no-session' });
|
|
26
|
+
return '아직 이 채팅에 대화가 없습니다 — 한 마디 보낸 뒤 다시';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (args.length === 0) {
|
|
30
|
+
const current = session.projectId ? deps.find(session.projectId) : null;
|
|
31
|
+
const projects = deps.list().sort((a, b) => a.name.localeCompare(b.name)).slice(0, 20);
|
|
32
|
+
debug.log('telegram.project', 'listed', { projects: projects.map(p => ({ id: p.id, name: p.name })) });
|
|
33
|
+
return [
|
|
34
|
+
`지금 대화의 프로젝트: ${current?.name ?? '받은 대화(프로젝트 없음)'}`,
|
|
35
|
+
'',
|
|
36
|
+
'프로젝트 목록:',
|
|
37
|
+
...projects.map(p => `• ${p.name}`),
|
|
38
|
+
'',
|
|
39
|
+
'옮기려면 /project <이름>',
|
|
40
|
+
].join('\n');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const name = args.join(' ').trim();
|
|
44
|
+
if (name === '-') {
|
|
45
|
+
deps.update(session.id, m => { delete m.projectId; });
|
|
46
|
+
debug.log('telegram.project', 'cleared', { projects: [] });
|
|
47
|
+
return '받은 대화로 옮겼습니다';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const projects = deps.list();
|
|
51
|
+
const normalized = name.toLocaleLowerCase();
|
|
52
|
+
const exact = projects.filter(p => p.name.toLocaleLowerCase() === normalized);
|
|
53
|
+
const matches = exact.length ? exact : projects.filter(p => p.name.toLocaleLowerCase().startsWith(normalized));
|
|
54
|
+
if (matches.length === 0) {
|
|
55
|
+
debug.log('telegram.project', 'rejected', { projects: [], reason: 'not-found' });
|
|
56
|
+
return '그 이름의 프로젝트가 없습니다 — /project 로 목록 보기';
|
|
57
|
+
}
|
|
58
|
+
if (matches.length > 1) {
|
|
59
|
+
debug.log('telegram.project', 'rejected', {
|
|
60
|
+
projects: matches.map(p => ({ id: p.id, name: p.name })), reason: 'ambiguous',
|
|
61
|
+
});
|
|
62
|
+
return `여러 프로젝트가 맞습니다 — 이름을 골라 주세요:\n${matches.map(p => `• ${p.name}`).join('\n')}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const project = matches[0]!;
|
|
66
|
+
deps.update(session.id, m => { m.projectId = project.id; });
|
|
67
|
+
debug.log('telegram.project', 'moved', { projects: [{ id: project.id, name: project.name }] });
|
|
68
|
+
return `이 대화를 ${project.name} 프로젝트로 옮겼습니다`;
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
package/src/telegram-report.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// the report channel while interactive Q&A stays on the main bot.
|
|
12
12
|
|
|
13
13
|
import { TelegramBot } from './telegram.js';
|
|
14
|
-
import {
|
|
14
|
+
import { isTradingKind, kindRouteTarget, logKindRouteFallback, mainHomeTarget } from './domains/telegram-kind-route.js';
|
|
15
15
|
export { DEFAULT_KIND_ROLES, roleForKind } from './domains/telegram-kind-route.js';
|
|
16
16
|
import { resolveChannelBotToken } from './channel-bot-token.js';
|
|
17
17
|
import type { UserConfig } from './user-config.js';
|
|
@@ -51,22 +51,27 @@ export interface ReportTarget {
|
|
|
51
51
|
chatId: number;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
54
|
+
/** An exact role channel wins. A configured channels table cannot silently fall through
|
|
55
|
+
* to the legacy report bot or a channel with a different role. Without that table, only
|
|
56
|
+
* named finance kinds can use the legacy trading report channel. */
|
|
57
57
|
export function resolveReportTarget(cfg: UserConfig, kind?: string): ReportTarget | null {
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
if (cfg.telegram.channels?.length) {
|
|
59
|
+
const routed = kindRouteTarget(cfg, kind);
|
|
60
|
+
if (routed) return routed;
|
|
61
|
+
logKindRouteFallback(kind, 'none', false);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
60
64
|
const rc = cfg.telegram.reportChannel;
|
|
61
65
|
const mainToken = resolveChannelBotToken('telegram', cfg).token;
|
|
62
66
|
const sameBot = !!mainToken && !!rc && (rc.botToken ?? mainToken) === mainToken;
|
|
63
|
-
if (
|
|
67
|
+
if (!isTradingKind(kind)) {
|
|
64
68
|
const home = mainHomeTarget(cfg);
|
|
65
69
|
logKindRouteFallback(kind, home ? 'main-home' : 'none', sameBot);
|
|
66
70
|
return home;
|
|
67
71
|
}
|
|
68
|
-
const botToken = rc?.botToken
|
|
69
|
-
const target = rc && Number.isFinite(rc.chatId) && botToken
|
|
72
|
+
const botToken = rc?.botToken;
|
|
73
|
+
const target = rc && Number.isFinite(rc.chatId) && botToken && botToken !== mainToken
|
|
74
|
+
? { botToken, chatId: rc.chatId } : null;
|
|
70
75
|
logKindRouteFallback(kind, target ? 'report-channel' : 'none', sameBot);
|
|
71
76
|
return target;
|
|
72
77
|
}
|
|
@@ -81,10 +86,9 @@ export interface SendReportOpts {
|
|
|
81
86
|
kind?: string;
|
|
82
87
|
}
|
|
83
88
|
|
|
84
|
-
/** Send a report to
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* Telegram API failure once a target exists. */
|
|
89
|
+
/** Send a report to its kind's exact-role channel (or the safe legacy target).
|
|
90
|
+
* Returns false when no safe target exists; throws only on an actual
|
|
91
|
+
* Telegram API failure after a target has been selected. */
|
|
88
92
|
export async function sendTelegramReport(
|
|
89
93
|
cfg: UserConfig,
|
|
90
94
|
text: string,
|
|
@@ -110,9 +114,9 @@ export async function sendTelegramReport(
|
|
|
110
114
|
export async function sendReportPhoto(
|
|
111
115
|
cfg: UserConfig,
|
|
112
116
|
photoUrl: string,
|
|
113
|
-
opts: { caption?: string; fetchImpl?: typeof fetch } = {},
|
|
117
|
+
opts: { caption?: string; fetchImpl?: typeof fetch; kind?: string } = {},
|
|
114
118
|
): Promise<boolean> {
|
|
115
|
-
const target = resolveReportTarget(cfg);
|
|
119
|
+
const target = resolveReportTarget(cfg, opts.kind);
|
|
116
120
|
if (!target || !photoUrl) return false;
|
|
117
121
|
const bot = new TelegramBot({
|
|
118
122
|
token: target.botToken,
|
|
@@ -131,9 +135,9 @@ export async function sendReportPhoto(
|
|
|
131
135
|
export async function sendReportPhotoBuffer(
|
|
132
136
|
cfg: UserConfig,
|
|
133
137
|
png: Buffer,
|
|
134
|
-
opts: { caption?: string; fetchImpl?: typeof fetch } = {},
|
|
138
|
+
opts: { caption?: string; fetchImpl?: typeof fetch; kind?: string } = {},
|
|
135
139
|
): Promise<boolean> {
|
|
136
|
-
const target = resolveReportTarget(cfg);
|
|
140
|
+
const target = resolveReportTarget(cfg, opts.kind);
|
|
137
141
|
if (!target || !png) return false;
|
|
138
142
|
const bot = new TelegramBot({
|
|
139
143
|
token: target.botToken,
|
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,6 +68,7 @@ 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';
|
|
@@ -338,6 +340,7 @@ export class TelegramBot {
|
|
|
338
340
|
private readonly fieldReel?: FieldReelOptions;
|
|
339
341
|
private readonly cardFollowupDeps: Pick<CardPhotoDeps, 'runGraph' | 'rootDir' | 'ocrText'>;
|
|
340
342
|
private readonly seatWorkDeps: TelegramSeatWorkDeps;
|
|
343
|
+
private seatAskTimer: ReturnType<typeof setInterval> | null = null;
|
|
341
344
|
/** 앨범 id → `#현장` 행사 · 답장 디바운스. 태그된 앨범만 들어온다. */
|
|
342
345
|
private readonly fieldGroups = new Map<string, {
|
|
343
346
|
event: string; mode?: 'instant'; at: number; chatId: number; threadId?: number; replyTo: number; count: number;
|
|
@@ -373,7 +376,15 @@ export class TelegramBot {
|
|
|
373
376
|
this.fieldRootDir = opts.fieldRootDir ?? getElanousConfigDir;
|
|
374
377
|
this.fieldReel = opts.fieldReel;
|
|
375
378
|
this.cardFollowupDeps = opts.cardFollowupDeps ?? {};
|
|
376
|
-
this.seatWorkDeps = opts.seatWorkDeps
|
|
379
|
+
this.seatWorkDeps = { ...opts.seatWorkDeps, askDeps: { ...opts.seatWorkDeps?.askDeps,
|
|
380
|
+
channel: 'telegram', botId: this.botId,
|
|
381
|
+
send: opts.seatWorkDeps?.askDeps?.send ?? (async (origin, text) => {
|
|
382
|
+
if (origin.channel !== 'telegram') throw new Error('seat ask belongs to another surface');
|
|
383
|
+
const posted = await this.sendMessage(Number(origin.chatId), text, { replyTo: origin.messageId, threadId: origin.threadId });
|
|
384
|
+
if (!posted) throw new Error('Telegram seat ask reply was not posted');
|
|
385
|
+
}),
|
|
386
|
+
} };
|
|
387
|
+
|
|
377
388
|
if (opts.onTriggerTap) {
|
|
378
389
|
// Assign through `as unknown` to bypass `readonly` + private —
|
|
379
390
|
// the tap is set once at construction and never reassigned.
|
|
@@ -1120,6 +1131,9 @@ export class TelegramBot {
|
|
|
1120
1131
|
async start(): Promise<void> {
|
|
1121
1132
|
this.running = true;
|
|
1122
1133
|
this.log(`telegram bot starting (allowlist size ${this.allowedUsers.size})`);
|
|
1134
|
+
this.seatAskTimer = setInterval(() => {
|
|
1135
|
+
void deliverSeatAnswers(this.seatWorkDeps.askDeps!).catch((error) => this.log(`seat ask delivery failed: ${String(error)}`));
|
|
1136
|
+
}, 10_000);
|
|
1123
1137
|
if (this.allowedUsers.size === 0) this.log('telegram.owner-gate empty-allowlist');
|
|
1124
1138
|
|
|
1125
1139
|
// Publish the slash-command menu to Telegram. Clients pick up the
|
|
@@ -1128,9 +1142,16 @@ export class TelegramBot {
|
|
|
1128
1142
|
// still processes `/commands` via the incoming-message dispatch
|
|
1129
1143
|
// path, users just don't get the autocomplete.
|
|
1130
1144
|
if (this.slashCommands.length > 0) {
|
|
1145
|
+
const audience = this.slashContext
|
|
1146
|
+
? readBotAudience((this.slashContext.userConfig.raw?.telegram as { commandAudience?: unknown } | undefined)?.commandAudience)
|
|
1147
|
+
: botAudienceFor('telegram');
|
|
1148
|
+
const commands = filterBotCommands('telegram', this.slashCommands, audience);
|
|
1149
|
+
debug.log('telegram.command', 'menu-filtered', {
|
|
1150
|
+
total: this.slashCommands.length, shown: commands.length, ...audience,
|
|
1151
|
+
});
|
|
1131
1152
|
try {
|
|
1132
1153
|
const result = await this.apiCall<unknown>('setMyCommands', {
|
|
1133
|
-
commands: toTelegramBotCommands(
|
|
1154
|
+
commands: toTelegramBotCommands(commands),
|
|
1134
1155
|
});
|
|
1135
1156
|
debug.log('telegram.command', 'published', { success: true, result });
|
|
1136
1157
|
this.log(`telegram: setMyCommands published (${String(result)})`);
|
|
@@ -1151,6 +1172,7 @@ export class TelegramBot {
|
|
|
1151
1172
|
const CONFLICT_BACKOFF_CAP = 60_000;
|
|
1152
1173
|
while (this.running) {
|
|
1153
1174
|
try {
|
|
1175
|
+
await deliverSeatAnswers(this.seatWorkDeps.askDeps!);
|
|
1154
1176
|
const wantCallbackQuery = this.callbackHandlers.size > 0;
|
|
1155
1177
|
const wantReaction = this.reactionHandlers.size > 0;
|
|
1156
1178
|
// allowed_updates 는 명시한 것만 받으므로 등록된 핸들러 종류만 추가(비파괴 — 핸들러
|
|
@@ -1292,7 +1314,11 @@ export class TelegramBot {
|
|
|
1292
1314
|
this.log('telegram bot stopped');
|
|
1293
1315
|
}
|
|
1294
1316
|
|
|
1295
|
-
stop(): void {
|
|
1317
|
+
stop(): void {
|
|
1318
|
+
this.running = false;
|
|
1319
|
+
if (this.seatAskTimer) clearInterval(this.seatAskTimer);
|
|
1320
|
+
this.seatAskTimer = null;
|
|
1321
|
+
}
|
|
1296
1322
|
|
|
1297
1323
|
/** Download + normalize this message's attachments into the shape
|
|
1298
1324
|
* the ACP content-blocks module consumes. Called lazily by slash
|
|
@@ -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. */
|