Skip to content

Commit 25af038

Browse files
Apply PR #18679: effectify Worktree service
2 parents c8e5551 + 1f2dd5d commit 25af038

5 files changed

Lines changed: 590 additions & 421 deletions

File tree

packages/opencode/specs/effect-migration.md

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -82,31 +82,38 @@ The `InstanceState.make` init callback receives a `Scope`, so you can use `Effec
8282
- **Subscriptions**: Yield `Bus.Service` at the layer level, then use `Stream` + `forkScoped` inside the init closure. The fiber is automatically interrupted when the instance scope closes:
8383

8484
```ts
85-
const bus = yield* Bus.Service
86-
87-
const cache = yield* InstanceState.make<State>(
88-
Effect.fn("Foo.state")(function* (ctx) {
89-
// ... load state ...
90-
91-
yield* bus
92-
.subscribeAll()
93-
.pipe(
94-
Stream.runForEach((event) => Effect.sync(() => { /* handle */ })),
85+
const bus = yield * Bus.Service
86+
87+
const cache =
88+
yield *
89+
InstanceState.make<State>(
90+
Effect.fn("Foo.state")(function* (ctx) {
91+
// ... load state ...
92+
93+
yield* bus.subscribeAll().pipe(
94+
Stream.runForEach((event) =>
95+
Effect.sync(() => {
96+
/* handle */
97+
}),
98+
),
9599
Effect.forkScoped,
96100
)
97101

98-
return { /* state */ }
99-
}),
100-
)
102+
return {
103+
/* state */
104+
}
105+
}),
106+
)
101107
```
102108

103109
- **Resource cleanup**: Use `Effect.acquireRelease` or `Effect.addFinalizer` for resources that need teardown (native watchers, process handles, etc.):
104110

105111
```ts
106-
yield* Effect.acquireRelease(
107-
Effect.sync(() => nativeAddon.watch(dir)),
108-
(watcher) => Effect.sync(() => watcher.close()),
109-
)
112+
yield *
113+
Effect.acquireRelease(
114+
Effect.sync(() => nativeAddon.watch(dir)),
115+
(watcher) => Effect.sync(() => watcher.close()),
116+
)
110117
```
111118

112119
- **Background fibers**: Use `Effect.forkScoped` — the fiber is interrupted on disposal.
@@ -169,8 +176,8 @@ Still open and likely worth migrating:
169176
- [x] `Plugin`
170177
- [x] `ToolRegistry`
171178
- [ ] `Pty`
172-
- [ ] `Worktree`
173-
- [x] `Bus`
179+
- [x] `Worktree`
180+
- [ ] `Bus`
174181
- [x] `Command`
175182
- [ ] `Config`
176183
- [ ] `Session`

packages/opencode/src/control-plane/adaptors/worktree.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,11 @@ export const WorktreeAdaptor: Adaptor = {
2222
},
2323
async create(info) {
2424
const config = Config.parse(info)
25-
const bootstrap = await Worktree.createFromInfo({
25+
await Worktree.createFromInfo({
2626
name: config.name,
2727
directory: config.directory,
2828
branch: config.branch,
2929
})
30-
return bootstrap()
3130
},
3231
async remove(info) {
3332
const config = Config.parse(info)

packages/opencode/src/server/routes/experimental.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export const ExperimentalRoutes = lazy(() =>
108108
...errors(400),
109109
},
110110
}),
111-
validator("json", Worktree.create.schema),
111+
validator("json", Worktree.CreateInput.optional()),
112112
async (c) => {
113113
const body = c.req.valid("json")
114114
const worktree = await Worktree.create(body)
@@ -155,7 +155,7 @@ export const ExperimentalRoutes = lazy(() =>
155155
...errors(400),
156156
},
157157
}),
158-
validator("json", Worktree.remove.schema),
158+
validator("json", Worktree.RemoveInput),
159159
async (c) => {
160160
const body = c.req.valid("json")
161161
await Worktree.remove(body)
@@ -181,7 +181,7 @@ export const ExperimentalRoutes = lazy(() =>
181181
...errors(400),
182182
},
183183
}),
184-
validator("json", Worktree.reset.schema),
184+
validator("json", Worktree.ResetInput),
185185
async (c) => {
186186
const body = c.req.valid("json")
187187
await Worktree.reset(body)

0 commit comments

Comments
 (0)