feat: experimental codemode (#34677)

This commit is contained in:
Aiden Cline
2026-07-02 23:48:34 -05:00
committed by GitHub
parent 04d236ceed
commit cb93114424
37 changed files with 11329 additions and 45 deletions
+30 -1
View File
@@ -26,6 +26,9 @@ import { Plugin } from "../plugin"
import { Provider } from "@/provider/provider"
import { WebSearchTool } from "./websearch"
import { CodeModeTool, catalogInstructions } from "./code-mode"
import { MCP } from "@/mcp"
import { McpCatalog } from "@/mcp/catalog"
import { LspTool } from "./lsp"
import * as Truncate from "./truncate"
import { ApplyPatchTool } from "./apply_patch"
@@ -51,6 +54,7 @@ import { BackgroundJob } from "@/background/job"
import { RuntimeFlags } from "@/effect/runtime-flags"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { ModelV2 } from "@opencode-ai/core/model"
import type { PermissionV1 } from "@opencode-ai/core/v1/permission"
export function webSearchEnabled(providerID: ProviderV2.ID, flags = { exa: false, parallel: false }) {
return providerID === ProviderV2.ID.opencode || flags.exa || flags.parallel
@@ -74,6 +78,7 @@ export interface Interface {
providerID: ProviderV2.ID
modelID: ModelV2.ID
agent: Agent.Info
permission?: PermissionV1.Ruleset
}) => Effect.Effect<Tool.Def[]>
}
@@ -87,6 +92,7 @@ const layer = Layer.effect(
const agents = yield* Agent.Service
const truncate = yield* Truncate.Service
const flags = yield* RuntimeFlags.Service
const mcp = yield* MCP.Service
const invalid = yield* InvalidTool
const task = yield* TaskTool
@@ -104,6 +110,7 @@ const layer = Layer.effect(
const greptool = yield* GrepTool
const patchtool = yield* ApplyPatchTool
const skilltool = yield* SkillTool
const codemode = yield* CodeModeTool
const agent = yield* Agent.Service
const state = yield* InstanceState.make<State>(
@@ -211,6 +218,7 @@ const layer = Layer.effect(
question: Tool.init(question),
lsp: Tool.init(lsptool),
plan: Tool.init(plan),
codemode: Tool.init(codemode),
})
return {
@@ -232,6 +240,7 @@ const layer = Layer.effect(
tool.patch,
...(flags.experimentalLspTool ? [tool.lsp] : []),
...(flags.experimentalPlanMode && flags.client === "cli" ? [tool.plan] : []),
...(flags.experimentalCodeMode ? [tool.codemode] : []),
],
task: tool.task,
read: tool.read,
@@ -263,11 +272,25 @@ const layer = Layer.effect(
return ["Available agent types and the tools they have access to:", description].join("\n")
})
// The grouped MCP-tool catalog appended to the code-mode base description, built
// fresh per turn so it tracks live tool-list changes. Hard-denied tools (the shared
// Permission.visibleTools predicate over the agent's ruleset) never enter the
// catalog, its inlined signatures, or the in-program search index.
const describeCodeMode = Effect.fn("ToolRegistry.describeCodeMode")(function* (agent: Agent.Info, permission?: PermissionV1.Ruleset) {
const visible = Permission.visibleTools(yield* mcp.tools(), Permission.merge(agent.permission, permission ?? []))
const servers = Object.keys(yield* mcp.clients()).map(McpCatalog.sanitize)
return catalogInstructions(visible, yield* mcp.defs(), servers)
})
const tools: Interface["tools"] = Effect.fn("ToolRegistry.tools")(function* (input) {
// Consulted once before the synchronous filter: code mode registers only when the
// experimental flag is on AND at least one MCP tool is connected.
const mcpToolCount = flags.experimentalCodeMode ? Object.keys(yield* mcp.tools()).length : 0
const filtered = (yield* all()).filter((tool) => {
if (tool.id === WebSearchTool.id) {
return webSearchEnabled(input.providerID, { exa: flags.enableExa, parallel: flags.enableParallel })
}
if (tool.id === CodeModeTool.id) return flags.experimentalCodeMode && mcpToolCount > 0
const usePatch =
input.modelID.includes("gpt-") && !input.modelID.includes("oss") && !input.modelID.includes("gpt-4")
@@ -292,7 +315,11 @@ const layer = Layer.effect(
: undefined
return {
id: tool.id,
description: [output.description, tool.id === TaskTool.id ? yield* describeTask(input.agent) : undefined]
description: [
output.description,
tool.id === TaskTool.id ? yield* describeTask(input.agent) : undefined,
tool.id === CodeModeTool.id ? yield* describeCodeMode(input.agent, input.permission) : undefined,
]
.filter(Boolean)
.join("\n"),
parameters: output.parameters,
@@ -314,6 +341,7 @@ const layer = Layer.effect(
}),
)
function isZodType(value: unknown): value is z.ZodType {
return typeof value === "object" && value !== null && "_zod" in value
}
@@ -406,6 +434,7 @@ export const node = LayerNode.make({
LSP.node,
Instruction.node,
FSUtil.node,
MCP.node,
EventV2Bridge.node,
httpClient,
CrossSpawnSpawner.node,