diff --git a/src-tauri/src/commands/acp.rs b/src-tauri/src/commands/acp.rs index 7b35683..2fe2be2 100644 --- a/src-tauri/src/commands/acp.rs +++ b/src-tauri/src/commands/acp.rs @@ -188,6 +188,7 @@ pub async fn acp_load_session( session_id: String, goose_session_id: String, working_dir: Option, + provider_id: Option, ) -> Result<(), String> { let current_dir = std::env::current_dir() .map_err(|error| format!("Failed to determine current working directory: {error}"))?; @@ -195,7 +196,7 @@ pub async fn acp_load_session( let manager = GooseAcpManager::start(app_handle).await?; manager - .load_session(session_id, goose_session_id, working_dir) + .load_session(session_id, goose_session_id, working_dir, provider_id) .await } diff --git a/src-tauri/src/services/acp/manager.rs b/src-tauri/src/services/acp/manager.rs index 2da75e7..ee2586d 100644 --- a/src-tauri/src/services/acp/manager.rs +++ b/src-tauri/src/services/acp/manager.rs @@ -25,6 +25,7 @@ enum ManagerCommand { local_session_id: String, goose_session_id: String, working_dir: PathBuf, + provider_id: Option, response: oneshot::Sender>, }, PrepareSession { @@ -128,6 +129,7 @@ impl GooseAcpManager { local_session_id: String, goose_session_id: String, working_dir: PathBuf, + provider_id: Option, ) -> Result<(), String> { let (response_tx, response_rx) = oneshot::channel(); self.command_tx @@ -135,6 +137,7 @@ impl GooseAcpManager { local_session_id, goose_session_id, working_dir, + provider_id, response: response_tx, }) .map_err(|_| "Goose ACP manager is unavailable".to_string())?; diff --git a/src-tauri/src/services/acp/manager/command_dispatch.rs b/src-tauri/src/services/acp/manager/command_dispatch.rs index 6ce59a6..c5a7936 100644 --- a/src-tauri/src/services/acp/manager/command_dispatch.rs +++ b/src-tauri/src/services/acp/manager/command_dispatch.rs @@ -60,6 +60,7 @@ pub(super) async fn dispatch_commands( local_session_id, goose_session_id, working_dir, + provider_id, response, } => { let connection = Arc::clone(&connection); @@ -73,6 +74,7 @@ pub(super) async fn dispatch_commands( &local_session_id, &goose_session_id, working_dir, + provider_id.as_deref(), ) .await; let _ = response.send(result); diff --git a/src-tauri/src/services/acp/manager/dispatcher.rs b/src-tauri/src/services/acp/manager/dispatcher.rs index 0e6155f..a9d0696 100644 --- a/src-tauri/src/services/acp/manager/dispatcher.rs +++ b/src-tauri/src/services/acp/manager/dispatcher.rs @@ -424,6 +424,12 @@ impl Client for SessionEventDispatcher { } else { // Start a new assistant message let new_id = uuid::Uuid::new_v4().to_string(); + let route_provider_id = { + let routes = self.routes.lock().await; + routes + .get(&goose_session_id) + .and_then(|r| r.provider_id.clone()) + }; let _ = self.app_handle.emit( "acp:message_created", MessageCreatedPayload { @@ -431,6 +437,7 @@ impl Client for SessionEventDispatcher { message_id: new_id.clone(), persona_id: None, persona_name: None, + provider_id: route_provider_id, }, ); let mut routes = self.routes.lock().await; diff --git a/src-tauri/src/services/acp/manager/session_ops.rs b/src-tauri/src/services/acp/manager/session_ops.rs index 1be791f..27fe2ba 100644 --- a/src-tauri/src/services/acp/manager/session_ops.rs +++ b/src-tauri/src/services/acp/manager/session_ops.rs @@ -426,9 +426,10 @@ pub(super) async fn load_session_inner( local_session_id: &str, goose_session_id: &str, working_dir: PathBuf, + provider_id: Option<&str>, ) -> Result<(), String> { dispatcher - .bind_session(goose_session_id, local_session_id, None) + .bind_session(goose_session_id, local_session_id, provider_id) .await; let response = connection diff --git a/src-tauri/src/services/acp/payloads.rs b/src-tauri/src/services/acp/payloads.rs index 4c6031c..306c0e8 100644 --- a/src-tauri/src/services/acp/payloads.rs +++ b/src-tauri/src/services/acp/payloads.rs @@ -9,6 +9,7 @@ pub(crate) struct MessageCreatedPayload { pub message_id: String, pub persona_id: Option, pub persona_name: Option, + pub provider_id: Option, } /// Payload for the `acp:text` event. diff --git a/src-tauri/src/services/acp/writer.rs b/src-tauri/src/services/acp/writer.rs index e693f4b..5932ed8 100644 --- a/src-tauri/src/services/acp/writer.rs +++ b/src-tauri/src/services/acp/writer.rs @@ -35,6 +35,7 @@ impl TauriMessageWriter { message_id: assistant_message_id.clone(), persona_id: persona_id.clone(), persona_name: persona_name.clone(), + provider_id: provider_id.clone(), }, ); diff --git a/src/app/AppShell.tsx b/src/app/AppShell.tsx index 386e4b3..9d98fc7 100644 --- a/src/app/AppShell.tsx +++ b/src/app/AppShell.tsx @@ -97,7 +97,12 @@ export function AppShell({ children }: { children?: React.ReactNode }) { (!project ? resolveEffectiveWorkingDir(null, await getHomeDir()) : undefined); - await acpLoadSession(sessionId, gooseSessionId, workingDir); + await acpLoadSession( + sessionId, + gooseSessionId, + workingDir, + session?.providerId, + ); const t3 = performance.now(); console.log( `[perf:load] ${sessionId.slice(0, 8)} acpLoadSession resolved in ${(t3 - t2).toFixed(1)}ms (total ${(t3 - t0).toFixed(1)}ms)`, diff --git a/src/features/chat/hooks/useAcpStream.ts b/src/features/chat/hooks/useAcpStream.ts index 7390286..e63ec3d 100644 --- a/src/features/chat/hooks/useAcpStream.ts +++ b/src/features/chat/hooks/useAcpStream.ts @@ -24,6 +24,7 @@ interface AcpMessageCreatedPayload { messageId: string; personaId?: string; personaName?: string; + providerId?: string; } interface AcpTextPayload { @@ -198,7 +199,8 @@ export function useAcpStream(enabled: boolean): void { listen("acp:message_created", (event) => { if (!active) return; const store = useChatStore.getState(); - const { sessionId, messageId, personaId, personaName } = event.payload; + const { sessionId, messageId, personaId, personaName, providerId } = + event.payload; if (store.loadingSessionIds.has(sessionId)) { if (!getBufferedMessage(sessionId, messageId)) { @@ -212,6 +214,7 @@ export function useAcpStream(enabled: boolean): void { agentVisible: true, personaId, personaName, + providerId, completionStatus: "inProgress", }, }); @@ -238,6 +241,7 @@ export function useAcpStream(enabled: boolean): void { agentVisible: true, personaId, personaName, + providerId, completionStatus: "inProgress", }, }); diff --git a/src/shared/api/acp.ts b/src/shared/api/acp.ts index 7883596..b94873e 100644 --- a/src/shared/api/acp.ts +++ b/src/shared/api/acp.ts @@ -107,11 +107,13 @@ export async function acpLoadSession( sessionId: string, gooseSessionId: string, workingDir?: string, + providerId?: string, ): Promise { return invoke("acp_load_session", { sessionId, gooseSessionId, workingDir: workingDir ?? null, + providerId: providerId ?? null, }); } diff --git a/src/shared/types/messages.ts b/src/shared/types/messages.ts index dc62b84..42e29cd 100644 --- a/src/shared/types/messages.ts +++ b/src/shared/types/messages.ts @@ -112,6 +112,7 @@ export interface MessageMetadata { /** Persona that generated this assistant message (set on send). */ personaId?: string; personaName?: string; + providerId?: string; /** Which persona this user message is addressed to. */ targetPersonaId?: string; targetPersonaName?: string;