feat(agent): unify models and validate OpenCode providers

Generate chat, task and learning models from agent-models.json.
Use WaterNetwork fast/expert models with 272k context and validate
upstream names before readiness. Add an isolated model check command
with signal-safe cleanup and plugin, Skill and MCP management docs.

Verified in isolation: type checks, 26 focused tests and both model
catalog checks; no model inference requests.
This commit is contained in:
2026-10-09 11:28:37 +08:00
parent 75d8d526f9
commit d58bd19039
30 changed files with 1125 additions and 469 deletions
+9
View File
@@ -11,6 +11,7 @@ import { z } from "zod";
import { resolve } from "node:path";
import { registerSessionSandbox } from "../session-sandbox.js";
import { registerMcpPolicy } from "../mcp-policy.js";
import { checkOpencodeModels } from "../model-check.js";
import add_task_human_evidence from "../tools/add_task_human_evidence.js";
import clear_scada_analysis from "../tools/clear_scada_analysis.js";
@@ -104,6 +105,13 @@ export default Plugin.define({
await ctx.rpc.register(Rpc.define({
id: "tjwater.tools",
methods: {
check_models: {
input: z.object({ models: z.array(z.object({ id: z.string(), provider_id: z.string(), model_id: z.string(), wire_id: z.string(), requires_tools: z.boolean() }).strict()).min(1).max(1000) }).strict(),
output: z.object({
models: z.array(z.object({ id: z.string(), model_id: z.string(), status: z.enum(["valid", "not_registered", "not_enabled", "no_tools", "wire_id_mismatch", "not_advertised", "unchecked"]) })),
providers: z.array(z.object({ id: z.string(), status: z.enum(["checked", "not_registered", "unsupported_catalog", "catalog_unavailable", "catalog_invalid", "credentials_unavailable"]), http_status: z.number().int().optional() })),
}),
},
list: {
input: z.object({}),
output: z.array(z.object({ id: z.string(), direct: z.boolean(), sandboxed: z.boolean(), workspaceRoot: z.string().optional() })),
@@ -122,6 +130,7 @@ export default Plugin.define({
},
events: {},
}), {
check_models: (input, context) => checkOpencodeModels(ctx, input, context.signal),
mcp: mcpReport,
list: async () => (await ctx.tool.list()).map((tool) => ({
id: tool.id,