Skip to content

Commit 237284e

Browse files
fix(batch): throw calls above 10 instead of failing the full batch
1 parent c31d198 commit 237284e

File tree

1 file changed

+33
-8
lines changed

1 file changed

+33
-8
lines changed

packages/opencode/src/tool/batch.ts

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export const BatchTool = Tool.define("batch", async () => {
1717
}),
1818
)
1919
.min(1, "Provide at least one tool call")
20-
.max(10, "Too many tools in batch. Maximum allowed is 10.")
2120
.describe("Array of tool calls to execute in parallel"),
2221
}),
2322
formatValidationError(error) {
@@ -34,14 +33,15 @@ export const BatchTool = Tool.define("batch", async () => {
3433
const { Session } = await import("../session")
3534
const { Identifier } = await import("../id/id")
3635

37-
const toolCalls = params.tool_calls
36+
const toolCalls = params.tool_calls.slice(0, 10)
37+
const discardedCalls = params.tool_calls.slice(10)
3838

3939
const { ToolRegistry } = await import("./registry")
4040
const availableTools = await ToolRegistry.tools("", "")
4141
const toolMap = new Map(availableTools.map((t) => [t.id, t]))
4242

4343
const partIDs = new Map<(typeof toolCalls)[0], string>()
44-
for (const call of toolCalls) {
44+
for (const call of [...toolCalls, ...discardedCalls]) {
4545
const partID = Identifier.ascending("part")
4646
partIDs.set(call, partID)
4747
Session.updatePart({
@@ -126,8 +126,33 @@ export const BatchTool = Tool.define("batch", async () => {
126126

127127
const results = await Promise.all(toolCalls.map((call) => executeCall(call)))
128128

129+
// Add discarded calls as errors
130+
const now = Date.now()
131+
for (const call of discardedCalls) {
132+
const partID = partIDs.get(call)!
133+
await Session.updatePart({
134+
id: partID,
135+
messageID: ctx.messageID,
136+
sessionID: ctx.sessionID,
137+
type: "tool",
138+
tool: call.tool,
139+
callID: partID,
140+
state: {
141+
status: "error",
142+
input: call.parameters,
143+
error: "Maximum of 10 tools allowed in batch",
144+
time: { start: now, end: now },
145+
},
146+
})
147+
results.push({
148+
success: false as const,
149+
tool: call.tool,
150+
error: new Error("Maximum of 10 tools allowed in batch"),
151+
})
152+
}
153+
129154
const successfulCalls = results.filter((r) => r.success).length
130-
const failedCalls = toolCalls.length - successfulCalls
155+
const failedCalls = results.length - successfulCalls
131156

132157
const outputParts = results.map((r) => {
133158
if (r.success) {
@@ -139,18 +164,18 @@ export const BatchTool = Tool.define("batch", async () => {
139164

140165
const outputMessage =
141166
failedCalls > 0
142-
? `Executed ${successfulCalls}/${toolCalls.length} tools successfully. ${failedCalls} failed.\n\n${outputParts.join("\n\n")}`
167+
? `Executed ${successfulCalls}/${results.length} tools successfully. ${failedCalls} failed.\n\n${outputParts.join("\n\n")}`
143168
: `All ${successfulCalls} tools executed successfully.\n\n${outputParts.join("\n\n")}\n\nKeep using the batch tool for optimal performance in your next response!`
144169

145170
return {
146-
title: `Batch execution (${successfulCalls}/${toolCalls.length} successful)`,
171+
title: `Batch execution (${successfulCalls}/${results.length} successful)`,
147172
output: outputMessage,
148173
attachments: results.filter((result) => result.success).flatMap((r) => r.result.attachments ?? []),
149174
metadata: {
150-
totalCalls: toolCalls.length,
175+
totalCalls: results.length,
151176
successful: successfulCalls,
152177
failed: failedCalls,
153-
tools: toolCalls.map((c) => c.tool),
178+
tools: params.tool_calls.map((c) => c.tool),
154179
details: results.map((r) => ({ tool: r.tool, success: r.success })),
155180
},
156181
}

0 commit comments

Comments
 (0)