Skip to content

Commit 186063f

Browse files
committed
refactor(effect): build task tool from agent services
1 parent 988c989 commit 186063f

5 files changed

Lines changed: 614 additions & 202 deletions

File tree

packages/opencode/src/session/prompt.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ import { Process } from "@/util/process"
4747
import { Cause, Effect, Exit, Layer, Option, Scope, ServiceMap } from "effect"
4848
import { InstanceState } from "@/effect/instance-state"
4949
import { makeRuntime } from "@/effect/run-service"
50-
import { TaskTool } from "@/tool/task"
5150

5251
// @ts-ignore
5352
globalThis.AI_SDK_LOG_WARNINGS = false
@@ -559,7 +558,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
559558
}) {
560559
const { task, model, lastUser, sessionID, session, msgs } = input
561560
const ctx = yield* InstanceState.context
562-
const taskTool = yield* registry.fromID(TaskTool.id)
561+
const taskTool = yield* registry.fromID("task")
563562
const taskModel = task.model ? yield* getModel(task.model.providerID, task.model.modelID, sessionID) : model
564563
const assistantMessage: MessageV2.Assistant = yield* sessions.updateMessage({
565564
id: MessageID.ascending(),
@@ -582,7 +581,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
582581
sessionID: assistantMessage.sessionID,
583582
type: "tool",
584583
callID: ulid(),
585-
tool: TaskTool.id,
584+
tool: "task",
586585
state: {
587586
status: "running",
588587
input: {

packages/opencode/src/tool/registry.ts

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ export namespace ToolRegistry {
5050
export interface Interface {
5151
readonly ids: () => Effect.Effect<string[]>
5252
readonly all: () => Effect.Effect<Tool.Def[]>
53+
readonly named: {
54+
task: Tool.Info
55+
read: Tool.Info
56+
}
5357
readonly tools: (model: {
5458
providerID: ProviderID
5559
modelID: ModelID
@@ -67,6 +71,7 @@ export namespace ToolRegistry {
6771
| Plugin.Service
6872
| Question.Service
6973
| Todo.Service
74+
| Agent.Service
7075
| LSP.Service
7176
| FileTime.Service
7277
| Instruction.Service
@@ -77,8 +82,18 @@ export namespace ToolRegistry {
7782
const config = yield* Config.Service
7883
const plugin = yield* Plugin.Service
7984

80-
const build = <T extends Tool.Info>(tool: T | Effect.Effect<T, never, any>) =>
81-
Effect.isEffect(tool) ? tool.pipe(Effect.flatMap(Tool.init)) : Tool.init(tool)
85+
const info = <T extends Tool.Info, R = never>(
86+
tool: T | Effect.Effect<T, never, R>,
87+
): Effect.Effect<T, never, R> => (Effect.isEffect(tool) ? tool : Effect.succeed(tool))
88+
89+
const build = <T extends Tool.Info, R = never>(
90+
tool: T | Effect.Effect<T, never, R>,
91+
): Effect.Effect<Tool.Def, never, R> => info(tool).pipe(Effect.flatMap(Tool.init))
92+
93+
const task = yield* info(TaskTool)
94+
const read = yield* info(ReadTool)
95+
const askInfo = yield* info(QuestionTool)
96+
const todoInfo = yield* info(TodoWriteTool)
8297

8398
const state = yield* InstanceState.make<State>(
8499
Effect.fn("ToolRegistry.state")(function* (ctx) {
@@ -135,31 +150,45 @@ export namespace ToolRegistry {
135150
const question =
136151
["app", "cli", "desktop"].includes(Flag.OPENCODE_CLIENT) || Flag.OPENCODE_ENABLE_QUESTION_TOOL
137152

153+
const invalid = yield* build(InvalidTool)
154+
const bash = yield* build(BashTool)
155+
const readDef = yield* build(read)
156+
const glob = yield* build(GlobTool)
157+
const grep = yield* build(GrepTool)
158+
const edit = yield* build(EditTool)
159+
const write = yield* build(WriteTool)
160+
const taskDef = yield* build(task)
161+
const fetch = yield* build(WebFetchTool)
162+
const todo = yield* build(todoInfo)
163+
const search = yield* build(WebSearchTool)
164+
const code = yield* build(CodeSearchTool)
165+
const skill = yield* build(SkillTool)
166+
const patch = yield* build(ApplyPatchTool)
167+
const ask = yield* build(askInfo)
168+
const lsp = yield* build(LspTool)
169+
const plan = yield* build(PlanExitTool)
170+
138171
return {
139172
custom,
140-
builtin: yield* Effect.forEach(
141-
[
142-
InvalidTool,
143-
BashTool,
144-
ReadTool,
145-
GlobTool,
146-
GrepTool,
147-
EditTool,
148-
WriteTool,
149-
TaskTool,
150-
WebFetchTool,
151-
TodoWriteTool,
152-
WebSearchTool,
153-
CodeSearchTool,
154-
SkillTool,
155-
ApplyPatchTool,
156-
...(question ? [QuestionTool] : []),
157-
...(Flag.OPENCODE_EXPERIMENTAL_LSP_TOOL ? [LspTool] : []),
158-
...(Flag.OPENCODE_EXPERIMENTAL_PLAN_MODE && Flag.OPENCODE_CLIENT === "cli" ? [PlanExitTool] : []),
159-
],
160-
build,
161-
{ concurrency: "unbounded" },
162-
),
173+
builtin: [
174+
invalid,
175+
...(question ? [ask] : []),
176+
bash,
177+
readDef,
178+
glob,
179+
grep,
180+
edit,
181+
write,
182+
taskDef,
183+
fetch,
184+
todo,
185+
search,
186+
code,
187+
skill,
188+
patch,
189+
...(Flag.OPENCODE_EXPERIMENTAL_LSP_TOOL ? [lsp] : []),
190+
...(Flag.OPENCODE_EXPERIMENTAL_PLAN_MODE && Flag.OPENCODE_CLIENT === "cli" ? [plan] : []),
191+
],
163192
}
164193
}),
165194
)
@@ -208,8 +237,7 @@ export namespace ToolRegistry {
208237
id: tool.id,
209238
description: [
210239
output.description,
211-
// TODO: remove this hack
212-
tool.id === TaskTool.id ? yield* TaskDescription(input.agent) : undefined,
240+
tool.id === "task" ? yield* TaskDescription(input.agent) : undefined,
213241
tool.id === SkillTool.id ? yield* SkillDescription(input.agent) : undefined,
214242
]
215243
.filter(Boolean)
@@ -223,7 +251,7 @@ export namespace ToolRegistry {
223251
)
224252
})
225253

226-
return Service.of({ ids, tools, all, fromID })
254+
return Service.of({ ids, all, named: { task, read }, tools, fromID })
227255
}),
228256
)
229257

@@ -234,6 +262,7 @@ export namespace ToolRegistry {
234262
Layer.provide(Plugin.defaultLayer),
235263
Layer.provide(Question.defaultLayer),
236264
Layer.provide(Todo.defaultLayer),
265+
Layer.provide(Agent.defaultLayer),
237266
Layer.provide(LSP.defaultLayer),
238267
Layer.provide(FileTime.defaultLayer),
239268
Layer.provide(Instruction.defaultLayer),

0 commit comments

Comments
 (0)