From 44029ccba215f2f5fb367f69e0d58fa993335358 Mon Sep 17 00:00:00 2001 From: hugocasa Date: Fri, 9 Oct 2026 12:04:06 +0200 Subject: [PATCH] fix: keep the base path in the chat SDK example, list slack_agents token scopes, bound the bot name lookup Co-Authored-By: Claude Opus 5.5 --- backend/windmill-api/src/slack_agents.rs | 16 ++++++++++++++-- backend/windmill-api/src/token.rs | 6 ++++++ .../flows/content/AgentUsePanel.svelte | 7 ++++++- .../components/flows/content/agentApiExamples.ts | 2 +- .../(logged)/agents/get/[...path]/+page.svelte | 1 + 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/backend/windmill-api/src/slack_agents.rs b/backend/windmill-api/src/slack_agents.rs index d77af87e42..448ecb11bf 100644 --- a/backend/windmill-api/src/slack_agents.rs +++ b/backend/windmill-api/src/slack_agents.rs @@ -123,12 +123,24 @@ async fn list_agent_channels( Some(_) => bot_name(&db, &w_id).await, None => None, }; - Ok(Json(AgentSlack { slack_team_name, signing_secret_set, bot_name, channels })) + Ok(Json(AgentSlack { + slack_team_name, + signing_secret_set, + bot_name, + channels, + })) } async fn bot_name(db: &DB, w_id: &str) -> Option { let token = bot_token(db, w_id).await.ok()?; - let res = slack_call(&token, "auth.test", &[]).await.ok()?; + // On every agent page load: a slow Slack must not hold the page for the client's 20s timeout. + let res = tokio::time::timeout( + std::time::Duration::from_secs(3), + slack_call(&token, "auth.test", &[]), + ) + .await + .ok()? + .ok()?; res["user"].as_str().map(str::to_string) } diff --git a/backend/windmill-api/src/token.rs b/backend/windmill-api/src/token.rs index b7fbe96404..bc77ac67a9 100644 --- a/backend/windmill-api/src/token.rs +++ b/backend/windmill-api/src/token.rs @@ -105,6 +105,12 @@ fn build_standard_scope_domains() -> Vec { "AI agent eval datasets and standalone runs", false, ), + ( + "slack_agents", + "Slack Agents", + "AI agents answering in Slack channels", + false, + ), ( "agent_workers", "Agent Workers", diff --git a/frontend/src/lib/components/flows/content/AgentUsePanel.svelte b/frontend/src/lib/components/flows/content/AgentUsePanel.svelte index 4250dd673d..142dcffa49 100644 --- a/frontend/src/lib/components/flows/content/AgentUsePanel.svelte +++ b/frontend/src/lib/components/flows/content/AgentUsePanel.svelte @@ -34,6 +34,7 @@ workspace, isAdmin, chat, + slackLoading, slackTeamName, botName, signingSecretSet, @@ -45,6 +46,8 @@ isAdmin: boolean /** Whether the agent keeps the conversation. Slack is offered only then: a thread is one. */ chat: boolean + /** Whether the workspace's Slack connection is still being read. */ + slackLoading: boolean /** Unset when Slack is not connected to the workspace. */ slackTeamName: string | undefined /** Unset when Slack can't be reached with the workspace's bot token. */ @@ -173,7 +176,9 @@ {#snippet content()}
- {#if !slackTeamName} + {#if slackLoading} + Loading… + {:else if !slackTeamName} Connect Slack to the workspace to ask this agent from Slack, by its name or as a channel's default. diff --git a/frontend/src/lib/components/flows/content/agentApiExamples.ts b/frontend/src/lib/components/flows/content/agentApiExamples.ts index 7dbc92f3d8..0a7b44fc8f 100644 --- a/frontend/src/lib/components/flows/content/agentApiExamples.ts +++ b/frontend/src/lib/components/flows/content/agentApiExamples.ts @@ -110,7 +110,7 @@ const TOKEN = '${t.token}' export function AgentChat() { const chat = useWindmillChat({ - baseUrl: '${new URL(t.api).origin}', + baseUrl: '${t.api.replace(/\/api\/w\/[^/]+$/, '')}', workspace: '${t.api.split('/').pop()}', token: TOKEN, // What the agent's conversations are filed under. With a token, history stays in this diff --git a/frontend/src/routes/(root)/(logged)/agents/get/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/agents/get/[...path]/+page.svelte index e37dc2764d..cc5fe242dc 100644 --- a/frontend/src/routes/(root)/(logged)/agents/get/[...path]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/agents/get/[...path]/+page.svelte @@ -214,6 +214,7 @@ workspace={ws} isAdmin={!!($userStore?.is_admin || $userStore?.is_super_admin)} chat={chatAvailable} + slackLoading={slack.loading && !slack.current} slackTeamName={slack.current?.slack_team_name} botName={slack.current?.bot_name} signingSecretSet={slack.current?.signing_secret_set ?? true}