From 8db26483394953aa4246fae04883b50abfe69696 Mon Sep 17 00:00:00 2001 From: ismeth Date: Thu, 19 Feb 2026 13:53:04 +0100 Subject: [PATCH] feat(athena): add temperature support to council member schema Allow per-member temperature overrides in council config. Adds temperature field to CouncilMemberSchema (0-2 range), CouncilMemberConfig type, and auto-generated JSON schema. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus --- assets/oh-my-opencode.schema.json | 178 ++++++++++++++++++++++++++++++ src/agents/athena/types.ts | 1 + src/config/schema/athena.test.ts | 40 ++++++- src/config/schema/athena.ts | 1 + 4 files changed, 219 insertions(+), 1 deletion(-) diff --git a/assets/oh-my-opencode.schema.json b/assets/oh-my-opencode.schema.json index b19e68bb..9ba32cc9 100644 --- a/assets/oh-my-opencode.schema.json +++ b/assets/oh-my-opencode.schema.json @@ -3156,6 +3156,179 @@ }, "additionalProperties": false }, + "council-member": { + "type": "object", + "properties": { + "model": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "category": { + "type": "string" + }, + "skills": { + "type": "array", + "items": { + "type": "string" + } + }, + "temperature": { + "type": "number", + "minimum": 0, + "maximum": 2 + }, + "top_p": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "prompt": { + "type": "string" + }, + "prompt_append": { + "type": "string" + }, + "tools": { + "type": "object", + "additionalProperties": { + "type": "boolean" + } + }, + "disable": { + "type": "boolean" + }, + "description": { + "type": "string" + }, + "mode": { + "type": "string", + "enum": [ + "subagent", + "primary", + "all" + ] + }, + "color": { + "type": "string", + "pattern": "^#[0-9A-Fa-f]{6}$" + }, + "permission": { + "type": "object", + "properties": { + "edit": { + "type": "string", + "enum": [ + "ask", + "allow", + "deny" + ] + }, + "bash": { + "anyOf": [ + { + "type": "string", + "enum": [ + "ask", + "allow", + "deny" + ] + }, + { + "type": "object", + "additionalProperties": { + "type": "string", + "enum": [ + "ask", + "allow", + "deny" + ] + } + } + ] + }, + "webfetch": { + "type": "string", + "enum": [ + "ask", + "allow", + "deny" + ] + }, + "task": { + "type": "string", + "enum": [ + "ask", + "allow", + "deny" + ] + }, + "doom_loop": { + "type": "string", + "enum": [ + "ask", + "allow", + "deny" + ] + }, + "external_directory": { + "type": "string", + "enum": [ + "ask", + "allow", + "deny" + ] + } + }, + "additionalProperties": false + }, + "maxTokens": { + "type": "number" + }, + "thinking": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ] + }, + "budgetTokens": { + "type": "number" + } + }, + "required": [ + "type" + ], + "additionalProperties": false + }, + "reasoningEffort": { + "type": "string", + "enum": [ + "low", + "medium", + "high", + "xhigh" + ] + }, + "textVerbosity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ] + }, + "providerOptions": { + "type": "object", + "additionalProperties": {} + } + }, + "additionalProperties": false + }, "athena": { "type": "object", "properties": { @@ -3344,6 +3517,11 @@ }, "name": { "type": "string" + }, + "temperature": { + "type": "number", + "minimum": 0, + "maximum": 2 } }, "required": [ diff --git a/src/agents/athena/types.ts b/src/agents/athena/types.ts index cb668c0c..eb88861e 100644 --- a/src/agents/athena/types.ts +++ b/src/agents/athena/types.ts @@ -2,6 +2,7 @@ export interface CouncilMemberConfig { model: string variant?: string name?: string + temperature?: number } export interface CouncilConfig { diff --git a/src/config/schema/athena.test.ts b/src/config/schema/athena.test.ts index 713c1504..f3bf6d8f 100644 --- a/src/config/schema/athena.test.ts +++ b/src/config/schema/athena.test.ts @@ -20,6 +20,7 @@ describe("CouncilMemberSchema", () => { model: "openai/gpt-5.3-codex", variant: "high", name: "analyst-a", + temperature: 0.3, } //#when @@ -110,11 +111,48 @@ describe("CouncilMemberSchema", () => { //#then expect(parsed.variant).toBeUndefined() expect(parsed.name).toBeUndefined() + expect(parsed.temperature).toBeUndefined() + }) + + test("accepts member config with temperature", () => { + //#given + const config = { model: "openai/gpt-5.3-codex", temperature: 0.5 } + + //#when + const result = CouncilMemberSchema.safeParse(config) + + //#then + expect(result.success).toBe(true) + if (result.success) { + expect(result.data.temperature).toBe(0.5) + } + }) + + test("rejects temperature below 0", () => { + //#given + const config = { model: "openai/gpt-5.3-codex", temperature: -0.1 } + + //#when + const result = CouncilMemberSchema.safeParse(config) + + //#then + expect(result.success).toBe(false) + }) + + test("rejects temperature above 2", () => { + //#given + const config = { model: "openai/gpt-5.3-codex", temperature: 2.1 } + + //#when + const result = CouncilMemberSchema.safeParse(config) + + //#then + expect(result.success).toBe(false) }) test("rejects member config with unknown fields", () => { //#given - const config = { model: "openai/gpt-5.3-codex", temperature: 0.2 } + const config = { model: "openai/gpt-5.3-codex", unknownField: true } //#when const result = CouncilMemberSchema.safeParse(config) diff --git a/src/config/schema/athena.ts b/src/config/schema/athena.ts index 2ac56af9..3972aaf0 100644 --- a/src/config/schema/athena.ts +++ b/src/config/schema/athena.ts @@ -14,6 +14,7 @@ export const CouncilMemberSchema = z.object({ model: ModelStringSchema, variant: z.string().optional(), name: z.string().optional(), + temperature: z.number().min(0).max(2).optional(), }).strict() export const CouncilConfigSchema = z.object({