@kya-os/cli
Version:
CLI for MCP-I setup and management
199 lines ⢠8.97 kB
JavaScript
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