Skip to content

Commit 83bb216

Browse files
authored
fix: ensure tools are always in same order (#26370)
1 parent fc46cef commit 83bb216

1 file changed

Lines changed: 6 additions & 5 deletions

File tree

  • packages/opencode/src/session

packages/opencode/src/session/llm.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ const live: Layer.Layer<
225225
execute: async () => ({ output: "", title: "", metadata: {} }),
226226
})
227227
}
228+
const sortedTools = Object.fromEntries(Object.entries(tools).toSorted(([a], [b]) => a.localeCompare(b)))
228229

229230
// Wire up toolExecutor for DWS workflow models so that tool calls
230231
// from the workflow service are executed via opencode's tool system
@@ -238,7 +239,7 @@ const live: Layer.Layer<
238239
workflowModel.sessionID = input.sessionID
239240
workflowModel.systemPrompt = system.join("\n")
240241
workflowModel.toolExecutor = async (toolName, argsJson, _requestID) => {
241-
const t = tools[toolName]
242+
const t = sortedTools[toolName]
242243
if (!t || !t.execute) {
243244
return { result: "", error: `Unknown tool: ${toolName}` }
244245
}
@@ -260,7 +261,7 @@ const live: Layer.Layer<
260261
}
261262

262263
const ruleset = Permission.merge(input.agent.permission ?? [], input.permission ?? [])
263-
workflowModel.sessionPreapprovedTools = Object.keys(tools).filter((name) => {
264+
workflowModel.sessionPreapprovedTools = Object.keys(sortedTools).filter((name) => {
264265
const match = ruleset.findLast((rule) => Wildcard.match(name, rule.permission))
265266
return !match || match.action !== "ask"
266267
})
@@ -341,7 +342,7 @@ const live: Layer.Layer<
341342
},
342343
async experimental_repairToolCall(failed) {
343344
const lower = failed.toolCall.toolName.toLowerCase()
344-
if (lower !== failed.toolCall.toolName && tools[lower]) {
345+
if (lower !== failed.toolCall.toolName && sortedTools[lower]) {
345346
l.info("repairing tool call", {
346347
tool: failed.toolCall.toolName,
347348
repaired: lower,
@@ -364,8 +365,8 @@ const live: Layer.Layer<
364365
topP: params.topP,
365366
topK: params.topK,
366367
providerOptions: ProviderTransform.providerOptions(input.model, params.options),
367-
activeTools: Object.keys(tools).filter((x) => x !== "invalid"),
368-
tools,
368+
activeTools: Object.keys(sortedTools).filter((x) => x !== "invalid"),
369+
tools: sortedTools,
369370
toolChoice: input.toolChoice,
370371
maxOutputTokens: params.maxOutputTokens,
371372
abortSignal: input.abort,

0 commit comments

Comments
 (0)