feat(agent): unify MCP tools and adopt Responses delivery
Move project and host queries into native MCP with host-owned OAuth/context, while retaining memory, skills, actions and publication plugins. Add nearby-model queries and explicit chat/task/learning model defaults. Adopt Responses HTTP/SSE and native steer/queue inbox delivery, preserving scoped session ownership, pending input edits and investigation communication. Disable local-provider discovery: Server /health allowed native vLLM to probe /v1/models on port 8000. A native before/after regression prevents recurrence. Validation: 170 focused Bun tests; service/plugin typechecks; native discovery, provider-discovery and input-inbox smoke checks; no paid model inference.
This commit is contained in:
+10
-6
@@ -17,7 +17,11 @@ const modelSchema = z.object({
|
||||
compatibility: z.record(z.unknown()).optional(),
|
||||
}).strict();
|
||||
const modelConfigSchema = z.object({
|
||||
default_model: text, task_model: text.optional(), learning_gate_model: text.optional(),
|
||||
defaults: z.object({
|
||||
chat: text,
|
||||
task: text,
|
||||
learning_gate: text,
|
||||
}).strict(),
|
||||
providers: z.record(z.object({
|
||||
name: text, api_url: text, api_key: text.optional(),
|
||||
package: text.default("@opencode/ai/providers/openai-compatible"),
|
||||
@@ -55,7 +59,7 @@ export const getAgentModelIds = (options: AgentModelOption[]) => options.map((mo
|
||||
export function parseAgentModelConfig(input: unknown): AgentModelConfig {
|
||||
const parsed = modelConfigSchema.safeParse(input);
|
||||
// Do not echo invalid values: provider configuration can contain credentials.
|
||||
if (!parsed.success) throw new Error("invalid agent model configuration structure");
|
||||
if (!parsed.success) throw new Error("invalid agent model configuration structure; configure role models under defaults.chat, defaults.task and defaults.learning_gate");
|
||||
const configuration = parsed.data;
|
||||
for (const [id, provider] of Object.entries(configuration.providers)) {
|
||||
if (!/^[A-Za-z0-9_-]+$/.test(id)) throw new Error("provider ID must contain only letters, digits, _ or -");
|
||||
@@ -72,10 +76,10 @@ export function parseAgentModelConfig(input: unknown): AgentModelConfig {
|
||||
for (const modelID of Object.keys(provider.models)) parseModelReference(`${id}/${modelID}`);
|
||||
}
|
||||
const allowed = getAgentModelIds(configuredToolModels(configuration));
|
||||
for (const role of ["default_model", "task_model", "learning_gate_model"] as const) {
|
||||
if (configuration[role] && !allowed.includes(configuration[role]!)) throw new Error(`${role} must name an enabled configured text model with tool support`);
|
||||
for (const role of ["chat", "task", "learning_gate"] as const) {
|
||||
if (!allowed.includes(configuration.defaults[role])) throw new Error(`defaults.${role} must name an enabled configured text model with tool support`);
|
||||
}
|
||||
if (!getAgentModelIds(getAgentModelOptions(configuration)).includes(configuration.default_model)) throw new Error("default_model must be selectable in the chat catalog");
|
||||
if (!getAgentModelIds(getAgentModelOptions(configuration)).includes(configuration.defaults.chat)) throw new Error("defaults.chat must be selectable in the chat catalog");
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@@ -101,5 +105,5 @@ export function compileOpencodeModels(configuration: AgentModelConfig) {
|
||||
}])),
|
||||
}];
|
||||
}));
|
||||
return { model: configuration.default_model, providers };
|
||||
return { model: configuration.defaults.chat, providers };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user