Typescript SDK for ACP extension methods#7319
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a custom-request (“extension methods”) layer to goose-acp, including schema generation and a small TypeScript package intended to provide generated ACP request/response types + a typed client for _goose/* methods (and wires that package into the desktop app via a local file: dependency).
Changes:
- Add
_goose/*custom request routing in the ACP server plus method handlers (sessions, tools, extensions, etc.) and tests. - Introduce a proc-macro (
goose-acp-macros) to generate both a dispatcher (handle_custom_request) and schema metadata (custom_method_schemas) from#[custom_method]handlers. - Add a Rust schema/meta generator binary and a TS codegen package (
ui/acp) that generates TS types/Zod validators/client from the Rust-emitted schema.
Reviewed changes
Copilot reviewed 15 out of 23 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| ui/desktop/package.json | Adds a local dependency on the new goose-acp-types package. |
| ui/desktop/package-lock.json | Locks the new local dependency and updates lock metadata accordingly. |
| ui/acp/tsconfig.json | Adds TS build configuration for the ACP types/client package. |
| ui/acp/src/index.ts | Public entrypoint re-exporting generated artifacts and GooseClient. |
| ui/acp/src/generated/zod.gen.ts | Generated Zod validators for ACP extension method payloads. |
| ui/acp/src/generated/types.gen.ts | Generated TS types for ACP extension method payloads. |
| ui/acp/src/generated/index.ts | Generated barrel + GOOSE_EXT_METHODS metadata list. |
| ui/acp/src/generated/client.gen.ts | Generated typed client wrapper around an extMethod provider. |
| ui/acp/package.json | Defines the goose-acp-types package metadata and scripts. |
| ui/acp/package-lock.json | Locks dependencies for the ui/acp package. |
| ui/acp/generate-schema.ts | Script to generate TS artifacts from the Rust-emitted schema/meta. |
| crates/goose-acp/tests/fixtures/server.rs | Adds a helper accessor to get the connection context for tests. |
| crates/goose-acp/tests/custom_requests_test.rs | New tests covering _goose/* custom request behavior. |
| crates/goose-acp/src/server.rs | Adds custom method handlers and routes underscore-prefixed requests to the dispatcher. |
| crates/goose-acp/src/lib.rs | Exposes the new custom_requests module. |
| crates/goose-acp/src/custom_requests.rs | Defines request/response structs + schema metadata container for custom methods. |
| crates/goose-acp/src/bin/generate_acp_schema.rs | New binary to emit acp-schema.json and acp-meta.json. |
| crates/goose-acp/acp-schema.json | Generated JSON schema for extension requests/responses. |
| crates/goose-acp/acp-meta.json | Generated method→(requestType/responseType) metadata for TS client generation. |
| crates/goose-acp/Cargo.toml | Adds schema-gen bin + dependencies (schemars, goose-acp-macros, serde derive). |
| crates/goose-acp-macros/src/lib.rs | New proc-macro implementing #[custom_methods] generation. |
| crates/goose-acp-macros/Cargo.toml | New proc-macro crate manifest. |
| Cargo.lock | Locks new Rust dependencies/crates. |
Files not reviewed (2)
- ui/acp/package-lock.json: Language not supported
- ui/desktop/package-lock.json: Language not supported
| /// Add an extension to an active session. | ||
| /// Method: `_agent/extensions/add` | ||
| #[derive(Debug, Deserialize, JsonSchema)] |
There was a problem hiding this comment.
The doc comments reference method names like _agent/.../_session/.../_config/..., but the actual custom request routing and tests use the _goose/... prefix; update these doc comments so the generated JSON schema/type docs don’t advertise the wrong method names.
There was a problem hiding this comment.
yeah this seems right
There was a problem hiding this comment.
Heh, yeah, here's the AIs adding comments, making them outdated, and then catching them in review!
There was a problem hiding this comment.
Heh, yeah, here's the AIs adding comments, making them outdated, and then catching them in review!
The final frontier
| "main": "./src/index.ts", | ||
| "types": "./src/index.ts", | ||
| "scripts": { |
There was a problem hiding this comment.
main/types point at TypeScript source files, but this package is consumed from ui/desktop via a file: dependency; unless the package is built to JS and these fields (or an exports map) point at emitted .js/.d.ts, importing goose-acp-types will fail at runtime/bundling.
| "main": "./src/index.ts", | |
| "types": "./src/index.ts", | |
| "scripts": { | |
| "main": "./dist/index.js", | |
| "types": "./dist/index.d.ts", | |
| "scripts": { | |
| "build": "tsc -p tsconfig.json", |
| export * from "./generated/index.js"; | ||
| export * from "./generated/zod.gen.js"; | ||
| export { GooseClient } from "./generated/client.gen.js"; |
There was a problem hiding this comment.
These re-exports target ./generated/*.js, but the repo contains *.ts sources; without a build step that emits the corresponding .js files (and a package entrypoint that uses the built output), consumers won’t be able to resolve these imports.
| export * from "./generated/index.js"; | |
| export * from "./generated/zod.gen.js"; | |
| export { GooseClient } from "./generated/client.gen.js"; | |
| export * from "./generated/index.ts"; | |
| export * from "./generated/zod.gen.ts"; | |
| export { GooseClient } from "./generated/client.gen.ts"; |
| * npm run generate # build Rust schema, then generate TS | ||
| */ | ||
|
|
||
| import { createClient } from "@hey-api/openapi-ts"; | ||
| import { execSync } from "child_process"; |
There was a problem hiding this comment.
The header comment says npm run generate builds the Rust schema, but this script only reads existing JSON files (and execSync is currently unused); either invoke the new Rust schema generator here or update the usage/docs and remove the unused import to avoid confusing future regenerations.
| * npm run generate # build Rust schema, then generate TS | |
| */ | |
| import { createClient } from "@hey-api/openapi-ts"; | |
| import { execSync } from "child_process"; | |
| * npm run generate # generate TS types from existing JSON schemas | |
| */ | |
| import { createClient } from "@hey-api/openapi-ts"; |
| /// Add an extension to an active session. | ||
| /// Method: `_agent/extensions/add` | ||
| #[derive(Debug, Deserialize, JsonSchema)] |
There was a problem hiding this comment.
yeah this seems right
crates/goose-acp/acp-meta.json
Outdated
| }, | ||
| { | ||
| "method": "tool/call", | ||
| "requestType": null, |
There was a problem hiding this comment.
why are the request and response types null on these ones?
There was a problem hiding this comment.
Opus decided just to stub those out returning "unimplemented". I just removed them -- we can add as necessary
|
Looks like |
* 'main' of github.com:block/goose: (40 commits) Remove trailing space from links (#7156) fix: detect low balance and prompt for top up (#7166) feat(apps): add support for MCP apps to sample (#7039) Typescript SDK for ACP extension methods (#7319) chore: upgrade to rmcp 0.16.0 (#7274) docs: add monitoring subagent activity section (#7323) docs: document Desktop UI recipe editing for model/provider and extensions (#7327) docs: add CLAUDE_THINKING_BUDGET and CLAUDE_THINKING_ENABLED environm… (#7330) fix: display 'Code Mode' instead of 'code_execution' in CLI (#7321) docs: add Permission Policy documentation for MCP Apps (#7325) update RPI plan prompt (#7326) docs: add CLI syntax highlighting theme customization (#7324) fix(cli): replace shell-based update with native Rust implementation (#7148) docs: rename Code Execution extension to Code Mode extension (#7316) docs: remove ALPHA_FEATURES flag from documentation (#7315) docs: escape variable syntax in recipes (#7314) docs: update OTel environment variable and config guides (#7221) docs: system proxy settings (#7311) docs: add Summon extension tutorial and update Skills references (#7310) docs: agent session id (#7289) ...
* origin/main: fix(ci): deflake smoke tests for Google models (#7344) feat: add Cerebras provider support (#7339) fix: skip whitespace-only text blocks in Anthropic message (#7343) fix(goose-acp): heap allocations (#7322) Remove trailing space from links (#7156) fix: detect low balance and prompt for top up (#7166) feat(apps): add support for MCP apps to sample (#7039) Typescript SDK for ACP extension methods (#7319) chore: upgrade to rmcp 0.16.0 (#7274) docs: add monitoring subagent activity section (#7323) docs: document Desktop UI recipe editing for model/provider and extensions (#7327) docs: add CLAUDE_THINKING_BUDGET and CLAUDE_THINKING_ENABLED environm… (#7330) fix: display 'Code Mode' instead of 'code_execution' in CLI (#7321) docs: add Permission Policy documentation for MCP Apps (#7325) update RPI plan prompt (#7326) docs: add CLI syntax highlighting theme customization (#7324) fix(cli): replace shell-based update with native Rust implementation (#7148) docs: rename Code Execution extension to Code Mode extension (#7316)
* origin/main: (29 commits) fix(ci): deflake smoke tests for Google models (#7344) feat: add Cerebras provider support (#7339) fix: skip whitespace-only text blocks in Anthropic message (#7343) fix(goose-acp): heap allocations (#7322) Remove trailing space from links (#7156) fix: detect low balance and prompt for top up (#7166) feat(apps): add support for MCP apps to sample (#7039) Typescript SDK for ACP extension methods (#7319) chore: upgrade to rmcp 0.16.0 (#7274) docs: add monitoring subagent activity section (#7323) docs: document Desktop UI recipe editing for model/provider and extensions (#7327) docs: add CLAUDE_THINKING_BUDGET and CLAUDE_THINKING_ENABLED environm… (#7330) fix: display 'Code Mode' instead of 'code_execution' in CLI (#7321) docs: add Permission Policy documentation for MCP Apps (#7325) update RPI plan prompt (#7326) docs: add CLI syntax highlighting theme customization (#7324) fix(cli): replace shell-based update with native Rust implementation (#7148) docs: rename Code Execution extension to Code Mode extension (#7316) docs: remove ALPHA_FEATURES flag from documentation (#7315) docs: escape variable syntax in recipes (#7314) ... # Conflicts: # ui/desktop/src/components/McpApps/McpAppRenderer.tsx # ui/desktop/src/components/McpApps/types.ts
* 'main' of github.com:block/goose: (24 commits) Docs: claude code uses stream-json (#7358) Improve link confirmation modal (#7333) fix(ci): deflake smoke tests for Google models (#7344) feat: add Cerebras provider support (#7339) fix: skip whitespace-only text blocks in Anthropic message (#7343) fix(goose-acp): heap allocations (#7322) Remove trailing space from links (#7156) fix: detect low balance and prompt for top up (#7166) feat(apps): add support for MCP apps to sample (#7039) Typescript SDK for ACP extension methods (#7319) chore: upgrade to rmcp 0.16.0 (#7274) docs: add monitoring subagent activity section (#7323) docs: document Desktop UI recipe editing for model/provider and extensions (#7327) docs: add CLAUDE_THINKING_BUDGET and CLAUDE_THINKING_ENABLED environm… (#7330) fix: display 'Code Mode' instead of 'code_execution' in CLI (#7321) docs: add Permission Policy documentation for MCP Apps (#7325) update RPI plan prompt (#7326) docs: add CLI syntax highlighting theme customization (#7324) fix(cli): replace shell-based update with native Rust implementation (#7148) docs: rename Code Execution extension to Code Mode extension (#7316) ...
This PR aims to generate a typescript SDK for the goose agent to be used over ACP, similar to what we have for the goosed HTTP server. The goal is to have a client wrapper for the ACP ClientSideConnection that calls goose methods using ACP's extension methods