mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-30 16:17:25 +00:00
* feat: open a flow linking an agent from its menu Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: toast when the flow handoff cannot be stored Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: turn an agent into a flow from its editor, and into a chat app from its page Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: let sandboxed apps run agents, and keep the flow handoff race-free Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: save the new flow as a draft before letting the agent draft go Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: offer the chat app only to those who may build apps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: give the agent page's chat app section a tab on small screens Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: show the flow handoff as an info alert, framed around context and output Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep the flow handoff from operators and say why the chat app is locked Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: collapse the flow handoff hint to its title and button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: show the flow handoff as a corner hint, as the flow editor shows its own Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: name the agent on the app button and say why it is disabled Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: ask whether the agent needs steps before or after it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: name what a flow adds around the agent in its hint Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: say a never-deployed agent turns into a flow Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * revert: leave agent runs and the raw-app guidance to the chat SDK's runnable transport Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: show the agent page's sections as tabs at every width, as a chat-mode flow's page does Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: one webhook panel for scripts, flows and agents, with an AI prompt and chat-mode examples Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: describe the preprocessor's event argument instead of the v1 wm_trigger Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: give the flow chat's preprocessor example the v2 event signature Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: group a webhook's request choices and examples under an HTTP tab, beside the AI prompt and chat SDK Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: drop a comment about guidance this branch no longer adds Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: say where the AI prompt expects the webhook token Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: tell the chat-flow prompt that memory_id is required Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep the webhook tabs next to their content Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep the webhook's REST tab name Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: build an agent's chat app from a template, not an AI session Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: don't send the agent chat app's message on an IME confirmation Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: agent API tab with one row of call examples and a copy-prompt button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: open build app in an AI session when AI sessions are on Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: app conversations through the memory_id query parameter, chat-mode flows included Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate the mcp session instructions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: type backendAsync's memoryId option in the eval diagnostics Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: pin git-sync hub scripts to windmill-cli 1.849.0 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep build app in the editor when windmill ai is off Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: webhook panel with http and chat sdk tabs over toggle settings Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: memoryId option on the sync backend call too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: bump the ui builder artifact for the memoryId option Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep the webhook panel's http and chat sdk tabs close to their content Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: shared-utils 1.0.14 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: cli takes shared-utils 1.0.14 for the memoryId option Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: pin the app conversation scoping and the memoryId signatures Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: assert the ownership refusal, not any refusal Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: match the memoryId option in the cli wmill.ts signature tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: show the webhook request formats in a card with their toggle Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: put the chat sdk example in the same card as the http request Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: add a windmill app tab to chat-mode flow pages Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: title the webhook example cards and label the ai prompt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: offer the chat app from the conversations sidebar instead of a tab Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: raise the chat app's chat-sdk floor to 1.851.0 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: render the agent's chat app card only once the workspace is known Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: gate the flow's build chat app menu item like the sidebar card Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: build the agent's chat app through the page's navigation, for app-only authors too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep an imported app in the editor inside a session preview Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: build a form app from an agent without managed memory Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: cover the agent form app's generated source Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
180 lines
6.2 KiB
Svelte
180 lines
6.2 KiB
Svelte
<script lang="ts">
|
|
import { Alert, Badge, Button, CopyButton, TabContent, Tabs } from '$lib/components/common'
|
|
import Tooltip from '$lib/components/Tooltip.svelte'
|
|
import type { SlackAgentChannel } from '$lib/gen'
|
|
import WebhooksPanel from '$lib/components/triggers/webhook/WebhooksPanel.svelte'
|
|
|
|
/**
|
|
* The ways to use an agent outside its page: in the Slack channels it is shared in, set in its
|
|
* settings and summed up here, and over the API.
|
|
*/
|
|
let {
|
|
agentPath,
|
|
isAdmin,
|
|
chat,
|
|
slackLoading,
|
|
slackTeamName,
|
|
botName,
|
|
missingScopes,
|
|
signingSecretSet,
|
|
runsAs,
|
|
anyone,
|
|
canShare,
|
|
channels,
|
|
section
|
|
}: {
|
|
agentPath: string
|
|
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. */
|
|
botName: string | undefined
|
|
/** Agent scopes the connection lacks: Slack was connected without AI agents enabled. */
|
|
missingScopes: string[]
|
|
/** Agents answer in Slack only when the instance verifies Slack's request signatures. */
|
|
signingSecretSet: boolean
|
|
/** Who the agent runs as; unset unless it runs on behalf of someone. */
|
|
runsAs: string | undefined
|
|
/** Whether anyone in its channels can ask it, rather than workspace members only. */
|
|
anyone: boolean
|
|
/** Whether the user can change its Slack settings: anyone who can edit it. */
|
|
canShare: boolean
|
|
channels: SlackAgentChannel[]
|
|
/** The section shown: the page offers them as its tabs. */
|
|
section: 'api' | 'slack'
|
|
} = $props()
|
|
|
|
let handle = $derived(`+${agentPath.split('/').pop()}`)
|
|
</script>
|
|
|
|
<div class="flex flex-col h-full">
|
|
<Tabs selected={section} hideTabs wrapperClass="flex-none w-full">
|
|
{#snippet content()}
|
|
<div class="min-h-0 grow overflow-y-auto">
|
|
<TabContent value="slack" class="flex flex-col gap-6 p-4">
|
|
{#if slackLoading}
|
|
<span class="text-xs text-hint">Loading…</span>
|
|
{:else if !slackTeamName}
|
|
<span class="text-xs text-secondary">
|
|
Connect Slack to the workspace, with AI agents enabled, to ask this agent from Slack,
|
|
by its name or as a channel's default.
|
|
</span>
|
|
{#if isAdmin}
|
|
<div>
|
|
<Button
|
|
variant="default"
|
|
unifiedSize="md"
|
|
href="/workspace_settings?tab=slack&agents=true"
|
|
>
|
|
Connect Slack
|
|
</Button>
|
|
</div>
|
|
{:else}
|
|
<span class="text-2xs text-hint">A workspace admin can connect it.</span>
|
|
{/if}
|
|
{:else}
|
|
{#if !signingSecretSet}
|
|
<Alert type="warning" title="Agents can't answer in Slack yet" size="xs">
|
|
Windmill needs the Slack app's signing secret to tell who sent a message.
|
|
{#if isAdmin}
|
|
A workspace's own Slack app takes it in the workspace settings, the instance's app
|
|
in the instance settings.
|
|
{:else}
|
|
A workspace or instance admin can set it.
|
|
{/if}
|
|
</Alert>
|
|
{/if}
|
|
{#if !botName}
|
|
<Alert type="warning" title="Windmill can't reach Slack" size="xs">
|
|
Slack refused the workspace's bot token or couldn't be reached, so agents can't
|
|
answer there.
|
|
{#if isAdmin}
|
|
<a href="/workspace_settings?tab=slack&agents=true">Reconnect Slack</a> to fix it.
|
|
{:else}
|
|
A workspace admin can reconnect Slack to fix it.
|
|
{/if}
|
|
</Alert>
|
|
{/if}
|
|
{#if botName && missingScopes.length > 0}
|
|
<Alert type="warning" title="Slack was connected without AI agents" size="xs">
|
|
The connection lacks {missingScopes.join(', ')}, so agents can't check who is
|
|
asking.
|
|
{#if isAdmin}
|
|
<a href="/workspace_settings?tab=slack&agents=true">Disconnect Slack</a>, then
|
|
connect it again with AI agents enabled.
|
|
{:else}
|
|
A workspace admin can reconnect Slack with AI agents enabled.
|
|
{/if}
|
|
</Alert>
|
|
{/if}
|
|
|
|
<div class="flex flex-col gap-2">
|
|
<div class="flex items-center justify-between gap-2">
|
|
<span class="text-xs font-semibold text-emphasis">Ask it in Slack</span>
|
|
{#if canShare}
|
|
<Button
|
|
variant="default"
|
|
unifiedSize="sm"
|
|
href="/agents/edit/{agentPath}?settings=true"
|
|
>
|
|
Edit in settings
|
|
</Button>
|
|
{/if}
|
|
</div>
|
|
{#if channels.length === 0}
|
|
<span class="text-2xs text-hint">Not shared in any channel of {slackTeamName}.</span
|
|
>
|
|
{:else}
|
|
<div class="flex items-center gap-2">
|
|
<code
|
|
class="text-2xs font-mono text-emphasis bg-surface-secondary rounded px-2 py-1"
|
|
>@{botName ?? '<Slack app name>'} {handle} your question</code
|
|
>
|
|
<CopyButton value={handle} title="Copy {handle}" />
|
|
<Tooltip>
|
|
{handle} matches the last part of the agent's path. Use the whole path,
|
|
<code>+{agentPath}</code>, when two agents shared in a channel have that name.
|
|
Replies in the thread that mention the bot go to the same agent, no name needed.
|
|
</Tooltip>
|
|
</div>
|
|
<div class="flex flex-wrap items-center gap-1">
|
|
<span class="text-2xs text-hint">in</span>
|
|
{#each channels as channel (channel.channel_id)}
|
|
<Badge small
|
|
>#{channel.channel_name}{channel.is_default ? ' · default' : ''}</Badge
|
|
>
|
|
{/each}
|
|
</div>
|
|
<span class="text-2xs text-hint">
|
|
{#if anyone}
|
|
Anyone in these channels can ask it, with {runsAs}'s permissions.
|
|
{:else if runsAs}
|
|
Workspace members can ask it, with {runsAs}'s permissions.
|
|
{:else}
|
|
Workspace members can ask it, with their own permissions.
|
|
{/if}
|
|
</span>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
</TabContent>
|
|
|
|
<TabContent value="api" class="p-4">
|
|
<WebhooksPanel
|
|
agent
|
|
{chat}
|
|
path={agentPath}
|
|
token=""
|
|
args={{ user_message: 'Hello' }}
|
|
scopes={[`jobs:run:agents:${agentPath}`]}
|
|
/>
|
|
</TabContent>
|
|
</div>
|
|
{/snippet}
|
|
</Tabs>
|
|
</div>
|