summaryrefslogtreecommitdiff
path: root/packages/cli/src/acp/acpPeer.ts
diff options
context:
space:
mode:
authorjoshualitt <[email protected]>2025-08-06 10:50:02 -0700
committerGitHub <[email protected]>2025-08-06 17:50:02 +0000
commit6133bea388a2de69c71a6be6f1450707f2ce4dfb (patch)
tree367de1d618069ea80e47d7e86c4fb8f82ad032a7 /packages/cli/src/acp/acpPeer.ts
parent882a97aff998b2f19731e9966d135f1db5a59914 (diff)
feat(core): Introduce `DeclarativeTool` and `ToolInvocation`. (#5613)
Diffstat (limited to 'packages/cli/src/acp/acpPeer.ts')
-rw-r--r--packages/cli/src/acp/acpPeer.ts149
1 files changed, 76 insertions, 73 deletions
diff --git a/packages/cli/src/acp/acpPeer.ts b/packages/cli/src/acp/acpPeer.ts
index 90952b7f..40d8753f 100644
--- a/packages/cli/src/acp/acpPeer.ts
+++ b/packages/cli/src/acp/acpPeer.ts
@@ -239,65 +239,62 @@ class GeminiAgent implements Agent {
);
}
- let toolCallId;
- const confirmationDetails = await tool.shouldConfirmExecute(
- args,
- abortSignal,
- );
- if (confirmationDetails) {
- let content: acp.ToolCallContent | null = null;
- if (confirmationDetails.type === 'edit') {
- content = {
- type: 'diff',
- path: confirmationDetails.fileName,
- oldText: confirmationDetails.originalContent,
- newText: confirmationDetails.newContent,
- };
- }
+ let toolCallId: number | undefined = undefined;
+ try {
+ const invocation = tool.build(args);
+ const confirmationDetails =
+ await invocation.shouldConfirmExecute(abortSignal);
+ if (confirmationDetails) {
+ let content: acp.ToolCallContent | null = null;
+ if (confirmationDetails.type === 'edit') {
+ content = {
+ type: 'diff',
+ path: confirmationDetails.fileName,
+ oldText: confirmationDetails.originalContent,
+ newText: confirmationDetails.newContent,
+ };
+ }
- const result = await this.client.requestToolCallConfirmation({
- label: tool.getDescription(args),
- icon: tool.icon,
- content,
- confirmation: toAcpToolCallConfirmation(confirmationDetails),
- locations: tool.toolLocations(args),
- });
+ const result = await this.client.requestToolCallConfirmation({
+ label: invocation.getDescription(),
+ icon: tool.icon,
+ content,
+ confirmation: toAcpToolCallConfirmation(confirmationDetails),
+ locations: invocation.toolLocations(),
+ });
- await confirmationDetails.onConfirm(toToolCallOutcome(result.outcome));
- switch (result.outcome) {
- case 'reject':
- return errorResponse(
- new Error(`Tool "${fc.name}" not allowed to run by the user.`),
- );
+ await confirmationDetails.onConfirm(toToolCallOutcome(result.outcome));
+ switch (result.outcome) {
+ case 'reject':
+ return errorResponse(
+ new Error(`Tool "${fc.name}" not allowed to run by the user.`),
+ );
- case 'cancel':
- return errorResponse(
- new Error(`Tool "${fc.name}" was canceled by the user.`),
- );
- case 'allow':
- case 'alwaysAllow':
- case 'alwaysAllowMcpServer':
- case 'alwaysAllowTool':
- break;
- default: {
- const resultOutcome: never = result.outcome;
- throw new Error(`Unexpected: ${resultOutcome}`);
+ case 'cancel':
+ return errorResponse(
+ new Error(`Tool "${fc.name}" was canceled by the user.`),
+ );
+ case 'allow':
+ case 'alwaysAllow':
+ case 'alwaysAllowMcpServer':
+ case 'alwaysAllowTool':
+ break;
+ default: {
+ const resultOutcome: never = result.outcome;
+ throw new Error(`Unexpected: ${resultOutcome}`);
+ }
}
+ toolCallId = result.id;
+ } else {
+ const result = await this.client.pushToolCall({
+ icon: tool.icon,
+ label: invocation.getDescription(),
+ locations: invocation.toolLocations(),
+ });
+ toolCallId = result.id;
}
- toolCallId = result.id;
- } else {
- const result = await this.client.pushToolCall({
- icon: tool.icon,
- label: tool.getDescription(args),
- locations: tool.toolLocations(args),
- });
-
- toolCallId = result.id;
- }
-
- try {
- const toolResult: ToolResult = await tool.execute(args, abortSignal);
+ const toolResult: ToolResult = await invocation.execute(abortSignal);
const toolCallContent = toToolCallContent(toolResult);
await this.client.updateToolCall({
@@ -320,12 +317,13 @@ class GeminiAgent implements Agent {
return convertToFunctionResponse(fc.name, callId, toolResult.llmContent);
} catch (e) {
const error = e instanceof Error ? e : new Error(String(e));
- await this.client.updateToolCall({
- toolCallId,
- status: 'error',
- content: { type: 'markdown', markdown: error.message },
- });
-
+ if (toolCallId) {
+ await this.client.updateToolCall({
+ toolCallId,
+ status: 'error',
+ content: { type: 'markdown', markdown: error.message },
+ });
+ }
return errorResponse(error);
}
}
@@ -408,7 +406,7 @@ class GeminiAgent implements Agent {
`Path ${pathName} not found directly, attempting glob search.`,
);
try {
- const globResult = await globTool.execute(
+ const globResult = await globTool.buildAndExecute(
{
pattern: `**/*${pathName}*`,
path: this.config.getTargetDir(),
@@ -530,12 +528,15 @@ class GeminiAgent implements Agent {
respectGitIgnore, // Use configuration setting
};
- const toolCall = await this.client.pushToolCall({
- icon: readManyFilesTool.icon,
- label: readManyFilesTool.getDescription(toolArgs),
- });
+ let toolCallId: number | undefined = undefined;
try {
- const result = await readManyFilesTool.execute(toolArgs, abortSignal);
+ const invocation = readManyFilesTool.build(toolArgs);
+ const toolCall = await this.client.pushToolCall({
+ icon: readManyFilesTool.icon,
+ label: invocation.getDescription(),
+ });
+ toolCallId = toolCall.id;
+ const result = await invocation.execute(abortSignal);
const content = toToolCallContent(result) || {
type: 'markdown',
markdown: `Successfully read: ${contentLabelsForDisplay.join(', ')}`,
@@ -578,14 +579,16 @@ class GeminiAgent implements Agent {
return processedQueryParts;
} catch (error: unknown) {
- await this.client.updateToolCall({
- toolCallId: toolCall.id,
- status: 'error',
- content: {
- type: 'markdown',
- markdown: `Error reading files (${contentLabelsForDisplay.join(', ')}): ${getErrorMessage(error)}`,
- },
- });
+ if (toolCallId) {
+ await this.client.updateToolCall({
+ toolCallId,
+ status: 'error',
+ content: {
+ type: 'markdown',
+ markdown: `Error reading files (${contentLabelsForDisplay.join(', ')}): ${getErrorMessage(error)}`,
+ },
+ });
+ }
throw error;
}
}