feat: GoosedClient — HTTP client for CLI-to-goosed communication#7752
feat: GoosedClient — HTTP client for CLI-to-goosed communication#7752bioinfornatics wants to merge 1 commit intoblock:mainfrom
Conversation
Add goosed_client module to goose-cli providing: - GoosedClient: HTTP/SSE client for goosed server communication - GoosedHandle: Managed server process lifecycle (start/stop) - Discovery: Auto-discovery of goosed binary and config - Types: Typed request/response models for all server APIs - Utils: Secret generation, SSE buffer parsing - 20 unit tests covering SSE parsing, secret generation, types Cherry-picked from feature/cli-via-goosed with zero modifications. Files: 8 changed, +1,937 lines Signed-off-by: Jonathan MERCIER <bioinfornatics@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 51879aceea
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| #[derive(Debug, Serialize)] | ||
| #[serde(rename_all = "camelCase")] |
There was a problem hiding this comment.
Serialize agent request bodies with snake_case keys
The client marks several request structs with #[serde(rename_all = "camelCase")] (e.g., StartAgentRequest, ResumeAgentRequest, StopAgentRequest, UpdateProviderRequest), which serializes keys like sessionId/workingDir; however, the corresponding server handlers in crates/goose-server/src/routes/agent.rs deserialize snake_case fields (e.g., session_id, working_dir) without camelCase aliases, so these calls will fail request parsing and return client errors instead of executing.
Useful? React with 👍 / 👎.
| return Err(anyhow!("resume_agent failed ({}): {}", status, body)); | ||
| } | ||
|
|
||
| resp.json().await.map_err(Into::into) |
There was a problem hiding this comment.
Deserialize
/agent/resume response using wrapper type
This method deserializes /agent/resume directly into Session, but the server returns a wrapper object (ResumeAgentResponse) containing session plus extension_results (crates/goose-server/src/routes/agent.rs), so successful resume responses will fail deserialization and resume_agent will error instead of returning the resumed session.
Useful? React with 👍 / 👎.
| impl Drop for GoosedClient { | ||
| fn drop(&mut self) { | ||
| if let Some(mut proc) = self.process.take() { | ||
| let _ = proc.start_kill(); |
There was a problem hiding this comment.
Keep discovered goosed process alive across CLI invocations
spawn_or_discover records a spawned daemon for later reuse, but Drop always calls start_kill() on self.process; in normal CLI execution the client is dropped at process end, so the newly recorded goosed instance is immediately terminated, preventing the advertised cross-invocation discovery/persistence flow from working.
Useful? React with 👍 / 👎.
|
This is a neat idea and closely resembles the direction we're going with ACP. See this issue here tracking that work: #6642 The idea is that goosed will become a backend for any client that speaks ACP (over HTTP or other transport), including the GUI and terminal UIs. If you'd like to contribute to that effort, feel free to post in that issue or tag me or @alexhancock |
Summary
Adds GoosedClient — an HTTP client for CLI-to-goosed server communication.
Features
Changes
crates/goose/src/Verification