fix: sync council-member tool restrictions across all layers, optimize athena guards
- Add switch_agent/background_wait to agent-tool-restrictions.ts (boolean format) - Add dynamic council member name matching via COUNCIL_MEMBER_KEY_PREFIX - Move athena question permission from hardcoded to tool-config-handler (CLI-mode aware) - Rename appendMissingCouncilPrompt -> applyMissingCouncilGuard - Optimize tool-execute-before: check hasPendingCouncilMembers before resolving session agent - Add fallback_models to council-member/athena in schema.json - Remove unused createAthenaAgent export from agents/index.ts - Add cross-reference comments for restriction sync points
This commit is contained in:
@@ -15,12 +15,28 @@ describe("agent-tool-restrictions", () => {
|
||||
expect(restrictions.call_omo_agent).toBe(false)
|
||||
})
|
||||
|
||||
test("council-member restrictions include call_omo_agent", () => {
|
||||
test("council-member restrictions include all denied tools", () => {
|
||||
//#given
|
||||
//#when
|
||||
const restrictions = getAgentToolRestrictions("council-member")
|
||||
//#then
|
||||
expect(restrictions.call_omo_agent).toBe(false)
|
||||
expect(restrictions.switch_agent).toBe(false)
|
||||
expect(restrictions.background_wait).toBe(false)
|
||||
})
|
||||
|
||||
test("#given dynamic council member name #when getAgentToolRestrictions #then returns council-member restrictions", () => {
|
||||
//#given
|
||||
const dynamicName = "Council: Claude Opus 4.6"
|
||||
//#when
|
||||
const restrictions = getAgentToolRestrictions(dynamicName)
|
||||
//#then
|
||||
expect(restrictions.write).toBe(false)
|
||||
expect(restrictions.edit).toBe(false)
|
||||
expect(restrictions.task).toBe(false)
|
||||
expect(restrictions.call_omo_agent).toBe(false)
|
||||
expect(restrictions.switch_agent).toBe(false)
|
||||
expect(restrictions.background_wait).toBe(false)
|
||||
})
|
||||
|
||||
test("hasAgentToolRestrictions returns true for athena", () => {
|
||||
|
||||
@@ -6,6 +6,8 @@ import { stripInvisibleAgentCharacters } from "./agent-display-names"
|
||||
* true = tool allowed, false = tool denied.
|
||||
*/
|
||||
|
||||
import { COUNCIL_MEMBER_KEY_PREFIX } from "../agents/builtin-agents/council-member-agents"
|
||||
|
||||
const EXPLORATION_AGENT_DENYLIST: Record<string, boolean> = {
|
||||
write: false,
|
||||
edit: false,
|
||||
@@ -51,11 +53,18 @@ const AGENT_RESTRICTIONS: Record<string, Record<string, boolean>> = {
|
||||
call_omo_agent: false,
|
||||
},
|
||||
|
||||
// NOTE: Athena/council tool restrictions are also defined in:
|
||||
// - src/agents/athena/agent.ts (AgentConfig permission format)
|
||||
// - src/agents/athena/council-member-agent.ts (AgentConfig permission format)
|
||||
// - src/plugin-handlers/tool-config-handler.ts (allow/deny string format)
|
||||
// Keep all three in sync when modifying.
|
||||
"council-member": {
|
||||
write: false,
|
||||
edit: false,
|
||||
task: false,
|
||||
call_omo_agent: false,
|
||||
switch_agent: false,
|
||||
background_wait: false,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -63,6 +72,10 @@ export function getAgentToolRestrictions(agentName: string): Record<string, bool
|
||||
// Custom/unknown agents get no restrictions (empty object), matching Claude Code's
|
||||
// trust model where project-registered agents retain full tool access including bash.
|
||||
const stripped = stripInvisibleAgentCharacters(agentName)
|
||||
if (stripped.startsWith(COUNCIL_MEMBER_KEY_PREFIX)) {
|
||||
return AGENT_RESTRICTIONS["council-member"] ?? {}
|
||||
}
|
||||
|
||||
return AGENT_RESTRICTIONS[stripped]
|
||||
?? Object.entries(AGENT_RESTRICTIONS).find(([key]) => key.toLowerCase() === stripped.toLowerCase())?.[1]
|
||||
?? {}
|
||||
|
||||
Reference in New Issue
Block a user