Skip to content

Commit 3d2c002

Browse files
kitlangtonvaur94
authored andcommitted
refactor(session): migrate session domain to Effect Schema (anomalyco#24005)
(cherry picked from commit 0517ab4)
1 parent d1b6c63 commit 3d2c002

18 files changed

Lines changed: 820 additions & 450 deletions

File tree

packages/opencode/specs/effect/schema.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,18 @@ with an inline note describing the bridge and what unblocks its removal.
170170
These are the highest-priority next targets. Each is a small, self-contained
171171
schema module with a clear domain.
172172

173+
- [x] `src/account/schema.ts`
173174
- [x] `src/control-plane/schema.ts`
174175
- [x] `src/permission/schema.ts`
175176
- [x] `src/project/schema.ts`
176177
- [x] `src/provider/schema.ts`
177178
- [x] `src/pty/schema.ts`
178179
- [x] `src/question/schema.ts`
179180
- [x] `src/session/schema.ts`
181+
- [x] `src/storage/schema.ts`
180182
- [x] `src/sync/schema.ts`
181183
- [x] `src/tool/schema.ts`
184+
- [x] `src/util/schema.ts`
182185

183186
### Session domain
184187

@@ -259,15 +262,15 @@ Possible later tightening after the Schema-first migration is stable:
259262
- promote repeated opaque strings and timestamp numbers into branded/newtype
260263
leaf schemas where that adds domain value without changing the wire format
261264

262-
- [ ] `src/session/compaction.ts`
263-
- [ ] `src/session/message-v2.ts`
264-
- [ ] `src/session/message.ts`
265-
- [ ] `src/session/prompt.ts`
266-
- [ ] `src/session/revert.ts`
267-
- [ ] `src/session/session.ts`
268-
- [ ] `src/session/status.ts`
269-
- [ ] `src/session/summary.ts`
270-
- [ ] `src/session/todo.ts`
265+
- [x] `src/session/compaction.ts`
266+
- [x] `src/session/message-v2.ts`
267+
- [x] `src/session/message.ts`
268+
- [x] `src/session/prompt.ts`
269+
- [x] `src/session/revert.ts`
270+
- [x] `src/session/session.ts`
271+
- [x] `src/session/status.ts`
272+
- [x] `src/session/summary.ts`
273+
- [x] `src/session/todo.ts`
271274

272275
### Provider domain
273276

packages/opencode/src/acp/agent.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ export class Agent implements ACPAgent {
372372
}
373373

374374
if (part.tool === "todowrite") {
375-
const parsedTodos = z.array(Todo.Info).safeParse(JSON.parse(part.state.output))
375+
const parsedTodos = z.array(Todo.Info.zod).safeParse(JSON.parse(part.state.output))
376376
if (parsedTodos.success) {
377377
await this.connection
378378
.sessionUpdate({
@@ -901,7 +901,7 @@ export class Agent implements ACPAgent {
901901
}
902902

903903
if (part.tool === "todowrite") {
904-
const parsedTodos = z.array(Todo.Info).safeParse(JSON.parse(part.state.output))
904+
const parsedTodos = z.array(Todo.Info.zod).safeParse(JSON.parse(part.state.output))
905905
if (parsedTodos.success) {
906906
await this.connection
907907
.sessionUpdate({

packages/opencode/src/cli/cmd/import.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { ShareNext } from "../../share"
1111
import { EOL } from "os"
1212
import { Filesystem } from "../../util"
1313
import { AppRuntime } from "@/effect/app-runtime"
14+
import { Schema } from "effect"
1415

1516
/** Discriminated union returned by the ShareNext API (GET /api/shares/:id/data) */
1617
export type ShareData =
@@ -154,10 +155,10 @@ export const ImportCommand = cmd({
154155
return
155156
}
156157

157-
const info = Session.Info.parse({
158+
const info = Schema.decodeUnknownSync(Session.Info)({
158159
...exportData.info,
159160
projectID: Instance.project.id,
160-
})
161+
}) as Session.Info
161162
const row = Session.toRow(info)
162163
Database.use((db) =>
163164
db

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ export const ExperimentalRoutes = lazy(() =>
335335
description: "List of sessions",
336336
content: {
337337
"application/json": {
338-
schema: resolver(Session.GlobalInfo.array()),
338+
schema: resolver(Session.GlobalInfo.zod.array()),
339339
},
340340
},
341341
},

packages/opencode/src/server/routes/instance/session.ts

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { PermissionID } from "@/permission/schema"
2323
import { ModelID, ProviderID } from "@/provider/schema"
2424
import { errors } from "../../error"
2525
import { lazy } from "@/util/lazy"
26+
import { zodObject } from "@/util/effect-zod"
2627
import { Bus } from "@/bus"
2728
import { NamedError } from "@opencode-ai/shared/util/error"
2829
import { jsonRequest, runRequest } from "./trace"
@@ -44,7 +45,7 @@ export const SessionRoutes = lazy(() =>
4445
description: "List of sessions",
4546
content: {
4647
"application/json": {
47-
schema: resolver(Session.Info.array()),
48+
schema: resolver(Session.Info.zod.array()),
4849
},
4950
},
5051
},
@@ -89,7 +90,7 @@ export const SessionRoutes = lazy(() =>
8990
description: "Get session status",
9091
content: {
9192
"application/json": {
92-
schema: resolver(z.record(z.string(), SessionStatus.Info)),
93+
schema: resolver(z.record(z.string(), SessionStatus.Info.zod)),
9394
},
9495
},
9596
},
@@ -114,7 +115,7 @@ export const SessionRoutes = lazy(() =>
114115
description: "Get session",
115116
content: {
116117
"application/json": {
117-
schema: resolver(Session.Info),
118+
schema: resolver(Session.Info.zod),
118119
},
119120
},
120121
},
@@ -124,7 +125,7 @@ export const SessionRoutes = lazy(() =>
124125
validator(
125126
"param",
126127
z.object({
127-
sessionID: Session.GetInput,
128+
sessionID: Session.GetInput.zod,
128129
}),
129130
),
130131
async (c) => {
@@ -147,7 +148,7 @@ export const SessionRoutes = lazy(() =>
147148
description: "List of children",
148149
content: {
149150
"application/json": {
150-
schema: resolver(Session.Info.array()),
151+
schema: resolver(Session.Info.zod.array()),
151152
},
152153
},
153154
},
@@ -157,7 +158,7 @@ export const SessionRoutes = lazy(() =>
157158
validator(
158159
"param",
159160
z.object({
160-
sessionID: Session.ChildrenInput,
161+
sessionID: Session.ChildrenInput.zod,
161162
}),
162163
),
163164
async (c) => {
@@ -179,7 +180,7 @@ export const SessionRoutes = lazy(() =>
179180
description: "Todo list",
180181
content: {
181182
"application/json": {
182-
schema: resolver(Todo.Info.array()),
183+
schema: resolver(Todo.Info.zod.array()),
183184
},
184185
},
185186
},
@@ -212,13 +213,13 @@ export const SessionRoutes = lazy(() =>
212213
description: "Successfully created session",
213214
content: {
214215
"application/json": {
215-
schema: resolver(Session.Info),
216+
schema: resolver(Session.Info.zod),
216217
},
217218
},
218219
},
219220
},
220221
}),
221-
validator("json", Session.CreateInput),
222+
validator("json", Session.CreateInput.zod),
222223
async (c) =>
223224
jsonRequest("SessionRoutes.create", c, function* () {
224225
const body = c.req.valid("json") ?? {}
@@ -247,7 +248,7 @@ export const SessionRoutes = lazy(() =>
247248
validator(
248249
"param",
249250
z.object({
250-
sessionID: Session.RemoveInput,
251+
sessionID: Session.RemoveInput.zod,
251252
}),
252253
),
253254
async (c) =>
@@ -269,7 +270,7 @@ export const SessionRoutes = lazy(() =>
269270
description: "Successfully updated session",
270271
content: {
271272
"application/json": {
272-
schema: resolver(Session.Info),
273+
schema: resolver(Session.Info.zod),
273274
},
274275
},
275276
},
@@ -377,7 +378,7 @@ export const SessionRoutes = lazy(() =>
377378
description: "200",
378379
content: {
379380
"application/json": {
380-
schema: resolver(Session.Info),
381+
schema: resolver(Session.Info.zod),
381382
},
382383
},
383384
},
@@ -386,14 +387,14 @@ export const SessionRoutes = lazy(() =>
386387
validator(
387388
"param",
388389
z.object({
389-
sessionID: Session.ForkInput.shape.sessionID,
390+
sessionID: SessionID.zod,
390391
}),
391392
),
392-
validator("json", Session.ForkInput.omit({ sessionID: true })),
393+
validator("json", zodObject(Session.ForkInput).omit({ sessionID: true })),
393394
async (c) =>
394395
jsonRequest("SessionRoutes.fork", c, function* () {
395396
const sessionID = c.req.valid("param").sessionID
396-
const body = c.req.valid("json")
397+
const body = c.req.valid("json") as { messageID?: MessageID }
397398
const svc = yield* Session.Service
398399
return yield* svc.fork({ ...body, sessionID })
399400
}),
@@ -440,7 +441,7 @@ export const SessionRoutes = lazy(() =>
440441
description: "Successfully shared session",
441442
content: {
442443
"application/json": {
443-
schema: resolver(Session.Info),
444+
schema: resolver(Session.Info.zod),
444445
},
445446
},
446447
},
@@ -482,18 +483,13 @@ export const SessionRoutes = lazy(() =>
482483
validator(
483484
"param",
484485
z.object({
485-
sessionID: SessionSummary.DiffInput.shape.sessionID,
486-
}),
487-
),
488-
validator(
489-
"query",
490-
z.object({
491-
messageID: SessionSummary.DiffInput.shape.messageID,
486+
sessionID: SessionID.zod,
492487
}),
493488
),
489+
validator("query", zodObject(SessionSummary.DiffInput).omit({ sessionID: true })),
494490
async (c) =>
495491
jsonRequest("SessionRoutes.diff", c, function* () {
496-
const query = c.req.valid("query")
492+
const query = c.req.valid("query") as Omit<SessionSummary.DiffInput, "sessionID">
497493
const params = c.req.valid("param")
498494
const summary = yield* SessionSummary.Service
499495
return yield* summary.diff({
@@ -513,7 +509,7 @@ export const SessionRoutes = lazy(() =>
513509
description: "Successfully unshared session",
514510
content: {
515511
"application/json": {
516-
schema: resolver(Session.Info),
512+
schema: resolver(Session.Info.zod),
517513
},
518514
},
519515
},
@@ -874,7 +870,7 @@ export const SessionRoutes = lazy(() =>
874870
sessionID: SessionID.zod,
875871
}),
876872
),
877-
validator("json", SessionPrompt.PromptInput.omit({ sessionID: true })),
873+
validator("json", zodObject(SessionPrompt.PromptInput).omit({ sessionID: true })),
878874
async (c) => {
879875
c.status(200)
880876
c.header("Content-Type", "application/json")
@@ -912,7 +908,7 @@ export const SessionRoutes = lazy(() =>
912908
sessionID: SessionID.zod,
913909
}),
914910
),
915-
validator("json", SessionPrompt.PromptInput.omit({ sessionID: true })),
911+
validator("json", zodObject(SessionPrompt.PromptInput).omit({ sessionID: true })),
916912
async (c) => {
917913
const sessionID = c.req.valid("param").sessionID
918914
const body = c.req.valid("json")
@@ -962,11 +958,11 @@ export const SessionRoutes = lazy(() =>
962958
sessionID: SessionID.zod,
963959
}),
964960
),
965-
validator("json", SessionPrompt.CommandInput.omit({ sessionID: true })),
961+
validator("json", zodObject(SessionPrompt.CommandInput).omit({ sessionID: true })),
966962
async (c) =>
967963
jsonRequest("SessionRoutes.command", c, function* () {
968964
const sessionID = c.req.valid("param").sessionID
969-
const body = c.req.valid("json")
965+
const body = c.req.valid("json") as Omit<SessionPrompt.CommandInput, "sessionID">
970966
const svc = yield* SessionPrompt.Service
971967
return yield* svc.command({ ...body, sessionID })
972968
}),
@@ -995,11 +991,11 @@ export const SessionRoutes = lazy(() =>
995991
sessionID: SessionID.zod,
996992
}),
997993
),
998-
validator("json", SessionPrompt.ShellInput.omit({ sessionID: true })),
994+
validator("json", zodObject(SessionPrompt.ShellInput).omit({ sessionID: true })),
999995
async (c) =>
1000996
jsonRequest("SessionRoutes.shell", c, function* () {
1001997
const sessionID = c.req.valid("param").sessionID
1002-
const body = c.req.valid("json")
998+
const body = c.req.valid("json") as Omit<SessionPrompt.ShellInput, "sessionID">
1003999
const svc = yield* SessionPrompt.Service
10041000
return yield* svc.shell({ ...body, sessionID })
10051001
}),
@@ -1015,7 +1011,7 @@ export const SessionRoutes = lazy(() =>
10151011
description: "Updated session",
10161012
content: {
10171013
"application/json": {
1018-
schema: resolver(Session.Info),
1014+
schema: resolver(Session.Info.zod),
10191015
},
10201016
},
10211017
},
@@ -1028,16 +1024,14 @@ export const SessionRoutes = lazy(() =>
10281024
sessionID: SessionID.zod,
10291025
}),
10301026
),
1031-
validator("json", SessionRevert.RevertInput.omit({ sessionID: true })),
1027+
validator("json", zodObject(SessionRevert.RevertInput).omit({ sessionID: true })),
10321028
async (c) => {
10331029
const sessionID = c.req.valid("param").sessionID
1034-
log.info("revert", c.req.valid("json"))
1030+
const body = c.req.valid("json") as Omit<SessionRevert.RevertInput, "sessionID">
1031+
log.info("revert", body)
10351032
return jsonRequest("SessionRoutes.revert", c, function* () {
10361033
const svc = yield* SessionRevert.Service
1037-
return yield* svc.revert({
1038-
sessionID,
1039-
...c.req.valid("json"),
1040-
})
1034+
return yield* svc.revert({ sessionID, ...body })
10411035
})
10421036
},
10431037
)
@@ -1052,7 +1046,7 @@ export const SessionRoutes = lazy(() =>
10521046
description: "Updated session",
10531047
content: {
10541048
"application/json": {
1055-
schema: resolver(Session.Info),
1049+
schema: resolver(Session.Info.zod),
10561050
},
10571051
},
10581052
},

0 commit comments

Comments
 (0)