diff --git a/frontend/src/lib/components/DropdownV2Inner.svelte b/frontend/src/lib/components/DropdownV2Inner.svelte index 5f8b96c32f..f961dcb6ea 100644 --- a/frontend/src/lib/components/DropdownV2Inner.svelte +++ b/frontend/src/lib/components/DropdownV2Inner.svelte @@ -53,12 +53,26 @@ {#if item.icon} {/if} -

- {item.displayName} -

+ {#if item.subtitle} +
+

+ {item.displayName} +

+

+ {item.subtitle} +

+
+ {:else} +

+ {item.displayName} +

+ {/if} {@render item.extra?.()} {#if item.shortcut || item.selected || item.toggle !== undefined} - +
- - - -
+ + +
+ {#if runPane === 'chat' && chatReady} + +
+ +
+ {:else if runPane === 'chat'} +
+ {AGENT_CHAT_BLOCKED_REASON} +
+ {:else} + +
- - - - - +
+ +
+ {/if} +
diff --git a/frontend/src/lib/components/flows/content/AgentRunPane.svelte b/frontend/src/lib/components/flows/content/AgentRunPane.svelte new file mode 100644 index 0000000000..50f40cb58b --- /dev/null +++ b/frontend/src/lib/components/flows/content/AgentRunPane.svelte @@ -0,0 +1,164 @@ + + +{#if agentModule} + +
+
+ +
+
+ +
+
+{/if} diff --git a/frontend/src/lib/components/flows/conversations/ConversationRow.svelte b/frontend/src/lib/components/flows/conversations/ConversationRow.svelte new file mode 100644 index 0000000000..068eb45212 --- /dev/null +++ b/frontend/src/lib/components/flows/conversations/ConversationRow.svelte @@ -0,0 +1,100 @@ + + + diff --git a/frontend/src/lib/components/flows/conversations/FlowChatInterface.svelte b/frontend/src/lib/components/flows/conversations/FlowChatInterface.svelte index 7a35e6ea1f..756032fb86 100644 --- a/frontend/src/lib/components/flows/conversations/FlowChatInterface.svelte +++ b/frontend/src/lib/components/flows/conversations/FlowChatInterface.svelte @@ -1,6 +1,7 @@ + + +{#snippet agentChip(interactive: boolean)} + +{/snippet} + + +{#snippet noHint()}{/snippet} + +{#snippet talkingTo()} +
+ Talking to + + {#snippet buttonReplacement()} + {@render agentChip(true)} + {/snippet} + +
+{/snippet} + +
+ + + +
+ {#if currentResource} +
+ {title} + {#if !newChat || chatStarted} + +
+ Talking to + {@render agentChip(false)} +
+ {/if} +
+
+
+ {#if chatReady} + + {#key `${newChat}:${currentResource.path}`} +
+ +
+ {/key} + {#if newChat && !chatStarted && currentResource.description} +
+ +
+ {/if} + {:else if agentResource.current !== undefined} +
+ {#if newChat && !chatStarted} + {@render talkingTo()} + {/if} + {AGENT_CHAT_BLOCKED_REASON} +
+ {/if} +
+ {:else if !catalog.loading && (newChat || agents.length === 0)} +
+ {agents.length === 0 + ? 'No saved agent in this workspace. Create one from the home page to chat with it.' + : 'No agent can chat yet: set its memory to auto from its editor.'} +
+ {/if} +
+
diff --git a/frontend/src/routes/(root)/(logged)/agents/add/+page.svelte b/frontend/src/routes/(root)/(logged)/agents/add/+page.svelte new file mode 100644 index 0000000000..e54568a9ed --- /dev/null +++ b/frontend/src/routes/(root)/(logged)/agents/add/+page.svelte @@ -0,0 +1,5 @@ + diff --git a/frontend/src/routes/(root)/(logged)/agents/add/+page.ts b/frontend/src/routes/(root)/(logged)/agents/add/+page.ts new file mode 100644 index 0000000000..38697b7210 --- /dev/null +++ b/frontend/src/routes/(root)/(logged)/agents/add/+page.ts @@ -0,0 +1,6 @@ +import { makeDraftAddLoad } from '$lib/draftAddRedirect' +import type { PageLoad } from './$types' + +export const prerender = false + +export const load: PageLoad = makeDraftAddLoad('agents/edit') diff --git a/frontend/src/routes/(root)/(logged)/agents/edit/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/agents/edit/[...path]/+page.svelte new file mode 100644 index 0000000000..2ef16c6bc0 --- /dev/null +++ b/frontend/src/routes/(root)/(logged)/agents/edit/[...path]/+page.svelte @@ -0,0 +1,356 @@ + + +
+
+
+
+ { + if (draft?.state) draft.state.description = v.trim() + }} + textClass="text-xs font-semibold text-emphasis leading-tight" + class="max-w-full" + /> +
+
+ {#if version != undefined && !refused} + + v{version} + + {/if} + + {#if ws && !refused} + draft?.sync.resetToDeployed(path)} + /> + {/if} + {#if readOnly} + + Read only + + {/if} +
+ +
+ {#if !refused} + (runPane = v as 'chat' | 'form')} + noWFull + > + {#snippet children({ item })} + + + {/snippet} + +
+ + {#if !draftOnly} + + + {/if} + + +
+ draft?.deployed} + getCurrent={() => draft?.state} + onDiscard={() => draft?.sync.resetToDeployed(path)} + title="Deployed <> Unsaved agent changes" + /> +
+ +
+ {#key `${ws}:${path}:${restores}`} + (toolId = id)} + {onSaved} + {runPane} + {isNew} + /> + {/key} +
+ + + +{#snippet pathField(autofocus: boolean)} + {#if pathEditable} + draft?.state?.draft_path ?? '', + (v) => { + if (draft?.state) draft.state.draft_path = v + } + } + initialPath={draft?.state?.draft_path ?? ''} + namePlaceholder="agent" + kind="resource" + size="sm" + drawerOffset={4000} + /> + {:else} + {shownPath} +

+ Rename a deployed agent with Move, from its page, so the flows linking it follow. +

+ {/if} +{/snippet} + + + + (settingsOpen = false)}> +
+
+ + +
+
+
+
+ + + versionDrawer?.closeDrawer()} noPadding> + { + versionDrawer?.closeDrawer() + if (ws) markAgentWritten(ws, path) + restores++ + }} + /> + + diff --git a/frontend/src/routes/(root)/(logged)/agents/get/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/agents/get/[...path]/+page.svelte new file mode 100644 index 0000000000..55204a25b9 --- /dev/null +++ b/frontend/src/routes/(root)/(logged)/agents/get/[...path]/+page.svelte @@ -0,0 +1,416 @@ + + + + + { + await goto(`${base}/agents/get/${e.detail}?workspace=${ws}`) + }} +/> + (deleteOpen = false)} + on:confirmed={() => { + deleteOpen = false + deleteAgent() + }} +> + Every flow linking {path} will fail at its agent step once it is gone. + + + versionDrawer?.closeDrawer()} noPadding> + { + versionDrawer?.closeDrawer() + if (ws) markAgentWritten(ws, path) + }} + /> + + + +
+
+
+
+ +
+ + {agent?.description || path} + + {#if agent?.description} + {path} + {/if} +
+ {#if loaded?.version != undefined} + + v{loaded.version} + + {/if} + {#if agent?.labels?.length} + + {/if} + +
+ {#if agent && !refusal} + (leftPane = v as 'chat' | 'form')} + noWFull + > + {#snippet children({ item })} + + + {/snippet} + +
+ {/if} +
+ {#if menuItems.length > 0} + + {/if} + {#if can_write && !$userStore?.operator} + + {/if} +
+
+
+ + {#if loadError} +
+ {loadError} +
+ {:else if refusal} +
+ {refusal} +
+ {:else if agent} +
+ + +
+ + {#if agent.description && leftPane === 'form'} +
+
+ +
+
+ {/if} +
+ {#if leftPane === 'chat' && chatReady} + + {:else if leftPane === 'chat'} +
+ {chatBlockedReason} +
+ {:else} + + {#key `${ws}:${path}:${writes}`} + + {/key} + {/if} +
+
+
+ +
+ + + + {#snippet content()} +
+ +
+

Model

+
+ {#each brain.filter((p) => p.label !== AGENT_BRAIN_LABELS['system_prompt']) as param (param.label)} +
+
{param.label}
+
{param.value}
+
+ {/each} +
+
+
+

System message

+ {#if systemPrompt} +
{systemPrompt}
+ {:else} + None + {/if} +
+
+

+ Tools ({tools.length}) +

+ {#if tools.length === 0} + No tools. + {:else} +
    + {#each tools as tool (tool.id)} +
  • + + {toolDisplayName(tool) ?? tool.id} + + {toolKind(tool)} +
  • + {/each} +
+ {/if} +
+
+ + + +
+ {/snippet} +
+
+
+
+
+ {:else} +
Loading agent...
+ {/if} +