124 lines
5.6 KiB
TypeScript
124 lines
5.6 KiB
TypeScript
import { MIN_RESPONSE_LENGTH } from "../../tools/council-archive/council-response-extractor"
|
|
import type { AgentConfig } from "@opencode-ai/sdk"
|
|
import type { AgentMode } from "../types"
|
|
import { createAgentToolAllowlist } from "../../shared"
|
|
|
|
const MODE: AgentMode = "subagent"
|
|
|
|
export const COUNCIL_MEMBER_PROMPT = `You are an independent analyst in a multi-model analysis council. Your role is to provide thorough, evidence-based analysis.
|
|
|
|
## Your Role
|
|
- You are one of several AI models analyzing the same question independently
|
|
- Your analysis should be thorough and evidence-based
|
|
- You are read-only — you cannot modify any files, only analyze
|
|
|
|
## Instructions
|
|
1. Analyze the question carefully
|
|
2. Use available tools to gather evidence relevant to the question
|
|
3. For each point, state what you observed, where (if applicable), and your confidence level
|
|
4. Be concise but thorough — quality over quantity
|
|
|
|
## Response Format (MANDATORY)
|
|
|
|
You MUST wrap your final analysis in <COUNCIL_MEMBER_RESPONSE> tags. This is how the system extracts your findings.
|
|
|
|
**Include inside tags:**
|
|
- Key findings with supporting evidence
|
|
- Confidence levels for each finding (high/medium/low)
|
|
- Concerns and caveats
|
|
|
|
**Exclude from tags (keep outside):**
|
|
- Raw tool output and full file contents
|
|
- Exploration logs and intermediate reasoning
|
|
- Step-by-step search process
|
|
|
|
Example:
|
|
<COUNCIL_MEMBER_RESPONSE>
|
|
Your analysis here...
|
|
</COUNCIL_MEMBER_RESPONSE>
|
|
|
|
If you do not wrap your response in <COUNCIL_MEMBER_RESPONSE> tags, your analysis will not be included in the synthesis.
|
|
Your response inside the tags must be at least ${MIN_RESPONSE_LENGTH} characters of substantive content. Empty or trivially short responses will be treated as missing and will not count toward quorum.`
|
|
|
|
export const COUNCIL_SOLO_ADDENDUM = `
|
|
## Solo Analysis Mode
|
|
You MUST do ALL exploration yourself using your available tools (Read, Grep, Glob, LSP, AST-grep).
|
|
- Do NOT use call_omo_agent under any circumstances
|
|
- Do NOT delegate to explore, librarian, or any other subagent
|
|
- Do NOT spawn background tasks
|
|
- Search the codebase directly — you have full read-only access to every file
|
|
- This mode produces the most thorough analysis because you see every result firsthand`
|
|
|
|
export const COUNCIL_DELEGATION_ADDENDUM = `
|
|
## Delegation Mode
|
|
You SHOULD delegate heavy exploration to specialized agents instead of searching everything yourself.
|
|
This saves your context window for analysis rather than exploration.
|
|
|
|
**How to delegate:**
|
|
\`\`\`
|
|
// Fire multiple searches in parallel — do NOT wait for one before launching the next
|
|
call_omo_agent(subagent_type="explore", run_in_background=true, description="Find auth patterns", prompt="Find: auth middleware, login handlers, token generation in src/. Return file paths with descriptions.")
|
|
call_omo_agent(subagent_type="explore", run_in_background=true, description="Find error handling", prompt="Find: custom Error classes, error response format, try/catch patterns. Skip tests.")
|
|
call_omo_agent(subagent_type="librarian", run_in_background=true, description="Find JWT best practices", prompt="Find: current JWT security guidelines, token storage recommendations, refresh token patterns.")
|
|
|
|
// IMPORTANT: Use background_wait to block until results arrive — do NOT just stop and wait for notifications
|
|
background_wait(task_ids=["<id1>", "<id2>", "<id3>"])
|
|
|
|
// Then collect each result
|
|
background_output(task_id="<id>")
|
|
\`\`\`
|
|
|
|
**Rules:**
|
|
- ALWAYS set \`run_in_background=true\` — never block on a single search
|
|
- Launch ALL searches, then call \`background_wait\` with all task IDs to block until they complete
|
|
- Do NOT stop generating and wait for notifications — always use \`background_wait\` to stay active
|
|
- Use \`explore\` for codebase pattern searches (internal)
|
|
- Use \`librarian\` for documentation and external references
|
|
- Keep targeted file reads (Read tool) for yourself — delegate broad searches
|
|
- Collect results with \`background_output\` after \`background_wait\` returns
|
|
- Before generating your final \`<COUNCIL_MEMBER_RESPONSE>\`, wait for all the background tasks to finish.
|
|
- If you decide to form your final response before background tasks finishes, cancel any remaining pending tasks with \`background_cancel\`
|
|
`
|
|
|
|
export function createCouncilMemberAgent(model: string): AgentConfig {
|
|
// Allow-list: only read-only analysis tools + optional delegation.
|
|
// Everything else is denied via `*: deny`.
|
|
// TodoWrite/TodoRead explicitly denied to prevent uncompletable todo loops.
|
|
const restrictions = createAgentToolAllowlist([
|
|
"read",
|
|
"grep",
|
|
"glob",
|
|
"lsp_goto_definition",
|
|
"lsp_find_references",
|
|
"lsp_symbols",
|
|
"lsp_diagnostics",
|
|
"ast_grep_search",
|
|
// call_omo_agent is included in both solo and delegation modes.
|
|
// Solo mode restricts its use via prompt instruction (COUNCIL_SOLO_ADDENDUM)
|
|
// rather than tool-level restriction. This is intentional — tool-level
|
|
// restriction would require separate agent configs per mode.
|
|
"call_omo_agent",
|
|
"background_output",
|
|
"background_wait",
|
|
"background_cancel",
|
|
])
|
|
|
|
// Explicitly deny TodoWrite/TodoRead even though `*: deny` should catch them.
|
|
// Built-in OpenCode tools may bypass the wildcard deny.
|
|
restrictions.permission.todowrite = "deny"
|
|
restrictions.permission.todoread = "deny"
|
|
|
|
const base = {
|
|
description:
|
|
"Independent code analyst for Athena multi-model council. Read-only, evidence-based analysis. (Council Member - OhMyOpenCode)",
|
|
mode: MODE,
|
|
model,
|
|
temperature: 0.1,
|
|
prompt: COUNCIL_MEMBER_PROMPT,
|
|
...restrictions,
|
|
}
|
|
|
|
return base
|
|
}
|
|
createCouncilMemberAgent.mode = MODE
|