feat: add better provider support, icons, regen, and a lot more

This commit is contained in:
Zoe
2026-02-12 14:56:13 +00:00
parent d5a5945c03
commit d29f95bacf
124 changed files with 6374 additions and 1861 deletions
+49 -9
View File
@@ -9,7 +9,7 @@ const props = defineProps<{
const activeTab = ref('input');
const indicatorStyle = computed(() => {
const tabs = ['input', 'output', 'trace'];
const tabs = ['input', 'output', 'error', 'trace'];
const index = tabs.indexOf(activeTab.value);
// Each tab button is ~48px (40px height + 8px gap)
const offset = index * 48;
@@ -27,19 +27,26 @@ const lineNumberWidth = ref(1);
const input: ComputedRef<string> = computed(() => {
switch (activeTab.value) {
case 'input':
if (props.toolCall.input === null) return '';
if (props.toolCall.input === null || props.toolCall.input === undefined) return '';
if (props.toolCall.input!.type === 'json') {
return JSON.stringify(JSON.parse(props.toolCall.input!.value), null, 2);
}
return props.toolCall.input!.value;
case 'output':
if (props.toolCall.output === null) return '';
if (props.toolCall.output === null || props.toolCall.output === undefined) return '';
if (props.toolCall.output!.type === 'json') {
return JSON.stringify(JSON.parse(props.toolCall.output!.value), null, 2);
}
return props.toolCall.output!.value;
case 'error':
if (props.toolCall.error === null || props.toolCall.error === undefined) return '';
if (props.toolCall.error!.type === 'json') {
return JSON.stringify(JSON.parse(props.toolCall.error!.value), null, 2);
}
return props.toolCall.error!.value;
case 'trace': {
const traceObj: any = { ...props.toolCall };
if (traceObj === null) return '';
@@ -105,7 +112,7 @@ watch(
<div class="w-full border rounded-lg border-[var(--color-highlight)] flex flex-row h-80 overflow-hidden">
<div class="flex items-center gap-2 flex-col border-r border-[var(--color-highlight)] p-1 relative shrink-0">
<button @click="activeTab = 'input'" :class="[
'hover:bg-[var(--color-highlight)] p-2 rounded-lg flex gap-1 items-center w-full transition-colors duration-200 ease-[cubic-bezier(0.5,_1,_0.89,_1)]',
'function-call-tab-selector',
activeTab === 'input' ? 'text-orange-6' : ''
]">
<div
@@ -114,18 +121,29 @@ watch(
</div>
Input
</button>
<button @click="activeTab = 'output'" :class="[
'hover:bg-[var(--color-highlight)] p-2 rounded-lg flex gap-1 items-center w-full transition-colors duration-200 ease-[cubic-bezier(0.5,_1,_0.89,_1)]',
activeTab === 'output' ? 'text-orange-6' : ''
]">
<button :disabled="toolCall.output === undefined || toolCall.output === null" @click="activeTab = 'output'"
:class="[
'function-call-tab-selector',
activeTab === 'output' ? 'text-orange-6' : ''
]">
<div
class="w-[24px] h-[24px] flex-shrink-0 rounded-lg overflow-hidden flex items-center justify-center">
<Icon name="mynaui:arrow-down-square" class="w-4.5 h-4.5" />
</div>
Output
</button>
<button v-if="toolCall.error !== undefined && toolCall.error !== null" @click="activeTab = 'error'" :class="[
'function-call-tab-selector',
activeTab === 'error' ? 'text-orange-6' : ''
]">
<div
class="w-[24px] h-[24px] flex-shrink-0 rounded-lg overflow-hidden flex items-center justify-center">
<Icon name="mynaui:danger-triangle" class="w-4.5 h-4.5" />
</div>
Error
</button>
<button @click="activeTab = 'trace'" :class="[
'hover:bg-[var(--color-highlight)] p-2 rounded-lg flex gap-1 items-center w-full transition-colors duration-200 ease-[cubic-bezier(0.5,_1,_0.89,_1)]',
'function-call-tab-selector',
activeTab === 'trace' ? 'text-orange-6' : ''
]">
<div
@@ -174,4 +192,26 @@ watch(
.light #function-call-container>pre>code .line::before {
color: rgba(0, 0, 0, 0.25);
}
.function-call-tab-selector {
padding: 0.5rem;
border-radius: 0.375rem;
display: flex;
gap: 0.25rem;
align-items: center;
width: 100%;
transition-property: color, background-color, border-color,
text-decoration-color, fill, stroke;
transition-duration: 200ms;
transition-timing-function: cubic-bezier(0.5, 1, 0.89, 1);
}
.function-call-tab-selector:hover:enabled {
background-color: var(--color-highlight);
}
.function-call-tab-selector:disabled {
opacity: 0.3;
cursor: not-allowed;
}
</style>
+5 -23
View File
@@ -12,28 +12,6 @@ const deubgToolCallOpen = ref(false);
const toggleDebugToolCall = () => {
deubgToolCallOpen.value = !deubgToolCallOpen.value;
};
const iconName = ref('mynaui:tool');
const iconColor = ref('var(--color-subtle)');
watch(
() => props.toolCall.status,
(status) => {
switch (status) {
case 'pending':
iconName.value = 'svg-spinners:180-ring-with-bg';
break;
case 'completed':
iconName.value = 'mynaui:tool';
break;
case 'failed':
iconName.value = 'mynaui:x-solid';
iconColor.value = '#ff3b3b';
break;
}
},
{ immediate: true },
);
</script>
<template>
@@ -44,8 +22,12 @@ watch(
<div class="flex items-center gap-1">
<div
class="w-[24px] h-[24px] flex-shrink-0 rounded-lg overflow-hidden bg-[var(--color-neutral)] flex items-center justify-center">
<Icon :name="iconName" :style="{ color: iconColor }"
<!-- Explicityly avoid setting the name via a reactive value, otherwise you risk corrupting the icon with that name globally -->
<Icon v-if="toolCall.status === 'pending'" name="svg-spinners:180-ring-with-bg"
class="w-3 h-3 text-[var(--color-subtle)]" />
<Icon v-else-if="toolCall.status === 'failed'" name="mynaui:x-solid"
class="w-3 h-3 text-[#ff3b3b]" />
<Icon v-else name="mynaui:tool" class="w-3 h-3 text-[var(--color-subtle)]" />
</div>
{{ toolCall.toolName }}
</div>