refactor(core): publish sync events to global event stream (#22347)

This commit is contained in:
James Long
2026-04-13 16:51:59 -04:00
committed by GitHub
parent 67aaecacac
commit b22add292c
10 changed files with 597 additions and 409 deletions
+6 -1
View File
@@ -155,7 +155,12 @@ export const { use: useGlobalSDK, provider: GlobalSDKProvider } = createSimpleCo
resetHeartbeat() resetHeartbeat()
streamErrorLogged = false streamErrorLogged = false
const directory = event.directory ?? "global" const directory = event.directory ?? "global"
const payload = event.payload if (event.payload.type === "sync") {
continue
}
const payload = event.payload as Event
const k = key(directory, payload) const k = key(directory, payload)
if (k) { if (k) {
const i = coalesced.get(k) const i = coalesced.get(k)
+2 -9
View File
@@ -16,10 +16,7 @@ export namespace BusEvent {
} }
export function payloads() { export function payloads() {
return z return registry
.discriminatedUnion(
"type",
registry
.entries() .entries()
.map(([type, def]) => { .map(([type, def]) => {
return z return z
@@ -31,10 +28,6 @@ export namespace BusEvent {
ref: "Event" + "." + def.type, ref: "Event" + "." + def.type,
}) })
}) })
.toArray() as any, .toArray()
)
.meta({
ref: "Event",
})
} }
} }
@@ -8,6 +8,10 @@ export function useEvent() {
function subscribe(handler: (event: Event) => void) { function subscribe(handler: (event: Event) => void) {
return sdk.event.on("event", (event) => { return sdk.event.on("event", (event) => {
if (event.payload.type === "sync") {
return
}
// Special hack for truly global events // Special hack for truly global events
if (event.directory === "global") { if (event.directory === "global") {
handler(event.payload) handler(event.payload)
@@ -21,8 +21,6 @@ const disposal = {
all: undefined as Promise<void> | undefined, all: undefined as Promise<void> | undefined,
} }
function emitDisposed(directory: string) {}
function boot(input: { directory: string; init?: () => Promise<any>; worktree?: string; project?: Project.Info }) { function boot(input: { directory: string; init?: () => Promise<any>; worktree?: string; project?: Project.Info }) {
return iife(async () => { return iife(async () => {
const ctx = const ctx =
@@ -1,8 +1,10 @@
import z from "zod"
import { Hono } from "hono" import { Hono } from "hono"
import { describeRoute, resolver } from "hono-openapi" import { describeRoute, resolver } from "hono-openapi"
import { streamSSE } from "hono/streaming" import { streamSSE } from "hono/streaming"
import { Log } from "@/util/log" import { Log } from "@/util/log"
import { BusEvent } from "@/bus/bus-event" import { BusEvent } from "@/bus/bus-event"
import { SyncEvent } from "@/sync"
import { Bus } from "@/bus" import { Bus } from "@/bus"
import { AsyncQueue } from "../../util/queue" import { AsyncQueue } from "../../util/queue"
@@ -20,7 +22,11 @@ export const EventRoutes = () =>
description: "Event stream", description: "Event stream",
content: { content: {
"text/event-stream": { "text/event-stream": {
schema: resolver(BusEvent.payloads()), schema: resolver(
z.union(BusEvent.payloads()).meta({
ref: "Event",
}),
),
}, },
}, },
}, },
@@ -109,7 +109,7 @@ export const GlobalRoutes = lazy(() =>
directory: z.string(), directory: z.string(),
project: z.string().optional(), project: z.string().optional(),
workspace: z.string().optional(), workspace: z.string().optional(),
payload: BusEvent.payloads(), payload: z.union([...BusEvent.payloads(), ...SyncEvent.payloads()]),
}) })
.meta({ .meta({
ref: "GlobalEvent", ref: "GlobalEvent",
@@ -135,52 +135,6 @@ export const GlobalRoutes = lazy(() =>
}) })
}, },
) )
.get(
"/sync-event",
describeRoute({
summary: "Subscribe to global sync events",
description: "Get global sync events",
operationId: "global.sync-event.subscribe",
responses: {
200: {
description: "Event stream",
content: {
"text/event-stream": {
schema: resolver(
z
.object({
payload: SyncEvent.payloads(),
})
.meta({
ref: "SyncEvent",
}),
),
},
},
},
},
}),
async (c) => {
log.info("global sync event connected")
c.header("Cache-Control", "no-cache, no-transform")
c.header("X-Accel-Buffering", "no")
c.header("X-Content-Type-Options", "nosniff")
return streamEvents(c, (q) => {
return SyncEvent.subscribeAll(({ def, event }) => {
// TODO: don't pass def, just pass the type (and it should
// be versioned)
q.push(
JSON.stringify({
payload: {
...event,
type: SyncEvent.versionedType(def.type, def.version),
},
}),
)
})
})
},
)
.get( .get(
"/config", "/config",
describeRoute({ describeRoute({
+21 -22
View File
@@ -2,9 +2,12 @@ import z from "zod"
import type { ZodObject } from "zod" import type { ZodObject } from "zod"
import { EventEmitter } from "events" import { EventEmitter } from "events"
import { Database, eq } from "@/storage/db" import { Database, eq } from "@/storage/db"
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 { Instance } from "@/project/instance"
import { EventSequenceTable, EventTable } from "./event.sql" import { EventSequenceTable, EventTable } from "./event.sql"
import { WorkspaceContext } from "@/control-plane/workspace-context"
import { EventID } from "./schema" import { EventID } from "./schema"
import { Flag } from "@/flag/flag" import { Flag } from "@/flag/flag"
@@ -37,8 +40,6 @@ export namespace SyncEvent {
let frozen = false let frozen = false
let convertEvent: (type: string, event: Event["data"]) => Promise<Record<string, unknown>> | Record<string, unknown> let convertEvent: (type: string, event: Event["data"]) => Promise<Record<string, unknown>> | Record<string, unknown>
const Bus = new EventEmitter<{ event: [{ def: Definition; event: Event }] }>()
export function reset() { export function reset() {
frozen = false frozen = false
projectors = undefined projectors = undefined
@@ -140,11 +141,6 @@ export namespace SyncEvent {
} }
Database.effect(() => { Database.effect(() => {
Bus.emit("event", {
def,
event,
})
if (options?.publish) { if (options?.publish) {
const result = convertEvent(def.type, event.data) const result = convertEvent(def.type, event.data)
if (result instanceof Promise) { if (result instanceof Promise) {
@@ -154,6 +150,17 @@ export namespace SyncEvent {
} else { } else {
ProjectBus.publish({ type: def.type, properties: def.schema }, result) ProjectBus.publish({ type: def.type, properties: def.schema }, result)
} }
GlobalBus.emit("event", {
directory: Instance.directory,
project: Instance.project.id,
workspace: WorkspaceContext.workspaceID,
payload: {
type: "sync",
name: versionedType(def.type, def.version),
...event,
},
})
} }
}) })
}) })
@@ -235,31 +242,23 @@ export namespace SyncEvent {
}) })
} }
export function subscribeAll(handler: (event: { def: Definition; event: Event }) => void) {
Bus.on("event", handler)
return () => Bus.off("event", handler)
}
export function payloads() { export function payloads() {
return z return registry
.union(
registry
.entries() .entries()
.map(([type, def]) => { .map(([type, def]) => {
return z return z
.object({ .object({
type: z.literal(type), type: z.literal("sync"),
aggregate: z.literal(def.aggregate), name: z.literal(type),
id: z.string(),
seq: z.number(),
aggregateID: z.literal(def.aggregate),
data: def.schema, data: def.schema,
}) })
.meta({ .meta({
ref: "SyncEvent" + "." + def.type, ref: "SyncEvent" + "." + def.type,
}) })
}) })
.toArray() as any, .toArray()
)
.meta({
ref: "SyncEvent",
})
} }
} }
-20
View File
@@ -51,7 +51,6 @@ import type {
GlobalDisposeResponses, GlobalDisposeResponses,
GlobalEventResponses, GlobalEventResponses,
GlobalHealthResponses, GlobalHealthResponses,
GlobalSyncEventSubscribeResponses,
GlobalUpgradeErrors, GlobalUpgradeErrors,
GlobalUpgradeResponses, GlobalUpgradeResponses,
InstanceDisposeResponses, InstanceDisposeResponses,
@@ -237,20 +236,6 @@ class HeyApiRegistry<T> {
} }
} }
export class SyncEvent extends HeyApiClient {
/**
* Subscribe to global sync events
*
* Get global sync events
*/
public subscribe<ThrowOnError extends boolean = false>(options?: Options<never, ThrowOnError>) {
return (options?.client ?? this.client).sse.get<GlobalSyncEventSubscribeResponses, unknown, ThrowOnError>({
url: "/global/sync-event",
...options,
})
}
}
export class Config extends HeyApiClient { export class Config extends HeyApiClient {
/** /**
* Get global configuration * Get global configuration
@@ -350,11 +335,6 @@ export class Global extends HeyApiClient {
}) })
} }
private _syncEvent?: SyncEvent
get syncEvent(): SyncEvent {
return (this._syncEvent ??= new SyncEvent({ client: this.client }))
}
private _config?: Config private _config?: Config
get config(): Config { get config(): Config {
return (this._config ??= new Config({ client: this.client })) return (this._config ??= new Config({ client: this.client }))
+177 -124
View File
@@ -971,7 +971,128 @@ export type EventSessionDeleted = {
} }
} }
export type Event = export type SyncEventMessageUpdated = {
type: "sync"
name: "message.updated.1"
id: string
seq: number
aggregateID: "sessionID"
data: {
sessionID: string
info: Message
}
}
export type SyncEventMessageRemoved = {
type: "sync"
name: "message.removed.1"
id: string
seq: number
aggregateID: "sessionID"
data: {
sessionID: string
messageID: string
}
}
export type SyncEventMessagePartUpdated = {
type: "sync"
name: "message.part.updated.1"
id: string
seq: number
aggregateID: "sessionID"
data: {
sessionID: string
part: Part
time: number
}
}
export type SyncEventMessagePartRemoved = {
type: "sync"
name: "message.part.removed.1"
id: string
seq: number
aggregateID: "sessionID"
data: {
sessionID: string
messageID: string
partID: string
}
}
export type SyncEventSessionCreated = {
type: "sync"
name: "session.created.1"
id: string
seq: number
aggregateID: "sessionID"
data: {
sessionID: string
info: Session
}
}
export type SyncEventSessionUpdated = {
type: "sync"
name: "session.updated.1"
id: string
seq: number
aggregateID: "sessionID"
data: {
sessionID: string
info: {
id: string | null
slug: string | null
projectID: string | null
workspaceID: string | null
directory: string | null
parentID: string | null
summary: {
additions: number
deletions: number
files: number
diffs?: Array<SnapshotFileDiff>
} | null
share?: {
url: string | null
}
title: string | null
version: string | null
time?: {
created: number | null
updated: number | null
compacting: number | null
archived: number | null
}
permission: PermissionRuleset | null
revert: {
messageID: string
partID?: string
snapshot?: string
diff?: string
} | null
}
}
}
export type SyncEventSessionDeleted = {
type: "sync"
name: "session.deleted.1"
id: string
seq: number
aggregateID: "sessionID"
data: {
sessionID: string
info: Session
}
}
export type GlobalEvent = {
directory: string
project?: string
workspace?: string
payload:
| EventProjectUpdated | EventProjectUpdated
| EventServerInstanceDisposed | EventServerInstanceDisposed
| EventInstallationUpdated | EventInstallationUpdated
@@ -1018,112 +1139,13 @@ export type Event =
| EventSessionCreated | EventSessionCreated
| EventSessionUpdated | EventSessionUpdated
| EventSessionDeleted | EventSessionDeleted
| SyncEventMessageUpdated
export type GlobalEvent = { | SyncEventMessageRemoved
directory: string | SyncEventMessagePartUpdated
project?: string | SyncEventMessagePartRemoved
workspace?: string | SyncEventSessionCreated
payload: Event | SyncEventSessionUpdated
} | SyncEventSessionDeleted
export type SyncEventMessageUpdated = {
type: "message.updated.1"
aggregate: "sessionID"
data: {
sessionID: string
info: Message
}
}
export type SyncEventMessageRemoved = {
type: "message.removed.1"
aggregate: "sessionID"
data: {
sessionID: string
messageID: string
}
}
export type SyncEventMessagePartUpdated = {
type: "message.part.updated.1"
aggregate: "sessionID"
data: {
sessionID: string
part: Part
time: number
}
}
export type SyncEventMessagePartRemoved = {
type: "message.part.removed.1"
aggregate: "sessionID"
data: {
sessionID: string
messageID: string
partID: string
}
}
export type SyncEventSessionCreated = {
type: "session.created.1"
aggregate: "sessionID"
data: {
sessionID: string
info: Session
}
}
export type SyncEventSessionUpdated = {
type: "session.updated.1"
aggregate: "sessionID"
data: {
sessionID: string
info: {
id: string | null
slug: string | null
projectID: string | null
workspaceID: string | null
directory: string | null
parentID: string | null
summary: {
additions: number
deletions: number
files: number
diffs?: Array<SnapshotFileDiff>
} | null
share?: {
url: string | null
}
title: string | null
version: string | null
time?: {
created: number | null
updated: number | null
compacting: number | null
archived: number | null
}
permission: PermissionRuleset | null
revert: {
messageID: string
partID?: string
snapshot?: string
diff?: string
} | null
}
}
}
export type SyncEventSessionDeleted = {
type: "session.deleted.1"
aggregate: "sessionID"
data: {
sessionID: string
info: Session
}
}
export type SyncEvent = {
payload: SyncEvent
} }
/** /**
@@ -1982,6 +2004,54 @@ export type File = {
status: "added" | "deleted" | "modified" status: "added" | "deleted" | "modified"
} }
export type Event =
| EventProjectUpdated
| EventServerInstanceDisposed
| EventInstallationUpdated
| EventInstallationUpdateAvailable
| EventServerConnected
| EventGlobalDisposed
| EventFileEdited
| EventFileWatcherUpdated
| EventLspClientDiagnostics
| EventLspUpdated
| EventMessagePartDelta
| EventPermissionAsked
| EventPermissionReplied
| EventSessionDiff
| EventSessionError
| EventQuestionAsked
| EventQuestionReplied
| EventQuestionRejected
| EventTodoUpdated
| EventSessionStatus
| EventSessionIdle
| EventSessionCompacted
| EventTuiPromptAppend
| EventTuiCommandExecute
| EventTuiToastShow
| EventTuiSessionSelect
| EventMcpToolsChanged
| EventMcpBrowserOpenFailed
| EventCommandExecuted
| EventVcsBranchUpdated
| EventWorktreeReady
| EventWorktreeFailed
| EventPtyCreated
| EventPtyUpdated
| EventPtyExited
| EventPtyDeleted
| EventWorkspaceReady
| EventWorkspaceFailed
| EventWorkspaceStatus
| EventMessageUpdated
| EventMessageRemoved
| EventMessagePartUpdated
| EventMessagePartRemoved
| EventSessionCreated
| EventSessionUpdated
| EventSessionDeleted
export type McpStatusConnected = { export type McpStatusConnected = {
status: "connected" status: "connected"
} }
@@ -2113,23 +2183,6 @@ export type GlobalEventResponses = {
export type GlobalEventResponse = GlobalEventResponses[keyof GlobalEventResponses] export type GlobalEventResponse = GlobalEventResponses[keyof GlobalEventResponses]
export type GlobalSyncEventSubscribeData = {
body?: never
path?: never
query?: never
url: "/global/sync-event"
}
export type GlobalSyncEventSubscribeResponses = {
/**
* Event stream
*/
200: SyncEvent
}
export type GlobalSyncEventSubscribeResponse =
GlobalSyncEventSubscribeResponses[keyof GlobalSyncEventSubscribeResponses]
export type GlobalConfigGetData = { export type GlobalConfigGetData = {
body?: never body?: never
path?: never path?: never
+398 -202
View File
@@ -66,31 +66,6 @@
] ]
} }
}, },
"/global/sync-event": {
"get": {
"operationId": "global.sync-event.subscribe",
"summary": "Subscribe to global sync events",
"description": "Get global sync events",
"responses": {
"200": {
"description": "Event stream",
"content": {
"text/event-stream": {
"schema": {
"$ref": "#/components/schemas/SyncEvent"
}
}
}
}
},
"x-codeSamples": [
{
"lang": "js",
"source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.global.sync-event.subscribe({\n ...\n})"
}
]
}
},
"/global/config": { "/global/config": {
"get": { "get": {
"operationId": "global.config.get", "operationId": "global.config.get",
@@ -9925,174 +9900,24 @@
}, },
"required": ["type", "properties"] "required": ["type", "properties"]
}, },
"Event": {
"anyOf": [
{
"$ref": "#/components/schemas/Event.project.updated"
},
{
"$ref": "#/components/schemas/Event.server.instance.disposed"
},
{
"$ref": "#/components/schemas/Event.installation.updated"
},
{
"$ref": "#/components/schemas/Event.installation.update-available"
},
{
"$ref": "#/components/schemas/Event.server.connected"
},
{
"$ref": "#/components/schemas/Event.global.disposed"
},
{
"$ref": "#/components/schemas/Event.file.edited"
},
{
"$ref": "#/components/schemas/Event.file.watcher.updated"
},
{
"$ref": "#/components/schemas/Event.lsp.client.diagnostics"
},
{
"$ref": "#/components/schemas/Event.lsp.updated"
},
{
"$ref": "#/components/schemas/Event.message.part.delta"
},
{
"$ref": "#/components/schemas/Event.permission.asked"
},
{
"$ref": "#/components/schemas/Event.permission.replied"
},
{
"$ref": "#/components/schemas/Event.session.diff"
},
{
"$ref": "#/components/schemas/Event.session.error"
},
{
"$ref": "#/components/schemas/Event.question.asked"
},
{
"$ref": "#/components/schemas/Event.question.replied"
},
{
"$ref": "#/components/schemas/Event.question.rejected"
},
{
"$ref": "#/components/schemas/Event.todo.updated"
},
{
"$ref": "#/components/schemas/Event.session.status"
},
{
"$ref": "#/components/schemas/Event.session.idle"
},
{
"$ref": "#/components/schemas/Event.session.compacted"
},
{
"$ref": "#/components/schemas/Event.tui.prompt.append"
},
{
"$ref": "#/components/schemas/Event.tui.command.execute"
},
{
"$ref": "#/components/schemas/Event.tui.toast.show"
},
{
"$ref": "#/components/schemas/Event.tui.session.select"
},
{
"$ref": "#/components/schemas/Event.mcp.tools.changed"
},
{
"$ref": "#/components/schemas/Event.mcp.browser.open.failed"
},
{
"$ref": "#/components/schemas/Event.command.executed"
},
{
"$ref": "#/components/schemas/Event.vcs.branch.updated"
},
{
"$ref": "#/components/schemas/Event.worktree.ready"
},
{
"$ref": "#/components/schemas/Event.worktree.failed"
},
{
"$ref": "#/components/schemas/Event.pty.created"
},
{
"$ref": "#/components/schemas/Event.pty.updated"
},
{
"$ref": "#/components/schemas/Event.pty.exited"
},
{
"$ref": "#/components/schemas/Event.pty.deleted"
},
{
"$ref": "#/components/schemas/Event.workspace.ready"
},
{
"$ref": "#/components/schemas/Event.workspace.failed"
},
{
"$ref": "#/components/schemas/Event.workspace.status"
},
{
"$ref": "#/components/schemas/Event.message.updated"
},
{
"$ref": "#/components/schemas/Event.message.removed"
},
{
"$ref": "#/components/schemas/Event.message.part.updated"
},
{
"$ref": "#/components/schemas/Event.message.part.removed"
},
{
"$ref": "#/components/schemas/Event.session.created"
},
{
"$ref": "#/components/schemas/Event.session.updated"
},
{
"$ref": "#/components/schemas/Event.session.deleted"
}
]
},
"GlobalEvent": {
"type": "object",
"properties": {
"directory": {
"type": "string"
},
"project": {
"type": "string"
},
"workspace": {
"type": "string"
},
"payload": {
"$ref": "#/components/schemas/Event"
}
},
"required": ["directory", "payload"]
},
"SyncEvent.message.updated": { "SyncEvent.message.updated": {
"type": "object", "type": "object",
"properties": { "properties": {
"type": { "type": {
"type": "string",
"const": "sync"
},
"name": {
"type": "string", "type": "string",
"const": "message.updated.1" "const": "message.updated.1"
}, },
"aggregate": { "id": {
"type": "string"
},
"seq": {
"type": "number"
},
"aggregateID": {
"type": "string", "type": "string",
"const": "sessionID" "const": "sessionID"
}, },
@@ -10110,16 +9935,26 @@
"required": ["sessionID", "info"] "required": ["sessionID", "info"]
} }
}, },
"required": ["type", "aggregate", "data"] "required": ["type", "name", "id", "seq", "aggregateID", "data"]
}, },
"SyncEvent.message.removed": { "SyncEvent.message.removed": {
"type": "object", "type": "object",
"properties": { "properties": {
"type": { "type": {
"type": "string",
"const": "sync"
},
"name": {
"type": "string", "type": "string",
"const": "message.removed.1" "const": "message.removed.1"
}, },
"aggregate": { "id": {
"type": "string"
},
"seq": {
"type": "number"
},
"aggregateID": {
"type": "string", "type": "string",
"const": "sessionID" "const": "sessionID"
}, },
@@ -10138,16 +9973,26 @@
"required": ["sessionID", "messageID"] "required": ["sessionID", "messageID"]
} }
}, },
"required": ["type", "aggregate", "data"] "required": ["type", "name", "id", "seq", "aggregateID", "data"]
}, },
"SyncEvent.message.part.updated": { "SyncEvent.message.part.updated": {
"type": "object", "type": "object",
"properties": { "properties": {
"type": { "type": {
"type": "string",
"const": "sync"
},
"name": {
"type": "string", "type": "string",
"const": "message.part.updated.1" "const": "message.part.updated.1"
}, },
"aggregate": { "id": {
"type": "string"
},
"seq": {
"type": "number"
},
"aggregateID": {
"type": "string", "type": "string",
"const": "sessionID" "const": "sessionID"
}, },
@@ -10168,16 +10013,26 @@
"required": ["sessionID", "part", "time"] "required": ["sessionID", "part", "time"]
} }
}, },
"required": ["type", "aggregate", "data"] "required": ["type", "name", "id", "seq", "aggregateID", "data"]
}, },
"SyncEvent.message.part.removed": { "SyncEvent.message.part.removed": {
"type": "object", "type": "object",
"properties": { "properties": {
"type": { "type": {
"type": "string",
"const": "sync"
},
"name": {
"type": "string", "type": "string",
"const": "message.part.removed.1" "const": "message.part.removed.1"
}, },
"aggregate": { "id": {
"type": "string"
},
"seq": {
"type": "number"
},
"aggregateID": {
"type": "string", "type": "string",
"const": "sessionID" "const": "sessionID"
}, },
@@ -10200,16 +10055,26 @@
"required": ["sessionID", "messageID", "partID"] "required": ["sessionID", "messageID", "partID"]
} }
}, },
"required": ["type", "aggregate", "data"] "required": ["type", "name", "id", "seq", "aggregateID", "data"]
}, },
"SyncEvent.session.created": { "SyncEvent.session.created": {
"type": "object", "type": "object",
"properties": { "properties": {
"type": { "type": {
"type": "string",
"const": "sync"
},
"name": {
"type": "string", "type": "string",
"const": "session.created.1" "const": "session.created.1"
}, },
"aggregate": { "id": {
"type": "string"
},
"seq": {
"type": "number"
},
"aggregateID": {
"type": "string", "type": "string",
"const": "sessionID" "const": "sessionID"
}, },
@@ -10227,16 +10092,26 @@
"required": ["sessionID", "info"] "required": ["sessionID", "info"]
} }
}, },
"required": ["type", "aggregate", "data"] "required": ["type", "name", "id", "seq", "aggregateID", "data"]
}, },
"SyncEvent.session.updated": { "SyncEvent.session.updated": {
"type": "object", "type": "object",
"properties": { "properties": {
"type": { "type": {
"type": "string",
"const": "sync"
},
"name": {
"type": "string", "type": "string",
"const": "session.updated.1" "const": "session.updated.1"
}, },
"aggregate": { "id": {
"type": "string"
},
"seq": {
"type": "number"
},
"aggregateID": {
"type": "string", "type": "string",
"const": "sessionID" "const": "sessionID"
}, },
@@ -10479,16 +10354,26 @@
"required": ["sessionID", "info"] "required": ["sessionID", "info"]
} }
}, },
"required": ["type", "aggregate", "data"] "required": ["type", "name", "id", "seq", "aggregateID", "data"]
}, },
"SyncEvent.session.deleted": { "SyncEvent.session.deleted": {
"type": "object", "type": "object",
"properties": { "properties": {
"type": { "type": {
"type": "string",
"const": "sync"
},
"name": {
"type": "string", "type": "string",
"const": "session.deleted.1" "const": "session.deleted.1"
}, },
"aggregate": { "id": {
"type": "string"
},
"seq": {
"type": "number"
},
"aggregateID": {
"type": "string", "type": "string",
"const": "sessionID" "const": "sessionID"
}, },
@@ -10506,16 +10391,185 @@
"required": ["sessionID", "info"] "required": ["sessionID", "info"]
} }
}, },
"required": ["type", "aggregate", "data"] "required": ["type", "name", "id", "seq", "aggregateID", "data"]
}, },
"SyncEvent": { "GlobalEvent": {
"type": "object", "type": "object",
"properties": { "properties": {
"directory": {
"type": "string"
},
"project": {
"type": "string"
},
"workspace": {
"type": "string"
},
"payload": { "payload": {
"$ref": "#/components/schemas/SyncEvent" "anyOf": [
{
"$ref": "#/components/schemas/Event.project.updated"
},
{
"$ref": "#/components/schemas/Event.server.instance.disposed"
},
{
"$ref": "#/components/schemas/Event.installation.updated"
},
{
"$ref": "#/components/schemas/Event.installation.update-available"
},
{
"$ref": "#/components/schemas/Event.server.connected"
},
{
"$ref": "#/components/schemas/Event.global.disposed"
},
{
"$ref": "#/components/schemas/Event.file.edited"
},
{
"$ref": "#/components/schemas/Event.file.watcher.updated"
},
{
"$ref": "#/components/schemas/Event.lsp.client.diagnostics"
},
{
"$ref": "#/components/schemas/Event.lsp.updated"
},
{
"$ref": "#/components/schemas/Event.message.part.delta"
},
{
"$ref": "#/components/schemas/Event.permission.asked"
},
{
"$ref": "#/components/schemas/Event.permission.replied"
},
{
"$ref": "#/components/schemas/Event.session.diff"
},
{
"$ref": "#/components/schemas/Event.session.error"
},
{
"$ref": "#/components/schemas/Event.question.asked"
},
{
"$ref": "#/components/schemas/Event.question.replied"
},
{
"$ref": "#/components/schemas/Event.question.rejected"
},
{
"$ref": "#/components/schemas/Event.todo.updated"
},
{
"$ref": "#/components/schemas/Event.session.status"
},
{
"$ref": "#/components/schemas/Event.session.idle"
},
{
"$ref": "#/components/schemas/Event.session.compacted"
},
{
"$ref": "#/components/schemas/Event.tui.prompt.append"
},
{
"$ref": "#/components/schemas/Event.tui.command.execute"
},
{
"$ref": "#/components/schemas/Event.tui.toast.show"
},
{
"$ref": "#/components/schemas/Event.tui.session.select"
},
{
"$ref": "#/components/schemas/Event.mcp.tools.changed"
},
{
"$ref": "#/components/schemas/Event.mcp.browser.open.failed"
},
{
"$ref": "#/components/schemas/Event.command.executed"
},
{
"$ref": "#/components/schemas/Event.vcs.branch.updated"
},
{
"$ref": "#/components/schemas/Event.worktree.ready"
},
{
"$ref": "#/components/schemas/Event.worktree.failed"
},
{
"$ref": "#/components/schemas/Event.pty.created"
},
{
"$ref": "#/components/schemas/Event.pty.updated"
},
{
"$ref": "#/components/schemas/Event.pty.exited"
},
{
"$ref": "#/components/schemas/Event.pty.deleted"
},
{
"$ref": "#/components/schemas/Event.workspace.ready"
},
{
"$ref": "#/components/schemas/Event.workspace.failed"
},
{
"$ref": "#/components/schemas/Event.workspace.status"
},
{
"$ref": "#/components/schemas/Event.message.updated"
},
{
"$ref": "#/components/schemas/Event.message.removed"
},
{
"$ref": "#/components/schemas/Event.message.part.updated"
},
{
"$ref": "#/components/schemas/Event.message.part.removed"
},
{
"$ref": "#/components/schemas/Event.session.created"
},
{
"$ref": "#/components/schemas/Event.session.updated"
},
{
"$ref": "#/components/schemas/Event.session.deleted"
},
{
"$ref": "#/components/schemas/SyncEvent.message.updated"
},
{
"$ref": "#/components/schemas/SyncEvent.message.removed"
},
{
"$ref": "#/components/schemas/SyncEvent.message.part.updated"
},
{
"$ref": "#/components/schemas/SyncEvent.message.part.removed"
},
{
"$ref": "#/components/schemas/SyncEvent.session.created"
},
{
"$ref": "#/components/schemas/SyncEvent.session.updated"
},
{
"$ref": "#/components/schemas/SyncEvent.session.deleted"
}
]
} }
}, },
"required": ["payload"] "required": ["directory", "payload"]
}, },
"LogLevel": { "LogLevel": {
"description": "Log level", "description": "Log level",
@@ -12608,6 +12662,148 @@
}, },
"required": ["path", "added", "removed", "status"] "required": ["path", "added", "removed", "status"]
}, },
"Event": {
"anyOf": [
{
"$ref": "#/components/schemas/Event.project.updated"
},
{
"$ref": "#/components/schemas/Event.server.instance.disposed"
},
{
"$ref": "#/components/schemas/Event.installation.updated"
},
{
"$ref": "#/components/schemas/Event.installation.update-available"
},
{
"$ref": "#/components/schemas/Event.server.connected"
},
{
"$ref": "#/components/schemas/Event.global.disposed"
},
{
"$ref": "#/components/schemas/Event.file.edited"
},
{
"$ref": "#/components/schemas/Event.file.watcher.updated"
},
{
"$ref": "#/components/schemas/Event.lsp.client.diagnostics"
},
{
"$ref": "#/components/schemas/Event.lsp.updated"
},
{
"$ref": "#/components/schemas/Event.message.part.delta"
},
{
"$ref": "#/components/schemas/Event.permission.asked"
},
{
"$ref": "#/components/schemas/Event.permission.replied"
},
{
"$ref": "#/components/schemas/Event.session.diff"
},
{
"$ref": "#/components/schemas/Event.session.error"
},
{
"$ref": "#/components/schemas/Event.question.asked"
},
{
"$ref": "#/components/schemas/Event.question.replied"
},
{
"$ref": "#/components/schemas/Event.question.rejected"
},
{
"$ref": "#/components/schemas/Event.todo.updated"
},
{
"$ref": "#/components/schemas/Event.session.status"
},
{
"$ref": "#/components/schemas/Event.session.idle"
},
{
"$ref": "#/components/schemas/Event.session.compacted"
},
{
"$ref": "#/components/schemas/Event.tui.prompt.append"
},
{
"$ref": "#/components/schemas/Event.tui.command.execute"
},
{
"$ref": "#/components/schemas/Event.tui.toast.show"
},
{
"$ref": "#/components/schemas/Event.tui.session.select"
},
{
"$ref": "#/components/schemas/Event.mcp.tools.changed"
},
{
"$ref": "#/components/schemas/Event.mcp.browser.open.failed"
},
{
"$ref": "#/components/schemas/Event.command.executed"
},
{
"$ref": "#/components/schemas/Event.vcs.branch.updated"
},
{
"$ref": "#/components/schemas/Event.worktree.ready"
},
{
"$ref": "#/components/schemas/Event.worktree.failed"
},
{
"$ref": "#/components/schemas/Event.pty.created"
},
{
"$ref": "#/components/schemas/Event.pty.updated"
},
{
"$ref": "#/components/schemas/Event.pty.exited"
},
{
"$ref": "#/components/schemas/Event.pty.deleted"
},
{
"$ref": "#/components/schemas/Event.workspace.ready"
},
{
"$ref": "#/components/schemas/Event.workspace.failed"
},
{
"$ref": "#/components/schemas/Event.workspace.status"
},
{
"$ref": "#/components/schemas/Event.message.updated"
},
{
"$ref": "#/components/schemas/Event.message.removed"
},
{
"$ref": "#/components/schemas/Event.message.part.updated"
},
{
"$ref": "#/components/schemas/Event.message.part.removed"
},
{
"$ref": "#/components/schemas/Event.session.created"
},
{
"$ref": "#/components/schemas/Event.session.updated"
},
{
"$ref": "#/components/schemas/Event.session.deleted"
}
]
},
"MCPStatusConnected": { "MCPStatusConnected": {
"type": "object", "type": "object",
"properties": { "properties": {