An open API service indexing awesome lists of open source software.

https://github.com/mumez/pharo-acp

ACP (Agent Client Protocol) client library for Pharo Smalltalk.
https://github.com/mumez/pharo-acp

acp pharo-smalltalk

Last synced: 5 months ago
JSON representation

ACP (Agent Client Protocol) client library for Pharo Smalltalk.

Awesome Lists containing this project

README

          

# pharo-acp

ACP (Agent Client Protocol) client library for Pharo Smalltalk.

Enables Pharo to communicate with ACP-compatible coding agents ([Gemini CLI](https://github.com/google-gemini/gemini-cli), [OpenCode](https://opencode.ai/), etc.) over JSON-RPC 2.0 via stdio.

References the [ACP TypeScript SDK](https://github.com/agentclientprotocol/typescript-sdk).

## Requirements

- Pharo 12+ (For Windows, use WSL since OSSubprocess does not support Windows)

## Installation

```smalltalk
Metacello new
baseline: 'ACP';
repository: 'github://mumez/pharo-acp:main/src';
load.
```

To include tests:

```smalltalk
Metacello new
baseline: 'ACP';
repository: 'github://mumez/pharo-acp:main/src';
load: 'Tests'.
```

## Quick Start

You need an ACP-compatible agent installed. Currently tested with:

- [Gemini CLI](https://github.com/google-gemini/gemini-cli) — `gemini --experimental-acp`
- [claude-code-acp](https://github.com/zed-industries/claude-agent-acp) — `claude-code-acp`
- [OpenCode](https://github.com/anomalyco/opencode) — `opencode acp`

```smalltalk
client := ACPClient new.

"Use Gemini CLI:"
client agentCommand: '/usr/bin/env' arguments: #('gemini' '--experimental-acp').
"Or claude-code-acp:"
"client agentCommand: '/usr/bin/env' arguments: #('claude-code-acp')."

client connect.

[
"Initialize"
client initializeBy: [ :params | "uses default protocolVersion and capabilities" ].

"Create session"
session := client newSessionBy: [ :params |
params cwd: FileSystem workingDirectory fullName ].

"Send prompt (blocks until agent responds)"
result := client promptBy: [ :params |
params sessionId: session sessionId.
params textPrompt: 'Hello!' ].

Transcript show: 'Stop reason: ', result stopReason; cr.
] ensure: [ client disconnect ].
```

Example Transcript output (Gemini CLI)

```
Session update [agent_thought_chunk]: ACPSessionUpdate(a Dictionary('sessionId'->'42f04b38-b27d-4adf-b1e5-f46f1d69216e' 'update'->a Dictionary('content'->a Dictionary('text'->'**Awaiting Initial Input**

I''ve processed the initial setup details: directory structure and environment specs, which point to a Pharo Smalltalk environment. Currently, I''m simply standing by, waiting for the user''s first directive or request before moving forward.

' 'type'->'text' ) 'sessionUpdate'->'agent_thought_chunk' ) ))
Session update [agent_message_chunk]: ACPSessionUpdate(a Dictionary('sessionId'->'42f04b38-b27d-4adf-b1e5-f46f1d69216e' 'update'->a Dictionary('content'->a Dictionary('text'->'Hello! How can I help you today?' 'type'->'text' ) 'sessionUpdate'->'agent_message_chunk' ) ))
Stop reason: end_turn

```

## Example: Chat UI

[pharo-acp-chat-ui](https://github.com/mumez/pharo-acp-chat-ui) is a minimal chat interface built on top of this library.

```smalltalk
"Launch with Gemini CLI:"
ACPChatPresenter gemini open.

"Or with Claude Code:"
ACPChatPresenter claude open.
```

## Custmizing update handler

By default, `ACPClient` uses `ACPTranscriptHandler` which logs session updates to the Transcript and auto-approves permission requests. Provide a custom handler by subclassing `ACPClientHandler`:

```smalltalk
client := ACPClient new.
client handler: MyCustomHandler new.
```

## Smoke Test

Run the smoke test against the TypeScript SDK example agent.

### Prerequisites

- Node.js and npm installed
- Clone the [TypeScript SDK](https://github.com/agentclientprotocol/typescript-sdk):
```bash
git clone https://github.com/agentclientprotocol/typescript-sdk.git
cd typescript-sdk
npm install
```
- Verify the example agent works:
```bash
npx tsx src/examples/agent.ts
```
Paste `{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":1}}` and press Enter — you should get a response.

### Run from Pharo

```smalltalk
"Set the path to the TypeScript example agent (once per image)"
ACPSmokeTest agentPath: '/path/to/typescript-sdk/src/examples/agent.ts'.

"Run the test"
ACPSmokeTest suite run.
```

## Architecture

Five-layer stack, each layer depending only on layers below:

```
ACPClient — User-facing facade (connect/prompt/cancel)
ACPClientConnection — ACP protocol methods + handler registration
ACPConnection — Bidirectional JSON-RPC engine (readLoop + pending requests)
ACPNdJsonTransport — ndjson line framing + mutex-protected writes
ACPProcessLauncher — OSSUnixSubprocess wrapper (non-blocking pipes)
```

## License

MIT