diff --git a/assets/help/status.schema.json b/assets/help/status.schema.json new file mode 100644 index 000000000..4b1e56f38 --- /dev/null +++ b/assets/help/status.schema.json @@ -0,0 +1,269 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/help/status.schema.json", + "title": "System Status", + "description": "JSON schema for oh-my-openagent system status output", + "type": "object", + "properties": { + "system": { + "type": "object", + "properties": { + "opencode": { + "type": "object", + "properties": { + "version": { + "type": "string", + "description": "OpenCode version" + }, + "running": { + "type": "boolean", + "description": "Whether the server is running" + }, + "uptime": { + "type": "number", + "description": "Server uptime in seconds" + } + }, + "required": [ + "version", + "running", + "uptime" + ], + "additionalProperties": false, + "description": "OpenCode server health" + }, + "sessions": { + "type": "object", + "properties": { + "total": { + "type": "number", + "description": "Total session count" + }, + "active": { + "type": "number", + "description": "Active session count" + }, + "statuses": { + "description": "Per-session statuses", + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "idle", + "retry", + "busy" + ], + "description": "Current session state" + }, + "attempt": { + "description": "Retry attempt count", + "type": "number" + }, + "message": { + "description": "Status detail message", + "type": "string" + }, + "next": { + "description": "Next retry timestamp (epoch ms)", + "type": "number" + } + }, + "required": [ + "type" + ], + "additionalProperties": false, + "ref": "SessionStatus" + } + } + }, + "required": [ + "total", + "active" + ], + "additionalProperties": false, + "description": "Session overview" + }, + "providers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Provider identifier" + }, + "name": { + "type": "string", + "description": "Provider display name" + }, + "connected": { + "type": "boolean", + "description": "Whether the provider is connected" + }, + "defaultModel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Default model ID" + }, + "modelsAvailable": { + "type": "number", + "description": "Number of available models" + } + }, + "required": [ + "id", + "name", + "connected", + "defaultModel", + "modelsAvailable" + ], + "additionalProperties": false, + "ref": "ProviderHealth" + }, + "description": "Provider connection statuses" + }, + "mcps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "MCP server name" + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "error" + ], + "description": "Server run state" + }, + "error": { + "description": "Error message if status is error", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "name", + "status" + ], + "additionalProperties": false, + "ref": "McpHealth" + }, + "description": "MCP server statuses" + }, + "lsps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "LSP server identifier" + }, + "running": { + "type": "boolean", + "description": "Whether the LSP server is running" + }, + "workspaceRoot": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Workspace root path" + } + }, + "required": [ + "id", + "running", + "workspaceRoot" + ], + "additionalProperties": false, + "ref": "LspHealth" + }, + "description": "LSP server statuses" + }, + "plugins": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Plugin name" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Plugin version" + }, + "enabled": { + "type": "boolean", + "description": "Whether the plugin is loaded" + } + }, + "required": [ + "name", + "version", + "enabled" + ], + "additionalProperties": false + }, + "description": "Loaded plugins" + } + }, + "required": [ + "opencode", + "sessions", + "providers", + "mcps", + "lsps", + "plugins" + ], + "additionalProperties": false, + "ref": "SystemHealth", + "description": "Overall system health" + }, + "timestamp": { + "type": "number", + "description": "Snapshot timestamp (epoch ms)" + } + }, + "required": [ + "system", + "timestamp" + ], + "additionalProperties": false, + "ref": "StatusResult" +} \ No newline at end of file diff --git a/script/build-help-schemas.ts b/script/build-help-schemas.ts index 606d75a96..c705d3711 100644 --- a/script/build-help-schemas.ts +++ b/script/build-help-schemas.ts @@ -1,7 +1,7 @@ #!/usr/bin/env bun import { z } from "zod" import { DoctorResultSchema as DoctorSchema } from "../src/help/schema/doctor" - +import { StatusResultSchema as StatusSchema } from "../src/help/schema/status" const SCHEMA_OUTPUT_DIR = "assets/help" interface SchemaEntry { @@ -39,6 +39,13 @@ const SCHEMAS: SchemaEntry[] = [ description: "JSON schema for oh-my-openagent doctor diagnostic output", id: "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/help/doctor.schema.json", }, + { + name: "status", + schema: StatusSchema, + title: "System Status", + description: "JSON schema for oh-my-openagent system status output", + id: "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/help/status.schema.json", + }, ] async function main() { diff --git a/src/help/schema/status.ts b/src/help/schema/status.ts new file mode 100644 index 000000000..fd49a71d0 --- /dev/null +++ b/src/help/schema/status.ts @@ -0,0 +1,77 @@ +import { z } from "zod" + +/** + * Help JSON schema for the `status` surface. + * Defines the structure of overall system status output. + */ +export const SessionStatusSchema = z + .object({ + type: z.enum(["idle", "retry", "busy"]).describe("Current session state"), + attempt: z.number().optional().describe("Retry attempt count"), + message: z.string().optional().describe("Status detail message"), + next: z.number().optional().describe("Next retry timestamp (epoch ms)"), + }) + .meta({ ref: "SessionStatus" }) + +export const ProviderHealthSchema = z + .object({ + id: z.string().describe("Provider identifier"), + name: z.string().describe("Provider display name"), + connected: z.boolean().describe("Whether the provider is connected"), + defaultModel: z.string().nullable().describe("Default model ID"), + modelsAvailable: z.number().describe("Number of available models"), + }) + .meta({ ref: "ProviderHealth" }) + +export const McpHealthSchema = z + .object({ + name: z.string().describe("MCP server name"), + status: z.enum(["running", "stopped", "error"]).describe("Server run state"), + error: z.string().nullable().optional().describe("Error message if status is error"), + }) + .meta({ ref: "McpHealth" }) + +export const LspHealthSchema = z + .object({ + id: z.string().describe("LSP server identifier"), + running: z.boolean().describe("Whether the LSP server is running"), + workspaceRoot: z.string().nullable().describe("Workspace root path"), + }) + .meta({ ref: "LspHealth" }) + +export const SystemHealthSchema = z + .object({ + opencode: z.object({ + version: z.string().describe("OpenCode version"), + running: z.boolean().describe("Whether the server is running"), + uptime: z.number().describe("Server uptime in seconds"), + }).describe("OpenCode server health"), + sessions: z.object({ + total: z.number().describe("Total session count"), + active: z.number().describe("Active session count"), + statuses: z.record(z.string(), SessionStatusSchema).optional().describe("Per-session statuses"), + }).describe("Session overview"), + providers: z.array(ProviderHealthSchema).describe("Provider connection statuses"), + mcps: z.array(McpHealthSchema).describe("MCP server statuses"), + lsps: z.array(LspHealthSchema).describe("LSP server statuses"), + plugins: z.array(z.object({ + name: z.string().describe("Plugin name"), + version: z.string().nullable().describe("Plugin version"), + enabled: z.boolean().describe("Whether the plugin is loaded"), + })).describe("Loaded plugins"), + }) + .meta({ ref: "SystemHealth" }) + +export const StatusResultSchema = z + .object({ + system: SystemHealthSchema.describe("Overall system health"), + timestamp: z.number().describe("Snapshot timestamp (epoch ms)"), + }) + .meta({ ref: "StatusResult" }) + +export type SessionStatus = z.infer +export type ProviderHealth = z.infer +export type McpHealth = z.infer +export type LspHealth = z.infer +export type SystemHealth = z.infer +export type StatusResult = z.infer