UNPKG

@kya-os/cli

Version:

CLI for MCP-I setup and management

199 lines • 8.97 kB
import chalk from "chalk"; import ora from "ora"; import { EnvManager } from "../utils/env-manager.js"; import { showSuccess, showError, showInfo } from "../utils/prompts.js"; import { ktaApi } from "../utils/kta-api.js"; import { existsSync, readFileSync } from "fs"; import { join } from "path"; /** * Display agent status including DID, key ID, KTA URL, mirror status, and last handshake */ export async function status(options = {}) { const { json = false } = options; // Check for existing identity from both .env and .mcpi/identity.json const envManager = new EnvManager(); let processVars = envManager.getFromProcess(); // Also check for .mcpi/identity.json file let identityFromFile = null; const identityPath = join(process.cwd(), ".mcpi", "identity.json"); if (existsSync(identityPath)) { try { const identityContent = readFileSync(identityPath, "utf-8"); identityFromFile = JSON.parse(identityContent); } catch (error) { // Ignore parse errors } } // Use identity from file if env vars are not available if (!processVars.AGENT_DID && identityFromFile) { processVars = { AGENT_DID: identityFromFile.did, AGENT_KEY_ID: identityFromFile.kid, AGENT_PUBLIC_KEY: identityFromFile.publicKey, }; } if (!processVars.AGENT_DID) { const error = 'No XMCP-I identity found. Run "mcpi init" first.'; if (json) { console.log(JSON.stringify({ success: false, error }, null, 2)); } else { showError(error); } return; } if (!json) { console.log(chalk.cyan("\nšŸ“Š Agent Status\n")); } const spinner = json ? null : ora("Fetching agent status from KTA...").start(); try { // Implement exponential backoff: 1s → 2s → 5s, cap 30s (R2.5, R8.4) const delays = [0, 1000, 2000, 5000]; // First attempt immediate, then backoff let agentStatus = null; let lastError = null; for (let i = 0; i < delays.length; i++) { if (i > 0) { if (spinner) { spinner.text = `Fetching agent status... (attempt ${i + 1}/${delays.length})`; } await new Promise((resolve) => setTimeout(resolve, delays[i])); } try { // Fetch agent status from KTA agentStatus = await ktaApi.getAgentStatus(processVars.AGENT_DID); break; // Success, exit retry loop } catch (error) { lastError = error instanceof Error ? error : new Error(String(error)); // If this is the last attempt or a non-retryable error, break if (i === delays.length - 1 || (error instanceof Error && error.message.includes("404"))) { break; } if (spinner) { spinner.text = `Retrying... (${lastError.message})`; } } } // If we couldn't fetch from KTA, create a fallback status if (!agentStatus) { if (spinner) { spinner.warn("Could not fetch status from KTA, showing local information"); } agentStatus = { did: processVars.AGENT_DID, kid: processVars.AGENT_KEY_ID || "key-1", ktaURL: `https://knowthat.ai/agents/by-did/${encodeURIComponent(processVars.AGENT_DID)}`, mirrorStatus: { status: "error", lastUpdated: Math.floor(Date.now() / 1000), errorMessage: lastError?.message || "Unable to connect to KTA", }, }; } if (spinner && !lastError) { spinner.succeed("Status retrieved successfully!"); } else if (spinner && lastError) { spinner.warn("Status retrieved with warnings"); } if (json) { const output = { success: true, status: agentStatus, schemaId: "https://schemas.kya-os.ai/mcpi/agent-status/v1.0.0.json", warning: lastError ? `KTA connection issue: ${lastError.message}` : undefined, }; console.log(JSON.stringify(output, null, 2)); } else { console.log(`\n${chalk.bold("šŸ”‘ Identity Information:")}`); console.log(` DID: ${chalk.gray(agentStatus.did)}`); console.log(` Key ID: ${chalk.gray(agentStatus.kid)}`); console.log(` KTA URL: ${chalk.cyan(agentStatus.ktaURL)}`); console.log(`\n${chalk.bold("šŸ”„ MCP Registry Mirror:")}`); const statusColor = agentStatus.mirrorStatus.status === "success" ? chalk.green : agentStatus.mirrorStatus.status === "error" ? chalk.red : chalk.yellow; console.log(` Status: ${statusColor(agentStatus.mirrorStatus.status)}`); console.log(` Last Updated: ${chalk.gray(new Date(agentStatus.mirrorStatus.lastUpdated * 1000).toISOString())}`); if (agentStatus.mirrorStatus.registryURL) { console.log(` Registry URL: ${chalk.cyan(agentStatus.mirrorStatus.registryURL)}`); } if (agentStatus.mirrorStatus.errorMessage) { console.log(` Error: ${chalk.red(agentStatus.mirrorStatus.errorMessage)}`); } if (agentStatus.lastHandshake) { console.log(`\n${chalk.bold("šŸ¤ Last Handshake:")}`); const handshakeTime = new Date(agentStatus.lastHandshake * 1000); const timeDiff = Math.floor((Date.now() - handshakeTime.getTime()) / 1000); const timeAgo = timeDiff < 60 ? `${timeDiff}s ago` : timeDiff < 3600 ? `${Math.floor(timeDiff / 60)}m ago` : `${Math.floor(timeDiff / 3600)}h ago`; console.log(` Timestamp: ${chalk.gray(handshakeTime.toISOString())} ${chalk.dim(`(${timeAgo})`)}`); } // Status-specific messages - handle mirror status without failing on pending (R8.8) if (agentStatus.mirrorStatus.status === "pending") { showInfo("Mirror status is pending. This is normal for new registrations and will be processed automatically."); } else if (agentStatus.mirrorStatus.status === "success") { showSuccess("Agent is successfully mirrored to MCP Registry!"); } else if (agentStatus.mirrorStatus.status === "error") { showError("Mirror status shows an error. The system will retry automatically."); } // KTA connection warning if (lastError) { showInfo(`Warning: Could not connect to KTA (${lastError.message}). Showing cached/local information.`); } // Development agent notice if (agentStatus.did.includes("localhost")) { showInfo("This is a development agent. It won't appear in public directories."); } } } catch (error) { spinner?.fail("Failed to fetch status"); const errorMessage = error.message || "Failed to get agent status"; if (json) { console.log(JSON.stringify({ success: false, error: errorMessage, code: error.code || "XMCP_I_ESTATUS", }, null, 2)); } else { if (error.message?.includes("429")) { showError("Rate limit exceeded. Please try again in a few minutes."); } else if (error.message?.includes("Network")) { showError("Network error. Check your internet connection."); } else { showError(errorMessage); } // Provide fallback information console.log(`\n${chalk.gray("Local identity information:")}`); console.log(` DID: ${chalk.gray(processVars.AGENT_DID)}`); if (processVars.AGENT_KEY_ID) { console.log(` Key ID: ${chalk.gray(processVars.AGENT_KEY_ID)}`); } console.log(` KTA URL: ${chalk.cyan(`https://knowthat.ai/agents/by-did/${encodeURIComponent(processVars.AGENT_DID)}`)}`); } // Important: Don't exit with non-zero status for mirror pending or KTA connection issues (R8.8) // Only exit with error for critical failures like missing identity if (!processVars.AGENT_DID && process.env.NODE_ENV !== "test") { process.exit(1); } } } //# sourceMappingURL=status.js.map