delegate-task: block prometheus task delegation
This commit is contained in:
@@ -267,6 +267,23 @@ describe("applyToolConfig", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("#given prometheus agent permissions", () => {
|
||||||
|
describe("#when applying tool config", () => {
|
||||||
|
it("#then should deny task delegation tools for prometheus", () => {
|
||||||
|
const params = createParams({ agents: ["prometheus"] })
|
||||||
|
|
||||||
|
applyToolConfig(params)
|
||||||
|
|
||||||
|
const agent = params.agentResult.prometheus as {
|
||||||
|
permission: Record<string, unknown>
|
||||||
|
}
|
||||||
|
expect(agent.permission.task).toBe("deny")
|
||||||
|
expect(agent.permission["task_*"]).toBe("deny")
|
||||||
|
expect(agent.permission.teammate).toBe("deny")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("#given disabled_tools includes 'question'", () => {
|
describe("#given disabled_tools includes 'question'", () => {
|
||||||
let originalConfigContent: string | undefined
|
let originalConfigContent: string | undefined
|
||||||
let originalCliRunMode: string | undefined
|
let originalCliRunMode: string | undefined
|
||||||
|
|||||||
@@ -105,10 +105,10 @@ export function applyToolConfig(params: {
|
|||||||
prometheus.permission = {
|
prometheus.permission = {
|
||||||
...prometheus.permission,
|
...prometheus.permission,
|
||||||
call_omo_agent: "deny",
|
call_omo_agent: "deny",
|
||||||
task: "allow",
|
task: "deny",
|
||||||
question: questionPermission,
|
question: questionPermission,
|
||||||
"task_*": "allow",
|
"task_*": "deny",
|
||||||
teammate: "allow",
|
teammate: "deny",
|
||||||
...denyTodoTools,
|
...denyTodoTools,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -329,13 +329,13 @@ export function isPlanAgent(agentName: string | undefined): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plan family: plan + prometheus. Shares mutual delegation blocking and task tool permission.
|
* Plan family: plan + prometheus. Shares mutual delegation blocking only.
|
||||||
* Does NOT share system prompt (only isPlanAgent controls that).
|
* Does NOT share system prompt or task permission (only isPlanAgent controls those).
|
||||||
*/
|
*/
|
||||||
export const PLAN_FAMILY_NAMES = ["plan", "prometheus"]
|
export const PLAN_FAMILY_NAMES = ["plan", "prometheus"]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given agent belongs to the plan family (blocking + task permission).
|
* Check if the given agent belongs to the plan family for mutual delegation blocking.
|
||||||
*/
|
*/
|
||||||
export function isPlanFamily(category: string): boolean
|
export function isPlanFamily(category: string): boolean
|
||||||
export function isPlanFamily(category: string | undefined): boolean
|
export function isPlanFamily(category: string | undefined): boolean
|
||||||
|
|||||||
@@ -605,8 +605,8 @@ describe("executeSyncContinuation - toast cleanup error paths", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test("keeps plan-family task delegation available during sync continuation", async () => {
|
test("keeps task delegation disabled during prometheus sync continuation", async () => {
|
||||||
//#given - a resumed plan-family session should keep its intended task capability
|
//#given - a resumed prometheus session should stay unable to delegate tasks
|
||||||
const promptAsyncCalls: Array<{ path: { id: string }; body: Record<string, unknown> }> = []
|
const promptAsyncCalls: Array<{ path: { id: string }; body: Record<string, unknown> }> = []
|
||||||
const mockClient = {
|
const mockClient = {
|
||||||
session: {
|
session: {
|
||||||
@@ -656,7 +656,7 @@ describe("executeSyncContinuation - toast cleanup error paths", () => {
|
|||||||
const args = {
|
const args = {
|
||||||
session_id: "ses_test_12345678",
|
session_id: "ses_test_12345678",
|
||||||
prompt: "continue planning",
|
prompt: "continue planning",
|
||||||
description: "resume plan task",
|
description: "resume prometheus task",
|
||||||
load_skills: [],
|
load_skills: [],
|
||||||
run_in_background: false,
|
run_in_background: false,
|
||||||
}
|
}
|
||||||
@@ -667,7 +667,7 @@ describe("executeSyncContinuation - toast cleanup error paths", () => {
|
|||||||
//#then
|
//#then
|
||||||
expect(promptAsyncCalls).toHaveLength(1)
|
expect(promptAsyncCalls).toHaveLength(1)
|
||||||
expect(promptAsyncCalls[0]?.body.tools).toEqual({
|
expect(promptAsyncCalls[0]?.body.tools).toEqual({
|
||||||
task: true,
|
task: false,
|
||||||
call_omo_agent: true,
|
call_omo_agent: true,
|
||||||
question: false,
|
question: false,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { DelegateTaskArgs, ToolContextWithMetadata } from "./types"
|
import type { DelegateTaskArgs, ToolContextWithMetadata } from "./types"
|
||||||
import type { ExecutorContext, SessionMessage } from "./executor-types"
|
import type { ExecutorContext, SessionMessage } from "./executor-types"
|
||||||
import { isPlanFamily } from "./constants"
|
import { isPlanAgent } from "./constants"
|
||||||
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
||||||
import { resolveCallID } from "./resolve-call-id"
|
import { resolveCallID } from "./resolve-call-id"
|
||||||
import { getTaskToastManager } from "../../features/task-toast-manager"
|
import { getTaskToastManager } from "../../features/task-toast-manager"
|
||||||
@@ -84,7 +84,7 @@ export async function executeSyncContinuation(
|
|||||||
storeToolMetadata(ctx.sessionID, callID, syncContMeta)
|
storeToolMetadata(ctx.sessionID, callID, syncContMeta)
|
||||||
}
|
}
|
||||||
|
|
||||||
const allowTask = isPlanFamily(resumeAgent)
|
const allowTask = isPlanAgent(resumeAgent)
|
||||||
const tddEnabled = sisyphusAgentConfig?.tdd
|
const tddEnabled = sisyphusAgentConfig?.tdd
|
||||||
const effectivePrompt = buildTaskPrompt(args.prompt, resumeAgent, tddEnabled)
|
const effectivePrompt = buildTaskPrompt(args.prompt, resumeAgent, tddEnabled)
|
||||||
const tools = {
|
const tools = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { DelegateTaskArgs, OpencodeClient, DelegatedModelConfig } from "./types"
|
import type { DelegateTaskArgs, OpencodeClient, DelegatedModelConfig } from "./types"
|
||||||
import type { SisyphusAgentConfig } from "../../config/schema"
|
import type { SisyphusAgentConfig } from "../../config/schema"
|
||||||
import { isPlanFamily } from "./constants"
|
import { isPlanAgent } from "./constants"
|
||||||
import { buildTaskPrompt } from "./prompt-builder"
|
import { buildTaskPrompt } from "./prompt-builder"
|
||||||
import {
|
import {
|
||||||
promptSyncWithModelSuggestionRetry,
|
promptSyncWithModelSuggestionRetry,
|
||||||
@@ -64,7 +64,7 @@ export async function sendSyncPrompt(
|
|||||||
},
|
},
|
||||||
deps: SendSyncPromptDeps = sendSyncPromptDeps
|
deps: SendSyncPromptDeps = sendSyncPromptDeps
|
||||||
): Promise<string | null> {
|
): Promise<string | null> {
|
||||||
const allowTask = isPlanFamily(input.agentToUse)
|
const allowTask = isPlanAgent(input.agentToUse)
|
||||||
const tddEnabled = input.sisyphusAgentConfig?.tdd
|
const tddEnabled = input.sisyphusAgentConfig?.tdd
|
||||||
const effectivePrompt = buildTaskPrompt(input.args.prompt, input.agentToUse, tddEnabled)
|
const effectivePrompt = buildTaskPrompt(input.args.prompt, input.agentToUse, tddEnabled)
|
||||||
const tools = {
|
const tools = {
|
||||||
|
|||||||
@@ -4105,7 +4105,7 @@ describe("sisyphus-task", () => {
|
|||||||
expect(promptBody.tools.task).toBe(true)
|
expect(promptBody.tools.task).toBe(true)
|
||||||
}, { timeout: 20000 })
|
}, { timeout: 20000 })
|
||||||
|
|
||||||
test("prometheus subagent should have task permission (plan family)", async () => {
|
test("prometheus subagent should NOT have task permission", async () => {
|
||||||
//#given
|
//#given
|
||||||
const { createDelegateTask } = require("./tools")
|
const { createDelegateTask } = require("./tools")
|
||||||
let promptBody: any
|
let promptBody: any
|
||||||
@@ -4131,7 +4131,7 @@ describe("sisyphus-task", () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
//#then
|
//#then
|
||||||
expect(promptBody.tools.task).toBe(true)
|
expect(promptBody.tools.task).toBe(false)
|
||||||
}, { timeout: 20000 })
|
}, { timeout: 20000 })
|
||||||
|
|
||||||
test("non-plan subagent should NOT have task permission", async () => {
|
test("non-plan subagent should NOT have task permission", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user