From c7fd8c1ec9a03cf5efd39928fb6c090dd4f662c2 Mon Sep 17 00:00:00 2001 From: daniel Date: Thu, 1 Oct 2026 15:17:06 +0100 Subject: [PATCH 1/2] chore(deps): use published ACP and agentkit forks instead of git pins Depend on agentkit-acp-sdk, agentkit-acp-http and agentkit-acp-schema from crates.io and on the released agentkit-acp 0.10.12 / agentkit-loop 0.10.13. ACP v2 prompt responses now carry the accepted user message id, and the macOS schema pin follows the published schema source. --- Cargo.lock | 100 ++++++++++-------- Cargo.toml | 28 +---- fixtures/mock-acp-v2.py | 2 +- fixtures/mock-acp.py | 2 +- macos/ACP/Schema/README.md | 4 +- macos/ACP/Schema/acp-v2.schema.json | 33 +++--- .../Generated/ACPWireModels.generated.swift | 8 +- .../generate-acp-swift.cpython-313.pyc | Bin 0 -> 25273 bytes scripts/generate-acp-swift.py | 8 +- .../test_generate_acp_swift.cpython-313.pyc | Bin 0 -> 5898 bytes src/protocols/acp/v2.rs | 12 +-- 11 files changed, 99 insertions(+), 98 deletions(-) create mode 100644 scripts/__pycache__/generate-acp-swift.cpython-313.pyc create mode 100644 scripts/tests/__pycache__/test_generate_acp_swift.cpython-313.pyc diff --git a/Cargo.lock b/Cargo.lock index b39984bd..4a1a78ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,43 +79,40 @@ dependencies = [ ] [[package]] -name = "agent-client-protocol" -version = "2.0.0" -source = "git+https://github.com/danielkov/rust-sdk.git?rev=423ba77cd555a09f68472b93c142c8f0baaabf43#423ba77cd555a09f68472b93c142c8f0baaabf43" +name = "agent-client-protocol-derive" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4893bfb11e0e193aa5a64611a126ee87567acb1879556519c902722899229de" dependencies = [ - "agent-client-protocol-derive", - "agent-client-protocol-schema", - "async-io", - "async-process", - "blocking", - "futures", - "futures-concurrency", - "rustc-hash", - "rustix 1.1.4", - "schemars 1.2.2", - "serde", - "serde_json", - "shell-words", - "tracing", - "uuid", - "windows-sys 0.61.2", + "quote", + "syn 3.0.4", ] [[package]] -name = "agent-client-protocol-derive" -version = "2.0.0" -source = "git+https://github.com/danielkov/rust-sdk.git?rev=423ba77cd555a09f68472b93c142c8f0baaabf43#423ba77cd555a09f68472b93c142c8f0baaabf43" +name = "agentkit-acp" +version = "0.10.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "394478ee8cb0e8916531ae4f450b953e4adfc0f700bbd4a1a85ebb265bfb18ce" dependencies = [ - "quote", - "syn 3.0.4", + "agentkit-acp-sdk", + "agentkit-core", + "agentkit-loop", + "agentkit-tools-core", + "async-trait", + "base64 0.22.1", + "serde_json", + "thiserror 2.0.18", + "tokio", + "tracing", ] [[package]] -name = "agent-client-protocol-http" -version = "2.0.0" -source = "git+https://github.com/danielkov/rust-sdk.git?rev=423ba77cd555a09f68472b93c142c8f0baaabf43#423ba77cd555a09f68472b93c142c8f0baaabf43" +name = "agentkit-acp-http" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1fe9230b43784cb66312e93eb72d6420c0a027029879feb02361435856b66" dependencies = [ - "agent-client-protocol", + "agentkit-acp-sdk", "async-stream", "async-tungstenite", "axum", @@ -132,9 +129,10 @@ dependencies = [ ] [[package]] -name = "agent-client-protocol-schema" -version = "1.7.0" -source = "git+https://github.com/danielkov/agent-client-protocol?rev=6e7e044f9464c4fd652d90699a09e9edc8b3bbad#6e7e044f9464c4fd652d90699a09e9edc8b3bbad" +name = "agentkit-acp-schema" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfcb839ccca8f4f43bfc9aa26473396f16afbd32071efd00d36801daed62f9d7" dependencies = [ "anyhow", "derive_more", @@ -147,20 +145,27 @@ dependencies = [ ] [[package]] -name = "agentkit-acp" -version = "0.10.11" -source = "git+https://github.com/daviddanialy/agentkit.git?rev=6d519ed1e93e28e54ba1cc18889534e2e8337181#6d519ed1e93e28e54ba1cc18889534e2e8337181" +name = "agentkit-acp-sdk" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b93c10bb458dd1c2c822275a7e1c390b46846a6bcd3cbc84aafa312563e36ad" dependencies = [ - "agent-client-protocol", - "agentkit-core", - "agentkit-loop", - "agentkit-tools-core", - "async-trait", - "base64 0.22.1", + "agent-client-protocol-derive", + "agentkit-acp-schema", + "async-io", + "async-process", + "blocking", + "futures", + "futures-concurrency", + "rustc-hash", + "rustix 1.1.4", + "schemars 1.2.2", + "serde", "serde_json", - "thiserror 2.0.18", - "tokio", + "shell-words", "tracing", + "uuid", + "windows-sys 0.61.2", ] [[package]] @@ -255,8 +260,9 @@ dependencies = [ [[package]] name = "agentkit-loop" -version = "0.10.12" -source = "git+https://github.com/danielkov/agentkit.git?rev=bec9dcc45ee0f436d538286bc220b16dc19fd5f3#bec9dcc45ee0f436d538286bc220b16dc19fd5f3" +version = "0.10.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e581d59925462f08c1145ee85e4c937db76fb6d1690b4b9ed49d44ca8c560141" dependencies = [ "agentkit-core", "agentkit-task-manager", @@ -3058,10 +3064,10 @@ dependencies = [ "a2a-protocol-client", "a2a-protocol-server", "a2a-protocol-types", - "agent-client-protocol", - "agent-client-protocol-http", - "agent-client-protocol-schema", "agentkit-acp", + "agentkit-acp-http", + "agentkit-acp-schema", + "agentkit-acp-sdk", "agentkit-adapter-completions", "agentkit-compaction", "agentkit-context", diff --git a/Cargo.toml b/Cargo.toml index 837bbe0e..b9228e89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,15 +32,15 @@ tokio-tungstenite = { version = "=0.29.0", default-features = false, features = a2a-protocol-client = "=0.11.0" a2a-protocol-server = { version = "=0.11.0", default-features = false } a2a-protocol-types = "=0.11.0" -agent-client-protocol = { version = "=2.0.0", features = ["unstable_session_fork", "unstable_session_inject"] } -agent-client-protocol-schema = { git = "https://github.com/danielkov/agent-client-protocol", rev = "6e7e044f9464c4fd652d90699a09e9edc8b3bbad", features = ["unstable_session_notices", "unstable_session_compaction", "unstable_tool_call_name"] } -agent-client-protocol-http = { version = "=2.0.0", default-features = false, features = ["server", "client"] } -agentkit-acp = { version = "=0.10.11", features = ["unstable-inject"] } +agent-client-protocol = { package = "agentkit-acp-sdk", version = "=2.2.0", features = ["unstable_session_fork", "unstable_session_inject"] } +agent-client-protocol-schema = { package = "agentkit-acp-schema", version = "=1.9.1", features = ["unstable_session_notices", "unstable_session_compaction"] } +agent-client-protocol-http = { package = "agentkit-acp-http", version = "=2.2.0", default-features = false, features = ["server", "client"] } +agentkit-acp = { version = "=0.10.12", features = ["unstable-inject"] } agentkit-adapter-completions = "=0.10.9" agentkit-core = "=0.10.5" agentkit-context = "=0.10.5" agentkit-compaction = "=0.10.5" -agentkit-loop = { version = "=0.10.12", features = ["otel"] } +agentkit-loop = { version = "=0.10.13", features = ["otel"] } agentkit-mcp = "=0.10.7" agentkit-http = "=0.10.7" agentkit-plugins = "=0.10.7" @@ -124,18 +124,6 @@ windows-sys = { version = "=0.61.2", features = [ jsonwebtoken = { version = "=11.0.0", default-features = false, features = ["aws_lc_rs", "use_pem"] } tokio = { version = "=1.53.1", features = ["test-util"] } -[patch.crates-io] -agentkit-loop = { git = "https://github.com/danielkov/agentkit.git", rev = "bec9dcc45ee0f436d538286bc220b16dc19fd5f3" } -agentkit-acp = { git = "https://github.com/daviddanialy/agentkit.git", rev = "6d519ed1e93e28e54ba1cc18889534e2e8337181" } -agent-client-protocol = { git = "https://github.com/danielkov/rust-sdk.git", rev = "423ba77cd555a09f68472b93c142c8f0baaabf43" } -agent-client-protocol-http = { git = "https://github.com/danielkov/rust-sdk.git", rev = "423ba77cd555a09f68472b93c142c8f0baaabf43" } - -[patch."https://github.com/danielkov/agentkit.git"] -agentkit-capabilities = "=0.10.5" -agentkit-core = "=0.10.5" -agentkit-task-manager = "=0.10.7" -agentkit-tools-core = "=0.10.5" - # Deny also in test builds; only test-only scopes may relax ergonomics. Crate # roots additionally forbid these in production so local allows cannot evade it. [lints.clippy] @@ -147,9 +135,3 @@ todo = "deny" unimplemented = "deny" disallowed_methods = "deny" disallowed_macros = "deny" - -# Keep the media-budget fork limited to ACP; share the existing loop and registry types. -[patch."https://github.com/daviddanialy/agentkit.git"] -agentkit-loop = { git = "https://github.com/danielkov/agentkit.git", rev = "bec9dcc45ee0f436d538286bc220b16dc19fd5f3" } -agentkit-core = "=0.10.5" -agentkit-tools-core = "=0.10.5" diff --git a/fixtures/mock-acp-v2.py b/fixtures/mock-acp-v2.py index 5c8ec1a8..483750b2 100644 --- a/fixtures/mock-acp-v2.py +++ b/fixtures/mock-acp-v2.py @@ -136,7 +136,7 @@ def prompt(request): if "MOCK_REJECT" in text: send({"jsonrpc": "2.0", "id": request["id"], "error": {"code": -32602, "message": "prompt rejected"}}) return - respond(request["id"], {}) + respond(request["id"], {"messageId": "user-1"}) send({"jsonrpc": "2.0", "method": "session/update", "params": {"sessionId": session_id, "update": {"sessionUpdate": "state_update", "state": "running"}}}) if "MOCK_PERMISSION" in text: send({ diff --git a/fixtures/mock-acp.py b/fixtures/mock-acp.py index 13f4cafb..0ce3ecc8 100644 --- a/fixtures/mock-acp.py +++ b/fixtures/mock-acp.py @@ -150,7 +150,7 @@ def prompt(request): "sessionId": request["params"]["sessionId"], "update": {"sessionUpdate": "state_update", "state": "idle", "stopReason": "refusal"} }}) - respond(request["id"], {}) + respond(request["id"], {"messageId": "user-1"}) send({"jsonrpc": "2.0", "method": "session/update", "params": { "sessionId": request["params"]["sessionId"], "update": {"sessionUpdate": "state_update", "state": "running"} diff --git a/macos/ACP/Schema/README.md b/macos/ACP/Schema/README.md index 34f71841..3c6befc2 100644 --- a/macos/ACP/Schema/README.md +++ b/macos/ACP/Schema/README.md @@ -1,8 +1,8 @@ # Pinned ACP v2 schema `acp-v2.schema.json` and `acp-v2.meta.json` are copied verbatim from the ACP -unstable v2 schema at `agent-client-protocol` commit -`6e7e044f9464c4fd652d90699a09e9edc8b3bbad`, the same revision pinned through +unstable v2 schema at `danielkov/agent-client-protocol` commit +`b7ddb8370e72e3adb6b895f879876cdd3f717ab9`, the source of the `agentkit-acp-schema` 1.9.1 crate in Kit's Rust dependency graph. They are persistent, versioned build inputs. Run `scripts/generate-acp-swift.py` after intentionally updating the pin. CI runs diff --git a/macos/ACP/Schema/acp-v2.schema.json b/macos/ACP/Schema/acp-v2.schema.json index f5741ab0..4abd3449 100644 --- a/macos/ACP/Schema/acp-v2.schema.json +++ b/macos/ACP/Schema/acp-v2.schema.json @@ -837,7 +837,7 @@ ] }, "name": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nProgrammatic name of the tool being invoked.\n\nThis field is optional and has patch semantics. Omission means no\nchange, `null` clears the name, and a string replaces it. For a tool\ncall ID the client has not seen before, omission or `null` means that no\ntool name is available.", + "description": "Programmatic name of the tool being invoked.\n\nThis field is optional and has patch semantics. Omission means no\nchange, `null` clears the name, and a string replaces it. For a tool\ncall ID the client has not seen before, omission or `null` means that no\ntool name is available.", "type": ["string", "null"], "x-deserialize-default-on-error": true }, @@ -5267,9 +5267,17 @@ "x-method": "session/set_config_option" }, "PromptResponse": { - "description": "Response acknowledging that a user prompt was accepted.\n\nThis response does not indicate that the agent has finished processing.\nProcessing and completion are reported through `state_update` session updates.\n\nSee protocol docs: [Prompt Accepted](https://agentclientprotocol.com/protocol/v2/draft/prompt-lifecycle#2-prompt-accepted)", + "description": "Response acknowledging that a user prompt was inserted into the ACP conversation.\n\nThis response does not indicate that the prompt was merely received or queued, nor that the\nagent has finished processing it.\nProcessing and completion are reported through `state_update` session updates.\n\nSee protocol docs: [Prompt Accepted](https://agentclientprotocol.com/protocol/v2/draft/prompt-lifecycle#2-prompt-accepted)", "type": "object", "properties": { + "messageId": { + "description": "Identifies the user message inserted into the ACP conversation.\n\nRequired and non-null. Omission and explicit `null` are both invalid.\n\nThe corresponding user-message session update carries this same identifier and may arrive\nbefore or after this response. Agents must echo the message during the live session, but are\nnot required to retain it. If retained and replayed, the message keeps this identifier.", + "allOf": [ + { + "$ref": "#/$defs/MessageId" + } + ] + }, "_meta": { "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/draft/extensibility)", "type": ["object", "null"], @@ -5277,9 +5285,14 @@ "additionalProperties": true } }, + "required": ["messageId"], "x-side": "agent", "x-method": "session/prompt" }, + "MessageId": { + "description": "Unique identifier for a message within a session.", + "type": "string" + }, "InjectSessionResponse": { "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nResponse acknowledging that an injected message is pending delivery.", "type": "object", @@ -5303,10 +5316,6 @@ "x-side": "agent", "x-method": "session/inject" }, - "MessageId": { - "description": "Unique identifier for a message within a session.", - "type": "string" - }, "RevokeInjectSessionResponse": { "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nResponse confirming that a pending injected message was revoked.", "type": "object", @@ -7923,7 +7932,7 @@ }, { "title": "ResumeSessionRequest", - "description": "Resumes an existing session.\n\nThe agent should resume the session context, allowing the conversation\nto continue. If `replayFrom` is set, the agent should replay\nconversation history before responding.", + "description": "Resumes an existing session.\n\nThe agent should resume the session context, allowing the conversation\nto continue. If `replayFrom` is set, the agent should replay\nretained conversation history before responding.", "allOf": [ { "$ref": "#/$defs/ResumeSessionRequest" @@ -7950,7 +7959,7 @@ }, { "title": "PromptRequest", - "description": "Processes a user prompt within a session.\n\nThis request accepts the prompt:\n- Receives user messages with optional context (files, images, etc.)\n- Returns once the prompt is accepted\n\nAfter acceptance, the Agent reports the accepted user message,\nprocessing state, output, tool calls, and completion through\n`session/update` notifications.\n\nSee protocol docs: [Prompt Lifecycle](https://agentclientprotocol.com/protocol/v2/draft/prompt-lifecycle)", + "description": "Processes a user prompt within a session.\n\nAcceptance means insertion into the ACP conversation:\n- Receives user messages with optional context (files, images, etc.)\n- Returns the inserted user message's ID without waiting for processing to finish\n\nThe Agent reports the user message with the same ID through `session/update`;\nthis notification may arrive before or after the response. Processing state,\noutput, tool calls, and completion are also reported through session updates.\n\nSee protocol docs: [Prompt Lifecycle](https://agentclientprotocol.com/protocol/v2/draft/prompt-lifecycle)", "allOf": [ { "$ref": "#/$defs/PromptRequest" @@ -8799,7 +8808,7 @@ "x-method": "session/fork" }, "ResumeSessionRequest": { - "description": "Request parameters for resuming an existing session.\n\nResumes an existing session and optionally replays prior conversation\nhistory according to `replayFrom`.", + "description": "Request parameters for resuming an existing session.\n\nResumes an existing session and optionally replays retained conversation\nhistory according to `replayFrom`.", "type": "object", "properties": { "sessionId": { @@ -8837,7 +8846,7 @@ "x-deserialize-skip-invalid-items": true }, "replayFrom": { - "description": "Inclusive cursor describing where conversation replay should begin.\n\nOptional. Omitted or `null` both mean the Agent should resume without\nreplaying previous conversation history. Replay cursors are inclusive:\nreplay includes the position identified by the cursor. Supplying\n`{ \"type\": \"start\" }` means the Agent should replay the whole\nconversation before responding.", + "description": "Inclusive cursor describing where conversation replay should begin.\n\nOptional. Omitted or `null` both mean the Agent should resume without\nreplaying previous conversation history. Replay cursors are inclusive:\nreplay includes the position identified by the cursor. Supplying\n`{ \"type\": \"start\" }` means the Agent should replay all retained\nconversation history before responding.", "anyOf": [ { "$ref": "#/$defs/ReplayFrom" @@ -8863,7 +8872,7 @@ "description": "Inclusive cursor describing where replayed session history should begin.\n\nReplay includes the position identified by the cursor.", "anyOf": [ { - "description": "Replay the whole conversation from its first replayable entry.", + "description": "Replay all retained conversation history from its first replayable entry.", "type": "object", "properties": { "type": { @@ -8914,7 +8923,7 @@ ] }, "ReplayFromStart": { - "description": "Inclusive replay cursor requesting replay from the start of the conversation.", + "description": "Inclusive replay cursor requesting replay from the start of retained conversation history.", "type": "object", "properties": { "_meta": { diff --git a/macos/KitDesktop/Generated/ACPWireModels.generated.swift b/macos/KitDesktop/Generated/ACPWireModels.generated.swift index b6d95bd6..b0a6ea22 100644 --- a/macos/KitDesktop/Generated/ACPWireModels.generated.swift +++ b/macos/KitDesktop/Generated/ACPWireModels.generated.swift @@ -1,6 +1,6 @@ // Generated by scripts/generate-acp-swift.py; DO NOT EDIT. -// Source: ACP v2 unstable schema, agent-client-protocol rev 6e7e044f9464c4fd652d90699a09e9edc8b3bbad -// Schema SHA-256: bd4bcc672f4cfcb3bd2a320d355ab6bf2d240a2a7177ca995cf6a36f24d3bd31 +// Source: ACP v2 unstable schema, agent-client-protocol rev b7ddb8370e72e3adb6b895f879876cdd3f717ab9 +// Schema SHA-256: 868810deef730e033dd413cc3dbb1d6524ef14c10c6abb18df00a9eb1e70979b // swiftlint:disable file_length import Foundation @@ -122,7 +122,9 @@ struct ACPPromptRequest: Codable, Equatable { var prompt: [JSONValue] } -struct ACPPromptResponse: Codable, Equatable {} +struct ACPPromptResponse: Codable, Equatable { + var messageId: String +} struct ACPInjectSessionRequest: Codable, Equatable { var sessionId: String diff --git a/scripts/__pycache__/generate-acp-swift.cpython-313.pyc b/scripts/__pycache__/generate-acp-swift.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d168f4bfed0c465f37d50f67ca6937c7c037df9 GIT binary patch literal 25273 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 YU)V}+kG^y^X{#2DU<4>*C7BcdA6_KuQ2+n{ literal 0 HcmV?d00001 diff --git a/scripts/generate-acp-swift.py b/scripts/generate-acp-swift.py index 19a4cc4c..4de6b0c1 100755 --- a/scripts/generate-acp-swift.py +++ b/scripts/generate-acp-swift.py @@ -101,7 +101,7 @@ "sessionId": ("allOf($ref:SessionId)", True), "prompt": ("array[$ref:ContentBlock]", True), }, - "PromptResponse": {}, + "PromptResponse": {"messageId": ("allOf($ref:MessageId)", True)}, "InjectSessionRequest": { "sessionId": ("allOf($ref:SessionId)", True), "mode": ("allOf($ref:SessionInjectMode)", True), @@ -375,7 +375,9 @@ var prompt: [JSONValue] } -struct ACPPromptResponse: Codable, Equatable {} +struct ACPPromptResponse: Codable, Equatable { + var messageId: String +} struct ACPInjectSessionRequest: Codable, Equatable { var sessionId: String @@ -628,7 +630,7 @@ def render() -> str: return ( "// Generated by scripts/generate-acp-swift.py; DO NOT EDIT.\n" "// Source: ACP v2 unstable schema, agent-client-protocol rev " - "6e7e044f9464c4fd652d90699a09e9edc8b3bbad\n" + "b7ddb8370e72e3adb6b895f879876cdd3f717ab9\n" f"// Schema SHA-256: {digest}\n\n" + BODY ) diff --git a/scripts/tests/__pycache__/test_generate_acp_swift.cpython-313.pyc b/scripts/tests/__pycache__/test_generate_acp_swift.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bad07dee40bdd2acaf69d5fa7046e16d95273f54 GIT binary patch literal 5898 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 O|K|KsfCycD2LA&i^s8n7 literal 0 HcmV?d00001 diff --git a/src/protocols/acp/v2.rs b/src/protocols/acp/v2.rs index 1aeed8c2..658a1b66 100644 --- a/src/protocols/acp/v2.rs +++ b/src/protocols/acp/v2.rs @@ -511,7 +511,7 @@ fn compose_title_update(call: &agentkit_core::ToolCallPart) -> Option, AcpRuntimeError>>, + reply: oneshot::Sender, wire::MessageId), AcpRuntimeError>>, } enum Command { @@ -1106,7 +1106,7 @@ impl Server { async fn prepare_prompt( &self, request: wire::PromptRequest, - ) -> Result, AcpRuntimeError> { + ) -> Result<(oneshot::Sender<()>, wire::MessageId), AcpRuntimeError> { let (sender, busy, handle) = self.prompt_route(&request.session_id)?; // Reject overlaps before waiting: mailbox pressure must not queue another turn. if busy.load(Ordering::Acquire) { @@ -1597,7 +1597,7 @@ async fn prepare_prompt( }; handle.start_injection_turn(); let (start, started) = oneshot::channel(); - if reply.send(Ok(start)).is_err() || started.await.is_err() { + if reply.send(Ok((start, user_message_id.clone()))).is_err() || started.await.is_err() { handle.stop_injection_turn(); integration.finish_prompt(session_id); return Ok(()); @@ -2359,8 +2359,8 @@ pub(crate) fn component( let state = Arc::clone(&state); cx.spawn(async move { match state.prepare_prompt(request).await { - Ok(start) => { - responder.respond(wire::PromptResponse::new())?; + Ok((start, message_id)) => { + responder.respond(wire::PromptResponse::new(message_id))?; let _ = start.send(()); Ok(()) } @@ -3554,7 +3554,7 @@ mod tests { reply, }; let acknowledge = async move { - response.await.unwrap().unwrap().send(()).unwrap(); + response.await.unwrap().unwrap().0.send(()).unwrap(); }; let task_manager = AsyncTaskManager::new(); From 355da6cab1ee7241744b8383fed926f07d087e6d Mon Sep 17 00:00:00 2001 From: daniel Date: Thu, 1 Oct 2026 16:15:54 +0100 Subject: [PATCH 2/2] test: keep unit tests off the live model catalog ACP config options embed the OpenRouter model list, fetched live with a best-effort fallback, so a fork could advertise a different catalog than its source when one fetch failed on CI. --- src/provider/adapter.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/provider/adapter.rs b/src/provider/adapter.rs index df7b761d..ce389a16 100644 --- a/src/provider/adapter.rs +++ b/src/provider/adapter.rs @@ -1515,6 +1515,10 @@ fn fallback_catalog() -> DiscoveredModels { } async fn fetch_model_ids(url: &str) -> Result { + // Unit tests must see one deterministic catalog, never the live public listing. + if cfg!(test) { + return Err("model catalog discovery is disabled in unit tests".into()); + } let client = reqwest::Client::builder() .redirect(reqwest::redirect::Policy::none()) .connect_timeout(Duration::from_secs(5))