Compare commits

...

1 Commits

Author SHA1 Message Date
Kit Langton ab31c41fee refactor(bus): one GlobalBus emit per event, with optional sync metadata
Today every sync.run produces TWO GlobalBus events:

  1. From bus.publish itself — the projection view:
     { payload: { id, type: "session.created", properties } }

  2. From sync/index.ts — the source-of-truth envelope:
     { payload: { type: "sync", syncEvent: { type: "session.created.1", id, seq, aggregateID, data } } }

These two emits live in different files and discriminate via
`payload.type` — either a real event type or the sentinel "sync".
That collision is the source of confusion in the codebase:
consumers have to know which shape they're looking at.

The duality dates back to:
  - d88912abf0 (Dec 2025): Dax added GlobalBus.emit inside bus.publish.
  - b22add292c (#22347, Apr 2026): James consolidated sync events onto
    GlobalBus by ADDING a second emit with the source envelope.

#22347's stated intent was "consolidate events into a single stream".
Two emits with different shapes on one channel isn't quite that. One
emit per event with a unified shape is.

This PR collapses the two emits into one:

  { payload: { id, type: "session.created", properties, sync?: { name, seq, aggregateID, data } } }

- bus.publish accepts an optional `sync?: SyncMetadata` option.
- sync/index.ts passes it; its own GlobalBus.emit is removed.
- BusEvent.effectPayloads() adds an optional `sync` field to every
  event schema.
- SyncEvent.effectPayloads() is no longer included in the wire schema
  (it's now subsumed by the optional field).
- Consumers migrate from `payload.type === "sync"` filtering to
  `payload.sync != null` filtering. control-plane/workspace.ts
  reconstructs SerializedEvent from { id, sync.* } for replay.

Note: this is a BREAKING SDK wire-format change. External consumers
that read `payload.type === "sync"` or `payload.syncEvent` need to
migrate. Internal opencode consumers all migrated in this PR.

Side observation: the runtime emit was using `payload.syncEvent`
(nested) while the SDK schema declared the fields at top level under
`type: "sync"` — a silent schema drift. Collapsing to one emit also
fixes that drift by definition.

Verified:
  - bun typecheck — clean
  - bun run test test/sync/index.test.ts test/bus/bus-effect.test.ts
    test/server/httpapi-event.test.ts
    test/server/httpapi-event-diagnostics.test.ts — 29/29 green
  - bun run test test/server/httpapi-sdk.test.ts -t "streams sync-backed" — green
2026-05-18 13:23:30 -04:00
10 changed files with 188 additions and 74 deletions
-4
View File
@@ -154,10 +154,6 @@ export const { use: useGlobalSDK, provider: GlobalSDKProvider } = createSimpleCo
resetHeartbeat() resetHeartbeat()
streamErrorLogged = false streamErrorLogged = false
const directory = event.directory ?? "global" const directory = event.directory ?? "global"
if (event.payload.type === "sync") {
continue
}
const payload = event.payload as Event const payload = event.payload as Event
const k = key(directory, payload) const k = key(directory, payload)
+13
View File
@@ -17,6 +17,17 @@ export function define<Type extends string, Properties extends Schema.Top>(
return result return result
} }
// Optional source-of-truth metadata for event-sourcing replay. Present on
// GlobalBus events that originated from `SyncEvent.run`; absent on transient
// bus events that don't have an event log entry. Consumers that replay the
// event log (cross-instance sync) filter by `payload.sync != null`.
const Sync = Schema.Struct({
name: Schema.String,
seq: Schema.Finite,
aggregateID: Schema.String,
data: Schema.Unknown,
}).annotate({ identifier: "Event.Sync" })
export function effectPayloads() { export function effectPayloads() {
return [ return [
...registry ...registry
@@ -26,6 +37,7 @@ export function effectPayloads() {
id: Schema.String, id: Schema.String,
type: Schema.Literal(type), type: Schema.Literal(type),
properties: def.properties, properties: def.properties,
sync: Schema.optional(Sync),
}).annotate({ identifier: `Event.${type}` }), }).annotate({ identifier: `Event.${type}` }),
) )
.toArray(), .toArray(),
@@ -36,6 +48,7 @@ export function effectPayloads() {
id: Schema.String, id: Schema.String,
type: Schema.Literal(definition.type), type: Schema.Literal(definition.type),
properties: definition.data, properties: definition.data,
sync: Schema.optional(Sync),
}).annotate({ identifier: `Event.${definition.type}` }), }).annotate({ identifier: `Event.${definition.type}` }),
) )
.toArray(), .toArray(),
+1 -1
View File
@@ -13,7 +13,7 @@ class GlobalBusEmitter extends EventEmitter<{
}> { }> {
override emit(eventName: "event", event: GlobalEvent): boolean { override emit(eventName: "event", event: GlobalEvent): boolean {
if (event.payload && typeof event.payload === "object" && !("id" in event.payload)) { if (event.payload && typeof event.payload === "object" && !("id" in event.payload)) {
event.payload.id = event.payload.syncEvent?.id ?? Identifier.create("evt", "ascending") event.payload.id = Identifier.create("evt", "ascending")
} }
return super.emit(eventName, event) return super.emit(eventName, event)
} }
+17 -3
View File
@@ -31,11 +31,21 @@ type State = {
typed: Map<string, PubSub.PubSub<Payload>> typed: Map<string, PubSub.PubSub<Payload>>
} }
export type SyncMetadata = {
readonly name: string
readonly seq: number
readonly aggregateID: string
readonly data: unknown
}
export interface Interface { export interface Interface {
// `sync` carries event-sourcing metadata when the publish originates from
// `SyncEvent.run`/`replay`. It rides on the same GlobalBus event as the
// projection — one wire event per domain event, with both views inside.
readonly publish: <D extends BusEvent.Definition>( readonly publish: <D extends BusEvent.Definition>(
def: D, def: D,
properties: BusProperties<D>, properties: BusProperties<D>,
options?: { id?: string }, options?: { id?: string; sync?: SyncMetadata },
) => Effect.Effect<void> ) => Effect.Effect<void>
// subscribe / subscribeAll are eager: the underlying PubSub subscription is // subscribe / subscribeAll are eager: the underlying PubSub subscription is
// acquired in the caller's Scope at `yield*` time. Any publish after the // acquired in the caller's Scope at `yield*` time. Any publish after the
@@ -94,7 +104,11 @@ export const layer = Layer.effect(
}) })
} }
function publish<D extends BusEvent.Definition>(def: D, properties: BusProperties<D>, options?: { id?: string }) { function publish<D extends BusEvent.Definition>(
def: D,
properties: BusProperties<D>,
options?: { id?: string; sync?: SyncMetadata },
) {
return Effect.gen(function* () { return Effect.gen(function* () {
const s = yield* InstanceState.get(state) const s = yield* InstanceState.get(state)
const payload: Payload = { id: options?.id ?? createID(), type: def.type, properties } const payload: Payload = { id: options?.id ?? createID(), type: def.type, properties }
@@ -112,7 +126,7 @@ export const layer = Layer.effect(
directory: dir, directory: dir,
project: context.project.id, project: context.project.id,
workspace, workspace,
payload, payload: options?.sync ? { ...payload, sync: options.sync } : payload,
}) })
}) })
} }
@@ -170,12 +170,7 @@ function globalPayloadEvent(value: unknown): Event | undefined {
return undefined return undefined
} }
const payload = value.payload return isEvent(value.payload) ? value.payload : undefined
if (payload.type === "sync") {
return undefined
}
return isEvent(payload) ? payload : undefined
} }
function isMatchingDisposeEvent(value: unknown, directory: string | undefined): boolean { function isMatchingDisposeEvent(value: unknown, directory: string | undefined): boolean {
@@ -12,10 +12,6 @@ export function useEvent() {
function subscribe(handler: (event: Event, metadata: EventMetadata) => void) { function subscribe(handler: (event: Event, metadata: EventMetadata) => void) {
return sdk.event.on("event", (event) => { return sdk.event.on("event", (event) => {
if (event.payload.type === "sync") {
return
}
if (event.directory === "global" || event.project === project.project()) { if (event.directory === "global" || event.project === project.project()) {
handler(event.payload, { workspace: event.workspace }) handler(event.payload, { workspace: event.workspace })
} }
@@ -428,11 +428,22 @@ export const layer = Layer.effect(
yield* parseSSE(stream, (evt) => yield* parseSSE(stream, (evt) =>
Effect.gen(function* () { Effect.gen(function* () {
if (!evt || typeof evt !== "object" || !("payload" in evt)) return if (!evt || typeof evt !== "object" || !("payload" in evt)) return
const payload = evt.payload as { type?: string; syncEvent?: SyncEvent.SerializedEvent } const payload = evt.payload as {
id?: string
type?: string
sync?: { name: string; seq: number; aggregateID: string; data: unknown }
}
if (payload.type === "server.heartbeat") return if (payload.type === "server.heartbeat") return
if (payload.type === "sync" && payload.syncEvent) { if (payload.sync) {
const failed = yield* sync.replay(payload.syncEvent).pipe( const serialized: SyncEvent.SerializedEvent = {
id: payload.id ?? "",
type: payload.sync.name,
seq: payload.sync.seq,
aggregateID: payload.sync.aggregateID,
data: payload.sync.data as never,
}
const failed = yield* sync.replay(serialized).pipe(
Effect.as(false), Effect.as(false),
Effect.catchCause((error) => Effect.catchCause((error) =>
Effect.sync(() => { Effect.sync(() => {
@@ -1,6 +1,5 @@
import { Config } from "@/config/config" import { Config } from "@/config/config"
import { BusEvent } from "@/bus/bus-event" import { BusEvent } from "@/bus/bus-event"
import { SyncEvent } from "@/sync"
import "@/server/event" import "@/server/event"
import { Schema } from "effect" import { Schema } from "effect"
import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi" import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
@@ -15,7 +14,10 @@ const GlobalEventSchema = Schema.Struct({
directory: Schema.String, directory: Schema.String,
project: Schema.optional(Schema.String), project: Schema.optional(Schema.String),
workspace: Schema.optional(Schema.String), workspace: Schema.optional(Schema.String),
payload: Schema.Union([...BusEvent.effectPayloads(), ...SyncEvent.effectPayloads()]), // One shape per event. Source-of-truth sync metadata, when present, is
// carried as an optional `sync` field inside the payload — see
// `BusEvent.effectPayloads()`.
payload: Schema.Union(BusEvent.effectPayloads()),
}).annotate({ identifier: "GlobalEvent" }) }).annotate({ identifier: "GlobalEvent" })
export const GlobalUpgradeInput = Schema.Struct({ export const GlobalUpgradeInput = Schema.Struct({
+7 -15
View File
@@ -4,7 +4,6 @@
// Remove that registry read when event schemas are generated from core directly. // Remove that registry read when event schemas are generated from core directly.
import { Database } from "@/storage/db" import { Database } from "@/storage/db"
import { eq } from "drizzle-orm" import { eq } from "drizzle-orm"
import { GlobalBus } from "@/bus/global"
import { Bus as ProjectBus } from "@/bus" import { Bus as ProjectBus } from "@/bus"
import { BusEvent } from "@/bus/bus-event" import { BusEvent } from "@/bus/bus-event"
import type { InstanceContext } from "@/project/instance-context" import type { InstanceContext } from "@/project/instance-context"
@@ -356,10 +355,16 @@ function process<Def extends Definition>(
throw new Error("SyncEvent.process: publish requires instance context") throw new Error("SyncEvent.process: publish requires instance context")
} }
const sync: ProjectBus.SyncMetadata = {
name: versionedType(def.type, def.version),
seq: event.seq,
aggregateID: event.aggregateID,
data: event.data,
}
const result = convertEvent(def.type, event.data) const result = convertEvent(def.type, event.data)
const publish = (data: unknown) => const publish = (data: unknown) =>
Effect.runPromise( Effect.runPromise(
attachWith(options.bus.publish(def, data as Properties<Def>, { id: event.id }), { attachWith(options.bus.publish(def, data as Properties<Def>, { id: event.id, sync }), {
instance: options.context?.instance, instance: options.context?.instance,
workspace: options.context?.workspace, workspace: options.context?.workspace,
}), }),
@@ -369,19 +374,6 @@ function process<Def extends Definition>(
} else { } else {
void publish(result) void publish(result)
} }
GlobalBus.emit("event", {
directory: options.context.instance.directory,
project: options.context.instance.project.id,
workspace: options.context.workspace,
payload: {
type: "sync",
syncEvent: {
type: versionedType(def.type, def.version),
...event,
},
},
})
} }
}) })
}) })
+131 -36
View File
@@ -5,10 +5,10 @@ export type ClientOptions = {
} }
export type Event = export type Event =
| EventTuiPromptAppend | EventTuiPromptAppend1
| EventTuiCommandExecute | EventTuiCommandExecute1
| EventTuiToastShow1 | EventTuiToastShow1
| EventTuiSessionSelect | EventTuiSessionSelect1
| EventServerConnected | EventServerConnected
| EventGlobalDisposed | EventGlobalDisposed
| EventServerInstanceDisposed | EventServerInstanceDisposed
@@ -110,6 +110,7 @@ export type EventTuiPromptAppend = {
properties: { properties: {
text: string text: string
} }
sync?: EventSync
} }
export type EventTuiCommandExecute = { export type EventTuiCommandExecute = {
@@ -135,6 +136,7 @@ export type EventTuiCommandExecute = {
| "agent.cycle" | "agent.cycle"
| string | string
} }
sync?: EventSync
} }
export type EventTuiToastShow = { export type EventTuiToastShow = {
@@ -146,6 +148,7 @@ export type EventTuiToastShow = {
variant: "info" | "success" | "warning" | "error" variant: "info" | "success" | "warning" | "error"
duration?: number duration?: number
} }
sync?: EventSync
} }
export type EventTuiSessionSelect = { export type EventTuiSessionSelect = {
@@ -157,6 +160,7 @@ export type EventTuiSessionSelect = {
*/ */
sessionID: string sessionID: string
} }
sync?: EventSync
} }
export type PermissionRequest = { export type PermissionRequest = {
@@ -863,39 +867,6 @@ export type GlobalEvent = {
| EventSessionNextCompactionDelta | EventSessionNextCompactionDelta
| EventSessionNextCompactionEnded | EventSessionNextCompactionEnded
| EventCatalogModelUpdated | EventCatalogModelUpdated
| SyncEventMessageUpdated
| SyncEventMessageRemoved
| SyncEventMessagePartUpdated
| SyncEventMessagePartRemoved
| SyncEventSessionCreated
| SyncEventSessionUpdated
| SyncEventSessionDeleted
| SyncEventSessionNextAgentSwitched
| SyncEventSessionNextModelSwitched
| SyncEventSessionNextPrompted
| SyncEventSessionNextSynthetic
| SyncEventSessionNextShellStarted
| SyncEventSessionNextShellEnded
| SyncEventSessionNextStepStarted
| SyncEventSessionNextStepEnded
| SyncEventSessionNextStepFailed
| SyncEventSessionNextTextStarted
| SyncEventSessionNextTextDelta
| SyncEventSessionNextTextEnded
| SyncEventSessionNextReasoningStarted
| SyncEventSessionNextReasoningDelta
| SyncEventSessionNextReasoningEnded
| SyncEventSessionNextToolInputStarted
| SyncEventSessionNextToolInputDelta
| SyncEventSessionNextToolInputEnded
| SyncEventSessionNextToolCalled
| SyncEventSessionNextToolProgress
| SyncEventSessionNextToolSuccess
| SyncEventSessionNextToolFailed
| SyncEventSessionNextRetried
| SyncEventSessionNextCompactionStarted
| SyncEventSessionNextCompactionDelta
| SyncEventSessionNextCompactionEnded
} }
/** /**
@@ -2403,12 +2374,20 @@ export type SyncEventSessionNextCompactionEnded = {
} }
} }
export type EventSync = {
name: string
seq: number
aggregateID: string
data: unknown
}
export type EventServerConnected = { export type EventServerConnected = {
id: string id: string
type: "server.connected" type: "server.connected"
properties: { properties: {
[key: string]: unknown [key: string]: unknown
} }
sync?: EventSync
} }
export type EventGlobalDisposed = { export type EventGlobalDisposed = {
@@ -2417,6 +2396,7 @@ export type EventGlobalDisposed = {
properties: { properties: {
[key: string]: unknown [key: string]: unknown
} }
sync?: EventSync
} }
export type EventServerInstanceDisposed = { export type EventServerInstanceDisposed = {
@@ -2425,6 +2405,7 @@ export type EventServerInstanceDisposed = {
properties: { properties: {
directory: string directory: string
} }
sync?: EventSync
} }
export type EventFileEdited = { export type EventFileEdited = {
@@ -2433,6 +2414,7 @@ export type EventFileEdited = {
properties: { properties: {
file: string file: string
} }
sync?: EventSync
} }
export type EventFileWatcherUpdated = { export type EventFileWatcherUpdated = {
@@ -2442,6 +2424,7 @@ export type EventFileWatcherUpdated = {
file: string file: string
event: "add" | "change" | "unlink" event: "add" | "change" | "unlink"
} }
sync?: EventSync
} }
export type EventLspClientDiagnostics = { export type EventLspClientDiagnostics = {
@@ -2451,6 +2434,7 @@ export type EventLspClientDiagnostics = {
serverID: string serverID: string
path: string path: string
} }
sync?: EventSync
} }
export type EventLspUpdated = { export type EventLspUpdated = {
@@ -2459,6 +2443,7 @@ export type EventLspUpdated = {
properties: { properties: {
[key: string]: unknown [key: string]: unknown
} }
sync?: EventSync
} }
export type EventMessagePartDelta = { export type EventMessagePartDelta = {
@@ -2471,12 +2456,14 @@ export type EventMessagePartDelta = {
field: string field: string
delta: string delta: string
} }
sync?: EventSync
} }
export type EventPermissionAsked = { export type EventPermissionAsked = {
id: string id: string
type: "permission.asked" type: "permission.asked"
properties: PermissionRequest properties: PermissionRequest
sync?: EventSync
} }
export type EventPermissionReplied = { export type EventPermissionReplied = {
@@ -2487,6 +2474,7 @@ export type EventPermissionReplied = {
requestID: string requestID: string
reply: "once" | "always" | "reject" reply: "once" | "always" | "reject"
} }
sync?: EventSync
} }
export type EventSessionDiff = { export type EventSessionDiff = {
@@ -2496,6 +2484,7 @@ export type EventSessionDiff = {
sessionID: string sessionID: string
diff: Array<SnapshotFileDiff> diff: Array<SnapshotFileDiff>
} }
sync?: EventSync
} }
export type EventSessionError = { export type EventSessionError = {
@@ -2512,24 +2501,28 @@ export type EventSessionError = {
| ContextOverflowError | ContextOverflowError
| ApiError | ApiError
} }
sync?: EventSync
} }
export type EventQuestionAsked = { export type EventQuestionAsked = {
id: string id: string
type: "question.asked" type: "question.asked"
properties: QuestionRequest properties: QuestionRequest
sync?: EventSync
} }
export type EventQuestionReplied = { export type EventQuestionReplied = {
id: string id: string
type: "question.replied" type: "question.replied"
properties: QuestionReplied properties: QuestionReplied
sync?: EventSync
} }
export type EventQuestionRejected = { export type EventQuestionRejected = {
id: string id: string
type: "question.rejected" type: "question.rejected"
properties: QuestionRejected properties: QuestionRejected
sync?: EventSync
} }
export type EventTodoUpdated = { export type EventTodoUpdated = {
@@ -2539,6 +2532,7 @@ export type EventTodoUpdated = {
sessionID: string sessionID: string
todos: Array<Todo> todos: Array<Todo>
} }
sync?: EventSync
} }
export type EventSessionStatus = { export type EventSessionStatus = {
@@ -2548,6 +2542,7 @@ export type EventSessionStatus = {
sessionID: string sessionID: string
status: SessionStatus status: SessionStatus
} }
sync?: EventSync
} }
export type EventSessionIdle = { export type EventSessionIdle = {
@@ -2556,6 +2551,7 @@ export type EventSessionIdle = {
properties: { properties: {
sessionID: string sessionID: string
} }
sync?: EventSync
} }
export type EventMcpToolsChanged = { export type EventMcpToolsChanged = {
@@ -2564,6 +2560,7 @@ export type EventMcpToolsChanged = {
properties: { properties: {
server: string server: string
} }
sync?: EventSync
} }
export type EventMcpBrowserOpenFailed = { export type EventMcpBrowserOpenFailed = {
@@ -2573,6 +2570,7 @@ export type EventMcpBrowserOpenFailed = {
mcpName: string mcpName: string
url: string url: string
} }
sync?: EventSync
} }
export type EventCommandExecuted = { export type EventCommandExecuted = {
@@ -2584,12 +2582,14 @@ export type EventCommandExecuted = {
arguments: string arguments: string
messageID: string messageID: string
} }
sync?: EventSync
} }
export type EventProjectUpdated = { export type EventProjectUpdated = {
id: string id: string
type: "project.updated" type: "project.updated"
properties: Project properties: Project
sync?: EventSync
} }
export type EventSessionCompacted = { export type EventSessionCompacted = {
@@ -2598,6 +2598,7 @@ export type EventSessionCompacted = {
properties: { properties: {
sessionID: string sessionID: string
} }
sync?: EventSync
} }
export type EventVcsBranchUpdated = { export type EventVcsBranchUpdated = {
@@ -2606,6 +2607,7 @@ export type EventVcsBranchUpdated = {
properties: { properties: {
branch?: string branch?: string
} }
sync?: EventSync
} }
export type EventWorkspaceReady = { export type EventWorkspaceReady = {
@@ -2614,6 +2616,7 @@ export type EventWorkspaceReady = {
properties: { properties: {
name: string name: string
} }
sync?: EventSync
} }
export type EventWorkspaceFailed = { export type EventWorkspaceFailed = {
@@ -2622,6 +2625,7 @@ export type EventWorkspaceFailed = {
properties: { properties: {
message: string message: string
} }
sync?: EventSync
} }
export type EventWorkspaceStatus = { export type EventWorkspaceStatus = {
@@ -2631,6 +2635,7 @@ export type EventWorkspaceStatus = {
workspaceID: string workspaceID: string
status: "connected" | "connecting" | "disconnected" | "error" status: "connected" | "connecting" | "disconnected" | "error"
} }
sync?: EventSync
} }
export type EventWorktreeReady = { export type EventWorktreeReady = {
@@ -2640,6 +2645,7 @@ export type EventWorktreeReady = {
name: string name: string
branch?: string branch?: string
} }
sync?: EventSync
} }
export type EventWorktreeFailed = { export type EventWorktreeFailed = {
@@ -2648,6 +2654,7 @@ export type EventWorktreeFailed = {
properties: { properties: {
message: string message: string
} }
sync?: EventSync
} }
export type EventPtyCreated = { export type EventPtyCreated = {
@@ -2656,6 +2663,7 @@ export type EventPtyCreated = {
properties: { properties: {
info: Pty info: Pty
} }
sync?: EventSync
} }
export type EventPtyUpdated = { export type EventPtyUpdated = {
@@ -2664,6 +2672,7 @@ export type EventPtyUpdated = {
properties: { properties: {
info: Pty info: Pty
} }
sync?: EventSync
} }
export type EventPtyExited = { export type EventPtyExited = {
@@ -2673,6 +2682,7 @@ export type EventPtyExited = {
id: string id: string
exitCode: number exitCode: number
} }
sync?: EventSync
} }
export type EventPtyDeleted = { export type EventPtyDeleted = {
@@ -2681,6 +2691,7 @@ export type EventPtyDeleted = {
properties: { properties: {
id: string id: string
} }
sync?: EventSync
} }
export type EventInstallationUpdated = { export type EventInstallationUpdated = {
@@ -2689,6 +2700,7 @@ export type EventInstallationUpdated = {
properties: { properties: {
version: string version: string
} }
sync?: EventSync
} }
export type EventInstallationUpdateAvailable = { export type EventInstallationUpdateAvailable = {
@@ -2697,6 +2709,7 @@ export type EventInstallationUpdateAvailable = {
properties: { properties: {
version: string version: string
} }
sync?: EventSync
} }
export type EventMessageUpdated = { export type EventMessageUpdated = {
@@ -2706,6 +2719,7 @@ export type EventMessageUpdated = {
sessionID: string sessionID: string
info: Message info: Message
} }
sync?: EventSync
} }
export type EventMessageRemoved = { export type EventMessageRemoved = {
@@ -2715,6 +2729,7 @@ export type EventMessageRemoved = {
sessionID: string sessionID: string
messageID: string messageID: string
} }
sync?: EventSync
} }
export type EventMessagePartUpdated = { export type EventMessagePartUpdated = {
@@ -2725,6 +2740,7 @@ export type EventMessagePartUpdated = {
part: Part part: Part
time: number time: number
} }
sync?: EventSync
} }
export type EventMessagePartRemoved = { export type EventMessagePartRemoved = {
@@ -2735,6 +2751,7 @@ export type EventMessagePartRemoved = {
messageID: string messageID: string
partID: string partID: string
} }
sync?: EventSync
} }
export type EventSessionCreated = { export type EventSessionCreated = {
@@ -2744,6 +2761,7 @@ export type EventSessionCreated = {
sessionID: string sessionID: string
info: Session info: Session
} }
sync?: EventSync
} }
export type EventSessionUpdated = { export type EventSessionUpdated = {
@@ -2753,6 +2771,7 @@ export type EventSessionUpdated = {
sessionID: string sessionID: string
info: Session info: Session
} }
sync?: EventSync
} }
export type EventSessionDeleted = { export type EventSessionDeleted = {
@@ -2762,6 +2781,7 @@ export type EventSessionDeleted = {
sessionID: string sessionID: string
info: Session info: Session
} }
sync?: EventSync
} }
export type EventSessionNextAgentSwitched = { export type EventSessionNextAgentSwitched = {
@@ -2772,6 +2792,7 @@ export type EventSessionNextAgentSwitched = {
sessionID: string sessionID: string
agent: string agent: string
} }
sync?: EventSync
} }
export type EventSessionNextModelSwitched = { export type EventSessionNextModelSwitched = {
@@ -2786,6 +2807,7 @@ export type EventSessionNextModelSwitched = {
variant: string variant: string
} }
} }
sync?: EventSync
} }
export type PromptSource = { export type PromptSource = {
@@ -2827,6 +2849,7 @@ export type EventSessionNextPrompted = {
sessionID: string sessionID: string
prompt: Prompt prompt: Prompt
} }
sync?: EventSync
} }
export type EventSessionNextSynthetic = { export type EventSessionNextSynthetic = {
@@ -2837,6 +2860,7 @@ export type EventSessionNextSynthetic = {
sessionID: string sessionID: string
text: string text: string
} }
sync?: EventSync
} }
export type EventSessionNextShellStarted = { export type EventSessionNextShellStarted = {
@@ -2848,6 +2872,7 @@ export type EventSessionNextShellStarted = {
callID: string callID: string
command: string command: string
} }
sync?: EventSync
} }
export type EventSessionNextShellEnded = { export type EventSessionNextShellEnded = {
@@ -2859,6 +2884,7 @@ export type EventSessionNextShellEnded = {
callID: string callID: string
output: string output: string
} }
sync?: EventSync
} }
export type EventSessionNextStepStarted = { export type EventSessionNextStepStarted = {
@@ -2875,6 +2901,7 @@ export type EventSessionNextStepStarted = {
} }
snapshot?: string snapshot?: string
} }
sync?: EventSync
} }
export type EventSessionNextStepEnded = { export type EventSessionNextStepEnded = {
@@ -2896,6 +2923,7 @@ export type EventSessionNextStepEnded = {
} }
snapshot?: string snapshot?: string
} }
sync?: EventSync
} }
export type SessionErrorUnknown = { export type SessionErrorUnknown = {
@@ -2911,6 +2939,7 @@ export type EventSessionNextStepFailed = {
sessionID: string sessionID: string
error: SessionErrorUnknown error: SessionErrorUnknown
} }
sync?: EventSync
} }
export type EventSessionNextTextStarted = { export type EventSessionNextTextStarted = {
@@ -2920,6 +2949,7 @@ export type EventSessionNextTextStarted = {
timestamp: number timestamp: number
sessionID: string sessionID: string
} }
sync?: EventSync
} }
export type EventSessionNextTextDelta = { export type EventSessionNextTextDelta = {
@@ -2930,6 +2960,7 @@ export type EventSessionNextTextDelta = {
sessionID: string sessionID: string
delta: string delta: string
} }
sync?: EventSync
} }
export type EventSessionNextTextEnded = { export type EventSessionNextTextEnded = {
@@ -2940,6 +2971,7 @@ export type EventSessionNextTextEnded = {
sessionID: string sessionID: string
text: string text: string
} }
sync?: EventSync
} }
export type EventSessionNextReasoningStarted = { export type EventSessionNextReasoningStarted = {
@@ -2950,6 +2982,7 @@ export type EventSessionNextReasoningStarted = {
sessionID: string sessionID: string
reasoningID: string reasoningID: string
} }
sync?: EventSync
} }
export type EventSessionNextReasoningDelta = { export type EventSessionNextReasoningDelta = {
@@ -2961,6 +2994,7 @@ export type EventSessionNextReasoningDelta = {
reasoningID: string reasoningID: string
delta: string delta: string
} }
sync?: EventSync
} }
export type EventSessionNextReasoningEnded = { export type EventSessionNextReasoningEnded = {
@@ -2972,6 +3006,7 @@ export type EventSessionNextReasoningEnded = {
reasoningID: string reasoningID: string
text: string text: string
} }
sync?: EventSync
} }
export type EventSessionNextToolInputStarted = { export type EventSessionNextToolInputStarted = {
@@ -2983,6 +3018,7 @@ export type EventSessionNextToolInputStarted = {
callID: string callID: string
name: string name: string
} }
sync?: EventSync
} }
export type EventSessionNextToolInputDelta = { export type EventSessionNextToolInputDelta = {
@@ -2994,6 +3030,7 @@ export type EventSessionNextToolInputDelta = {
callID: string callID: string
delta: string delta: string
} }
sync?: EventSync
} }
export type EventSessionNextToolInputEnded = { export type EventSessionNextToolInputEnded = {
@@ -3005,6 +3042,7 @@ export type EventSessionNextToolInputEnded = {
callID: string callID: string
text: string text: string
} }
sync?: EventSync
} }
export type EventSessionNextToolCalled = { export type EventSessionNextToolCalled = {
@@ -3025,6 +3063,7 @@ export type EventSessionNextToolCalled = {
} }
} }
} }
sync?: EventSync
} }
export type ToolTextContent = { export type ToolTextContent = {
@@ -3051,6 +3090,7 @@ export type EventSessionNextToolProgress = {
} }
content: Array<ToolTextContent | ToolFileContent> content: Array<ToolTextContent | ToolFileContent>
} }
sync?: EventSync
} }
export type EventSessionNextToolSuccess = { export type EventSessionNextToolSuccess = {
@@ -3071,6 +3111,7 @@ export type EventSessionNextToolSuccess = {
} }
} }
} }
sync?: EventSync
} }
export type EventSessionNextToolFailed = { export type EventSessionNextToolFailed = {
@@ -3088,6 +3129,7 @@ export type EventSessionNextToolFailed = {
} }
} }
} }
sync?: EventSync
} }
export type SessionNextRetryError = { export type SessionNextRetryError = {
@@ -3112,6 +3154,7 @@ export type EventSessionNextRetried = {
attempt: number attempt: number
error: SessionNextRetryError error: SessionNextRetryError
} }
sync?: EventSync
} }
export type EventSessionNextCompactionStarted = { export type EventSessionNextCompactionStarted = {
@@ -3122,6 +3165,7 @@ export type EventSessionNextCompactionStarted = {
sessionID: string sessionID: string
reason: "auto" | "manual" reason: "auto" | "manual"
} }
sync?: EventSync
} }
export type EventSessionNextCompactionDelta = { export type EventSessionNextCompactionDelta = {
@@ -3132,6 +3176,7 @@ export type EventSessionNextCompactionDelta = {
sessionID: string sessionID: string
text: string text: string
} }
sync?: EventSync
} }
export type EventSessionNextCompactionEnded = { export type EventSessionNextCompactionEnded = {
@@ -3143,6 +3188,7 @@ export type EventSessionNextCompactionEnded = {
text: string text: string
include?: string include?: string
} }
sync?: EventSync
} }
export type ModelV2Info = { export type ModelV2Info = {
@@ -3249,6 +3295,7 @@ export type EventCatalogModelUpdated = {
properties: { properties: {
model: ModelV2Info model: ModelV2Info
} }
sync?: EventSync
} }
export type SessionInfo = { export type SessionInfo = {
@@ -3553,6 +3600,41 @@ export type ProviderV2Info = {
} }
} }
export type EventTuiPromptAppend1 = {
id: string
type: "tui.prompt.append"
properties: {
text: string
}
sync?: EventSync
}
export type EventTuiCommandExecute1 = {
id: string
type: "tui.command.execute"
properties: {
command:
| "session.list"
| "session.new"
| "session.share"
| "session.interrupt"
| "session.compact"
| "session.page.up"
| "session.page.down"
| "session.line.up"
| "session.line.down"
| "session.half.page.up"
| "session.half.page.down"
| "session.first"
| "session.last"
| "prompt.clear"
| "prompt.submit"
| "agent.cycle"
| string
}
sync?: EventSync
}
export type EventTuiToastShow1 = { export type EventTuiToastShow1 = {
id: string id: string
type: "tui.toast.show" type: "tui.toast.show"
@@ -3562,6 +3644,19 @@ export type EventTuiToastShow1 = {
variant: "info" | "success" | "warning" | "error" variant: "info" | "success" | "warning" | "error"
duration?: number duration?: number
} }
sync?: EventSync
}
export type EventTuiSessionSelect1 = {
id: string
type: "tui.session.select"
properties: {
/**
* Session ID to navigate to
*/
sessionID: string
}
sync?: EventSync
} }
export type ModelV2Info1 = { export type ModelV2Info1 = {