feat(athena): use Question tool TUI for council member selection with dynamic member list

This commit is contained in:
ismeth
2026-02-13 10:52:57 +01:00
committed by YeonGyu-Kim
parent 922b66ec36
commit e0b6ad1a53
4 changed files with 37 additions and 19 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
export const ATHENA_COUNCIL_TOOL_DESCRIPTION = `Execute Athena's multi-model council. Sends the question to all configured council members in parallel and returns their collected responses.
export const ATHENA_COUNCIL_TOOL_DESCRIPTION_TEMPLATE = `Execute Athena's multi-model council. Sends the question to all configured council members in parallel and returns their collected responses.
Optionally pass a members array of member names or model IDs to consult only specific council members. If omitted, all configured members are consulted.
This tool reads council member configuration from the plugin config (agents.athena.council.members). Each member runs as an independent background agent with their configured model, variant, and temperature.
{members}
Returns council member responses with status, response text, and timing. Use this output for synthesis.
+4 -3
View File
@@ -2,7 +2,7 @@
import { describe, expect, test } from "bun:test"
import type { BackgroundManager } from "../../features/background-agent"
import { ATHENA_COUNCIL_TOOL_DESCRIPTION } from "./constants"
import { ATHENA_COUNCIL_TOOL_DESCRIPTION_TEMPLATE } from "./constants"
import { createAthenaCouncilTool, filterCouncilMembers } from "./tools"
const mockManager = {
@@ -127,8 +127,9 @@ describe("createAthenaCouncilTool", () => {
councilConfig: { members: [{ model: "openai/gpt-5.3-codex" }] },
})
// #then
expect(athenaCouncilTool.description).toBe(ATHENA_COUNCIL_TOOL_DESCRIPTION)
// #then - description should be dynamic and include the member model
expect(athenaCouncilTool.description).toContain("openai/gpt-5.3-codex")
expect(athenaCouncilTool.description).toContain("Available council members:")
expect((athenaCouncilTool as { args: Record<string, unknown> }).args.question).toBeDefined()
expect((athenaCouncilTool as { args: Record<string, unknown> }).args.members).toBeDefined()
})
+11 -2
View File
@@ -2,7 +2,7 @@ import { tool, type ToolDefinition } from "@opencode-ai/plugin"
import { executeCouncil } from "../../agents/athena/council-orchestrator"
import type { CouncilConfig, CouncilMemberConfig, CouncilMemberResponse } from "../../agents/athena/types"
import type { BackgroundManager, BackgroundTask, BackgroundTaskStatus } from "../../features/background-agent"
import { ATHENA_COUNCIL_TOOL_DESCRIPTION } from "./constants"
import { ATHENA_COUNCIL_TOOL_DESCRIPTION_TEMPLATE } from "./constants"
import { createCouncilLauncher } from "./council-launcher"
import type { AthenaCouncilToolArgs } from "./types"
@@ -152,14 +152,23 @@ export function filterCouncilMembers(
return { members: filteredMembers }
}
function buildToolDescription(councilConfig: CouncilConfig | undefined): string {
const memberList = councilConfig?.members.length
? councilConfig.members.map((m) => `- ${m.name ?? m.model}`).join("\n")
: "No members configured."
return ATHENA_COUNCIL_TOOL_DESCRIPTION_TEMPLATE.replace("{members}", `Available council members:\n${memberList}`)
}
export function createAthenaCouncilTool(args: {
backgroundManager: BackgroundManager
councilConfig: CouncilConfig | undefined
}): ToolDefinition {
const { backgroundManager, councilConfig } = args
const description = buildToolDescription(councilConfig)
return tool({
description: ATHENA_COUNCIL_TOOL_DESCRIPTION,
description,
args: {
question: tool.schema.string().describe("The question to send to all council members"),
members: tool.schema