fix(athena): remove duplicate council prompt, add temp file cleanup, fix code quality

- Remove COUNCIL_MEMBER_PROMPT from temp file content since it's already
  provided as the council member's system prompt via agent config, saving
  ~350+ tokens per council member per invocation
- Add startup cleanup for stale athena-council-*.md files older than 30
  minutes in .sisyphus/tmp/ to handle cases where process exits before
  setTimeout cleanup fires
- Remove redundant intermediate permission object spread in createAthenaAgent
- Fix test style: it() -> test(), add #given/#then prefixes per conventions
This commit is contained in:
ismeth
2026-02-24 15:12:05 +01:00
committed by YeonGyu-Kim
parent 5cbf08eabc
commit b8f3e5434f
3 changed files with 49 additions and 24 deletions
+1 -4
View File
@@ -236,9 +236,6 @@ export function createAthenaAgent(model: string): AgentConfig {
const restrictions = createAgentToolRestrictions(["write", "edit", "call_omo_agent"])
// question permission is set by tool-config-handler.ts based on CLI mode (allow/deny)
const permission = {
...restrictions.permission,
}
const base = {
description:
@@ -246,7 +243,7 @@ export function createAthenaAgent(model: string): AgentConfig {
mode: MODE,
model,
temperature: 0.1,
permission,
permission: restrictions.permission,
prompt: ATHENA_SYSTEM_PROMPT,
color: "#1F8EFA",
}
+16 -16
View File
@@ -1,4 +1,4 @@
import { describe, expect, it } from "bun:test"
import { describe, expect, test } from "bun:test"
import type { AgentConfig } from "@opencode-ai/sdk"
import { applyModelThinkingConfig } from "./model-thinking-config"
@@ -10,20 +10,20 @@ const BASE_CONFIG: AgentConfig = {
}
describe("applyModelThinkingConfig", () => {
describe("given a GPT model", () => {
it("returns reasoningEffort medium", () => {
describe("#given a GPT model", () => {
test("#then returns reasoningEffort medium", () => {
const result = applyModelThinkingConfig(BASE_CONFIG, "gpt-5.2")
expect(result).toEqual({ ...BASE_CONFIG, reasoningEffort: "medium" })
})
it("returns reasoningEffort medium for openai-prefixed model", () => {
test("#then returns reasoningEffort medium for openai-prefixed model", () => {
const result = applyModelThinkingConfig(BASE_CONFIG, "openai/gpt-5.2")
expect(result).toEqual({ ...BASE_CONFIG, reasoningEffort: "medium" })
})
})
describe("given an Anthropic model", () => {
it("returns thinking config with budgetTokens 32000", () => {
describe("#given an Anthropic model", () => {
test("#then returns thinking config with budgetTokens 32000", () => {
const result = applyModelThinkingConfig(BASE_CONFIG, "anthropic/claude-opus-4-6")
expect(result).toEqual({
...BASE_CONFIG,
@@ -32,29 +32,29 @@ describe("applyModelThinkingConfig", () => {
})
})
describe("given a Google model", () => {
it("returns base config unchanged", () => {
describe("#given a Google model", () => {
test("#then returns base config unchanged", () => {
const result = applyModelThinkingConfig(BASE_CONFIG, "google/gemini-3-pro")
expect(result).toBe(BASE_CONFIG)
})
})
describe("given a Kimi model", () => {
it("returns base config unchanged", () => {
describe("#given a Kimi model", () => {
test("#then returns base config unchanged", () => {
const result = applyModelThinkingConfig(BASE_CONFIG, "kimi/kimi-k2.5")
expect(result).toBe(BASE_CONFIG)
})
})
describe("given a model with no provider prefix", () => {
it("returns base config unchanged for non-GPT model", () => {
describe("#given a model with no provider prefix", () => {
test("#then returns base config unchanged for non-GPT model", () => {
const result = applyModelThinkingConfig(BASE_CONFIG, "gemini-3-pro")
expect(result).toBe(BASE_CONFIG)
})
})
describe("given a Claude model through a non-Anthropic provider", () => {
it("returns thinking config for github-copilot/claude-opus-4-6", () => {
describe("#given a Claude model through a non-Anthropic provider", () => {
test("#then returns thinking config for github-copilot/claude-opus-4-6", () => {
const result = applyModelThinkingConfig(BASE_CONFIG, "github-copilot/claude-opus-4-6")
expect(result).toEqual({
...BASE_CONFIG,
@@ -62,7 +62,7 @@ describe("applyModelThinkingConfig", () => {
})
})
it("returns thinking config for opencode/claude-opus-4-6", () => {
test("#then returns thinking config for opencode/claude-opus-4-6", () => {
const result = applyModelThinkingConfig(BASE_CONFIG, "opencode/claude-opus-4-6")
expect(result).toEqual({
...BASE_CONFIG,
@@ -70,7 +70,7 @@ describe("applyModelThinkingConfig", () => {
})
})
it("returns thinking config for opencode/claude-sonnet-4-6", () => {
test("#then returns thinking config for opencode/claude-sonnet-4-6", () => {
const result = applyModelThinkingConfig(BASE_CONFIG, "opencode/claude-sonnet-4-6")
expect(result).toEqual({
...BASE_CONFIG,
+32 -4
View File
@@ -1,13 +1,38 @@
import { tool, type ToolDefinition } from "@opencode-ai/plugin"
import { randomUUID } from "node:crypto"
import { writeFile, unlink, mkdir } from "node:fs/promises"
import { writeFile, unlink, mkdir, readdir, stat } from "node:fs/promises"
import { join } from "node:path"
import { log } from "../../shared/logger"
import { COUNCIL_MEMBER_PROMPT, COUNCIL_SOLO_ADDENDUM, COUNCIL_DELEGATION_ADDENDUM } from "../../agents/athena"
import { COUNCIL_SOLO_ADDENDUM, COUNCIL_DELEGATION_ADDENDUM } from "../../agents/athena"
const CLEANUP_DELAY_MS = 30 * 60 * 1000
const COUNCIL_TMP_DIR = ".sisyphus/tmp"
const COUNCIL_FILE_PREFIX = "athena-council-"
async function cleanupStaleTempFiles(directory: string): Promise<void> {
const tmpDir = join(directory, COUNCIL_TMP_DIR)
try {
const files = await readdir(tmpDir)
const now = Date.now()
for (const file of files) {
if (!file.startsWith(COUNCIL_FILE_PREFIX) || !file.endsWith(".md")) continue
const filePath = join(tmpDir, file)
try {
const fileStat = await stat(filePath)
if (now - fileStat.mtimeMs > CLEANUP_DELAY_MS) {
await unlink(filePath)
log("[prepare-council-prompt] Cleaned up stale temp file", { filePath })
}
} catch {
// File may have been deleted between readdir and stat
}
}
} catch {
// Directory may not exist yet — nothing to clean
}
}
export function createPrepareCouncilPromptTool(directory: string): ToolDefinition {
const description = `Save a council analysis prompt to a temp file so council members can read it.
@@ -21,6 +46,10 @@ The "mode" parameter controls whether council members can delegate exploration t
Returns the file path to reference in subsequent task() calls.`
cleanupStaleTempFiles(directory).catch((err) => {
log("[prepare-council-prompt] Startup cleanup failed", { error: String(err) })
})
return tool({
description,
args: {
@@ -40,8 +69,7 @@ Returns the file path to reference in subsequent task() calls.`
const filePath = join(tmpDir, filename)
const modeAddendum = mode === "delegation" ? COUNCIL_DELEGATION_ADDENDUM : COUNCIL_SOLO_ADDENDUM
const content = `${COUNCIL_MEMBER_PROMPT}
${modeAddendum}
const content = `${modeAddendum}
## Analysis Question