fix(athena): remove dead temperature/permission fields from council launch pipeline

LaunchInput.temperature and LaunchInput.permission were accepted and
passed through the council orchestrator but never forwarded to the
actual promptAsync API call (SDK doesn't support per-request temperature
or permission). Remove the dead fields, the unused AthenaConfig
interface, and update tests/docs/schema accordingly.
This commit is contained in:
ismeth 2026-02-14 15:38:34 +01:00 committed by YeonGyu-Kim
parent 189bf89dc6
commit 13692c63d1
9 changed files with 17 additions and 95 deletions

View File

@ -3338,11 +3338,6 @@
"type": "string", "type": "string",
"minLength": 1 "minLength": 1
}, },
"temperature": {
"type": "number",
"minimum": 0,
"maximum": 2
},
"variant": { "variant": {
"type": "string" "type": "string"
}, },

View File

@ -11,8 +11,6 @@ interface MockLaunchInput {
parentMessageID: string parentMessageID: string
parentAgent?: string parentAgent?: string
model?: { providerID: string; modelID: string; variant?: string } model?: { providerID: string; modelID: string; variant?: string }
temperature?: number
permission?: Record<string, "ask" | "allow" | "deny">
} }
function createMockTask(id: string, launch: MockLaunchInput) { function createMockTask(id: string, launch: MockLaunchInput) {
@ -68,7 +66,6 @@ describe("executeCouncil", () => {
for (const launch of launches) { for (const launch of launches) {
expect(launch.prompt).toBe(expectedPrompt) expect(launch.prompt).toBe(expectedPrompt)
expect(launch.agent).toBe("athena") expect(launch.agent).toBe("athena")
expect(launch.permission).toEqual({ write: "deny", edit: "deny", task: "deny", athena_council: "deny" })
} }
expect(launches[0]?.model).toEqual({ providerID: "openai", modelID: "gpt-5.3-codex" }) expect(launches[0]?.model).toEqual({ providerID: "openai", modelID: "gpt-5.3-codex" })
@ -170,10 +167,10 @@ describe("executeCouncil", () => {
expect(result.failures.find((f) => f.member.model === "invalid-model")?.error).toContain("Launch failed") expect(result.failures.find((f) => f.member.model === "invalid-model")?.error).toContain("Launch failed")
}) })
//#given members with per-member temperature and variant //#given members with per-member variant
//#when executeCouncil is called //#when executeCouncil is called
//#then launch receives those values for each corresponding member //#then launch receives variant in model for each corresponding member
test("passes member temperature and variant to launch input", async () => { test("passes member variant to launch input model", async () => {
const launches: MockLaunchInput[] = [] const launches: MockLaunchInput[] = []
const launcher = { const launcher = {
launch: async (input: MockLaunchInput) => { launch: async (input: MockLaunchInput) => {
@ -186,8 +183,8 @@ describe("executeCouncil", () => {
question: "Compare architecture options", question: "Compare architecture options",
council: { council: {
members: [ members: [
{ model: "openai/gpt-5.3-codex", temperature: 0.1, variant: "high" }, { model: "openai/gpt-5.3-codex", variant: "high" },
{ model: "anthropic/claude-sonnet-4-5", temperature: 0.3 }, { model: "anthropic/claude-sonnet-4-5" },
], ],
}, },
launcher, launcher,
@ -196,9 +193,7 @@ describe("executeCouncil", () => {
}) })
expect(launches).toHaveLength(2) expect(launches).toHaveLength(2)
expect(launches[0]?.temperature).toBe(0.1)
expect(launches[0]?.model?.variant).toBe("high") expect(launches[0]?.model?.variant).toBe("high")
expect(launches[1]?.temperature).toBe(0.3)
expect(launches[1]?.model?.variant).toBeUndefined() expect(launches[1]?.model?.variant).toBeUndefined()
}) })

View File

@ -1,5 +1,4 @@
import type { LaunchInput, BackgroundTask } from "../../features/background-agent/types" import type { LaunchInput, BackgroundTask } from "../../features/background-agent/types"
import { createAgentToolRestrictions } from "../../shared/permission-compat"
import { buildCouncilPrompt } from "./council-prompt" import { buildCouncilPrompt } from "./council-prompt"
import { parseModelString } from "./model-parser" import { parseModelString } from "./model-parser"
import type { CouncilConfig, CouncilLaunchFailure, CouncilLaunchedMember, CouncilLaunchResult, CouncilMemberConfig } from "./types" import type { CouncilConfig, CouncilLaunchFailure, CouncilLaunchedMember, CouncilLaunchResult, CouncilMemberConfig } from "./types"
@ -72,7 +71,6 @@ async function launchMember(
throw new Error(`Invalid model string: "${member.model}"`) throw new Error(`Invalid model string: "${member.model}"`)
} }
const restrictions = createAgentToolRestrictions(["write", "edit", "task", "athena_council"])
const memberName = member.name ?? member.model const memberName = member.name ?? member.model
return launcher.launch({ return launcher.launch({
description: `Council member: ${memberName}`, description: `Council member: ${memberName}`,
@ -86,7 +84,5 @@ async function launchMember(
modelID: parsedModel.modelID, modelID: parsedModel.modelID,
...(member.variant ? { variant: member.variant } : {}), ...(member.variant ? { variant: member.variant } : {}),
}, },
...(member.temperature !== undefined ? { temperature: member.temperature } : {}),
permission: restrictions.permission,
}) })
} }

View File

@ -1,6 +1,5 @@
export interface CouncilMemberConfig { export interface CouncilMemberConfig {
model: string model: string
temperature?: number
variant?: string variant?: string
name?: string name?: string
} }
@ -9,11 +8,6 @@ export interface CouncilConfig {
members: CouncilMemberConfig[] members: CouncilMemberConfig[]
} }
export interface AthenaConfig {
model?: string
council: CouncilConfig
}
export interface CouncilLaunchFailure { export interface CouncilLaunchFailure {
member: CouncilMemberConfig member: CouncilMemberConfig
error: string error: string

View File

@ -18,7 +18,6 @@ describe("CouncilMemberSchema", () => {
//#given //#given
const config = { const config = {
model: "openai/gpt-5.3-codex", model: "openai/gpt-5.3-codex",
temperature: 0.4,
variant: "high", variant: "high",
name: "analyst-a", name: "analyst-a",
} }
@ -32,7 +31,7 @@ describe("CouncilMemberSchema", () => {
test("rejects member config missing model", () => { test("rejects member config missing model", () => {
//#given //#given
const config = { temperature: 0.5 } const config = { name: "no-model" }
//#when //#when
const result = CouncilMemberSchema.safeParse(config) const result = CouncilMemberSchema.safeParse(config)
@ -85,34 +84,11 @@ describe("CouncilMemberSchema", () => {
expect(result.success).toBe(false) expect(result.success).toBe(false)
}) })
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("z.infer produces expected type shape", () => { test("z.infer produces expected type shape", () => {
//#given //#given
type InferredCouncilMember = z.infer<typeof CouncilMemberSchema> type InferredCouncilMember = z.infer<typeof CouncilMemberSchema>
const member: InferredCouncilMember = { const member: InferredCouncilMember = {
model: "anthropic/claude-opus-4-6", model: "anthropic/claude-opus-4-6",
temperature: 0.1,
variant: "medium", variant: "medium",
name: "oracle", name: "oracle",
} }
@ -132,7 +108,6 @@ describe("CouncilMemberSchema", () => {
const parsed = CouncilMemberSchema.parse(config) const parsed = CouncilMemberSchema.parse(config)
//#then //#then
expect(parsed.temperature).toBeUndefined()
expect(parsed.variant).toBeUndefined() expect(parsed.variant).toBeUndefined()
expect(parsed.name).toBeUndefined() expect(parsed.name).toBeUndefined()
}) })
@ -156,9 +131,9 @@ describe("CouncilConfigSchema", () => {
//#given //#given
const config = { const config = {
members: [ members: [
{ model: "anthropic/claude-opus-4-6", name: "a", temperature: 0.1 }, { model: "anthropic/claude-opus-4-6", name: "a" },
{ model: "openai/gpt-5.3-codex", name: "b", variant: "high" }, { model: "openai/gpt-5.3-codex", name: "b", variant: "high" },
{ model: "xai/grok-code-fast-1", name: "c", temperature: 1.2, variant: "low" }, { model: "xai/grok-code-fast-1", name: "c", variant: "low" },
], ],
} }

View File

@ -14,7 +14,6 @@ const ModelStringSchema = z
export const CouncilMemberSchema = z.object({ export const CouncilMemberSchema = z.object({
model: ModelStringSchema, model: ModelStringSchema,
temperature: z.number().min(0).max(2).optional(),
variant: z.string().optional(), variant: z.string().optional(),
name: z.string().optional(), name: z.string().optional(),
}) })

View File

@ -72,10 +72,6 @@ export interface LaunchInput {
skills?: string[] skills?: string[]
skillContent?: string skillContent?: string
category?: string category?: string
/** Per-task temperature override for council members or custom launches */
temperature?: number
/** Tool permission overrides (e.g., { write: "deny", edit: "deny" }) */
permission?: Record<string, "ask" | "allow" | "deny">
} }
export interface ResumeInput { export interface ResumeInput {

View File

@ -16,10 +16,10 @@ function createMockTask(id: string): BackgroundTask {
} }
describe("createCouncilLauncher", () => { describe("createCouncilLauncher", () => {
//#given a council launch input with temperature and permission //#given a council launch input with all fields
//#when launch is called //#when launch is called
//#then temperature and permission are forwarded to the background manager //#then all fields are forwarded to the background manager
test("forwards temperature and permission to background manager", async () => { test("forwards all launch input fields to background manager", async () => {
const capturedInputs: LaunchInput[] = [] const capturedInputs: LaunchInput[] = []
const mockManager = { const mockManager = {
launch: async (input: LaunchInput) => { launch: async (input: LaunchInput) => {
@ -38,40 +38,14 @@ describe("createCouncilLauncher", () => {
parentSessionID: "session-1", parentSessionID: "session-1",
parentMessageID: "message-1", parentMessageID: "message-1",
model: { providerID: "openai", modelID: "gpt-5.3-codex" }, model: { providerID: "openai", modelID: "gpt-5.3-codex" },
temperature: 0.3,
permission: { write: "deny", edit: "deny", task: "deny" },
}) })
expect(capturedInputs).toHaveLength(1) expect(capturedInputs).toHaveLength(1)
expect(capturedInputs[0]?.temperature).toBe(0.3) expect(capturedInputs[0]?.description).toBe("Council member: test")
expect(capturedInputs[0]?.permission).toEqual({ write: "deny", edit: "deny", task: "deny" }) expect(capturedInputs[0]?.prompt).toBe("Analyze this")
}) expect(capturedInputs[0]?.agent).toBe("athena")
expect(capturedInputs[0]?.parentSessionID).toBe("session-1")
//#given a council launch input without temperature and permission expect(capturedInputs[0]?.parentMessageID).toBe("message-1")
//#when launch is called expect(capturedInputs[0]?.model).toEqual({ providerID: "openai", modelID: "gpt-5.3-codex" })
//#then undefined temperature and permission are forwarded (not dropped)
test("forwards undefined temperature and permission without error", async () => {
const capturedInputs: LaunchInput[] = []
const mockManager = {
launch: async (input: LaunchInput) => {
capturedInputs.push(input)
return createMockTask("bg-2")
},
getTask: () => undefined,
} as unknown as BackgroundManager
const launcher = createCouncilLauncher(mockManager)
await launcher.launch({
description: "Council member: test",
prompt: "Analyze this",
agent: "athena",
parentSessionID: "session-1",
parentMessageID: "message-1",
})
expect(capturedInputs).toHaveLength(1)
expect(capturedInputs[0]?.temperature).toBeUndefined()
expect(capturedInputs[0]?.permission).toBeUndefined()
}) })
}) })

View File

@ -12,8 +12,6 @@ export function createCouncilLauncher(manager: BackgroundManager): CouncilLaunch
parentMessageID: input.parentMessageID, parentMessageID: input.parentMessageID,
parentAgent: input.parentAgent, parentAgent: input.parentAgent,
model: input.model, model: input.model,
temperature: input.temperature,
permission: input.permission,
}) })
}, },
} }