feat(help): #686 doctor help JSON schema
This commit is contained in:
@@ -0,0 +1,344 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/help/doctor.schema.json",
|
||||||
|
"title": "Doctor Diagnostic Result",
|
||||||
|
"description": "JSON schema for oh-my-openagent doctor diagnostic output",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"results": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Check display name"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"pass",
|
||||||
|
"fail",
|
||||||
|
"warn",
|
||||||
|
"skip"
|
||||||
|
],
|
||||||
|
"description": "Check outcome"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Result summary message"
|
||||||
|
},
|
||||||
|
"details": {
|
||||||
|
"description": "Detailed diagnostic lines",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"issues": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Short issue title"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Detailed description of the issue"
|
||||||
|
},
|
||||||
|
"fix": {
|
||||||
|
"description": "Suggested fix or remediation",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"affects": {
|
||||||
|
"description": "Components or areas affected",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"severity": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"error",
|
||||||
|
"warning"
|
||||||
|
],
|
||||||
|
"description": "Severity level of the issue"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"title",
|
||||||
|
"description",
|
||||||
|
"severity"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"ref": "DoctorIssue"
|
||||||
|
},
|
||||||
|
"description": "Issues found by this check"
|
||||||
|
},
|
||||||
|
"duration": {
|
||||||
|
"description": "Check execution time in milliseconds",
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"status",
|
||||||
|
"message",
|
||||||
|
"issues"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"ref": "CheckResult"
|
||||||
|
},
|
||||||
|
"description": "All check results"
|
||||||
|
},
|
||||||
|
"systemInfo": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"opencodeVersion": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Installed OpenCode version"
|
||||||
|
},
|
||||||
|
"opencodePath": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Path to OpenCode binary"
|
||||||
|
},
|
||||||
|
"pluginVersion": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "oh-my-openagent plugin version"
|
||||||
|
},
|
||||||
|
"loadedVersion": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Loaded plugin version at runtime"
|
||||||
|
},
|
||||||
|
"bunVersion": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Bun runtime version"
|
||||||
|
},
|
||||||
|
"configPath": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Path to active config file"
|
||||||
|
},
|
||||||
|
"configValid": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the config parses correctly"
|
||||||
|
},
|
||||||
|
"isLocalDev": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether running in local development mode"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"opencodeVersion",
|
||||||
|
"opencodePath",
|
||||||
|
"pluginVersion",
|
||||||
|
"loadedVersion",
|
||||||
|
"bunVersion",
|
||||||
|
"configPath",
|
||||||
|
"configValid",
|
||||||
|
"isLocalDev"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"ref": "SystemInfo",
|
||||||
|
"description": "System environment information"
|
||||||
|
},
|
||||||
|
"tools": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"lspServers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "LSP server identifier"
|
||||||
|
},
|
||||||
|
"extensions": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "File extensions handled"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"extensions"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"ref": "LspServerInfo"
|
||||||
|
},
|
||||||
|
"description": "Detected LSP servers"
|
||||||
|
},
|
||||||
|
"astGrepCli": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "AST-Grep CLI availability"
|
||||||
|
},
|
||||||
|
"astGrepNapi": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "AST-Grep NAPI availability"
|
||||||
|
},
|
||||||
|
"commentChecker": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Comment checker availability"
|
||||||
|
},
|
||||||
|
"ghCli": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"installed": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether GitHub CLI is installed"
|
||||||
|
},
|
||||||
|
"authenticated": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether GitHub CLI is authenticated"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "GitHub username if authenticated"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"installed",
|
||||||
|
"authenticated",
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"ref": "GhCliInfo",
|
||||||
|
"description": "GitHub CLI status"
|
||||||
|
},
|
||||||
|
"mcpBuiltin": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "Built-in MCP server names"
|
||||||
|
},
|
||||||
|
"mcpUser": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "User-configured MCP server names"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"lspServers",
|
||||||
|
"astGrepCli",
|
||||||
|
"astGrepNapi",
|
||||||
|
"commentChecker",
|
||||||
|
"ghCli",
|
||||||
|
"mcpBuiltin",
|
||||||
|
"mcpUser"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"ref": "ToolsSummary",
|
||||||
|
"description": "Tool and server availability summary"
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"total": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Total number of checks run"
|
||||||
|
},
|
||||||
|
"passed": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Checks that passed"
|
||||||
|
},
|
||||||
|
"failed": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Checks that failed"
|
||||||
|
},
|
||||||
|
"warnings": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Checks with warnings"
|
||||||
|
},
|
||||||
|
"skipped": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Checks that were skipped"
|
||||||
|
},
|
||||||
|
"duration": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Total execution time in milliseconds"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"total",
|
||||||
|
"passed",
|
||||||
|
"failed",
|
||||||
|
"warnings",
|
||||||
|
"skipped",
|
||||||
|
"duration"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"ref": "DoctorSummary",
|
||||||
|
"description": "Aggregate check statistics"
|
||||||
|
},
|
||||||
|
"exitCode": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Process exit code (0 = success)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"results",
|
||||||
|
"systemInfo",
|
||||||
|
"tools",
|
||||||
|
"summary",
|
||||||
|
"exitCode"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"ref": "DoctorResult"
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env bun
|
||||||
|
import { z } from "zod"
|
||||||
|
import { DoctorResultSchema as DoctorSchema } from "../src/help/schema/doctor"
|
||||||
|
|
||||||
|
const SCHEMA_OUTPUT_DIR = "assets/help"
|
||||||
|
|
||||||
|
interface SchemaEntry {
|
||||||
|
name: string
|
||||||
|
schema: z.ZodType
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
async function writeJsonSchema(entry: SchemaEntry): Promise<void> {
|
||||||
|
const jsonSchema = z.toJSONSchema(entry.schema, {
|
||||||
|
target: "draft-7",
|
||||||
|
unrepresentable: "any",
|
||||||
|
}) as Record<string, unknown>
|
||||||
|
|
||||||
|
const output = {
|
||||||
|
$schema: "http://json-schema.org/draft-07/schema#",
|
||||||
|
$id: entry.id,
|
||||||
|
title: entry.title,
|
||||||
|
description: entry.description,
|
||||||
|
...jsonSchema,
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = `${SCHEMA_OUTPUT_DIR}/${entry.name}.schema.json`
|
||||||
|
await Bun.write(filePath, JSON.stringify(output, null, 2))
|
||||||
|
console.log(` ✓ ${entry.name}.schema.json`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const SCHEMAS: SchemaEntry[] = [
|
||||||
|
{
|
||||||
|
name: "doctor",
|
||||||
|
schema: DoctorSchema,
|
||||||
|
title: "Doctor Diagnostic Result",
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log("Generating Help JSON Schemas...\n")
|
||||||
|
for (const entry of SCHEMAS) {
|
||||||
|
await writeJsonSchema(entry)
|
||||||
|
}
|
||||||
|
console.log(`\nDone — ${SCHEMAS.length} schema(s) generated in ${SCHEMA_OUTPUT_DIR}/`)
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Help JSON schema for the `doctor` surface.
|
||||||
|
* Defines the structure of doctor diagnostic output.
|
||||||
|
*/
|
||||||
|
export const DoctorIssueSchema = z
|
||||||
|
.object({
|
||||||
|
title: z.string().describe("Short issue title"),
|
||||||
|
description: z.string().describe("Detailed description of the issue"),
|
||||||
|
fix: z.string().optional().describe("Suggested fix or remediation"),
|
||||||
|
affects: z.array(z.string()).optional().describe("Components or areas affected"),
|
||||||
|
severity: z.enum(["error", "warning"]).describe("Severity level of the issue"),
|
||||||
|
})
|
||||||
|
.meta({ ref: "DoctorIssue" })
|
||||||
|
|
||||||
|
export const CheckResultSchema = z
|
||||||
|
.object({
|
||||||
|
name: z.string().describe("Check display name"),
|
||||||
|
status: z.enum(["pass", "fail", "warn", "skip"]).describe("Check outcome"),
|
||||||
|
message: z.string().describe("Result summary message"),
|
||||||
|
details: z.array(z.string()).optional().describe("Detailed diagnostic lines"),
|
||||||
|
issues: z.array(DoctorIssueSchema).describe("Issues found by this check"),
|
||||||
|
duration: z.number().optional().describe("Check execution time in milliseconds"),
|
||||||
|
})
|
||||||
|
.meta({ ref: "CheckResult" })
|
||||||
|
|
||||||
|
export const SystemInfoSchema = z
|
||||||
|
.object({
|
||||||
|
opencodeVersion: z.string().nullable().describe("Installed OpenCode version"),
|
||||||
|
opencodePath: z.string().nullable().describe("Path to OpenCode binary"),
|
||||||
|
pluginVersion: z.string().nullable().describe("oh-my-openagent plugin version"),
|
||||||
|
loadedVersion: z.string().nullable().describe("Loaded plugin version at runtime"),
|
||||||
|
bunVersion: z.string().nullable().describe("Bun runtime version"),
|
||||||
|
configPath: z.string().nullable().describe("Path to active config file"),
|
||||||
|
configValid: z.boolean().describe("Whether the config parses correctly"),
|
||||||
|
isLocalDev: z.boolean().describe("Whether running in local development mode"),
|
||||||
|
})
|
||||||
|
.meta({ ref: "SystemInfo" })
|
||||||
|
|
||||||
|
export const LspServerInfoSchema = z
|
||||||
|
.object({
|
||||||
|
id: z.string().describe("LSP server identifier"),
|
||||||
|
extensions: z.array(z.string()).describe("File extensions handled"),
|
||||||
|
})
|
||||||
|
.meta({ ref: "LspServerInfo" })
|
||||||
|
|
||||||
|
export const GhCliInfoSchema = z
|
||||||
|
.object({
|
||||||
|
installed: z.boolean().describe("Whether GitHub CLI is installed"),
|
||||||
|
authenticated: z.boolean().describe("Whether GitHub CLI is authenticated"),
|
||||||
|
username: z.string().nullable().describe("GitHub username if authenticated"),
|
||||||
|
})
|
||||||
|
.meta({ ref: "GhCliInfo" })
|
||||||
|
|
||||||
|
export const ToolsSummarySchema = z
|
||||||
|
.object({
|
||||||
|
lspServers: z.array(LspServerInfoSchema).describe("Detected LSP servers"),
|
||||||
|
astGrepCli: z.boolean().describe("AST-Grep CLI availability"),
|
||||||
|
astGrepNapi: z.boolean().describe("AST-Grep NAPI availability"),
|
||||||
|
commentChecker: z.boolean().describe("Comment checker availability"),
|
||||||
|
ghCli: GhCliInfoSchema.describe("GitHub CLI status"),
|
||||||
|
mcpBuiltin: z.array(z.string()).describe("Built-in MCP server names"),
|
||||||
|
mcpUser: z.array(z.string()).describe("User-configured MCP server names"),
|
||||||
|
})
|
||||||
|
.meta({ ref: "ToolsSummary" })
|
||||||
|
|
||||||
|
export const DoctorSummarySchema = z
|
||||||
|
.object({
|
||||||
|
total: z.number().describe("Total number of checks run"),
|
||||||
|
passed: z.number().describe("Checks that passed"),
|
||||||
|
failed: z.number().describe("Checks that failed"),
|
||||||
|
warnings: z.number().describe("Checks with warnings"),
|
||||||
|
skipped: z.number().describe("Checks that were skipped"),
|
||||||
|
duration: z.number().describe("Total execution time in milliseconds"),
|
||||||
|
})
|
||||||
|
.meta({ ref: "DoctorSummary" })
|
||||||
|
|
||||||
|
export const DoctorResultSchema = z
|
||||||
|
.object({
|
||||||
|
results: z.array(CheckResultSchema).describe("All check results"),
|
||||||
|
systemInfo: SystemInfoSchema.describe("System environment information"),
|
||||||
|
tools: ToolsSummarySchema.describe("Tool and server availability summary"),
|
||||||
|
summary: DoctorSummarySchema.describe("Aggregate check statistics"),
|
||||||
|
exitCode: z.number().describe("Process exit code (0 = success)"),
|
||||||
|
})
|
||||||
|
.meta({ ref: "DoctorResult" })
|
||||||
|
|
||||||
|
export type DoctorIssue = z.infer<typeof DoctorIssueSchema>
|
||||||
|
export type CheckResult = z.infer<typeof CheckResultSchema>
|
||||||
|
export type SystemInfo = z.infer<typeof SystemInfoSchema>
|
||||||
|
export type LspServerInfo = z.infer<typeof LspServerInfoSchema>
|
||||||
|
export type GhCliInfo = z.infer<typeof GhCliInfoSchema>
|
||||||
|
export type ToolsSummary = z.infer<typeof ToolsSummarySchema>
|
||||||
|
export type DoctorSummary = z.infer<typeof DoctorSummarySchema>
|
||||||
|
export type DoctorResult = z.infer<typeof DoctorResultSchema>
|
||||||
Reference in New Issue
Block a user