Files
pi-subagents/src/tools.ts

66 lines
2.2 KiB
TypeScript

import { Type } from "typebox";
import { FINALIZE_TOOL_NAME } from "./constants.ts";
import type { PromptConfig, SubagentFinalizePayload } from "./types.ts";
import { FinalizeStatus } from "./types.ts";
// Resolve Tools - Use exactly one permission mode. approved_tools/allowed_tools
// is a whitelist; denied_tools is a blacklist over the currently active tools.
export function resolveTools(
agent: PromptConfig,
activeTools: string[],
): string[] {
const withoutDelegationTools = (tools: string[]) =>
tools.filter((tool) => tool !== "subagent" && tool !== FINALIZE_TOOL_NAME);
const resolved =
agent.approvedTools.length > 0
? withoutDelegationTools([...new Set(agent.approvedTools)])
: withoutDelegationTools(
[...new Set(activeTools)].filter(
(tool) => !new Set(agent.deniedTools).has(tool),
),
);
return [...new Set([...resolved, FINALIZE_TOOL_NAME])];
}
// Validate Finalize Payload - Keep the parent contract strict and small.
export function validateFinalizePayload(
value: unknown,
): SubagentFinalizePayload | null {
if (!value || typeof value !== "object") return null;
const payload = value as Record<string, unknown>;
if (payload.status === FinalizeStatus.SUCCESS) {
return typeof payload.result === "string" && payload.result.trim()
? { status: FinalizeStatus.SUCCESS, result: payload.result }
: null;
}
if (payload.status === FinalizeStatus.ERROR) {
const result =
typeof payload.result === "string" ? payload.result : undefined;
return typeof payload.error === "string" && payload.error.trim()
? { status: FinalizeStatus.ERROR, error: payload.error, result }
: null;
}
return null;
}
export const SubagentParams = Type.Object({
agent: Type.String({
description: "Name of the prompt-defined subagent to invoke",
}),
task: Type.String({ description: "Task to delegate to the subagent" }),
sessionId: Type.Optional(
Type.String({
description:
"Optional sticky subagent session id. Reuse to continue a previous subagent context.",
}),
),
cwd: Type.Optional(
Type.String({
description:
"Working directory for the subagent process. Defaults to current cwd.",
}),
),
});