paseo-acp-agy 1.1.0
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/LICENSE +21 -0
- package/PROTOCOL.md +149 -0
- package/README.md +137 -0
- package/dist/acp-server.d.ts +28 -0
- package/dist/acp-server.js +575 -0
- package/dist/antigravity-process.d.ts +52 -0
- package/dist/antigravity-process.js +535 -0
- package/dist/attachments.d.ts +1 -0
- package/dist/attachments.js +102 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +51 -0
- package/dist/logger.d.ts +19 -0
- package/dist/logger.js +124 -0
- package/dist/permissions.d.ts +11 -0
- package/dist/permissions.js +29 -0
- package/dist/protocol.d.ts +201 -0
- package/dist/protocol.js +471 -0
- package/dist/session-store.d.ts +27 -0
- package/dist/session-store.js +74 -0
- package/dist/session.d.ts +66 -0
- package/dist/session.js +227 -0
- package/dist/slash-commands.d.ts +33 -0
- package/dist/slash-commands.js +434 -0
- package/dist/version.d.ts +17 -0
- package/dist/version.js +95 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Arthur Melo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/PROTOCOL.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Protocol Specification & Mapping: Antigravity stream-json ↔ ACP
|
|
2
|
+
|
|
3
|
+
`agy-acp` exposes the official Google Antigravity CLI (`agy`) to Paseo through ACP while keeping authentication and model execution inside the official CLI.
|
|
4
|
+
|
|
5
|
+
## Antigravity process
|
|
6
|
+
|
|
7
|
+
Each Paseo ACP session owns one persistent `agy` process:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
agy --input-format stream-json --output-format stream-json --print=""
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Optional session flags are applied when the process starts or is restarted:
|
|
14
|
+
|
|
15
|
+
- `--model <model-id>`
|
|
16
|
+
- `--effort <low|medium|high>` when supported by the selected model
|
|
17
|
+
- `--mode <mode-id>`
|
|
18
|
+
- `--conversation <conversation-id>` when resuming
|
|
19
|
+
- `--sandbox`
|
|
20
|
+
- `--dangerously-skip-permissions` only when explicitly configured
|
|
21
|
+
|
|
22
|
+
Configuration changes schedule a controlled restart before the next prompt. On POSIX systems `agy` is launched as a process-group leader; shutdown, restart and turn cancellation signal the process group so tool subprocesses are not left orphaned.
|
|
23
|
+
|
|
24
|
+
## Antigravity stream-json
|
|
25
|
+
|
|
26
|
+
### Input
|
|
27
|
+
|
|
28
|
+
One NDJSON object per user turn:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{"event":"user","message":{"content":"User prompt"}}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Output
|
|
35
|
+
|
|
36
|
+
`agy` emits NDJSON events:
|
|
37
|
+
|
|
38
|
+
- `init` — process/session metadata and `conversation_id`
|
|
39
|
+
- `step_update` — streaming assistant text, thoughts, tool calls and usage
|
|
40
|
+
- `result` — terminal result for a prompt turn
|
|
41
|
+
|
|
42
|
+
One open stdin/stdout stream is reused for multiple turns.
|
|
43
|
+
|
|
44
|
+
## ACP wire methods
|
|
45
|
+
|
|
46
|
+
The ACP wire protocol uses snake_case method names. `agy-acp` accepts these methods:
|
|
47
|
+
|
|
48
|
+
| ACP method | agy-acp behavior |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `initialize` | Advertise provider/session capabilities |
|
|
51
|
+
| `session/new` | Create a new isolated session |
|
|
52
|
+
| `session/resume` | Restore and validate a persisted ACP session without history replay |
|
|
53
|
+
| `session/prompt` | Send a prompt to the persistent `agy` process |
|
|
54
|
+
| `session/cancel` | Cancel the reserved/running turn; signal the `agy` process group when running |
|
|
55
|
+
| `session/close` | Persist state and terminate the process tree |
|
|
56
|
+
| `session/set_mode` | Change mode; restart before the next turn if needed |
|
|
57
|
+
| `session/set_model` | Change base model; restart before the next turn if needed |
|
|
58
|
+
| `session/set_config_option` | Change `thought_level` / reasoning effort |
|
|
59
|
+
| `session/update` | Stream messages, thoughts, tool calls, usage and commands to Paseo |
|
|
60
|
+
| `provider/usage` | Return current Antigravity quota and credit state |
|
|
61
|
+
|
|
62
|
+
For backwards compatibility, the server also accepts the exact pre-hardening aliases:
|
|
63
|
+
|
|
64
|
+
- `setSessionMode`
|
|
65
|
+
- `unstable_setSessionModel`
|
|
66
|
+
- `setSessionConfigOption`
|
|
67
|
+
|
|
68
|
+
### `session/load`
|
|
69
|
+
|
|
70
|
+
`agy-acp` currently advertises `loadSession: false`. ACP `session/load` requires the agent to replay prior conversation history through `session/update` notifications. The adapter intentionally does not claim that capability until replay is implemented. Paseo persistence uses `session/resume`, which restores model context without replaying already-rendered history.
|
|
71
|
+
|
|
72
|
+
## Turn concurrency and cancellation
|
|
73
|
+
|
|
74
|
+
A session-level prompt operation is reserved synchronously before any slash-command or process startup/restart `await`. Therefore:
|
|
75
|
+
|
|
76
|
+
- a second `session/prompt` cannot enter while `/resume`, `/usage`, or another asynchronous slash command is running;
|
|
77
|
+
- a second prompt cannot enter during first-turn startup;
|
|
78
|
+
- cancellation received during startup prevents the user prompt from ever being written to `agy` stdin;
|
|
79
|
+
- stale child events cannot resolve or reject a newer turn;
|
|
80
|
+
- each active process turn tracks the exact child process that owns it;
|
|
81
|
+
- the session prompt reservation is always released in `finally`, for both slash-command and ordinary prompt paths.
|
|
82
|
+
|
|
83
|
+
## Models and thinking effort
|
|
84
|
+
|
|
85
|
+
`agy-acp` discovers models through `agy models`. Model variants ending in `-high`, `-medium` or `-low` are exposed as a base model plus a separate ACP `thought_level` config option. Discovery is cached for one minute per `agy` binary path, with a fallback list if discovery fails.
|
|
86
|
+
|
|
87
|
+
## Session persistence and resume validation
|
|
88
|
+
|
|
89
|
+
ACP session metadata is stored outside the repository under:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
${XDG_STATE_HOME:-~/.local/state}/agy-acp/sessions/
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Each session is stored in its own `0600` JSON file inside a `0700` directory. Persisted state contains only:
|
|
96
|
+
|
|
97
|
+
- ACP `sessionId`
|
|
98
|
+
- Antigravity `conversation_id`
|
|
99
|
+
- cwd
|
|
100
|
+
- model
|
|
101
|
+
- effort
|
|
102
|
+
- mode
|
|
103
|
+
- accumulated token/cost/context usage
|
|
104
|
+
- update timestamp
|
|
105
|
+
|
|
106
|
+
No Google credentials or OAuth tokens are read or persisted by the adapter.
|
|
107
|
+
|
|
108
|
+
When Paseo requests `session/resume`, the adapter starts `agy --conversation <id>`, waits for its `init` event, and verifies that Antigravity actually opened the requested conversation before returning success.
|
|
109
|
+
|
|
110
|
+
## Token usage, context window, cost and quota
|
|
111
|
+
|
|
112
|
+
- Cumulative `inputTokens`, `outputTokens`, `cachedInputTokens` and `totalTokens` are persisted per ACP session.
|
|
113
|
+
- Usage from a completed Antigravity `result` is recorded even when the turn ends with `status: ERROR`, because model/tool work may already have consumed billable tokens.
|
|
114
|
+
- The model used for cost calculation is snapshotted at the beginning of the prompt operation. A `session/set_model` received mid-turn applies to the next Antigravity process, without repricing the current turn.
|
|
115
|
+
- Raw session cost is accumulated without per-turn rounding. Rounding occurs only in UI-facing ACP payloads, preserving micro-costs across many small turns.
|
|
116
|
+
- Context-window limits are attached to model definitions and streaming usage updates.
|
|
117
|
+
- `fetchAntigravityUsage()` treats `/usage` as the primary availability probe. A failed, timed-out or missing `agy` command returns `status: unavailable` with an error instead of a false zero-usage `available` result.
|
|
118
|
+
- `/credits` failure is treated as partial data loss when `/usage` succeeds: quota remains available, balances are omitted and the error explains the missing credit data.
|
|
119
|
+
|
|
120
|
+
## Child-process lifecycle
|
|
121
|
+
|
|
122
|
+
- One ACP session = one `agy` process tree.
|
|
123
|
+
- On POSIX, the child is a process-group leader and signals target the whole group.
|
|
124
|
+
- A child being replaced is terminated and awaited before a replacement is spawned.
|
|
125
|
+
- `SIGTERM` is used first; `SIGKILL` follows a bounded timeout.
|
|
126
|
+
- Child event handlers are identity-checked so an old process cannot alter a newer process.
|
|
127
|
+
|
|
128
|
+
## Attachments
|
|
129
|
+
|
|
130
|
+
Inline base64 images are written under the adapter state directory with `0600` permissions and a content-addressed file name. The adapter:
|
|
131
|
+
|
|
132
|
+
- accepts only known image MIME types;
|
|
133
|
+
- validates base64 by decode/re-encode equivalence;
|
|
134
|
+
- enforces a default 20 MiB decoded-size limit (`AGY_ACP_MAX_ATTACHMENT_BYTES` can override it);
|
|
135
|
+
- converts valid `file://` URIs with Node's URL parser.
|
|
136
|
+
|
|
137
|
+
## Slash commands
|
|
138
|
+
|
|
139
|
+
The adapter intercepts selected local commands such as `/resume`, `/usage`, `/credits`, `/skills`, `/agents`, `/changelog` and `/help`.
|
|
140
|
+
|
|
141
|
+
- Resume identifiers are validated before filesystem lookup.
|
|
142
|
+
- Paseo session IDs resolve through the persisted session store rather than by scraping logs.
|
|
143
|
+
- `/resume` stats all conversation candidates first and reads transcript contents only for the newest requested entries.
|
|
144
|
+
- `/resume <id>` validates the Antigravity conversation before reporting success.
|
|
145
|
+
- Subprocess-based slash commands use bounded timeouts and output buffers.
|
|
146
|
+
|
|
147
|
+
## CI
|
|
148
|
+
|
|
149
|
+
`.github/workflows/agy-acp.yml` runs `npm ci`, `npm audit --omit=dev --audit-level=high`, `npm run typecheck` and `npm test` for changes under `tools/agy-acp`.
|
package/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# paseo-acp-agy
|
|
2
|
+
|
|
3
|
+
> **Agent Client Protocol (ACP)** provider adapter connecting **Google Antigravity (`agy`)** to **[Paseo](https://paseo.sh)**, **Zed**, and any ACP-compliant agent client over stdio.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/tucomel/paseo-acp-agy/actions/workflows/ci.yml)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
`paseo-acp-agy` allows you to use Google Antigravity as a first-class agent provider inside Paseo. It implements the JSON-RPC [Agent Client Protocol](https://agentclientprotocol.com) over standard input/output (`stdio`), dynamically exposing supported models, tracking session token usage, calculating real-time cost, displaying context window usage, and supporting slash commands.
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
- **Zero-Downtime Daemon Compatibility**: Conforms to the [Paseo Server & CLI specification](https://paseo.sh/docs#server--cli). Updates to this adapter apply to future agent launches without restarting the Paseo daemon.
|
|
16
|
+
- **Dynamic Model Catalog**: Exposes Google Gemini (Flash, Pro) and Anthropic Claude models configured in your Antigravity CLI environment.
|
|
17
|
+
- **Usage & Quota Telemetry**: Real-time context window meters, prompt/output token tracking, pricing windows, and quota limit notifications.
|
|
18
|
+
- **Session Management**: Native support for session modes (Default / Plan mode), session cancellation, and resume.
|
|
19
|
+
- **Slash Commands**: In-session support for `/help`, `/usage`, and `/resume`.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Quick Start in Paseo
|
|
24
|
+
|
|
25
|
+
### 1. Configure Provider in Paseo
|
|
26
|
+
|
|
27
|
+
Add `antigravity` under `agents.providers` in your `~/.paseo/config.json`:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"agents": {
|
|
32
|
+
"providers": {
|
|
33
|
+
"antigravity": {
|
|
34
|
+
"extends": "acp",
|
|
35
|
+
"label": "Antigravity",
|
|
36
|
+
"command": ["npx", "-y", "paseo-acp-agy", "--acp"],
|
|
37
|
+
"enabled": true
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
> **Local / Development Setup:**
|
|
45
|
+
> If you cloned this repository locally, you can compile and point directly to the binary:
|
|
46
|
+
> ```json
|
|
47
|
+
> "command": ["node", "/path/to/paseo-acp-agy/dist/index.js"]
|
|
48
|
+
> ```
|
|
49
|
+
> Or install globally:
|
|
50
|
+
> ```bash
|
|
51
|
+
> npm install -g paseo-acp-agy
|
|
52
|
+
> ```
|
|
53
|
+
> And configure `"command": ["paseo-acp-agy"]`.
|
|
54
|
+
|
|
55
|
+
### 2. Reload Paseo Configuration
|
|
56
|
+
|
|
57
|
+
Apply changes immediately without restarting the daemon:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
paseo reload
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3. Verify with Diagnostics
|
|
64
|
+
|
|
65
|
+
Run the official Paseo provider diagnostic command:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
paseo provider diagnostic antigravity
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
List detected models:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
paseo provider models antigravity
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 4. Run an Agent
|
|
78
|
+
|
|
79
|
+
Launch a task directly from your terminal:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
paseo run --provider antigravity "Analyze the repository architecture"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Or select **Antigravity** from the provider dropdown in the Paseo Desktop App or Web UI (`https://app.paseo.sh`).
|
|
86
|
+
|
|
87
|
+
### 5. Official Paseo Catalog Entry
|
|
88
|
+
|
|
89
|
+
To include `paseo-acp-agy` in Paseo's built-in provider store (`ACP_PROVIDER_CATALOG`), see the [Paseo Catalog Specification](docs/paseo-catalog-entry.md).
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Requirements
|
|
94
|
+
|
|
95
|
+
- **Node.js**: >= 20.0.0 (Node.js 22 recommended)
|
|
96
|
+
- **Google Antigravity CLI (`agy`)**: Installed and authenticated in your `PATH` (or specified via `AGY_BIN_PATH`).
|
|
97
|
+
- **Paseo**: [Paseo CLI / Daemon](https://paseo.sh/docs#server--cli) (`@getpaseo/cli`) >= 0.7.0.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Environment Variables
|
|
102
|
+
|
|
103
|
+
| Variable | Description | Default |
|
|
104
|
+
| :--- | :--- | :--- |
|
|
105
|
+
| `AGY_BIN_PATH` | Path to the Google Antigravity binary | Auto-detected from `PATH` or `~/.local/bin/agy` |
|
|
106
|
+
| `AGY_ACP_LOG_FILE` | Enable debug file logging | Disabled |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Development
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Clone repository
|
|
114
|
+
git clone https://github.com/tucomel/paseo-acp-agy.git
|
|
115
|
+
cd paseo-acp-agy
|
|
116
|
+
|
|
117
|
+
# Install dependencies
|
|
118
|
+
npm install
|
|
119
|
+
|
|
120
|
+
# Typecheck
|
|
121
|
+
npm run typecheck
|
|
122
|
+
|
|
123
|
+
# Run test suite (56+ unit & protocol tests)
|
|
124
|
+
npm test
|
|
125
|
+
|
|
126
|
+
# Build distribution
|
|
127
|
+
npm run build
|
|
128
|
+
|
|
129
|
+
# Test ACP initialization via stdio
|
|
130
|
+
printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":1,"clientCapabilities":{}}}\n' | node dist/index.js
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
MIT © [Arthur Melo](https://github.com/tucomel)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Readable, Writable } from "node:stream";
|
|
2
|
+
import { SessionManager } from "./session.js";
|
|
3
|
+
export declare class ACPServer {
|
|
4
|
+
private sessionManager;
|
|
5
|
+
private input;
|
|
6
|
+
private output;
|
|
7
|
+
private binaryPath;
|
|
8
|
+
private rl;
|
|
9
|
+
private isRunning;
|
|
10
|
+
constructor(options?: {
|
|
11
|
+
input?: Readable;
|
|
12
|
+
output?: Writable;
|
|
13
|
+
sessionManager?: SessionManager;
|
|
14
|
+
binaryPath?: string;
|
|
15
|
+
});
|
|
16
|
+
start(): void;
|
|
17
|
+
private send;
|
|
18
|
+
private sendNotification;
|
|
19
|
+
private sendSuccess;
|
|
20
|
+
private sendError;
|
|
21
|
+
private publishCommands;
|
|
22
|
+
private sessionState;
|
|
23
|
+
private requireSession;
|
|
24
|
+
private validateModel;
|
|
25
|
+
private turnUsagePayload;
|
|
26
|
+
private handleLine;
|
|
27
|
+
stop(): Promise<void>;
|
|
28
|
+
}
|