133 lines
3.9 KiB
Vue
133 lines
3.9 KiB
Vue
|
|
<script setup lang="ts">
|
||
|
|
import { ref, onMounted } from 'vue'
|
||
|
|
import { List, Typography, Button, Card, Spin, message, Tag, Space } from 'ant-design-vue'
|
||
|
|
import { apiClient, API } from '../router/api'
|
||
|
|
|
||
|
|
interface LLMConfig {
|
||
|
|
model_id?: string
|
||
|
|
[key: string]: unknown
|
||
|
|
}
|
||
|
|
|
||
|
|
interface OrganizationRef {
|
||
|
|
uuid?: string
|
||
|
|
name?: string
|
||
|
|
[key: string]: unknown
|
||
|
|
}
|
||
|
|
|
||
|
|
interface Agent {
|
||
|
|
uuid: string
|
||
|
|
name: string
|
||
|
|
agent_type: string
|
||
|
|
llm_config: LLMConfig
|
||
|
|
organization: string | OrganizationRef
|
||
|
|
}
|
||
|
|
|
||
|
|
const agents = ref<Agent[]>([])
|
||
|
|
const loading = ref(false)
|
||
|
|
const loadError = ref(false)
|
||
|
|
|
||
|
|
type MaybePaginated<T> = T[] | { results?: T[] }
|
||
|
|
|
||
|
|
const fetchAgents = async () => {
|
||
|
|
loading.value = true
|
||
|
|
loadError.value = false
|
||
|
|
try {
|
||
|
|
const response = await apiClient.get<MaybePaginated<Agent>>(API.agentConfigs())
|
||
|
|
|
||
|
|
const data = response.data
|
||
|
|
agents.value = Array.isArray(data) ? data : data.results || []
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Failed to fetch agents:', error)
|
||
|
|
message.error('Failed to load agent configurations')
|
||
|
|
loadError.value = true
|
||
|
|
} finally {
|
||
|
|
loading.value = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const getAgentTypeLabel = (type: string) => {
|
||
|
|
const types: Record<string, string> = {
|
||
|
|
curriculum: 'Curriculum Agent',
|
||
|
|
knowledge: 'Knowledge Agent',
|
||
|
|
assessment: 'Assessment Agent',
|
||
|
|
monitor: 'Progress Monitor',
|
||
|
|
}
|
||
|
|
return types[type] || type
|
||
|
|
}
|
||
|
|
|
||
|
|
onMounted(() => {
|
||
|
|
fetchAgents()
|
||
|
|
})
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<template>
|
||
|
|
<div class="page">
|
||
|
|
<Typography.Title :level="2">Agent Configurations</Typography.Title>
|
||
|
|
<Typography.Paragraph type="secondary">
|
||
|
|
Manage your AI personas and their specific tool permissions.
|
||
|
|
</Typography.Paragraph>
|
||
|
|
|
||
|
|
<Card class="panel" :bordered="false">
|
||
|
|
<Spin :spinning="loading" tip="Loading Agents...">
|
||
|
|
<div v-if="loadError" class="empty">
|
||
|
|
<Typography.Paragraph type="danger">
|
||
|
|
Failed to load agents.
|
||
|
|
</Typography.Paragraph>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div v-else-if="!loading && agents.length === 0" class="empty">
|
||
|
|
<Typography.Paragraph type="secondary">
|
||
|
|
No agent configurations found.
|
||
|
|
</Typography.Paragraph>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<List v-else :data-source="agents" item-layout="horizontal">
|
||
|
|
<template #renderItem="{ item }">
|
||
|
|
<List.Item class="item">
|
||
|
|
<List.Item.Meta :title="item.name">
|
||
|
|
<template #description>
|
||
|
|
<Space direction="vertical">
|
||
|
|
<Tag color="blue">
|
||
|
|
{{ getAgentTypeLabel(item.agent_type) }}
|
||
|
|
</Tag>
|
||
|
|
<span class="config-summary">
|
||
|
|
Model: {{ item.llm_config?.model_id || 'Default' }}
|
||
|
|
</span>
|
||
|
|
</Space>
|
||
|
|
</template>
|
||
|
|
</List.Item.Meta>
|
||
|
|
<RouterLink :to="`/agents/${item.uuid}`">
|
||
|
|
<Button type="primary">Manage & Run</Button>
|
||
|
|
</RouterLink>
|
||
|
|
</List.Item>
|
||
|
|
</template>
|
||
|
|
</List>
|
||
|
|
</Spin>
|
||
|
|
</Card>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.page {
|
||
|
|
max-width: 900px;
|
||
|
|
margin: 0 auto;
|
||
|
|
padding: 2rem 1rem;
|
||
|
|
}
|
||
|
|
.panel {
|
||
|
|
background: #0f172a;
|
||
|
|
border: 1px solid #1f2937;
|
||
|
|
}
|
||
|
|
.item :deep(.ant-list-item-meta-title) {
|
||
|
|
color: #f8fafc;
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
.config-summary {
|
||
|
|
color: #94a3b8;
|
||
|
|
font-size: 0.85rem;
|
||
|
|
}
|
||
|
|
.empty {
|
||
|
|
padding: 3rem;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
</style>
|