refactor: Collapsible Content Block & small fixes
This commit is contained in:
parent
d89ada8cee
commit
56b34bf63b
|
|
@ -24,7 +24,7 @@
|
|||
onSystemPromptClick
|
||||
}: Props = $props();
|
||||
|
||||
const fileUploadTooltipText = 'Add files';
|
||||
const fileUploadTooltipText = 'Add files or context';
|
||||
|
||||
function handleFileUpload(fileType?: FileTypeCategory) {
|
||||
onFileUpload?.(fileType);
|
||||
|
|
|
|||
|
|
@ -7,17 +7,21 @@
|
|||
* similar to the reasoning/thinking block UI.
|
||||
*/
|
||||
|
||||
import { MarkdownContent, SyntaxHighlightedCode } from '$lib/components/app';
|
||||
import {
|
||||
CollapsibleContentBlock,
|
||||
MarkdownContent,
|
||||
SyntaxHighlightedCode
|
||||
} from '$lib/components/app';
|
||||
import { config } from '$lib/stores/settings.svelte';
|
||||
import { Wrench, Loader2 } from '@lucide/svelte';
|
||||
import CollapsibleInfoCard from './CollapsibleInfoCard.svelte';
|
||||
import { AgenticSectionType } from '$lib/types/agentic';
|
||||
|
||||
interface Props {
|
||||
content: string;
|
||||
}
|
||||
|
||||
interface AgenticSection {
|
||||
type: 'text' | 'tool_call' | 'tool_call_pending' | 'tool_call_streaming';
|
||||
type: AgenticSectionType;
|
||||
content: string;
|
||||
toolName?: string;
|
||||
toolArgs?: string;
|
||||
|
|
@ -66,7 +70,7 @@
|
|||
if (match.index > lastIndex) {
|
||||
const textBefore = rawContent.slice(lastIndex, match.index).trim();
|
||||
if (textBefore) {
|
||||
sections.push({ type: 'text', content: textBefore });
|
||||
sections.push({ type: AgenticSectionType.TEXT, content: textBefore });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,7 +86,7 @@
|
|||
const toolResult = match[3].replace(/^\n+|\n+$/g, '');
|
||||
|
||||
sections.push({
|
||||
type: 'tool_call',
|
||||
type: AgenticSectionType.TOOL_CALL,
|
||||
content: toolResult,
|
||||
toolName,
|
||||
toolArgs,
|
||||
|
|
@ -115,7 +119,7 @@
|
|||
if (pendingIndex > 0) {
|
||||
const textBefore = remainingContent.slice(0, pendingIndex).trim();
|
||||
if (textBefore) {
|
||||
sections.push({ type: 'text', content: textBefore });
|
||||
sections.push({ type: AgenticSectionType.TEXT, content: textBefore });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +136,7 @@
|
|||
const streamingResult = (pendingMatch[3] || '').replace(/^\n+|\n+$/g, '');
|
||||
|
||||
sections.push({
|
||||
type: 'tool_call_pending',
|
||||
type: AgenticSectionType.TOOL_CALL_PENDING,
|
||||
content: streamingResult,
|
||||
toolName,
|
||||
toolArgs,
|
||||
|
|
@ -144,7 +148,7 @@
|
|||
if (pendingIndex > 0) {
|
||||
const textBefore = remainingContent.slice(0, pendingIndex).trim();
|
||||
if (textBefore) {
|
||||
sections.push({ type: 'text', content: textBefore });
|
||||
sections.push({ type: AgenticSectionType.TEXT, content: textBefore });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +173,7 @@
|
|||
}
|
||||
|
||||
sections.push({
|
||||
type: 'tool_call_streaming',
|
||||
type: AgenticSectionType.TOOL_CALL_STREAMING,
|
||||
content: '',
|
||||
toolName: partialWithNameMatch[1],
|
||||
toolArgs: partialArgs || undefined,
|
||||
|
|
@ -181,7 +185,7 @@
|
|||
if (pendingIndex > 0) {
|
||||
const textBefore = remainingContent.slice(0, pendingIndex).trim();
|
||||
if (textBefore) {
|
||||
sections.push({ type: 'text', content: textBefore });
|
||||
sections.push({ type: AgenticSectionType.TEXT, content: textBefore });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +193,7 @@
|
|||
const nameMatch = earlyMatch[1]?.match(/<<<TOOL_NAME:([^>]+)>>>/);
|
||||
|
||||
sections.push({
|
||||
type: 'tool_call_streaming',
|
||||
type: AgenticSectionType.TOOL_CALL_STREAMING,
|
||||
content: '',
|
||||
toolName: nameMatch?.[1],
|
||||
toolArgs: undefined,
|
||||
|
|
@ -207,13 +211,13 @@
|
|||
}
|
||||
|
||||
if (remainingText) {
|
||||
sections.push({ type: 'text', content: remainingText });
|
||||
sections.push({ type: AgenticSectionType.TEXT, content: remainingText });
|
||||
}
|
||||
}
|
||||
|
||||
// If no tool calls found, return content as single text section
|
||||
if (sections.length === 0 && rawContent.trim()) {
|
||||
sections.push({ type: 'text', content: rawContent });
|
||||
sections.push({ type: AgenticSectionType.TEXT, content: rawContent });
|
||||
}
|
||||
|
||||
return sections;
|
||||
|
|
@ -231,13 +235,12 @@
|
|||
|
||||
<div class="agentic-content">
|
||||
{#each sections as section, index (index)}
|
||||
{#if section.type === 'text'}
|
||||
{#if section.type === AgenticSectionType.TEXT}
|
||||
<div class="agentic-text">
|
||||
<MarkdownContent content={section.content} />
|
||||
</div>
|
||||
{:else if section.type === 'tool_call_streaming'}
|
||||
<!-- Streaming state - show CollapsibleInfoCard with live streaming args -->
|
||||
<CollapsibleInfoCard
|
||||
{:else if section.type === AgenticSectionType.TOOL_CALL_STREAMING}
|
||||
<CollapsibleContentBlock
|
||||
open={isExpanded(index, true)}
|
||||
class="my-2"
|
||||
icon={Loader2}
|
||||
|
|
@ -264,12 +267,12 @@
|
|||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</CollapsibleInfoCard>
|
||||
{:else if section.type === 'tool_call' || section.type === 'tool_call_pending'}
|
||||
{@const isPending = section.type === 'tool_call_pending'}
|
||||
</CollapsibleContentBlock>
|
||||
{:else if section.type === AgenticSectionType.TOOL_CALL || section.type === AgenticSectionType.TOOL_CALL_PENDING}
|
||||
{@const isPending = section.type === AgenticSectionType.TOOL_CALL_PENDING}
|
||||
{@const toolIcon = isPending ? Loader2 : Wrench}
|
||||
{@const toolIconClass = isPending ? 'h-4 w-4 animate-spin' : 'h-4 w-4'}
|
||||
<CollapsibleInfoCard
|
||||
<CollapsibleContentBlock
|
||||
open={isExpanded(index, isPending)}
|
||||
class="my-2"
|
||||
icon={toolIcon}
|
||||
|
|
@ -308,7 +311,7 @@
|
|||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</CollapsibleInfoCard>
|
||||
</CollapsibleContentBlock>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@
|
|||
|
||||
function handleEdit() {
|
||||
isEditing = true;
|
||||
// Clear placeholder content for system messages
|
||||
// Clear temporary placeholder content for system messages
|
||||
editedContent =
|
||||
message.role === 'system' && message.content === SYSTEM_MESSAGE_PLACEHOLDER
|
||||
? ''
|
||||
|
|
@ -183,7 +183,7 @@
|
|||
// System messages: update in place without branching
|
||||
const newContent = editedContent.trim();
|
||||
|
||||
// If content is empty or still the placeholder, remove without deleting children
|
||||
// If content is empty, remove without deleting children
|
||||
if (!newContent) {
|
||||
const conversationDeleted = await removeSystemPromptPlaceholder(message.id);
|
||||
isEditing = false;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { Brain } from '@lucide/svelte';
|
||||
import { config } from '$lib/stores/settings.svelte';
|
||||
import CollapsibleInfoCard from './CollapsibleInfoCard.svelte';
|
||||
import { CollapsibleContentBlock } from '$lib/components/app';
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<CollapsibleInfoCard
|
||||
<CollapsibleContentBlock
|
||||
bind:open={isExpanded}
|
||||
class="mb-6 {className}"
|
||||
icon={Brain}
|
||||
|
|
@ -39,4 +39,4 @@
|
|||
{reasoningContent ?? ''}
|
||||
</div>
|
||||
</div>
|
||||
</CollapsibleInfoCard>
|
||||
</CollapsibleContentBlock>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import * as Dialog from '$lib/components/ui/dialog';
|
||||
import { McpSettingsSection } from '$lib/components/app';
|
||||
import McpSettingsSection from '../mcp/McpSettingsSection.svelte';
|
||||
import { config, settingsStore } from '$lib/stores/settings.svelte';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import McpLogo from '../misc/McpLogo.svelte';
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export { default as ChatMessageStatistics } from './chat/ChatMessages/ChatMessag
|
|||
export { default as ChatMessageSystem } from './chat/ChatMessages/ChatMessageSystem.svelte';
|
||||
export { default as ChatMessageThinkingBlock } from './chat/ChatMessages/ChatMessageThinkingBlock.svelte';
|
||||
export { default as ChatMessages } from './chat/ChatMessages/ChatMessages.svelte';
|
||||
export { default as CollapsibleInfoCard } from './chat/ChatMessages/CollapsibleInfoCard.svelte';
|
||||
export { default as CollapsibleContentBlock } from './chat/ChatMessages/CollapsibleContentBlock.svelte';
|
||||
export { default as MessageBranchingControls } from './chat/ChatMessages/ChatMessageBranchingControls.svelte';
|
||||
|
||||
export { default as ChatScreen } from './chat/ChatScreen/ChatScreen.svelte';
|
||||
|
|
|
|||
|
|
@ -7,3 +7,13 @@ export interface AgenticConfig {
|
|||
maxToolPreviewLines: number;
|
||||
filterReasoningAfterFirstTurn: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Types of sections in agentic content display.
|
||||
*/
|
||||
export enum AgenticSectionType {
|
||||
TEXT = 'text',
|
||||
TOOL_CALL = 'tool_call',
|
||||
TOOL_CALL_PENDING = 'tool_call_pending',
|
||||
TOOL_CALL_STREAMING = 'tool_call_streaming'
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue