84 lines
3.4 KiB
TypeScript
84 lines
3.4 KiB
TypeScript
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
import { Type } from "typebox";
|
|
|
|
export default function (pi: ExtensionAPI) {
|
|
pi.registerTool({
|
|
name: "propose_delegation",
|
|
label: "Propose Delegation",
|
|
description:
|
|
"Submit a sequential list of focused child-agent work units. " +
|
|
"This is the only tool available in delegation planning mode. " +
|
|
"Do not execute the task or perform desktop/browser/filesystem actions.",
|
|
parameters: Type.Object({
|
|
title: Type.String({
|
|
description: "Short title for the delegated run.",
|
|
}),
|
|
reason: Type.String({
|
|
description: "Brief reason this task benefits from sequential child agents.",
|
|
}),
|
|
units: Type.Array(
|
|
Type.Object({
|
|
id: Type.Optional(Type.String({
|
|
description: "Stable short id for this work unit, e.g. scout-1.",
|
|
})),
|
|
title: Type.String({
|
|
description: "Short label shown in the UI.",
|
|
}),
|
|
role: Type.String({
|
|
description: "Focused role such as scout, researcher, worker, reviewer, or synthesizer.",
|
|
}),
|
|
objective: Type.String({
|
|
description: "The concrete subtask for the child agent.",
|
|
}),
|
|
allowed_tools: Type.Optional(Type.Array(Type.String(), {
|
|
description: "Optional tool names or categories the child is expected to use.",
|
|
maxItems: 8,
|
|
})),
|
|
expected_output: Type.String({
|
|
description: "The specific text/artifact handoff expected from the child.",
|
|
}),
|
|
depends_on: Type.Optional(Type.Array(Type.String(), {
|
|
description: "Optional ids this unit depends on. Keep sequential ordering simple.",
|
|
maxItems: 5,
|
|
})),
|
|
requires_user_approval: Type.Optional(Type.Boolean({
|
|
description: "True only if this unit should pause for user approval before running.",
|
|
})),
|
|
}),
|
|
{
|
|
description: "Sequential child-agent work units.",
|
|
minItems: 1,
|
|
maxItems: 8,
|
|
},
|
|
),
|
|
}),
|
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
const payload = {
|
|
title: String(params.title || "Delegated Run").trim(),
|
|
reason: String(params.reason || "").trim(),
|
|
units: Array.isArray(params.units)
|
|
? params.units.map((unit: any, idx: number) => ({
|
|
id: String(unit.id || `step-${idx + 1}`).trim(),
|
|
title: String(unit.title || `Step ${idx + 1}`).trim(),
|
|
role: String(unit.role || "worker").trim(),
|
|
objective: String(unit.objective || "").trim(),
|
|
allowed_tools: Array.isArray(unit.allowed_tools)
|
|
? unit.allowed_tools.map((tool: string) => String(tool || "").trim()).filter(Boolean)
|
|
: [],
|
|
expected_output: String(unit.expected_output || "").trim(),
|
|
depends_on: Array.isArray(unit.depends_on)
|
|
? unit.depends_on.map((dep: string) => String(dep || "").trim()).filter(Boolean)
|
|
: [],
|
|
requires_user_approval: unit.requires_user_approval === true,
|
|
})).filter((unit: any) => unit.objective)
|
|
: [],
|
|
};
|
|
|
|
return {
|
|
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
details: payload,
|
|
};
|
|
},
|
|
});
|
|
}
|