Skip to main content
Glama
systempromptio

SystemPrompt Coding Agent

Official
check-status.ts8.28 kB
/** * @fileoverview Check status orchestrator tool handler that inspects system health, * service availability, and active tasks/sessions across the orchestration platform * @module handlers/tools/orchestrator/check-status */ import type { ToolHandler, CallToolResult, ToolHandlerContext } from "./types.js"; import { formatToolResponse } from "./types.js"; import { logger } from "../../utils/logger.js"; import { execSync } from "child_process"; import * as net from "net"; import { type CheckStatusArgs, StatusCheckError, SystemStatus, ServiceStatus, SessionStatus, type CheckStatusResponse } from "./utils/index.js"; import { agentToOrchestratorState, type AgentState } from "../../types/session-states.js"; import { isToolAvailable, taskOperations, agentOperations } from "./utils/index.js"; import { TASK_STATUS } from "../../constants/task-status.js"; /** * Internal service status information */ interface InternalServiceStatus { available: boolean; cli_path: string | null; error: string | null; version: string | null; cli_name: string; daemon_reachable?: boolean; daemon_has_tool?: boolean; } /** * Checks the status of Claude Code SDK availability * * @param args - Check status parameters including verbosity and test options * @param context - Execution context containing session information * @returns Comprehensive status report of all services and system state * * @example * ```typescript * await handleCheckStatus({ * verbose: true, * include_tasks: true * }); * ``` */ export const handleCheckStatus: ToolHandler<CheckStatusArgs> = async ( args: CheckStatusArgs, context?: ToolHandlerContext, ): Promise<CallToolResult> => { try { logger.info("Checking system status", { sessionId: context?.sessionId, }); const claudeStatus = createEmptyServiceStatus("Claude Code"); const daemonHost = process.env.CLAUDE_PROXY_HOST || process.env.HOST_BRIDGE_DAEMON_HOST || "host.docker.internal"; const daemonPort = parseInt( process.env.CLAUDE_PROXY_PORT || process.env.HOST_BRIDGE_DAEMON_PORT || "9876", 10, ); const daemonStatus = await checkDaemonConnectivity(); if (daemonStatus.reachable) { claudeStatus.daemon_reachable = true; claudeStatus.daemon_has_tool = daemonStatus.tools.includes("claude"); claudeStatus.available = claudeStatus.daemon_has_tool; claudeStatus.cli_path = process.env.CLAUDE_PATH || null; } else { claudeStatus.available = isToolAvailable("CLAUDECODE"); } await checkClaudeCodeVersion(claudeStatus); const tasks = await taskOperations.taskStore.getAllTasks(); const activeTasks = tasks.filter( (t: any) => t.status === TASK_STATUS.PENDING || t.status === TASK_STATUS.IN_PROGRESS || t.status === TASK_STATUS.WAITING, ); const sessions = agentOperations.agentManager.getAllSessions(); const activeSessions = sessions.filter( (s: any) => s.status === "active" || s.status === "busy", ); const claudeActive = claudeStatus.available; let systemStatus: SystemStatus; if (claudeActive) { systemStatus = SystemStatus.ACTIVE; } else { systemStatus = SystemStatus.NOT_ACTIVE; } logger.info("Status check completed", { systemStatus, claudeActive, activeTasks: activeTasks.length, activeSessions: activeSessions.length, }); const response: CheckStatusResponse = { status: systemStatus, services: { claude: { status: claudeActive ? ServiceStatus.ACTIVE : ServiceStatus.NOT_ACTIVE, available: claudeActive, }, }, daemon: { connected: daemonStatus.reachable, host: daemonHost, port: daemonPort, }, tasks: { active: activeTasks.length, total: tasks.length, }, sessions: { active: activeSessions.length, total: sessions.length, }, processes: activeSessions.map((s: any) => { const orchestratorState = agentToOrchestratorState(s.status as AgentState); const status = orchestratorState === 'active' ? SessionStatus.ACTIVE : orchestratorState === 'busy' ? SessionStatus.BUSY : SessionStatus.TERMINATED; return { id: s.id, type: s.type as "claude", status, taskId: s.taskId, }; }), }; return formatToolResponse({ message: `System ${systemStatus}`, result: response, }); } catch (error) { logger.error("Failed to check status", { error, args }); if (error instanceof StatusCheckError) { return formatToolResponse({ status: "error", message: error.message, error: { type: "status_check_error", details: error.details, }, }); } return formatToolResponse({ status: "error", message: error instanceof Error ? error.message : "Failed to check status", error: { type: "status_check_error", details: error instanceof Error ? error.stack : undefined, }, }); } }; /** * Creates an empty service status object * * @param cliName - Name of the CLI service * @returns Empty internal service status structure */ function createEmptyServiceStatus(cliName: string): InternalServiceStatus { return { available: false, cli_path: null, error: null, version: null, cli_name: cliName, }; } /** * Checks daemon connectivity and available tools * * @returns Daemon status with reachability and available tools */ async function checkDaemonConnectivity(): Promise<{ reachable: boolean; tools: string[]; error?: string; }> { const proxyHost = process.env.CLAUDE_PROXY_HOST || process.env.HOST_BRIDGE_DAEMON_HOST || "host.docker.internal"; const proxyPort = parseInt( process.env.CLAUDE_PROXY_PORT || process.env.HOST_BRIDGE_DAEMON_PORT || "9876", 10, ); return new Promise((resolve) => { const timeout = setTimeout(() => { client.destroy(); resolve({ reachable: false, tools: [], error: "Connection timeout" }); }, 5000); const client = net.createConnection({ port: proxyPort, host: proxyHost }); client.on("connect", () => { clearTimeout(timeout); const message = JSON.stringify({ tool: "status", command: "check", }); client.write(message + "\n"); let responseData = ""; client.on("data", (data) => { responseData += data.toString(); if (responseData.includes("Available tools:")) { const tools: string[] = []; if (responseData.includes("claude")) tools.push("claude"); client.destroy(); resolve({ reachable: true, tools }); } }); setTimeout(() => { client.destroy(); resolve({ reachable: true, tools: [] }); }, 2000); }); client.on("error", (error) => { clearTimeout(timeout); resolve({ reachable: false, tools: [], error: error instanceof Error ? error.message : String(error), }); }); }); } /** * Checks Claude Code CLI version * * @param claudeStatus - Service status object to update with version info */ async function checkClaudeCodeVersion(claudeStatus: InternalServiceStatus): Promise<void> { try { if (!claudeStatus.available && !claudeStatus.daemon_has_tool) { claudeStatus.error = "Claude Code CLI not available"; return; } if (claudeStatus.daemon_reachable && claudeStatus.daemon_has_tool) { logger.info("Claude available through daemon"); claudeStatus.version = "Available via daemon"; return; } logger.info("Checking Claude Code version locally"); const version = execSync("claude --version", { encoding: "utf-8", env: { ...process.env }, timeout: 30000, }).trim(); claudeStatus.version = version; logger.info("Claude Code version detected", { version }); } catch (error) { claudeStatus.error = "Failed to get Claude Code version"; logger.error("Claude Code version check failed", { error }); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systempromptio/systemprompt-code-orchestrator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server