fix(session): avoid sticky prompt tool overrides (#31394)
This commit is contained in:
parent
b34d9242d1
commit
f43209bb8c
4 changed files with 58 additions and 27 deletions
|
|
@ -1198,11 +1198,8 @@ export const layer = Layer.effect(
|
||||||
permissions.push({ permission: t, action: enabled ? "allow" : "deny", pattern: "*" })
|
permissions.push({ permission: t, action: enabled ? "allow" : "deny", pattern: "*" })
|
||||||
}
|
}
|
||||||
if (permissions.length > 0) {
|
if (permissions.length > 0) {
|
||||||
// Merge so per-call tool rules don't clobber inherited session rules
|
session.permission = permissions
|
||||||
// (e.g. external_directory allows from the parent session).
|
yield* sessions.setPermission({ sessionID: session.id, permission: permissions })
|
||||||
const merged = Permission.merge(session.permission ?? [], permissions)
|
|
||||||
session.permission = merged
|
|
||||||
yield* sessions.setPermission({ sessionID: session.id, permission: merged })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.noReply === true) return message
|
if (input.noReply === true) return message
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,24 @@ export const TaskTool = Tool.define(
|
||||||
const parentAgent = parent.agent
|
const parentAgent = parent.agent
|
||||||
? yield* agent.get(parent.agent).pipe(Effect.catchCause(() => Effect.succeed(undefined)))
|
? yield* agent.get(parent.agent).pipe(Effect.catchCause(() => Effect.succeed(undefined)))
|
||||||
: undefined
|
: undefined
|
||||||
|
const childPermission = deriveSubagentSessionPermission({
|
||||||
|
parentSessionPermission: parent.permission ?? [],
|
||||||
|
parentAgent,
|
||||||
|
subagent: next,
|
||||||
|
})
|
||||||
|
const childToolDenies = [
|
||||||
|
...(next.permission.some((rule) => rule.permission === "todowrite")
|
||||||
|
? []
|
||||||
|
: [{ permission: "todowrite" as const, pattern: "*" as const, action: "deny" as const }]),
|
||||||
|
...(next.permission.some((rule) => rule.permission === id)
|
||||||
|
? []
|
||||||
|
: [{ permission: id, pattern: "*" as const, action: "deny" as const }]),
|
||||||
|
...(cfg.experimental?.primary_tools?.map((permission) => ({
|
||||||
|
permission,
|
||||||
|
pattern: "*" as const,
|
||||||
|
action: "deny" as const,
|
||||||
|
})) ?? []),
|
||||||
|
]
|
||||||
const nextSession =
|
const nextSession =
|
||||||
session ??
|
session ??
|
||||||
(yield* sessions.create({
|
(yield* sessions.create({
|
||||||
|
|
@ -132,16 +150,14 @@ export const TaskTool = Tool.define(
|
||||||
title: params.description + ` (@${next.name} subagent)`,
|
title: params.description + ` (@${next.name} subagent)`,
|
||||||
agent: next.name,
|
agent: next.name,
|
||||||
permission: [
|
permission: [
|
||||||
...deriveSubagentSessionPermission({
|
...childPermission,
|
||||||
parentSessionPermission: parent.permission ?? [],
|
...childToolDenies.filter(
|
||||||
parentAgent,
|
(deny) =>
|
||||||
subagent: next,
|
!childPermission.some(
|
||||||
}),
|
(rule) =>
|
||||||
...(cfg.experimental?.primary_tools?.map((item) => ({
|
rule.permission === deny.permission && rule.pattern === deny.pattern && rule.action === deny.action,
|
||||||
pattern: "*",
|
),
|
||||||
action: "allow" as const,
|
),
|
||||||
permission: item,
|
|
||||||
})) ?? []),
|
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
@ -182,11 +198,6 @@ export const TaskTool = Tool.define(
|
||||||
},
|
},
|
||||||
variant: next.model ? undefined : variant,
|
variant: next.model ? undefined : variant,
|
||||||
agent: next.name,
|
agent: next.name,
|
||||||
tools: {
|
|
||||||
...(next.permission.some((rule) => rule.permission === "todowrite") ? {} : { todowrite: false }),
|
|
||||||
...(next.permission.some((rule) => rule.permission === id) ? {} : { task: false }),
|
|
||||||
...Object.fromEntries((cfg.experimental?.primary_tools ?? []).map((item) => [item, false])),
|
|
||||||
},
|
|
||||||
parts,
|
parts,
|
||||||
})
|
})
|
||||||
return result.parts.findLast((item) => item.type === "text")?.text ?? ""
|
return result.parts.findLast((item) => item.type === "text")?.text ?? ""
|
||||||
|
|
|
||||||
|
|
@ -824,6 +824,33 @@ it.instance("subtask child inherits parent session external_directory allow", ()
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
noLLMServer.instance("prompt tools replace previous prompt tool rules", () =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const prompt = yield* SessionPrompt.Service
|
||||||
|
const sessions = yield* Session.Service
|
||||||
|
const session = yield* sessions.create({ title: "Prompt tools" })
|
||||||
|
|
||||||
|
yield* prompt.prompt({
|
||||||
|
sessionID: session.id,
|
||||||
|
agent: "build",
|
||||||
|
noReply: true,
|
||||||
|
tools: { bash: false },
|
||||||
|
parts: [{ type: "text", text: "first" }],
|
||||||
|
})
|
||||||
|
yield* prompt.prompt({
|
||||||
|
sessionID: session.id,
|
||||||
|
agent: "build",
|
||||||
|
noReply: true,
|
||||||
|
tools: { read: true },
|
||||||
|
parts: [{ type: "text", text: "second" }],
|
||||||
|
})
|
||||||
|
|
||||||
|
const reloaded = yield* sessions.get(session.id)
|
||||||
|
expect(reloaded.permission).toEqual([{ permission: "read", pattern: "*", action: "allow" }])
|
||||||
|
expect(Permission.evaluate("bash", "anything", reloaded.permission ?? []).action).toBe("ask")
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
it.instance(
|
it.instance(
|
||||||
"running subtask preserves metadata after tool-call transition",
|
"running subtask preserves metadata after tool-call transition",
|
||||||
() =>
|
() =>
|
||||||
|
|
|
||||||
|
|
@ -421,19 +421,15 @@ describe("tool.task", () => {
|
||||||
{
|
{
|
||||||
permission: "bash",
|
permission: "bash",
|
||||||
pattern: "*",
|
pattern: "*",
|
||||||
action: "allow",
|
action: "deny",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
permission: "read",
|
permission: "read",
|
||||||
pattern: "*",
|
pattern: "*",
|
||||||
action: "allow",
|
action: "deny",
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
expect(seen?.tools).toEqual({
|
expect(seen?.tools).toBeUndefined()
|
||||||
todowrite: false,
|
|
||||||
bash: false,
|
|
||||||
read: false,
|
|
||||||
})
|
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
config: {
|
config: {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue