Skip to content

Commit d2898cd

Browse files
committed
core: restructure v2 event system with session.next namespace and data encapsulation
- Rename all event types from session.* to session.next.* for clearer namespacing - Wrap event payload in data field for better schema organization - Add timestamp to all event schemas for consistent event tracking - Fix effect-zod handling for Declaration ASTs with type parameters - Remove obsolete session-entry-stepper tests This provides a cleaner event structure that separates metadata from payload data, making the event system more maintainable and easier to extend.
1 parent 1554e24 commit d2898cd

7 files changed

Lines changed: 135 additions & 748 deletions

File tree

packages/opencode/src/util/effect-zod.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ function bodyWithChecks(ast: SchemaAST.AST): z.ZodTypeAny {
9090
// Schema.withDecodingDefault also attaches encoding, but we want `.default(v)`
9191
// on the inner Zod rather than a transform wrapper — so optional ASTs whose
9292
// encoding resolves a default from Option.none() route through body()/opt().
93-
const hasEncoding = ast.encoding?.length && ast._tag !== "Declaration"
93+
const hasEncoding = ast.encoding?.length && (ast._tag !== "Declaration" || ast.typeParameters.length === 0)
9494
const hasTransform = hasEncoding && !(SchemaAST.isOptional(ast) && extractDefault(ast) !== undefined)
9595
const base = hasTransform ? encoded(ast) : body(ast)
9696
return ast.checks?.length ? applyChecks(base, ast.checks, ast) : base

packages/opencode/src/v2/event.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,10 @@ export function define<const Type extends string, Fields extends Schema.Struct.F
1717
aggregate: string
1818
version?: number
1919
}) {
20-
const Event = Schema.Struct({
21-
id: ID,
20+
const Payload = Schema.Struct({
2221
metadata: Schema.Record(Schema.String, Schema.Unknown).pipe(Schema.optional),
23-
timestamp: Schema.DateTimeUtc,
2422
type: Schema.Literal(input.type),
25-
version: Schema.Number.pipe(Schema.optional),
26-
...input.schema,
23+
data: Schema.Struct(input.schema),
2724
}).annotate({
2825
identifier: input.type,
2926
})
@@ -32,10 +29,14 @@ export function define<const Type extends string, Fields extends Schema.Struct.F
3229
type: input.type,
3330
version: input.version ?? 1,
3431
aggregate: input.aggregate,
35-
schema: Event,
32+
schema: Payload.fields.data,
3633
})
3734

38-
return Object.assign(Event, { Sync })
35+
return Object.assign(Payload, {
36+
Sync,
37+
version: input.version,
38+
aggregate: input.aggregate,
39+
})
3940
}
4041

4142
export * as Event from "./event"

packages/opencode/src/v2/session-entry-stepper.ts

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -63,40 +63,40 @@ export function stepWith<Result>(adapter: Adapter<Result>, event: SessionEvent.E
6363
const latestReasoning = (assistant: DraftAssistant | undefined) =>
6464
assistant?.content.findLast((item): item is DraftReasoning => item.type === "reasoning")
6565

66-
SessionEvent.Event.match(event, {
67-
"session.prompted": (event) => {
66+
SessionEvent.All.match(event, {
67+
"session.next.prompted": (event) => {
6868
const entry = SessionEntry.User.fromEvent(event)
6969
if (currentAssistant) {
7070
adapter.appendPending(entry)
7171
return
7272
}
7373
adapter.appendEntry(entry)
7474
},
75-
"session.synthetic": (event) => {
75+
"session.next.synthetic": (event) => {
7676
adapter.appendEntry(SessionEntry.Synthetic.fromEvent(event))
7777
},
78-
"session.step.started": (event) => {
78+
"session.next.step.started": (event) => {
7979
if (currentAssistant) {
8080
adapter.updateAssistant(
8181
produce(currentAssistant, (draft) => {
82-
draft.time.completed = event.timestamp
82+
draft.time.completed = event.data.timestamp
8383
}),
8484
)
8585
}
8686
adapter.appendEntry(SessionEntry.Assistant.fromEvent(event))
8787
},
88-
"session.step.ended": (event) => {
88+
"session.next.step.ended": (event) => {
8989
if (currentAssistant) {
9090
adapter.updateAssistant(
9191
produce(currentAssistant, (draft) => {
92-
draft.time.completed = event.timestamp
93-
draft.cost = event.cost
94-
draft.tokens = event.tokens
92+
draft.time.completed = event.data.timestamp
93+
draft.cost = event.data.cost
94+
draft.tokens = event.data.tokens
9595
}),
9696
)
9797
}
9898
},
99-
"session.text.started": () => {
99+
"session.next.text.started": () => {
100100
if (currentAssistant) {
101101
adapter.updateAssistant(
102102
produce(currentAssistant, (draft) => {
@@ -108,27 +108,27 @@ export function stepWith<Result>(adapter: Adapter<Result>, event: SessionEvent.E
108108
)
109109
}
110110
},
111-
"session.text.delta": (event) => {
111+
"session.next.text.delta": (event) => {
112112
if (currentAssistant) {
113113
adapter.updateAssistant(
114114
produce(currentAssistant, (draft) => {
115115
const match = latestText(draft)
116-
if (match) match.text += event.delta
116+
if (match) match.text += event.data.delta
117117
}),
118118
)
119119
}
120120
},
121-
"session.text.ended": () => {},
122-
"session.tool.input.started": (event) => {
121+
"session.next.text.ended": () => {},
122+
"session.next.tool.input.started": (event) => {
123123
if (currentAssistant) {
124124
adapter.updateAssistant(
125125
produce(currentAssistant, (draft) => {
126126
draft.content.push({
127127
type: "tool",
128-
callID: event.callID,
129-
name: event.name,
128+
callID: event.data.callID,
129+
name: event.data.name,
130130
time: {
131-
created: event.timestamp,
131+
created: event.data.timestamp,
132132
},
133133
state: {
134134
status: "pending",
@@ -139,62 +139,62 @@ export function stepWith<Result>(adapter: Adapter<Result>, event: SessionEvent.E
139139
)
140140
}
141141
},
142-
"session.tool.input.delta": (event) => {
142+
"session.next.tool.input.delta": (event) => {
143143
if (currentAssistant) {
144144
adapter.updateAssistant(
145145
produce(currentAssistant, (draft) => {
146-
const match = latestTool(draft, event.callID)
146+
const match = latestTool(draft, event.data.callID)
147147
// oxlint-disable-next-line no-base-to-string -- event.delta is a Schema.String (runtime string)
148-
if (match && match.state.status === "pending") match.state.input += event.delta
148+
if (match && match.state.status === "pending") match.state.input += event.data.delta
149149
}),
150150
)
151151
}
152152
},
153-
"session.tool.input.ended": () => {},
154-
"session.tool.called": (event) => {
153+
"session.next.tool.input.ended": () => {},
154+
"session.next.tool.called": (event) => {
155155
if (currentAssistant) {
156156
adapter.updateAssistant(
157157
produce(currentAssistant, (draft) => {
158-
const match = latestTool(draft, event.callID)
158+
const match = latestTool(draft, event.data.callID)
159159
if (match) {
160-
match.time.ran = event.timestamp
160+
match.time.ran = event.data.timestamp
161161
match.state = {
162162
status: "running",
163-
input: event.input,
163+
input: event.data.input,
164164
}
165165
}
166166
}),
167167
)
168168
}
169169
},
170-
"session.tool.success": (event) => {
170+
"session.next.tool.success": (event) => {
171171
if (currentAssistant) {
172172
adapter.updateAssistant(
173173
produce(currentAssistant, (draft) => {
174-
const match = latestTool(draft, event.callID)
174+
const match = latestTool(draft, event.data.callID)
175175
if (match && match.state.status === "running") {
176176
match.state = {
177177
status: "completed",
178178
input: match.state.input,
179-
output: event.output ?? "",
180-
title: event.title,
179+
output: event.data.output ?? "",
180+
title: event.data.title,
181181
metadata: event.metadata ?? {},
182-
attachments: [...(event.attachments ?? [])],
182+
attachments: [...(event.data.attachments ?? [])],
183183
}
184184
}
185185
}),
186186
)
187187
}
188188
},
189-
"session.tool.error": (event) => {
189+
"session.next.tool.error": (event) => {
190190
if (currentAssistant) {
191191
adapter.updateAssistant(
192192
produce(currentAssistant, (draft) => {
193-
const match = latestTool(draft, event.callID)
193+
const match = latestTool(draft, event.data.callID)
194194
if (match && match.state.status === "running") {
195195
match.state = {
196196
status: "error",
197-
error: event.error,
197+
error: event.data.error,
198198
input: match.state.input,
199199
metadata: event.metadata ?? {},
200200
}
@@ -203,7 +203,7 @@ export function stepWith<Result>(adapter: Adapter<Result>, event: SessionEvent.E
203203
)
204204
}
205205
},
206-
"session.reasoning.started": () => {
206+
"session.next.reasoning.started": () => {
207207
if (currentAssistant) {
208208
adapter.updateAssistant(
209209
produce(currentAssistant, (draft) => {
@@ -215,27 +215,27 @@ export function stepWith<Result>(adapter: Adapter<Result>, event: SessionEvent.E
215215
)
216216
}
217217
},
218-
"session.reasoning.delta": (event) => {
218+
"session.next.reasoning.delta": (event) => {
219219
if (currentAssistant) {
220220
adapter.updateAssistant(
221221
produce(currentAssistant, (draft) => {
222222
const match = latestReasoning(draft)
223-
if (match) match.text += event.delta
223+
if (match) match.text += event.data.delta
224224
}),
225225
)
226226
}
227227
},
228-
"session.reasoning.ended": (event) => {
228+
"session.next.reasoning.ended": (event) => {
229229
if (currentAssistant) {
230230
adapter.updateAssistant(
231231
produce(currentAssistant, (draft) => {
232232
const match = latestReasoning(draft)
233-
if (match) match.text = event.text
233+
if (match) match.text = event.data.text
234234
}),
235235
)
236236
}
237237
},
238-
"session.retried": (event) => {
238+
"session.next.retried": (event) => {
239239
if (currentAssistant) {
240240
adapter.updateAssistant(
241241
produce(currentAssistant, (draft) => {
@@ -244,7 +244,7 @@ export function stepWith<Result>(adapter: Adapter<Result>, event: SessionEvent.E
244244
)
245245
}
246246
},
247-
"session.compacted": (event) => {
247+
"session.next.compacted": (event) => {
248248
adapter.appendEntry(SessionEntry.Compaction.fromEvent(event))
249249
},
250250
})

packages/opencode/src/v2/session-entry.ts

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,30 @@ export class User extends Schema.Class<User>("Session.Entry.User")({
2626
}) {
2727
static fromEvent(event: SessionEvent.Prompted) {
2828
return new User({
29-
id: event.id,
29+
id: ID.create(),
3030
type: "user",
3131
metadata: event.metadata,
32-
text: event.prompt.text,
33-
files: event.prompt.files,
34-
agents: event.prompt.agents,
35-
time: { created: event.timestamp },
32+
text: event.data.prompt.text,
33+
files: event.data.prompt.files,
34+
agents: event.data.prompt.agents,
35+
time: { created: event.data.timestamp },
3636
})
3737
}
3838
}
3939

4040
export class Synthetic extends Schema.Class<Synthetic>("Session.Entry.Synthetic")({
41-
...SessionEvent.Synthetic.fields,
4241
...Base,
42+
sessionID: SessionEvent.Synthetic.fields.data.fields.sessionID,
43+
text: SessionEvent.Synthetic.fields.data.fields.text,
4344
type: Schema.Literal("synthetic"),
4445
}) {
4546
static fromEvent(event: SessionEvent.Synthetic) {
4647
return new Synthetic({
47-
...event,
48+
sessionID: event.data.sessionID,
49+
text: event.data.text,
50+
id: ID.create(),
4851
type: "synthetic",
49-
time: { created: event.timestamp },
52+
time: { created: event.data.timestamp },
5053
})
5154
}
5255
}
@@ -116,10 +119,10 @@ export class AssistantRetry extends Schema.Class<AssistantRetry>("Session.Entry.
116119
}) {
117120
static fromEvent(event: SessionEvent.Retried) {
118121
return new AssistantRetry({
119-
attempt: event.attempt,
120-
error: event.error,
122+
attempt: event.data.attempt,
123+
error: event.data.error,
121124
time: {
122-
created: event.timestamp,
125+
created: event.data.timestamp,
123126
},
124127
})
125128
}
@@ -153,10 +156,10 @@ export class Assistant extends Schema.Class<Assistant>("Session.Entry.Assistant"
153156
}) {
154157
static fromEvent(event: SessionEvent.Step.Started) {
155158
return new Assistant({
156-
id: event.id,
159+
id: ID.create(),
157160
type: "assistant",
158161
time: {
159-
created: event.timestamp,
162+
created: event.data.timestamp,
160163
},
161164
content: [],
162165
retries: [],
@@ -165,15 +168,20 @@ export class Assistant extends Schema.Class<Assistant>("Session.Entry.Assistant"
165168
}
166169

167170
export class Compaction extends Schema.Class<Compaction>("Session.Entry.Compaction")({
168-
...SessionEvent.Compacted.fields,
169171
type: Schema.Literal("compaction"),
172+
sessionID: SessionEvent.Compacted.fields.data.fields.sessionID,
173+
auto: SessionEvent.Compacted.fields.data.fields.auto,
174+
overflow: SessionEvent.Compacted.fields.data.fields.overflow,
170175
...Base,
171176
}) {
172177
static fromEvent(event: SessionEvent.Compacted) {
173178
return new Compaction({
174-
...event,
179+
sessionID: event.data.sessionID,
180+
auto: event.data.auto,
181+
overflow: event.data.overflow,
182+
id: ID.create(),
175183
type: "compaction",
176-
time: { created: event.timestamp },
184+
time: { created: event.data.timestamp },
177185
})
178186
}
179187
}

0 commit comments

Comments
 (0)