refactor(schema): declare event durability at definition level (#35172)

This commit is contained in:
Kit Langton
2026-07-03 12:35:35 -04:00
committed by GitHub
parent bd8d858bf7
commit de476aa51b
53 changed files with 700 additions and 1165 deletions
+96 -146
View File
@@ -1109,7 +1109,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.agent.switched" readonly type: "session.next.agent.switched"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1122,7 +1122,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.model.switched" readonly type: "session.next.model.switched"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1135,7 +1135,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.moved" readonly type: "session.next.moved"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1148,7 +1148,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.renamed" readonly type: "session.next.renamed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly timestamp: number; readonly sessionID: string; readonly title: string } readonly data: { readonly timestamp: number; readonly sessionID: string; readonly title: string }
} }
@@ -1156,7 +1156,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.forked" readonly type: "session.next.forked"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1169,7 +1169,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.prompted" readonly type: "session.next.prompted"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1196,7 +1196,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.prompt.admitted" readonly type: "session.next.prompt.admitted"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1223,7 +1223,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.context.updated" readonly type: "session.next.context.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1236,7 +1236,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.synthetic" readonly type: "session.next.synthetic"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1251,7 +1251,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.skill.activated" readonly type: "session.next.skill.activated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1265,7 +1265,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.shell.started" readonly type: "session.next.shell.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1279,7 +1279,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.shell.ended" readonly type: "session.next.shell.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1292,7 +1292,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.step.started" readonly type: "session.next.step.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1307,7 +1307,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.step.ended" readonly type: "session.next.step.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1329,7 +1329,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.step.failed" readonly type: "session.next.step.failed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1342,7 +1342,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.text.started" readonly type: "session.next.text.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1355,7 +1355,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.text.ended" readonly type: "session.next.text.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1365,11 +1365,40 @@ export type SessionLogOutput =
readonly text: string readonly text: string
} }
} }
| {
readonly id: string
readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.reasoning.started"
readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: {
readonly timestamp: number
readonly sessionID: string
readonly assistantMessageID: string
readonly reasoningID: string
readonly providerMetadata?: { readonly [x: string]: { readonly [x: string]: unknown } }
}
}
| {
readonly id: string
readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.reasoning.ended"
readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: {
readonly timestamp: number
readonly sessionID: string
readonly assistantMessageID: string
readonly reasoningID: string
readonly text: string
readonly providerMetadata?: { readonly [x: string]: { readonly [x: string]: unknown } }
}
}
| { | {
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.input.started" readonly type: "session.next.tool.input.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1383,7 +1412,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.input.ended" readonly type: "session.next.tool.input.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1397,7 +1426,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.called" readonly type: "session.next.tool.called"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1416,7 +1445,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.progress" readonly type: "session.next.tool.progress"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1434,7 +1463,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.success" readonly type: "session.next.tool.success"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1458,7 +1487,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.failed" readonly type: "session.next.tool.failed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1473,40 +1502,11 @@ export type SessionLogOutput =
} }
} }
} }
| {
readonly id: string
readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.reasoning.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: {
readonly timestamp: number
readonly sessionID: string
readonly assistantMessageID: string
readonly reasoningID: string
readonly providerMetadata?: { readonly [x: string]: { readonly [x: string]: unknown } }
}
}
| {
readonly id: string
readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.reasoning.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: {
readonly timestamp: number
readonly sessionID: string
readonly assistantMessageID: string
readonly reasoningID: string
readonly text: string
readonly providerMetadata?: { readonly [x: string]: { readonly [x: string]: unknown } }
}
}
| { | {
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.retried" readonly type: "session.next.retried"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1526,7 +1526,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.compaction.started" readonly type: "session.next.compaction.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1539,7 +1539,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.compaction.ended" readonly type: "session.next.compaction.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1554,7 +1554,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.revert.staged" readonly type: "session.next.revert.staged"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -1578,7 +1578,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.revert.cleared" readonly type: "session.next.revert.cleared"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly timestamp: number; readonly sessionID: string } readonly data: { readonly timestamp: number; readonly sessionID: string }
} }
@@ -1586,7 +1586,7 @@ export type SessionLogOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.revert.committed" readonly type: "session.next.revert.committed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly timestamp: number; readonly sessionID: string; readonly messageID: string } readonly data: { readonly timestamp: number; readonly sessionID: string; readonly messageID: string }
} }
@@ -3773,7 +3773,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "models-dev.refreshed" readonly type: "models-dev.refreshed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: {} readonly data: {}
} }
@@ -3781,7 +3780,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "integration.updated" readonly type: "integration.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: {} readonly data: {}
} }
@@ -3789,7 +3787,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "integration.connection.updated" readonly type: "integration.connection.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly integrationID: string } readonly data: { readonly integrationID: string }
} }
@@ -3797,7 +3794,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "catalog.updated" readonly type: "catalog.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: {} readonly data: {}
} }
@@ -3805,7 +3801,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "agent.updated" readonly type: "agent.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: {} readonly data: {}
} }
@@ -3813,7 +3808,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.created" readonly type: "session.created"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID: string readonly sessionID: string
@@ -3874,7 +3869,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.updated" readonly type: "session.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID: string readonly sessionID: string
@@ -3935,7 +3930,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.deleted" readonly type: "session.deleted"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID: string readonly sessionID: string
@@ -3996,7 +3991,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "message.updated" readonly type: "message.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID: string readonly sessionID: string
@@ -4100,7 +4095,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "message.removed" readonly type: "message.removed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly sessionID: string; readonly messageID: string } readonly data: { readonly sessionID: string; readonly messageID: string }
} }
@@ -4108,7 +4103,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "message.part.updated" readonly type: "message.part.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID: string readonly sessionID: string
@@ -4346,7 +4341,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "message.part.removed" readonly type: "message.part.removed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly sessionID: string; readonly messageID: string; readonly partID: string } readonly data: { readonly sessionID: string; readonly messageID: string; readonly partID: string }
} }
@@ -4354,7 +4349,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.agent.switched" readonly type: "session.next.agent.switched"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4367,7 +4362,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.model.switched" readonly type: "session.next.model.switched"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4380,7 +4375,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.moved" readonly type: "session.next.moved"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4393,7 +4388,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.renamed" readonly type: "session.next.renamed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly timestamp: number; readonly sessionID: string; readonly title: string } readonly data: { readonly timestamp: number; readonly sessionID: string; readonly title: string }
} }
@@ -4401,7 +4396,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.forked" readonly type: "session.next.forked"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4414,7 +4409,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.prompted" readonly type: "session.next.prompted"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4441,7 +4436,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.prompt.admitted" readonly type: "session.next.prompt.admitted"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4468,7 +4463,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.execution.settled" readonly type: "session.next.execution.settled"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4481,7 +4475,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.context.updated" readonly type: "session.next.context.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4494,7 +4488,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.synthetic" readonly type: "session.next.synthetic"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4509,7 +4503,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.skill.activated" readonly type: "session.next.skill.activated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4523,7 +4517,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.shell.started" readonly type: "session.next.shell.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4537,7 +4531,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.shell.ended" readonly type: "session.next.shell.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4550,7 +4544,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.step.started" readonly type: "session.next.step.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4565,7 +4559,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.step.ended" readonly type: "session.next.step.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4587,7 +4581,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.step.failed" readonly type: "session.next.step.failed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4600,7 +4594,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.text.started" readonly type: "session.next.text.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4613,7 +4607,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.text.delta" readonly type: "session.next.text.delta"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4627,7 +4620,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.text.ended" readonly type: "session.next.text.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4641,7 +4634,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.reasoning.started" readonly type: "session.next.reasoning.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4655,7 +4648,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.reasoning.delta" readonly type: "session.next.reasoning.delta"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4669,7 +4661,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.reasoning.ended" readonly type: "session.next.reasoning.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4684,7 +4676,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.input.started" readonly type: "session.next.tool.input.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4698,7 +4690,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.input.delta" readonly type: "session.next.tool.input.delta"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4712,7 +4703,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.input.ended" readonly type: "session.next.tool.input.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4726,7 +4717,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.called" readonly type: "session.next.tool.called"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4745,7 +4736,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.progress" readonly type: "session.next.tool.progress"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4763,7 +4754,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.success" readonly type: "session.next.tool.success"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4787,7 +4778,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.tool.failed" readonly type: "session.next.tool.failed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4806,7 +4797,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.retried" readonly type: "session.next.retried"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4826,7 +4817,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.compaction.started" readonly type: "session.next.compaction.started"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4839,7 +4830,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.compaction.delta" readonly type: "session.next.compaction.delta"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4852,7 +4842,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.compaction.ended" readonly type: "session.next.compaction.ended"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4867,7 +4857,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.revert.staged" readonly type: "session.next.revert.staged"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly timestamp: number readonly timestamp: number
@@ -4891,7 +4881,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.revert.cleared" readonly type: "session.next.revert.cleared"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly timestamp: number; readonly sessionID: string } readonly data: { readonly timestamp: number; readonly sessionID: string }
} }
@@ -4899,7 +4889,7 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.next.revert.committed" readonly type: "session.next.revert.committed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly timestamp: number; readonly sessionID: string; readonly messageID: string } readonly data: { readonly timestamp: number; readonly sessionID: string; readonly messageID: string }
} }
@@ -4907,7 +4897,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "file.edited" readonly type: "file.edited"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly file: string } readonly data: { readonly file: string }
} }
@@ -4915,7 +4904,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "reference.updated" readonly type: "reference.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: {} readonly data: {}
} }
@@ -4923,7 +4911,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "permission.v2.asked" readonly type: "permission.v2.asked"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly id: string readonly id: string
@@ -4939,7 +4926,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "permission.v2.replied" readonly type: "permission.v2.replied"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID: string readonly sessionID: string
@@ -4951,7 +4937,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "plugin.added" readonly type: "plugin.added"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly id: string } readonly data: { readonly id: string }
} }
@@ -4959,7 +4944,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "project.directories.updated" readonly type: "project.directories.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly projectID: string } readonly data: { readonly projectID: string }
} }
@@ -4967,7 +4951,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "command.updated" readonly type: "command.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: {} readonly data: {}
} }
@@ -4975,7 +4958,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "skill.updated" readonly type: "skill.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: {} readonly data: {}
} }
@@ -4983,7 +4965,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "file.watcher.updated" readonly type: "file.watcher.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly file: string; readonly event: "add" | "change" | "unlink" } readonly data: { readonly file: string; readonly event: "add" | "change" | "unlink" }
} }
@@ -4991,7 +4972,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "pty.created" readonly type: "pty.created"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly info: { readonly info: {
@@ -5010,7 +4990,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "pty.updated" readonly type: "pty.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly info: { readonly info: {
@@ -5029,7 +5008,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "pty.exited" readonly type: "pty.exited"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly id: string; readonly exitCode: number } readonly data: { readonly id: string; readonly exitCode: number }
} }
@@ -5037,7 +5015,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "pty.deleted" readonly type: "pty.deleted"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly id: string } readonly data: { readonly id: string }
} }
@@ -5045,7 +5022,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "shell.created" readonly type: "shell.created"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly info: { readonly info: {
@@ -5066,7 +5042,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "shell.exited" readonly type: "shell.exited"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly id: string readonly id: string
@@ -5078,7 +5053,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "shell.deleted" readonly type: "shell.deleted"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly id: string } readonly data: { readonly id: string }
} }
@@ -5086,7 +5060,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "question.v2.asked" readonly type: "question.v2.asked"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly id: string readonly id: string
@@ -5105,7 +5078,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "question.v2.replied" readonly type: "question.v2.replied"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID: string readonly sessionID: string
@@ -5117,7 +5089,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "question.v2.rejected" readonly type: "question.v2.rejected"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly sessionID: string; readonly requestID: string } readonly data: { readonly sessionID: string; readonly requestID: string }
} }
@@ -5125,7 +5096,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "form.created" readonly type: "form.created"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly form: readonly form:
@@ -5240,7 +5210,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "form.replied" readonly type: "form.replied"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly id: string readonly id: string
@@ -5252,7 +5221,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "form.cancelled" readonly type: "form.cancelled"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly id: string; readonly sessionID: string } readonly data: { readonly id: string; readonly sessionID: string }
} }
@@ -5260,7 +5228,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "todo.updated" readonly type: "todo.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID: string readonly sessionID: string
@@ -5271,7 +5238,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.status" readonly type: "session.status"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID: string readonly sessionID: string
@@ -5298,7 +5264,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.idle" readonly type: "session.idle"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly sessionID: string } readonly data: { readonly sessionID: string }
} }
@@ -5306,7 +5271,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "tui.prompt.append" readonly type: "tui.prompt.append"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly text: string } readonly data: { readonly text: string }
} }
@@ -5314,7 +5278,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "tui.command.execute" readonly type: "tui.command.execute"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly command: readonly command:
@@ -5342,7 +5305,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "tui.toast.show" readonly type: "tui.toast.show"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly title?: string readonly title?: string
@@ -5355,7 +5317,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "tui.session.select" readonly type: "tui.session.select"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly sessionID: string } readonly data: { readonly sessionID: string }
} }
@@ -5363,7 +5324,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "installation.updated" readonly type: "installation.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly version: string } readonly data: { readonly version: string }
} }
@@ -5371,7 +5331,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "installation.update-available" readonly type: "installation.update-available"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly version: string } readonly data: { readonly version: string }
} }
@@ -5379,7 +5338,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "vcs.branch.updated" readonly type: "vcs.branch.updated"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly branch?: string } readonly data: { readonly branch?: string }
} }
@@ -5387,7 +5345,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "mcp.status.changed" readonly type: "mcp.status.changed"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly server: string } readonly data: { readonly server: string }
} }
@@ -5395,7 +5352,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "permission.asked" readonly type: "permission.asked"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly id: string readonly id: string
@@ -5411,7 +5367,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "permission.replied" readonly type: "permission.replied"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID: string readonly sessionID: string
@@ -5423,7 +5378,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "question.asked" readonly type: "question.asked"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly id: string readonly id: string
@@ -5442,7 +5396,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "question.replied" readonly type: "question.replied"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID: string readonly sessionID: string
@@ -5454,7 +5407,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "question.rejected" readonly type: "question.rejected"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly sessionID: string; readonly requestID: string } readonly data: { readonly sessionID: string; readonly requestID: string }
} }
@@ -5462,7 +5414,6 @@ export type EventSubscribeOutput =
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } readonly metadata?: { readonly [x: string]: unknown }
readonly type: "session.error" readonly type: "session.error"
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly location?: { readonly directory: string; readonly workspaceID?: string }
readonly data: { readonly data: {
readonly sessionID?: string | undefined readonly sessionID?: string | undefined
@@ -5503,7 +5454,6 @@ export type EventSubscribeOutput =
| { | {
readonly id: string readonly id: string
readonly metadata?: { readonly [x: string]: unknown } | undefined readonly metadata?: { readonly [x: string]: unknown } | undefined
readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } | undefined
readonly location?: { readonly directory: string; readonly workspaceID?: string } | undefined readonly location?: { readonly directory: string; readonly workspaceID?: string } | undefined
readonly type: "server.connected" readonly type: "server.connected"
readonly data: {} readonly data: {}
+2 -1
View File
@@ -92,8 +92,9 @@ export class SubscriberOverflowError extends Schema.TaggedErrorClass<SubscriberO
{ capacity: Schema.Int }, { capacity: Schema.Int },
) {} ) {}
export const define = Event.define
export const versionedType = Event.versionedType export const versionedType = Event.versionedType
export const durable = Event.durable
export const ephemeral = Event.ephemeral
export interface PublishOptions { export interface PublishOptions {
readonly id?: ID readonly id?: ID
+2 -2
View File
@@ -25,7 +25,7 @@ import type { DeepMutable } from "../schema"
import { Slug } from "../util/slug" import { Slug } from "../util/slug"
type DatabaseService = Database.Interface["db"] type DatabaseService = Database.Interface["db"]
type MessageEvent = Exclude<SessionEvent.Event, typeof SessionEvent.Forked.Type> type MessageEvent = Exclude<SessionEvent.DurableEvent, typeof SessionEvent.Forked.Type>
const decodeMessage = Schema.decodeUnknownSync(SessionMessage.Message) const decodeMessage = Schema.decodeUnknownSync(SessionMessage.Message)
const encodeMessage = Schema.encodeSync(SessionMessage.Message) const encodeMessage = Schema.encodeSync(SessionMessage.Message)
@@ -417,7 +417,7 @@ function run(db: DatabaseService, event: MessageEvent) {
}) })
} }
function insertMessage(db: DatabaseService, event: SessionEvent.Event, message: SessionMessage.Message) { function insertMessage(db: DatabaseService, event: SessionEvent.DurableEvent, message: SessionMessage.Message) {
if (event.durable === undefined) return Effect.die("Durable Session event is missing aggregate sequence") if (event.durable === undefined) return Effect.die("Durable Session event is missing aggregate sequence")
const encoded = encodeMessage(message) const encoded = encodeMessage(message)
const { id, type, ...data } = encoded const { id, type, ...data } = encoded
+7 -7
View File
@@ -22,14 +22,14 @@ const locationLayer = Layer.succeed(
location({ directory: AbsolutePath.make("project"), workspaceID: WorkspaceV2.ID.make("wrk_test") }), location({ directory: AbsolutePath.make("project"), workspaceID: WorkspaceV2.ID.make("wrk_test") }),
), ),
) )
const Message = EventV2.define({ const Message = EventV2.ephemeral({
type: "test.message", type: "test.message",
schema: { schema: {
text: Schema.String, text: Schema.String,
}, },
}) })
const SyncMessage = EventV2.define({ const SyncMessage = EventV2.durable({
type: "test.sync", type: "test.sync",
durable: { durable: {
version: 1, version: 1,
@@ -41,7 +41,7 @@ const SyncMessage = EventV2.define({
}, },
}) })
const SyncSent = EventV2.define({ const SyncSent = EventV2.durable({
type: "test.sent", type: "test.sent",
durable: { durable: {
version: 1, version: 1,
@@ -53,14 +53,14 @@ const SyncSent = EventV2.define({
}, },
}) })
const GlobalMessage = EventV2.define({ const GlobalMessage = EventV2.ephemeral({
type: "test.global", type: "test.global",
schema: { schema: {
text: Schema.String, text: Schema.String,
}, },
}) })
const VersionedMessage = EventV2.define({ const VersionedMessage = EventV2.durable({
type: "test.versioned", type: "test.versioned",
durable: { durable: {
version: 2, version: 2,
@@ -129,12 +129,12 @@ describe("EventV2", () => {
it.effect("selects the latest durable definition independent of declaration order", () => it.effect("selects the latest durable definition independent of declaration order", () =>
Effect.sync(() => { Effect.sync(() => {
const latest = EventV2.define({ const latest = EventV2.durable({
type: "test.out-of-order", type: "test.out-of-order",
durable: { version: 2, aggregate: "id" }, durable: { version: 2, aggregate: "id" },
schema: { id: Schema.String }, schema: { id: Schema.String },
}) })
const historical = EventV2.define({ const historical = EventV2.durable({
type: "test.out-of-order", type: "test.out-of-order",
durable: { version: 1, aggregate: "id" }, durable: { version: 1, aggregate: "id" },
schema: { id: Schema.String }, schema: { id: Schema.String },
+1 -1
View File
@@ -78,7 +78,7 @@ describe("SessionV2.log", () => {
it.effect("reads across undecodable gaps in aggregate order and marks the true log position", () => it.effect("reads across undecodable gaps in aggregate order and marks the true log position", () =>
Effect.gen(function* () { Effect.gen(function* () {
const GapEvent = EventV2.define({ const GapEvent = EventV2.durable({
type: "test.session.log.gap", type: "test.session.log.gap",
durable: { aggregate: "sessionID", version: 1 }, durable: { aggregate: "sessionID", version: 1 },
schema: { sessionID: SessionV2.ID, value: Schema.String }, schema: { sessionID: SessionV2.ID, value: Schema.String },
@@ -25,6 +25,7 @@ function prompted(messageID: string): V2Event {
return { return {
id: "evt_prompted", id: "evt_prompted",
type: "session.next.prompted", type: "session.next.prompted",
durable: { aggregateID: "ses_1", seq: 0, version: 1 },
data: { timestamp: 1, sessionID: "ses_1", messageID, prompt: { text: "hello" }, delivery: "steer" }, data: { timestamp: 1, sessionID: "ses_1", messageID, prompt: { text: "hello" }, delivery: "steer" },
} }
} }
@@ -39,11 +40,7 @@ function settled(outcome: "success" | "interrupted" = "success"): V2Event {
// Runs one non-interactive prompt against a mocked SDK. `turn` produces the // Runs one non-interactive prompt against a mocked SDK. `turn` produces the
// live events the prompt admission triggers, keyed by the generated message ID. // live events the prompt admission triggers, keyed by the generated message ID.
async function run(input: { async function run(input: { turn: (messageID: string) => V2Event[]; pendingForms?: FormInfo[]; attached?: boolean }) {
turn: (messageID: string) => V2Event[]
pendingForms?: FormInfo[]
attached?: boolean
}) {
const sdk = new OpencodeClient() const sdk = new OpencodeClient()
const values: V2Event[] = [{ id: "evt_connected", type: "server.connected", data: {} }] const values: V2Event[] = [{ id: "evt_connected", type: "server.connected", data: {} }]
let wake: (() => void) | undefined let wake: (() => void) | undefined
@@ -64,8 +61,9 @@ async function run(input: {
) )
spyOn(sdk.v2.session.permission, "list").mockImplementation(() => ok({ data: [] }) as never) spyOn(sdk.v2.session.permission, "list").mockImplementation(() => ok({ data: [] }) as never)
spyOn(sdk.v2.session.question, "list").mockImplementation(() => ok({ data: [] }) as never) spyOn(sdk.v2.session.question, "list").mockImplementation(() => ok({ data: [] }) as never)
spyOn(sdk.v2.session.form, "list").mockImplementation((request) => spyOn(sdk.v2.session.form, "list").mockImplementation(
ok({ data: input.pendingForms?.filter((item) => item.sessionID === request.sessionID) ?? [] }) as never, (request) =>
ok({ data: input.pendingForms?.filter((item) => item.sessionID === request.sessionID) ?? [] }) as never,
) )
spyOn(sdk.v2.session.form, "cancel").mockImplementation(() => ok(undefined) as never) spyOn(sdk.v2.session.form, "cancel").mockImplementation(() => ok(undefined) as never)
spyOn(sdk.v2.session, "prompt").mockImplementation((request) => { spyOn(sdk.v2.session, "prompt").mockImplementation((request) => {
@@ -53,6 +53,10 @@ function connected(id = "evt_connected") {
return { id, type: "server.connected", data: {} } satisfies RunV2Event return { id, type: "server.connected", data: {} } satisfies RunV2Event
} }
function durable(sessionID: string, seq = 0, version = 1) {
return { aggregateID: sessionID, seq, version }
}
function footer() { function footer() {
const commits: StreamCommit[] = [] const commits: StreamCommit[] = []
const events: FooterEvent[] = [] const events: FooterEvent[] = []
@@ -94,7 +98,10 @@ function sdk(input: {
const client = new OpencodeClient() const client = new OpencodeClient()
let subscription = 0 let subscription = 0
spyOn(client.v2.event, "subscribe").mockImplementation( spyOn(client.v2.event, "subscribe").mockImplementation(
() => Promise.resolve({ stream: input.streams[subscription++]?.stream ?? feed().stream }) as ReturnType<typeof client.v2.event.subscribe>, () =>
Promise.resolve({ stream: input.streams[subscription++]?.stream ?? feed().stream }) as ReturnType<
typeof client.v2.event.subscribe
>,
) )
spyOn(client.v2.session, "messages").mockImplementation((request) => spyOn(client.v2.session, "messages").mockImplementation((request) =>
ok({ ok({
@@ -193,32 +200,33 @@ describe("V2 mini transport", () => {
}) })
while (!admitted) await Bun.sleep(0) while (!admitted) await Bun.sleep(0)
events.push({ events.push({
id: "evt_prompted", id: "evt_prompted",
type: "session.next.prompted", type: "session.next.prompted",
data: { durable: durable("ses_1"),
timestamp: 2, data: {
sessionID: "ses_1", timestamp: 2,
messageID: "msg_prompt", sessionID: "ses_1",
prompt: { text: "hello" }, messageID: "msg_prompt",
delivery: "steer", prompt: { text: "hello" },
}, delivery: "steer",
}) },
events.push({ })
id: "evt_text", events.push({
type: "session.next.text.delta", id: "evt_text",
data: { type: "session.next.text.delta",
timestamp: 3, data: {
sessionID: "ses_1", timestamp: 3,
assistantMessageID: "msg_assistant", sessionID: "ses_1",
textID: "txt_1", assistantMessageID: "msg_assistant",
delta: "answer", textID: "txt_1",
}, delta: "answer",
}) },
events.push({ })
id: "evt_settled", events.push({
type: "session.next.execution.settled", id: "evt_settled",
data: { timestamp: 4, sessionID: "ses_1", outcome: "success" }, type: "session.next.execution.settled",
}) data: { timestamp: 4, sessionID: "ses_1", outcome: "success" },
})
await turn await turn
expect(ui.commits.map((item) => item.text)).toEqual(["previous prompt", "answer"]) expect(ui.commits.map((item) => item.text)).toEqual(["previous prompt", "answer"])
@@ -245,9 +253,7 @@ describe("V2 mini transport", () => {
limits: () => ({}), limits: () => ({}),
footer: ui.api, footer: ui.api,
}) })
let request: let request: Parameters<OpencodeClient["v2"]["session"]["prompt"]>[0] | undefined
| Parameters<OpencodeClient["v2"]["session"]["prompt"]>[0]
| undefined
// The generated method has conditional return types for throwOnError; this mock represents the successful branch. // The generated method has conditional return types for throwOnError; this mock represents the successful branch.
// @ts-expect-error successful SDK response is valid for both modes at runtime // @ts-expect-error successful SDK response is valid for both modes at runtime
spyOn(client.v2.session, "prompt").mockImplementation((input) => { spyOn(client.v2.session, "prompt").mockImplementation((input) => {
@@ -256,6 +262,7 @@ describe("V2 mini transport", () => {
events.push({ events.push({
id: "evt_prompted", id: "evt_prompted",
type: "session.next.prompted", type: "session.next.prompted",
durable: durable("ses_1"),
data: { data: {
timestamp: 2, timestamp: 2,
sessionID: "ses_1", sessionID: "ses_1",
@@ -341,9 +348,7 @@ describe("V2 mini transport", () => {
limits: () => ({}), limits: () => ({}),
footer: ui.api, footer: ui.api,
}) })
let request: let request: Parameters<OpencodeClient["v2"]["session"]["prompt"]>[0] | undefined
| Parameters<OpencodeClient["v2"]["session"]["prompt"]>[0]
| undefined
// The generated method has conditional return types for throwOnError; this mock represents the successful branch. // The generated method has conditional return types for throwOnError; this mock represents the successful branch.
// @ts-expect-error successful SDK response is valid for both modes at runtime // @ts-expect-error successful SDK response is valid for both modes at runtime
spyOn(client.v2.session, "prompt").mockImplementation((input) => { spyOn(client.v2.session, "prompt").mockImplementation((input) => {
@@ -352,6 +357,7 @@ describe("V2 mini transport", () => {
events.push({ events.push({
id: "evt_prompted", id: "evt_prompted",
type: "session.next.prompted", type: "session.next.prompted",
durable: durable("ses_1"),
data: { data: {
timestamp: 2, timestamp: 2,
sessionID: "ses_1", sessionID: "ses_1",
@@ -440,9 +446,7 @@ describe("V2 mini transport", () => {
limits: () => ({}), limits: () => ({}),
footer: ui.api, footer: ui.api,
}) })
let request: let request: Parameters<OpencodeClient["v2"]["session"]["prompt"]>[0] | undefined
| Parameters<OpencodeClient["v2"]["session"]["prompt"]>[0]
| undefined
// The generated method has conditional return types for throwOnError; this mock represents the successful branch. // The generated method has conditional return types for throwOnError; this mock represents the successful branch.
// @ts-expect-error successful SDK response is valid for both modes at runtime // @ts-expect-error successful SDK response is valid for both modes at runtime
spyOn(client.v2.session, "prompt").mockImplementation((input) => { spyOn(client.v2.session, "prompt").mockImplementation((input) => {
@@ -451,6 +455,7 @@ describe("V2 mini transport", () => {
events.push({ events.push({
id: "evt_prompted", id: "evt_prompted",
type: "session.next.prompted", type: "session.next.prompted",
durable: durable("ses_1"),
data: { data: {
timestamp: 2, timestamp: 2,
sessionID: "ses_1", sessionID: "ses_1",
@@ -593,7 +598,9 @@ describe("V2 mini transport", () => {
const messageID = request.id ?? "msg_prompt" const messageID = request.id ?? "msg_prompt"
const prompt = request.prompt ?? { text: "" } const prompt = request.prompt ?? { text: "" }
admitted = true admitted = true
return ok({ data: { admittedSeq: 1, id: messageID, sessionID: "ses_1", prompt, delivery: "steer" as const, timeCreated: 2 } }) return ok({
data: { admittedSeq: 1, id: messageID, sessionID: "ses_1", prompt, delivery: "steer" as const, timeCreated: 2 },
})
}) })
const turn = transport.runPromptTurn({ const turn = transport.runPromptTurn({
@@ -663,7 +670,9 @@ describe("V2 mini transport", () => {
const messageID = request.id ?? "msg_prompt" const messageID = request.id ?? "msg_prompt"
const prompt = request.prompt ?? { text: "" } const prompt = request.prompt ?? { text: "" }
admitted = true admitted = true
return ok({ data: { admittedSeq: 1, id: messageID, sessionID: "ses_1", prompt, delivery: "steer" as const, timeCreated: 2 } }) return ok({
data: { admittedSeq: 1, id: messageID, sessionID: "ses_1", prompt, delivery: "steer" as const, timeCreated: 2 },
})
}) })
const turn = transport.runPromptTurn({ const turn = transport.runPromptTurn({
@@ -805,6 +814,7 @@ describe("V2 mini transport", () => {
events.push({ events.push({
id: "evt_reasoning", id: "evt_reasoning",
type: "session.next.reasoning.ended", type: "session.next.reasoning.ended",
durable: durable("ses_1"),
data: { data: {
timestamp: 3, timestamp: 3,
sessionID: "ses_1", sessionID: "ses_1",
@@ -841,7 +851,9 @@ describe("V2 mini transport", () => {
const messageID = request.id ?? "msg_prompt" const messageID = request.id ?? "msg_prompt"
const prompt = request.prompt ?? { text: "" } const prompt = request.prompt ?? { text: "" }
admitted = true admitted = true
return ok({ data: { admittedSeq: 1, id: messageID, sessionID: "ses_1", prompt, delivery: "steer" as const, timeCreated: 2 } }) return ok({
data: { admittedSeq: 1, id: messageID, sessionID: "ses_1", prompt, delivery: "steer" as const, timeCreated: 2 },
})
}) })
const interrupted = spyOn(client.v2.session, "interrupt").mockImplementation(() => ok(undefined)) const interrupted = spyOn(client.v2.session, "interrupt").mockImplementation(() => ok(undefined))
@@ -896,7 +908,9 @@ describe("V2 mini transport", () => {
const messageID = request.id ?? "msg_prompt" const messageID = request.id ?? "msg_prompt"
const prompt = request.prompt ?? { text: "" } const prompt = request.prompt ?? { text: "" }
admitted = true admitted = true
return ok({ data: { admittedSeq: 1, id: messageID, sessionID: "ses_1", prompt, delivery: "steer" as const, timeCreated: 2 } }) return ok({
data: { admittedSeq: 1, id: messageID, sessionID: "ses_1", prompt, delivery: "steer" as const, timeCreated: 2 },
})
}) })
const turn = transport.runPromptTurn({ const turn = transport.runPromptTurn({
@@ -911,6 +925,7 @@ describe("V2 mini transport", () => {
events.push({ events.push({
id: "evt_prompted", id: "evt_prompted",
type: "session.next.prompted", type: "session.next.prompted",
durable: durable("ses_1"),
data: { data: {
timestamp: 2, timestamp: 2,
sessionID: "ses_1", sessionID: "ses_1",
@@ -952,7 +967,9 @@ describe("V2 mini transport", () => {
const messageID = request.id ?? "msg_prompt" const messageID = request.id ?? "msg_prompt"
const prompt = request.prompt ?? { text: "" } const prompt = request.prompt ?? { text: "" }
admitted = true admitted = true
return ok({ data: { admittedSeq: 1, id: messageID, sessionID: "ses_1", prompt, delivery: "steer" as const, timeCreated: 2 } }) return ok({
data: { admittedSeq: 1, id: messageID, sessionID: "ses_1", prompt, delivery: "steer" as const, timeCreated: 2 },
})
}) })
const interrupted = spyOn(client.v2.session, "interrupt").mockImplementation(() => ok(undefined)) const interrupted = spyOn(client.v2.session, "interrupt").mockImplementation(() => ok(undefined))
const controller = new AbortController() const controller = new AbortController()
@@ -969,6 +986,7 @@ describe("V2 mini transport", () => {
events.push({ events.push({
id: "evt_prompted", id: "evt_prompted",
type: "session.next.prompted", type: "session.next.prompted",
durable: durable("ses_1"),
data: { data: {
timestamp: 2, timestamp: 2,
sessionID: "ses_1", sessionID: "ses_1",
@@ -1031,13 +1049,13 @@ describe("V2 mini transport", () => {
limits: () => ({}), limits: () => ({}),
footer: ui.api, footer: ui.api,
}) })
const states = () => const states = () => ui.events.flatMap((event) => (event.type === "stream.subagent" ? [event.state] : []))
ui.events.flatMap((event) => (event.type === "stream.subagent" ? [event.state] : []))
transport.selectSubagent("ses_child") transport.selectSubagent("ses_child")
events.push({ events.push({
id: "evt_child_step", id: "evt_child_step",
type: "session.next.step.started", type: "session.next.step.started",
durable: durable("ses_child"),
data: { data: {
timestamp: 2, timestamp: 2,
sessionID: "ses_child", sessionID: "ses_child",
@@ -1107,13 +1125,13 @@ describe("V2 mini transport", () => {
limits: () => ({}), limits: () => ({}),
footer: ui.api, footer: ui.api,
}) })
const states = () => const states = () => ui.events.flatMap((event) => (event.type === "stream.subagent" ? [event.state] : []))
ui.events.flatMap((event) => (event.type === "stream.subagent" ? [event.state] : []))
// Both events arrive while session.get is still in flight. // Both events arrive while session.get is still in flight.
events.push({ events.push({
id: "evt_child_step", id: "evt_child_step",
type: "session.next.step.started", type: "session.next.step.started",
durable: durable("ses_child"),
data: { data: {
timestamp: 2, timestamp: 2,
sessionID: "ses_child", sessionID: "ses_child",
@@ -1165,13 +1183,13 @@ describe("V2 mini transport", () => {
limits: () => ({}), limits: () => ({}),
footer: ui.api, footer: ui.api,
}) })
const states = () => const states = () => ui.events.flatMap((event) => (event.type === "stream.subagent" ? [event.state] : []))
ui.events.flatMap((event) => (event.type === "stream.subagent" ? [event.state] : []))
// Child event arrives first and gets buffered behind the gated session.get. // Child event arrives first and gets buffered behind the gated session.get.
events.push({ events.push({
id: "evt_child_step", id: "evt_child_step",
type: "session.next.step.started", type: "session.next.step.started",
durable: durable("ses_child"),
data: { data: {
timestamp: 2, timestamp: 2,
sessionID: "ses_child", sessionID: "ses_child",
@@ -1184,6 +1202,7 @@ describe("V2 mini transport", () => {
events.push({ events.push({
id: "evt_parent_call", id: "evt_parent_call",
type: "session.next.tool.called", type: "session.next.tool.called",
durable: durable("ses_1"),
data: { data: {
timestamp: 3, timestamp: 3,
sessionID: "ses_1", sessionID: "ses_1",
@@ -1197,6 +1216,7 @@ describe("V2 mini transport", () => {
events.push({ events.push({
id: "evt_parent_success", id: "evt_parent_success",
type: "session.next.tool.success", type: "session.next.tool.success",
durable: durable("ses_1", 1),
data: { data: {
timestamp: 4, timestamp: 4,
sessionID: "ses_1", sessionID: "ses_1",
@@ -9,6 +9,10 @@ import { SessionEvent } from "@opencode-ai/core/session/event"
import { SessionMessageUpdater } from "@opencode-ai/core/session/message-updater" import { SessionMessageUpdater } from "@opencode-ai/core/session/message-updater"
import { SessionMessage } from "@opencode-ai/core/session/message" import { SessionMessage } from "@opencode-ai/core/session/message"
function durable(sessionID: SessionID, seq = 0, version = 1) {
return { aggregateID: sessionID, seq: EventV2.Seq.make(seq), version: EventV2.Version.make(version) }
}
test.skip("step snapshots carry over to assistant messages", () => { test.skip("step snapshots carry over to assistant messages", () => {
const state: SessionMessageUpdater.MemoryState = { messages: [] } const state: SessionMessageUpdater.MemoryState = { messages: [] }
const sessionID = SessionID.make("session") const sessionID = SessionID.make("session")
@@ -18,6 +22,7 @@ test.skip("step snapshots carry over to assistant messages", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), { SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(), id: EventV2.ID.create(),
type: "session.next.step.started", type: "session.next.step.started",
durable: durable(sessionID),
data: { data: {
sessionID, sessionID,
assistantMessageID, assistantMessageID,
@@ -39,6 +44,7 @@ test.skip("step snapshots carry over to assistant messages", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), { SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(), id: EventV2.ID.create(),
type: "session.next.step.ended", type: "session.next.step.ended",
durable: durable(sessionID, 1, 2),
data: { data: {
sessionID, sessionID,
assistantMessageID, assistantMessageID,
@@ -71,6 +77,7 @@ test.skip("text ended populates assistant text content", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), { SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(), id: EventV2.ID.create(),
type: "session.next.step.started", type: "session.next.step.started",
durable: durable(sessionID),
data: { data: {
sessionID, sessionID,
assistantMessageID, assistantMessageID,
@@ -89,6 +96,7 @@ test.skip("text ended populates assistant text content", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), { SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(), id: EventV2.ID.create(),
type: "session.next.text.started", type: "session.next.text.started",
durable: durable(sessionID, 1),
data: { data: {
sessionID, sessionID,
assistantMessageID, assistantMessageID,
@@ -102,6 +110,7 @@ test.skip("text ended populates assistant text content", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), { SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(), id: EventV2.ID.create(),
type: "session.next.text.ended", type: "session.next.text.ended",
durable: durable(sessionID, 2),
data: { data: {
sessionID, sessionID,
assistantMessageID, assistantMessageID,
@@ -127,6 +136,7 @@ test.skip("tool completion stores completed timestamp", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), { SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(), id: EventV2.ID.create(),
type: "session.next.step.started", type: "session.next.step.started",
durable: durable(sessionID),
data: { data: {
sessionID, sessionID,
assistantMessageID, assistantMessageID,
@@ -145,6 +155,7 @@ test.skip("tool completion stores completed timestamp", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), { SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(), id: EventV2.ID.create(),
type: "session.next.tool.input.started", type: "session.next.tool.input.started",
durable: durable(sessionID, 1),
data: { data: {
sessionID, sessionID,
assistantMessageID, assistantMessageID,
@@ -159,6 +170,7 @@ test.skip("tool completion stores completed timestamp", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), { SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(), id: EventV2.ID.create(),
type: "session.next.tool.called", type: "session.next.tool.called",
durable: durable(sessionID, 2),
data: { data: {
sessionID, sessionID,
assistantMessageID, assistantMessageID,
@@ -175,6 +187,7 @@ test.skip("tool completion stores completed timestamp", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), { SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(), id: EventV2.ID.create(),
type: "session.next.tool.success", type: "session.next.tool.success",
durable: durable(sessionID, 3),
data: { data: {
sessionID, sessionID,
assistantMessageID, assistantMessageID,
@@ -205,6 +218,7 @@ test("compaction events reduce to compaction message only when completed", () =>
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), { SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id, id,
type: "session.next.compaction.started", type: "session.next.compaction.started",
durable: durable(sessionID),
data: { data: {
sessionID, sessionID,
messageID: compactionID, messageID: compactionID,
@@ -246,6 +260,7 @@ test("compaction events reduce to compaction message only when completed", () =>
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), { SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(), id: EventV2.ID.create(),
type: "session.next.compaction.ended", type: "session.next.compaction.ended",
durable: durable(sessionID, 1),
data: { data: {
sessionID, sessionID,
messageID: compactionID, messageID: compactionID,
-1
View File
@@ -9,7 +9,6 @@ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/un
const fields = { const fields = {
id: Event.ID, id: Event.ID,
metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)), metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
durable: Schema.optional(Schema.Struct({ aggregateID: Schema.String, seq: Event.Seq, version: Event.Version })),
location: Schema.optional(Location.Ref), location: Schema.optional(Location.Ref),
} }
+2 -2
View File
@@ -1,14 +1,14 @@
export * as Agent from "./agent.js" export * as Agent from "./agent.js"
import { Schema } from "effect" import { Schema } from "effect"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { Model } from "./model.js" import { Model } from "./model.js"
import { Permission } from "./permission.js" import { Permission } from "./permission.js"
import { Provider } from "./provider.js" import { Provider } from "./provider.js"
import { PositiveInt, statics } from "./schema.js" import { PositiveInt, statics } from "./schema.js"
const Updated = define({ type: "agent.updated", schema: {} }) const Updated = ephemeral({ type: "agent.updated", schema: {} })
export const ID = Schema.String.pipe(Schema.brand("AgentV2.ID")) export const ID = Schema.String.pipe(Schema.brand("AgentV2.ID"))
export type ID = typeof ID.Type export type ID = typeof ID.Type
+2 -2
View File
@@ -1,6 +1,6 @@
export * as Catalog from "./catalog.js" export * as Catalog from "./catalog.js"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
const Updated = define({ type: "catalog.updated", schema: {} }) const Updated = ephemeral({ type: "catalog.updated", schema: {} })
export const Event = { Updated, Definitions: inventory(Updated) } export const Event = { Updated, Definitions: inventory(Updated) }
+2 -2
View File
@@ -1,11 +1,11 @@
export * as Command from "./command.js" export * as Command from "./command.js"
import { Schema } from "effect" import { Schema } from "effect"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { Model } from "./model.js" import { Model } from "./model.js"
const Updated = define({ type: "command.updated", schema: {} }) const Updated = ephemeral({ type: "command.updated", schema: {} })
export interface Info extends Schema.Schema.Type<typeof Info> {} export interface Info extends Schema.Schema.Type<typeof Info> {}
export const Info = Schema.Struct({ export const Info = Schema.Struct({
@@ -5,11 +5,8 @@ import { SessionEvent } from "./session-event.js"
import { SessionV1 } from "./session-v1.js" import { SessionV1 } from "./session-v1.js"
export const SessionDurable = { export const SessionDurable = {
definitions: Event.durable(SessionEvent.DurableDefinitions), definitions: Event.durableMap(SessionEvent.Definitions),
schema: SessionEvent.Durable, schema: SessionEvent.Durable,
} as const } as const
export const Durable = Event.durable([ export const Durable = Event.durableMap([...SessionV1.Event.Definitions, ...SessionEvent.Definitions])
...SessionV1.Event.Definitions.filter((definition) => definition.durable !== undefined),
...SessionEvent.DurableDefinitions,
])
+6 -2
View File
@@ -36,8 +36,12 @@ import { VcsEvent } from "./vcs-event.js"
import { WorkspaceEvent } from "./workspace-event.js" import { WorkspaceEvent } from "./workspace-event.js"
import { WorktreeEvent } from "./worktree-event.js" import { WorktreeEvent } from "./worktree-event.js"
const sessionV1DurableDefinitions = SessionV1.Event.Definitions.filter((definition) => definition.durable !== undefined) const sessionV1DurableDefinitions = SessionV1.Event.Definitions.filter(
const sessionV1LiveDefinitions = SessionV1.Event.Definitions.filter((definition) => definition.durable === undefined) (definition) => definition.durability === "durable",
)
const sessionV1LiveDefinitions = SessionV1.Event.Definitions.filter(
(definition) => definition.durability === "ephemeral",
)
const coreDefinitions = Event.inventory(...sessionV1DurableDefinitions, ...SessionEvent.Definitions) const coreDefinitions = Event.inventory(...sessionV1DurableDefinitions, ...SessionEvent.Definitions)
+63 -19
View File
@@ -24,50 +24,70 @@ export type Seq = typeof Seq.Type
export const Version = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)).pipe(Schema.brand("Event.Version")) export const Version = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)).pipe(Schema.brand("Event.Version"))
export type Version = typeof Version.Type export type Version = typeof Version.Type
export type Definition< const DurableEnvelope = Schema.Struct({ aggregateID: Schema.String, seq: Seq, version: Version })
export type DurableEnvelope = typeof DurableEnvelope.Type
export type DurableDefinition<
Type extends string = string, Type extends string = string,
DataSchema extends Schema.Codec<unknown, unknown> = Schema.Codec<unknown, unknown>, DataSchema extends Schema.Codec<unknown, unknown> = Schema.Codec<unknown, unknown>,
> = Schema.Top & { > = Schema.Top & {
readonly type: Type readonly type: Type
readonly durable?: { readonly durability: "durable"
readonly durable: {
readonly version: number readonly version: number
readonly aggregate: string readonly aggregate: string
} }
readonly data: DataSchema readonly data: DataSchema
} }
export type EphemeralDefinition<
Type extends string = string,
DataSchema extends Schema.Codec<unknown, unknown> = Schema.Codec<unknown, unknown>,
> = Schema.Top & {
readonly type: Type
readonly durability: "ephemeral"
readonly durable?: never
readonly data: DataSchema
}
export type Definition<
Type extends string = string,
DataSchema extends Schema.Codec<unknown, unknown> = Schema.Codec<unknown, unknown>,
> = DurableDefinition<Type, DataSchema> | EphemeralDefinition<Type, DataSchema>
export type Data<D extends Definition> = Schema.Schema.Type<D["data"]> export type Data<D extends Definition> = Schema.Schema.Type<D["data"]>
export type Payload<D extends Definition = Definition> = { type PayloadBase<D extends Definition> = {
readonly id: ID readonly id: ID
readonly type: D["type"] readonly type: D["type"]
readonly data: Data<D> readonly data: Data<D>
readonly durable?: {
readonly aggregateID: string
readonly seq: Seq
readonly version: Version
}
readonly location?: Location.Ref readonly location?: Location.Ref
readonly metadata?: Record<string, unknown> readonly metadata?: Record<string, unknown>
} }
export function define< export type Payload<D extends Definition = Definition> = D extends DurableDefinition
const Type extends string, ? PayloadBase<D> & { readonly durable: DurableEnvelope }
const Fields extends Readonly<Record<PropertyKey, Schema.Codec<unknown, unknown>>>, : PayloadBase<D> & { readonly durable?: never }
>(input: {
type Input<Type extends string, Fields extends Readonly<Record<PropertyKey, Schema.Codec<unknown, unknown>>>> = {
readonly type: Type readonly type: Type
readonly durable?: { readonly durable?: {
readonly version: number readonly version: number
readonly aggregate: string readonly aggregate: string
} }
readonly schema: Fields readonly schema: Fields
}) { }
export function durable<
const Type extends string,
const Fields extends Readonly<Record<PropertyKey, Schema.Codec<unknown, unknown>>>,
>(input: Input<Type, Fields> & { readonly durable: NonNullable<Input<Type, Fields>["durable"]> }) {
const data = Schema.Struct(input.schema) const data = Schema.Struct(input.schema)
return Schema.Struct({ return Schema.Struct({
id: ID, id: ID,
metadata: optional(Schema.Record(Schema.String, Schema.Unknown)), metadata: optional(Schema.Record(Schema.String, Schema.Unknown)),
type: Schema.Literal(input.type), type: Schema.Literal(input.type),
durable: optional(Schema.Struct({ aggregateID: Schema.String, seq: Seq, version: Version })), durable: DurableEnvelope,
location: optional(Location.Ref), location: optional(Location.Ref),
data, data,
}) })
@@ -75,10 +95,34 @@ export function define<
.pipe( .pipe(
statics(() => ({ statics(() => ({
type: input.type, type: input.type,
...(input.durable === undefined ? {} : { durable: input.durable }), durability: "durable" as const,
durable: input.durable,
data, data,
})), })),
) satisfies Definition<Type, typeof data> ) satisfies DurableDefinition<Type, typeof data>
}
export function ephemeral<
const Type extends string,
const Fields extends Readonly<Record<PropertyKey, Schema.Codec<unknown, unknown>>>,
>(input: Omit<Input<Type, Fields>, "durable">) {
const data = Schema.Struct(input.schema)
return Schema.Struct({
id: ID,
metadata: optional(Schema.Record(Schema.String, Schema.Unknown)),
type: Schema.Literal(input.type),
location: optional(Location.Ref),
data,
})
.annotate({ identifier: input.type })
.pipe(
statics(() => ({
type: input.type,
durability: "ephemeral" as const,
durable: undefined,
data,
})),
) satisfies EphemeralDefinition<Type, typeof data>
} }
export function inventory<const Definitions extends ReadonlyArray<Definition>>(...definitions: Definitions) { export function inventory<const Definitions extends ReadonlyArray<Definition>>(...definitions: Definitions) {
@@ -107,15 +151,15 @@ export function versionedType(type: string, version: number) {
return `${type}.${version}` return `${type}.${version}`
} }
export function durable<const Definitions extends ReadonlyArray<Definition>>(definitions: Definitions) { export function durableMap<const Definitions extends ReadonlyArray<Definition>>(definitions: Definitions) {
return readonlyMap( return readonlyMap(
definitions.reduce((result, definition) => { definitions.reduce((result, definition) => {
if (!definition.durable) return result if (definition.durability !== "durable") return result
const key = versionedType(definition.type, definition.durable.version) const key = versionedType(definition.type, definition.durable.version)
if (result.has(key)) throw new Error(`Duplicate durable event definition for ${key}`) if (result.has(key)) throw new Error(`Duplicate durable event definition for ${key}`)
result.set(key, definition) result.set(key, definition)
return result return result
}, new Map<string, Definitions[number]>()), }, new Map<string, DurableDefinition>()),
) )
} }
+2 -2
View File
@@ -1,9 +1,9 @@
export * as FileSystemWatcher from "./filesystem-watcher.js" export * as FileSystemWatcher from "./filesystem-watcher.js"
import { Schema } from "effect" import { Schema } from "effect"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
const Updated = define({ const Updated = ephemeral({
type: "file.watcher.updated", type: "file.watcher.updated",
schema: { schema: {
file: Schema.String, file: Schema.String,
+2 -2
View File
@@ -2,10 +2,10 @@ export * as FileSystem from "./filesystem.js"
import { Schema } from "effect" import { Schema } from "effect"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { NonNegativeInt, PositiveInt, RelativePath } from "./schema.js" import { NonNegativeInt, PositiveInt, RelativePath } from "./schema.js"
const Edited = define({ const Edited = ephemeral({
type: "file.edited", type: "file.edited",
schema: { file: Schema.String }, schema: { file: Schema.String },
}) })
+9 -7
View File
@@ -1,7 +1,7 @@
export * as Form from "./form.js" export * as Form from "./form.js"
import { Schema } from "effect" import { Schema } from "effect"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { ascending } from "./identifier.js" import { ascending } from "./identifier.js"
import { NonNegativeInt, optional, statics } from "./schema.js" import { NonNegativeInt, optional, statics } from "./schema.js"
@@ -127,9 +127,11 @@ export interface UrlInfo extends Schema.Schema.Type<typeof UrlInfo> {}
export const Info = Schema.Union([FormInfo, UrlInfo]).pipe(Schema.toTaggedUnion("mode")) export const Info = Schema.Union([FormInfo, UrlInfo]).pipe(Schema.toTaggedUnion("mode"))
export type Info = FormInfo | UrlInfo export type Info = FormInfo | UrlInfo
export const Value = Schema.Union([Schema.String, Schema.Number, Schema.Boolean, Schema.Array(Schema.String)]).annotate({ export const Value = Schema.Union([Schema.String, Schema.Number, Schema.Boolean, Schema.Array(Schema.String)]).annotate(
identifier: "Form.Value", {
}) identifier: "Form.Value",
},
)
export type Value = typeof Value.Type export type Value = typeof Value.Type
export const Answer = Schema.Record(Schema.String, Value).annotate({ identifier: "Form.Answer" }) export const Answer = Schema.Record(Schema.String, Value).annotate({ identifier: "Form.Answer" })
@@ -149,8 +151,8 @@ export const Reply = Schema.Struct({
}).annotate({ identifier: "Form.Reply" }) }).annotate({ identifier: "Form.Reply" })
export interface Reply extends Schema.Schema.Type<typeof Reply> {} export interface Reply extends Schema.Schema.Type<typeof Reply> {}
const Created = define({ type: "form.created", schema: { form: Info } }) const Created = ephemeral({ type: "form.created", schema: { form: Info } })
const Replied = define({ type: "form.replied", schema: { id: ID, sessionID: Schema.String, answer: Answer } }) const Replied = ephemeral({ type: "form.replied", schema: { id: ID, sessionID: Schema.String, answer: Answer } })
const Cancelled = define({ type: "form.cancelled", schema: { id: ID, sessionID: Schema.String } }) const Cancelled = ephemeral({ type: "form.cancelled", schema: { id: ID, sessionID: Schema.String } })
export const Event = { Created, Replied, Cancelled, Definitions: inventory(Created, Replied, Cancelled) } export const Event = { Created, Replied, Cancelled, Definitions: inventory(Created, Replied, Cancelled) }
+1 -1
View File
@@ -3,7 +3,7 @@ export * as IdeEvent from "./ide-event.js"
import { Schema } from "effect" import { Schema } from "effect"
import { Event } from "./event.js" import { Event } from "./event.js"
export const Installed = Event.define({ export const Installed = Event.ephemeral({
type: "ide.installed", type: "ide.installed",
schema: { schema: {
ide: Schema.String, ide: Schema.String,
+2 -2
View File
@@ -3,14 +3,14 @@ export * as InstallationEvent from "./installation-event.js"
import { Schema } from "effect" import { Schema } from "effect"
import { Event } from "./event.js" import { Event } from "./event.js"
export const Updated = Event.define({ export const Updated = Event.ephemeral({
type: "installation.updated", type: "installation.updated",
schema: { schema: {
version: Schema.String, version: Schema.String,
}, },
}) })
export const UpdateAvailable = Event.define({ export const UpdateAvailable = Event.ephemeral({
type: "installation.update-available", type: "installation.update-available",
schema: { schema: {
version: Schema.String, version: Schema.String,
+3 -3
View File
@@ -2,7 +2,7 @@ export * as Integration from "./integration.js"
import { Schema } from "effect" import { Schema } from "effect"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { Connection } from "./connection.js" import { Connection } from "./connection.js"
import { ascending } from "./identifier.js" import { ascending } from "./identifier.js"
import { statics } from "./schema.js" import { statics } from "./schema.js"
@@ -76,11 +76,11 @@ export type Method = typeof Method.Type
export const Inputs = Schema.Record(Schema.String, Schema.String).annotate({ identifier: "Integration.Inputs" }) export const Inputs = Schema.Record(Schema.String, Schema.String).annotate({ identifier: "Integration.Inputs" })
export type Inputs = typeof Inputs.Type export type Inputs = typeof Inputs.Type
const Updated = define({ const Updated = ephemeral({
type: "integration.updated", type: "integration.updated",
schema: {}, schema: {},
}) })
const ConnectionUpdated = define({ const ConnectionUpdated = ephemeral({
type: "integration.connection.updated", type: "integration.connection.updated",
schema: { integrationID: ID }, schema: { integrationID: ID },
}) })
+1 -1
View File
@@ -2,6 +2,6 @@ export * as LspEvent from "./lsp-event.js"
import { Event } from "./event.js" import { Event } from "./event.js"
export const Updated = Event.define({ type: "lsp.updated", schema: {} }) export const Updated = Event.ephemeral({ type: "lsp.updated", schema: {} })
export const Definitions = Event.inventory(Updated) export const Definitions = Event.inventory(Updated)
+3 -3
View File
@@ -3,14 +3,14 @@ export * as McpEvent from "./mcp-event.js"
import { Schema } from "effect" import { Schema } from "effect"
import { Event } from "./event.js" import { Event } from "./event.js"
export const ToolsChanged = Event.define({ export const ToolsChanged = Event.ephemeral({
type: "mcp.tools.changed", type: "mcp.tools.changed",
schema: { schema: {
server: Schema.String, server: Schema.String,
}, },
}) })
export const BrowserOpenFailed = Event.define({ export const BrowserOpenFailed = Event.ephemeral({
type: "mcp.browser.open.failed", type: "mcp.browser.open.failed",
schema: { schema: {
mcpName: Schema.String, mcpName: Schema.String,
@@ -20,7 +20,7 @@ export const BrowserOpenFailed = Event.define({
// Emitted whenever a server's connection status settles (connected, failed, needs_auth, closed) so // Emitted whenever a server's connection status settles (connected, failed, needs_auth, closed) so
// observers can refresh status without polling. // observers can refresh status without polling.
export const StatusChanged = Event.define({ export const StatusChanged = Event.ephemeral({
type: "mcp.status.changed", type: "mcp.status.changed",
schema: { schema: {
server: Schema.String, server: Schema.String,
+2 -2
View File
@@ -1,8 +1,8 @@
export * as ModelsDev from "./models-dev.js" export * as ModelsDev from "./models-dev.js"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
const Refreshed = define({ const Refreshed = ephemeral({
type: "models-dev.refreshed", type: "models-dev.refreshed",
schema: {}, schema: {},
}) })
+3 -3
View File
@@ -2,7 +2,7 @@ export * as Permission from "./permission.js"
import { Schema } from "effect" import { Schema } from "effect"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { ascending } from "./identifier.js" import { ascending } from "./identifier.js"
import { SessionID } from "./session-id.js" import { SessionID } from "./session-id.js"
import { statics } from "./schema.js" import { statics } from "./schema.js"
@@ -40,8 +40,8 @@ export interface Request extends Schema.Schema.Type<typeof Request> {}
export const Reply = Schema.Literals(["once", "always", "reject"]).annotate({ identifier: "PermissionV2.Reply" }) export const Reply = Schema.Literals(["once", "always", "reject"]).annotate({ identifier: "PermissionV2.Reply" })
export type Reply = typeof Reply.Type export type Reply = typeof Reply.Type
const Asked = define({ type: "permission.v2.asked", schema: Request.fields }) const Asked = ephemeral({ type: "permission.v2.asked", schema: Request.fields })
const Replied = define({ const Replied = ephemeral({
type: "permission.v2.replied", type: "permission.v2.replied",
schema: { schema: {
sessionID: SessionID, sessionID: SessionID,
+2 -2
View File
@@ -1,7 +1,7 @@
export * as Plugin from "./plugin.js" export * as Plugin from "./plugin.js"
import { Schema } from "effect" import { Schema } from "effect"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
export const ID = Schema.String.pipe(Schema.brand("Plugin.ID")) export const ID = Schema.String.pipe(Schema.brand("Plugin.ID"))
export type ID = typeof ID.Type export type ID = typeof ID.Type
@@ -11,7 +11,7 @@ export const Info = Schema.Struct({
id: ID, id: ID,
}).annotate({ identifier: "Plugin.Info" }) }).annotate({ identifier: "Plugin.Info" })
const Added = define({ const Added = ephemeral({
type: "plugin.added", type: "plugin.added",
schema: { id: ID }, schema: { id: ID },
}) })
+2 -2
View File
@@ -1,9 +1,9 @@
export * as ProjectDirectories from "./project-directories.js" export * as ProjectDirectories from "./project-directories.js"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { Project } from "./project.js" import { Project } from "./project.js"
const Updated = define({ const Updated = ephemeral({
type: "project.directories.updated", type: "project.directories.updated",
schema: { projectID: Project.ID }, schema: { projectID: Project.ID },
}) })
+2 -2
View File
@@ -1,7 +1,7 @@
export * as Project from "./project.js" export * as Project from "./project.js"
import { Schema } from "effect" import { Schema } from "effect"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { AbsolutePath, NonNegativeInt, optional } from "./schema.js" import { AbsolutePath, NonNegativeInt, optional } from "./schema.js"
import { ProjectID } from "./project-id.js" import { ProjectID } from "./project-id.js"
@@ -56,5 +56,5 @@ export const Info = Schema.Struct({
}).annotate({ identifier: "Project" }) }).annotate({ identifier: "Project" })
export interface Info extends Schema.Schema.Type<typeof Info> {} export interface Info extends Schema.Schema.Type<typeof Info> {}
const Updated = define({ type: "project.updated", schema: Info.fields }) const Updated = ephemeral({ type: "project.updated", schema: Info.fields })
export const Event = { Updated, Definitions: inventory(Updated) } export const Event = { Updated, Definitions: inventory(Updated) }
+5 -5
View File
@@ -2,7 +2,7 @@ export * as Pty from "./pty.js"
import { Schema } from "effect" import { Schema } from "effect"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { ascending } from "./identifier.js" import { ascending } from "./identifier.js"
import { NonNegativeInt, PositiveInt, statics } from "./schema.js" import { NonNegativeInt, PositiveInt, statics } from "./schema.js"
@@ -31,10 +31,10 @@ export const Info = Schema.Struct({
}).annotate({ identifier: "Pty" }) }).annotate({ identifier: "Pty" })
export interface Info extends Schema.Schema.Type<typeof Info> {} export interface Info extends Schema.Schema.Type<typeof Info> {}
const Created = define({ type: "pty.created", schema: { info: Info } }) const Created = ephemeral({ type: "pty.created", schema: { info: Info } })
const Updated = define({ type: "pty.updated", schema: { info: Info } }) const Updated = ephemeral({ type: "pty.updated", schema: { info: Info } })
const Exited = define({ type: "pty.exited", schema: { id: ID, exitCode: NonNegativeInt } }) const Exited = ephemeral({ type: "pty.exited", schema: { id: ID, exitCode: NonNegativeInt } })
const Deleted = define({ type: "pty.deleted", schema: { id: ID } }) const Deleted = ephemeral({ type: "pty.deleted", schema: { id: ID } })
export const Event = { Created, Updated, Exited, Deleted, Definitions: inventory(Created, Updated, Exited, Deleted) } export const Event = { Created, Updated, Exited, Deleted, Definitions: inventory(Created, Updated, Exited, Deleted) }
export const CreateInput = Schema.Struct({ export const CreateInput = Schema.Struct({
+4 -4
View File
@@ -2,7 +2,7 @@ export * as Question from "./question.js"
import { Schema } from "effect" import { Schema } from "effect"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { ascending } from "./identifier.js" import { ascending } from "./identifier.js"
import { SessionID } from "./session-id.js" import { SessionID } from "./session-id.js"
import { statics } from "./schema.js" import { statics } from "./schema.js"
@@ -67,8 +67,8 @@ export const Reply = Schema.Struct({
}).annotate({ identifier: "QuestionV2.Reply" }) }).annotate({ identifier: "QuestionV2.Reply" })
export interface Reply extends Schema.Schema.Type<typeof Reply> {} export interface Reply extends Schema.Schema.Type<typeof Reply> {}
const Asked = define({ type: "question.v2.asked", schema: Request.fields }) const Asked = ephemeral({ type: "question.v2.asked", schema: Request.fields })
const Replied = define({ const Replied = ephemeral({
type: "question.v2.replied", type: "question.v2.replied",
schema: { schema: {
sessionID: SessionID, sessionID: SessionID,
@@ -76,7 +76,7 @@ const Replied = define({
answers: Schema.Array(Answer), answers: Schema.Array(Answer),
}, },
}) })
const Rejected = define({ const Rejected = ephemeral({
type: "question.v2.rejected", type: "question.v2.rejected",
schema: { schema: {
sessionID: SessionID, sessionID: SessionID,
+2 -2
View File
@@ -2,10 +2,10 @@ export * as Reference from "./reference.js"
import { Schema } from "effect" import { Schema } from "effect"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { AbsolutePath } from "./schema.js" import { AbsolutePath } from "./schema.js"
const Updated = define({ type: "reference.updated", schema: {} }) const Updated = ephemeral({ type: "reference.updated", schema: {} })
export const Event = { Updated, Definitions: inventory(Updated) } export const Event = { Updated, Definitions: inventory(Updated) }
export interface LocalSource extends Schema.Schema.Type<typeof LocalSource> {} export interface LocalSource extends Schema.Schema.Type<typeof LocalSource> {}
+2 -2
View File
@@ -2,7 +2,7 @@ export * as ServerEvent from "./server-event.js"
import { Event } from "./event.js" import { Event } from "./event.js"
export const Connected = Event.define({ type: "server.connected", schema: {} }) export const Connected = Event.ephemeral({ type: "server.connected", schema: {} })
export const Disposed = Event.define({ type: "global.disposed", schema: {} }) export const Disposed = Event.ephemeral({ type: "global.disposed", schema: {} })
export const Definitions = Event.inventory(Connected, Disposed) export const Definitions = Event.inventory(Connected, Disposed)
@@ -3,7 +3,7 @@ export * as SessionCompactionEvent from "./session-compaction-event.js"
import { Event } from "./event.js" import { Event } from "./event.js"
import { SessionID } from "./session-id.js" import { SessionID } from "./session-id.js"
export const Compacted = Event.define({ export const Compacted = Event.ephemeral({
type: "session.compacted", type: "session.compacted",
schema: { schema: {
sessionID: SessionID, sessionID: SessionID,
+40 -70
View File
@@ -51,7 +51,7 @@ const stepSettlementOptions = {
export const UnknownError = SessionMessage.UnknownError export const UnknownError = SessionMessage.UnknownError
export type UnknownError = SessionMessage.UnknownError export type UnknownError = SessionMessage.UnknownError
export const AgentSwitched = Event.define({ export const AgentSwitched = Event.durable({
type: "session.next.agent.switched", type: "session.next.agent.switched",
...options, ...options,
schema: { schema: {
@@ -62,7 +62,7 @@ export const AgentSwitched = Event.define({
}) })
export type AgentSwitched = typeof AgentSwitched.Type export type AgentSwitched = typeof AgentSwitched.Type
export const ModelSwitched = Event.define({ export const ModelSwitched = Event.durable({
type: "session.next.model.switched", type: "session.next.model.switched",
...options, ...options,
schema: { schema: {
@@ -73,7 +73,7 @@ export const ModelSwitched = Event.define({
}) })
export type ModelSwitched = typeof ModelSwitched.Type export type ModelSwitched = typeof ModelSwitched.Type
export const Moved = Event.define({ export const Moved = Event.durable({
type: "session.next.moved", type: "session.next.moved",
...options, ...options,
schema: { schema: {
@@ -84,7 +84,7 @@ export const Moved = Event.define({
}) })
export type Moved = typeof Moved.Type export type Moved = typeof Moved.Type
export const Renamed = Event.define({ export const Renamed = Event.durable({
type: "session.next.renamed", type: "session.next.renamed",
...options, ...options,
schema: { schema: {
@@ -94,7 +94,7 @@ export const Renamed = Event.define({
}) })
export type Renamed = typeof Renamed.Type export type Renamed = typeof Renamed.Type
export const Forked = Event.define({ export const Forked = Event.durable({
type: "session.next.forked", type: "session.next.forked",
...options, ...options,
schema: { schema: {
@@ -105,21 +105,21 @@ export const Forked = Event.define({
}) })
export type Forked = typeof Forked.Type export type Forked = typeof Forked.Type
export const Prompted = Event.define({ export const Prompted = Event.durable({
type: "session.next.prompted", type: "session.next.prompted",
...options, ...options,
schema: PromptFields, schema: PromptFields,
}) })
export type Prompted = typeof Prompted.Type export type Prompted = typeof Prompted.Type
export const PromptAdmitted = Event.define({ export const PromptAdmitted = Event.durable({
type: "session.next.prompt.admitted", type: "session.next.prompt.admitted",
...options, ...options,
schema: PromptFields, schema: PromptFields,
}) })
export type PromptAdmitted = typeof PromptAdmitted.Type export type PromptAdmitted = typeof PromptAdmitted.Type
export const ExecutionSettled = Event.define({ export const ExecutionSettled = Event.ephemeral({
type: "session.next.execution.settled", type: "session.next.execution.settled",
schema: { schema: {
...Base, ...Base,
@@ -129,7 +129,7 @@ export const ExecutionSettled = Event.define({
}) })
export type ExecutionSettled = typeof ExecutionSettled.Type export type ExecutionSettled = typeof ExecutionSettled.Type
export const ContextUpdated = Event.define({ export const ContextUpdated = Event.durable({
type: "session.next.context.updated", type: "session.next.context.updated",
...options, ...options,
schema: { schema: {
@@ -140,7 +140,7 @@ export const ContextUpdated = Event.define({
}) })
export type ContextUpdated = typeof ContextUpdated.Type export type ContextUpdated = typeof ContextUpdated.Type
export const Synthetic = Event.define({ export const Synthetic = Event.durable({
type: "session.next.synthetic", type: "session.next.synthetic",
...options, ...options,
schema: { schema: {
@@ -154,7 +154,7 @@ export const Synthetic = Event.define({
export type Synthetic = typeof Synthetic.Type export type Synthetic = typeof Synthetic.Type
export namespace Skill { export namespace Skill {
export const Activated = Event.define({ export const Activated = Event.durable({
type: "session.next.skill.activated", type: "session.next.skill.activated",
...options, ...options,
schema: { schema: {
@@ -168,7 +168,7 @@ export namespace Skill {
} }
export namespace Shell { export namespace Shell {
export const Started = Event.define({ export const Started = Event.durable({
type: "session.next.shell.started", type: "session.next.shell.started",
...options, ...options,
schema: { schema: {
@@ -180,7 +180,7 @@ export namespace Shell {
}) })
export type Started = typeof Started.Type export type Started = typeof Started.Type
export const Ended = Event.define({ export const Ended = Event.durable({
type: "session.next.shell.ended", type: "session.next.shell.ended",
...options, ...options,
schema: { schema: {
@@ -193,7 +193,7 @@ export namespace Shell {
} }
export namespace Step { export namespace Step {
export const Started = Event.define({ export const Started = Event.durable({
type: "session.next.step.started", type: "session.next.step.started",
...options, ...options,
schema: { schema: {
@@ -206,7 +206,7 @@ export namespace Step {
}) })
export type Started = typeof Started.Type export type Started = typeof Started.Type
export const Ended = Event.define({ export const Ended = Event.durable({
type: "session.next.step.ended", type: "session.next.step.ended",
...stepSettlementOptions, ...stepSettlementOptions,
schema: { schema: {
@@ -229,7 +229,7 @@ export namespace Step {
}) })
export type Ended = typeof Ended.Type export type Ended = typeof Ended.Type
export const Failed = Event.define({ export const Failed = Event.durable({
type: "session.next.step.failed", type: "session.next.step.failed",
...stepSettlementOptions, ...stepSettlementOptions,
schema: { schema: {
@@ -242,7 +242,7 @@ export namespace Step {
} }
export namespace Text { export namespace Text {
export const Started = Event.define({ export const Started = Event.durable({
type: "session.next.text.started", type: "session.next.text.started",
...options, ...options,
schema: { schema: {
@@ -254,7 +254,7 @@ export namespace Text {
export type Started = typeof Started.Type export type Started = typeof Started.Type
// Stream fragments are live-only; Text.Ended is the replayable full-value boundary. // Stream fragments are live-only; Text.Ended is the replayable full-value boundary.
export const Delta = Event.define({ export const Delta = Event.ephemeral({
type: "session.next.text.delta", type: "session.next.text.delta",
schema: { schema: {
...Base, ...Base,
@@ -265,7 +265,7 @@ export namespace Text {
}) })
export type Delta = typeof Delta.Type export type Delta = typeof Delta.Type
export const Ended = Event.define({ export const Ended = Event.durable({
type: "session.next.text.ended", type: "session.next.text.ended",
...options, ...options,
schema: { schema: {
@@ -279,7 +279,7 @@ export namespace Text {
} }
export namespace Reasoning { export namespace Reasoning {
export const Started = Event.define({ export const Started = Event.durable({
type: "session.next.reasoning.started", type: "session.next.reasoning.started",
...options, ...options,
schema: { schema: {
@@ -292,7 +292,7 @@ export namespace Reasoning {
export type Started = typeof Started.Type export type Started = typeof Started.Type
// Stream fragments are live-only; Reasoning.Ended is the replayable full-value boundary. // Stream fragments are live-only; Reasoning.Ended is the replayable full-value boundary.
export const Delta = Event.define({ export const Delta = Event.ephemeral({
type: "session.next.reasoning.delta", type: "session.next.reasoning.delta",
schema: { schema: {
...Base, ...Base,
@@ -303,7 +303,7 @@ export namespace Reasoning {
}) })
export type Delta = typeof Delta.Type export type Delta = typeof Delta.Type
export const Ended = Event.define({ export const Ended = Event.durable({
type: "session.next.reasoning.ended", type: "session.next.reasoning.ended",
...options, ...options,
schema: { schema: {
@@ -325,7 +325,7 @@ export namespace Tool {
} }
export namespace Input { export namespace Input {
export const Started = Event.define({ export const Started = Event.durable({
type: "session.next.tool.input.started", type: "session.next.tool.input.started",
...options, ...options,
schema: { schema: {
@@ -336,7 +336,7 @@ export namespace Tool {
export type Started = typeof Started.Type export type Started = typeof Started.Type
// Stream fragments are live-only; Input.Ended is the replayable raw-input boundary. // Stream fragments are live-only; Input.Ended is the replayable raw-input boundary.
export const Delta = Event.define({ export const Delta = Event.ephemeral({
type: "session.next.tool.input.delta", type: "session.next.tool.input.delta",
schema: { schema: {
...ToolBase, ...ToolBase,
@@ -345,7 +345,7 @@ export namespace Tool {
}) })
export type Delta = typeof Delta.Type export type Delta = typeof Delta.Type
export const Ended = Event.define({ export const Ended = Event.durable({
type: "session.next.tool.input.ended", type: "session.next.tool.input.ended",
...options, ...options,
schema: { schema: {
@@ -356,7 +356,7 @@ export namespace Tool {
export type Ended = typeof Ended.Type export type Ended = typeof Ended.Type
} }
export const Called = Event.define({ export const Called = Event.durable({
type: "session.next.tool.called", type: "session.next.tool.called",
...options, ...options,
schema: { schema: {
@@ -375,7 +375,7 @@ export namespace Tool {
* Replayable bounded running-tool state. Tools should checkpoint semantic * Replayable bounded running-tool state. Tools should checkpoint semantic
* transitions or at a bounded cadence, not persist every stdout/stderr chunk. * transitions or at a bounded cadence, not persist every stdout/stderr chunk.
*/ */
export const Progress = Event.define({ export const Progress = Event.durable({
type: "session.next.tool.progress", type: "session.next.tool.progress",
...options, ...options,
schema: { schema: {
@@ -386,7 +386,7 @@ export namespace Tool {
}) })
export type Progress = typeof Progress.Type export type Progress = typeof Progress.Type
export const Success = Event.define({ export const Success = Event.durable({
type: "session.next.tool.success", type: "session.next.tool.success",
...options, ...options,
schema: { schema: {
@@ -403,7 +403,7 @@ export namespace Tool {
}) })
export type Success = typeof Success.Type export type Success = typeof Success.Type
export const Failed = Event.define({ export const Failed = Event.durable({
type: "session.next.tool.failed", type: "session.next.tool.failed",
...options, ...options,
schema: { schema: {
@@ -431,7 +431,7 @@ export const RetryError = Schema.Struct({
}) })
export interface RetryError extends Schema.Schema.Type<typeof RetryError> {} export interface RetryError extends Schema.Schema.Type<typeof RetryError> {}
export const Retried = Event.define({ export const Retried = Event.durable({
type: "session.next.retried", type: "session.next.retried",
...options, ...options,
schema: { schema: {
@@ -443,7 +443,7 @@ export const Retried = Event.define({
export type Retried = typeof Retried.Type export type Retried = typeof Retried.Type
export namespace Compaction { export namespace Compaction {
export const Started = Event.define({ export const Started = Event.durable({
type: "session.next.compaction.started", type: "session.next.compaction.started",
...options, ...options,
schema: { schema: {
@@ -454,7 +454,7 @@ export namespace Compaction {
}) })
export type Started = typeof Started.Type export type Started = typeof Started.Type
export const Delta = Event.define({ export const Delta = Event.ephemeral({
type: "session.next.compaction.delta", type: "session.next.compaction.delta",
schema: { schema: {
...Base, ...Base,
@@ -464,7 +464,7 @@ export namespace Compaction {
}) })
export type Delta = typeof Delta.Type export type Delta = typeof Delta.Type
export const Ended = Event.define({ export const Ended = Event.durable({
type: "session.next.compaction.ended", type: "session.next.compaction.ended",
...options, ...options,
schema: { schema: {
@@ -479,53 +479,19 @@ export namespace Compaction {
} }
export namespace RevertEvent { export namespace RevertEvent {
export const Staged = Event.define({ export const Staged = Event.durable({
type: "session.next.revert.staged", type: "session.next.revert.staged",
...options, ...options,
schema: { ...Base, revert: Revert.State }, schema: { ...Base, revert: Revert.State },
}) })
export const Cleared = Event.define({ type: "session.next.revert.cleared", ...options, schema: Base }) export const Cleared = Event.durable({ type: "session.next.revert.cleared", ...options, schema: Base })
export const Committed = Event.define({ export const Committed = Event.durable({
type: "session.next.revert.committed", type: "session.next.revert.committed",
...options, ...options,
schema: { ...Base, messageID: SessionMessage.ID }, schema: { ...Base, messageID: SessionMessage.ID },
}) })
} }
export const DurableDefinitions = Event.inventory(
AgentSwitched,
ModelSwitched,
Moved,
Renamed,
Forked,
Prompted,
PromptAdmitted,
ContextUpdated,
Synthetic,
Skill.Activated,
Shell.Started,
Shell.Ended,
Step.Started,
Step.Ended,
Step.Failed,
Text.Started,
Text.Ended,
Tool.Input.Started,
Tool.Input.Ended,
Tool.Called,
Tool.Progress,
Tool.Success,
Tool.Failed,
Reasoning.Started,
Reasoning.Ended,
Retried,
Compaction.Started,
Compaction.Ended,
RevertEvent.Staged,
RevertEvent.Cleared,
RevertEvent.Committed,
)
export const Definitions = Event.inventory( export const Definitions = Event.inventory(
AgentSwitched, AgentSwitched,
ModelSwitched, ModelSwitched,
@@ -565,6 +531,10 @@ export const Definitions = Event.inventory(
RevertEvent.Committed, RevertEvent.Committed,
) )
export const DurableDefinitions = Event.inventory(
...Definitions.filter((definition) => definition.durability === "durable"),
)
export const Durable = Schema.Union(DurableDefinitions, { mode: "oneOf" }) export const Durable = Schema.Union(DurableDefinitions, { mode: "oneOf" })
.pipe(Schema.toTaggedUnion("type")) .pipe(Schema.toTaggedUnion("type"))
.annotate({ identifier: "SessionDurableEvent" }) .annotate({ identifier: "SessionDurableEvent" })
+2 -2
View File
@@ -32,7 +32,7 @@ export const Info = Schema.Union([
]).annotate({ identifier: "SessionStatus" }) ]).annotate({ identifier: "SessionStatus" })
export type Info = Schema.Schema.Type<typeof Info> export type Info = Schema.Schema.Type<typeof Info>
export const Status = Event.define({ export const Status = Event.ephemeral({
type: "session.status", type: "session.status",
schema: { schema: {
sessionID: SessionID, sessionID: SessionID,
@@ -41,7 +41,7 @@ export const Status = Event.define({
}) })
// deprecated // deprecated
export const Idle = Event.define({ export const Idle = Event.ephemeral({
type: "session.idle", type: "session.idle",
schema: { schema: {
sessionID: SessionID, sessionID: SessionID,
+2 -2
View File
@@ -1,7 +1,7 @@
export * as SessionTodo from "./session-todo.js" export * as SessionTodo from "./session-todo.js"
import { Schema } from "effect" import { Schema } from "effect"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { SessionID } from "./session-id.js" import { SessionID } from "./session-id.js"
export const Info = Schema.Struct({ export const Info = Schema.Struct({
@@ -15,7 +15,7 @@ export const Info = Schema.Struct({
}).annotate({ identifier: "Todo" }) }).annotate({ identifier: "Todo" })
export interface Info extends Schema.Schema.Type<typeof Info> {} export interface Info extends Schema.Schema.Type<typeof Info> {}
const Updated = define({ const Updated = ephemeral({
type: "todo.updated", type: "todo.updated",
schema: { schema: {
sessionID: SessionID, sessionID: SessionID,
+4 -4
View File
@@ -2,7 +2,7 @@ export * as Shell from "./shell.js"
import { Schema } from "effect" import { Schema } from "effect"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
import { ascending } from "./identifier.js" import { ascending } from "./identifier.js"
import { NonNegativeInt, statics } from "./schema.js" import { NonNegativeInt, statics } from "./schema.js"
@@ -49,9 +49,9 @@ export const Info = Schema.Struct({
}).annotate({ identifier: "Shell" }) }).annotate({ identifier: "Shell" })
export interface Info extends Schema.Schema.Type<typeof Info> {} export interface Info extends Schema.Schema.Type<typeof Info> {}
const Created = define({ type: "shell.created", schema: { info: Info } }) const Created = ephemeral({ type: "shell.created", schema: { info: Info } })
const Exited = define({ type: "shell.exited", schema: { id: ID, exit: optional(Schema.Number), status: Status } }) const Exited = ephemeral({ type: "shell.exited", schema: { id: ID, exit: optional(Schema.Number), status: Status } })
const Deleted = define({ type: "shell.deleted", schema: { id: ID } }) const Deleted = ephemeral({ type: "shell.deleted", schema: { id: ID } })
export const Event = { Created, Exited, Deleted, Definitions: inventory(Created, Exited, Deleted) } export const Event = { Created, Exited, Deleted, Definitions: inventory(Created, Exited, Deleted) }
export const CreateInput = Schema.Struct({ export const CreateInput = Schema.Struct({
+2 -2
View File
@@ -3,7 +3,7 @@ export * as Skill from "./skill.js"
import { Schema } from "effect" import { Schema } from "effect"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { AbsolutePath } from "./schema.js" import { AbsolutePath } from "./schema.js"
import { define, inventory } from "./event.js" import { ephemeral, inventory } from "./event.js"
export interface DirectorySource extends Schema.Schema.Type<typeof DirectorySource> {} export interface DirectorySource extends Schema.Schema.Type<typeof DirectorySource> {}
export const DirectorySource = Schema.Struct({ export const DirectorySource = Schema.Struct({
@@ -27,7 +27,7 @@ export const Info = Schema.Struct({
content: Schema.String, content: Schema.String,
}).annotate({ identifier: "SkillV2.Info" }) }).annotate({ identifier: "SkillV2.Info" })
const Updated = define({ type: "skill.updated", schema: {} }) const Updated = ephemeral({ type: "skill.updated", schema: {} })
export const Event = { Updated, Definitions: inventory(Updated) } export const Event = { Updated, Definitions: inventory(Updated) }
export interface EmbeddedSource extends Schema.Schema.Type<typeof EmbeddedSource> {} export interface EmbeddedSource extends Schema.Schema.Type<typeof EmbeddedSource> {}
+4 -4
View File
@@ -8,9 +8,9 @@ import { SessionID } from "./session-id.js"
const DEFAULT_TOAST_DURATION = 5000 const DEFAULT_TOAST_DURATION = 5000
export const PromptAppend = Event.define({ type: "tui.prompt.append", schema: { text: Schema.String } }) export const PromptAppend = Event.ephemeral({ type: "tui.prompt.append", schema: { text: Schema.String } })
export const CommandExecute = Event.define({ export const CommandExecute = Event.ephemeral({
type: "tui.command.execute", type: "tui.command.execute",
schema: { schema: {
command: Schema.Union([ command: Schema.Union([
@@ -38,7 +38,7 @@ export const CommandExecute = Event.define({
}, },
}) })
export const ToastShow = Event.define({ export const ToastShow = Event.ephemeral({
type: "tui.toast.show", type: "tui.toast.show",
schema: { schema: {
title: optional(Schema.String), title: optional(Schema.String),
@@ -50,7 +50,7 @@ export const ToastShow = Event.define({
}, },
}) })
export const SessionSelect = Event.define({ export const SessionSelect = Event.ephemeral({
type: "tui.session.select", type: "tui.session.select",
schema: { schema: {
sessionID: SessionID.annotate({ description: "Session ID to navigate to" }), sessionID: SessionID.annotate({ description: "Session ID to navigate to" }),
+2 -2
View File
@@ -1,11 +1,11 @@
export * as LegacyEvent from "./legacy-event.js" export * as LegacyEvent from "./legacy-event.js"
import { Schema } from "effect" import { Schema } from "effect"
import { define, inventory } from "../event.js" import { ephemeral, inventory } from "../event.js"
import { SessionID } from "../session-id.js" import { SessionID } from "../session-id.js"
import { SessionV1 } from "./session.js" import { SessionV1 } from "./session.js"
export const CommandExecuted = define({ export const CommandExecuted = ephemeral({
type: "command.executed", type: "command.executed",
schema: { schema: {
name: Schema.String, name: Schema.String,
+3 -3
View File
@@ -1,7 +1,7 @@
export * as PermissionV1 from "./permission.js" export * as PermissionV1 from "./permission.js"
import { Schema } from "effect" import { Schema } from "effect"
import { define, inventory } from "../event.js" import { ephemeral, inventory } from "../event.js"
import { ascending } from "../identifier.js" import { ascending } from "../identifier.js"
import { Project } from "../project.js" import { Project } from "../project.js"
import { statics } from "../schema.js" import { statics } from "../schema.js"
@@ -58,8 +58,8 @@ export const ReplyInput = Schema.Struct({ requestID: ID, ...ReplyBody.fields }).
}) })
export type ReplyInput = typeof ReplyInput.Type export type ReplyInput = typeof ReplyInput.Type
const Asked = define({ type: "permission.asked", schema: Request.fields }) const Asked = ephemeral({ type: "permission.asked", schema: Request.fields })
const Replied = define({ const Replied = ephemeral({
type: "permission.replied", type: "permission.replied",
schema: { sessionID: SessionID, requestID: ID, reply: Reply }, schema: { sessionID: SessionID, requestID: ID, reply: Reply },
}) })
+4 -4
View File
@@ -1,7 +1,7 @@
export * as QuestionV1 from "./question.js" export * as QuestionV1 from "./question.js"
import { Schema } from "effect" import { Schema } from "effect"
import { define, inventory } from "../event.js" import { ephemeral, inventory } from "../event.js"
import { ascending } from "../identifier.js" import { ascending } from "../identifier.js"
import { statics } from "../schema.js" import { statics } from "../schema.js"
import { SessionID } from "../session-id.js" import { SessionID } from "../session-id.js"
@@ -55,9 +55,9 @@ export const Rejected = Schema.Struct({ sessionID: SessionID, requestID: ID }).a
identifier: "QuestionRejected", identifier: "QuestionRejected",
}) })
const Asked = define({ type: "question.asked", schema: Request.fields }) const Asked = ephemeral({ type: "question.asked", schema: Request.fields })
const RepliedEvent = define({ type: "question.replied", schema: Replied.fields }) const RepliedEvent = ephemeral({ type: "question.replied", schema: Replied.fields })
const RejectedEvent = define({ type: "question.rejected", schema: Rejected.fields }) const RejectedEvent = ephemeral({ type: "question.rejected", schema: Rejected.fields })
export const Event = { export const Event = {
Asked, Asked,
Replied: RepliedEvent, Replied: RepliedEvent,
+11 -11
View File
@@ -1,7 +1,7 @@
export * as SessionV1 from "./session.js" export * as SessionV1 from "./session.js"
import { Effect, Schema, Types } from "effect" import { Effect, Schema, Types } from "effect"
import { define, inventory } from "../event.js" import { durable, ephemeral, inventory } from "../event.js"
import { FileDiff } from "../file-diff.js" import { FileDiff } from "../file-diff.js"
import { Project } from "../project.js" import { Project } from "../project.js"
import { Provider } from "../provider.js" import { Provider } from "../provider.js"
@@ -569,7 +569,7 @@ export const SessionInfo = Schema.Struct({
export type SessionInfo = typeof SessionInfo.Type export type SessionInfo = typeof SessionInfo.Type
const events = { const events = {
Created: define({ Created: durable({
type: "session.created", type: "session.created",
...options, ...options,
schema: { schema: {
@@ -577,7 +577,7 @@ const events = {
info: SessionInfo, info: SessionInfo,
}, },
}), }),
Updated: define({ Updated: durable({
type: "session.updated", type: "session.updated",
...options, ...options,
schema: { schema: {
@@ -585,7 +585,7 @@ const events = {
info: SessionInfo, info: SessionInfo,
}, },
}), }),
Deleted: define({ Deleted: durable({
type: "session.deleted", type: "session.deleted",
...options, ...options,
schema: { schema: {
@@ -593,7 +593,7 @@ const events = {
info: SessionInfo, info: SessionInfo,
}, },
}), }),
MessageUpdated: define({ MessageUpdated: durable({
type: "message.updated", type: "message.updated",
...options, ...options,
schema: { schema: {
@@ -601,7 +601,7 @@ const events = {
info: Info, info: Info,
}, },
}), }),
MessageRemoved: define({ MessageRemoved: durable({
type: "message.removed", type: "message.removed",
...options, ...options,
schema: { schema: {
@@ -609,7 +609,7 @@ const events = {
messageID: MessageID, messageID: MessageID,
}, },
}), }),
PartUpdated: define({ PartUpdated: durable({
type: "message.part.updated", type: "message.part.updated",
...options, ...options,
schema: { schema: {
@@ -618,7 +618,7 @@ const events = {
time: Schema.Finite, time: Schema.Finite,
}, },
}), }),
PartRemoved: define({ PartRemoved: durable({
type: "message.part.removed", type: "message.part.removed",
...options, ...options,
schema: { schema: {
@@ -629,7 +629,7 @@ const events = {
}), }),
} }
export const PartDelta = define({ export const PartDelta = ephemeral({
type: "message.part.delta", type: "message.part.delta",
schema: { schema: {
sessionID: SessionID, sessionID: SessionID,
@@ -640,7 +640,7 @@ export const PartDelta = define({
}, },
}) })
export const Diff = define({ export const Diff = ephemeral({
type: "session.diff", type: "session.diff",
schema: { schema: {
sessionID: SessionID, sessionID: SessionID,
@@ -648,7 +648,7 @@ export const Diff = define({
}, },
}) })
export const Error = define({ export const Error = ephemeral({
type: "session.error", type: "session.error",
schema: { schema: {
sessionID: Schema.optional(SessionID), sessionID: Schema.optional(SessionID),
+1 -1
View File
@@ -4,7 +4,7 @@ import { Schema } from "effect"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { Event } from "./event.js" import { Event } from "./event.js"
export const BranchUpdated = Event.define({ export const BranchUpdated = Event.ephemeral({
type: "vcs.branch.updated", type: "vcs.branch.updated",
schema: { schema: {
branch: optional(Schema.String), branch: optional(Schema.String),
+3 -3
View File
@@ -10,21 +10,21 @@ export const ConnectionStatus = Schema.Struct({
}).annotate({ identifier: "WorkspaceEvent.ConnectionStatus" }) }).annotate({ identifier: "WorkspaceEvent.ConnectionStatus" })
export interface ConnectionStatus extends Schema.Schema.Type<typeof ConnectionStatus> {} export interface ConnectionStatus extends Schema.Schema.Type<typeof ConnectionStatus> {}
export const Ready = Event.define({ export const Ready = Event.ephemeral({
type: "workspace.ready", type: "workspace.ready",
schema: { schema: {
name: Schema.String, name: Schema.String,
}, },
}) })
export const Failed = Event.define({ export const Failed = Event.ephemeral({
type: "workspace.failed", type: "workspace.failed",
schema: { schema: {
message: Schema.String, message: Schema.String,
}, },
}) })
export const Status = Event.define({ export const Status = Event.ephemeral({
type: "workspace.status", type: "workspace.status",
schema: ConnectionStatus.fields, schema: ConnectionStatus.fields,
}) })
+2 -2
View File
@@ -4,7 +4,7 @@ import { Schema } from "effect"
import { optional } from "./schema.js" import { optional } from "./schema.js"
import { Event } from "./event.js" import { Event } from "./event.js"
export const Ready = Event.define({ export const Ready = Event.ephemeral({
type: "worktree.ready", type: "worktree.ready",
schema: { schema: {
name: Schema.String, name: Schema.String,
@@ -12,7 +12,7 @@ export const Ready = Event.define({
}, },
}) })
export const Failed = Event.define({ export const Failed = Event.ephemeral({
type: "worktree.failed", type: "worktree.failed",
schema: { schema: {
message: Schema.String, message: Schema.String,
+65 -4
View File
@@ -1,5 +1,15 @@
import { describe, expect, test } from "bun:test" import { describe, expect, test } from "bun:test"
import { Agent, FileSystem, Form, Integration, Permission, Project, Reference, Session, Workspace } from "../src/index.js" import {
Agent,
FileSystem,
Form,
Integration,
Permission,
Project,
Reference,
Session,
Workspace,
} from "../src/index.js"
import { EventManifest } from "../src/event-manifest.js" import { EventManifest } from "../src/event-manifest.js"
import { IdeEvent } from "../src/ide-event.js" import { IdeEvent } from "../src/ide-event.js"
import { SessionEvent } from "../src/session-event.js" import { SessionEvent } from "../src/session-event.js"
@@ -9,11 +19,11 @@ import { WorkspaceEvent } from "../src/workspace-event.js"
describe("public event manifest", () => { describe("public event manifest", () => {
test("owns the complete public event surface", () => { test("owns the complete public event surface", () => {
expect(EventManifest.ServerDefinitions.filter((definition) => definition.type !== "agent.updated").length).toBe(86) expect(EventManifest.ServerDefinitions).toContain(Agent.Event.Updated)
expect(EventManifest.ServerDefinitions.filter((definition) => definition.type === "agent.updated")).toEqual([ expect(EventManifest.ServerDefinitions.filter((definition) => definition.type === "agent.updated")).toEqual([
Agent.Event.Updated, Agent.Event.Updated,
]) ])
expect(EventManifest.Definitions.filter((definition) => definition.type !== "agent.updated").length).toBe(101) expect(EventManifest.Definitions).toContain(Agent.Event.Updated)
expect(EventManifest.Definitions.filter((definition) => definition.type === "agent.updated")).toEqual([ expect(EventManifest.Definitions.filter((definition) => definition.type === "agent.updated")).toEqual([
Agent.Event.Updated, Agent.Event.Updated,
]) ])
@@ -29,7 +39,9 @@ describe("public event manifest", () => {
SessionV1.Event.Diff, SessionV1.Event.Diff,
SessionV1.Event.Error, SessionV1.Event.Error,
]) ])
expect(Array.from(EventManifest.Latest.keys()).filter((type) => type !== "agent.updated").length).toBe(101) expect(Array.from(EventManifest.Latest.keys())).toEqual(
EventManifest.Definitions.map((definition) => definition.type),
)
expect(EventManifest.Latest.get("agent.updated")).toBe(Agent.Event.Updated) expect(EventManifest.Latest.get("agent.updated")).toBe(Agent.Event.Updated)
expect(Agent.Event.Updated.durable).toBeUndefined() expect(Agent.Event.Updated.durable).toBeUndefined()
expect(EventManifest.Durable.has("agent.updated")).toBe(false) expect(EventManifest.Durable.has("agent.updated")).toBe(false)
@@ -62,4 +74,53 @@ describe("public event manifest", () => {
expect(EventManifest.Durable.has("session.next.step.ended.1")).toBe(false) expect(EventManifest.Durable.has("session.next.step.ended.1")).toBe(false)
expect(EventManifest.Durable.get("session.next.step.ended.2")).toBe(SessionEvent.Step.Ended) expect(EventManifest.Durable.get("session.next.step.ended.2")).toBe(SessionEvent.Step.Ended)
}) })
test("derives durable definitions from explicit definition durability", () => {
expect(Array.from(EventManifest.Durable.keys()).toSorted()).toEqual(
[
"session.created.1",
"session.updated.1",
"session.deleted.1",
"message.updated.1",
"message.removed.1",
"message.part.updated.1",
"message.part.removed.1",
"session.next.agent.switched.1",
"session.next.model.switched.1",
"session.next.moved.1",
"session.next.renamed.1",
"session.next.forked.1",
"session.next.prompted.1",
"session.next.prompt.admitted.1",
"session.next.context.updated.1",
"session.next.synthetic.1",
"session.next.skill.activated.1",
"session.next.shell.started.1",
"session.next.shell.ended.1",
"session.next.step.started.1",
"session.next.step.ended.2",
"session.next.step.failed.2",
"session.next.text.started.1",
"session.next.text.ended.1",
"session.next.tool.input.started.1",
"session.next.tool.input.ended.1",
"session.next.tool.called.1",
"session.next.tool.progress.1",
"session.next.tool.success.1",
"session.next.tool.failed.1",
"session.next.reasoning.started.1",
"session.next.reasoning.ended.1",
"session.next.retried.1",
"session.next.compaction.started.1",
"session.next.compaction.ended.1",
"session.next.revert.staged.1",
"session.next.revert.cleared.1",
"session.next.revert.committed.1",
].toSorted(),
)
expect(SessionEvent.DurableDefinitions).toEqual(
SessionEvent.Definitions.filter((definition) => definition.durability === "durable"),
)
expect(EventManifest.Definitions.every((definition) => definition.durability !== undefined)).toBe(true)
})
}) })
+5 -5
View File
@@ -6,17 +6,17 @@ import { EventLog } from "../src/event-log.js"
describe("public event schemas", () => { describe("public event schemas", () => {
test("definition is pure", () => { test("definition is pure", () => {
const definitions = Event.inventory() const definitions = Event.inventory()
Event.define({ type: "test.pure", schema: { value: Schema.String } }) Event.ephemeral({ type: "test.pure", schema: { value: Schema.String } })
expect(definitions).toEqual([]) expect(definitions).toEqual([])
}) })
test("latest selection is independent of declaration order", () => { test("latest selection is independent of declaration order", () => {
const historical = Event.define({ const historical = Event.durable({
type: "test.versioned", type: "test.versioned",
durable: { aggregate: "id", version: 1 }, durable: { aggregate: "id", version: 1 },
schema: { id: Schema.String }, schema: { id: Schema.String },
}) })
const current = Event.define({ const current = Event.durable({
type: "test.versioned", type: "test.versioned",
durable: { aggregate: "id", version: 2 }, durable: { aggregate: "id", version: 2 },
schema: { id: Schema.String, value: Schema.String }, schema: { id: Schema.String, value: Schema.String },
@@ -27,13 +27,13 @@ describe("public event schemas", () => {
}) })
test("durable definitions are indexed by type and version", () => { test("durable definitions are indexed by type and version", () => {
const definition = Event.define({ const definition = Event.durable({
type: "test.durable", type: "test.durable",
durable: { aggregate: "id", version: 1 }, durable: { aggregate: "id", version: 1 },
schema: { id: Schema.String }, schema: { id: Schema.String },
}) })
expect(Event.durable([definition]).get("test.durable.1")).toBe(definition) expect(Event.durableMap([definition]).get("test.durable.1")).toBe(definition)
}) })
test("synced marker encodes the captured watermark", () => { test("synced marker encodes the captured watermark", () => {
+1 -1
View File
@@ -149,7 +149,7 @@ it.live(
const opencode = yield* fixture.sdk.OpenCode.create() const opencode = yield* fixture.sdk.OpenCode.create()
const id = sessionID(fixture) const id = sessionID(fixture)
const connected = yield* Latch.make(false) const connected = yield* Latch.make(false)
const prompted = yield* Deferred.make<OpenCodeEvent>() const prompted = yield* Deferred.make<Extract<OpenCodeEvent, { type: "session.next.prompted" }>>()
yield* opencode.events.subscribe().pipe( yield* opencode.events.subscribe().pipe(
Stream.runForEach((event) => Stream.runForEach((event) =>
File diff suppressed because it is too large Load Diff
@@ -33,10 +33,7 @@ async function setup() {
}, },
}, },
event: { event: {
on: <Type extends V2Event["type"]>( on: <Type extends V2Event["type"]>(type: Type, handler: (event: Extract<V2Event, { type: Type }>) => void) => {
type: Type,
handler: (event: Extract<V2Event, { type: Type }>) => void,
) => {
const list = handlers.get(type) ?? [] const list = handlers.get(type) ?? []
const wrapped = handler as (event: V2Event) => void const wrapped = handler as (event: V2Event) => void
list.push(wrapped) list.push(wrapped)
@@ -86,10 +83,15 @@ function permission(id: string, sessionID = "session"): PermissionRequest {
} }
} }
function durable(sessionID: string) {
return { aggregateID: sessionID, seq: 0, version: 1 }
}
function stepStarted(id: string, sessionID = "session"): V2Event { function stepStarted(id: string, sessionID = "session"): V2Event {
return { return {
id, id,
type: "session.next.step.started", type: "session.next.step.started",
durable: durable(sessionID),
data: { data: {
sessionID, sessionID,
assistantMessageID: `msg_${id}`, assistantMessageID: `msg_${id}`,
@@ -104,6 +106,7 @@ function stepEnded(id: string, sessionID = "session", finish = "stop"): V2Event
return { return {
id, id,
type: "session.next.step.ended", type: "session.next.step.ended",
durable: durable(sessionID),
data: { data: {
sessionID, sessionID,
assistantMessageID: `msg_${id}`, assistantMessageID: `msg_${id}`,
@@ -119,6 +122,7 @@ function stepFailed(id: string, sessionID = "session"): V2Event {
return { return {
id, id,
type: "session.next.step.failed", type: "session.next.step.failed",
durable: durable(sessionID),
data: { data: {
sessionID, sessionID,
assistantMessageID: `msg_${id}`, assistantMessageID: `msg_${id}`,
+21 -1
View File
@@ -21,6 +21,10 @@ function emitEvent(events: ReturnType<typeof createEventStream>, event: V2Event)
events.emit({ ...event, location: { directory } }) events.emit({ ...event, location: { directory } })
} }
function durable(sessionID: string, seq = 0, version = 1) {
return { aggregateID: sessionID, seq, version }
}
test("refreshes resources into reactive getters", async () => { test("refreshes resources into reactive getters", async () => {
const events = createEventStream() const events = createEventStream()
const location = { const location = {
@@ -261,6 +265,7 @@ test("tracks session status from active sessions and execution events", async ()
emitEvent(events, { emitEvent(events, {
id: "evt_step_started", id: "evt_step_started",
type: "session.next.step.started", type: "session.next.step.started",
durable: durable("session-live"),
data: { data: {
sessionID: "session-live", sessionID: "session-live",
assistantMessageID: "message-live", assistantMessageID: "message-live",
@@ -274,6 +279,7 @@ test("tracks session status from active sessions and execution events", async ()
emitEvent(events, { emitEvent(events, {
id: "evt_step_ended", id: "evt_step_ended",
type: "session.next.step.ended", type: "session.next.step.ended",
durable: durable("session-live", 1, 2),
data: { data: {
sessionID: "session-live", sessionID: "session-live",
assistantMessageID: "message-live", assistantMessageID: "message-live",
@@ -303,6 +309,7 @@ test("tracks session status from active sessions and execution events", async ()
emitEvent(events, { emitEvent(events, {
id: "evt_failed_step_started", id: "evt_failed_step_started",
type: "session.next.step.started", type: "session.next.step.started",
durable: durable("session-failed"),
data: { data: {
sessionID: "session-failed", sessionID: "session-failed",
assistantMessageID: "message-failed", assistantMessageID: "message-failed",
@@ -316,6 +323,7 @@ test("tracks session status from active sessions and execution events", async ()
emitEvent(events, { emitEvent(events, {
id: "evt_step_failed", id: "evt_step_failed",
type: "session.next.step.failed", type: "session.next.step.failed",
durable: durable("session-failed", 1, 2),
data: { data: {
sessionID: "session-failed", sessionID: "session-failed",
assistantMessageID: "message-failed", assistantMessageID: "message-failed",
@@ -548,7 +556,10 @@ test("keeps shell state scoped to location", async () => {
if (url.pathname !== "/api/shell") return if (url.pathname !== "/api/shell") return
const requestDirectory = url.searchParams.get("location[directory]") const requestDirectory = url.searchParams.get("location[directory]")
return json({ return json({
location: { directory: requestDirectory ?? directory, project: { id: "proj_test", directory: requestDirectory ?? directory } }, location: {
directory: requestDirectory ?? directory,
project: { id: "proj_test", directory: requestDirectory ?? directory },
},
data: [ data: [
{ {
id: requestDirectory === other ? "sh_other" : "sh_default", id: requestDirectory === other ? "sh_other" : "sh_default",
@@ -773,11 +784,13 @@ test("settles pending tools when a live failure arrives", async () => {
emitEvent(events, { emitEvent(events, {
id: "evt_agent_1", id: "evt_agent_1",
type: "session.next.agent.switched", type: "session.next.agent.switched",
durable: durable("session-1"),
data: { sessionID: "session-1", messageID: "msg_agent_1", timestamp: 0, agent: "build" }, data: { sessionID: "session-1", messageID: "msg_agent_1", timestamp: 0, agent: "build" },
}) })
emitEvent(events, { emitEvent(events, {
id: "evt_model_1", id: "evt_model_1",
type: "session.next.model.switched", type: "session.next.model.switched",
durable: durable("session-1", 1),
data: { data: {
sessionID: "session-1", sessionID: "session-1",
messageID: "msg_model_1", messageID: "msg_model_1",
@@ -788,6 +801,7 @@ test("settles pending tools when a live failure arrives", async () => {
emitEvent(events, { emitEvent(events, {
id: "evt_step_started_1", id: "evt_step_started_1",
type: "session.next.step.started", type: "session.next.step.started",
durable: durable("session-1", 2),
data: { data: {
sessionID: "session-1", sessionID: "session-1",
assistantMessageID: "msg_explicit_assistant_9", assistantMessageID: "msg_explicit_assistant_9",
@@ -799,6 +813,7 @@ test("settles pending tools when a live failure arrives", async () => {
emitEvent(events, { emitEvent(events, {
id: "evt_input_1", id: "evt_input_1",
type: "session.next.tool.input.started", type: "session.next.tool.input.started",
durable: durable("session-1", 3),
data: { data: {
sessionID: "session-1", sessionID: "session-1",
assistantMessageID: "msg_explicit_assistant_9", assistantMessageID: "msg_explicit_assistant_9",
@@ -810,6 +825,7 @@ test("settles pending tools when a live failure arrives", async () => {
emitEvent(events, { emitEvent(events, {
id: "evt_called_1", id: "evt_called_1",
type: "session.next.tool.called", type: "session.next.tool.called",
durable: durable("session-1", 4),
data: { data: {
sessionID: "session-1", sessionID: "session-1",
timestamp: 2, timestamp: 2,
@@ -823,6 +839,7 @@ test("settles pending tools when a live failure arrives", async () => {
emitEvent(events, { emitEvent(events, {
id: "evt_failed_1", id: "evt_failed_1",
type: "session.next.tool.failed", type: "session.next.tool.failed",
durable: durable("session-1", 5),
data: { data: {
sessionID: "session-1", sessionID: "session-1",
timestamp: 3, timestamp: 3,
@@ -912,6 +929,7 @@ test("renders admitted prompts immediately with queued marker and clears when pr
emitEvent(events, { emitEvent(events, {
id: "evt_admitted_1", id: "evt_admitted_1",
type: "session.next.prompt.admitted", type: "session.next.prompt.admitted",
durable: durable(sessionID),
data: { data: {
sessionID, sessionID,
messageID, messageID,
@@ -930,6 +948,7 @@ test("renders admitted prompts immediately with queued marker and clears when pr
emitEvent(events, { emitEvent(events, {
id: "evt_prompted_1", id: "evt_prompted_1",
type: "session.next.prompted", type: "session.next.prompted",
durable: durable(sessionID, 1),
data: { data: {
sessionID, sessionID,
messageID, messageID,
@@ -989,6 +1008,7 @@ test("projects live context updates with their message ID", async () => {
emitEvent(events, { emitEvent(events, {
id: "evt_context_1", id: "evt_context_1",
type: "session.next.context.updated", type: "session.next.context.updated",
durable: durable("session-1"),
data: { data: {
sessionID: "session-1", sessionID: "session-1",
messageID: "msg_context_1", messageID: "msg_context_1",
+20
View File
@@ -1,5 +1,25 @@
# V2 Schema Changelog # V2 Schema Changelog
## 2026-07-03: Require Durable Envelope On Durable Events
- Make the wire `durable` envelope required on durable event definitions.
- Remove the `durable` envelope field from live-only event definitions.
Compatibility:
- No stored event row, database, or runtime publish behavior change; runtime already attaches the envelope only after durable commit/replay.
- Generated clients now model the existing invariant: durable events carry `durable`, live-only events do not.
## 2026-07-03: Declare Event Durability At Definition Level
- Add explicit `Event.durable(...)` and `Event.ephemeral(...)` definition constructors.
- Preserve the existing durable and live-only event classifications while deriving durable inventories from definition metadata instead of hand-maintained lists.
Compatibility:
- No wire payload, stored event row, database, or behavior change.
- Generated clients were regenerated from the unchanged public event schemas.
## 2026-07-02: Rename Session Log Replay Marker ## 2026-07-02: Rename Session Log Replay Marker
- Rename the replay boundary marker from `log.caught_up` / `EventLog.CaughtUp` to `log.synced` / `EventLog.Synced`. - Rename the replay boundary marker from `log.caught_up` / `EventLog.CaughtUp` to `log.synced` / `EventLog.Synced`.