UNPKG

@elevenlabs/convai-cli

Version:

CLI tool to manage ElevenLabs conversational AI agents

161 lines 8.56 kB
import React, { useState, useEffect } from 'react'; import { Box, Text, useApp } from 'ink'; import App from '../App.js'; import StatusCard from '../components/StatusCard.js'; import theme from '../themes/elevenlabs.js'; import { readAgentConfig } from '../../utils.js'; import { loadLockFile } from '../../utils.js'; import path from 'path'; import fs from 'fs-extra'; export const StatusView = ({ agentName, environment, onComplete }) => { const { exit } = useApp(); const [agents, setAgents] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const loadStatus = async () => { try { // Load agents configuration const agentsConfigPath = path.resolve('agents.json'); if (!(await fs.pathExists(agentsConfigPath))) { throw new Error('agents.json not found. Run "convai init" first.'); } const agentsConfig = await readAgentConfig(agentsConfigPath); const lockFilePath = path.resolve('convai.lock'); const lockData = await loadLockFile(lockFilePath); const statusList = []; // Process each agent for (const agentDef of agentsConfig.agents) { // Filter by agent name if specified if (agentName && agentDef.name !== agentName) { continue; } // Handle both old and new config formats const environments = agentDef.environments || { prod: { config: agentDef.config } }; for (const [env, envConfig] of Object.entries(environments)) { // Filter by environment if specified if (environment && env !== environment) { continue; } const configPath = envConfig.config; const fullConfigPath = path.resolve(configPath); const configExists = await fs.pathExists(fullConfigPath); let status = 'missing'; let configHash; let deployedHash; let agentId; if (configExists) { // Calculate current config hash const config = await readAgentConfig(fullConfigPath); const { calculateConfigHash } = await import('../../utils.js'); configHash = calculateConfigHash(config); // Get deployed info from lock file const lockKey = `${agentDef.name}_${env}`; const agentLock = lockData.agents?.[lockKey]; if (agentLock && typeof agentLock === 'object') { if ('config_hash' in agentLock) { deployedHash = agentLock.config_hash; agentId = agentLock.id; } else if ('hash' in agentLock) { deployedHash = agentLock.hash; agentId = agentLock.id; } if (configHash === deployedHash) { status = 'synced'; } else { status = 'modified'; } } else { status = 'not-deployed'; } } statusList.push({ name: agentDef.name, environment: env, configPath, configExists, configHash, deployedHash, agentId, status }); } } setAgents(statusList); setLoading(false); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load status'); setLoading(false); } }; loadStatus(); // Auto-exit after showing status const timer = setTimeout(() => { if (onComplete) { onComplete(); } else { exit(); } }, 10000); // Show for 10 seconds return () => clearTimeout(timer); }, [agentName, environment, exit, onComplete]); const syncedCount = agents.filter(a => a.status === 'synced').length; const modifiedCount = agents.filter(a => a.status === 'modified').length; const notDeployedCount = agents.filter(a => a.status === 'not-deployed').length; const missingCount = agents.filter(a => a.status === 'missing').length; return (React.createElement(App, { title: "ElevenLabs Conversational AI", subtitle: "Agent Status", showOverlay: false }, React.createElement(Box, { flexDirection: "column", gap: 1 }, loading ? (React.createElement(StatusCard, { title: "Loading Status", status: "loading", message: "Checking agent configurations..." })) : error ? (React.createElement(StatusCard, { title: "Error", status: "error", message: error })) : agents.length === 0 ? (React.createElement(StatusCard, { title: "No Agents Found", status: "idle", message: "No agents match the specified criteria" })) : (React.createElement(React.Fragment, null, React.createElement(Box, { marginBottom: 1 }, React.createElement(StatusCard, { title: "Status Summary", status: modifiedCount > 0 ? 'warning' : 'success', message: `${agents.length} agent(s) found`, details: [ `✓ ${syncedCount} synced`, `⚠ ${modifiedCount} modified`, `○ ${notDeployedCount} not deployed`, `✗ ${missingCount} missing` ] })), React.createElement(Box, { flexDirection: "column", gap: 1 }, React.createElement(Text, { color: theme.colors.text.primary, bold: true }, "Agents:"), agents.map((agent, index) => { let status; let statusText; let details = []; switch (agent.status) { case 'synced': status = 'success'; statusText = '✓ Synced'; break; case 'modified': status = 'warning'; statusText = '⚠ Modified locally'; details.push('Run "convai sync" to update'); break; case 'not-deployed': status = 'idle'; statusText = '○ Not deployed'; details.push('Run "convai sync" to deploy'); break; case 'missing': status = 'error'; statusText = '✗ Config file missing'; break; default: status = 'idle'; statusText = 'Unknown'; } if (agent.agentId) { details.push(`ID: ${agent.agentId}`); } if (agent.configPath) { details.push(`Config: ${agent.configPath}`); } return (React.createElement(StatusCard, { key: index, title: `${agent.name} (${agent.environment})`, status: status, message: statusText, details: details, borderStyle: "single" })); })), React.createElement(Box, { marginTop: 1 }, React.createElement(Text, { color: theme.colors.text.muted }, "Press Ctrl+C to exit (auto-exit in 10s)"))))))); }; export default StatusView; //# sourceMappingURL=StatusView.js.map