Files
pi-ask/src/ask-tool.ts
T

75 lines
1.9 KiB
TypeScript

import type {
ExtensionAPI,
ExtensionContext,
} from "@mariozechner/pi-coding-agent";
import { appendAskPayload } from "./ask-payload-store.ts";
import {
ASK_TOOL_DESCRIPTION,
ASK_TOOL_PROMPT_GUIDELINES,
invalidPayloadResponse,
nonInteractiveResponse,
renderAskToolCall,
renderAskToolResult,
successfulResponse,
validateParams,
} from "./ask-tool-helpers.ts";
import { getAskConfigStore } from "./config/store.ts";
import { AskParamsSchema } from "./schema.ts";
import type { AskParams } from "./types.ts";
import { runAskFlow } from "./ui/controller.ts";
export function registerAskTool(pi: ExtensionAPI) {
pi.registerTool({
name: "ask_user",
label: "Ask User",
description: ASK_TOOL_DESCRIPTION,
promptSnippet:
"Clarify ambiguous or preference-sensitive decisions with a short interactive interview before proceeding",
promptGuidelines: [...ASK_TOOL_PROMPT_GUIDELINES],
parameters: AskParamsSchema,
execute: (toolCallId, params, signal, onUpdate, ctx) =>
executeAskTool(
pi,
toolCallId,
params as AskParams,
signal,
onUpdate,
ctx
),
renderCall: renderAskToolCall,
renderResult: renderAskToolResult,
});
}
async function executeAskTool(
pi: Pick<ExtensionAPI, "appendEntry">,
toolCallId: string,
params: AskParams,
_signal: AbortSignal | undefined,
_onUpdate: unknown,
ctx: ExtensionContext
) {
const config = await getAskConfigStore().getConfig();
const validation = validateParams(params, {
presentSingleAsMulti: config.behaviour.presentSingleAsMulti,
});
if (!validation.ok) {
return invalidPayloadResponse(params, validation.issues);
}
appendAskPayload(pi, {
params,
source: "tool",
sourceEntryId: toolCallId,
});
if (!ctx.hasUI) {
return nonInteractiveResponse(validation.state);
}
ctx.ui.setWorkingVisible(false);
try {
const result = await runAskFlow(ctx, params);
return successfulResponse(result);
} finally {
ctx.ui.setWorkingVisible(true);
}
}