Files
honker/docs/plan.md
T
jbrechtel 722169adfd Expanded ACP support
Can now send chain-of-thought messages
Manage terminals
Control agent working directory
Adding more tool support and notifications
Some session management
Added image support
Added slash commands
2026-05-09 16:25:20 -04:00

234 lines
7.7 KiB
Markdown

# Honker ACP Bridge — Implementation Plan
## Current State
What's implemented today:
- ✅ Initialize ACP connection to Goose (`goose acp` over stdio)
- ✅ Create new sessions (one per Signal contact)
- ✅ Send text prompts and collect text responses
- ✅ Interactive permission requests over Signal (numbered options)
- ✅ Signal-cli lifecycle management and socket communication
---
## Phase 1: Essential — Make the Bridge Robust
### 1.1 Terminal Execution (Client ← Agent)
**Priority: HIGH — Goose cannot function without this**
Goose's primary tool is running shell commands. The ACP protocol has the agent
ask the *client* to execute commands via `create_terminal`, then polls output
with `terminal_output` and `wait_for_terminal_exit`.
Currently we return `None` for all terminal methods, which means Goose can't
run any commands. We need to:
- `create_terminal(command, args, cwd, env)` → spawn a real subprocess, return
a `terminal_id`
- `terminal_output(terminal_id)` → return accumulated stdout/stderr
- `wait_for_terminal_exit(terminal_id)` → await process completion, return exit code
- `release_terminal(terminal_id)` → clean up
- `kill_terminal(terminal_id)` → kill the subprocess
Implementation: a `TerminalManager` class that tracks running subprocesses
keyed by terminal_id.
### 1.2 File System Operations (Client ← Agent)
**Priority: HIGH — Goose cannot edit code without this**
The agent asks the client to read/write files:
- `read_text_file(path, line, limit)` → read from the local filesystem, return content
- `write_text_file(path, content)` → write to the local filesystem
Currently we return `None`, so Goose can't read or write files.
These should be straightforward to implement against the local filesystem.
We should also advertise these capabilities in `ClientCapabilities` during
`initialize`:
```python
ClientCapabilities(
fs=FileSystemCapabilities(read_text_file=True, write_text_file=True),
terminal=True,
)
```
### 1.3 Cancellation
**Priority: MEDIUM**
Allow Signal users to cancel a running prompt. The user could send a special
command (e.g. `/cancel`) while a prompt is in progress. We'd call
`conn.cancel(session_id)` to tell Goose to stop.
The `PromptResponse.stop_reason` already distinguishes `cancelled` from
`end_turn`, `max_tokens`, `refusal`, and `max_turn_requests` — we should
handle each appropriately in the reply.
### 1.4 Stop Reason Handling
**Priority: MEDIUM**
Currently we only look at the response text. We should handle all stop reasons:
- `end_turn` — normal completion (current behavior)
- `max_tokens` — context limit hit; notify user
- `max_turn_requests` — agent hit its turn limit; notify user
- `refusal` — agent refused the request; notify user
- `cancelled` — user cancelled; acknowledge
---
## Phase 2: Enriched Feedback
### 2.1 Tool Call Notifications
**Priority: MEDIUM**
Forward tool activity as status messages so the Signal user knows what Goose
is doing while working. On `ToolCallStart`, send a brief message like:
"🔧 Running: `ls -la /src`"
On `ToolCallProgress` with status updates, optionally send progress. We need
to be careful not to spam — batch or throttle these.
### 2.2 Agent Thoughts
**Priority: LOW-MEDIUM**
`AgentThoughtChunk` contains the agent's chain-of-thought reasoning. Could
forward these optionally (config flag) as italicized or prefixed messages.
Useful for debugging but noisy for everyday use.
### 2.3 Plan Updates
**Priority: LOW-MEDIUM**
`AgentPlanUpdate` sends a structured plan with entries (content, priority,
status). Could render as a checklist:
```
📋 Plan:
✅ Read the project structure
🔄 Implement the new feature
⬚ Write tests
⬚ Update documentation
```
### 2.4 Usage/Cost Updates
**Priority: LOW**
`UsageUpdate` reports token usage (size, used) and optional `Cost` (amount,
currency). Could send periodic summaries or on-demand via a `/usage` command.
---
## Phase 3: Session Management
### 3.1 Session Persistence (Load/Resume)
**Priority: MEDIUM**
Goose supports `load_session` and `resume_session`. We could persist the
session_id→contact mapping in SQLite (as the README mentions) and restore
sessions across honker restarts.
- `load_session(cwd, session_id)` — restore conversation history
- `resume_session(cwd, session_id)` — resume an interrupted session
- `list_sessions()` — list available sessions
- `close_session(session_id)` — explicitly end a session
User commands: `/sessions`, `/load <id>`, `/new` (force new session)
### 3.2 Session Commands
**Priority: MEDIUM**
Signal user sends special commands (prefix with `/`):
- `/new` — start a fresh session
- `/sessions` — list previous sessions
- `/load <id>` — resume a previous session
- `/cancel` — cancel current prompt
- `/mode <mode>` — change session mode (via `set_session_mode`)
- `/model <model>` — change model (via `set_session_model`)
- `/usage` — show token usage / cost
### 3.3 Session Modes
**Priority: LOW**
Goose supports modes (e.g., "auto" vs "manual" approval). `set_session_mode`
and `CurrentModeUpdate` notifications. Could expose via `/mode` command.
### 3.4 Session Configuration
**Priority: LOW**
`set_config_option` lets the client change boolean/select config options.
`ConfigOptionUpdate` notifications report changes. Could expose via a
`/config` command.
---
## Phase 4: Rich Content
### 4.1 Image Support (Input)
**Priority: MEDIUM**
Signal users can send images. signal-cli provides attachment data. ACP
supports `ImageContentBlock` in prompts (with base64 `data` and `mime_type`).
We could forward Signal image attachments to Goose as image content blocks.
### 4.2 Image Support (Output)
**Priority: LOW**
If Goose responds with `ImageContentBlock` in agent messages, we could send
them as Signal attachments. Less common but possible.
### 4.3 File/Resource Content
**Priority: LOW**
`ResourceContentBlock` and `EmbeddedResourceContentBlock` in agent messages.
Could send file contents as Signal attachments or inline code blocks.
### 4.4 Audio Support
**Priority: LOW**
ACP has `AudioContentBlock`. Signal supports voice messages. Theoretically
bridgeable but Goose doesn't currently use audio.
---
## Phase 5: Advanced / Optional
### 5.1 Multi-User Concurrency
**Priority: MEDIUM**
Currently each contact gets their own session, and prompts run as async tasks.
But there's no protection against a user sending a second message while the
first is still processing. Options:
- Queue messages per-user (process sequentially)
- Allow concurrent prompts (may confuse Goose session state)
- Tell the user "please wait" if a prompt is in progress
### 5.2 Group Messaging
**Priority: LOW**
Signal groups could map to shared Goose sessions. Would need the account
number (already in config) for group message handling. signal-cli has
different envelope structure for group messages.
### 5.3 Extension Methods
**Priority: LOW**
`ext_method` and `ext_notification` are catch-alls for custom protocol
extensions. Log them for now; implement specific ones if Goose uses them.
### 5.4 MCP Server Configuration
**Priority: LOW**
`new_session` accepts `mcp_servers` to connect external tool servers. Could
be configured per-contact or globally in honker config.
---
## Decisions Made
1. **Terminal execution**: Permission gate is enough. No additional sandboxing.
2. **Tool call notifications**: Light — send "🔧 Running: ..." on tool start.
Goose already keeps extensive logs at `~/.local/state/goose/logs/`.
3. **Agent thoughts**: Opt-in via config flag (`forward_thoughts: true`).
4. **Cancellation UX**: `/cancel` plus general `/command` prefix convention.
5. **Multi-user concurrency**: "Please wait" — reject concurrent prompts per user.
6. **Image attachments**: Yes, wire up in Phase 1.
7. **Working directory**: Global config option (`working_directory`).