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

7.7 KiB

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:

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).