Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 084cff4fe6 | |||
| ef3fc6039e | |||
| 3599513128 | |||
| 7dd8f53f2f | |||
| 90bb7251e3 | |||
| e57bef95e5 | |||
| 71b4465595 | |||
| 9b63e5368e | |||
| 8f265d00ba | |||
| 5a3a099b94 | |||
| 1f6f5dd08c | |||
| 6e532f64f5 |
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { X } from '@lucide/vue'
|
import { X, ExternalLink } from '@lucide/vue'
|
||||||
import type { AgentNodeData } from '../../composables/useDashboardData'
|
import type { AgentNodeData } from '../../composables/useDashboardData'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@@ -25,6 +25,9 @@ defineEmits<{
|
|||||||
<div>
|
<div>
|
||||||
<h2>{{ agent.name }}</h2>
|
<h2>{{ agent.name }}</h2>
|
||||||
<span class="modal-role">{{ agent.role }}</span>
|
<span class="modal-role">{{ agent.role }}</span>
|
||||||
|
<a :href="`/agents/${agent.id}`" class="agent-link-btn" title="Open agent config">
|
||||||
|
<ExternalLink :size="12" />
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="modal-close-btn" @click="$emit('close')" aria-label="Close">
|
<button class="modal-close-btn" @click="$emit('close')" aria-label="Close">
|
||||||
@@ -38,7 +41,34 @@ defineEmits<{
|
|||||||
<!-- Current Task -->
|
<!-- Current Task -->
|
||||||
<section class="modal-section">
|
<section class="modal-section">
|
||||||
<h3 class="section-label">Current Task</h3>
|
<h3 class="section-label">Current Task</h3>
|
||||||
<p class="section-value">{{ agent.currentTask }}</p>
|
<p class="section-value">
|
||||||
|
{{ agent.currentTask }}
|
||||||
|
<span class="thinking-dots">
|
||||||
|
<span class="thinking-dot blue"></span>
|
||||||
|
<span class="thinking-dot violet"></span>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Live Thinking -->
|
||||||
|
<section class="modal-section">
|
||||||
|
<h3 class="section-label">Live Thinking</h3>
|
||||||
|
<div class="thinking-panel">
|
||||||
|
<div class="thinking-stream" ref="thinkingStreamRef">
|
||||||
|
<div
|
||||||
|
v-for="(msg, idx) in agent.thinkingStream"
|
||||||
|
:key="idx"
|
||||||
|
class="thinking-entry"
|
||||||
|
:style="{ animationDelay: `${idx * 0.05}s` }"
|
||||||
|
>
|
||||||
|
<span class="entry-time">{{ msg.time }}</span>
|
||||||
|
<span class="entry-text">{{ msg.text }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="!agent.thinkingStream?.length" class="thinking-placeholder">
|
||||||
|
Waiting for thought stream...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Goal + Progress -->
|
<!-- Goal + Progress -->
|
||||||
@@ -66,7 +96,8 @@ defineEmits<{
|
|||||||
class="work-step"
|
class="work-step"
|
||||||
>
|
>
|
||||||
<span class="step-dot"></span>
|
<span class="step-dot"></span>
|
||||||
<span class="step-text">{{ step }}</span>
|
<span class="step-time">{{ step.time }}</span>
|
||||||
|
<span class="step-text">{{ step.text }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -74,15 +105,6 @@ defineEmits<{
|
|||||||
<!-- Footer Stats -->
|
<!-- Footer Stats -->
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<span class="footer-badge">Runtime: {{ runtime }}</span>
|
<span class="footer-badge">Runtime: {{ runtime }}</span>
|
||||||
<span
|
|
||||||
class="footer-badge"
|
|
||||||
:style="{
|
|
||||||
color: agent.workload > 65 ? '#eab308' : '#22c55e',
|
|
||||||
borderColor: agent.workload > 65 ? 'rgba(234,179,8,0.2)' : 'rgba(34,197,94,0.2)',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
Workload: {{ agent.workload }}%
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -168,6 +190,29 @@ defineEmits<{
|
|||||||
color: #6b7385;
|
color: #6b7385;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
.agent-link-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
margin-left: 4px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: transparent;
|
||||||
|
color: #6b7385;
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
flex-shrink: 0;
|
||||||
|
text-decoration: none;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.agent-link-btn:hover {
|
||||||
|
opacity: 1;
|
||||||
|
color: var(--agent-color);
|
||||||
|
}
|
||||||
|
|
||||||
.modal-close-btn {
|
.modal-close-btn {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
@@ -211,6 +256,9 @@ defineEmits<{
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #e8eaf0;
|
color: #e8eaf0;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Progress */
|
/* Progress */
|
||||||
@@ -241,6 +289,87 @@ defineEmits<{
|
|||||||
transition: width 0.5s ease;
|
transition: width 0.5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Live Thinking */
|
||||||
|
.thinking-panel {
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid rgba(139, 124, 246, 0.2);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 14px;
|
||||||
|
background: rgba(12, 16, 22, 0.6);
|
||||||
|
overflow: hidden;
|
||||||
|
animation: panel-pulse 2.5s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes panel-pulse {
|
||||||
|
0%, 100% { border-color: rgba(139, 124, 246, 0.25); box-shadow: 0 0 12px rgba(139,124,246,0.08); }
|
||||||
|
50% { border-color: rgba(139, 124, 246, 0.5); box-shadow: 0 0 24px rgba(139,124,246,0.18), 0 0 40px rgba(139,124,246,0.06); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.thinking-dots {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 6px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.thinking-dot {
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.thinking-dot.blue {
|
||||||
|
background: #3b82f6;
|
||||||
|
box-shadow: 0 0 8px #3b82f6;
|
||||||
|
animation: pulse-dot-blue 1.2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
.thinking-dot.violet {
|
||||||
|
background: #8b7cf6;
|
||||||
|
box-shadow: 0 0 8px #8b7cf6;
|
||||||
|
animation: pulse-dot-violet 1.8s ease-in-out infinite 0.3s;
|
||||||
|
}
|
||||||
|
@keyframes pulse-dot-blue {
|
||||||
|
0%, 100% { opacity: 0.4; transform: scale(0.7); }
|
||||||
|
50% { opacity: 1; transform: scale(1.3); }
|
||||||
|
}
|
||||||
|
@keyframes pulse-dot-violet {
|
||||||
|
0%, 100% { opacity: 0.3; transform: scale(0.6); }
|
||||||
|
50% { opacity: 1; transform: scale(1.4); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.thinking-stream {
|
||||||
|
max-height: 160px;
|
||||||
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.thinking-entry {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: baseline;
|
||||||
|
animation: slide-in-right 0.3s ease-out both;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
@keyframes slide-in-right {
|
||||||
|
from { opacity: 0; transform: translateX(-16px); }
|
||||||
|
to { opacity: 1; transform: translateX(0); }
|
||||||
|
}
|
||||||
|
.entry-time {
|
||||||
|
font-size: 8.5px;
|
||||||
|
color: #6b7385;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
min-width: 42px;
|
||||||
|
}
|
||||||
|
.entry-text {
|
||||||
|
color: #9ea5b3;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.thinking-placeholder {
|
||||||
|
font-size: 10px;
|
||||||
|
color: #4a5160;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
/* Working Feed */
|
/* Working Feed */
|
||||||
.work-feed {
|
.work-feed {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -265,6 +394,13 @@ defineEmits<{
|
|||||||
color: #7e8799;
|
color: #7e8799;
|
||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
|
.step-time {
|
||||||
|
font-size: 8.5px;
|
||||||
|
color: #6b7385;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
min-width: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Footer */
|
/* Footer */
|
||||||
.modal-footer {
|
.modal-footer {
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ const connectionPaths = computed<Record<string, ConnectionPath | null>>(() => {
|
|||||||
|
|
||||||
// Spread start points across Iris bottom edge (30%-70% range)
|
// Spread start points across Iris bottom edge (30%-70% range)
|
||||||
const t = total > 1 ? idx / (total - 1) : 0.5
|
const t = total > 1 ? idx / (total - 1) : 0.5
|
||||||
const startX = iris.left + iris.width * (0.30 + t * 0.40)
|
const startX = iris.left + iris.width * (0.38 + t * 0.24)
|
||||||
const startY = iris.bottom - 1
|
const startY = iris.bottom - 1
|
||||||
|
|
||||||
// Determine column: left or right of Iris center
|
// Determine column: left or right of Iris center
|
||||||
@@ -130,8 +130,8 @@ const connectionPaths = computed<Record<string, ConnectionPath | null>>(() => {
|
|||||||
|
|
||||||
// Bézier control points
|
// Bézier control points
|
||||||
const cp1x = startX
|
const cp1x = startX
|
||||||
const cp1y = startY + 40
|
const cp1y = startY + 70
|
||||||
const cp2x = endX + (isLeftColumn ? 50 : -50)
|
const cp2x = endX + (isLeftColumn ? 35 : -35)
|
||||||
const cp2y = endY - 10
|
const cp2y = endY - 10
|
||||||
|
|
||||||
const d = `M ${startX} ${startY} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${endX} ${endY}`
|
const d = `M ${startX} ${startY} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${endX} ${endY}`
|
||||||
@@ -334,7 +334,7 @@ onUnmounted(() => {
|
|||||||
<!-- Cards Layer (above SVG) -->
|
<!-- Cards Layer (above SVG) -->
|
||||||
<div class="cards-layer">
|
<div class="cards-layer">
|
||||||
<!-- Hero: Iris centered top -->
|
<!-- Hero: Iris centered top -->
|
||||||
<div class="hero-slot" data-agent-id="iris">
|
<div class="hero-slot" :data-agent-id="hero.id">
|
||||||
<article
|
<article
|
||||||
class="agent-card hero-card"
|
class="agent-card hero-card"
|
||||||
:style="{
|
:style="{
|
||||||
@@ -445,7 +445,7 @@ onUnmounted(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 32px;
|
gap: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-slot {
|
.hero-slot {
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ export interface AgentNodeData {
|
|||||||
workload: number // 0-100
|
workload: number // 0-100
|
||||||
active: boolean
|
active: boolean
|
||||||
runtimeSeconds: number
|
runtimeSeconds: number
|
||||||
workingFeed: string[]
|
workingFeed: Array<{ time: string; text: string }>
|
||||||
|
thinkingStream?: Array<{ time: string; text: string }>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MissionData {
|
export interface MissionData {
|
||||||
@@ -81,6 +82,7 @@ export function useDashboardData() {
|
|||||||
|
|
||||||
// Agent runtimes (simulated)
|
// Agent runtimes (simulated)
|
||||||
const agentStartTimes = reactive<Record<string, number>>({
|
const agentStartTimes = reactive<Record<string, number>>({
|
||||||
|
iris: now - 28800000,
|
||||||
developer: now - 3600000,
|
developer: now - 3600000,
|
||||||
devops: now - 1800000,
|
devops: now - 1800000,
|
||||||
researcher: now - 2700000,
|
researcher: now - 2700000,
|
||||||
@@ -98,6 +100,31 @@ export function useDashboardData() {
|
|||||||
|
|
||||||
// Agents
|
// Agents
|
||||||
const agents = ref<AgentNodeData[]>([
|
const agents = ref<AgentNodeData[]>([
|
||||||
|
{
|
||||||
|
id: 'iris',
|
||||||
|
name: 'Iris',
|
||||||
|
role: 'Chief of Staff',
|
||||||
|
description: 'Koordiniert, delegiert, hält das Team tight. Die erste Anlaufstelle zwischen Boss und Maschine.',
|
||||||
|
color: '#8b7cf6',
|
||||||
|
icon: 'bot',
|
||||||
|
currentTask: 'Orchestrating Nexus Dashboard redesign',
|
||||||
|
goal: 'Complete Mission Control v3',
|
||||||
|
progress: 85,
|
||||||
|
workload: 55,
|
||||||
|
active: true,
|
||||||
|
runtimeSeconds: 28800,
|
||||||
|
workingFeed: [
|
||||||
|
{ time: '22:38', text: 'Analyzed user feedback on Dashboard' },
|
||||||
|
{ time: '22:36', text: 'Delegated card redesign to Developer' },
|
||||||
|
{ time: '22:34', text: 'Verifying full-width layout deployment' },
|
||||||
|
{ time: '22:32', text: 'Reviewing AgentModal integration' },
|
||||||
|
],
|
||||||
|
thinkingStream: [
|
||||||
|
{ time: '22:24', text: 'Analysing constraint: full-width layout' },
|
||||||
|
{ time: '22:25', text: 'Removing max-width from global CSS' },
|
||||||
|
{ time: '22:26', text: 'Verifying Dashboard grid reflow' },
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'developer',
|
id: 'developer',
|
||||||
name: 'Developer',
|
name: 'Developer',
|
||||||
@@ -112,10 +139,15 @@ export function useDashboardData() {
|
|||||||
active: true,
|
active: true,
|
||||||
runtimeSeconds: 3600,
|
runtimeSeconds: 3600,
|
||||||
workingFeed: [
|
workingFeed: [
|
||||||
'Created DungeonController',
|
{ time: '22:30', text: 'Created DungeonController' },
|
||||||
'Defined dungeon schema',
|
{ time: '22:28', text: 'Defined dungeon schema' },
|
||||||
'Implementing room generation algorithm',
|
{ time: '22:26', text: 'Implementing room generation algorithm' },
|
||||||
'Writing unit tests for RoomFactory',
|
{ time: '22:24', text: 'Writing unit tests for RoomFactory' },
|
||||||
|
],
|
||||||
|
thinkingStream: [
|
||||||
|
{ time: '22:22', text: 'Parsing dungeon spec from Iris' },
|
||||||
|
{ time: '22:23', text: 'Designing RoomFactory interface' },
|
||||||
|
{ time: '22:24', text: 'Implementing corridor connection logic' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -132,10 +164,15 @@ export function useDashboardData() {
|
|||||||
active: false,
|
active: false,
|
||||||
runtimeSeconds: 1800,
|
runtimeSeconds: 1800,
|
||||||
workingFeed: [
|
workingFeed: [
|
||||||
'Analyzed Docker layer cache',
|
{ time: '22:20', text: 'Analyzed Docker layer cache' },
|
||||||
'Optimized COPY order in Dockerfile',
|
{ time: '22:18', text: 'Optimized COPY order in Dockerfile' },
|
||||||
'Added .dockerignore for node_modules',
|
{ time: '22:16', text: 'Added .dockerignore for node_modules' },
|
||||||
'Testing incremental builds',
|
{ time: '22:14', text: 'Testing incremental builds' },
|
||||||
|
],
|
||||||
|
thinkingStream: [
|
||||||
|
{ time: '22:20', text: 'Checking build cache hit rates' },
|
||||||
|
{ time: '22:21', text: 'Benchmarking multi-stage vs single-stage' },
|
||||||
|
{ time: '22:22', text: 'Calculating potential speedup from caching' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -152,9 +189,14 @@ export function useDashboardData() {
|
|||||||
active: true,
|
active: true,
|
||||||
runtimeSeconds: 2700,
|
runtimeSeconds: 2700,
|
||||||
workingFeed: [
|
workingFeed: [
|
||||||
'Evaluated WebSocket vs SSE vs WebRTC',
|
{ time: '22:18', text: 'Evaluated WebSocket vs SSE vs WebRTC' },
|
||||||
'Documented SignalR limitations',
|
{ time: '22:17', text: 'Documented SignalR limitations' },
|
||||||
'Prototyping WebSocket fallback',
|
{ time: '22:16', text: 'Prototyping WebSocket fallback' },
|
||||||
|
],
|
||||||
|
thinkingStream: [
|
||||||
|
{ time: '22:18', text: 'Cross-referencing WebSocket latency benchmarks' },
|
||||||
|
{ time: '22:19', text: 'Checking SSE browser support matrix' },
|
||||||
|
{ time: '22:20', text: 'Drafting recommendation summary' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -171,10 +213,15 @@ export function useDashboardData() {
|
|||||||
active: false,
|
active: false,
|
||||||
runtimeSeconds: 900,
|
runtimeSeconds: 900,
|
||||||
workingFeed: [
|
workingFeed: [
|
||||||
'Reviewed DungeonController.cs',
|
{ time: '22:15', text: 'Reviewed DungeonController.cs' },
|
||||||
'Found 3 minor style issues',
|
{ time: '22:14', text: 'Found 3 minor style issues' },
|
||||||
'Approved RoomValidator',
|
{ time: '22:13', text: 'Approved RoomValidator' },
|
||||||
'Running integration tests',
|
{ time: '22:12', text: 'Running integration tests' },
|
||||||
|
],
|
||||||
|
thinkingStream: [
|
||||||
|
{ time: '22:15', text: 'Analyzing DungeonController PR diff' },
|
||||||
|
{ time: '22:16', text: 'Checking RoomValidator edge cases' },
|
||||||
|
{ time: '22:17', text: 'Verifying integration test coverage' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, onUnmounted } from 'vue'
|
import { onMounted, onUnmounted, ref } from 'vue'
|
||||||
import MissionCard from '../components/dashboard/MissionCard.vue'
|
import MissionCard from '../components/dashboard/MissionCard.vue'
|
||||||
import OperationsFeed from '../components/dashboard/OperationsFeed.vue'
|
import OperationsFeed from '../components/dashboard/OperationsFeed.vue'
|
||||||
import TeamNetwork from '../components/dashboard/TeamNetwork.vue'
|
import TeamNetwork from '../components/dashboard/TeamNetwork.vue'
|
||||||
import ChatPanel from '../components/dashboard/ChatPanel.vue'
|
import ChatPanel from '../components/dashboard/ChatPanel.vue'
|
||||||
import QueuePanel from '../components/dashboard/QueuePanel.vue'
|
import QueuePanel from '../components/dashboard/QueuePanel.vue'
|
||||||
|
import AgentModal from '../components/dashboard/AgentModal.vue'
|
||||||
import { useDashboardData } from '../composables/useDashboardData'
|
import { useDashboardData } from '../composables/useDashboardData'
|
||||||
|
import type { AgentNodeData } from '../../composables/useDashboardData'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
agents, missions, feedEntries, chatMessages,
|
agents, missions, feedEntries, chatMessages,
|
||||||
@@ -14,6 +16,13 @@ const {
|
|||||||
sendChat, removeQueueItem, moveQueueItem, changeQueuePriority,
|
sendChat, removeQueueItem, moveQueueItem, changeQueuePriority,
|
||||||
} = useDashboardData()
|
} = useDashboardData()
|
||||||
|
|
||||||
|
const selectedAgent = ref<AgentNodeData | null>(null)
|
||||||
|
|
||||||
|
function onAgentSelect(id: string) {
|
||||||
|
const agent = agents.value.find(a => a.id === id)
|
||||||
|
if (agent) selectedAgent.value = agent
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(startRuntime)
|
onMounted(startRuntime)
|
||||||
onUnmounted(stopRuntime)
|
onUnmounted(stopRuntime)
|
||||||
|
|
||||||
@@ -58,10 +67,12 @@ function onQueueExecuteNow(id: string): void {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TeamNetwork
|
<TeamNetwork
|
||||||
|
hero-id="iris"
|
||||||
:agents="agents"
|
:agents="agents"
|
||||||
:iris-runtime="irisRuntime"
|
:iris-runtime="irisRuntime"
|
||||||
:get-agent-runtime="getAgentRuntime"
|
:get-agent-runtime="getAgentRuntime"
|
||||||
:iris-focus="irisFocus"
|
:iris-focus="irisFocus"
|
||||||
|
@select="onAgentSelect"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Legend -->
|
<!-- Legend -->
|
||||||
@@ -84,6 +95,13 @@ function onQueueExecuteNow(id: string): void {
|
|||||||
<ChatPanel :messages="chatMessages" :iris-busy="irisBusy" :iris-focus="irisFocus" @send="onChatSend" />
|
<ChatPanel :messages="chatMessages" :iris-busy="irisBusy" :iris-focus="irisFocus" @send="onChatSend" />
|
||||||
<QueuePanel :items="queue" @remove="removeQueueItem" @move-up="onQueueMoveUp" @move-down="onQueueMoveDown" @change-priority="changeQueuePriority" @execute-now="onQueueExecuteNow" />
|
<QueuePanel :items="queue" @remove="removeQueueItem" @move-up="onQueueMoveUp" @move-down="onQueueMoveDown" @change-priority="changeQueuePriority" @execute-now="onQueueExecuteNow" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<AgentModal
|
||||||
|
v-if="selectedAgent"
|
||||||
|
:agent="selectedAgent"
|
||||||
|
:runtime="getAgentRuntime(selectedAgent.id)"
|
||||||
|
@close="selectedAgent = null"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user