Przeglądaj źródła

fix(opencode): avoid deferred MCP search at step limit

Aiden Cline 1 miesiąc temu
rodzic
commit
0bff5bf389

+ 2 - 1
packages/opencode/src/session/mcp-tools.ts

@@ -51,6 +51,7 @@ interface Input {
   bypassAgentCheck: boolean
   messages: SessionV1.WithParts[]
   promptOps: TaskPromptOps
+  canDeferMcpTools?: boolean
 }
 
 interface DeferredToolDescriptor {
@@ -243,7 +244,7 @@ export const resolve = Effect.fn("SessionMcpTools.resolve")(function* (input: In
     Object.entries(mcpTools).filter(([key]) => userTools?.[key] !== false && !mcpDisabled.has(key)),
   )
   const deferredDescriptors =
-    flags.experimentalToolSearch && Object.keys(allowedMcpTools).length > 0
+    (input.canDeferMcpTools ?? true) && flags.experimentalToolSearch && Object.keys(allowedMcpTools).length > 0
       ? yield* deferredToolDescriptors(allowedMcpTools)
       : []
   const deferMcpTools =

+ 1 - 0
packages/opencode/src/session/prompt.ts

@@ -1231,6 +1231,7 @@ export const layer = Layer.effect(
               bypassAgentCheck,
               messages: msgs,
               promptOps,
+              canDeferMcpTools: maxSteps - step >= 2,
             }).pipe(
               Effect.provideService(Plugin.Service, plugin),
               Effect.provideService(Permission.Service, permission),

+ 1 - 0
packages/opencode/src/session/tools.ts

@@ -28,6 +28,7 @@ export const resolve = Effect.fn("SessionTools.resolve")(function* (input: {
   bypassAgentCheck: boolean
   messages: SessionV1.WithParts[]
   promptOps: TaskPromptOps
+  canDeferMcpTools?: boolean
 }) {
   const tools: Record<string, Tool> = {}
   const run = yield* EffectBridge.make()

+ 19 - 8
packages/opencode/test/session/tools.test.ts

@@ -132,15 +132,16 @@ const belowThresholdIt = makeIt({
   queryDescription: "Natural language analytics query",
 })
 
-function resolveTools(messages: SessionV1.WithParts[] = []) {
+function resolveTools(input: { messages?: SessionV1.WithParts[]; canDeferMcpTools?: boolean } = {}) {
   return SessionTools.resolve({
     agent,
     model,
     session,
     processor,
     bypassAgentCheck: false,
-    messages,
+    messages: input.messages ?? [],
     promptOps,
+    canDeferMcpTools: input.canDeferMcpTools,
   })
 }
 
@@ -189,12 +190,14 @@ describe("session.tools", () => {
 
   deferredIt.instance("does not expose per-message disabled MCP tools through deferred search", () =>
     Effect.gen(function* () {
-      const tools = yield* resolveTools([
-        {
-          info: { ...user, tools: { posthog_feature_flags: false } },
-          parts: [],
-        },
-      ])
+      const tools = yield* resolveTools({
+        messages: [
+          {
+            info: { ...user, tools: { posthog_feature_flags: false } },
+            parts: [],
+          },
+        ],
+      })
 
       const search = tools.search_deferred_tools.execute
       if (!search) throw new Error("missing search_deferred_tools executor")
@@ -229,4 +232,12 @@ describe("session.tools", () => {
       expect(Object.keys(tools).sort()).toEqual(["posthog_feature_flags", "posthog_query_trends"])
     }),
   )
+
+  deferredIt.instance("keeps MCP tools direct when deferred search cannot finish before the last step", () =>
+    Effect.gen(function* () {
+      const tools = yield* resolveTools({ canDeferMcpTools: false })
+
+      expect(Object.keys(tools).sort()).toEqual(["posthog_feature_flags", "posthog_query_trends"])
+    }),
+  )
 })