refactor(modules): extract approvals + interactive as registry-based modules
Phase 2 / PR #3 of the module refactor. Moves the approval and interactive- question flows out of core and into src/modules/, wired through the response dispatcher and delivery action registries. New modules: - src/modules/interactive/ — registers a response handler that claims pending_questions rows, writes question_response to the session DB, wakes the container. createPendingQuestion call stays inline in delivery.ts (guarded by hasTable) per plan. - src/modules/approvals/ — registers 3 delivery actions (install_packages, request_rebuild, add_mcp_server), a response handler for pending_approvals (including OneCLI action fall-through), an adapter-ready hook that boots the OneCLI manual-approval handler, and a shutdown hook that stops it. OneCLI implementation (src/onecli-approvals.ts) moves into the module. Core lifecycle hooks added (narrow, not registries): - onDeliveryAdapterReady(cb) in delivery.ts — fires when setDeliveryAdapter runs (or immediately if already set). Used by approvals for OneCLI boot. - onShutdown(cb) in index.ts — fires on SIGTERM/SIGINT. Used by approvals for OneCLI teardown. - getDeliveryAdapter() getter in delivery.ts — for live-flow adapter access in registered delivery actions. Core shrinks: delivery.ts 911 → 665 lines, index.ts 405 → 224 lines. dispatchResponse now logs "Unclaimed response" instead of falling through to an inline handler — the inline fallback moved into the two modules. Migration files renamed to the module-<name>-<short>.ts convention: - 003-pending-approvals.ts → module-approvals-pending-approvals.ts - 007-pending-approvals-title-options.ts → module-approvals-title-options.ts Migration.name fields unchanged so existing DBs treat them as already-applied. Degradation verified: emptying the modules barrel builds clean and 137/137 tests pass. Actions would log "Unknown system action"; button clicks would log "Unclaimed response". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
53
src/modules/approvals/agent.md
Normal file
53
src/modules/approvals/agent.md
Normal file
@@ -0,0 +1,53 @@
|
||||
## Self-modification tools (require admin approval)
|
||||
|
||||
Three fire-and-forget tools change your container image or config. Each sends an approval card to an admin's DM; you get notified via system chat on approve/reject.
|
||||
|
||||
### install_packages
|
||||
|
||||
Add apt and/or npm packages to your container image. On approval, the config is updated AND the image is rebuilt in the same step — you'll get a follow-up prompt ~5s after rebuild telling you to verify the packages are available.
|
||||
|
||||
```
|
||||
install_packages({
|
||||
apt: ["ripgrep", "jq"], // names only, no version specs or flags
|
||||
npm: ["@anthropic-ai/sdk"], // global install
|
||||
reason: "need rg for fast code search"
|
||||
})
|
||||
```
|
||||
|
||||
- Max 20 packages per request.
|
||||
- Names must match strict regex (blocks shell injection via `vim; curl evil.com`).
|
||||
- After approval: rebuild runs automatically. You do NOT need to call `request_rebuild` separately.
|
||||
|
||||
### add_mcp_server
|
||||
|
||||
Wire an EXISTING third-party MCP server into your runtime config. You must already know the exact `command` and `args`.
|
||||
|
||||
```
|
||||
add_mcp_server({
|
||||
name: "github",
|
||||
command: "npx",
|
||||
args: ["@modelcontextprotocol/server-github"],
|
||||
env: { GITHUB_TOKEN: "..." }
|
||||
})
|
||||
```
|
||||
|
||||
- Does NOT install packages. Use `install_packages` first if the command isn't already available.
|
||||
- On approval, container is killed so the next message wakes it with the new server wired up.
|
||||
|
||||
### request_rebuild
|
||||
|
||||
Rebuild your container image. Only useful if you've already landed `install_packages` approvals whose rebuild step failed, or if you're recovering from a bad config edit.
|
||||
|
||||
```
|
||||
request_rebuild({ reason: "previous install_packages rebuild failed" })
|
||||
```
|
||||
|
||||
### How approval works
|
||||
|
||||
You won't see the admin's response in your current turn. After approval, the container is killed and next time a message arrives your container starts fresh on the new image. If a follow-up system prompt fires (as with `install_packages`), you'll see it and should act on it — verify the change, report to the user.
|
||||
|
||||
If denied, you'll get a chat message telling you the request was rejected. Do not retry automatically; explain to the user what was denied.
|
||||
|
||||
## Credential approvals (OneCLI)
|
||||
|
||||
When you call an external API that requires credentials, OneCLI may prompt an admin for approval before releasing the token. This happens transparently: the HTTP call blocks until admin approves or denies. No action needed from you — just make the call. If it errors out with a credential failure, tell the user and stop.
|
||||
Reference in New Issue
Block a user